4 * Developped by Christophe Dolivet
\r
5 * Released under LGPL, Apache and BSD licenses (use the one you want)
\r
11 t.error= false; // to know if load is interrrupt
\r
13 t.inlinePopup= [{popup_id: "area_search_replace", icon_id: "search"},
\r
14 {popup_id: "edit_area_help", icon_id: "help"}];
\r
19 parent.editAreaLoader.set_browser_infos(t); // navigator identification
\r
20 // fix IE8 detection as we run in IE7 emulate mode through X-UA <meta> tag
\r
24 t.last_selection={};
\r
25 t.last_text_to_highlight="";
\r
26 t.last_hightlighted_text= "";
\r
28 t.allready_used_syntax= {};
\r
29 t.check_line_selection_timer= 50; // the timer delay for modification and/or selection change detection
\r
31 t.textareaFocused= false;
\r
32 t.highlight_selection_line= null;
\r
41 t.revertAssocBracket= {};
\r
42 // bracket selection init
\r
43 t.assocBracket["("]=")";
\r
44 t.assocBracket["{"]="}";
\r
45 t.assocBracket["["]="]";
\r
46 for(var index in t.assocBracket){
\r
47 t.revertAssocBracket[t.assocBracket[index]]=index;
\r
49 t.is_editable= true;
\r
55 t.code = []; // store highlight syntax for languagues*/
\r
58 /*t.default_font_family= "monospace";
\r
59 t.default_font_size= 10;*/
\r
60 t.tab_nb_char= 8; //nb of white spaces corresponding to a tabulation
\r
64 t.is_tabbing= false;
\r
66 t.fullscreen= {'isFull': false};
\r
68 t.isResizing=false; // resize var
\r
70 // init with settings and ID (area_id is a global var defined by editAreaLoader on iframe creation
\r
72 t.settings= editAreas[t.id]["settings"];
\r
74 if((""+t.settings['replace_tab_by_spaces']).match(/^[0-9]+$/))
\r
76 t.tab_nb_char= t.settings['replace_tab_by_spaces'];
\r
78 for(var i=0; i<t.tab_nb_char; i++)
\r
84 // retrieve the init parameter for syntax
\r
85 if(t.settings["syntax_selection_allow"] && t.settings["syntax_selection_allow"].length>0)
\r
86 t.syntax_list= t.settings["syntax_selection_allow"].replace(/ /g,"").split(",");
\r
88 if(t.settings['syntax'])
\r
89 t.allready_used_syntax[t.settings['syntax']]=true;
\r
93 EditArea.prototype.init= function(){
\r
94 var t=this, a, s=t.settings;
\r
95 t.textarea = _$("textarea");
\r
96 t.container = _$("container");
\r
97 t.result = _$("result");
\r
98 t.content_highlight = _$("content_highlight");
\r
99 t.selection_field = _$("selection_field");
\r
100 t.selection_field_text= _$("selection_field_text");
\r
101 t.processing_screen = _$("processing");
\r
102 t.editor_area = _$("editor");
\r
103 t.tab_browsing_area = _$("tab_browsing_area");
\r
104 t.test_font_size = _$("test_font_size");
\r
107 if(!s['is_editable'])
\r
108 t.set_editable(false);
\r
110 t.set_show_line_colors( s['show_line_colors'] );
\r
112 if(syntax_selec= _$("syntax_selection"))
\r
114 // set up syntax selection lsit in the toolbar
\r
115 for(var i=0; i<t.syntax_list.length; i++) {
\r
116 var syntax= t.syntax_list[i];
\r
117 var option= document.createElement("option");
\r
118 option.value= syntax;
\r
119 if(syntax==s['syntax'])
\r
120 option.selected= "selected";
\r
121 option.innerHTML= t.get_translation("syntax_" + syntax, "word");
\r
122 syntax_selec.appendChild(option);
\r
126 // add plugins buttons in the toolbar
\r
127 spans= parent.getChildren(_$("toolbar_1"), "span", "", "", "all", -1);
\r
129 for(var i=0; i<spans.length; i++){
\r
131 id=spans[i].id.replace(/tmp_tool_(.*)/, "$1");
\r
132 if(id!= spans[i].id){
\r
133 for(var j in t.plugins){
\r
134 if(typeof(t.plugins[j].get_control_html)=="function" ){
\r
135 html=t.plugins[j].get_control_html(id);
\r
137 html= t.get_translation(html, "template");
\r
138 var new_span= document.createElement("span");
\r
139 new_span.innerHTML= html;
\r
140 var father= spans[i].parentNode;
\r
141 spans[i].parentNode.replaceChild(new_span, spans[i]);
\r
142 break; // exit the for loop
\r
150 //a.value = 'a';//editAreas[t.id]["textarea"].value;
\r
154 t.debug=parent.document.getElementById("edit_area_debug_"+t.id);
\r
157 //this.update_size();
\r
159 if(_$("redo") != null)
\r
160 t.switchClassSticky(_$("redo"), 'editAreaButtonDisabled', true);
\r
162 // insert css rules for highlight mode
\r
163 if(typeof(parent.editAreaLoader.syntax[s["syntax"]])!="undefined"){
\r
164 for(var i in parent.editAreaLoader.syntax){
\r
165 if (typeof(parent.editAreaLoader.syntax[i]["styles"]) != "undefined"){
\r
166 t.add_style(parent.editAreaLoader.syntax[i]["styles"]);
\r
173 _$("editor").onkeypress = keyDown;
\r
175 _$("editor").onkeydown = keyDown;
\r
177 for(var i=0; i<t.inlinePopup.length; i++){
\r
179 _$(t.inlinePopup[i]["popup_id"]).onkeypress = keyDown;
\r
181 _$(t.inlinePopup[i]["popup_id"]).onkeydown = keyDown;
\r
184 if(s["allow_resize"]=="both" || s["allow_resize"]=="x" || s["allow_resize"]=="y")
\r
185 t.allow_resize(true);
\r
187 parent.editAreaLoader.toggle(t.id, "on");
\r
189 // line selection init
\r
190 t.change_smooth_selection_mode(editArea.smooth_selection);
\r
192 t.execCommand("change_highlight", s["start_highlight"]);
\r
194 // get font size datas
\r
195 t.set_font(editArea.settings["font_family"], editArea.settings["font_size"]);
\r
197 // set unselectable text
\r
198 children= parent.getChildren(document.body, "", "selec", "none", "all", -1);
\r
199 for(var i=0; i<children.length; i++){
\r
201 children[i].unselectable = true; // IE
\r
203 children[i].onmousedown= function(){return false};
\r
204 /* children[i].style.MozUserSelect = "none"; // Moz
\r
205 children[i].style.KhtmlUserSelect = "none"; // Konqueror/Safari*/
\r
208 a.spellcheck= s["gecko_spellcheck"];
\r
210 /** Browser specific style fixes **/
\r
212 // fix rendering bug for highlighted lines beginning with no tabs
\r
213 if( t.isFirefox >= '3' ) {
\r
214 t.content_highlight.style.paddingLeft= "1px";
\r
215 t.selection_field.style.paddingLeft= "1px";
\r
216 t.selection_field_text.style.paddingLeft= "1px";
\r
219 if(t.isIE && t.isIE < 8 ){
\r
220 a.style.marginTop= "-1px";
\r
224 t.editor_area.style.position= "absolute";
\r
228 t.editor_area.style.position = "absolute";
\r
229 a.style.marginLeft ="-3px";
\r
230 if( t.isSafari < 3.2 ) // Safari 3.0 (3.1?)
\r
231 a.style.marginTop ="1px";
\r
234 // si le textarea n'est pas grand, un click sous le textarea doit provoquer un focus sur le textarea
\r
235 parent.editAreaLoader.add_event(t.result, "click", function(e){ if((e.target || e.srcElement)==editArea.result) { editArea.area_select(editArea.textarea.value.length, 0);} });
\r
237 if(s['is_multi_files']!=false)
\r
238 t.open_file({'id': t.curr_file, 'text': ''});
\r
240 t.set_word_wrap( s['word_wrap'] );
\r
242 setTimeout("editArea.focus();editArea.manage_size();editArea.execCommand('EA_load');", 10);
\r
243 //start checkup routine
\r
245 t.check_line_selection(true);
\r
246 t.scroll_to_view();
\r
248 for(var i in t.plugins){
\r
249 if(typeof(t.plugins[i].onload)=="function")
\r
250 t.plugins[i].onload();
\r
252 if(s['fullscreen']==true)
\r
253 t.toggle_full_screen(true);
\r
255 parent.editAreaLoader.add_event(window, "resize", editArea.update_size);
\r
256 parent.editAreaLoader.add_event(parent.window, "resize", editArea.update_size);
\r
257 parent.editAreaLoader.add_event(top.window, "resize", editArea.update_size);
\r
258 parent.editAreaLoader.add_event(window, "unload", function(){
\r
259 // in case where editAreaLoader have been already cleaned
\r
260 if( parent.editAreaLoader )
\r
262 parent.editAreaLoader.remove_event(parent.window, "resize", editArea.update_size);
\r
263 parent.editAreaLoader.remove_event(top.window, "resize", editArea.update_size);
\r
265 if(editAreas[editArea.id] && editAreas[editArea.id]["displayed"]){
\r
266 editArea.execCommand("EA_unload");
\r
271 /*date= new Date();
\r
272 alert(date.getTime()- parent.editAreaLoader.start_time);*/
\r
277 //called by the toggle_on
\r
278 EditArea.prototype.update_size= function(){
\r
279 var d=document,pd=parent.document,height,width,popup,maxLeft,maxTop;
\r
281 if( typeof editAreas != 'undefined' && editAreas[editArea.id] && editAreas[editArea.id]["displayed"]==true){
\r
282 if(editArea.fullscreen['isFull']){
\r
283 pd.getElementById("frame_"+editArea.id).style.width = pd.getElementsByTagName("html")[0].clientWidth + "px";
\r
284 pd.getElementById("frame_"+editArea.id).style.height = pd.getElementsByTagName("html")[0].clientHeight + "px";
\r
287 if(editArea.tab_browsing_area.style.display=='block' && ( !editArea.isIE || editArea.isIE >= 8 ) )
\r
289 editArea.tab_browsing_area.style.height = "0px";
\r
290 editArea.tab_browsing_area.style.height = (editArea.result.offsetTop - editArea.tab_browsing_area.offsetTop -1)+"px";
\r
293 height = d.body.offsetHeight - editArea.get_all_toolbar_height() - 4;
\r
294 editArea.result.style.height = height +"px";
\r
296 width = d.body.offsetWidth -2;
\r
297 editArea.result.style.width = width+"px";
\r
298 //alert("result h: "+ height+" w: "+width+"\ntoolbar h: "+this.get_all_toolbar_height()+"\nbody_h: "+document.body.offsetHeight);
\r
300 // check that the popups don't get out of the screen
\r
301 for( i=0; i < editArea.inlinePopup.length; i++ )
\r
303 popup = _$(editArea.inlinePopup[i]["popup_id"]);
\r
304 maxLeft = d.body.offsetWidth - popup.offsetWidth;
\r
305 maxTop = d.body.offsetHeight - popup.offsetHeight;
\r
306 if( popup.offsetTop > maxTop )
\r
307 popup.style.top = maxTop+"px";
\r
308 if( popup.offsetLeft > maxLeft )
\r
309 popup.style.left = maxLeft+"px";
\r
312 editArea.manage_size( true );
\r
313 editArea.fixLinesHeight( editArea.textarea.value, 0,-1);
\r
318 EditArea.prototype.manage_size= function(onlyOneTime){
\r
319 if(!editAreas[this.id])
\r
322 if(editAreas[this.id]["displayed"]==true && this.textareaFocused)
\r
324 var area_height,resized= false;
\r
326 //1) Manage display width
\r
327 //1.1) Calc the new width to use for display
\r
328 if( !this.settings['word_wrap'] )
\r
330 var area_width= this.textarea.scrollWidth;
\r
331 area_height= this.textarea.scrollHeight;
\r
332 // bug on old opera versions
\r
333 if(this.isOpera && this.isOpera < 9.6 ){
\r
336 //1.2) the width is not the same, we must resize elements
\r
337 if(this.textarea.previous_scrollWidth!=area_width)
\r
339 this.container.style.width= area_width+"px";
\r
340 this.textarea.style.width= area_width+"px";
\r
341 this.content_highlight.style.width= area_width+"px";
\r
342 this.textarea.previous_scrollWidth=area_width;
\r
346 // manage wrap width
\r
347 if( this.settings['word_wrap'] )
\r
349 newW=this.textarea.offsetWidth;
\r
350 if( this.isFirefox || this.isIE )
\r
352 if( this.isSafari )
\r
354 this.content_highlight.style.width=this.selection_field_text.style.width=this.selection_field.style.width=this.test_font_size.style.width=newW+"px";
\r
357 //2) Manage display height
\r
358 //2.1) Calc the new height to use for display
\r
359 if( this.isOpera || this.isFirefox || this.isSafari ) {
\r
360 area_height= this.getLinePosTop( this.last_selection["nb_line"] + 1 );
\r
362 area_height = this.textarea.scrollHeight;
\r
364 //2.2) the width is not the same, we must resize elements
\r
365 if(this.textarea.previous_scrollHeight!=area_height)
\r
367 this.container.style.height= (area_height+2)+"px";
\r
368 this.textarea.style.height= area_height+"px";
\r
369 this.content_highlight.style.height= area_height+"px";
\r
370 this.textarea.previous_scrollHeight= area_height;
\r
374 //3) if there is new lines, we add new line numbers in the line numeration area
\r
375 if(this.last_selection["nb_line"] >= this.line_number)
\r
377 var newLines= '', destDiv=_$("line_number"), start=this.line_number, end=this.last_selection["nb_line"]+100;
\r
378 for( i = start+1; i < end; i++ )
\r
380 newLines+='<div id="line_'+ i +'">'+i+"</div>";
\r
381 this.line_number++;
\r
383 destDiv.innerHTML= destDiv.innerHTML + newLines;
\r
385 this.fixLinesHeight( this.textarea.value, start, -1 );
\r
388 //4) be sure the text is well displayed
\r
389 this.textarea.scrollTop="0px";
\r
390 this.textarea.scrollLeft="0px";
\r
392 this.scroll_to_view();
\r
397 setTimeout("editArea.manage_size();", 100);
\r
400 EditArea.prototype.execCommand= function(cmd, param){
\r
402 for(var i in this.plugins){
\r
403 if(typeof(this.plugins[i].execCommand)=="function"){
\r
404 if(!this.plugins[i].execCommand(cmd, param))
\r
410 if(this.settings["save_callback"].length>0)
\r
411 eval("parent."+this.settings["save_callback"]+"('"+ this.id +"', editArea.textarea.value);");
\r
414 if(this.settings["load_callback"].length>0)
\r
415 eval("parent."+this.settings["load_callback"]+"('"+ this.id +"');");
\r
418 if(this.settings["change_callback"].length>0)
\r
419 eval("parent."+this.settings["change_callback"]+"('"+ this.id +"');");
\r
422 if(this.settings["EA_load_callback"].length>0)
\r
423 eval("parent."+this.settings["EA_load_callback"]+"('"+ this.id +"');");
\r
426 if(this.settings["EA_unload_callback"].length>0)
\r
427 eval("parent."+this.settings["EA_unload_callback"]+"('"+ this.id +"');");
\r
430 if(this.settings["EA_toggle_on_callback"].length>0)
\r
431 eval("parent."+this.settings["EA_toggle_on_callback"]+"('"+ this.id +"');");
\r
434 if(this.settings["EA_toggle_off_callback"].length>0)
\r
435 eval("parent."+this.settings["EA_toggle_off_callback"]+"('"+ this.id +"');");
\r
438 if(!this.do_highlight)
\r
440 case "file_switch_on":
\r
441 if(this.settings["EA_file_switch_on_callback"].length>0)
\r
442 eval("parent."+this.settings["EA_file_switch_on_callback"]+"(param);");
\r
444 case "file_switch_off":
\r
445 if(this.settings["EA_file_switch_off_callback"].length>0)
\r
446 eval("parent."+this.settings["EA_file_switch_off_callback"]+"(param);");
\r
449 if(this.settings["EA_file_close_callback"].length>0)
\r
450 return eval("parent."+this.settings["EA_file_close_callback"]+"(param);");
\r
454 if(typeof(eval("editArea."+cmd))=="function")
\r
456 if(this.settings["debug"])
\r
457 eval("editArea."+ cmd +"(param);");
\r
459 try{eval("editArea."+ cmd +"(param);");}catch(e){};
\r
464 EditArea.prototype.get_translation= function(word, mode){
\r
465 if(mode=="template")
\r
466 return parent.editAreaLoader.translate(word, this.settings["language"], mode);
\r
468 return parent.editAreaLoader.get_word_translation(word, this.settings["language"]);
\r
471 EditArea.prototype.add_plugin= function(plug_name, plug_obj){
\r
472 for(var i=0; i<this.settings["plugins"].length; i++){
\r
473 if(this.settings["plugins"][i]==plug_name){
\r
474 this.plugins[plug_name]=plug_obj;
\r
475 plug_obj.baseURL=parent.editAreaLoader.baseURL + "plugins/" + plug_name + "/";
\r
476 if( typeof(plug_obj.init)=="function" )
\r
482 EditArea.prototype.load_css= function(url){
\r
484 link = document.createElement("link");
\r
485 link.type = "text/css";
\r
486 link.rel= "stylesheet";
\r
489 head = document.getElementsByTagName("head");
\r
490 head[0].appendChild(link);
\r
492 document.write("<link href='"+ url +"' rel='stylesheet' type='text/css' />");
\r
496 EditArea.prototype.load_script= function(url){
\r
498 script = document.createElement("script");
\r
499 script.type = "text/javascript";
\r
501 script.charset= "UTF-8";
\r
502 head = document.getElementsByTagName("head");
\r
503 head[0].appendChild(script);
\r
505 document.write("<script type='text/javascript' src='" + url + "' charset=\"UTF-8\"><"+"/script>");
\r
509 // add plugin translation to language translation array
\r
510 EditArea.prototype.add_lang= function(language, values){
\r
511 if(!parent.editAreaLoader.lang[language])
\r
512 parent.editAreaLoader.lang[language]={};
\r
513 for(var i in values)
\r
514 parent.editAreaLoader.lang[language][i]= values[i];
\r
517 // short cut for document.getElementById()
\r
518 function _$(id){return document.getElementById( id );};
\r
520 var editArea = new EditArea();
\r
521 parent.editAreaLoader.add_event(window, "load", init);
\r
524 setTimeout("editArea.init(); ", 10);
\r