User:Zocky/wysawygEd.js
From Wikipedia
Note: After saving, you may have to bypass your browser's cache to see the changes. Mozilla / Firefox / Safari: hold down Shift while clicking Reload, or press Ctrl-Shift-R (Cmd-Shift-R on Apple Mac); IE: hold Ctrl while clicking Refresh, or press Ctrl-F5; Konqueror:: simply click the Reload button, or press F5; Opera users may need to completely clear their cache in Tools→Preferences.
//<pre><nowiki> /* CodePress - A Real Time Syntax Highlighting JS Engine - v0.85 You can use and modify this code as you want. Just keep my credits somewhere around. Thanks. Fernando M.A.d.S. - fermads@gmail.com http://codepress.fermads.net/ */ CodePress = { range : null, language : 'wiki', // set initial vars and start sh initialize : function() { this.detect(); chars = top.codePressTriggerChars || '[{|}]\n'; // charcodes that trigger syntax highlighting this.language=document.body.getAttribute('codePressLanguage'); highlightTrigger=false; cc = '­'; // control char if(browser.ff) { editor = document.getElementById('ffedt'); document.designMode = 'on'; document.addEventListener('keydown', this.keyDownHandler, true); document.addEventListener('keypress', this.keyPressHandler, true); document.addEventListener('keyup', this.keyUpHandler, true); document.addEventListener('blur', this.blurHandler,true); document.body.focus(); } else if(browser.ie) { editor = document.getElementById('ieedt'); editor.contentEditable = 'true'; document.onkeypress = this.keyPressHandler; document.onkeydown = this.keyDownHandler; document.onkeyup = this.keyUpHandler; document.onblur = this.blurHandler; } else { // TODO: textarea without syntax highlighting for non supported browsers alert('your browser is not supported at the moment'); return; } this.syntaxHighlight(1); window.scroll(0,0); }, // detect browser, for now IE and FF detect : function() { browser = { ie:false, ff:false }; if(navigator.appName.indexOf("Microsoft") != -1) browser.ie = true; else if (navigator.appName == "Netscape") browser.ff = true; }, // transform syntax highlighted code to original code plainText : function() { code = editor.innerHTML; code = code.replace(/<br\/?>/gi,'\n'); code = code.replace(/<\/p>/gi,'\r'); code = code.replace(/<p>/gi,'\n'); code = code.replace(/ /gi,' '); code = code.replace(/­/gi,''); code = code.replace(/<.*?>/g,''); code = code.replace(/</g,'<'); code = code.replace(/>/g,'>'); code= code.replace(/&#(\d+);/g, function(p,p1) { return String.fromCharCode(p1); }); code = code.replace(/&/g,'&'); return code; }, blurHandler : function(evt) { if (top.codePressBlurHook) { top.codePressBlurHook(CodePress.plainText()); } }, // treat key bindings keyPressHandler : function(evt) { evt = (evt) ? evt : (window.event) ? event : null; if(evt) { charCode = (evt.charCode); if(charCode && chars.indexOf(String.fromCharCode(charCode))>=0) { // syntax highlighting highlightTrigger=true; } } }, keyUpHandler : function(evt) { if (highlightTrigger) { CodePress.syntaxHighlight(); CodePress.findString(); highlightTrigger=false; } }, keyDownHandler : function(evt) { evt = (evt) ? evt : (window.event) ? event : null; if(evt) { charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode : ((evt.which) ? evt.which : 0)); if(charCode==13) highlightTrigger=true; //dirty hack else if(charCode==46||charCode==8) { // save to history when delete or backspace pressed CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML; highlightTrigger=true; //dirty hack } else if((charCode==90||charCode==89) && evt.ctrlKey) { // undo and redo (charCode==89||evt.shiftKey) ? CodePress.actions.redo() : CodePress.actions.undo() ; evt.returnValue = false; if(browser.ff)evt.preventDefault(); } else if(charCode==86 && evt.ctrlKey) { // paste // TODO: pasted text should be parsed and highlighted highlightTrigger=true; } } }, // put cursor back to its original position after every parsing findString : function() { if(browser.ff) { if(self.find(cc)) window.getSelection().getRangeAt(0).deleteContents(); } else if(browser.ie) { range = self.document.body.createTextRange(); if(range.findText(cc)){ range.select(); range.text = ''; } } }, insertSpace : function() { if(browser.ff) { if(!arguments[0]) window.getSelection().getRangeAt(0).insertNode(document.createTextNode(" ")); } else if(browser.ie) { if(!arguments[0]) document.selection.createRange().text = " "; } }, // syntax highlighting parser syntaxHighlight : function() { if(browser.ff) { //document.execCommand("inserthtml", false, cc); // crash firefox+linux? if(!arguments[0]) window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc)); x = editor.innerHTML; x = x.replace(/<br\/?>/g,'\n'); x = x.replace(/<.*?>|<\/.*?>/g,''); } else if(browser.ie) { if(!arguments[0]) document.selection.createRange().text = cc; x = editor.innerHTML; x = x.replace(/<P>/g,'\n'); x = x.replace(/<\/P>/g,'\r'); x = x.replace(/<\/?.*?>/g,''); } if (this.language=='hook' && top.codePressHighlightHook) { x=top.codePressHighlightHook(x); } else if (languages[this.language]) { for(i=0;i<languages[this.language].length;i++) x = x.replace(languages[this.language][i],languages[this.language][i+1]); } if(browser.ff) { x = x.replace(/\n/g,'<br/>'); } else if(browser.ie) { x = '<P>'+x; x = x.replace(/\n/g,'<P>'); x = x.replace(/\r/g,'<\/P>'); x = x.replace(/(<P>)+/,'<P>'); x = x.replace(/<P><\/P>/g,'<P> <\/P>'); } editor.innerHTML = this.actions.history[this.actions.next()] = (browser.ff) ? x : '<pre>'+x+'</pre>' ; }, // undo and redo methods actions : { pos : -1, // actual history position history : [], // history vector undo : function() { if(editor.innerHTML.indexOf(cc)==-1){ if(browser.ff) window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc)); else document.selection.createRange().text = cc; this.history[this.pos] = editor.innerHTML; } this.pos--; if(typeof(this.history[this.pos])=='undefined') this.pos++; editor.innerHTML = this.history[this.pos]; CodePress.findString(); }, redo : function() { this.pos++; if(typeof(this.history[this.pos])=='undefined') this.pos--; editor.innerHTML = this.history[this.pos]; CodePress.findString(); }, next : function() { // get next vector position and clean old ones if(this.pos>20) this.history[this.pos-21] = undefined; return ++this.pos; } } } // language specific regular expressions // TODO: distribute languages into specific [language].js files languages = { java : [ /([\"\'].*?[\"\'])/g,'<s>$1</s>', // strings /(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)([ \.\"\'\{\(;&<])/g,'<b>$1</b>$2', // reserved words /([^:])\/\/(.*?)(<br>|<\/P>)/g,'$1<i>//$2</i>$3', // comments /\/\*(.*?)\*\//g,'<i>/*$1*/</i>' // comments ], javascript : [ /([\"\'].*?[\"\'])/g,'<s>$1</s>', // strings /(break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)([ \.\"\'\{\(\);,&<])/g,'<b>$1</b>$2', // reserved words /(alert|isNaN|parent|Array|parseFloat|parseInt|blur|clearTimeout|prompt|prototype|close|confirm|length|Date|location|scroll|Math|document|element|name|self|elements|setTimeout|navigator|status| String|escape|Number|submit|eval|Object|event|onblur|focus|onerror|onfocus|top|onload|toString|onunload|unescape|open|opener|valueOf|window)([ \.\"\'\{\(\);,&<])/g,'<u>$1</u>$2', // special words // /([&\|\\\/=!\[\]\(\)])([ \.\"\'\{\(;\xad&<])/g,'<em>$1</em>$2', // special chars; /([\(\){}\?\[\]])/g,'<em>$1</em>', // special chars; /([^:])\/\/(.*?)(<br>|<\/P>)/g,'$1<i>//$2</i>$3', // comments /\/\*(.*?)\*\//g,'<i>/*$1*/</i>' // comments ], php : [ /(<[^!\?]*?>)/g,'<b>$1</b>', // all tags /(<style.*?>)(.*?)(<\/style>)/g,'<em>$1</em><em>$2</em><em>$3</em>', // style tags /(<script.*?>)(.*?)(<\/script>)/g,'<u>$1</u><u>$2</u><u>$3</u>', // script tags /([\"\'].*?[\"\'])/g,'<s>$1</s>', // strings /(<\?.*?\?>)/g,'<strong>$1</strong>', // bgcolor inside php tags /(<\?php|\?>)/g,'<cite>$1</cite>', // php tags /(\$.*?)([ \)\(\[\{\+\-\*\/&!\|%=;])/g,'<var>$1</var>$2', /(and|or|xor|__FILE__|exception|__LINE__|array|as|break|case|class|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|for|foreach|function|global|if|include|include_once|isset|list|new|print|require|require_once|return|static|switch|unset|use|var|while|__FUNCTION__|__CLASS__|__METHOD__|final|php_user_filter|interface|implements|extends|public|private|protected|abstract|clone|try|catch|throw|this)([ \.\"\'\{\(;&<])/g,'<ins>$1</ins>$2', // reserved words /([^:])\/\/(.*?)(<br>|<\/P>)/g,'$1<i>//$2</i>$3', // php comments /\/\*(.*?)\*\//g,'<i>/*$1*/</i>', // php comments /(<!--.*?-->.)/g,'<big>$1</big>' // html comments ], html : [ /(<[^!]*?>)/g,'<b>$1</b>', // all tags /(<style.*?>)(.*?)(<\/style>)/g,'<em>$1</em><em>$2</em><em>$3</em>', // style tags /(<script.*?>)(.*?)(<\/script>)/g,'<u>$1</u><u>$2</u><u>$3</u>', // script tags /=(["'].*?["'])/g,'=<s>$1</s>', // atributes /(<!--.*?-->.)/g,'<i>$1</i>' // comments ], css : [ /(\}|^)(.*?)(\{)/g,'$1<b>$2</b>$3', // tags, ids, classes, etc /([\{;])(.*?):/g,'$1<em>$2</em>:', // keys // /([\{\}:;])/g,'<u>$1</u>', // dividers // SHY BUG HERE !!!!!!!!! /([\"\'].*?[\"\'])/g,'<s>$1</s>', // strings /\/\*(.*?)\*\//g,'<i>/*$1*/</i>', // comments ], text : [ // do nothing, as expected ] } onload = function () {CodePress.initialize()} //</nowiki></pre>