1 //replace tabulation by the good number of white spaces
\r
2 EditArea.prototype.replace_tab= function(text){
\r
3 return text.replace(/((\n?)([^\t\n]*)\t)/gi, editArea.smartTab); // slower than simple replace...
\r
6 // call by the replace_tab function
\r
7 EditArea.prototype.smartTab= function(){
\r
9 return EditArea.prototype.smartTab.arguments[2] + EditArea.prototype.smartTab.arguments[3] + val.substr(0, editArea.tab_nb_char - (EditArea.prototype.smartTab.arguments[3].length)%editArea.tab_nb_char);
\r
12 EditArea.prototype.show_waiting_screen= function(){
\r
13 width = this.editor_area.offsetWidth;
\r
14 height = this.editor_area.offsetHeight;
\r
15 if( !(this.isIE && this.isIE<6) )
\r
20 this.processing_screen.style.display= "block";
\r
21 this.processing_screen.style.width = width+"px";
\r
22 this.processing_screen.style.height = height+"px";
\r
23 this.waiting_screen_displayed = true;
\r
26 EditArea.prototype.hide_waiting_screen= function(){
\r
27 this.processing_screen.style.display="none";
\r
28 this.waiting_screen_displayed= false;
\r
31 EditArea.prototype.add_style= function(styles){
\r
32 if(styles.length>0){
\r
33 newcss = document.createElement("style");
\r
34 newcss.type="text/css";
\r
36 if(newcss.styleSheet){ // IE
\r
37 newcss.styleSheet.cssText = styles;
\r
39 newcss.appendChild(document.createTextNode(styles));
\r
41 document.getElementsByTagName("head")[0].appendChild(newcss);
\r
45 EditArea.prototype.set_font= function(family, size){
\r
46 var t=this, a=this.textarea, s=this.settings, elem_font, i, elem;
\r
47 // list all elements concerned by font changes
\r
48 var elems= ["textarea", "content_highlight", "cursor_pos", "end_bracket", "selection_field", "selection_field_text", "line_number"];
\r
50 if(family && family!="")
\r
51 s["font_family"]= family;
\r
53 s["font_size"] = size;
\r
54 if( t.isOpera && t.isOpera < 9.6 ) // opera<9.6 can't manage non monospace font
\r
55 s['font_family']="monospace";
\r
57 // update the select tag
\r
58 if( elem_font = _$("area_font_size") )
\r
60 for( i = 0; i < elem_font.length; i++ )
\r
62 if( elem_font.options[i].value && elem_font.options[i].value == s["font_size"] )
\r
63 elem_font.options[i].selected=true;
\r
68 * somethimes firefox has rendering mistake with non-monospace font for text width in textarea vs in div for changing font size (eg: verdana change between 11pt to 12pt)
\r
69 * => looks like a browser internal random bug as text width can change while content_highlight is updated
\r
70 * we'll check if the font-size produce the same text width inside textarea and div and if not, we'll increment the font-size
\r
72 * This is an ugly fix
\r
78 var div1 = document.createElement( 'div' ), text1 = document.createElement( 'textarea' );
\r
83 visibility: 'hidden',
\r
84 fontFamily: s["font_family"],
\r
85 fontSize: s["font_size"]+"pt",
\r
86 lineHeight: t.lineHeight+"px",
\r
90 whiteSpace: 'nowrap'
\r
92 var diff, changed = false;
\r
95 div1.style[ i ] = styles[i];
\r
96 text1.style[ i ] = styles[i];
\r
98 // no wrap for this text
\r
100 text1.setAttribute('wrap', 'off');
\r
101 t.container.appendChild( div1 );
\r
102 t.container.appendChild( text1 );
\r
103 // try to make FF to bug
\r
104 div1.innerHTML = text1.value = 'azertyuiopqsdfghjklm';
\r
105 div1.innerHTML = text1.value = text1.value+'wxcvbn^p*รน$!:;,,';
\r
106 diff = text1.scrollWidth - div1.scrollWidth;
108 // firefox return here a diff of 1 px between equals scrollWidth (can't explain)
\r
109 if( Math.abs( diff ) >= 2 )
\r
114 t.container.removeChild( div1 );
\r
115 t.container.removeChild( text1 );
\r
117 }while( changed && nbTry > 0 );
\r
121 // calc line height
\r
122 elem = t.test_font_size;
\r
123 elem.style.fontFamily = ""+s["font_family"];
\r
124 elem.style.fontSize = s["font_size"]+"pt";
\r
125 elem.innerHTML = "0";
\r
126 t.lineHeight = elem.offsetHeight;
\r
128 // update font for all concerned elements
\r
129 for( i=0; i<elems.length; i++)
\r
131 elem = _$(elems[i]);
\r
132 elem.style.fontFamily = s["font_family"];
\r
133 elem.style.fontSize = s["font_size"]+"pt";
\r
134 elem.style.lineHeight = t.lineHeight+"px";
\r
136 // define a css for <pre> tags
\r
137 t.add_style("pre{font-family:"+s["font_family"]+"}");
\r
139 // old opera and IE>=8 doesn't update font changes to the textarea
\r
140 if( ( t.isOpera && t.isOpera < 9.6 ) || t.isIE >= 8 )
\r
142 var parNod = a.parentNode, nxtSib = a.nextSibling, start= a.selectionStart, end= a.selectionEnd;
\r
143 parNod.removeChild(a);
\r
144 parNod.insertBefore(a, nxtSib);
\r
145 t.area_select(start, end-start);
\r
148 // force update of selection field
\r
150 this.update_size();
\r
151 this.check_line_selection();
\r
154 EditArea.prototype.change_font_size= function(){
\r
155 var size=_$("area_font_size").value;
\r
157 this.set_font("", size);
\r
161 EditArea.prototype.open_inline_popup= function(popup_id){
\r
162 this.close_all_inline_popup();
\r
163 var popup= _$(popup_id);
\r
164 var editor= _$("editor");
\r
166 // search matching icon
\r
167 for(var i=0; i<this.inlinePopup.length; i++){
\r
168 if(this.inlinePopup[i]["popup_id"]==popup_id){
\r
169 var icon= _$(this.inlinePopup[i]["icon_id"]);
\r
171 this.switchClassSticky(icon, 'editAreaButtonSelected', true);
\r
177 popup.style.height="auto";
\r
178 popup.style.overflow= "visible";
\r
180 if(document.body.offsetHeight< popup.offsetHeight){
\r
181 popup.style.height= (document.body.offsetHeight-10)+"px";
\r
182 popup.style.overflow= "auto";
\r
185 if(!popup.positionned){
\r
186 var new_left= editor.offsetWidth /2 - popup.offsetWidth /2;
\r
187 var new_top= editor.offsetHeight /2 - popup.offsetHeight /2;
\r
188 //var new_top= area.offsetHeight /2 - popup.offsetHeight /2;
\r
189 //var new_left= area.offsetWidth /2 - popup.offsetWidth /2;
\r
190 //alert("new_top: ("+new_top+") = calculeOffsetTop(area) ("+calculeOffsetTop(area)+") + area.offsetHeight /2("+ area.offsetHeight /2+") - popup.offsetHeight /2("+popup.offsetHeight /2+") - scrollTop: "+document.body.scrollTop);
\r
191 popup.style.left= new_left+"px";
\r
192 popup.style.top= new_top+"px";
\r
193 popup.positionned=true;
\r
195 popup.style.visibility="visible";
\r
197 //popup.style.display="block";
\r
200 EditArea.prototype.close_inline_popup= function(popup_id){
\r
201 var popup= _$(popup_id);
\r
202 // search matching icon
\r
203 for(var i=0; i<this.inlinePopup.length; i++){
\r
204 if(this.inlinePopup[i]["popup_id"]==popup_id){
\r
205 var icon= _$(this.inlinePopup[i]["icon_id"]);
\r
207 this.switchClassSticky(icon, 'editAreaButtonNormal', false);
\r
213 popup.style.visibility="hidden";
\r
216 EditArea.prototype.close_all_inline_popup= function(e){
\r
217 for(var i=0; i<this.inlinePopup.length; i++){
\r
218 this.close_inline_popup(this.inlinePopup[i]["popup_id"]);
\r
220 this.textarea.focus();
\r
223 EditArea.prototype.show_help= function(){
\r
225 this.open_inline_popup("edit_area_help");
\r
229 EditArea.prototype.new_document= function(){
\r
230 this.textarea.value="";
\r
231 this.area_select(0,0);
\r
234 EditArea.prototype.get_all_toolbar_height= function(){
\r
235 var area= _$("editor");
\r
236 var results= parent.getChildren(area, "div", "class", "area_toolbar", "all", "0"); // search only direct children
\r
237 //results= results.concat(getChildren(area, "table", "class", "area_toolbar", "all", "0"));
\r
239 for(var i=0; i<results.length; i++){
\r
240 height+= results[i].offsetHeight;
\r
242 //alert("toolbar height: "+height);
\r
246 EditArea.prototype.go_to_line= function(line){
\r
249 var icon= _$("go_to_line");
\r
251 this.restoreClass(icon);
\r
252 this.switchClassSticky(icon, 'editAreaButtonSelected', true);
\r
255 line= prompt(this.get_translation("go_to_line_prompt"));
\r
257 this.switchClassSticky(icon, 'editAreaButtonNormal', false);
\r
259 if(line && line!=null && line.search(/^[0-9]+$/)!=-1){
\r
261 var lines= this.textarea.value.split("\n");
\r
262 if(line > lines.length)
\r
263 start= this.textarea.value.length;
\r
265 for(var i=0; i<Math.min(line-1, lines.length); i++)
\r
266 start+= lines[i].length + 1;
\r
268 this.area_select(start, 0);
\r
275 EditArea.prototype.change_smooth_selection_mode= function(setTo){
\r
276 //alert("setTo: "+setTo);
\r
277 if(this.do_highlight)
\r
281 if(setTo === false)
\r
282 this.smooth_selection=true;
\r
284 this.smooth_selection=false;
\r
286 var icon= _$("change_smooth_selection");
\r
287 this.textarea.focus();
\r
288 if(this.smooth_selection===true){
\r
289 //setAttribute(icon, "class", getAttribute(icon, "class").replace(/ selected/g, "") );
\r
290 /*setAttribute(icon, "oldClassName", "editAreaButtonNormal" );
\r
291 setAttribute(icon, "className", "editAreaButtonNormal" );*/
\r
292 //this.restoreClass(icon);
\r
293 //this.restoreAndSwitchClass(icon,'editAreaButtonNormal');
\r
294 this.switchClassSticky(icon, 'editAreaButtonNormal', false);
\r
296 this.smooth_selection=false;
\r
297 this.selection_field.style.display= "none";
\r
298 _$("cursor_pos").style.display= "none";
\r
299 _$("end_bracket").style.display= "none";
\r
301 //setAttribute(icon, "class", getAttribute(icon, "class") + " selected");
\r
302 //this.switchClass(icon,'editAreaButtonSelected');
\r
303 this.switchClassSticky(icon, 'editAreaButtonSelected', false);
\r
304 this.smooth_selection=true;
\r
305 this.selection_field.style.display= "block";
\r
306 _$("cursor_pos").style.display= "block";
\r
307 _$("end_bracket").style.display= "block";
\r
311 // the auto scroll of the textarea has some lacks when it have to show cursor in the visible area when the textarea size change
\r
312 // show specifiy whereas it is the "top" or "bottom" of the selection that is showned
\r
313 EditArea.prototype.scroll_to_view= function(show){
\r
314 var zone, lineElem;
\r
315 if(!this.smooth_selection)
\r
317 zone= _$("result");
\r
319 // manage height scroll
\r
320 var cursor_pos_top= _$("cursor_pos").cursor_top;
\r
323 //cursor_pos_top+= (this.last_selection["line_nb"]-1)* this.lineHeight;
\r
324 cursor_pos_top+= this.getLinePosTop( this.last_selection['line_start'] + this.last_selection['line_nb'] - 1 );
\r
327 var max_height_visible= zone.clientHeight + zone.scrollTop;
\r
328 var miss_top = cursor_pos_top + this.lineHeight - max_height_visible;
\r
331 zone.scrollTop= zone.scrollTop + miss_top;
\r
332 }else if( zone.scrollTop > cursor_pos_top){
\r
333 // when erase all the content -> does'nt scroll back to the top
\r
334 //alert("else: "+cursor_pos_top);
\r
335 zone.scrollTop= cursor_pos_top;
\r
338 // manage left scroll
\r
339 //var cursor_pos_left= parseInt(_$("cursor_pos").style.left.replace("px",""));
\r
340 var cursor_pos_left= _$("cursor_pos").cursor_left;
\r
341 var max_width_visible= zone.clientWidth + zone.scrollLeft;
\r
342 var miss_left= cursor_pos_left + 10 - max_width_visible;
\r
344 zone.scrollLeft= zone.scrollLeft + miss_left + 50;
\r
345 }else if( zone.scrollLeft > cursor_pos_left){
\r
346 zone.scrollLeft= cursor_pos_left ;
\r
347 }else if( zone.scrollLeft == 45){
\r
348 // show the line numbers if textarea align to it's left
\r
353 EditArea.prototype.check_undo= function(only_once){
\r
354 if(!editAreas[this.id])
\r
356 if(this.textareaFocused && editAreas[this.id]["displayed"]==true){
\r
357 var text=this.textarea.value;
\r
358 if(this.previous.length<=1)
\r
359 this.switchClassSticky(_$("undo"), 'editAreaButtonDisabled', true);
\r
361 if(!this.previous[this.previous.length-1] || this.previous[this.previous.length-1]["text"] != text){
\r
362 this.previous.push({"text": text, "selStart": this.textarea.selectionStart, "selEnd": this.textarea.selectionEnd});
\r
363 if(this.previous.length > this.settings["max_undo"]+1)
\r
364 this.previous.shift();
\r
367 if(this.previous.length >= 2)
\r
368 this.switchClassSticky(_$("undo"), 'editAreaButtonNormal', false);
\r
372 setTimeout("editArea.check_undo()", 3000);
\r
375 EditArea.prototype.undo= function(){
\r
376 //alert("undo"+this.previous.length);
\r
377 if(this.previous.length > 0)
\r
379 this.getIESelection();
\r
380 // var pos_cursor=this.textarea.selectionStart;
\r
381 this.next.push( { "text": this.textarea.value, "selStart": this.textarea.selectionStart, "selEnd": this.textarea.selectionEnd } );
\r
382 var prev= this.previous.pop();
\r
383 if( prev["text"] == this.textarea.value && this.previous.length > 0 )
\r
384 prev =this.previous.pop();
\r
385 this.textarea.value = prev["text"];
\r
386 this.last_undo = prev["text"];
\r
387 this.area_select(prev["selStart"], prev["selEnd"]-prev["selStart"]);
\r
388 this.switchClassSticky(_$("redo"), 'editAreaButtonNormal', false);
\r
389 this.resync_highlight(true);
\r
390 //alert("undo"+this.previous.length);
\r
391 this.check_file_changes();
\r
395 EditArea.prototype.redo= function(){
\r
396 if(this.next.length > 0)
\r
398 /*this.getIESelection();*/
\r
399 //var pos_cursor=this.textarea.selectionStart;
\r
400 var next= this.next.pop();
\r
401 this.previous.push(next);
\r
402 this.textarea.value= next["text"];
\r
403 this.last_undo= next["text"];
\r
404 this.area_select(next["selStart"], next["selEnd"]-next["selStart"]);
\r
405 this.switchClassSticky(_$("undo"), 'editAreaButtonNormal', false);
\r
406 this.resync_highlight(true);
\r
407 this.check_file_changes();
\r
409 if( this.next.length == 0)
\r
410 this.switchClassSticky(_$("redo"), 'editAreaButtonDisabled', true);
\r
413 EditArea.prototype.check_redo= function(){
\r
414 if(editArea.next.length == 0 || editArea.textarea.value!=editArea.last_undo){
\r
415 editArea.next= []; // undo the ability to use "redo" button
\r
416 editArea.switchClassSticky(_$("redo"), 'editAreaButtonDisabled', true);
\r
420 this.switchClassSticky(_$("redo"), 'editAreaButtonNormal', false);
\r
425 // functions that manage icons roll over, disabled, etc...
\r
426 EditArea.prototype.switchClass = function(element, class_name, lock_state) {
\r
427 var lockChanged = false;
\r
429 if (typeof(lock_state) != "undefined" && element != null) {
\r
430 element.classLock = lock_state;
\r
431 lockChanged = true;
\r
434 if (element != null && (lockChanged || !element.classLock)) {
\r
435 element.oldClassName = element.className;
\r
436 element.className = class_name;
\r
440 EditArea.prototype.restoreAndSwitchClass = function(element, class_name) {
\r
441 if (element != null && !element.classLock) {
\r
442 this.restoreClass(element);
\r
443 this.switchClass(element, class_name);
\r
447 EditArea.prototype.restoreClass = function(element) {
\r
448 if (element != null && element.oldClassName && !element.classLock) {
\r
449 element.className = element.oldClassName;
\r
450 element.oldClassName = null;
\r
454 EditArea.prototype.setClassLock = function(element, lock_state) {
\r
455 if (element != null)
\r
456 element.classLock = lock_state;
\r
459 EditArea.prototype.switchClassSticky = function(element, class_name, lock_state) {
\r
460 var lockChanged = false;
\r
461 if (typeof(lock_state) != "undefined" && element != null) {
\r
462 element.classLock = lock_state;
\r
463 lockChanged = true;
\r
466 if (element != null && (lockChanged || !element.classLock)) {
\r
467 element.className = class_name;
\r
468 element.oldClassName = class_name;
\r
472 //make the "page up" and "page down" buttons works correctly
\r
473 EditArea.prototype.scroll_page= function(params){
\r
474 var dir= params["dir"], shift_pressed= params["shift"];
\r
475 var lines= this.textarea.value.split("\n");
\r
476 var new_pos=0, length=0, char_left=0, line_nb=0, curLine=0;
\r
477 var toScrollAmount = _$("result").clientHeight -30;
\r
478 var nbLineToScroll = 0, diff= 0;
\r
481 nbLineToScroll = Math.ceil( toScrollAmount / this.lineHeight );
\r
483 // fix number of line to scroll
\r
484 for( i = this.last_selection["line_start"]; i - diff > this.last_selection["line_start"] - nbLineToScroll ; i-- )
\r
486 if( elem = _$('line_'+ i) )
\r
488 diff += Math.floor( ( elem.offsetHeight - 1 ) / this.lineHeight );
\r
491 nbLineToScroll -= diff;
\r
493 if(this.last_selection["selec_direction"]=="up"){
\r
494 for(line_nb=0; line_nb< Math.min(this.last_selection["line_start"]-nbLineToScroll, lines.length); line_nb++){
\r
495 new_pos+= lines[line_nb].length + 1;
\r
497 char_left=Math.min(lines[Math.min(lines.length-1, line_nb)].length, this.last_selection["curr_pos"]-1);
\r
499 length=this.last_selection["selectionEnd"]-new_pos-char_left;
\r
500 this.area_select(new_pos+char_left, length);
\r
504 for(line_nb=0; line_nb< Math.min(this.last_selection["line_start"]+this.last_selection["line_nb"]-1-nbLineToScroll, lines.length); line_nb++){
\r
505 new_pos+= lines[line_nb].length + 1;
\r
507 char_left=Math.min(lines[Math.min(lines.length-1, line_nb)].length, this.last_selection["curr_pos"]-1);
\r
509 //length=this.last_selection["selectionEnd"]-new_pos-char_left;
\r
510 start= Math.min(this.last_selection["selectionStart"], new_pos+char_left);
\r
511 length= Math.max(new_pos+char_left, this.last_selection["selectionStart"] )- start ;
\r
512 if(new_pos+char_left < this.last_selection["selectionStart"])
\r
515 start=new_pos+char_left;
\r
516 this.area_select(start, length);
\r
522 var nbLineToScroll= Math.floor( toScrollAmount / this.lineHeight );
\r
523 // fix number of line to scroll
\r
524 for( i = this.last_selection["line_start"]; i + diff < this.last_selection["line_start"] + nbLineToScroll ; i++ )
\r
526 if( elem = _$('line_'+ i) )
\r
528 diff += Math.floor( ( elem.offsetHeight - 1 ) / this.lineHeight );
\r
531 nbLineToScroll -= diff;
\r
533 if(this.last_selection["selec_direction"]=="down"){
\r
535 for(line_nb=0; line_nb< Math.min(this.last_selection["line_start"]+this.last_selection["line_nb"]-2+nbLineToScroll, lines.length); line_nb++){
\r
536 if(line_nb==this.last_selection["line_start"]-1)
\r
537 char_left= this.last_selection["selectionStart"] -new_pos;
\r
538 new_pos+= lines[line_nb].length + 1;
\r
542 length=Math.abs(this.last_selection["selectionStart"]-new_pos);
\r
543 length+=Math.min(lines[Math.min(lines.length-1, line_nb)].length, this.last_selection["curr_pos"]);
\r
544 //length+=Math.min(lines[Math.min(lines.length-1, line_nb)].length, char_left);
\r
545 this.area_select(Math.min(this.last_selection["selectionStart"], new_pos), length);
\r
547 this.area_select(new_pos+char_left, 0);
\r
552 for(line_nb=0; line_nb< Math.min(this.last_selection["line_start"]+nbLineToScroll-1, lines.length, lines.length); line_nb++){
\r
553 if(line_nb==this.last_selection["line_start"]-1)
\r
554 char_left= this.last_selection["selectionStart"] -new_pos;
\r
555 new_pos+= lines[line_nb].length + 1;
\r
558 length=Math.abs(this.last_selection["selectionEnd"]-new_pos-char_left);
\r
559 length+=Math.min(lines[Math.min(lines.length-1, line_nb)].length, this.last_selection["curr_pos"])- char_left-1;
\r
560 //length+=Math.min(lines[Math.min(lines.length-1, line_nb)].length, char_left);
\r
561 this.area_select(Math.min(this.last_selection["selectionEnd"], new_pos+char_left), length);
\r
562 if(new_pos+char_left > this.last_selection["selectionEnd"])
\r
565 this.area_select(new_pos+char_left, 0);
\r
570 //console.log( new_pos, char_left, length, nbLineToScroll, toScrollAmount, _$("result").clientHeigh );
\r
571 this.check_line_selection();
\r
572 this.scroll_to_view(view);
\r
575 EditArea.prototype.start_resize= function(e){
\r
576 parent.editAreaLoader.resize["id"] = editArea.id;
\r
577 parent.editAreaLoader.resize["start_x"] = (e)? e.pageX : event.x + document.body.scrollLeft;
\r
578 parent.editAreaLoader.resize["start_y"] = (e)? e.pageY : event.y + document.body.scrollTop;
\r
581 editArea.textarea.focus();
\r
582 editArea.getIESelection();
\r
584 parent.editAreaLoader.resize["selectionStart"] = editArea.textarea.selectionStart;
\r
585 parent.editAreaLoader.resize["selectionEnd"] = editArea.textarea.selectionEnd;
\r
586 parent.editAreaLoader.start_resize_area();
\r
589 EditArea.prototype.toggle_full_screen= function(to){
\r
590 var t=this, p=parent, a=t.textarea, html, frame, selStart, selEnd, old, icon;
\r
591 if(typeof(to)=="undefined")
\r
592 to= !t.fullscreen['isFull'];
\r
593 old = t.fullscreen['isFull'];
\r
594 t.fullscreen['isFull']= to;
\r
595 icon = _$("fullscreen");
\r
596 selStart = t.textarea.selectionStart;
\r
597 selEnd = t.textarea.selectionEnd;
\r
598 html = p.document.getElementsByTagName("html")[0];
\r
599 frame = p.document.getElementById("frame_"+t.id);
\r
602 { // toogle on fullscreen
\r
604 t.fullscreen['old_overflow'] = p.get_css_property(html, "overflow");
\r
605 t.fullscreen['old_height'] = p.get_css_property(html, "height");
\r
606 t.fullscreen['old_width'] = p.get_css_property(html, "width");
\r
607 t.fullscreen['old_scrollTop'] = html.scrollTop;
\r
608 t.fullscreen['old_scrollLeft'] = html.scrollLeft;
\r
609 t.fullscreen['old_zIndex'] = p.get_css_property(frame, "z-index");
\r
611 html.style.height = "100%";
\r
612 html.style.width = "100%";
\r
614 html.style.overflow = "hidden";
\r
615 html.scrollTop = 0;
\r
616 html.scrollLeft = 0;
\r
618 frame.style.position = "absolute";
\r
619 frame.style.width = html.clientWidth+"px";
\r
620 frame.style.height = html.clientHeight+"px";
\r
621 frame.style.display = "block";
\r
622 frame.style.zIndex = "999999";
\r
623 frame.style.top = "0px";
\r
624 frame.style.left = "0px";
\r
626 // if the iframe was in a div with position absolute, the top and left are the one of the div,
\r
627 // so I fix it by seeing at witch position the iframe start and correcting it
\r
628 frame.style.top = "-"+p.calculeOffsetTop(frame)+"px";
\r
629 frame.style.left = "-"+p.calculeOffsetLeft(frame)+"px";
\r
631 // parent.editAreaLoader.execCommand(t.id, "update_size();");
\r
632 // var body=parent.document.getElementsByTagName("body")[0];
\r
633 // body.appendChild(frame);
\r
635 t.switchClassSticky(icon, 'editAreaButtonSelected', false);
\r
636 t.fullscreen['allow_resize']= t.resize_allowed;
\r
637 t.allow_resize(false);
\r
639 //t.area_select(selStart, selEnd-selStart);
\r
642 // opera can't manage to do a direct size update
\r
644 p.editAreaLoader.execCommand(t.id, "update_size();");
\r
645 t.area_select(selStart, selEnd-selStart);
\r
646 t.scroll_to_view();
\r
649 setTimeout("p.editAreaLoader.execCommand('"+ t.id +"', 'update_size();');editArea.focus();", 10);
\r
655 { // toogle off fullscreen
\r
656 frame.style.position="static";
\r
657 frame.style.zIndex= t.fullscreen['old_zIndex'];
\r
661 html.style.height = "auto";
\r
662 html.style.width = "auto";
\r
663 html.style.overflow = "auto";
\r
665 else if(t.isIE && p!=top)
\r
666 { // IE doesn't manage html overflow in frames like in normal page...
\r
667 html.style.overflow = "auto";
\r
671 html.style.overflow = t.fullscreen['old_overflow'];
\r
673 html.scrollTop = t.fullscreen['old_scrollTop'];
\r
674 html.scrollLeft = t.fullscreen['old_scrollLeft'];
\r
676 p.editAreaLoader.hide(t.id);
\r
677 p.editAreaLoader.show(t.id);
\r
679 t.switchClassSticky(icon, 'editAreaButtonNormal', false);
\r
680 if(t.fullscreen['allow_resize'])
\r
681 t.allow_resize(t.fullscreen['allow_resize']);
\r
683 t.area_select(selStart, selEnd-selStart);
\r
684 setTimeout("editArea.scroll_to_view();", 10);
\r
687 //p.editAreaLoader.remove_event(p.window, "resize", editArea.update_size);
\r
692 EditArea.prototype.allow_resize= function(allow){
\r
693 var resize= _$("resize_area");
\r
696 resize.style.visibility="visible";
\r
697 parent.editAreaLoader.add_event(resize, "mouseup", editArea.start_resize);
\r
699 resize.style.visibility="hidden";
\r
700 parent.editAreaLoader.remove_event(resize, "mouseup", editArea.start_resize);
\r
702 this.resize_allowed= allow;
\r
706 EditArea.prototype.change_syntax= function(new_syntax, is_waiting){
\r
707 // alert("cahnge to "+new_syntax);
\r
708 // the syntax is the same
\r
709 if(new_syntax==this.settings['syntax'])
\r
712 // check that the syntax is one allowed
\r
713 var founded= false;
\r
714 for(var i=0; i<this.syntax_list.length; i++)
\r
716 if(this.syntax_list[i]==new_syntax)
\r
722 // the reg syntax file is not loaded
\r
723 if(!parent.editAreaLoader.load_syntax[new_syntax])
\r
725 // load the syntax file and wait for file loading
\r
727 parent.editAreaLoader.load_script(parent.editAreaLoader.baseURL + "reg_syntax/" + new_syntax + ".js");
\r
728 setTimeout("editArea.change_syntax('"+ new_syntax +"', true);", 100);
\r
729 this.show_waiting_screen();
\r
733 if(!this.allready_used_syntax[new_syntax])
\r
734 { // the syntax has still not been used
\r
735 // rebuild syntax definition for new languages
\r
736 parent.editAreaLoader.init_syntax_regexp();
\r
737 // add style to the new list
\r
738 this.add_style(parent.editAreaLoader.syntax[new_syntax]["styles"]);
\r
739 this.allready_used_syntax[new_syntax]=true;
\r
741 // be sure that the select option is correctly updated
\r
742 var sel= _$("syntax_selection");
\r
743 if(sel && sel.value!=new_syntax)
\r
745 for(var i=0; i<sel.length; i++){
\r
746 if(sel.options[i].value && sel.options[i].value == new_syntax)
\r
747 sel.options[i].selected=true;
\r
751 /* if(this.settings['syntax'].length==0)
\r
753 this.switchClassSticky(_$("highlight"), 'editAreaButtonNormal', false);
\r
754 this.switchClassSticky(_$("reset_highlight"), 'editAreaButtonNormal', false);
\r
755 this.change_highlight(true);
\r
758 this.settings['syntax']= new_syntax;
\r
759 this.resync_highlight(true);
\r
760 this.hide_waiting_screen();
\r
768 // check if the file has changed
\r
769 EditArea.prototype.set_editable= function(is_editable){
\r
772 document.body.className= "";
\r
773 this.textarea.readOnly= false;
\r
774 this.is_editable= true;
\r
778 document.body.className= "non_editable";
\r
779 this.textarea.readOnly= true;
\r
780 this.is_editable= false;
\r
783 if(editAreas[this.id]["displayed"]==true)
\r
784 this.update_size();
\r
787 /***** Wrap mode *****/
\r
789 // toggling function for set_wrap_mode
\r
790 EditArea.prototype.toggle_word_wrap= function(){
\r
791 this.set_word_wrap( !this.settings['word_wrap'] );
\r
795 // open a new tab for the given file
\r
796 EditArea.prototype.set_word_wrap= function(to){
\r
797 var t=this, a= t.textarea;
\r
801 this.settings['word_wrap']= false;
\r
802 t.switchClassSticky( _$("word_wrap"), 'editAreaButtonDisabled', true );
\r
808 wrap_mode = 'soft';
\r
809 this.container.className+= ' word_wrap';
\r
810 this.container.style.width="";
\r
811 this.content_highlight.style.width="";
\r
812 a.style.width="100%";
\r
813 if( t.isIE && t.isIE < 7 ) // IE 6 count 50 px too much
\r
815 a.style.width = ( a.offsetWidth-5 )+"px";
\r
818 t.switchClassSticky( _$("word_wrap"), 'editAreaButtonSelected', false );
\r
823 this.container.className = this.container.className.replace(/word_wrap/g, '');
\r
824 t.switchClassSticky( _$("word_wrap"), 'editAreaButtonNormal', true );
\r
826 this.textarea.previous_scrollWidth = '';
\r
827 this.textarea.previous_scrollHeight = '';
\r
830 a.setAttribute('wrap', wrap_mode);
\r
831 // only IE can change wrap mode on the fly without element reloading
\r
834 var start=a.selectionStart, end= a.selectionEnd;
\r
835 var parNod = a.parentNode, nxtSib = a.nextSibling;
\r
836 parNod.removeChild(a);
\r
837 parNod.insertBefore(a, nxtSib);
\r
838 this.area_select(start, end-start);
\r
840 // reset some optimisation
\r
841 this.settings['word_wrap'] = to;
\r
843 this.update_size();
\r
844 this.check_line_selection();
\r
846 /***** tabbed files managing functions *****/
\r
848 // open a new tab for the given file
\r
849 EditArea.prototype.open_file= function(settings){
\r
851 if(settings['id']!="undefined")
\r
853 var id= settings['id'];
\r
854 // create a new file object with defautl values
\r
856 new_file['id'] = id;
\r
857 new_file['title'] = id;
\r
858 new_file['text'] = "";
\r
859 new_file['last_selection'] = "";
\r
860 new_file['last_text_to_highlight'] = "";
\r
861 new_file['last_hightlighted_text'] = "";
\r
862 new_file['previous'] = [];
\r
863 new_file['next'] = [];
\r
864 new_file['last_undo'] = "";
\r
865 new_file['smooth_selection'] = this.settings['smooth_selection'];
\r
866 new_file['do_highlight']= this.settings['start_highlight'];
\r
867 new_file['syntax'] = this.settings['syntax'];
\r
868 new_file['scroll_top'] = 0;
\r
869 new_file['scroll_left'] = 0;
\r
870 new_file['selection_start']= 0;
\r
871 new_file['selection_end']= 0;
\r
872 new_file['edited'] = false;
\r
873 new_file['font_size'] = this.settings["font_size"];
\r
874 new_file['font_family'] = this.settings["font_family"];
\r
875 new_file['word_wrap'] = this.settings["word_wrap"];
\r
876 new_file['toolbar'] = {'links':{}, 'selects': {}};
\r
877 new_file['compare_edited_text']= new_file['text'];
\r
880 this.files[id]= new_file;
\r
881 this.update_file(id, settings);
\r
882 this.files[id]['compare_edited_text']= this.files[id]['text'];
\r
885 var html_id= 'tab_file_'+encodeURIComponent(id);
\r
886 this.filesIdAssoc[html_id]= id;
\r
887 this.files[id]['html_id']= html_id;
\r
889 if(!_$(this.files[id]['html_id']) && id!="")
\r
891 // be sure the tab browsing area is displayed
\r
892 this.tab_browsing_area.style.display= "block";
\r
893 var elem= document.createElement('li');
\r
894 elem.id= this.files[id]['html_id'];
\r
895 var close= "<img src=\""+ parent.editAreaLoader.baseURL +"images/close.gif\" title=\""+ this.get_translation('close_tab', 'word') +"\" onclick=\"editArea.execCommand('close_file', editArea.filesIdAssoc['"+ html_id +"']);return false;\" class=\"hidden\" onmouseover=\"this.className=''\" onmouseout=\"this.className='hidden'\" />";
\r
896 elem.innerHTML= "<a onclick=\"javascript:editArea.execCommand('switch_to_file', editArea.filesIdAssoc['"+ html_id +"']);\" selec=\"none\"><b><span><strong class=\"edited\">*</strong>"+ this.files[id]['title'] + close +"</span></b></a>";
\r
897 _$('tab_browsing_list').appendChild(elem);
\r
898 var elem= document.createElement('text');
\r
899 this.update_size();
\r
902 // open file callback (for plugin)
\r
904 this.execCommand('file_open', this.files[id]);
\r
906 this.switch_to_file(id, true);
\r
913 // close the given file
\r
914 EditArea.prototype.close_file= function(id){
\r
917 this.save_file(id);
\r
919 // close file callback
\r
920 if(this.execCommand('file_close', this.files[id])!==false)
\r
922 // remove the tab in the toolbar
\r
923 var li= _$(this.files[id]['html_id']);
\r
924 li.parentNode.removeChild(li);
\r
925 // select a new file
\r
926 if(id== this.curr_file)
\r
929 var is_next= false;
\r
930 for(var i in this.files)
\r
942 // display the next file
\r
943 this.switch_to_file(next_file);
\r
946 delete (this.files[id]);
\r
947 this.update_size();
\r
952 // backup current file datas
\r
953 EditArea.prototype.save_file= function(id){
\r
954 var t= this, save, a_links, a_selects, save_butt, img, i;
\r
957 var save= t.files[id];
\r
958 save['last_selection'] = t.last_selection;
\r
959 save['last_text_to_highlight'] = t.last_text_to_highlight;
\r
960 save['last_hightlighted_text'] = t.last_hightlighted_text;
\r
961 save['previous'] = t.previous;
\r
962 save['next'] = t.next;
\r
963 save['last_undo'] = t.last_undo;
\r
964 save['smooth_selection'] = t.smooth_selection;
\r
965 save['do_highlight'] = t.do_highlight;
\r
966 save['syntax'] = t.settings['syntax'];
\r
967 save['text'] = t.textarea.value;
\r
968 save['scroll_top'] = t.result.scrollTop;
\r
969 save['scroll_left'] = t.result.scrollLeft;
\r
970 save['selection_start'] = t.last_selection["selectionStart"];
\r
971 save['selection_end'] = t.last_selection["selectionEnd"];
\r
972 save['font_size'] = t.settings["font_size"];
\r
973 save['font_family'] = t.settings["font_family"];
\r
974 save['word_wrap'] = t.settings["word_wrap"];
\r
975 save['toolbar'] = {'links':{}, 'selects': {}};
\r
977 // save toolbar buttons state for fileSpecific buttons
\r
978 a_links= _$("toolbar_1").getElementsByTagName("a");
\r
979 for( i=0; i<a_links.length; i++ )
\r
981 if( a_links[i].getAttribute('fileSpecific') == 'yes' )
\r
984 img = a_links[i].getElementsByTagName('img')[0];
\r
985 save_butt['classLock'] = img.classLock;
\r
986 save_butt['className'] = img.className;
\r
987 save_butt['oldClassName'] = img.oldClassName;
\r
989 save['toolbar']['links'][a_links[i].id]= save_butt;
\r
993 // save toolbar select state for fileSpecific buttons
\r
994 a_selects= _$("toolbar_1").getElementsByTagName("select");
\r
995 for( i=0; i<a_selects.length; i++)
\r
997 if(a_selects[i].getAttribute('fileSpecific')=='yes')
\r
999 save['toolbar']['selects'][a_selects[i].id]= a_selects[i].value;
\r
1003 t.files[id]= save;
\r
1011 // update file_datas
\r
1012 EditArea.prototype.update_file= function(id, new_values){
\r
1013 for(var i in new_values)
\r
1015 this.files[id][i]= new_values[i];
\r
1019 // display file datas
\r
1020 EditArea.prototype.display_file= function(id){
\r
1021 var t = this, a= t.textarea, new_file, a_lis, a_selects, a_links, a_options, i, j;
\r
1023 // we're showing the empty file
\r
1027 t.tab_browsing_area.style.display= "none";
\r
1028 _$("no_file_selected").style.display= "block";
\r
1029 t.result.className= "empty";
\r
1030 // clear current datas
\r
1033 t.open_file({id: ''});
\r
1036 // we try to show a non existent file, so we left
\r
1037 else if( typeof( t.files[id] ) == 'undefined' )
\r
1041 // display a normal file
\r
1044 t.result.className= "";
\r
1045 a.readOnly= !t.is_editable;
\r
1046 _$("no_file_selected").style.display= "none";
\r
1047 t.tab_browsing_area.style.display= "block";
\r
1050 // ensure to have last state for undo/redo actions
\r
1051 t.check_redo(true);
\r
1052 t.check_undo(true);
\r
1055 // replace selected tab file
\r
1056 a_lis= t.tab_browsing_area.getElementsByTagName('li');
\r
1057 for( i=0; i<a_lis.length; i++)
\r
1059 if(a_lis[i].id == t.files[id]['html_id'])
\r
1060 a_lis[i].className='selected';
\r
1062 a_lis[i].className='';
\r
1065 // replace next files datas
\r
1066 new_file= t.files[id];
\r
1068 // restore text content
\r
1069 a.value= new_file['text'];
\r
1071 // restore font-size
\r
1072 t.set_font(new_file['font_family'], new_file['font_size']);
\r
1074 // restore selection and scroll
\r
1075 t.area_select(new_file['last_selection']['selection_start'], new_file['last_selection']['selection_end'] - new_file['last_selection']['selection_start']);
\r
1076 t.manage_size(true);
\r
1077 t.result.scrollTop= new_file['scroll_top'];
\r
1078 t.result.scrollLeft= new_file['scroll_left'];
\r
1080 // restore undo, redo
\r
1081 t.previous= new_file['previous'];
\r
1082 t.next= new_file['next'];
\r
1083 t.last_undo= new_file['last_undo'];
\r
1084 t.check_redo(true);
\r
1085 t.check_undo(true);
\r
1087 // restore highlight
\r
1088 t.execCommand("change_highlight", new_file['do_highlight']);
\r
1089 t.execCommand("change_syntax", new_file['syntax']);
\r
1092 t.execCommand("change_smooth_selection_mode", new_file['smooth_selection']);
\r
1095 t.execCommand("set_word_wrap", new_file['word_wrap']);
\r
1097 // restore links state in toolbar
\r
1098 a_links= new_file['toolbar']['links'];
\r
1099 for( i in a_links)
\r
1101 if( img = _$(i).getElementsByTagName('img')[0] )
\r
1103 img.classLock = a_links[i]['classLock'];
\r
1104 img.className = a_links[i]['className'];
\r
1105 img.oldClassName= a_links[i]['oldClassName'];
\r
1109 // restore select state in toolbar
\r
1110 a_selects = new_file['toolbar']['selects'];
\r
1111 for( i in a_selects)
\r
1113 a_options = _$(i).options;
\r
1114 for( j=0; j<a_options.length; j++)
\r
1116 if( a_options[j].value == a_selects[i] )
\r
1117 _$(i).options[j].selected=true;
\r
1123 // change tab for displaying a new one
\r
1124 EditArea.prototype.switch_to_file= function(file_to_show, force_refresh){
\r
1125 if(file_to_show!=this.curr_file || force_refresh)
\r
1127 this.save_file(this.curr_file);
\r
1128 if(this.curr_file!='')
\r
1129 this.execCommand('file_switch_off', this.files[this.curr_file]);
\r
1130 this.display_file(file_to_show);
\r
1131 if(file_to_show!='')
\r
1132 this.execCommand('file_switch_on', this.files[file_to_show]);
\r
1136 // get all infos for the given file
\r
1137 EditArea.prototype.get_file= function(id){
\r
1138 if(id==this.curr_file)
\r
1139 this.save_file(id);
\r
1140 return this.files[id];
\r
1143 // get all available files infos
\r
1144 EditArea.prototype.get_all_files= function(){
\r
1145 tmp_files= this.files;
\r
1146 this.save_file(this.curr_file);
\r
1148 delete(this.files['']);
\r
1153 // check if the file has changed
\r
1154 EditArea.prototype.check_file_changes= function(){
\r
1156 var id= this.curr_file;
\r
1157 if(this.files[id] && this.files[id]['compare_edited_text']!=undefined)
\r
1159 if(this.files[id]['compare_edited_text'].length==this.textarea.value.length && this.files[id]['compare_edited_text']==this.textarea.value)
\r
1161 if(this.files[id]['edited']!= false)
\r
1162 this.set_file_edited_mode(id, false);
\r
1166 if(this.files[id]['edited']!= true)
\r
1167 this.set_file_edited_mode(id, true);
\r
1172 // set if the file is edited or not
\r
1173 EditArea.prototype.set_file_edited_mode= function(id, to){
\r
1174 // change CSS for edited tab
\r
1175 if(this.files[id] && _$(this.files[id]['html_id']))
\r
1177 var link= _$(this.files[id]['html_id']).getElementsByTagName('a')[0];
\r
1180 link.className= 'edited';
\r
1184 link.className= '';
\r
1185 if(id==this.curr_file)
\r
1186 text= this.textarea.value;
\r
1188 text= this.files[id]['text'];
\r
1189 this.files[id]['compare_edited_text']= text;
\r
1192 this.files[id]['edited']= to;
\r
1196 EditArea.prototype.set_show_line_colors = function(new_value){
\r
1197 this.show_line_colors = new_value;
\r
1200 this.selection_field.className += ' show_colors';
\r
1202 this.selection_field.className = this.selection_field.className.replace( / show_colors/g, '' );
\r