Podświetlanie składni w edytorze XML dzięki editArea. Closes #17. Niestety dla tekstó...
[redakcja.git] / project / static / js / manage_area.js
diff --git a/project/static/js/manage_area.js b/project/static/js/manage_area.js
new file mode 100755 (executable)
index 0000000..e10c5e9
--- /dev/null
@@ -0,0 +1,623 @@
+       EditArea.prototype.focus = function() {\r
+               this.textarea.focus();\r
+               this.textareaFocused=true;\r
+       };\r
+\r
+\r
+       EditArea.prototype.check_line_selection= function(timer_checkup){\r
+               var changes, infos, new_top, new_width,i;\r
+               \r
+               var t1=t2=t2_1=t3=tLines=tend= new Date().getTime();\r
+               // l'editeur n'existe plus => on quitte\r
+               if(!editAreas[this.id])\r
+                       return false;\r
+               \r
+               if(!this.smooth_selection && !this.do_highlight)\r
+               {\r
+                       //do nothing\r
+               }\r
+               else if(this.textareaFocused && editAreas[this.id]["displayed"]==true && this.isResizing==false)\r
+               {\r
+                       infos   = this.get_selection_infos();\r
+                       changes = this.checkTextEvolution( typeof( this.last_selection['full_text'] ) == 'undefined' ? '' : this.last_selection['full_text'], infos['full_text'] );\r
+               \r
+                       t2= new Date().getTime();\r
+                       \r
+                       // if selection change\r
+                       if(this.last_selection["line_start"] != infos["line_start"] || this.last_selection["line_nb"] != infos["line_nb"] || infos["full_text"] != this.last_selection["full_text"] || this.reload_highlight || this.last_selection["selectionStart"] != infos["selectionStart"] || this.last_selection["selectionEnd"] != infos["selectionEnd"] || !timer_checkup )\r
+                       {\r
+                               // move and adjust text selection elements\r
+                               new_top         = this.getLinePosTop( infos["line_start"] );\r
+                               new_width       = Math.max(this.textarea.scrollWidth, this.container.clientWidth -50);\r
+                               this.selection_field.style.top=this.selection_field_text.style.top=new_top+"px";\r
+                               if(!this.settings['word_wrap']){        \r
+                                       this.selection_field.style.width=this.selection_field_text.style.width=this.test_font_size.style.width=new_width+"px";\r
+                               }\r
+                               \r
+                               // usefull? => _$("cursor_pos").style.top=new_top+"px"; \r
+               \r
+                               if(this.do_highlight==true)\r
+                               {\r
+                                       // fill selection elements\r
+                                       var curr_text   = infos["full_text"].split("\n");\r
+                                       var content             = "";\r
+                                       //alert("length: "+curr_text.length+ " i: "+ Math.max(0,infos["line_start"]-1)+ " end: "+Math.min(curr_text.length, infos["line_start"]+infos["line_nb"]-1)+ " line: "+infos["line_start"]+" [0]: "+curr_text[0]+" [1]: "+curr_text[1]);\r
+                                       var start               = Math.max(0,infos["line_start"]-1);\r
+                                       var end                 = Math.min(curr_text.length, infos["line_start"]+infos["line_nb"]-1);\r
+                                       \r
+                                       //curr_text[start]= curr_text[start].substr(0,infos["curr_pos"]-1) +"¤_overline_¤"+ curr_text[start].substr(infos["curr_pos"]-1);\r
+                                       for(i=start; i< end; i++){\r
+                                               content+= curr_text[i]+"\n";    \r
+                                       }\r
+                                       \r
+                                       // add special chars arround selected characters\r
+                                       selLength       = infos['selectionEnd'] - infos['selectionStart'];\r
+                                       content         = content.substr( 0, infos["curr_pos"] - 1 ) + "\r\r" + content.substr( infos["curr_pos"] - 1, selLength ) + "\r\r" + content.substr( infos["curr_pos"] - 1 + selLength );\r
+                                       content         = '<span>'+ content.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace("\r\r", '</span><strong>').replace("\r\r", '</strong><span>') +'</span>';\r
+                                       \r
+                                       if( this.isIE || ( this.isOpera && this.isOpera < 9.6 ) ) {\r
+                                               this.selection_field.innerHTML= "<pre>" + content.replace(/^\r?\n/, "<br>") + "</pre>";\r
+                                       } else {\r
+                                               this.selection_field.innerHTML= content;\r
+                                       }\r
+                                       this.selection_field_text.innerHTML = this.selection_field.innerHTML;\r
+                                       t2_1 = new Date().getTime();\r
+                                       // check if we need to update the highlighted background \r
+                                       if(this.reload_highlight || (infos["full_text"] != this.last_text_to_highlight && (this.last_selection["line_start"]!=infos["line_start"] || this.show_line_colors || this.settings['word_wrap'] || this.last_selection["line_nb"]!=infos["line_nb"] || this.last_selection["nb_line"]!=infos["nb_line"]) ) )\r
+                                       {\r
+                                               this.maj_highlight(infos);\r
+                                       }\r
+                               }               \r
+                       }\r
+                       t3= new Date().getTime();\r
+                       \r
+                       // manage line heights\r
+                       if( this.settings['word_wrap'] && infos["full_text"] != this.last_selection["full_text"])\r
+                       {\r
+                               // refresh only 1 line if text change concern only one line and that the total line number has not changed\r
+                               if( changes.newText.split("\n").length == 1 && this.last_selection['nb_line'] && infos['nb_line'] == this.last_selection['nb_line'] )\r
+                               {\r
+                                       this.fixLinesHeight( infos['full_text'], changes.lineStart, changes.lineStart );\r
+                               }\r
+                               else\r
+                               {\r
+                                       this.fixLinesHeight( infos['full_text'], changes.lineStart, -1 );\r
+                               }\r
+                       }\r
+               \r
+                       tLines= new Date().getTime();\r
+                       // manage bracket finding\r
+                       if( infos["line_start"] != this.last_selection["line_start"] || infos["curr_pos"] != this.last_selection["curr_pos"] || infos["full_text"].length!=this.last_selection["full_text"].length || this.reload_highlight || !timer_checkup )\r
+                       {\r
+                               // move _cursor_pos\r
+                               var selec_char= infos["curr_line"].charAt(infos["curr_pos"]-1);\r
+                               var no_real_move=true;\r
+                               if(infos["line_nb"]==1 && (this.assocBracket[selec_char] || this.revertAssocBracket[selec_char]) ){\r
+                                       \r
+                                       no_real_move=false;                                     \r
+                                       //findEndBracket(infos["line_start"], infos["curr_pos"], selec_char);\r
+                                       if(this.findEndBracket(infos, selec_char) === true){\r
+                                               _$("end_bracket").style.visibility      ="visible";\r
+                                               _$("cursor_pos").style.visibility       ="visible";\r
+                                               _$("cursor_pos").innerHTML                      = selec_char;\r
+                                               _$("end_bracket").innerHTML                     = (this.assocBracket[selec_char] || this.revertAssocBracket[selec_char]);\r
+                                       }else{\r
+                                               _$("end_bracket").style.visibility      ="hidden";\r
+                                               _$("cursor_pos").style.visibility       ="hidden";\r
+                                       }\r
+                               }else{\r
+                                       _$("cursor_pos").style.visibility       ="hidden";\r
+                                       _$("end_bracket").style.visibility      ="hidden";\r
+                               }\r
+                               //alert("move cursor");\r
+                               this.displayToCursorPosition("cursor_pos", infos["line_start"], infos["curr_pos"]-1, infos["curr_line"], no_real_move);\r
+                               if(infos["line_nb"]==1 && infos["line_start"]!=this.last_selection["line_start"])\r
+                                       this.scroll_to_view();\r
+                       }\r
+                       this.last_selection=infos;\r
+               }\r
+               \r
+               tend= new Date().getTime();\r
+               //if( (tend-t1) > 7 )\r
+               //      console.log( "tps total: "+ (tend-t1) + " tps get_infos: "+ (t2-t1)+ " tps selec: "+ (t2_1-t2)+ " tps highlight: "+ (t3-t2_1) +" tps lines: "+ (tLines-t3) +" tps cursor+lines: "+ (tend-tLines)+" \n" );\r
+               \r
+               \r
+               if(timer_checkup){\r
+                       setTimeout("editArea.check_line_selection(true)", this.check_line_selection_timer);\r
+               }\r
+       };\r
+\r
+\r
+       EditArea.prototype.get_selection_infos= function(){\r
+               var sel={}, start, end, len, str;\r
+       \r
+               this.getIESelection();\r
+               start   = this.textarea.selectionStart;\r
+               end             = this.textarea.selectionEnd;           \r
+               \r
+               if( this.last_selection["selectionStart"] == start && this.last_selection["selectionEnd"] == end && this.last_selection["full_text"] == this.textarea.value )\r
+               {       \r
+                       return this.last_selection;\r
+               }\r
+                       \r
+               if(this.tabulation!="\t" && this.textarea.value.indexOf("\t")!=-1) \r
+               {       // can append only after copy/paste \r
+                       len             = this.textarea.value.length;\r
+                       this.textarea.value     = this.replace_tab(this.textarea.value);\r
+                       start   = end   = start+(this.textarea.value.length-len);\r
+                       this.area_select( start, 0 );\r
+               }\r
+               \r
+               sel["selectionStart"]   = start;\r
+               sel["selectionEnd"]             = end;          \r
+               sel["full_text"]                = this.textarea.value;\r
+               sel["line_start"]               = 1;\r
+               sel["line_nb"]                  = 1;\r
+               sel["curr_pos"]                 = 0;\r
+               sel["curr_line"]                = "";\r
+               sel["indexOfCursor"]    = 0;\r
+               sel["selec_direction"]  = this.last_selection["selec_direction"];\r
+\r
+               //return sel;   \r
+               var splitTab= sel["full_text"].split("\n");\r
+               var nbLine      = Math.max(0, splitTab.length);         \r
+               var nbChar      = Math.max(0, sel["full_text"].length - (nbLine - 1));  // (remove \n caracters from the count)\r
+               if( sel["full_text"].indexOf("\r") != -1 )\r
+                       nbChar  = nbChar - ( nbLine - 1 );              // (remove \r caracters from the count)\r
+               sel["nb_line"]  = nbLine;               \r
+               sel["nb_char"]  = nbChar;\r
+       \r
+               if(start>0){\r
+                       str                                     = sel["full_text"].substr(0,start);\r
+                       sel["curr_pos"]         = start - str.lastIndexOf("\n");\r
+                       sel["line_start"]       = Math.max(1, str.split("\n").length);\r
+               }else{\r
+                       sel["curr_pos"]=1;\r
+               }\r
+               if(end>start){\r
+                       sel["line_nb"]=sel["full_text"].substring(start,end).split("\n").length;\r
+               }\r
+               sel["indexOfCursor"]=start;             \r
+               sel["curr_line"]=splitTab[Math.max(0,sel["line_start"]-1)];\r
+       \r
+               // determine in which direction the selection grow\r
+               if(sel["selectionStart"] == this.last_selection["selectionStart"]){\r
+                       if(sel["selectionEnd"]>this.last_selection["selectionEnd"])\r
+                               sel["selec_direction"]= "down";\r
+                       else if(sel["selectionEnd"] == this.last_selection["selectionStart"])\r
+                               sel["selec_direction"]= this.last_selection["selec_direction"];\r
+               }else if(sel["selectionStart"] == this.last_selection["selectionEnd"] && sel["selectionEnd"]>this.last_selection["selectionEnd"]){\r
+                       sel["selec_direction"]= "down";\r
+               }else{\r
+                       sel["selec_direction"]= "up";\r
+               }\r
+               \r
+               _$("nbLine").innerHTML  = nbLine;               \r
+               _$("nbChar").innerHTML  = nbChar;               \r
+               _$("linePos").innerHTML = sel["line_start"];\r
+               _$("currPos").innerHTML = sel["curr_pos"];\r
+\r
+               return sel;             \r
+       };\r
+       \r
+       // set IE position in Firefox mode (textarea.selectionStart and textarea.selectionEnd)\r
+       EditArea.prototype.getIESelection= function(){\r
+               var selectionStart, selectionEnd, range, stored_range;\r
+               \r
+               if( !this.isIE )\r
+                       return false;\r
+                       \r
+               // make it work as nowrap mode (easier for range manipulation with lineHeight)\r
+               if( this.settings['word_wrap'] )\r
+                       this.textarea.wrap='off';\r
+                       \r
+               try{\r
+                       range                   = document.selection.createRange();\r
+                       stored_range    = range.duplicate();\r
+                       stored_range.moveToElementText( this.textarea );\r
+                       stored_range.setEndPoint( 'EndToEnd', range );\r
+                       if( stored_range.parentElement() != this.textarea )\r
+                               throw "invalid focus";\r
+                               \r
+                       // the range don't take care of empty lines in the end of the selection\r
+                       var scrollTop   = this.result.scrollTop + document.body.scrollTop;\r
+                       var relative_top= range.offsetTop - parent.calculeOffsetTop(this.textarea) + scrollTop;\r
+                       var line_start  = Math.round((relative_top / this.lineHeight) +1);\r
+                       var line_nb             = Math.round( range.boundingHeight / this.lineHeight );\r
+                                               \r
+                       selectionStart  = stored_range.text.length - range.text.length;         \r
+                       selectionStart  += ( line_start - this.textarea.value.substr(0, selectionStart).split("\n").length)*2;          // count missing empty \r to the selection\r
+                       selectionStart  -= ( line_start - this.textarea.value.substr(0, selectionStart).split("\n").length ) * 2;\r
+                       \r
+                       selectionEnd    = selectionStart + range.text.length;           \r
+                       selectionEnd    += (line_start + line_nb - 1 - this.textarea.value.substr(0, selectionEnd ).split("\n").length)*2;                      \r
+               \r
+                       this.textarea.selectionStart    = selectionStart;\r
+                       this.textarea.selectionEnd              = selectionEnd;\r
+               }\r
+               catch(e){}\r
+               \r
+               // restore wrap mode\r
+               if( this.settings['word_wrap'] )\r
+                       this.textarea.wrap='soft';\r
+       };\r
+       \r
+       // select the text for IE (and take care of \r caracters)\r
+       EditArea.prototype.setIESelection= function(){\r
+               var a = this.textarea, nbLineStart, nbLineEnd, range;\r
+               \r
+               if( !this.isIE )\r
+                       return false;\r
+               \r
+               nbLineStart     = a.value.substr(0, a.selectionStart).split("\n").length - 1;\r
+               nbLineEnd       = a.value.substr(0, a.selectionEnd).split("\n").length - 1;\r
+               range           = document.selection.createRange();\r
+               range.moveToElementText( a );\r
+               range.setEndPoint( 'EndToStart', range );\r
+               \r
+               range.moveStart('character', a.selectionStart - nbLineStart);\r
+               range.moveEnd('character', a.selectionEnd - nbLineEnd - (a.selectionStart - nbLineStart)  );\r
+               range.select();\r
+       };\r
+       \r
+       \r
+       \r
+       EditArea.prototype.checkTextEvolution=function(lastText,newText){\r
+               // ch will contain changes datas\r
+               var ch={},baseStep=200, cpt=0, end, step,tStart=new Date().getTime();\r
+       \r
+               end             = Math.min(newText.length, lastText.length);\r
+        step   = baseStep;\r
+        // find how many chars are similar at the begin of the text                                            \r
+               while( cpt<end && step>=1 ){\r
+            if(lastText.substr(cpt, step) == newText.substr(cpt, step)){\r
+                cpt+= step;\r
+            }else{\r
+                step= Math.floor(step/2);\r
+            }\r
+               }\r
+               \r
+               ch.posStart     = cpt;\r
+               ch.lineStart= newText.substr(0, ch.posStart).split("\n").length -1;                                             \r
+               \r
+               cpt_last        = lastText.length;\r
+        cpt                    = newText.length;\r
+        step           = baseStep;                     \r
+        // find how many chars are similar at the end of the text                                              \r
+               while( cpt>=0 && cpt_last>=0 && step>=1 ){\r
+            if(lastText.substr(cpt_last-step, step) == newText.substr(cpt-step, step)){\r
+                cpt-= step;\r
+                cpt_last-= step;\r
+            }else{\r
+                step= Math.floor(step/2);\r
+            }\r
+               }\r
+               \r
+               ch.posNewEnd    = cpt;\r
+               ch.posLastEnd   = cpt_last;\r
+               if(ch.posNewEnd<=ch.posStart){\r
+                       if(lastText.length < newText.length){\r
+                               ch.posNewEnd= ch.posStart + newText.length - lastText.length;\r
+                               ch.posLastEnd= ch.posStart;\r
+                       }else{\r
+                               ch.posLastEnd= ch.posStart + lastText.length - newText.length;\r
+                               ch.posNewEnd= ch.posStart;\r
+                       }\r
+               } \r
+               ch.newText              = newText.substring(ch.posStart, ch.posNewEnd);\r
+               ch.lastText             = lastText.substring(ch.posStart, ch.posLastEnd);                                   \r
+               \r
+               ch.lineNewEnd   = newText.substr(0, ch.posNewEnd).split("\n").length -1;\r
+               ch.lineLastEnd  = lastText.substr(0, ch.posLastEnd).split("\n").length -1;\r
+               \r
+               ch.newTextLine  = newText.split("\n").slice(ch.lineStart, ch.lineNewEnd+1).join("\n");\r
+               ch.lastTextLine = lastText.split("\n").slice(ch.lineStart, ch.lineLastEnd+1).join("\n");\r
+               //console.log( ch );\r
+               return ch;      \r
+       };\r
+       \r
+       EditArea.prototype.tab_selection= function(){\r
+               if(this.is_tabbing)\r
+                       return;\r
+               this.is_tabbing=true;\r
+               //infos=getSelectionInfos();\r
+               //if( document.selection ){\r
+               this.getIESelection();\r
+               /* Insertion du code de formatage */\r
+               var start = this.textarea.selectionStart;\r
+               var end = this.textarea.selectionEnd;\r
+               var insText = this.textarea.value.substring(start, end);\r
+               \r
+               /* Insert tabulation and ajust cursor position */\r
+               var pos_start=start;\r
+               var pos_end=end;\r
+               if (insText.length == 0) {\r
+                       // if only one line selected\r
+                       this.textarea.value = this.textarea.value.substr(0, start) + this.tabulation + this.textarea.value.substr(end);\r
+                       pos_start = start + this.tabulation.length;\r
+                       pos_end=pos_start;\r
+               } else {\r
+                       start= Math.max(0, this.textarea.value.substr(0, start).lastIndexOf("\n")+1);\r
+                       endText=this.textarea.value.substr(end);\r
+                       startText=this.textarea.value.substr(0, start);\r
+                       tmp= this.textarea.value.substring(start, end).split("\n");\r
+                       insText= this.tabulation+tmp.join("\n"+this.tabulation);\r
+                       this.textarea.value = startText + insText + endText;\r
+                       pos_start = start;\r
+                       pos_end= this.textarea.value.indexOf("\n", startText.length + insText.length);\r
+                       if(pos_end==-1)\r
+                               pos_end=this.textarea.value.length;\r
+                       //pos = start + repdeb.length + insText.length + ;\r
+               }\r
+               this.textarea.selectionStart = pos_start;\r
+               this.textarea.selectionEnd = pos_end;\r
+               \r
+               //if( document.selection ){\r
+               if(this.isIE)\r
+               {\r
+                       this.setIESelection();\r
+                       setTimeout("editArea.is_tabbing=false;", 100);  // IE can't accept to make 2 tabulation without a little break between both\r
+               }\r
+               else\r
+               { \r
+                       this.is_tabbing=false;\r
+               }       \r
+               \r
+       };\r
+       \r
+       EditArea.prototype.invert_tab_selection= function(){\r
+               var t=this, a=this.textarea;\r
+               if(t.is_tabbing)\r
+                       return;\r
+               t.is_tabbing=true;\r
+               //infos=getSelectionInfos();\r
+               //if( document.selection ){\r
+               t.getIESelection();\r
+               \r
+               var start       = a.selectionStart;\r
+               var end         = a.selectionEnd;\r
+               var insText     = a.value.substring(start, end);\r
+               \r
+               /* Tab remove and cursor seleciton adjust */\r
+               var pos_start=start;\r
+               var pos_end=end;\r
+               if (insText.length == 0) {\r
+                       if(a.value.substring(start-t.tabulation.length, start)==t.tabulation)\r
+                       {\r
+                               a.value         = a.value.substr(0, start-t.tabulation.length) + a.value.substr(end);\r
+                               pos_start       = Math.max(0, start-t.tabulation.length);\r
+                               pos_end         = pos_start;\r
+                       }       \r
+                       /*\r
+                       a.value = a.value.substr(0, start) + t.tabulation + insText + a.value.substr(end);\r
+                       pos_start = start + t.tabulation.length;\r
+                       pos_end=pos_start;*/\r
+               } else {\r
+                       start           = a.value.substr(0, start).lastIndexOf("\n")+1;\r
+                       endText         = a.value.substr(end);\r
+                       startText       = a.value.substr(0, start);\r
+                       tmp                     = a.value.substring(start, end).split("\n");\r
+                       insText         = "";\r
+                       for(i=0; i<tmp.length; i++){                            \r
+                               for(j=0; j<t.tab_nb_char; j++){\r
+                                       if(tmp[i].charAt(0)=="\t"){\r
+                                               tmp[i]=tmp[i].substr(1);\r
+                                               j=t.tab_nb_char;\r
+                                       }else if(tmp[i].charAt(0)==" ")\r
+                                               tmp[i]=tmp[i].substr(1);\r
+                               }               \r
+                               insText+=tmp[i];\r
+                               if(i<tmp.length-1)\r
+                                       insText+="\n";\r
+                       }\r
+                       //insText+="_";\r
+                       a.value         = startText + insText + endText;\r
+                       pos_start       = start;\r
+                       pos_end         = a.value.indexOf("\n", startText.length + insText.length);\r
+                       if(pos_end==-1)\r
+                               pos_end=a.value.length;\r
+                       //pos = start + repdeb.length + insText.length + ;\r
+               }\r
+               a.selectionStart = pos_start;\r
+               a.selectionEnd = pos_end;\r
+               \r
+               //if( document.selection ){\r
+               if(t.isIE){\r
+                       // select the text for IE\r
+                       t.setIESelection();\r
+                       setTimeout("editArea.is_tabbing=false;", 100);  // IE can accept to make 2 tabulation without a little break between both\r
+               }else\r
+                       t.is_tabbing=false;\r
+       };\r
+       \r
+       EditArea.prototype.press_enter= function(){             \r
+               if(!this.smooth_selection)\r
+                       return false;\r
+               this.getIESelection();\r
+               var scrollTop= this.result.scrollTop;\r
+               var scrollLeft= this.result.scrollLeft;\r
+               var start=this.textarea.selectionStart;\r
+               var end= this.textarea.selectionEnd;\r
+               var start_last_line= Math.max(0 , this.textarea.value.substring(0, start).lastIndexOf("\n") + 1 );\r
+               var begin_line= this.textarea.value.substring(start_last_line, start).replace(/^([ \t]*).*/gm, "$1");\r
+               var lineStart = this.textarea.value.substring(0, start).split("\n").length;\r
+               if(begin_line=="\n" || begin_line=="\r" || begin_line.length==0)\r
+               {\r
+                       return false;\r
+               }\r
+                       \r
+               if(this.isIE || ( this.isOpera && this.isOpera < 9.6 ) ){\r
+                       begin_line="\r\n"+ begin_line;\r
+               }else{\r
+                       begin_line="\n"+ begin_line;\r
+               }       \r
+               //alert(start_last_line+" strat: "+start +"\n"+this.textarea.value.substring(start_last_line, start)+"\n_"+begin_line+"_")\r
+               this.textarea.value= this.textarea.value.substring(0, start) + begin_line + this.textarea.value.substring(end);\r
+               \r
+               this.area_select(start+ begin_line.length ,0);\r
+               // during this process IE scroll back to the top of the textarea\r
+               if(this.isIE){\r
+                       this.result.scrollTop   = scrollTop;\r
+                       this.result.scrollLeft  = scrollLeft;\r
+               }\r
+               return true;\r
+               \r
+       };\r
+       \r
+       EditArea.prototype.findEndBracket= function(infos, bracket){\r
+                       \r
+               var start=infos["indexOfCursor"];\r
+               var normal_order=true;\r
+               //curr_text=infos["full_text"].split("\n");\r
+               if(this.assocBracket[bracket])\r
+                       endBracket=this.assocBracket[bracket];\r
+               else if(this.revertAssocBracket[bracket]){\r
+                       endBracket=this.revertAssocBracket[bracket];\r
+                       normal_order=false;\r
+               }       \r
+               var end=-1;\r
+               var nbBracketOpen=0;\r
+               \r
+               for(var i=start; i<infos["full_text"].length && i>=0; ){\r
+                       if(infos["full_text"].charAt(i)==endBracket){                           \r
+                               nbBracketOpen--;\r
+                               if(nbBracketOpen<=0){\r
+                                       //i=infos["full_text"].length;\r
+                                       end=i;\r
+                                       break;\r
+                               }\r
+                       }else if(infos["full_text"].charAt(i)==bracket)\r
+                               nbBracketOpen++;\r
+                       if(normal_order)\r
+                               i++;\r
+                       else\r
+                               i--;\r
+               }\r
+               \r
+               //end=infos["full_text"].indexOf("}", start);\r
+               if(end==-1)\r
+                       return false;   \r
+               var endLastLine=infos["full_text"].substr(0, end).lastIndexOf("\n");                    \r
+               if(endLastLine==-1)\r
+                       line=1;\r
+               else\r
+                       line= infos["full_text"].substr(0, endLastLine).split("\n").length + 1;\r
+                                       \r
+               var curPos= end - endLastLine - 1;\r
+               var endLineLength       = infos["full_text"].substring(end).split("\n")[0].length;\r
+               this.displayToCursorPosition("end_bracket", line, curPos, infos["full_text"].substring(endLastLine +1, end + endLineLength));\r
+               return true;\r
+       };\r
+       \r
+       EditArea.prototype.displayToCursorPosition= function(id, start_line, cur_pos, lineContent, no_real_move){\r
+               var elem,dest,content,posLeft=0,posTop,fixPadding,topOffset,endElem;    \r
+\r
+               elem            = this.test_font_size;\r
+               dest            = _$(id);\r
+               content         = "<span id='test_font_size_inner'>"+lineContent.substr(0, cur_pos).replace(/&/g,"&amp;").replace(/</g,"&lt;")+"</span><span id='endTestFont'>"+lineContent.substr(cur_pos).replace(/&/g,"&amp;").replace(/</g,"&lt;")+"</span>";\r
+               if( this.isIE || ( this.isOpera && this.isOpera < 9.6 ) ) {\r
+                       elem.innerHTML= "<pre>" + content.replace(/^\r?\n/, "<br>") + "</pre>";\r
+               } else {\r
+                       elem.innerHTML= content;\r
+               }\r
+               \r
+\r
+               endElem         = _$('endTestFont');\r
+               topOffset       = endElem.offsetTop;\r
+               fixPadding      = parseInt( this.content_highlight.style.paddingLeft.replace("px", "") );\r
+               posLeft         = 45 + endElem.offsetLeft + ( !isNaN( fixPadding ) && topOffset > 0 ? fixPadding : 0 );\r
+               posTop          = this.getLinePosTop( start_line ) + topOffset;// + Math.floor( ( endElem.offsetHeight - 1 ) / this.lineHeight ) * this.lineHeight;\r
+       \r
+               // detect the case where the span start on a line but has no display on it\r
+               if( this.isIE && cur_pos > 0 && endElem.offsetLeft == 0 )\r
+               {\r
+                       posTop  +=      this.lineHeight;\r
+               }\r
+               if(no_real_move!=true){ // when the cursor is hidden no need to move him\r
+                       dest.style.top=posTop+"px";\r
+                       dest.style.left=posLeft+"px";   \r
+               }\r
+               // usefull for smarter scroll\r
+               dest.cursor_top=posTop;\r
+               dest.cursor_left=posLeft;       \r
+       //      _$(id).style.marginLeft=posLeft+"px";\r
+       };\r
+       \r
+       EditArea.prototype.getLinePosTop= function(start_line){\r
+               var elem= _$('line_'+ start_line), posTop=0;\r
+               if( elem )\r
+                       posTop  = elem.offsetTop;\r
+               else\r
+                       posTop  = this.lineHeight * (start_line-1);\r
+               return posTop;\r
+       };\r
+       \r
+       \r
+       // return the dislpayed height of a text (take word-wrap into account)\r
+       EditArea.prototype.getTextHeight= function(text){\r
+               var t=this,elem,height;\r
+               elem            = t.test_font_size;\r
+               content         = text.replace(/&/g,"&amp;").replace(/</g,"&lt;");\r
+               if( t.isIE || ( this.isOpera && this.isOpera < 9.6 ) ) {\r
+                       elem.innerHTML= "<pre>" + content.replace(/^\r?\n/, "<br>") + "</pre>";\r
+               } else {\r
+                       elem.innerHTML= content;\r
+               }\r
+               height  = elem.offsetHeight;\r
+               height  = Math.max( 1, Math.floor( elem.offsetHeight / this.lineHeight ) ) * this.lineHeight;\r
+               return height;\r
+       };\r
+\r
+       /**\r
+        * Fix line height for the given lines\r
+        * @param Integer linestart\r
+        * @param Integer lineEnd End line or -1 to cover all lines\r
+        */\r
+       EditArea.prototype.fixLinesHeight= function( textValue, lineStart,lineEnd ){\r
+               var aText = textValue.split("\n");\r
+               if( lineEnd == -1 )\r
+                       lineEnd = aText.length-1;\r
+               for( var i = Math.max(0, lineStart); i <= lineEnd; i++ )\r
+               {\r
+                       if( elem = _$('line_'+ ( i+1 ) ) )\r
+                       {\r
+                               elem.style.height= typeof( aText[i] ) != "undefined" ? this.getTextHeight( aText[i] )+"px" : this.lineHeight;\r
+                       }\r
+               }\r
+       };\r
+       \r
+       EditArea.prototype.area_select= function(start, length){\r
+               this.textarea.focus();\r
+               \r
+               start   = Math.max(0, Math.min(this.textarea.value.length, start));\r
+               end             = Math.max(start, Math.min(this.textarea.value.length, start+length));\r
+\r
+               if(this.isIE)\r
+               {\r
+                       this.textarea.selectionStart    = start;\r
+                       this.textarea.selectionEnd              = end;          \r
+                       this.setIESelection();\r
+               }\r
+               else\r
+               {\r
+                       // Opera bug when moving selection start and selection end\r
+                       if(this.isOpera && this.isOpera < 9.6 )\r
+                       {       \r
+                               this.textarea.setSelectionRange(0, 0);\r
+                       }\r
+                       this.textarea.setSelectionRange(start, end);\r
+               }\r
+               this.check_line_selection();\r
+       };\r
+       \r
+       \r
+       EditArea.prototype.area_get_selection= function(){\r
+               var text="";\r
+               if( document.selection ){\r
+                       var range = document.selection.createRange();\r
+                       text=range.text;\r
+               }else{\r
+                       text= this.textarea.value.substring(this.textarea.selectionStart, this.textarea.selectionEnd);\r
+               }\r
+               return text;                    \r
+       };
\ No newline at end of file