web/wp-includes/js/codepress/engines/opera.js
changeset 136 bde1974c263b
equal deleted inserted replaced
135:53cff4b4a802 136:bde1974c263b
       
     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  * Contributors :
       
     7  *
       
     8  * 	Michael Hurni <michael.hurni@gmail.com>
       
     9  *
       
    10  * This program is free software; you can redistribute it and/or modify it under the terms of the 
       
    11  * GNU Lesser General Public License as published by the Free Software Foundation.
       
    12  * 
       
    13  * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php
       
    14  */
       
    15 
       
    16 
       
    17 CodePress = {
       
    18 	scrolling : false,
       
    19 	autocomplete : true,
       
    20 
       
    21 	// set initial vars and start sh
       
    22 	initialize : function() {
       
    23 		if(typeof(editor)=='undefined' && !arguments[0]) return;
       
    24 		chars = '|32|46|62|'; // charcodes that trigger syntax highlighting
       
    25 		cc = '\u2009'; // control char
       
    26 		editor = document.getElementsByTagName('body')[0];
       
    27 		document.designMode = 'on';
       
    28 		document.addEventListener('keyup', this.keyHandler, true);
       
    29 		window.addEventListener('scroll', function() { if(!CodePress.scrolling) CodePress.syntaxHighlight('scroll') }, false);
       
    30 		completeChars = this.getCompleteChars();
       
    31 //		CodePress.syntaxHighlight('init');
       
    32 	},
       
    33 
       
    34 	// treat key bindings
       
    35 	keyHandler : function(evt) {
       
    36     	keyCode = evt.keyCode;	
       
    37 		charCode = evt.charCode;
       
    38 
       
    39 		if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo) 
       
    40 			CodePress.shortcuts(charCode?charCode:keyCode);
       
    41 		}
       
    42 		else if(completeChars.indexOf('|'+String.fromCharCode(charCode)+'|')!=-1 && CodePress.autocomplete) { // auto complete
       
    43 			CodePress.complete(String.fromCharCode(charCode));
       
    44 		}
       
    45 	    else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting
       
    46 		 	CodePress.syntaxHighlight('generic');
       
    47 		}
       
    48 		else if(keyCode==9 || evt.tabKey) {  // snippets activation (tab)
       
    49 			CodePress.snippets(evt);
       
    50 		}
       
    51 		else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed
       
    52 		 	CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;
       
    53 		}
       
    54 		else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo
       
    55 			(charCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo(); 
       
    56 			evt.preventDefault();
       
    57 		}
       
    58 		else if(keyCode==86 && evt.ctrlKey)  { // paste
       
    59 			// TODO: pasted text should be parsed and highlighted
       
    60 		}
       
    61 	},
       
    62 
       
    63 	// put cursor back to its original position after every parsing
       
    64 	findString : function() {
       
    65 		var sel = window.getSelection();
       
    66 		var range = window.document.createRange();
       
    67 		var span = window.document.getElementsByTagName('span')[0];
       
    68 			
       
    69 		range.selectNode(span);
       
    70 		sel.removeAllRanges();
       
    71 		sel.addRange(range);
       
    72 		span.parentNode.removeChild(span);
       
    73 		//if(self.find(cc))
       
    74 		//window.getSelection().getRangeAt(0).deleteContents();
       
    75 	},
       
    76 	
       
    77 	// split big files, highlighting parts of it
       
    78 	split : function(code,flag) {
       
    79 		if(flag=='scroll') {
       
    80 			this.scrolling = true;
       
    81 			return code;
       
    82 		}
       
    83 		else {
       
    84 			this.scrolling = false;
       
    85 			mid = code.indexOf('<SPAN>');
       
    86 			if(mid-2000<0) {ini=0;end=4000;}
       
    87 			else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;}
       
    88 			else {ini=mid-2000;end=mid+2000;}
       
    89 			code = code.substring(ini,end);
       
    90 			return code;
       
    91 		}
       
    92 	},
       
    93 	
       
    94 	// syntax highlighting parser
       
    95 	syntaxHighlight : function(flag) {
       
    96 		//if(document.designMode=='off') document.designMode='on'
       
    97 		if(flag!='init') {
       
    98 			var span = document.createElement('span');
       
    99 			window.getSelection().getRangeAt(0).insertNode(span);
       
   100 		}
       
   101 
       
   102 		o = editor.innerHTML;
       
   103 //		o = o.replace(/<br>/g,'\r\n');
       
   104 //		o = o.replace(/<(b|i|s|u|a|em|tt|ins|big|cite|strong)?>/g,'');
       
   105 		//alert(o)
       
   106 		o = o.replace(/<(?!span|\/span|br).*?>/gi,'');
       
   107 //		alert(o)
       
   108 //		x = o;
       
   109 		x = z = this.split(o,flag);
       
   110 		//alert(z)
       
   111 //		x = x.replace(/\r\n/g,'<br>');
       
   112 		x = x.replace(/\t/g, '        ');
       
   113 
       
   114 
       
   115 		if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]);
       
   116 	
       
   117 		for(i=0;i<Language.syntax.length;i++) 
       
   118 			x = x.replace(Language.syntax[i].input,Language.syntax[i].output);
       
   119 
       
   120 		editor.innerHTML = this.actions.history[this.actions.next()] = (flag=='scroll') ? x : o.split(z).join(x); 
       
   121 
       
   122 		if(flag!='init') this.findString();
       
   123 	},
       
   124 	
       
   125 	getLastWord : function() {
       
   126 		var rangeAndCaret = CodePress.getRangeAndCaret();
       
   127 		words = rangeAndCaret[0].substring(rangeAndCaret[1]-40,rangeAndCaret[1]);
       
   128 		words = words.replace(/[\s\n\r\);\W]/g,'\n').split('\n');
       
   129 		return words[words.length-1].replace(/[\W]/gi,'').toLowerCase();
       
   130 	}, 
       
   131 	
       
   132 	snippets : function(evt) {
       
   133 		var snippets = Language.snippets;	
       
   134 		var trigger = this.getLastWord();
       
   135 		for (var i=0; i<snippets.length; i++) {
       
   136 			if(snippets[i].input == trigger) {
       
   137 				var content = snippets[i].output.replace(/</g,'&lt;');
       
   138 				content = content.replace(/>/g,'&gt;');
       
   139 				if(content.indexOf('$0')<0) content += cc;
       
   140 				else content = content.replace(/\$0/,cc);
       
   141 				content = content.replace(/\n/g,'<br>');
       
   142 				var pattern = new RegExp(trigger+cc,'gi');
       
   143 				evt.preventDefault(); // prevent the tab key from being added
       
   144 				this.syntaxHighlight('snippets',pattern,content);
       
   145 			}
       
   146 		}
       
   147 	},
       
   148 	
       
   149 	readOnly : function() {
       
   150 		document.designMode = (arguments[0]) ? 'off' : 'on';
       
   151 	},
       
   152 
       
   153 	complete : function(trigger) {
       
   154 		window.getSelection().getRangeAt(0).deleteContents();
       
   155 		var complete = Language.complete;
       
   156 		for (var i=0; i<complete.length; i++) {
       
   157 			if(complete[i].input == trigger) {
       
   158 				var pattern = new RegExp('\\'+trigger+cc);
       
   159 				var content = complete[i].output.replace(/\$0/g,cc);
       
   160 				parent.setTimeout(function () { CodePress.syntaxHighlight('complete',pattern,content)},0); // wait for char to appear on screen
       
   161 			}
       
   162 		}
       
   163 	},
       
   164 
       
   165 	getCompleteChars : function() {
       
   166 		var cChars = '';
       
   167 		for(var i=0;i<Language.complete.length;i++)
       
   168 			cChars += '|'+Language.complete[i].input;
       
   169 		return cChars+'|';
       
   170 	},
       
   171 
       
   172 	shortcuts : function() {
       
   173 		var cCode = arguments[0];
       
   174 		if(cCode==13) cCode = '[enter]';
       
   175 		else if(cCode==32) cCode = '[space]';
       
   176 		else cCode = '['+String.fromCharCode(charCode).toLowerCase()+']';
       
   177 		for(var i=0;i<Language.shortcuts.length;i++)
       
   178 			if(Language.shortcuts[i].input == cCode)
       
   179 				this.insertCode(Language.shortcuts[i].output,false);
       
   180 	},
       
   181 	
       
   182 	getRangeAndCaret : function() {	
       
   183 		var range = window.getSelection().getRangeAt(0);
       
   184 		var range2 = range.cloneRange();
       
   185 		var node = range.endContainer;			
       
   186 		var caret = range.endOffset;
       
   187 		range2.selectNode(node);	
       
   188 		return [range2.toString(),caret];
       
   189 	},
       
   190 	
       
   191 	insertCode : function(code,replaceCursorBefore) {
       
   192 		var range = window.getSelection().getRangeAt(0);
       
   193 		var node = window.document.createTextNode(code);
       
   194 		var selct = window.getSelection();
       
   195 		var range2 = range.cloneRange();
       
   196 		// Insert text at cursor position
       
   197 		selct.removeAllRanges();
       
   198 		range.deleteContents();
       
   199 		range.insertNode(node);
       
   200 		// Move the cursor to the end of text
       
   201 		range2.selectNode(node);		
       
   202 		range2.collapse(replaceCursorBefore);
       
   203 		selct.removeAllRanges();
       
   204 		selct.addRange(range2);
       
   205 	},
       
   206 	
       
   207 	// get code from editor
       
   208 	getCode : function() {
       
   209 		var code = editor.innerHTML;
       
   210 		code = code.replace(/<br>/g,'\n');
       
   211 		code = code.replace(/\u2009/g,'');
       
   212 		code = code.replace(/<.*?>/g,'');
       
   213 		code = code.replace(/&lt;/g,'<');
       
   214 		code = code.replace(/&gt;/g,'>');
       
   215 		code = code.replace(/&amp;/gi,'&');
       
   216 		return code;
       
   217 	},
       
   218 
       
   219 	// put code inside editor
       
   220 	setCode : function() {
       
   221 		var code = arguments[0];
       
   222 		code = code.replace(/\u2009/gi,'');
       
   223 		code = code.replace(/&/gi,'&amp;');
       
   224        	code = code.replace(/</g,'&lt;');
       
   225         code = code.replace(/>/g,'&gt;');
       
   226 		editor.innerHTML = code;
       
   227 	},
       
   228 
       
   229 	// undo and redo methods
       
   230 	actions : {
       
   231 		pos : -1, // actual history position
       
   232 		history : [], // history vector
       
   233 		
       
   234 		undo : function() {
       
   235 			if(editor.innerHTML.indexOf(cc)==-1){
       
   236 				window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc));
       
   237 			 	this.history[this.pos] = editor.innerHTML;
       
   238 			}
       
   239 			this.pos--;
       
   240 			if(typeof(this.history[this.pos])=='undefined') this.pos++;
       
   241 			editor.innerHTML = this.history[this.pos];
       
   242 			CodePress.findString();
       
   243 		},
       
   244 		
       
   245 		redo : function() {
       
   246 			this.pos++;
       
   247 			if(typeof(this.history[this.pos])=='undefined') this.pos--;
       
   248 			editor.innerHTML = this.history[this.pos];
       
   249 			CodePress.findString();
       
   250 		},
       
   251 		
       
   252 		next : function() { // get next vector position and clean old ones
       
   253 			if(this.pos>20) this.history[this.pos-21] = undefined;
       
   254 			return ++this.pos;
       
   255 		}
       
   256 	}
       
   257 }
       
   258 
       
   259 Language={};
       
   260 window.addEventListener('load', function() { CodePress.initialize('new'); }, true);