web/wp-includes/js/codepress/engines/msie.js
branchwordpress
changeset 109 03b0d1493584
child 132 4d4862461b8d
equal deleted inserted replaced
-1:000000000000 109:03b0d1493584
       
     1 /*
       
     2  * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/
       
     3  * 
       
     4  * Copyright (C) 2007 Fernando M.A.d.S. <fermads@gmail.com>
       
     5  *
       
     6  * Developers:
       
     7  *		Fernando M.A.d.S. <fermads@gmail.com>
       
     8  *		Michael Hurni <michael.hurni@gmail.com>
       
     9  * Contributors: 	
       
    10  *		Martin D. Kirk
       
    11  *
       
    12  * This program is free software; you can redistribute it and/or modify it under the terms of the 
       
    13  * GNU Lesser General Public License as published by the Free Software Foundation.
       
    14  * 
       
    15  * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php
       
    16  */
       
    17 
       
    18 CodePress = {
       
    19 	scrolling : false,
       
    20 	autocomplete : true,
       
    21 	
       
    22 	// set initial vars and start sh
       
    23 	initialize : function() {
       
    24 		if(typeof(editor)=='undefined' && !arguments[0]) return;
       
    25 		chars = '|32|46|62|'; // charcodes that trigger syntax highlighting
       
    26 		cc = '\u2009'; // carret char
       
    27 		editor = document.getElementsByTagName('pre')[0];
       
    28 		editor.contentEditable = 'true';
       
    29 		document.getElementsByTagName('body')[0].onfocus = function() {editor.focus();}
       
    30 		document.attachEvent('onkeydown', this.metaHandler);
       
    31 		document.attachEvent('onkeypress', this.keyHandler);
       
    32 		window.attachEvent('onscroll', function() { if(!CodePress.scrolling) setTimeout(function(){CodePress.syntaxHighlight('scroll')},1)});
       
    33 		completeChars = this.getCompleteChars();
       
    34 		completeEndingChars =  this.getCompleteEndingChars();
       
    35 		setTimeout(function() { window.scroll(0,0) },50); // scroll IE to top
       
    36 	},
       
    37 	
       
    38 	// treat key bindings
       
    39 	keyHandler : function(evt) {
       
    40 		charCode = evt.keyCode;
       
    41 		fromChar = String.fromCharCode(charCode);
       
    42 		
       
    43 		if( (completeEndingChars.indexOf('|'+fromChar+'|')!= -1 || completeChars.indexOf('|'+fromChar+'|')!=-1  )&& CodePress.autocomplete) { // auto complete
       
    44 			if(!CodePress.completeEnding(fromChar))
       
    45 			     CodePress.complete(fromChar);
       
    46 		}
       
    47 	    else if(chars.indexOf('|'+charCode+'|')!=-1||charCode==13) { // syntax highlighting
       
    48 		 	CodePress.syntaxHighlight('generic');
       
    49 		}
       
    50 	},
       
    51 
       
    52 	metaHandler : function(evt) {
       
    53 		keyCode = evt.keyCode;
       
    54 		
       
    55 		if(keyCode==9 || evt.tabKey) { 
       
    56 			CodePress.snippets();
       
    57 		}
       
    58 		else if((keyCode==122||keyCode==121||keyCode==90) && evt.ctrlKey) { // undo and redo
       
    59 			(keyCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo(); 
       
    60 			evt.returnValue = false;
       
    61 		}
       
    62 		else if(keyCode==34||keyCode==33) { // handle page up/down for IE
       
    63 			self.scrollBy(0, (keyCode==34) ? 200 : -200); 
       
    64 			evt.returnValue = false;
       
    65 		}
       
    66 		else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed
       
    67 		 	CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;
       
    68 		}
       
    69 		else if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && keyCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo) 
       
    70 			CodePress.shortcuts(keyCode);
       
    71 			evt.returnValue = false;
       
    72 		}
       
    73 		else if(keyCode==86 && evt.ctrlKey)  { // handle paste
       
    74 			window.clipboardData.setData('Text',window.clipboardData.getData('Text').replace(/\t/g,'\u2008'));
       
    75 		 	top.setTimeout(function(){CodePress.syntaxHighlight('paste');},10);
       
    76 		}
       
    77 		else if(keyCode==67 && evt.ctrlKey)  { // handle cut
       
    78 			// window.clipboardData.setData('Text',x[0]);
       
    79 			// code = window.clipboardData.getData('Text');
       
    80 		}
       
    81 	},
       
    82 
       
    83 	// put cursor back to its original position after every parsing
       
    84 	
       
    85 	
       
    86 	findString : function() {
       
    87 		range = self.document.body.createTextRange();
       
    88 		if(range.findText(cc)){
       
    89 			range.select();
       
    90 			range.text = '';
       
    91 		}
       
    92 	},
       
    93 	
       
    94 	// split big files, highlighting parts of it
       
    95 	split : function(code,flag) {
       
    96 		if(flag=='scroll') {
       
    97 			this.scrolling = true;
       
    98 			return code;
       
    99 		}
       
   100 		else {
       
   101 			this.scrolling = false;
       
   102 			mid = code.indexOf(cc);
       
   103 			if(mid-2000<0) {ini=0;end=4000;}
       
   104 			else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;}
       
   105 			else {ini=mid-2000;end=mid+2000;}
       
   106 			code = code.substring(ini,end);
       
   107 			return code.substring(code.indexOf('<P>'),code.lastIndexOf('</P>')+4);
       
   108 		}
       
   109 	},
       
   110 	
       
   111 	// syntax highlighting parser
       
   112 	syntaxHighlight : function(flag) {
       
   113 		if(flag!='init') document.selection.createRange().text = cc;
       
   114 		o = editor.innerHTML;
       
   115 		if(flag=='paste') { // fix pasted text
       
   116 			o = o.replace(/<BR>/g,'\r\n'); 
       
   117 			o = o.replace(/\u2008/g,'\t');
       
   118 		}
       
   119 		o = o.replace(/<P>/g,'\n');
       
   120 		o = o.replace(/<\/P>/g,'\r');
       
   121 		o = o.replace(/<.*?>/g,'');
       
   122 		o = o.replace(/&nbsp;/g,'');			
       
   123 		o = '<PRE><P>'+o+'</P></PRE>';
       
   124 		o = o.replace(/\n\r/g,'<P></P>');
       
   125 		o = o.replace(/\n/g,'<P>');
       
   126 		o = o.replace(/\r/g,'<\/P>');
       
   127 		o = o.replace(/<P>(<P>)+/,'<P>');
       
   128 		o = o.replace(/<\/P>(<\/P>)+/,'</P>');
       
   129 		o = o.replace(/<P><\/P>/g,'<P><BR/></P>');
       
   130 		x = z = this.split(o,flag);
       
   131 
       
   132 		if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]);
       
   133 	
       
   134 		for(i=0;i<Language.syntax.length;i++) 
       
   135 			x = x.replace(Language.syntax[i].input,Language.syntax[i].output);
       
   136 			
       
   137 		editor.innerHTML = this.actions.history[this.actions.next()] = (flag=='scroll') ? x : o.replace(z,x);
       
   138 		if(flag!='init') this.findString();
       
   139 	},
       
   140 
       
   141 	snippets : function(evt) {
       
   142 		var snippets = Language.snippets;
       
   143 		var trigger = this.getLastWord();
       
   144 		for (var i=0; i<snippets.length; i++) {
       
   145 			if(snippets[i].input == trigger) {
       
   146 				var content = snippets[i].output.replace(/</g,'&lt;');
       
   147 				content = content.replace(/>/g,'&gt;');
       
   148 				if(content.indexOf('$0')<0) content += cc;
       
   149 				else content = content.replace(/\$0/,cc);
       
   150 				content = content.replace(/\n/g,'</P><P>');
       
   151 				var pattern = new RegExp(trigger+cc,"gi");
       
   152 				this.syntaxHighlight('snippets',pattern,content);
       
   153 			}
       
   154 		}
       
   155 	},
       
   156 	
       
   157 	readOnly : function() {
       
   158 		editor.contentEditable = (arguments[0]) ? 'false' : 'true';
       
   159 	},
       
   160 	
       
   161 	complete : function(trigger) {
       
   162 		var complete = Language.complete;
       
   163 		for (var i=0; i<complete.length; i++) {
       
   164 			if(complete[i].input == trigger) {
       
   165 				var pattern = new RegExp('\\'+trigger+cc);
       
   166 				var content = complete[i].output.replace(/\$0/g,cc);
       
   167 				setTimeout(function () { CodePress.syntaxHighlight('complete',pattern,content)},0); // wait for char to appear on screen
       
   168 			}
       
   169 		}
       
   170 	},
       
   171 	
       
   172 	getCompleteChars : function() {
       
   173 		var cChars = '';
       
   174 		for(var i=0;i<Language.complete.length;i++)
       
   175 			cChars += '|'+Language.complete[i].input;
       
   176 		return cChars+'|';
       
   177 	},
       
   178 
       
   179 	getCompleteEndingChars : function() {
       
   180 		var cChars = '';
       
   181 		for(var i=0;i<Language.complete.length;i++)
       
   182 			cChars += '|'+Language.complete[i].output.charAt(Language.complete[i].output.length-1);
       
   183 		return cChars+'|';
       
   184 	},
       
   185 
       
   186 	completeEnding : function(trigger) {
       
   187 		var range = document.selection.createRange();
       
   188 		try {
       
   189 			range.moveEnd('character', 1)
       
   190 		}
       
   191 		catch(e) {
       
   192 			return false;
       
   193 		}
       
   194 		var next_character = range.text
       
   195 		range.moveEnd('character', -1)
       
   196 		if(next_character != trigger )  return false;
       
   197 		else {
       
   198 			range.moveEnd('character', 1)
       
   199 			range.text=''
       
   200 			return true;
       
   201 		}
       
   202 	},	
       
   203 
       
   204 	shortcuts : function() {
       
   205 		var cCode = arguments[0];
       
   206 		if(cCode==13) cCode = '[enter]';
       
   207 		else if(cCode==32) cCode = '[space]';
       
   208 		else cCode = '['+String.fromCharCode(keyCode).toLowerCase()+']';
       
   209 		for(var i=0;i<Language.shortcuts.length;i++)
       
   210 			if(Language.shortcuts[i].input == cCode)
       
   211 				this.insertCode(Language.shortcuts[i].output,false);
       
   212 	},
       
   213 	
       
   214 	getLastWord : function() {
       
   215 		var rangeAndCaret = CodePress.getRangeAndCaret();
       
   216 		words = rangeAndCaret[0].substring(rangeAndCaret[1]-40,rangeAndCaret[1]);
       
   217 		words = words.replace(/[\s\n\r\);\W]/g,'\n').split('\n');
       
   218 		return words[words.length-1].replace(/[\W]/gi,'').toLowerCase();
       
   219 	}, 
       
   220 
       
   221 	getRangeAndCaret : function() {	
       
   222 		var range = document.selection.createRange();
       
   223 		var caret = Math.abs(range.moveStart('character', -1000000)+1);
       
   224 		range = this.getCode();
       
   225 		range = range.replace(/\n\r/gi,'  ');
       
   226 		range = range.replace(/\n/gi,'');
       
   227 		return [range.toString(),caret];
       
   228 	},
       
   229 	
       
   230 	insertCode : function(code,replaceCursorBefore) {
       
   231 		var repdeb = '';
       
   232 		var repfin = '';
       
   233 		
       
   234 		if(replaceCursorBefore) { repfin = code; }
       
   235 		else { repdeb = code; }
       
   236 		
       
   237 		if(typeof document.selection != 'undefined') {
       
   238 			var range = document.selection.createRange();
       
   239 			range.text = repdeb + repfin;
       
   240 			range = document.selection.createRange();
       
   241 			range.move('character', -repfin.length);
       
   242 			range.select();	
       
   243 		}	
       
   244 	},
       
   245 
       
   246 	// get code from editor	
       
   247 	getCode : function() {
       
   248 		var code = editor.innerHTML;
       
   249 		code = code.replace(/<br>/g,'\n');
       
   250 		code = code.replace(/<\/p>/gi,'\r');
       
   251 		code = code.replace(/<p>/i,''); // IE first line fix
       
   252 		code = code.replace(/<p>/gi,'\n');
       
   253 		code = code.replace(/&nbsp;/gi,'');
       
   254 		code = code.replace(/\u2009/g,'');
       
   255 		code = code.replace(/<.*?>/g,'');
       
   256 		code = code.replace(/&lt;/g,'<');
       
   257 		code = code.replace(/&gt;/g,'>');
       
   258 		code = code.replace(/&amp;/gi,'&');
       
   259 		return code;
       
   260 	},
       
   261 
       
   262 	// put code inside editor
       
   263 	setCode : function() {
       
   264 		var code = arguments[0];
       
   265 		code = code.replace(/\u2009/gi,'');
       
   266 		code = code.replace(/&/gi,'&amp;');		
       
   267        	code = code.replace(/</g,'&lt;');
       
   268         code = code.replace(/>/g,'&gt;');
       
   269 		editor.innerHTML = '<pre>'+code+'</pre>';
       
   270 	},
       
   271 
       
   272 	
       
   273 	// undo and redo methods
       
   274 	actions : {
       
   275 		pos : -1, // actual history position
       
   276 		history : [], // history vector
       
   277 		
       
   278 		undo : function() {
       
   279 			if(editor.innerHTML.indexOf(cc)==-1){
       
   280 				document.selection.createRange().text = cc;
       
   281 			 	this.history[this.pos] = editor.innerHTML;
       
   282 			}
       
   283 			this.pos--;
       
   284 			if(typeof(this.history[this.pos])=='undefined') this.pos++;
       
   285 			editor.innerHTML = this.history[this.pos];
       
   286 			CodePress.findString();
       
   287 		},
       
   288 		
       
   289 		redo : function() {
       
   290 			this.pos++;
       
   291 			if(typeof(this.history[this.pos])=='undefined') this.pos--;
       
   292 			editor.innerHTML = this.history[this.pos];
       
   293 			CodePress.findString();
       
   294 		},
       
   295 		
       
   296 		next : function() { // get next vector position and clean old ones
       
   297 			if(this.pos>20) this.history[this.pos-21] = undefined;
       
   298 			return ++this.pos;
       
   299 		}
       
   300 	}
       
   301 }
       
   302 
       
   303 Language={};
       
   304 window.attachEvent('onload', function() { CodePress.initialize('new');});