editarea-rails 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. data/LICENSE.txt +22 -0
  2. data/README.md +31 -0
  3. data/lib/editarea-rails.rb +8 -0
  4. data/lib/editarea-rails/version.rb +5 -0
  5. data/vendor/assets/images/autocompletion.gif +0 -0
  6. data/vendor/assets/images/close.gif +0 -0
  7. data/vendor/assets/images/fullscreen.gif +0 -0
  8. data/vendor/assets/images/go_to_line.gif +0 -0
  9. data/vendor/assets/images/help.gif +0 -0
  10. data/vendor/assets/images/highlight.gif +0 -0
  11. data/vendor/assets/images/load.gif +0 -0
  12. data/vendor/assets/images/move.gif +0 -0
  13. data/vendor/assets/images/newdocument.gif +0 -0
  14. data/vendor/assets/images/opacity.png +0 -0
  15. data/vendor/assets/images/plugins/charmap/charmap.gif +0 -0
  16. data/vendor/assets/images/plugins/test/css/test.css +3 -0
  17. data/vendor/assets/images/plugins/test/images/Thumbs.db +0 -0
  18. data/vendor/assets/images/plugins/test/images/test.gif +0 -0
  19. data/vendor/assets/images/plugins/test/langs/bg.js +10 -0
  20. data/vendor/assets/images/plugins/test/langs/cs.js +4 -0
  21. data/vendor/assets/images/plugins/test/langs/de.js +4 -0
  22. data/vendor/assets/images/plugins/test/langs/dk.js +4 -0
  23. data/vendor/assets/images/plugins/test/langs/en.js +4 -0
  24. data/vendor/assets/images/plugins/test/langs/eo.js +4 -0
  25. data/vendor/assets/images/plugins/test/langs/es.js +4 -0
  26. data/vendor/assets/images/plugins/test/langs/fr.js +4 -0
  27. data/vendor/assets/images/plugins/test/langs/hr.js +4 -0
  28. data/vendor/assets/images/plugins/test/langs/it.js +4 -0
  29. data/vendor/assets/images/plugins/test/langs/ja.js +4 -0
  30. data/vendor/assets/images/plugins/test/langs/mk.js +4 -0
  31. data/vendor/assets/images/plugins/test/langs/nl.js +4 -0
  32. data/vendor/assets/images/plugins/test/langs/pl.js +4 -0
  33. data/vendor/assets/images/plugins/test/langs/pt.js +4 -0
  34. data/vendor/assets/images/plugins/test/langs/ru.js +4 -0
  35. data/vendor/assets/images/plugins/test/langs/sk.js +4 -0
  36. data/vendor/assets/images/plugins/test/langs/zh.js +4 -0
  37. data/vendor/assets/images/plugins/test/test.js +110 -0
  38. data/vendor/assets/images/plugins/test/test2.js +1 -0
  39. data/vendor/assets/images/processing.gif +0 -0
  40. data/vendor/assets/images/redo.gif +0 -0
  41. data/vendor/assets/images/reset_highlight.gif +0 -0
  42. data/vendor/assets/images/save.gif +0 -0
  43. data/vendor/assets/images/search.gif +0 -0
  44. data/vendor/assets/images/smooth_selection.gif +0 -0
  45. data/vendor/assets/images/spacer.gif +0 -0
  46. data/vendor/assets/images/statusbar_resize.gif +0 -0
  47. data/vendor/assets/images/undo.gif +0 -0
  48. data/vendor/assets/images/word_wrap.gif +0 -0
  49. data/vendor/assets/javascripts/autocompletion.js +491 -0
  50. data/vendor/assets/javascripts/edit_area.js +527 -0
  51. data/vendor/assets/javascripts/edit_area_full.js +38 -0
  52. data/vendor/assets/javascripts/edit_area_functions.js +1202 -0
  53. data/vendor/assets/javascripts/edit_area_loader.js +1081 -0
  54. data/vendor/assets/javascripts/elements_functions.js +336 -0
  55. data/vendor/assets/javascripts/highlight.js +407 -0
  56. data/vendor/assets/javascripts/keyboard.js +145 -0
  57. data/vendor/assets/javascripts/langs/bg.js +54 -0
  58. data/vendor/assets/javascripts/langs/cs.js +48 -0
  59. data/vendor/assets/javascripts/langs/de.js +48 -0
  60. data/vendor/assets/javascripts/langs/dk.js +48 -0
  61. data/vendor/assets/javascripts/langs/en.js +48 -0
  62. data/vendor/assets/javascripts/langs/eo.js +48 -0
  63. data/vendor/assets/javascripts/langs/es.js +48 -0
  64. data/vendor/assets/javascripts/langs/fi.js +48 -0
  65. data/vendor/assets/javascripts/langs/fr.js +48 -0
  66. data/vendor/assets/javascripts/langs/hr.js +48 -0
  67. data/vendor/assets/javascripts/langs/it.js +48 -0
  68. data/vendor/assets/javascripts/langs/ja.js +48 -0
  69. data/vendor/assets/javascripts/langs/mk.js +48 -0
  70. data/vendor/assets/javascripts/langs/nl.js +48 -0
  71. data/vendor/assets/javascripts/langs/pl.js +48 -0
  72. data/vendor/assets/javascripts/langs/pt.js +48 -0
  73. data/vendor/assets/javascripts/langs/ru.js +48 -0
  74. data/vendor/assets/javascripts/langs/sk.js +48 -0
  75. data/vendor/assets/javascripts/langs/zh.js +48 -0
  76. data/vendor/assets/javascripts/manage_area.js +623 -0
  77. data/vendor/assets/javascripts/plugins/charmap/charmap.js +90 -0
  78. data/vendor/assets/javascripts/plugins/charmap/jscripts/map.js +373 -0
  79. data/vendor/assets/javascripts/plugins/charmap/langs/bg.js +12 -0
  80. data/vendor/assets/javascripts/plugins/charmap/langs/cs.js +6 -0
  81. data/vendor/assets/javascripts/plugins/charmap/langs/de.js +6 -0
  82. data/vendor/assets/javascripts/plugins/charmap/langs/dk.js +6 -0
  83. data/vendor/assets/javascripts/plugins/charmap/langs/en.js +6 -0
  84. data/vendor/assets/javascripts/plugins/charmap/langs/eo.js +6 -0
  85. data/vendor/assets/javascripts/plugins/charmap/langs/es.js +6 -0
  86. data/vendor/assets/javascripts/plugins/charmap/langs/fr.js +6 -0
  87. data/vendor/assets/javascripts/plugins/charmap/langs/hr.js +6 -0
  88. data/vendor/assets/javascripts/plugins/charmap/langs/it.js +6 -0
  89. data/vendor/assets/javascripts/plugins/charmap/langs/ja.js +6 -0
  90. data/vendor/assets/javascripts/plugins/charmap/langs/mk.js +6 -0
  91. data/vendor/assets/javascripts/plugins/charmap/langs/nl.js +6 -0
  92. data/vendor/assets/javascripts/plugins/charmap/langs/pl.js +6 -0
  93. data/vendor/assets/javascripts/plugins/charmap/langs/pt.js +6 -0
  94. data/vendor/assets/javascripts/plugins/charmap/langs/ru.js +6 -0
  95. data/vendor/assets/javascripts/plugins/charmap/langs/sk.js +6 -0
  96. data/vendor/assets/javascripts/plugins/charmap/langs/zh.js +6 -0
  97. data/vendor/assets/javascripts/plugins/charmap/popup.html +24 -0
  98. data/vendor/assets/javascripts/plugins/test/langs/bg.js +10 -0
  99. data/vendor/assets/javascripts/plugins/test/langs/cs.js +4 -0
  100. data/vendor/assets/javascripts/plugins/test/langs/de.js +4 -0
  101. data/vendor/assets/javascripts/plugins/test/langs/dk.js +4 -0
  102. data/vendor/assets/javascripts/plugins/test/langs/en.js +4 -0
  103. data/vendor/assets/javascripts/plugins/test/langs/eo.js +4 -0
  104. data/vendor/assets/javascripts/plugins/test/langs/es.js +4 -0
  105. data/vendor/assets/javascripts/plugins/test/langs/fr.js +4 -0
  106. data/vendor/assets/javascripts/plugins/test/langs/hr.js +4 -0
  107. data/vendor/assets/javascripts/plugins/test/langs/it.js +4 -0
  108. data/vendor/assets/javascripts/plugins/test/langs/ja.js +4 -0
  109. data/vendor/assets/javascripts/plugins/test/langs/mk.js +4 -0
  110. data/vendor/assets/javascripts/plugins/test/langs/nl.js +4 -0
  111. data/vendor/assets/javascripts/plugins/test/langs/pl.js +4 -0
  112. data/vendor/assets/javascripts/plugins/test/langs/pt.js +4 -0
  113. data/vendor/assets/javascripts/plugins/test/langs/ru.js +4 -0
  114. data/vendor/assets/javascripts/plugins/test/langs/sk.js +4 -0
  115. data/vendor/assets/javascripts/plugins/test/langs/zh.js +4 -0
  116. data/vendor/assets/javascripts/plugins/test/test.js +110 -0
  117. data/vendor/assets/javascripts/plugins/test/test2.js +1 -0
  118. data/vendor/assets/javascripts/reg_syntax.js +166 -0
  119. data/vendor/assets/javascripts/reg_syntax/basic.js +70 -0
  120. data/vendor/assets/javascripts/reg_syntax/brainfuck.js +45 -0
  121. data/vendor/assets/javascripts/reg_syntax/c.js +63 -0
  122. data/vendor/assets/javascripts/reg_syntax/coldfusion.js +120 -0
  123. data/vendor/assets/javascripts/reg_syntax/cpp.js +66 -0
  124. data/vendor/assets/javascripts/reg_syntax/css.js +85 -0
  125. data/vendor/assets/javascripts/reg_syntax/html.js +51 -0
  126. data/vendor/assets/javascripts/reg_syntax/java.js +57 -0
  127. data/vendor/assets/javascripts/reg_syntax/js.js +94 -0
  128. data/vendor/assets/javascripts/reg_syntax/pas.js +83 -0
  129. data/vendor/assets/javascripts/reg_syntax/perl.js +88 -0
  130. data/vendor/assets/javascripts/reg_syntax/php.js +157 -0
  131. data/vendor/assets/javascripts/reg_syntax/python.js +145 -0
  132. data/vendor/assets/javascripts/reg_syntax/robotstxt.js +25 -0
  133. data/vendor/assets/javascripts/reg_syntax/ruby.js +68 -0
  134. data/vendor/assets/javascripts/reg_syntax/sql.js +56 -0
  135. data/vendor/assets/javascripts/reg_syntax/tsql.js +88 -0
  136. data/vendor/assets/javascripts/reg_syntax/vb.js +53 -0
  137. data/vendor/assets/javascripts/reg_syntax/xml.js +57 -0
  138. data/vendor/assets/javascripts/regexp.js +139 -0
  139. data/vendor/assets/javascripts/resize_area.js +73 -0
  140. data/vendor/assets/javascripts/search_replace.js +174 -0
  141. data/vendor/assets/stylesheets/edit_area.css +530 -0
  142. data/vendor/assets/stylesheets/plugins/charmap/css/charmap.css +64 -0
  143. data/vendor/assets/stylesheets/plugins/test/css/test.css +3 -0
  144. metadata +210 -0
@@ -0,0 +1,336 @@
1
+ /****
2
+ * This page contains some general usefull functions for javascript
3
+ *
4
+ ****/
5
+
6
+
7
+ // need to redefine this functiondue to IE problem
8
+ function getAttribute( elm, aName ) {
9
+ var aValue,taName,i;
10
+ try{
11
+ aValue = elm.getAttribute( aName );
12
+ }catch(exept){}
13
+
14
+ if( ! aValue ){
15
+ for( i = 0; i < elm.attributes.length; i ++ ) {
16
+ taName = elm.attributes[i] .name.toLowerCase();
17
+ if( taName == aName ) {
18
+ aValue = elm.attributes[i] .value;
19
+ return aValue;
20
+ }
21
+ }
22
+ }
23
+ return aValue;
24
+ };
25
+
26
+ // need to redefine this function due to IE problem
27
+ function setAttribute( elm, attr, val ) {
28
+ if(attr=="class"){
29
+ elm.setAttribute("className", val);
30
+ elm.setAttribute("class", val);
31
+ }else{
32
+ elm.setAttribute(attr, val);
33
+ }
34
+ };
35
+
36
+ /* return a child element
37
+ elem: element we are searching in
38
+ elem_type: type of the eleemnt we are searching (DIV, A, etc...)
39
+ elem_attribute: attribute of the searched element that must match
40
+ elem_attribute_match: value that elem_attribute must match
41
+ option: "all" if must return an array of all children, otherwise return the first match element
42
+ depth: depth of search (-1 or no set => unlimited)
43
+ */
44
+ function getChildren(elem, elem_type, elem_attribute, elem_attribute_match, option, depth)
45
+ {
46
+ if(!option)
47
+ var option="single";
48
+ if(!depth)
49
+ var depth=-1;
50
+ if(elem){
51
+ var children= elem.childNodes;
52
+ var result=null;
53
+ var results= [];
54
+ for (var x=0;x<children.length;x++) {
55
+ strTagName = new String(children[x].tagName);
56
+ children_class="?";
57
+ if(strTagName!= "undefined"){
58
+ child_attribute= getAttribute(children[x],elem_attribute);
59
+ if((strTagName.toLowerCase()==elem_type.toLowerCase() || elem_type=="") && (elem_attribute=="" || child_attribute==elem_attribute_match)){
60
+ if(option=="all"){
61
+ results.push(children[x]);
62
+ }else{
63
+ return children[x];
64
+ }
65
+ }
66
+ if(depth!=0){
67
+ result=getChildren(children[x], elem_type, elem_attribute, elem_attribute_match, option, depth-1);
68
+ if(option=="all"){
69
+ if(result.length>0){
70
+ results= results.concat(result);
71
+ }
72
+ }else if(result!=null){
73
+ return result;
74
+ }
75
+ }
76
+ }
77
+ }
78
+ if(option=="all")
79
+ return results;
80
+ }
81
+ return null;
82
+ };
83
+
84
+ function isChildOf(elem, parent){
85
+ if(elem){
86
+ if(elem==parent)
87
+ return true;
88
+ while(elem.parentNode != 'undefined'){
89
+ return isChildOf(elem.parentNode, parent);
90
+ }
91
+ }
92
+ return false;
93
+ };
94
+
95
+ function getMouseX(e){
96
+
97
+ if(e!=null && typeof(e.pageX)!="undefined"){
98
+ return e.pageX;
99
+ }else{
100
+ return (e!=null?e.x:event.x)+ document.documentElement.scrollLeft;
101
+ }
102
+ };
103
+
104
+ function getMouseY(e){
105
+ if(e!=null && typeof(e.pageY)!="undefined"){
106
+ return e.pageY;
107
+ }else{
108
+ return (e!=null?e.y:event.y)+ document.documentElement.scrollTop;
109
+ }
110
+ };
111
+
112
+ function calculeOffsetLeft(r){
113
+ return calculeOffset(r,"offsetLeft")
114
+ };
115
+
116
+ function calculeOffsetTop(r){
117
+ return calculeOffset(r,"offsetTop")
118
+ };
119
+
120
+ function calculeOffset(element,attr){
121
+ var offset=0;
122
+ while(element){
123
+ offset+=element[attr];
124
+ element=element.offsetParent
125
+ }
126
+ return offset;
127
+ };
128
+
129
+ /** return the computed style
130
+ * @param: elem: the reference to the element
131
+ * @param: prop: the name of the css property
132
+ */
133
+ function get_css_property(elem, prop)
134
+ {
135
+ if(document.defaultView)
136
+ {
137
+ return document.defaultView.getComputedStyle(elem, null).getPropertyValue(prop);
138
+ }
139
+ else if(elem.currentStyle)
140
+ {
141
+ var prop = prop.replace(/-\D/gi, function(sMatch)
142
+ {
143
+ return sMatch.charAt(sMatch.length - 1).toUpperCase();
144
+ });
145
+ return elem.currentStyle[prop];
146
+ }
147
+ else return null;
148
+ }
149
+
150
+ /****
151
+ * Moving an element
152
+ ***/
153
+
154
+ var _mCE; // currently moving element
155
+
156
+ /* allow to move an element in a window
157
+ e: the event
158
+ id: the id of the element
159
+ frame: the frame of the element
160
+ ex of use:
161
+ in html: <img id='move_area_search_replace' onmousedown='return parent.start_move_element(event,"area_search_replace", parent.frames["this_frame_id"]);' .../>
162
+ or
163
+ in javascript: document.getElementById("my_div").onmousedown= start_move_element
164
+ */
165
+ function start_move_element(e, id, frame){
166
+ var elem_id=(e.target || e.srcElement).id;
167
+ if(id)
168
+ elem_id=id;
169
+ if(!frame)
170
+ frame=window;
171
+ if(frame.event)
172
+ e=frame.event;
173
+
174
+ _mCE= frame.document.getElementById(elem_id);
175
+ _mCE.frame=frame;
176
+ frame.document.onmousemove= move_element;
177
+ frame.document.onmouseup= end_move_element;
178
+ /*_mCE.onmousemove= move_element;
179
+ _mCE.onmouseup= end_move_element;*/
180
+
181
+ //alert(_mCE.frame.document.body.offsetHeight);
182
+
183
+ mouse_x= getMouseX(e);
184
+ mouse_y= getMouseY(e);
185
+ //window.status=frame+ " elem: "+elem_id+" elem: "+ _mCE + " mouse_x: "+mouse_x;
186
+ _mCE.start_pos_x = mouse_x - (_mCE.style.left.replace("px","") || calculeOffsetLeft(_mCE));
187
+ _mCE.start_pos_y = mouse_y - (_mCE.style.top.replace("px","") || calculeOffsetTop(_mCE));
188
+ return false;
189
+ };
190
+
191
+ function end_move_element(e){
192
+ _mCE.frame.document.onmousemove= "";
193
+ _mCE.frame.document.onmouseup= "";
194
+ _mCE=null;
195
+ };
196
+
197
+ function move_element(e){
198
+ var newTop,newLeft,maxLeft;
199
+
200
+ if( _mCE.frame && _mCE.frame.event )
201
+ e=_mCE.frame.event;
202
+ newTop = getMouseY(e) - _mCE.start_pos_y;
203
+ newLeft = getMouseX(e) - _mCE.start_pos_x;
204
+
205
+ maxLeft = _mCE.frame.document.body.offsetWidth- _mCE.offsetWidth;
206
+ max_top = _mCE.frame.document.body.offsetHeight- _mCE.offsetHeight;
207
+ newTop = Math.min(Math.max(0, newTop), max_top);
208
+ newLeft = Math.min(Math.max(0, newLeft), maxLeft);
209
+
210
+ _mCE.style.top = newTop+"px";
211
+ _mCE.style.left = newLeft+"px";
212
+ return false;
213
+ };
214
+
215
+ /***
216
+ * Managing a textarea (this part need the navigator infos from editAreaLoader
217
+ ***/
218
+
219
+ var nav= editAreaLoader.nav;
220
+
221
+ // allow to get infos on the selection: array(start, end)
222
+ function getSelectionRange(textarea){
223
+ return {"start": textarea.selectionStart, "end": textarea.selectionEnd};
224
+ };
225
+
226
+ // allow to set the selection
227
+ function setSelectionRange(t, start, end){
228
+ t.focus();
229
+
230
+ start = Math.max(0, Math.min(t.value.length, start));
231
+ end = Math.max(start, Math.min(t.value.length, end));
232
+
233
+ if( nav.isOpera && nav.isOpera < 9.6 ){ // Opera bug when moving selection start and selection end
234
+ t.selectionEnd = 1;
235
+ t.selectionStart = 0;
236
+ t.selectionEnd = 1;
237
+ t.selectionStart = 0;
238
+ }
239
+ t.selectionStart = start;
240
+ t.selectionEnd = end;
241
+ //textarea.setSelectionRange(start, end);
242
+
243
+ if(nav.isIE)
244
+ set_IE_selection(t);
245
+ };
246
+
247
+
248
+ // set IE position in Firefox mode (textarea.selectionStart and textarea.selectionEnd). should work as a repeated task
249
+ function get_IE_selection(t){
250
+ var d=document,div,range,stored_range,elem,scrollTop,relative_top,line_start,line_nb,range_start,range_end,tab;
251
+ if(t && t.focused)
252
+ {
253
+ if(!t.ea_line_height)
254
+ { // calculate the lineHeight
255
+ div= d.createElement("div");
256
+ div.style.fontFamily= get_css_property(t, "font-family");
257
+ div.style.fontSize= get_css_property(t, "font-size");
258
+ div.style.visibility= "hidden";
259
+ div.innerHTML="0";
260
+ d.body.appendChild(div);
261
+ t.ea_line_height= div.offsetHeight;
262
+ d.body.removeChild(div);
263
+ }
264
+ //t.focus();
265
+ range = d.selection.createRange();
266
+ try
267
+ {
268
+ stored_range = range.duplicate();
269
+ stored_range.moveToElementText( t );
270
+ stored_range.setEndPoint( 'EndToEnd', range );
271
+ if(stored_range.parentElement() == t){
272
+ // the range don't take care of empty lines in the end of the selection
273
+ elem = t;
274
+ scrollTop = 0;
275
+ while(elem.parentNode){
276
+ scrollTop+= elem.scrollTop;
277
+ elem = elem.parentNode;
278
+ }
279
+
280
+ // var scrollTop= t.scrollTop + document.body.scrollTop;
281
+
282
+ // var relative_top= range.offsetTop - calculeOffsetTop(t) + scrollTop;
283
+ relative_top= range.offsetTop - calculeOffsetTop(t)+ scrollTop;
284
+ // alert("rangeoffset: "+ range.offsetTop +"\ncalcoffsetTop: "+ calculeOffsetTop(t) +"\nrelativeTop: "+ relative_top);
285
+ line_start = Math.round((relative_top / t.ea_line_height) +1);
286
+
287
+ line_nb = Math.round(range.boundingHeight / t.ea_line_height);
288
+
289
+ range_start = stored_range.text.length - range.text.length;
290
+ tab = t.value.substr(0, range_start).split("\n");
291
+ range_start += (line_start - tab.length)*2; // add missing empty lines to the selection
292
+ t.selectionStart = range_start;
293
+
294
+ range_end = t.selectionStart + range.text.length;
295
+ tab = t.value.substr(0, range_start + range.text.length).split("\n");
296
+ range_end += (line_start + line_nb - 1 - tab.length)*2;
297
+ t.selectionEnd = range_end;
298
+ }
299
+ }
300
+ catch(e){}
301
+ }
302
+ if( t && t.id )
303
+ {
304
+ setTimeout("get_IE_selection(document.getElementById('"+ t.id +"'));", 50);
305
+ }
306
+ };
307
+
308
+ function IE_textarea_focus(){
309
+ event.srcElement.focused= true;
310
+ }
311
+
312
+ function IE_textarea_blur(){
313
+ event.srcElement.focused= false;
314
+ }
315
+
316
+ // select the text for IE (take into account the \r difference)
317
+ function set_IE_selection( t ){
318
+ var nbLineStart,nbLineStart,nbLineEnd,range;
319
+ if(!window.closed){
320
+ nbLineStart=t.value.substr(0, t.selectionStart).split("\n").length - 1;
321
+ nbLineEnd=t.value.substr(0, t.selectionEnd).split("\n").length - 1;
322
+ try
323
+ {
324
+ range = document.selection.createRange();
325
+ range.moveToElementText( t );
326
+ range.setEndPoint( 'EndToStart', range );
327
+ range.moveStart('character', t.selectionStart - nbLineStart);
328
+ range.moveEnd('character', t.selectionEnd - nbLineEnd - (t.selectionStart - nbLineStart) );
329
+ range.select();
330
+ }
331
+ catch(e){}
332
+ }
333
+ };
334
+
335
+
336
+ editAreaLoader.waiting_loading["elements_functions.js"]= "loaded";
@@ -0,0 +1,407 @@
1
+ // change_to: "on" or "off"
2
+ EditArea.prototype.change_highlight= function(change_to){
3
+ if(this.settings["syntax"].length==0 && change_to==false){
4
+ this.switchClassSticky(_$("highlight"), 'editAreaButtonDisabled', true);
5
+ this.switchClassSticky(_$("reset_highlight"), 'editAreaButtonDisabled', true);
6
+ return false;
7
+ }
8
+
9
+ if(this.do_highlight==change_to)
10
+ return false;
11
+
12
+
13
+ this.getIESelection();
14
+ var pos_start= this.textarea.selectionStart;
15
+ var pos_end= this.textarea.selectionEnd;
16
+
17
+ if(this.do_highlight===true || change_to==false)
18
+ this.disable_highlight();
19
+ else
20
+ this.enable_highlight();
21
+ this.textarea.focus();
22
+ this.textarea.selectionStart = pos_start;
23
+ this.textarea.selectionEnd = pos_end;
24
+ this.setIESelection();
25
+
26
+ };
27
+
28
+ EditArea.prototype.disable_highlight= function(displayOnly){
29
+ var t= this, a=t.textarea, new_Obj, old_class, new_class;
30
+
31
+ t.selection_field.innerHTML="";
32
+ t.selection_field_text.innerHTML="";
33
+ t.content_highlight.style.visibility="hidden";
34
+ // replacing the node is far more faster than deleting it's content in firefox
35
+ new_Obj= t.content_highlight.cloneNode(false);
36
+ new_Obj.innerHTML= "";
37
+ t.content_highlight.parentNode.insertBefore(new_Obj, t.content_highlight);
38
+ t.content_highlight.parentNode.removeChild(t.content_highlight);
39
+ t.content_highlight= new_Obj;
40
+ old_class= parent.getAttribute( a,"class" );
41
+ if(old_class){
42
+ new_class= old_class.replace( "hidden","" );
43
+ parent.setAttribute( a, "class", new_class );
44
+ }
45
+
46
+ a.style.backgroundColor="transparent"; // needed in order to see the bracket finders
47
+
48
+ //var icon= document.getElementById("highlight");
49
+ //setAttribute(icon, "class", getAttribute(icon, "class").replace(/ selected/g, "") );
50
+ //t.restoreClass(icon);
51
+ //t.switchClass(icon,'editAreaButtonNormal');
52
+ t.switchClassSticky(_$("highlight"), 'editAreaButtonNormal', true);
53
+ t.switchClassSticky(_$("reset_highlight"), 'editAreaButtonDisabled', true);
54
+
55
+ t.do_highlight=false;
56
+
57
+ t.switchClassSticky(_$("change_smooth_selection"), 'editAreaButtonSelected', true);
58
+ if(typeof(t.smooth_selection_before_highlight)!="undefined" && t.smooth_selection_before_highlight===false){
59
+ t.change_smooth_selection_mode(false);
60
+ }
61
+
62
+ // this.textarea.style.backgroundColor="#FFFFFF";
63
+ };
64
+
65
+ EditArea.prototype.enable_highlight= function(){
66
+ var t=this, a=t.textarea, new_class;
67
+ t.show_waiting_screen();
68
+
69
+ t.content_highlight.style.visibility="visible";
70
+ new_class =parent.getAttribute(a,"class")+" hidden";
71
+ parent.setAttribute( a, "class", new_class );
72
+
73
+ // IE can't manage mouse click outside text range without this
74
+ if( t.isIE )
75
+ a.style.backgroundColor="#FFFFFF";
76
+
77
+ t.switchClassSticky(_$("highlight"), 'editAreaButtonSelected', false);
78
+ t.switchClassSticky(_$("reset_highlight"), 'editAreaButtonNormal', false);
79
+
80
+ t.smooth_selection_before_highlight=t.smooth_selection;
81
+ if(!t.smooth_selection)
82
+ t.change_smooth_selection_mode(true);
83
+ t.switchClassSticky(_$("change_smooth_selection"), 'editAreaButtonDisabled', true);
84
+
85
+
86
+ t.do_highlight=true;
87
+ t.resync_highlight();
88
+
89
+ t.hide_waiting_screen();
90
+ };
91
+
92
+ /**
93
+ * Ask to update highlighted text
94
+ * @param Array infos - Array of datas returned by EditArea.get_selection_infos()
95
+ */
96
+ EditArea.prototype.maj_highlight= function(infos){
97
+ // for speed mesure
98
+ var debug_opti="",tps_start= new Date().getTime(), tps_middle_opti=new Date().getTime();
99
+ var t=this, hightlighted_text, updated_highlight;
100
+ var textToHighlight=infos["full_text"], doSyntaxOpti = false, doHtmlOpti = false, stay_begin="", stay_end="", trace_new , trace_last;
101
+
102
+ if(t.last_text_to_highlight==infos["full_text"] && t.resync_highlight!==true)
103
+ return;
104
+
105
+ // OPTIMISATION: will search to update only changed lines
106
+ if(t.reload_highlight===true){
107
+ t.reload_highlight=false;
108
+ }else if(textToHighlight.length==0){
109
+ textToHighlight="\n ";
110
+ }else{
111
+ // get text change datas
112
+ changes = t.checkTextEvolution(t.last_text_to_highlight,textToHighlight);
113
+
114
+ // check if it can only reparse the changed text
115
+ trace_new = t.get_syntax_trace(changes.newTextLine).replace(/\r/g, '');
116
+ trace_last = t.get_syntax_trace(changes.lastTextLine).replace(/\r/g, '');
117
+ doSyntaxOpti = ( trace_new == trace_last );
118
+
119
+ // check if the difference comes only from a new line created
120
+ // => we have to remember that the editor can automaticaly add tabulation or space after the new line)
121
+ if( !doSyntaxOpti && trace_new == "\n"+trace_last && /^[ \t\s]*\n[ \t\s]*$/.test( changes.newText.replace(/\r/g, '') ) && changes.lastText =="" )
122
+ {
123
+ doSyntaxOpti = true;
124
+ }
125
+
126
+ // we do the syntax optimisation
127
+ if( doSyntaxOpti ){
128
+
129
+ tps_middle_opti=new Date().getTime();
130
+
131
+ stay_begin= t.last_hightlighted_text.split("\n").slice(0, changes.lineStart).join("\n");
132
+ if(changes.lineStart>0)
133
+ stay_begin+= "\n";
134
+ stay_end= t.last_hightlighted_text.split("\n").slice(changes.lineLastEnd+1).join("\n");
135
+ if(stay_end.length>0)
136
+ stay_end= "\n"+stay_end;
137
+
138
+ // Final check to see that we're not in the middle of span tags
139
+ if( stay_begin.split('<span').length != stay_begin.split('</span').length
140
+ || stay_end.split('<span').length != stay_end.split('</span').length )
141
+ {
142
+ doSyntaxOpti = false;
143
+ stay_end = '';
144
+ stay_begin = '';
145
+ }
146
+ else
147
+ {
148
+ if(stay_begin.length==0 && changes.posLastEnd==-1)
149
+ changes.newTextLine+="\n";
150
+ textToHighlight=changes.newTextLine;
151
+ }
152
+ }
153
+ if(t.settings["debug"]){
154
+ var ch =changes;
155
+ debug_opti= ( doSyntaxOpti?"Optimisation": "No optimisation" )
156
+ +" start: "+ch.posStart +"("+ch.lineStart+")"
157
+ +" end_new: "+ ch.posNewEnd+"("+ch.lineNewEnd+")"
158
+ +" end_last: "+ ch.posLastEnd+"("+ch.lineLastEnd+")"
159
+ +"\nchanged_text: "+ch.newText+" => trace: "+trace_new
160
+ +"\nchanged_last_text: "+ch.lastText+" => trace: "+trace_last
161
+ //debug_opti+= "\nchanged: "+ infos["full_text"].substring(ch.posStart, ch.posNewEnd);
162
+ + "\nchanged_line: "+ch.newTextLine
163
+ + "\nlast_changed_line: "+ch.lastTextLine
164
+ +"\nstay_begin: "+ stay_begin.slice(-100)
165
+ +"\nstay_end: "+ stay_end.substr( 0, 100 );
166
+ //debug_opti="start: "+stay_begin_len+ "("+nb_line_start_unchanged+") end: "+ (stay_end_len)+ "("+(splited.length-nb_line_end_unchanged)+") ";
167
+ //debug_opti+="changed: "+ textToHighlight.substring(stay_begin_len, textToHighlight.length-stay_end_len)+" \n";
168
+
169
+ //debug_opti+="changed: "+ stay_begin.substr(stay_begin.length-200)+ "----------"+ textToHighlight+"------------------"+ stay_end.substr(0,200) +"\n";
170
+ +"\n";
171
+ }
172
+
173
+
174
+ // END OPTIMISATION
175
+ }
176
+
177
+ tps_end_opti = new Date().getTime();
178
+
179
+ // apply highlight
180
+ updated_highlight = t.colorize_text(textToHighlight);
181
+ tpsAfterReg = new Date().getTime();
182
+
183
+ /***
184
+ * see if we can optimize for updating only the required part of the HTML code
185
+ *
186
+ * The goal here will be to find the text node concerned by the modification and to update it
187
+ */
188
+ //-------------------------------------------
189
+
190
+ // disable latest optimization tricks (introduced in 0.8.1 and removed in 0.8.2), TODO: check for another try later
191
+ doSyntaxOpti = doHtmlOpti = false;
192
+ if( doSyntaxOpti )
193
+ {
194
+ try
195
+ {
196
+ var replacedBloc, i, nbStart = '', nbEnd = '', newHtml, lengthOld, lengthNew;
197
+ replacedBloc = t.last_hightlighted_text.substring( stay_begin.length, t.last_hightlighted_text.length - stay_end.length );
198
+
199
+ lengthOld = replacedBloc.length;
200
+ lengthNew = updated_highlight.length;
201
+
202
+ // find the identical caracters at the beginning
203
+ for( i=0; i < lengthOld && i < lengthNew && replacedBloc.charAt(i) == updated_highlight.charAt(i) ; i++ )
204
+ {
205
+ }
206
+ nbStart = i;
207
+ // find the identical caracters at the end
208
+ for( i=0; i + nbStart < lengthOld && i + nbStart < lengthNew && replacedBloc.charAt(lengthOld-i-1) == updated_highlight.charAt(lengthNew-i-1) ; i++ )
209
+ {
210
+ }
211
+ nbEnd = i;
212
+ //console.log( nbStart, nbEnd, replacedBloc, updated_highlight );
213
+ // get the changes
214
+ lastHtml = replacedBloc.substring( nbStart, lengthOld - nbEnd );
215
+ newHtml = updated_highlight.substring( nbStart, lengthNew - nbEnd );
216
+
217
+ // We can do the optimisation only if we havn't touch to span elements
218
+ if( newHtml.indexOf('<span') == -1 && newHtml.indexOf('</span') == -1
219
+ && lastHtml.indexOf('<span') == -1 && lastHtml.indexOf('</span') == -1 )
220
+ {
221
+ var beginStr, nbOpendedSpan, nbClosedSpan, nbUnchangedChars, span, textNode;
222
+ doHtmlOpti = true;
223
+ beginStr = t.last_hightlighted_text.substr( 0, stay_begin.length + nbStart );
224
+ // fix special chars
225
+ newHtml = newHtml.replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&');
226
+
227
+ nbOpendedSpan = beginStr.split('<span').length - 1;
228
+ nbClosedSpan = beginStr.split('</span').length - 1;
229
+ // retrieve the previously opened span (Add 1 for the first level span?)
230
+ span = t.content_highlight.getElementsByTagName('span')[ nbOpendedSpan ];
231
+
232
+ //--------[
233
+ // get the textNode to update
234
+
235
+ // if we're inside a span, we'll take the one that is opened (can be a parent of the current span)
236
+ parentSpan = span;
237
+ maxStartOffset = maxEndOffset = 0;
238
+
239
+ // it will be in the child of the root node
240
+ if( nbOpendedSpan == nbClosedSpan )
241
+ {
242
+ while( parentSpan.parentNode != t.content_highlight && parentSpan.parentNode.tagName != 'PRE' )
243
+ {
244
+ parentSpan = parentSpan.parentNode;
245
+ }
246
+ }
247
+ // get the last opened span
248
+ else
249
+ {
250
+ maxStartOffset = maxEndOffset = beginStr.length + 1;
251
+ // move to parent node for each closed span found after the lastest open span
252
+ nbClosed = beginStr.substr( Math.max( 0, beginStr.lastIndexOf( '<span', maxStartOffset - 1 ) ) ).split('</span').length - 1;
253
+ while( nbClosed > 0 )
254
+ {
255
+ nbClosed--;
256
+ parentSpan = parentSpan.parentNode;
257
+ }
258
+
259
+ // find the position of the last opended tag
260
+ while( parentSpan.parentNode != t.content_highlight && parentSpan.parentNode.tagName != 'PRE' && ( tmpMaxStartOffset = Math.max( 0, beginStr.lastIndexOf( '<span', maxStartOffset - 1 ) ) ) < ( tmpMaxEndOffset = Math.max( 0, beginStr.lastIndexOf( '</span', maxEndOffset - 1 ) ) ) )
261
+ {
262
+ maxStartOffset = tmpMaxStartOffset;
263
+ maxEndOffset = tmpMaxEndOffset;
264
+ }
265
+ }
266
+ // Note: maxEndOffset is no more used but maxStartOffset will be used
267
+
268
+ if( parentSpan.parentNode == t.content_highlight || parentSpan.parentNode.tagName == 'PRE' )
269
+ {
270
+ maxStartOffset = Math.max( 0, beginStr.indexOf( '<span' ) );
271
+ }
272
+
273
+ // find the matching text node (this will be one that will be at the end of the beginStr
274
+ if( maxStartOffset == beginStr.length )
275
+ {
276
+ nbSubSpanBefore = 0;
277
+ }
278
+ else
279
+ {
280
+ lastEndPos = Math.max( 0, beginStr.lastIndexOf( '>', maxStartOffset ) );
281
+
282
+ // count the number of sub spans
283
+ nbSubSpanBefore = beginStr.substr( lastEndPos ).split('<span').length-1;
284
+ }
285
+
286
+ // there is no sub-span before
287
+ if( nbSubSpanBefore == 0 )
288
+ {
289
+ textNode = parentSpan.firstChild;
290
+ }
291
+ // we need to find where is the text node modified
292
+ else
293
+ {
294
+ // take the last direct child (no sub-child)
295
+ lastSubSpan = parentSpan.getElementsByTagName('span')[ nbSubSpanBefore - 1 ];
296
+ while( lastSubSpan.parentNode != parentSpan )
297
+ {
298
+ lastSubSpan = lastSubSpan.parentNode;
299
+ }
300
+
301
+ // associate to next text node following the last sub span
302
+ if( lastSubSpan.nextSibling == null || lastSubSpan.nextSibling.nodeType != 3 )
303
+ {
304
+ textNode = document.createTextNode('');
305
+ lastSubSpan.parentNode.insertBefore( textNode, lastSubSpan.nextSibling );
306
+ }
307
+ else
308
+ {
309
+ textNode = lastSubSpan.nextSibling;
310
+ }
311
+ }
312
+ //--------]
313
+
314
+
315
+ //--------[
316
+ // update the textNode content
317
+
318
+ // number of caracters after the last opened of closed span
319
+ //nbUnchangedChars = ( lastIndex = beginStr.lastIndexOf( '>' ) ) == -1 ? beginStr.length : beginStr.length - ( lastIndex + 1 );
320
+ //nbUnchangedChars = ? beginStr.length : beginStr.substr( lastIndex + 1 ).replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&').length;
321
+
322
+ if( ( lastIndex = beginStr.lastIndexOf( '>' ) ) == -1 )
323
+ {
324
+ nbUnchangedChars = beginStr.length;
325
+ }
326
+ else
327
+ {
328
+ nbUnchangedChars = beginStr.substr( lastIndex + 1 ).replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&').length;
329
+ //nbUnchangedChars += beginStr.substr( ).replace( /&/g, '&amp;').replace( /</g, '&lt;').replace( />/g, '&gt;').length - beginStr.length;
330
+ }
331
+ //alert( nbUnchangedChars );
332
+ // console.log( span, textNode, nbOpendedSpan,nbClosedSpan, span.nextSibling, textNode.length, nbUnchangedChars, lastHtml, lastHtml.length, newHtml, newHtml.length );
333
+ // alert( textNode.parentNode.className +'-'+ textNode.parentNode.tagName+"\n"+ textNode.data +"\n"+ nbUnchangedChars +"\n"+ lastHtml.length +"\n"+ newHtml +"\n"+ newHtml.length );
334
+ // console.log( nbUnchangedChars, lastIndex, beginStr.length, beginStr.replace(/&/g, '&amp;'), lastHtml.length, '|', newHtml.replace( /\t/g, 't').replace( /\n/g, 'n').replace( /\r/g, 'r'), lastHtml.replace( /\t/g, 't').replace( /\n/g, 'n').replace( /\r/, 'r') );
335
+ // console.log( textNode.data.replace(/&/g, '&amp;') );
336
+ // IE only manage \r for cariage return in textNode and not \n or \r\n
337
+ if( t.isIE )
338
+ {
339
+ nbUnchangedChars -= ( beginStr.substr( beginStr.length - nbUnchangedChars ).split("\n").length - 1 );
340
+ //alert( textNode.data.replace(/\r/g, '_r').replace(/\n/g, '_n'));
341
+ textNode.replaceData( nbUnchangedChars, lastHtml.replace(/\n/g, '').length, newHtml.replace(/\n/g, '') );
342
+ }
343
+ else
344
+ {
345
+ textNode.replaceData( nbUnchangedChars, lastHtml.length, newHtml );
346
+ }
347
+ //--------]
348
+ }
349
+ }
350
+ // an exception shouldn't occured but if replaceData failed at least it won't break everything
351
+ catch( e )
352
+ {
353
+ // throw e;
354
+ // console.log( e );
355
+ doHtmlOpti = false;
356
+ }
357
+
358
+ }
359
+
360
+ /*** END HTML update's optimisation ***/
361
+ // end test
362
+
363
+ // console.log( (TPS6-TPS5), (TPS5-TPS4), (TPS4-TPS3), (TPS3-TPS2), (TPS2-TPS1), _CPT );
364
+ // get the new highlight content
365
+ tpsAfterOpti2 = new Date().getTime();
366
+ hightlighted_text = stay_begin + updated_highlight + stay_end;
367
+ if( !doHtmlOpti )
368
+ {
369
+ // update the content of the highlight div by first updating a clone node (as there is no display in the same time for t node it's quite faster (5*))
370
+ var new_Obj= t.content_highlight.cloneNode(false);
371
+ if( ( t.isIE && t.isIE < 8 ) || ( t.isOpera && t.isOpera < 9.6 ) )
372
+ new_Obj.innerHTML= "<pre><span class='"+ t.settings["syntax"] +"'>" + hightlighted_text + "</span></pre>";
373
+ else
374
+ new_Obj.innerHTML= "<span class='"+ t.settings["syntax"] +"'>"+ hightlighted_text +"</span>";
375
+
376
+ t.content_highlight.parentNode.replaceChild(new_Obj, t.content_highlight);
377
+
378
+ t.content_highlight= new_Obj;
379
+ }
380
+
381
+ t.last_text_to_highlight= infos["full_text"];
382
+ t.last_hightlighted_text= hightlighted_text;
383
+
384
+ tps3=new Date().getTime();
385
+
386
+ if(t.settings["debug"]){
387
+ //lineNumber=tab_text.length;
388
+ //t.debug.value+=" \nNB char: "+_$("src").value.length+" Nb line: "+ lineNumber;
389
+
390
+ t.debug.value= "Tps optimisation "+(tps_end_opti-tps_start)
391
+ +" | tps reg exp: "+ (tpsAfterReg-tps_end_opti)
392
+ +" | tps opti HTML : "+ (tpsAfterOpti2-tpsAfterReg) + ' '+ ( doHtmlOpti ? 'yes' : 'no' )
393
+ +" | tps update highlight content: "+ (tps3-tpsAfterOpti2)
394
+ +" | tpsTotal: "+ (tps3-tps_start)
395
+ + "("+tps3+")\n"+ debug_opti;
396
+ // t.debug.value+= "highlight\n"+hightlighted_text;*/
397
+ }
398
+
399
+ };
400
+
401
+ EditArea.prototype.resync_highlight= function(reload_now){
402
+ this.reload_highlight=true;
403
+ this.last_text_to_highlight="";
404
+ this.focus();
405
+ if(reload_now)
406
+ this.check_line_selection(false);
407
+ };