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