fixws and 'new' button in grid query

This commit is contained in:
Massimo Di Pierro
2011-12-05 11:39:42 -06:00
parent 01f6f82cdf
commit d281acb421
305 changed files with 8352 additions and 8032 deletions
@@ -1,491 +1,491 @@
/**
* Autocompletion class
*
* An auto completion box appear while you're writing. It's possible to force it to appear with Ctrl+Space short cut
*
* Loaded as a plugin inside editArea (everything made here could have been made in the plugin directory)
* But is definitly linked to syntax selection (no need to do 2 different files for color and auto complete for each syntax language)
* and add a too important feature that many people would miss if included as a plugin
*
* - init param: autocompletion_start
* - Button name: "autocompletion"
*/
var EditArea_autocompletion= {
/**
* Get called once this file is loaded (editArea still not initialized)
*
* @return nothing
*/
init: function(){
// alert("test init: "+ this._someInternalFunction(2, 3));
if(editArea.settings["autocompletion"])
this.enabled= true;
else
this.enabled= false;
this.current_word = false;
this.shown = false;
this.selectIndex = -1;
this.forceDisplay = false;
this.isInMiddleWord = false;
this.autoSelectIfOneResult = false;
this.delayBeforeDisplay = 100;
this.checkDelayTimer = false;
this.curr_syntax_str = '';
this.file_syntax_datas = {};
}
/**
* Returns the HTML code for a specific control string or false if this plugin doesn't have that control.
* A control can be a button, select list or any other HTML item to present in the EditArea user interface.
* Language variables such as {$lang_somekey} will also be replaced with contents from
* the language packs.
*
* @param {string} ctrl_name: the name of the control to add
* @return HTML code for a specific control or false.
* @type string or boolean
*/
/*,get_control_html: function(ctrl_name){
switch( ctrl_name ){
case 'autocompletion':
// Control id, button img, command
return parent.editAreaLoader.get_button_html('autocompletion_but', 'autocompletion.gif', 'toggle_autocompletion', false, this.baseURL);
break;
}
return false;
}*/
/**
* Get called once EditArea is fully loaded and initialised
*
* @return nothing
*/
,onload: function(){
if(this.enabled)
{
var icon= document.getElementById("autocompletion");
if(icon)
editArea.switchClassSticky(icon, 'editAreaButtonSelected', true);
}
this.container = document.createElement('div');
this.container.id = "auto_completion_area";
editArea.container.insertBefore( this.container, editArea.container.firstChild );
// add event detection for hiding suggestion box
parent.editAreaLoader.add_event( document, "click", function(){ editArea.plugins['autocompletion']._hide();} );
parent.editAreaLoader.add_event( editArea.textarea, "blur", function(){ editArea.plugins['autocompletion']._hide();} );
}
/**
* Is called each time the user touch a keyboard key.
*
* @param (event) e: the keydown event
* @return true - pass to next handler in chain, false - stop chain execution
* @type boolean
*/
,onkeydown: function(e){
if(!this.enabled)
return true;
if (EA_keys[e.keyCode])
letter=EA_keys[e.keyCode];
else
letter=String.fromCharCode(e.keyCode);
// shown
if( this._isShown() )
{
// if escape, hide the box
if(letter=="Esc")
{
this._hide();
return false;
}
// Enter
else if( letter=="Entrer")
{
var as = this.container.getElementsByTagName('A');
// select a suggested entry
if( this.selectIndex >= 0 && this.selectIndex < as.length )
{
as[ this.selectIndex ].onmousedown();
return false
}
// simply add an enter in the code
else
{
this._hide();
return true;
}
}
else if( letter=="Tab" || letter=="Down")
{
this._selectNext();
return false;
}
else if( letter=="Up")
{
this._selectBefore();
return false;
}
}
// hidden
else
{
}
// show current suggestion list and do autoSelect if possible (no matter it's shown or hidden)
if( letter=="Space" && CtrlPressed(e) )
{
//parent.console.log('SHOW SUGGEST');
this.forceDisplay = true;
this.autoSelectIfOneResult = true;
this._checkLetter();
return false;
}
// wait a short period for check that the cursor isn't moving
setTimeout("editArea.plugins['autocompletion']._checkDelayAndCursorBeforeDisplay();", editArea.check_line_selection_timer +5 );
this.checkDelayTimer = false;
return true;
}
/**
* Executes a specific command, this function handles plugin commands.
*
* @param {string} cmd: the name of the command being executed
* @param {unknown} param: the parameter of the command
* @return true - pass to next handler in chain, false - stop chain execution
* @type boolean
*/
,execCommand: function(cmd, param){
switch( cmd ){
case 'toggle_autocompletion':
var icon= document.getElementById("autocompletion");
if(!this.enabled)
{
if(icon != null){
editArea.restoreClass(icon);
editArea.switchClassSticky(icon, 'editAreaButtonSelected', true);
}
this.enabled= true;
}
else
{
this.enabled= false;
if(icon != null)
editArea.switchClassSticky(icon, 'editAreaButtonNormal', false);
}
return true;
}
return true;
}
,_checkDelayAndCursorBeforeDisplay: function()
{
this.checkDelayTimer = setTimeout("if(editArea.textarea.selectionStart == "+ editArea.textarea.selectionStart +") EditArea_autocompletion._checkLetter();", this.delayBeforeDisplay - editArea.check_line_selection_timer - 5 );
}
// hide the suggested box
,_hide: function(){
this.container.style.display="none";
this.selectIndex = -1;
this.shown = false;
this.forceDisplay = false;
this.autoSelectIfOneResult = false;
}
// display the suggested box
,_show: function(){
if( !this._isShown() )
{
this.container.style.display="block";
this.selectIndex = -1;
this.shown = true;
}
}
// is the suggested box displayed?
,_isShown: function(){
return this.shown;
}
// setter and getter
,_isInMiddleWord: function( new_value ){
if( typeof( new_value ) == "undefined" )
return this.isInMiddleWord;
else
this.isInMiddleWord = new_value;
}
// select the next element in the suggested box
,_selectNext: function()
{
var as = this.container.getElementsByTagName('A');
// clean existing elements
for( var i=0; i<as.length; i++ )
{
if( as[i].className )
as[i].className = as[i].className.replace(/ focus/g, '');
}
this.selectIndex++;
this.selectIndex = ( this.selectIndex >= as.length || this.selectIndex < 0 ) ? 0 : this.selectIndex;
as[ this.selectIndex ].className += " focus";
}
// select the previous element in the suggested box
,_selectBefore: function()
{
var as = this.container.getElementsByTagName('A');
// clean existing elements
for( var i=0; i<as.length; i++ )
{
if( as[i].className )
as[i].className = as[ i ].className.replace(/ focus/g, '');
}
this.selectIndex--;
this.selectIndex = ( this.selectIndex >= as.length || this.selectIndex < 0 ) ? as.length-1 : this.selectIndex;
as[ this.selectIndex ].className += " focus";
}
,_select: function( content )
{
cursor_forced_position = content.indexOf( '{@}' );
content = content.replace(/{@}/g, '' );
editArea.getIESelection();
// retrive the number of matching characters
var start_index = Math.max( 0, editArea.textarea.selectionEnd - content.length );
line_string = editArea.textarea.value.substring( start_index, editArea.textarea.selectionEnd + 1);
limit = line_string.length -1;
nbMatch = 0;
for( i =0; i<limit ; i++ )
{
if( line_string.substring( limit - i - 1, limit ) == content.substring( 0, i + 1 ) )
nbMatch = i + 1;
}
// if characters match, we should include them in the selection that will be replaced
if( nbMatch > 0 )
parent.editAreaLoader.setSelectionRange(editArea.id, editArea.textarea.selectionStart - nbMatch , editArea.textarea.selectionEnd);
parent.editAreaLoader.setSelectedText(editArea.id, content );
range= parent.editAreaLoader.getSelectionRange(editArea.id);
if( cursor_forced_position != -1 )
new_pos = range["end"] - ( content.length-cursor_forced_position );
else
new_pos = range["end"];
parent.editAreaLoader.setSelectionRange(editArea.id, new_pos, new_pos);
this._hide();
}
/**
* Parse the AUTO_COMPLETION part of syntax definition files
*/
,_parseSyntaxAutoCompletionDatas: function(){
//foreach syntax loaded
for(var lang in parent.editAreaLoader.load_syntax)
{
if(!parent.editAreaLoader.syntax[lang]['autocompletion']) // init the regexp if not already initialized
{
parent.editAreaLoader.syntax[lang]['autocompletion']= {};
// the file has auto completion datas
if(parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'])
{
// parse them
for(var i in parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'])
{
datas = parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'][i];
tmp = {};
if(datas["CASE_SENSITIVE"]!="undefined" && datas["CASE_SENSITIVE"]==false)
tmp["modifiers"]="i";
else
tmp["modifiers"]="";
tmp["prefix_separator"]= datas["REGEXP"]["prefix_separator"];
tmp["match_prefix_separator"]= new RegExp( datas["REGEXP"]["prefix_separator"] +"$", tmp["modifiers"]);
tmp["match_word"]= new RegExp("(?:"+ datas["REGEXP"]["before_word"] +")("+ datas["REGEXP"]["possible_words_letters"] +")$", tmp["modifiers"]);
tmp["match_next_letter"]= new RegExp("^("+ datas["REGEXP"]["letter_after_word_must_match"] +")$", tmp["modifiers"]);
tmp["keywords"]= {};
//console.log( datas["KEYWORDS"] );
for( var prefix in datas["KEYWORDS"] )
{
tmp["keywords"][prefix]= {
prefix: prefix,
prefix_name: prefix,
prefix_reg: new RegExp("(?:"+ parent.editAreaLoader.get_escaped_regexp( prefix ) +")(?:"+ tmp["prefix_separator"] +")$", tmp["modifiers"] ),
datas: []
};
for( var j=0; j<datas["KEYWORDS"][prefix].length; j++ )
{
tmp["keywords"][prefix]['datas'][j]= {
is_typing: datas["KEYWORDS"][prefix][j][0],
// if replace with is empty, replace with the is_typing value
replace_with: datas["KEYWORDS"][prefix][j][1] ? datas["KEYWORDS"][prefix][j][1].replace('§', datas["KEYWORDS"][prefix][j][0] ) : '',
comment: datas["KEYWORDS"][prefix][j][2] ? datas["KEYWORDS"][prefix][j][2] : ''
};
// the replace with shouldn't be empty
if( tmp["keywords"][prefix]['datas'][j]['replace_with'].length == 0 )
tmp["keywords"][prefix]['datas'][j]['replace_with'] = tmp["keywords"][prefix]['datas'][j]['is_typing'];
// if the comment is empty, display the replace_with value
if( tmp["keywords"][prefix]['datas'][j]['comment'].length == 0 )
tmp["keywords"][prefix]['datas'][j]['comment'] = tmp["keywords"][prefix]['datas'][j]['replace_with'].replace(/{@}/g, '' );
}
}
tmp["max_text_length"]= datas["MAX_TEXT_LENGTH"];
parent.editAreaLoader.syntax[lang]['autocompletion'][i] = tmp;
}
}
}
}
}
,_checkLetter: function(){
// check that syntax hasn't changed
if( this.curr_syntax_str != editArea.settings['syntax'] )
{
if( !parent.editAreaLoader.syntax[editArea.settings['syntax']]['autocompletion'] )
this._parseSyntaxAutoCompletionDatas();
this.curr_syntax= parent.editAreaLoader.syntax[editArea.settings['syntax']]['autocompletion'];
this.curr_syntax_str = editArea.settings['syntax'];
//console.log( this.curr_syntax );
}
if( editArea.is_editable )
{
time=new Date;
t1= time.getTime();
editArea.getIESelection();
this.selectIndex = -1;
start=editArea.textarea.selectionStart;
var str = editArea.textarea.value;
var results= [];
for(var i in this.curr_syntax)
{
var last_chars = str.substring(Math.max(0, start-this.curr_syntax[i]["max_text_length"]), start);
var matchNextletter = str.substring(start, start+1).match( this.curr_syntax[i]["match_next_letter"]);
// if not writting in the middle of a word or if forcing display
if( matchNextletter || this.forceDisplay )
{
// check if the last chars match a separator
var match_prefix_separator = last_chars.match(this.curr_syntax[i]["match_prefix_separator"]);
// check if it match a possible word
var match_word= last_chars.match(this.curr_syntax[i]["match_word"]);
//console.log( match_word );
if( match_word )
{
var begin_word= match_word[1];
var match_curr_word= new RegExp("^"+ parent.editAreaLoader.get_escaped_regexp( begin_word ), this.curr_syntax[i]["modifiers"]);
//console.log( match_curr_word );
for(var prefix in this.curr_syntax[i]["keywords"])
{
// parent.console.log( this.curr_syntax[i]["keywords"][prefix] );
for(var j=0; j<this.curr_syntax[i]["keywords"][prefix]['datas'].length; j++)
{
// parent.console.log( this.curr_syntax[i]["keywords"][prefix]['datas'][j]['is_typing'] );
// the key word match or force display
if( this.curr_syntax[i]["keywords"][prefix]['datas'][j]['is_typing'].match(match_curr_word) )
{
// parent.console.log('match');
hasMatch = false;
var before = last_chars.substr( 0, last_chars.length - begin_word.length );
// no prefix to match => it's valid
if( !match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length == 0 )
{
if( ! before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
hasMatch = true;
}
// we still need to check the prefix if there is one
else if( this.curr_syntax[i]["keywords"][prefix]['prefix'].length > 0 )
{
if( before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
hasMatch = true;
}
if( hasMatch )
results[results.length]= [ this.curr_syntax[i]["keywords"][prefix], this.curr_syntax[i]["keywords"][prefix]['datas'][j] ];
}
}
}
}
// it doesn't match any possible word but we want to display something
// we'll display to list of all available words
else if( this.forceDisplay || match_prefix_separator )
{
for(var prefix in this.curr_syntax[i]["keywords"])
{
for(var j=0; j<this.curr_syntax[i]["keywords"][prefix]['datas'].length; j++)
{
hasMatch = false;
// no prefix to match => it's valid
if( !match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length == 0 )
{
hasMatch = true;
}
// we still need to check the prefix if there is one
else if( match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length > 0 )
{
var before = last_chars; //.substr( 0, last_chars.length );
if( before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
hasMatch = true;
}
if( hasMatch )
results[results.length]= [ this.curr_syntax[i]["keywords"][prefix], this.curr_syntax[i]["keywords"][prefix]['datas'][j] ];
}
}
}
}
}
// there is only one result, and we can select it automatically
if( results.length == 1 && this.autoSelectIfOneResult )
{
// console.log( results );
this._select( results[0][1]['replace_with'] );
}
else if( results.length == 0 )
{
this._hide();
}
else
{
// build the suggestion box content
var lines=[];
for(var i=0; i<results.length; i++)
{
var line= "<li><a href=\"#\" class=\"entry\" onmousedown=\"EditArea_autocompletion._select('"+ results[i][1]['replace_with'].replace(new RegExp('"', "g"), "&quot;") +"');return false;\">"+ results[i][1]['comment'];
if(results[i][0]['prefix_name'].length>0)
line+='<span class="prefix">'+ results[i][0]['prefix_name'] +'</span>';
line+='</a></li>';
lines[lines.length]=line;
}
// sort results
this.container.innerHTML = '<ul>'+ lines.sort().join('') +'</ul>';
var cursor = _$("cursor_pos");
this.container.style.top = ( cursor.cursor_top + editArea.lineHeight ) +"px";
this.container.style.left = ( cursor.cursor_left + 8 ) +"px";
this._show();
}
this.autoSelectIfOneResult = false;
time=new Date;
t2= time.getTime();
//parent.console.log( begin_word +"\n"+ (t2-t1) +"\n"+ html );
}
}
};
// Load as a plugin
editArea.settings['plugins'][ editArea.settings['plugins'].length ] = 'autocompletion';
editArea.add_plugin('autocompletion', EditArea_autocompletion);
/**
* Autocompletion class
*
* An auto completion box appear while you're writing. It's possible to force it to appear with Ctrl+Space short cut
*
* Loaded as a plugin inside editArea (everything made here could have been made in the plugin directory)
* But is definitly linked to syntax selection (no need to do 2 different files for color and auto complete for each syntax language)
* and add a too important feature that many people would miss if included as a plugin
*
* - init param: autocompletion_start
* - Button name: "autocompletion"
*/
var EditArea_autocompletion= {
/**
* Get called once this file is loaded (editArea still not initialized)
*
* @return nothing
*/
init: function(){
// alert("test init: "+ this._someInternalFunction(2, 3));
if(editArea.settings["autocompletion"])
this.enabled= true;
else
this.enabled= false;
this.current_word = false;
this.shown = false;
this.selectIndex = -1;
this.forceDisplay = false;
this.isInMiddleWord = false;
this.autoSelectIfOneResult = false;
this.delayBeforeDisplay = 100;
this.checkDelayTimer = false;
this.curr_syntax_str = '';
this.file_syntax_datas = {};
}
/**
* Returns the HTML code for a specific control string or false if this plugin doesn't have that control.
* A control can be a button, select list or any other HTML item to present in the EditArea user interface.
* Language variables such as {$lang_somekey} will also be replaced with contents from
* the language packs.
*
* @param {string} ctrl_name: the name of the control to add
* @return HTML code for a specific control or false.
* @type string or boolean
*/
/*,get_control_html: function(ctrl_name){
switch( ctrl_name ){
case 'autocompletion':
// Control id, button img, command
return parent.editAreaLoader.get_button_html('autocompletion_but', 'autocompletion.gif', 'toggle_autocompletion', false, this.baseURL);
break;
}
return false;
}*/
/**
* Get called once EditArea is fully loaded and initialised
*
* @return nothing
*/
,onload: function(){
if(this.enabled)
{
var icon= document.getElementById("autocompletion");
if(icon)
editArea.switchClassSticky(icon, 'editAreaButtonSelected', true);
}
this.container = document.createElement('div');
this.container.id = "auto_completion_area";
editArea.container.insertBefore( this.container, editArea.container.firstChild );
// add event detection for hiding suggestion box
parent.editAreaLoader.add_event( document, "click", function(){ editArea.plugins['autocompletion']._hide();} );
parent.editAreaLoader.add_event( editArea.textarea, "blur", function(){ editArea.plugins['autocompletion']._hide();} );
}
/**
* Is called each time the user touch a keyboard key.
*
* @param (event) e: the keydown event
* @return true - pass to next handler in chain, false - stop chain execution
* @type boolean
*/
,onkeydown: function(e){
if(!this.enabled)
return true;
if (EA_keys[e.keyCode])
letter=EA_keys[e.keyCode];
else
letter=String.fromCharCode(e.keyCode);
// shown
if( this._isShown() )
{
// if escape, hide the box
if(letter=="Esc")
{
this._hide();
return false;
}
// Enter
else if( letter=="Entrer")
{
var as = this.container.getElementsByTagName('A');
// select a suggested entry
if( this.selectIndex >= 0 && this.selectIndex < as.length )
{
as[ this.selectIndex ].onmousedown();
return false
}
// simply add an enter in the code
else
{
this._hide();
return true;
}
}
else if( letter=="Tab" || letter=="Down")
{
this._selectNext();
return false;
}
else if( letter=="Up")
{
this._selectBefore();
return false;
}
}
// hidden
else
{
}
// show current suggestion list and do autoSelect if possible (no matter it's shown or hidden)
if( letter=="Space" && CtrlPressed(e) )
{
//parent.console.log('SHOW SUGGEST');
this.forceDisplay = true;
this.autoSelectIfOneResult = true;
this._checkLetter();
return false;
}
// wait a short period for check that the cursor isn't moving
setTimeout("editArea.plugins['autocompletion']._checkDelayAndCursorBeforeDisplay();", editArea.check_line_selection_timer +5 );
this.checkDelayTimer = false;
return true;
}
/**
* Executes a specific command, this function handles plugin commands.
*
* @param {string} cmd: the name of the command being executed
* @param {unknown} param: the parameter of the command
* @return true - pass to next handler in chain, false - stop chain execution
* @type boolean
*/
,execCommand: function(cmd, param){
switch( cmd ){
case 'toggle_autocompletion':
var icon= document.getElementById("autocompletion");
if(!this.enabled)
{
if(icon != null){
editArea.restoreClass(icon);
editArea.switchClassSticky(icon, 'editAreaButtonSelected', true);
}
this.enabled= true;
}
else
{
this.enabled= false;
if(icon != null)
editArea.switchClassSticky(icon, 'editAreaButtonNormal', false);
}
return true;
}
return true;
}
,_checkDelayAndCursorBeforeDisplay: function()
{
this.checkDelayTimer = setTimeout("if(editArea.textarea.selectionStart == "+ editArea.textarea.selectionStart +") EditArea_autocompletion._checkLetter();", this.delayBeforeDisplay - editArea.check_line_selection_timer - 5 );
}
// hide the suggested box
,_hide: function(){
this.container.style.display="none";
this.selectIndex = -1;
this.shown = false;
this.forceDisplay = false;
this.autoSelectIfOneResult = false;
}
// display the suggested box
,_show: function(){
if( !this._isShown() )
{
this.container.style.display="block";
this.selectIndex = -1;
this.shown = true;
}
}
// is the suggested box displayed?
,_isShown: function(){
return this.shown;
}
// setter and getter
,_isInMiddleWord: function( new_value ){
if( typeof( new_value ) == "undefined" )
return this.isInMiddleWord;
else
this.isInMiddleWord = new_value;
}
// select the next element in the suggested box
,_selectNext: function()
{
var as = this.container.getElementsByTagName('A');
// clean existing elements
for( var i=0; i<as.length; i++ )
{
if( as[i].className )
as[i].className = as[i].className.replace(/ focus/g, '');
}
this.selectIndex++;
this.selectIndex = ( this.selectIndex >= as.length || this.selectIndex < 0 ) ? 0 : this.selectIndex;
as[ this.selectIndex ].className += " focus";
}
// select the previous element in the suggested box
,_selectBefore: function()
{
var as = this.container.getElementsByTagName('A');
// clean existing elements
for( var i=0; i<as.length; i++ )
{
if( as[i].className )
as[i].className = as[ i ].className.replace(/ focus/g, '');
}
this.selectIndex--;
this.selectIndex = ( this.selectIndex >= as.length || this.selectIndex < 0 ) ? as.length-1 : this.selectIndex;
as[ this.selectIndex ].className += " focus";
}
,_select: function( content )
{
cursor_forced_position = content.indexOf( '{@}' );
content = content.replace(/{@}/g, '' );
editArea.getIESelection();
// retrive the number of matching characters
var start_index = Math.max( 0, editArea.textarea.selectionEnd - content.length );
line_string = editArea.textarea.value.substring( start_index, editArea.textarea.selectionEnd + 1);
limit = line_string.length -1;
nbMatch = 0;
for( i =0; i<limit ; i++ )
{
if( line_string.substring( limit - i - 1, limit ) == content.substring( 0, i + 1 ) )
nbMatch = i + 1;
}
// if characters match, we should include them in the selection that will be replaced
if( nbMatch > 0 )
parent.editAreaLoader.setSelectionRange(editArea.id, editArea.textarea.selectionStart - nbMatch , editArea.textarea.selectionEnd);
parent.editAreaLoader.setSelectedText(editArea.id, content );
range= parent.editAreaLoader.getSelectionRange(editArea.id);
if( cursor_forced_position != -1 )
new_pos = range["end"] - ( content.length-cursor_forced_position );
else
new_pos = range["end"];
parent.editAreaLoader.setSelectionRange(editArea.id, new_pos, new_pos);
this._hide();
}
/**
* Parse the AUTO_COMPLETION part of syntax definition files
*/
,_parseSyntaxAutoCompletionDatas: function(){
//foreach syntax loaded
for(var lang in parent.editAreaLoader.load_syntax)
{
if(!parent.editAreaLoader.syntax[lang]['autocompletion']) // init the regexp if not already initialized
{
parent.editAreaLoader.syntax[lang]['autocompletion']= {};
// the file has auto completion datas
if(parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'])
{
// parse them
for(var i in parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'])
{
datas = parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'][i];
tmp = {};
if(datas["CASE_SENSITIVE"]!="undefined" && datas["CASE_SENSITIVE"]==false)
tmp["modifiers"]="i";
else
tmp["modifiers"]="";
tmp["prefix_separator"]= datas["REGEXP"]["prefix_separator"];
tmp["match_prefix_separator"]= new RegExp( datas["REGEXP"]["prefix_separator"] +"$", tmp["modifiers"]);
tmp["match_word"]= new RegExp("(?:"+ datas["REGEXP"]["before_word"] +")("+ datas["REGEXP"]["possible_words_letters"] +")$", tmp["modifiers"]);
tmp["match_next_letter"]= new RegExp("^("+ datas["REGEXP"]["letter_after_word_must_match"] +")$", tmp["modifiers"]);
tmp["keywords"]= {};
//console.log( datas["KEYWORDS"] );
for( var prefix in datas["KEYWORDS"] )
{
tmp["keywords"][prefix]= {
prefix: prefix,
prefix_name: prefix,
prefix_reg: new RegExp("(?:"+ parent.editAreaLoader.get_escaped_regexp( prefix ) +")(?:"+ tmp["prefix_separator"] +")$", tmp["modifiers"] ),
datas: []
};
for( var j=0; j<datas["KEYWORDS"][prefix].length; j++ )
{
tmp["keywords"][prefix]['datas'][j]= {
is_typing: datas["KEYWORDS"][prefix][j][0],
// if replace with is empty, replace with the is_typing value
replace_with: datas["KEYWORDS"][prefix][j][1] ? datas["KEYWORDS"][prefix][j][1].replace('§', datas["KEYWORDS"][prefix][j][0] ) : '',
comment: datas["KEYWORDS"][prefix][j][2] ? datas["KEYWORDS"][prefix][j][2] : ''
};
// the replace with shouldn't be empty
if( tmp["keywords"][prefix]['datas'][j]['replace_with'].length == 0 )
tmp["keywords"][prefix]['datas'][j]['replace_with'] = tmp["keywords"][prefix]['datas'][j]['is_typing'];
// if the comment is empty, display the replace_with value
if( tmp["keywords"][prefix]['datas'][j]['comment'].length == 0 )
tmp["keywords"][prefix]['datas'][j]['comment'] = tmp["keywords"][prefix]['datas'][j]['replace_with'].replace(/{@}/g, '' );
}
}
tmp["max_text_length"]= datas["MAX_TEXT_LENGTH"];
parent.editAreaLoader.syntax[lang]['autocompletion'][i] = tmp;
}
}
}
}
}
,_checkLetter: function(){
// check that syntax hasn't changed
if( this.curr_syntax_str != editArea.settings['syntax'] )
{
if( !parent.editAreaLoader.syntax[editArea.settings['syntax']]['autocompletion'] )
this._parseSyntaxAutoCompletionDatas();
this.curr_syntax= parent.editAreaLoader.syntax[editArea.settings['syntax']]['autocompletion'];
this.curr_syntax_str = editArea.settings['syntax'];
//console.log( this.curr_syntax );
}
if( editArea.is_editable )
{
time=new Date;
t1= time.getTime();
editArea.getIESelection();
this.selectIndex = -1;
start=editArea.textarea.selectionStart;
var str = editArea.textarea.value;
var results= [];
for(var i in this.curr_syntax)
{
var last_chars = str.substring(Math.max(0, start-this.curr_syntax[i]["max_text_length"]), start);
var matchNextletter = str.substring(start, start+1).match( this.curr_syntax[i]["match_next_letter"]);
// if not writting in the middle of a word or if forcing display
if( matchNextletter || this.forceDisplay )
{
// check if the last chars match a separator
var match_prefix_separator = last_chars.match(this.curr_syntax[i]["match_prefix_separator"]);
// check if it match a possible word
var match_word= last_chars.match(this.curr_syntax[i]["match_word"]);
//console.log( match_word );
if( match_word )
{
var begin_word= match_word[1];
var match_curr_word= new RegExp("^"+ parent.editAreaLoader.get_escaped_regexp( begin_word ), this.curr_syntax[i]["modifiers"]);
//console.log( match_curr_word );
for(var prefix in this.curr_syntax[i]["keywords"])
{
// parent.console.log( this.curr_syntax[i]["keywords"][prefix] );
for(var j=0; j<this.curr_syntax[i]["keywords"][prefix]['datas'].length; j++)
{
// parent.console.log( this.curr_syntax[i]["keywords"][prefix]['datas'][j]['is_typing'] );
// the key word match or force display
if( this.curr_syntax[i]["keywords"][prefix]['datas'][j]['is_typing'].match(match_curr_word) )
{
// parent.console.log('match');
hasMatch = false;
var before = last_chars.substr( 0, last_chars.length - begin_word.length );
// no prefix to match => it's valid
if( !match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length == 0 )
{
if( ! before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
hasMatch = true;
}
// we still need to check the prefix if there is one
else if( this.curr_syntax[i]["keywords"][prefix]['prefix'].length > 0 )
{
if( before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
hasMatch = true;
}
if( hasMatch )
results[results.length]= [ this.curr_syntax[i]["keywords"][prefix], this.curr_syntax[i]["keywords"][prefix]['datas'][j] ];
}
}
}
}
// it doesn't match any possible word but we want to display something
// we'll display to list of all available words
else if( this.forceDisplay || match_prefix_separator )
{
for(var prefix in this.curr_syntax[i]["keywords"])
{
for(var j=0; j<this.curr_syntax[i]["keywords"][prefix]['datas'].length; j++)
{
hasMatch = false;
// no prefix to match => it's valid
if( !match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length == 0 )
{
hasMatch = true;
}
// we still need to check the prefix if there is one
else if( match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length > 0 )
{
var before = last_chars; //.substr( 0, last_chars.length );
if( before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
hasMatch = true;
}
if( hasMatch )
results[results.length]= [ this.curr_syntax[i]["keywords"][prefix], this.curr_syntax[i]["keywords"][prefix]['datas'][j] ];
}
}
}
}
}
// there is only one result, and we can select it automatically
if( results.length == 1 && this.autoSelectIfOneResult )
{
// console.log( results );
this._select( results[0][1]['replace_with'] );
}
else if( results.length == 0 )
{
this._hide();
}
else
{
// build the suggestion box content
var lines=[];
for(var i=0; i<results.length; i++)
{
var line= "<li><a href=\"#\" class=\"entry\" onmousedown=\"EditArea_autocompletion._select('"+ results[i][1]['replace_with'].replace(new RegExp('"', "g"), "&quot;") +"');return false;\">"+ results[i][1]['comment'];
if(results[i][0]['prefix_name'].length>0)
line+='<span class="prefix">'+ results[i][0]['prefix_name'] +'</span>';
line+='</a></li>';
lines[lines.length]=line;
}
// sort results
this.container.innerHTML = '<ul>'+ lines.sort().join('') +'</ul>';
var cursor = _$("cursor_pos");
this.container.style.top = ( cursor.cursor_top + editArea.lineHeight ) +"px";
this.container.style.left = ( cursor.cursor_left + 8 ) +"px";
this._show();
}
this.autoSelectIfOneResult = false;
time=new Date;
t2= time.getTime();
//parent.console.log( begin_word +"\n"+ (t2-t1) +"\n"+ html );
}
}
};
// Load as a plugin
editArea.settings['plugins'][ editArea.settings['plugins'].length ] = 'autocompletion';
editArea.add_plugin('autocompletion', EditArea_autocompletion);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,336 +1,337 @@
/****
* This page contains some general usefull functions for javascript
*
****/
// need to redefine this functiondue to IE problem
function getAttribute( elm, aName ) {
var aValue,taName,i;
try{
aValue = elm.getAttribute( aName );
}catch(exept){}
if( ! aValue ){
for( i = 0; i < elm.attributes.length; i ++ ) {
taName = elm.attributes[i] .name.toLowerCase();
if( taName == aName ) {
aValue = elm.attributes[i] .value;
return aValue;
}
}
}
return aValue;
};
// need to redefine this function due to IE problem
function setAttribute( elm, attr, val ) {
if(attr=="class"){
elm.setAttribute("className", val);
elm.setAttribute("class", val);
}else{
elm.setAttribute(attr, val);
}
};
/* return a child element
elem: element we are searching in
elem_type: type of the eleemnt we are searching (DIV, A, etc...)
elem_attribute: attribute of the searched element that must match
elem_attribute_match: value that elem_attribute must match
option: "all" if must return an array of all children, otherwise return the first match element
depth: depth of search (-1 or no set => unlimited)
*/
function getChildren(elem, elem_type, elem_attribute, elem_attribute_match, option, depth)
{
if(!option)
var option="single";
if(!depth)
var depth=-1;
if(elem){
var children= elem.childNodes;
var result=null;
var results= [];
for (var x=0;x<children.length;x++) {
strTagName = new String(children[x].tagName);
children_class="?";
if(strTagName!= "undefined"){
child_attribute= getAttribute(children[x],elem_attribute);
if((strTagName.toLowerCase()==elem_type.toLowerCase() || elem_type=="") && (elem_attribute=="" || child_attribute==elem_attribute_match)){
if(option=="all"){
results.push(children[x]);
}else{
return children[x];
}
}
if(depth!=0){
result=getChildren(children[x], elem_type, elem_attribute, elem_attribute_match, option, depth-1);
if(option=="all"){
if(result.length>0){
results= results.concat(result);
}
}else if(result!=null){
return result;
}
}
}
}
if(option=="all")
return results;
}
return null;
};
function isChildOf(elem, parent){
if(elem){
if(elem==parent)
return true;
while(elem.parentNode != 'undefined'){
return isChildOf(elem.parentNode, parent);
}
}
return false;
};
function getMouseX(e){
if(e!=null && typeof(e.pageX)!="undefined"){
return e.pageX;
}else{
return (e!=null?e.x:event.x)+ document.documentElement.scrollLeft;
}
};
function getMouseY(e){
if(e!=null && typeof(e.pageY)!="undefined"){
return e.pageY;
}else{
return (e!=null?e.y:event.y)+ document.documentElement.scrollTop;
}
};
function calculeOffsetLeft(r){
return calculeOffset(r,"offsetLeft")
};
function calculeOffsetTop(r){
return calculeOffset(r,"offsetTop")
};
function calculeOffset(element,attr){
var offset=0;
while(element){
offset+=element[attr];
element=element.offsetParent
}
return offset;
};
/** return the computed style
* @param: elem: the reference to the element
* @param: prop: the name of the css property
*/
function get_css_property(elem, prop)
{
if(document.defaultView)
{
return document.defaultView.getComputedStyle(elem, null).getPropertyValue(prop);
}
else if(elem.currentStyle)
{
var prop = prop.replace(/-\D/gi, function(sMatch)
{
return sMatch.charAt(sMatch.length - 1).toUpperCase();
});
return elem.currentStyle[prop];
}
else return null;
}
/****
* Moving an element
***/
var _mCE; // currently moving element
/* allow to move an element in a window
e: the event
id: the id of the element
frame: the frame of the element
ex of use:
in html: <img id='move_area_search_replace' onmousedown='return parent.start_move_element(event,"area_search_replace", parent.frames["this_frame_id"]);' .../>
or
in javascript: document.getElementById("my_div").onmousedown= start_move_element
*/
function start_move_element(e, id, frame){
var elem_id=(e.target || e.srcElement).id;
if(id)
elem_id=id;
if(!frame)
frame=window;
if(frame.event)
e=frame.event;
_mCE= frame.document.getElementById(elem_id);
_mCE.frame=frame;
frame.document.onmousemove= move_element;
frame.document.onmouseup= end_move_element;
/*_mCE.onmousemove= move_element;
_mCE.onmouseup= end_move_element;*/
//alert(_mCE.frame.document.body.offsetHeight);
mouse_x= getMouseX(e);
mouse_y= getMouseY(e);
//window.status=frame+ " elem: "+elem_id+" elem: "+ _mCE + " mouse_x: "+mouse_x;
_mCE.start_pos_x = mouse_x - (_mCE.style.left.replace("px","") || calculeOffsetLeft(_mCE));
_mCE.start_pos_y = mouse_y - (_mCE.style.top.replace("px","") || calculeOffsetTop(_mCE));
return false;
};
function end_move_element(e){
_mCE.frame.document.onmousemove= "";
_mCE.frame.document.onmouseup= "";
_mCE=null;
};
function move_element(e){
var newTop,newLeft,maxLeft;
if( _mCE.frame && _mCE.frame.event )
e=_mCE.frame.event;
newTop = getMouseY(e) - _mCE.start_pos_y;
newLeft = getMouseX(e) - _mCE.start_pos_x;
maxLeft = _mCE.frame.document.body.offsetWidth- _mCE.offsetWidth;
max_top = _mCE.frame.document.body.offsetHeight- _mCE.offsetHeight;
newTop = Math.min(Math.max(0, newTop), max_top);
newLeft = Math.min(Math.max(0, newLeft), maxLeft);
_mCE.style.top = newTop+"px";
_mCE.style.left = newLeft+"px";
return false;
};
/***
* Managing a textarea (this part need the navigator infos from editAreaLoader
***/
var nav= editAreaLoader.nav;
// allow to get infos on the selection: array(start, end)
function getSelectionRange(textarea){
return {"start": textarea.selectionStart, "end": textarea.selectionEnd};
};
// allow to set the selection
function setSelectionRange(t, start, end){
t.focus();
start = Math.max(0, Math.min(t.value.length, start));
end = Math.max(start, Math.min(t.value.length, end));
if( nav.isOpera && nav.isOpera < 9.6 ){ // Opera bug when moving selection start and selection end
t.selectionEnd = 1;
t.selectionStart = 0;
t.selectionEnd = 1;
t.selectionStart = 0;
}
t.selectionStart = start;
t.selectionEnd = end;
//textarea.setSelectionRange(start, end);
if(nav.isIE)
set_IE_selection(t);
};
// set IE position in Firefox mode (textarea.selectionStart and textarea.selectionEnd). should work as a repeated task
function get_IE_selection(t){
var d=document,div,range,stored_range,elem,scrollTop,relative_top,line_start,line_nb,range_start,range_end,tab;
if(t && t.focused)
{
if(!t.ea_line_height)
{ // calculate the lineHeight
div= d.createElement("div");
div.style.fontFamily= get_css_property(t, "font-family");
div.style.fontSize= get_css_property(t, "font-size");
div.style.visibility= "hidden";
div.innerHTML="0";
d.body.appendChild(div);
t.ea_line_height= div.offsetHeight;
d.body.removeChild(div);
}
//t.focus();
range = d.selection.createRange();
try
{
stored_range = range.duplicate();
stored_range.moveToElementText( t );
stored_range.setEndPoint( 'EndToEnd', range );
if(stored_range.parentElement() == t){
// the range don't take care of empty lines in the end of the selection
elem = t;
scrollTop = 0;
while(elem.parentNode){
scrollTop+= elem.scrollTop;
elem = elem.parentNode;
}
// var scrollTop= t.scrollTop + document.body.scrollTop;
// var relative_top= range.offsetTop - calculeOffsetTop(t) + scrollTop;
relative_top= range.offsetTop - calculeOffsetTop(t)+ scrollTop;
// alert("rangeoffset: "+ range.offsetTop +"\ncalcoffsetTop: "+ calculeOffsetTop(t) +"\nrelativeTop: "+ relative_top);
line_start = Math.round((relative_top / t.ea_line_height) +1);
line_nb = Math.round(range.boundingHeight / t.ea_line_height);
range_start = stored_range.text.length - range.text.length;
tab = t.value.substr(0, range_start).split("\n");
range_start += (line_start - tab.length)*2; // add missing empty lines to the selection
t.selectionStart = range_start;
range_end = t.selectionStart + range.text.length;
tab = t.value.substr(0, range_start + range.text.length).split("\n");
range_end += (line_start + line_nb - 1 - tab.length)*2;
t.selectionEnd = range_end;
}
}
catch(e){}
}
if( t && t.id )
{
setTimeout("get_IE_selection(document.getElementById('"+ t.id +"'));", 50);
}
};
function IE_textarea_focus(){
event.srcElement.focused= true;
}
function IE_textarea_blur(){
event.srcElement.focused= false;
}
// select the text for IE (take into account the \r difference)
function set_IE_selection( t ){
var nbLineStart,nbLineStart,nbLineEnd,range;
if(!window.closed){
nbLineStart=t.value.substr(0, t.selectionStart).split("\n").length - 1;
nbLineEnd=t.value.substr(0, t.selectionEnd).split("\n").length - 1;
try
{
range = document.selection.createRange();
range.moveToElementText( t );
range.setEndPoint( 'EndToStart', range );
range.moveStart('character', t.selectionStart - nbLineStart);
range.moveEnd('character', t.selectionEnd - nbLineEnd - (t.selectionStart - nbLineStart) );
range.select();
}
catch(e){}
}
};
editAreaLoader.waiting_loading["elements_functions.js"]= "loaded";
/****
* This page contains some general usefull functions for javascript
*
****/
// need to redefine this functiondue to IE problem
function getAttribute( elm, aName ) {
var aValue,taName,i;
try{
aValue = elm.getAttribute( aName );
}catch(exept){}
if( ! aValue ){
for( i = 0; i < elm.attributes.length; i ++ ) {
taName = elm.attributes[i] .name.toLowerCase();
if( taName == aName ) {
aValue = elm.attributes[i] .value;
return aValue;
}
}
}
return aValue;
};
// need to redefine this function due to IE problem
function setAttribute( elm, attr, val ) {
if(attr=="class"){
elm.setAttribute("className", val);
elm.setAttribute("class", val);
}else{
elm.setAttribute(attr, val);
}
};
/* return a child element
elem: element we are searching in
elem_type: type of the eleemnt we are searching (DIV, A, etc...)
elem_attribute: attribute of the searched element that must match
elem_attribute_match: value that elem_attribute must match
option: "all" if must return an array of all children, otherwise return the first match element
depth: depth of search (-1 or no set => unlimited)
*/
function getChildren(elem, elem_type, elem_attribute, elem_attribute_match, option, depth)
{
if(!option)
var option="single";
if(!depth)
var depth=-1;
if(elem){
var children= elem.childNodes;
var result=null;
var results= [];
for (var x=0;x<children.length;x++) {
strTagName = new String(children[x].tagName);
children_class="?";
if(strTagName!= "undefined"){
child_attribute= getAttribute(children[x],elem_attribute);
if((strTagName.toLowerCase()==elem_type.toLowerCase() || elem_type=="") && (elem_attribute=="" || child_attribute==elem_attribute_match)){
if(option=="all"){
results.push(children[x]);
}else{
return children[x];
}
}
if(depth!=0){
result=getChildren(children[x], elem_type, elem_attribute, elem_attribute_match, option, depth-1);
if(option=="all"){
if(result.length>0){
results= results.concat(result);
}
}else if(result!=null){
return result;
}
}
}
}
if(option=="all")
return results;
}
return null;
};
function isChildOf(elem, parent){
if(elem){
if(elem==parent)
return true;
while(elem.parentNode != 'undefined'){
return isChildOf(elem.parentNode, parent);
}
}
return false;
};
function getMouseX(e){
if(e!=null && typeof(e.pageX)!="undefined"){
return e.pageX;
}else{
return (e!=null?e.x:event.x)+ document.documentElement.scrollLeft;
}
};
function getMouseY(e){
if(e!=null && typeof(e.pageY)!="undefined"){
return e.pageY;
}else{
return (e!=null?e.y:event.y)+ document.documentElement.scrollTop;
}
};
function calculeOffsetLeft(r){
return calculeOffset(r,"offsetLeft")
};
function calculeOffsetTop(r){
return calculeOffset(r,"offsetTop")
};
function calculeOffset(element,attr){
var offset=0;
while(element){
offset+=element[attr];
element=element.offsetParent
}
return offset;
};
/** return the computed style
* @param: elem: the reference to the element
* @param: prop: the name of the css property
*/
function get_css_property(elem, prop)
{
if(document.defaultView)
{
return document.defaultView.getComputedStyle(elem, null).getPropertyValue(prop);
}
else if(elem.currentStyle)
{
var prop = prop.replace(/-\D/gi, function(sMatch)
{
return sMatch.charAt(sMatch.length - 1).toUpperCase();
});
return elem.currentStyle[prop];
}
else return null;
}
/****
* Moving an element
***/
var _mCE; // currently moving element
/* allow to move an element in a window
e: the event
id: the id of the element
frame: the frame of the element
ex of use:
in html: <img id='move_area_search_replace' onmousedown='return parent.start_move_element(event,"area_search_replace", parent.frames["this_frame_id"]);' .../>
or
in javascript: document.getElementById("my_div").onmousedown= start_move_element
*/
function start_move_element(e, id, frame){
var elem_id=(e.target || e.srcElement).id;
if(id)
elem_id=id;
if(!frame)
frame=window;
if(frame.event)
e=frame.event;
_mCE= frame.document.getElementById(elem_id);
_mCE.frame=frame;
frame.document.onmousemove= move_element;
frame.document.onmouseup= end_move_element;
/*_mCE.onmousemove= move_element;
_mCE.onmouseup= end_move_element;*/
//alert(_mCE.frame.document.body.offsetHeight);
mouse_x= getMouseX(e);
mouse_y= getMouseY(e);
//window.status=frame+ " elem: "+elem_id+" elem: "+ _mCE + " mouse_x: "+mouse_x;
_mCE.start_pos_x = mouse_x - (_mCE.style.left.replace("px","") || calculeOffsetLeft(_mCE));
_mCE.start_pos_y = mouse_y - (_mCE.style.top.replace("px","") || calculeOffsetTop(_mCE));
return false;
};
function end_move_element(e){
_mCE.frame.document.onmousemove= "";
_mCE.frame.document.onmouseup= "";
_mCE=null;
};
function move_element(e){
var newTop,newLeft,maxLeft;
if( _mCE.frame && _mCE.frame.event )
e=_mCE.frame.event;
newTop = getMouseY(e) - _mCE.start_pos_y;
newLeft = getMouseX(e) - _mCE.start_pos_x;
maxLeft = _mCE.frame.document.body.offsetWidth- _mCE.offsetWidth;
max_top = _mCE.frame.document.body.offsetHeight- _mCE.offsetHeight;
newTop = Math.min(Math.max(0, newTop), max_top);
newLeft = Math.min(Math.max(0, newLeft), maxLeft);
_mCE.style.top = newTop+"px";
_mCE.style.left = newLeft+"px";
return false;
};
/***
* Managing a textarea (this part need the navigator infos from editAreaLoader
***/
var nav= editAreaLoader.nav;
// allow to get infos on the selection: array(start, end)
function getSelectionRange(textarea){
return {"start": textarea.selectionStart, "end": textarea.selectionEnd};
};
// allow to set the selection
function setSelectionRange(t, start, end){
t.focus();
start = Math.max(0, Math.min(t.value.length, start));
end = Math.max(start, Math.min(t.value.length, end));
if( nav.isOpera && nav.isOpera < 9.6 ){ // Opera bug when moving selection start and selection end
t.selectionEnd = 1;
t.selectionStart = 0;
t.selectionEnd = 1;
t.selectionStart = 0;
}
t.selectionStart = start;
t.selectionEnd = end;
//textarea.setSelectionRange(start, end);
if(nav.isIE)
set_IE_selection(t);
};
// set IE position in Firefox mode (textarea.selectionStart and textarea.selectionEnd). should work as a repeated task
function get_IE_selection(t){
var d=document,div,range,stored_range,elem,scrollTop,relative_top,line_start,line_nb,range_start,range_end,tab;
if(t && t.focused)
{
if(!t.ea_line_height)
{ // calculate the lineHeight
div= d.createElement("div");
div.style.fontFamily= get_css_property(t, "font-family");
div.style.fontSize= get_css_property(t, "font-size");
div.style.visibility= "hidden";
div.innerHTML="0";
d.body.appendChild(div);
t.ea_line_height= div.offsetHeight;
d.body.removeChild(div);
}
//t.focus();
range = d.selection.createRange();
try
{
stored_range = range.duplicate();
stored_range.moveToElementText( t );
stored_range.setEndPoint( 'EndToEnd', range );
if(stored_range.parentElement() == t){
// the range don't take care of empty lines in the end of the selection
elem = t;
scrollTop = 0;
while(elem.parentNode){
scrollTop+= elem.scrollTop;
elem = elem.parentNode;
}
// var scrollTop= t.scrollTop + document.body.scrollTop;
// var relative_top= range.offsetTop - calculeOffsetTop(t) + scrollTop;
relative_top= range.offsetTop - calculeOffsetTop(t)+ scrollTop;
// alert("rangeoffset: "+ range.offsetTop +"\ncalcoffsetTop: "+ calculeOffsetTop(t) +"\nrelativeTop: "+ relative_top);
line_start = Math.round((relative_top / t.ea_line_height) +1);
line_nb = Math.round(range.boundingHeight / t.ea_line_height);
range_start = stored_range.text.length - range.text.length;
tab = t.value.substr(0, range_start).split("\n");
range_start += (line_start - tab.length)*2; // add missing empty lines to the selection
t.selectionStart = range_start;
range_end = t.selectionStart + range.text.length;
tab = t.value.substr(0, range_start + range.text.length).split("\n");
range_end += (line_start + line_nb - 1 - tab.length)*2;
t.selectionEnd = range_end;
}
}
catch(e){}
}
if( t && t.id )
{
setTimeout("get_IE_selection(document.getElementById('"+ t.id +"'));", 50);
}
};
function IE_textarea_focus(){
event.srcElement.focused= true;
}
function IE_textarea_blur(){
event.srcElement.focused= false;
}
// select the text for IE (take into account the \r difference)
function set_IE_selection( t ){
var nbLineStart,nbLineStart,nbLineEnd,range;
if(!window.closed){
nbLineStart=t.value.substr(0, t.selectionStart).split("\n").length - 1;
nbLineEnd=t.value.substr(0, t.selectionEnd).split("\n").length - 1;
try
{
range = document.selection.createRange();
range.moveToElementText( t );
range.setEndPoint( 'EndToStart', range );
range.moveStart('character', t.selectionStart - nbLineStart);
range.moveEnd('character', t.selectionEnd - nbLineEnd - (t.selectionStart - nbLineStart) );
range.select();
}
catch(e){}
}
};
editAreaLoader.waiting_loading["elements_functions.js"]= "loaded";
+408 -407
View File
@@ -1,407 +1,408 @@
// change_to: "on" or "off"
EditArea.prototype.change_highlight= function(change_to){
if(this.settings["syntax"].length==0 && change_to==false){
this.switchClassSticky(_$("highlight"), 'editAreaButtonDisabled', true);
this.switchClassSticky(_$("reset_highlight"), 'editAreaButtonDisabled', true);
return false;
}
if(this.do_highlight==change_to)
return false;
this.getIESelection();
var pos_start= this.textarea.selectionStart;
var pos_end= this.textarea.selectionEnd;
if(this.do_highlight===true || change_to==false)
this.disable_highlight();
else
this.enable_highlight();
this.textarea.focus();
this.textarea.selectionStart = pos_start;
this.textarea.selectionEnd = pos_end;
this.setIESelection();
};
EditArea.prototype.disable_highlight= function(displayOnly){
var t= this, a=t.textarea, new_Obj, old_class, new_class;
t.selection_field.innerHTML="";
t.selection_field_text.innerHTML="";
t.content_highlight.style.visibility="hidden";
// replacing the node is far more faster than deleting it's content in firefox
new_Obj= t.content_highlight.cloneNode(false);
new_Obj.innerHTML= "";
t.content_highlight.parentNode.insertBefore(new_Obj, t.content_highlight);
t.content_highlight.parentNode.removeChild(t.content_highlight);
t.content_highlight= new_Obj;
old_class= parent.getAttribute( a,"class" );
if(old_class){
new_class= old_class.replace( "hidden","" );
parent.setAttribute( a, "class", new_class );
}
a.style.backgroundColor="transparent"; // needed in order to see the bracket finders
//var icon= document.getElementById("highlight");
//setAttribute(icon, "class", getAttribute(icon, "class").replace(/ selected/g, "") );
//t.restoreClass(icon);
//t.switchClass(icon,'editAreaButtonNormal');
t.switchClassSticky(_$("highlight"), 'editAreaButtonNormal', true);
t.switchClassSticky(_$("reset_highlight"), 'editAreaButtonDisabled', true);
t.do_highlight=false;
t.switchClassSticky(_$("change_smooth_selection"), 'editAreaButtonSelected', true);
if(typeof(t.smooth_selection_before_highlight)!="undefined" && t.smooth_selection_before_highlight===false){
t.change_smooth_selection_mode(false);
}
// this.textarea.style.backgroundColor="#FFFFFF";
};
EditArea.prototype.enable_highlight= function(){
var t=this, a=t.textarea, new_class;
t.show_waiting_screen();
t.content_highlight.style.visibility="visible";
new_class =parent.getAttribute(a,"class")+" hidden";
parent.setAttribute( a, "class", new_class );
// IE can't manage mouse click outside text range without this
if( t.isIE )
a.style.backgroundColor="#FFFFFF";
t.switchClassSticky(_$("highlight"), 'editAreaButtonSelected', false);
t.switchClassSticky(_$("reset_highlight"), 'editAreaButtonNormal', false);
t.smooth_selection_before_highlight=t.smooth_selection;
if(!t.smooth_selection)
t.change_smooth_selection_mode(true);
t.switchClassSticky(_$("change_smooth_selection"), 'editAreaButtonDisabled', true);
t.do_highlight=true;
t.resync_highlight();
t.hide_waiting_screen();
};
/**
* Ask to update highlighted text
* @param Array infos - Array of datas returned by EditArea.get_selection_infos()
*/
EditArea.prototype.maj_highlight= function(infos){
// for speed mesure
var debug_opti="",tps_start= new Date().getTime(), tps_middle_opti=new Date().getTime();
var t=this, hightlighted_text, updated_highlight;
var textToHighlight=infos["full_text"], doSyntaxOpti = false, doHtmlOpti = false, stay_begin="", stay_end="", trace_new , trace_last;
if(t.last_text_to_highlight==infos["full_text"] && t.resync_highlight!==true)
return;
// OPTIMISATION: will search to update only changed lines
if(t.reload_highlight===true){
t.reload_highlight=false;
}else if(textToHighlight.length==0){
textToHighlight="\n ";
}else{
// get text change datas
changes = t.checkTextEvolution(t.last_text_to_highlight,textToHighlight);
// check if it can only reparse the changed text
trace_new = t.get_syntax_trace(changes.newTextLine).replace(/\r/g, '');
trace_last = t.get_syntax_trace(changes.lastTextLine).replace(/\r/g, '');
doSyntaxOpti = ( trace_new == trace_last );
// check if the difference comes only from a new line created
// => we have to remember that the editor can automaticaly add tabulation or space after the new line)
if( !doSyntaxOpti && trace_new == "\n"+trace_last && /^[ \t\s]*\n[ \t\s]*$/.test( changes.newText.replace(/\r/g, '') ) && changes.lastText =="" )
{
doSyntaxOpti = true;
}
// we do the syntax optimisation
if( doSyntaxOpti ){
tps_middle_opti=new Date().getTime();
stay_begin= t.last_hightlighted_text.split("\n").slice(0, changes.lineStart).join("\n");
if(changes.lineStart>0)
stay_begin+= "\n";
stay_end= t.last_hightlighted_text.split("\n").slice(changes.lineLastEnd+1).join("\n");
if(stay_end.length>0)
stay_end= "\n"+stay_end;
// Final check to see that we're not in the middle of span tags
if( stay_begin.split('<span').length != stay_begin.split('</span').length
|| stay_end.split('<span').length != stay_end.split('</span').length )
{
doSyntaxOpti = false;
stay_end = '';
stay_begin = '';
}
else
{
if(stay_begin.length==0 && changes.posLastEnd==-1)
changes.newTextLine+="\n";
textToHighlight=changes.newTextLine;
}
}
if(t.settings["debug"]){
var ch =changes;
debug_opti= ( doSyntaxOpti?"Optimisation": "No optimisation" )
+" start: "+ch.posStart +"("+ch.lineStart+")"
+" end_new: "+ ch.posNewEnd+"("+ch.lineNewEnd+")"
+" end_last: "+ ch.posLastEnd+"("+ch.lineLastEnd+")"
+"\nchanged_text: "+ch.newText+" => trace: "+trace_new
+"\nchanged_last_text: "+ch.lastText+" => trace: "+trace_last
//debug_opti+= "\nchanged: "+ infos["full_text"].substring(ch.posStart, ch.posNewEnd);
+ "\nchanged_line: "+ch.newTextLine
+ "\nlast_changed_line: "+ch.lastTextLine
+"\nstay_begin: "+ stay_begin.slice(-100)
+"\nstay_end: "+ stay_end.substr( 0, 100 );
//debug_opti="start: "+stay_begin_len+ "("+nb_line_start_unchanged+") end: "+ (stay_end_len)+ "("+(splited.length-nb_line_end_unchanged)+") ";
//debug_opti+="changed: "+ textToHighlight.substring(stay_begin_len, textToHighlight.length-stay_end_len)+" \n";
//debug_opti+="changed: "+ stay_begin.substr(stay_begin.length-200)+ "----------"+ textToHighlight+"------------------"+ stay_end.substr(0,200) +"\n";
+"\n";
}
// END OPTIMISATION
}
tps_end_opti = new Date().getTime();
// apply highlight
updated_highlight = t.colorize_text(textToHighlight);
tpsAfterReg = new Date().getTime();
/***
* see if we can optimize for updating only the required part of the HTML code
*
* The goal here will be to find the text node concerned by the modification and to update it
*/
//-------------------------------------------
// disable latest optimization tricks (introduced in 0.8.1 and removed in 0.8.2), TODO: check for another try later
doSyntaxOpti = doHtmlOpti = false;
if( doSyntaxOpti )
{
try
{
var replacedBloc, i, nbStart = '', nbEnd = '', newHtml, lengthOld, lengthNew;
replacedBloc = t.last_hightlighted_text.substring( stay_begin.length, t.last_hightlighted_text.length - stay_end.length );
lengthOld = replacedBloc.length;
lengthNew = updated_highlight.length;
// find the identical caracters at the beginning
for( i=0; i < lengthOld && i < lengthNew && replacedBloc.charAt(i) == updated_highlight.charAt(i) ; i++ )
{
}
nbStart = i;
// find the identical caracters at the end
for( i=0; i + nbStart < lengthOld && i + nbStart < lengthNew && replacedBloc.charAt(lengthOld-i-1) == updated_highlight.charAt(lengthNew-i-1) ; i++ )
{
}
nbEnd = i;
//console.log( nbStart, nbEnd, replacedBloc, updated_highlight );
// get the changes
lastHtml = replacedBloc.substring( nbStart, lengthOld - nbEnd );
newHtml = updated_highlight.substring( nbStart, lengthNew - nbEnd );
// We can do the optimisation only if we havn't touch to span elements
if( newHtml.indexOf('<span') == -1 && newHtml.indexOf('</span') == -1
&& lastHtml.indexOf('<span') == -1 && lastHtml.indexOf('</span') == -1 )
{
var beginStr, nbOpendedSpan, nbClosedSpan, nbUnchangedChars, span, textNode;
doHtmlOpti = true;
beginStr = t.last_hightlighted_text.substr( 0, stay_begin.length + nbStart );
// fix special chars
newHtml = newHtml.replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&');
nbOpendedSpan = beginStr.split('<span').length - 1;
nbClosedSpan = beginStr.split('</span').length - 1;
// retrieve the previously opened span (Add 1 for the first level span?)
span = t.content_highlight.getElementsByTagName('span')[ nbOpendedSpan ];
//--------[
// get the textNode to update
// if we're inside a span, we'll take the one that is opened (can be a parent of the current span)
parentSpan = span;
maxStartOffset = maxEndOffset = 0;
// it will be in the child of the root node
if( nbOpendedSpan == nbClosedSpan )
{
while( parentSpan.parentNode != t.content_highlight && parentSpan.parentNode.tagName != 'PRE' )
{
parentSpan = parentSpan.parentNode;
}
}
// get the last opened span
else
{
maxStartOffset = maxEndOffset = beginStr.length + 1;
// move to parent node for each closed span found after the lastest open span
nbClosed = beginStr.substr( Math.max( 0, beginStr.lastIndexOf( '<span', maxStartOffset - 1 ) ) ).split('</span').length - 1;
while( nbClosed > 0 )
{
nbClosed--;
parentSpan = parentSpan.parentNode;
}
// find the position of the last opended tag
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 ) ) ) )
{
maxStartOffset = tmpMaxStartOffset;
maxEndOffset = tmpMaxEndOffset;
}
}
// Note: maxEndOffset is no more used but maxStartOffset will be used
if( parentSpan.parentNode == t.content_highlight || parentSpan.parentNode.tagName == 'PRE' )
{
maxStartOffset = Math.max( 0, beginStr.indexOf( '<span' ) );
}
// find the matching text node (this will be one that will be at the end of the beginStr
if( maxStartOffset == beginStr.length )
{
nbSubSpanBefore = 0;
}
else
{
lastEndPos = Math.max( 0, beginStr.lastIndexOf( '>', maxStartOffset ) );
// count the number of sub spans
nbSubSpanBefore = beginStr.substr( lastEndPos ).split('<span').length-1;
}
// there is no sub-span before
if( nbSubSpanBefore == 0 )
{
textNode = parentSpan.firstChild;
}
// we need to find where is the text node modified
else
{
// take the last direct child (no sub-child)
lastSubSpan = parentSpan.getElementsByTagName('span')[ nbSubSpanBefore - 1 ];
while( lastSubSpan.parentNode != parentSpan )
{
lastSubSpan = lastSubSpan.parentNode;
}
// associate to next text node following the last sub span
if( lastSubSpan.nextSibling == null || lastSubSpan.nextSibling.nodeType != 3 )
{
textNode = document.createTextNode('');
lastSubSpan.parentNode.insertBefore( textNode, lastSubSpan.nextSibling );
}
else
{
textNode = lastSubSpan.nextSibling;
}
}
//--------]
//--------[
// update the textNode content
// number of caracters after the last opened of closed span
//nbUnchangedChars = ( lastIndex = beginStr.lastIndexOf( '>' ) ) == -1 ? beginStr.length : beginStr.length - ( lastIndex + 1 );
//nbUnchangedChars = ? beginStr.length : beginStr.substr( lastIndex + 1 ).replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&').length;
if( ( lastIndex = beginStr.lastIndexOf( '>' ) ) == -1 )
{
nbUnchangedChars = beginStr.length;
}
else
{
nbUnchangedChars = beginStr.substr( lastIndex + 1 ).replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&').length;
//nbUnchangedChars += beginStr.substr( ).replace( /&/g, '&amp;').replace( /</g, '&lt;').replace( />/g, '&gt;').length - beginStr.length;
}
//alert( nbUnchangedChars );
// console.log( span, textNode, nbOpendedSpan,nbClosedSpan, span.nextSibling, textNode.length, nbUnchangedChars, lastHtml, lastHtml.length, newHtml, newHtml.length );
// alert( textNode.parentNode.className +'-'+ textNode.parentNode.tagName+"\n"+ textNode.data +"\n"+ nbUnchangedChars +"\n"+ lastHtml.length +"\n"+ newHtml +"\n"+ newHtml.length );
// 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') );
// console.log( textNode.data.replace(/&/g, '&amp;') );
// IE only manage \r for cariage return in textNode and not \n or \r\n
if( t.isIE )
{
nbUnchangedChars -= ( beginStr.substr( beginStr.length - nbUnchangedChars ).split("\n").length - 1 );
//alert( textNode.data.replace(/\r/g, '_r').replace(/\n/g, '_n'));
textNode.replaceData( nbUnchangedChars, lastHtml.replace(/\n/g, '').length, newHtml.replace(/\n/g, '') );
}
else
{
textNode.replaceData( nbUnchangedChars, lastHtml.length, newHtml );
}
//--------]
}
}
// an exception shouldn't occured but if replaceData failed at least it won't break everything
catch( e )
{
// throw e;
// console.log( e );
doHtmlOpti = false;
}
}
/*** END HTML update's optimisation ***/
// end test
// console.log( (TPS6-TPS5), (TPS5-TPS4), (TPS4-TPS3), (TPS3-TPS2), (TPS2-TPS1), _CPT );
// get the new highlight content
tpsAfterOpti2 = new Date().getTime();
hightlighted_text = stay_begin + updated_highlight + stay_end;
if( !doHtmlOpti )
{
// 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*))
var new_Obj= t.content_highlight.cloneNode(false);
if( ( t.isIE && t.isIE < 8 ) || ( t.isOpera && t.isOpera < 9.6 ) )
new_Obj.innerHTML= "<pre><span class='"+ t.settings["syntax"] +"'>" + hightlighted_text + "</span></pre>";
else
new_Obj.innerHTML= "<span class='"+ t.settings["syntax"] +"'>"+ hightlighted_text +"</span>";
t.content_highlight.parentNode.replaceChild(new_Obj, t.content_highlight);
t.content_highlight= new_Obj;
}
t.last_text_to_highlight= infos["full_text"];
t.last_hightlighted_text= hightlighted_text;
tps3=new Date().getTime();
if(t.settings["debug"]){
//lineNumber=tab_text.length;
//t.debug.value+=" \nNB char: "+_$("src").value.length+" Nb line: "+ lineNumber;
t.debug.value= "Tps optimisation "+(tps_end_opti-tps_start)
+" | tps reg exp: "+ (tpsAfterReg-tps_end_opti)
+" | tps opti HTML : "+ (tpsAfterOpti2-tpsAfterReg) + ' '+ ( doHtmlOpti ? 'yes' : 'no' )
+" | tps update highlight content: "+ (tps3-tpsAfterOpti2)
+" | tpsTotal: "+ (tps3-tps_start)
+ "("+tps3+")\n"+ debug_opti;
// t.debug.value+= "highlight\n"+hightlighted_text;*/
}
};
EditArea.prototype.resync_highlight= function(reload_now){
this.reload_highlight=true;
this.last_text_to_highlight="";
this.focus();
if(reload_now)
this.check_line_selection(false);
};
// change_to: "on" or "off"
EditArea.prototype.change_highlight= function(change_to){
if(this.settings["syntax"].length==0 && change_to==false){
this.switchClassSticky(_$("highlight"), 'editAreaButtonDisabled', true);
this.switchClassSticky(_$("reset_highlight"), 'editAreaButtonDisabled', true);
return false;
}
if(this.do_highlight==change_to)
return false;
this.getIESelection();
var pos_start= this.textarea.selectionStart;
var pos_end= this.textarea.selectionEnd;
if(this.do_highlight===true || change_to==false)
this.disable_highlight();
else
this.enable_highlight();
this.textarea.focus();
this.textarea.selectionStart = pos_start;
this.textarea.selectionEnd = pos_end;
this.setIESelection();
};
EditArea.prototype.disable_highlight= function(displayOnly){
var t= this, a=t.textarea, new_Obj, old_class, new_class;
t.selection_field.innerHTML="";
t.selection_field_text.innerHTML="";
t.content_highlight.style.visibility="hidden";
// replacing the node is far more faster than deleting it's content in firefox
new_Obj= t.content_highlight.cloneNode(false);
new_Obj.innerHTML= "";
t.content_highlight.parentNode.insertBefore(new_Obj, t.content_highlight);
t.content_highlight.parentNode.removeChild(t.content_highlight);
t.content_highlight= new_Obj;
old_class= parent.getAttribute( a,"class" );
if(old_class){
new_class= old_class.replace( "hidden","" );
parent.setAttribute( a, "class", new_class );
}
a.style.backgroundColor="transparent"; // needed in order to see the bracket finders
//var icon= document.getElementById("highlight");
//setAttribute(icon, "class", getAttribute(icon, "class").replace(/ selected/g, "") );
//t.restoreClass(icon);
//t.switchClass(icon,'editAreaButtonNormal');
t.switchClassSticky(_$("highlight"), 'editAreaButtonNormal', true);
t.switchClassSticky(_$("reset_highlight"), 'editAreaButtonDisabled', true);
t.do_highlight=false;
t.switchClassSticky(_$("change_smooth_selection"), 'editAreaButtonSelected', true);
if(typeof(t.smooth_selection_before_highlight)!="undefined" && t.smooth_selection_before_highlight===false){
t.change_smooth_selection_mode(false);
}
// this.textarea.style.backgroundColor="#FFFFFF";
};
EditArea.prototype.enable_highlight= function(){
var t=this, a=t.textarea, new_class;
t.show_waiting_screen();
t.content_highlight.style.visibility="visible";
new_class =parent.getAttribute(a,"class")+" hidden";
parent.setAttribute( a, "class", new_class );
// IE can't manage mouse click outside text range without this
if( t.isIE )
a.style.backgroundColor="#FFFFFF";
t.switchClassSticky(_$("highlight"), 'editAreaButtonSelected', false);
t.switchClassSticky(_$("reset_highlight"), 'editAreaButtonNormal', false);
t.smooth_selection_before_highlight=t.smooth_selection;
if(!t.smooth_selection)
t.change_smooth_selection_mode(true);
t.switchClassSticky(_$("change_smooth_selection"), 'editAreaButtonDisabled', true);
t.do_highlight=true;
t.resync_highlight();
t.hide_waiting_screen();
};
/**
* Ask to update highlighted text
* @param Array infos - Array of datas returned by EditArea.get_selection_infos()
*/
EditArea.prototype.maj_highlight= function(infos){
// for speed mesure
var debug_opti="",tps_start= new Date().getTime(), tps_middle_opti=new Date().getTime();
var t=this, hightlighted_text, updated_highlight;
var textToHighlight=infos["full_text"], doSyntaxOpti = false, doHtmlOpti = false, stay_begin="", stay_end="", trace_new , trace_last;
if(t.last_text_to_highlight==infos["full_text"] && t.resync_highlight!==true)
return;
// OPTIMISATION: will search to update only changed lines
if(t.reload_highlight===true){
t.reload_highlight=false;
}else if(textToHighlight.length==0){
textToHighlight="\n ";
}else{
// get text change datas
changes = t.checkTextEvolution(t.last_text_to_highlight,textToHighlight);
// check if it can only reparse the changed text
trace_new = t.get_syntax_trace(changes.newTextLine).replace(/\r/g, '');
trace_last = t.get_syntax_trace(changes.lastTextLine).replace(/\r/g, '');
doSyntaxOpti = ( trace_new == trace_last );
// check if the difference comes only from a new line created
// => we have to remember that the editor can automaticaly add tabulation or space after the new line)
if( !doSyntaxOpti && trace_new == "\n"+trace_last && /^[ \t\s]*\n[ \t\s]*$/.test( changes.newText.replace(/\r/g, '') ) && changes.lastText =="" )
{
doSyntaxOpti = true;
}
// we do the syntax optimisation
if( doSyntaxOpti ){
tps_middle_opti=new Date().getTime();
stay_begin= t.last_hightlighted_text.split("\n").slice(0, changes.lineStart).join("\n");
if(changes.lineStart>0)
stay_begin+= "\n";
stay_end= t.last_hightlighted_text.split("\n").slice(changes.lineLastEnd+1).join("\n");
if(stay_end.length>0)
stay_end= "\n"+stay_end;
// Final check to see that we're not in the middle of span tags
if( stay_begin.split('<span').length != stay_begin.split('</span').length
|| stay_end.split('<span').length != stay_end.split('</span').length )
{
doSyntaxOpti = false;
stay_end = '';
stay_begin = '';
}
else
{
if(stay_begin.length==0 && changes.posLastEnd==-1)
changes.newTextLine+="\n";
textToHighlight=changes.newTextLine;
}
}
if(t.settings["debug"]){
var ch =changes;
debug_opti= ( doSyntaxOpti?"Optimisation": "No optimisation" )
+" start: "+ch.posStart +"("+ch.lineStart+")"
+" end_new: "+ ch.posNewEnd+"("+ch.lineNewEnd+")"
+" end_last: "+ ch.posLastEnd+"("+ch.lineLastEnd+")"
+"\nchanged_text: "+ch.newText+" => trace: "+trace_new
+"\nchanged_last_text: "+ch.lastText+" => trace: "+trace_last
//debug_opti+= "\nchanged: "+ infos["full_text"].substring(ch.posStart, ch.posNewEnd);
+ "\nchanged_line: "+ch.newTextLine
+ "\nlast_changed_line: "+ch.lastTextLine
+"\nstay_begin: "+ stay_begin.slice(-100)
+"\nstay_end: "+ stay_end.substr( 0, 100 );
//debug_opti="start: "+stay_begin_len+ "("+nb_line_start_unchanged+") end: "+ (stay_end_len)+ "("+(splited.length-nb_line_end_unchanged)+") ";
//debug_opti+="changed: "+ textToHighlight.substring(stay_begin_len, textToHighlight.length-stay_end_len)+" \n";
//debug_opti+="changed: "+ stay_begin.substr(stay_begin.length-200)+ "----------"+ textToHighlight+"------------------"+ stay_end.substr(0,200) +"\n";
+"\n";
}
// END OPTIMISATION
}
tps_end_opti = new Date().getTime();
// apply highlight
updated_highlight = t.colorize_text(textToHighlight);
tpsAfterReg = new Date().getTime();
/***
* see if we can optimize for updating only the required part of the HTML code
*
* The goal here will be to find the text node concerned by the modification and to update it
*/
//-------------------------------------------
// disable latest optimization tricks (introduced in 0.8.1 and removed in 0.8.2), TODO: check for another try later
doSyntaxOpti = doHtmlOpti = false;
if( doSyntaxOpti )
{
try
{
var replacedBloc, i, nbStart = '', nbEnd = '', newHtml, lengthOld, lengthNew;
replacedBloc = t.last_hightlighted_text.substring( stay_begin.length, t.last_hightlighted_text.length - stay_end.length );
lengthOld = replacedBloc.length;
lengthNew = updated_highlight.length;
// find the identical caracters at the beginning
for( i=0; i < lengthOld && i < lengthNew && replacedBloc.charAt(i) == updated_highlight.charAt(i) ; i++ )
{
}
nbStart = i;
// find the identical caracters at the end
for( i=0; i + nbStart < lengthOld && i + nbStart < lengthNew && replacedBloc.charAt(lengthOld-i-1) == updated_highlight.charAt(lengthNew-i-1) ; i++ )
{
}
nbEnd = i;
//console.log( nbStart, nbEnd, replacedBloc, updated_highlight );
// get the changes
lastHtml = replacedBloc.substring( nbStart, lengthOld - nbEnd );
newHtml = updated_highlight.substring( nbStart, lengthNew - nbEnd );
// We can do the optimisation only if we havn't touch to span elements
if( newHtml.indexOf('<span') == -1 && newHtml.indexOf('</span') == -1
&& lastHtml.indexOf('<span') == -1 && lastHtml.indexOf('</span') == -1 )
{
var beginStr, nbOpendedSpan, nbClosedSpan, nbUnchangedChars, span, textNode;
doHtmlOpti = true;
beginStr = t.last_hightlighted_text.substr( 0, stay_begin.length + nbStart );
// fix special chars
newHtml = newHtml.replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&');
nbOpendedSpan = beginStr.split('<span').length - 1;
nbClosedSpan = beginStr.split('</span').length - 1;
// retrieve the previously opened span (Add 1 for the first level span?)
span = t.content_highlight.getElementsByTagName('span')[ nbOpendedSpan ];
//--------[
// get the textNode to update
// if we're inside a span, we'll take the one that is opened (can be a parent of the current span)
parentSpan = span;
maxStartOffset = maxEndOffset = 0;
// it will be in the child of the root node
if( nbOpendedSpan == nbClosedSpan )
{
while( parentSpan.parentNode != t.content_highlight && parentSpan.parentNode.tagName != 'PRE' )
{
parentSpan = parentSpan.parentNode;
}
}
// get the last opened span
else
{
maxStartOffset = maxEndOffset = beginStr.length + 1;
// move to parent node for each closed span found after the lastest open span
nbClosed = beginStr.substr( Math.max( 0, beginStr.lastIndexOf( '<span', maxStartOffset - 1 ) ) ).split('</span').length - 1;
while( nbClosed > 0 )
{
nbClosed--;
parentSpan = parentSpan.parentNode;
}
// find the position of the last opended tag
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 ) ) ) )
{
maxStartOffset = tmpMaxStartOffset;
maxEndOffset = tmpMaxEndOffset;
}
}
// Note: maxEndOffset is no more used but maxStartOffset will be used
if( parentSpan.parentNode == t.content_highlight || parentSpan.parentNode.tagName == 'PRE' )
{
maxStartOffset = Math.max( 0, beginStr.indexOf( '<span' ) );
}
// find the matching text node (this will be one that will be at the end of the beginStr
if( maxStartOffset == beginStr.length )
{
nbSubSpanBefore = 0;
}
else
{
lastEndPos = Math.max( 0, beginStr.lastIndexOf( '>', maxStartOffset ) );
// count the number of sub spans
nbSubSpanBefore = beginStr.substr( lastEndPos ).split('<span').length-1;
}
// there is no sub-span before
if( nbSubSpanBefore == 0 )
{
textNode = parentSpan.firstChild;
}
// we need to find where is the text node modified
else
{
// take the last direct child (no sub-child)
lastSubSpan = parentSpan.getElementsByTagName('span')[ nbSubSpanBefore - 1 ];
while( lastSubSpan.parentNode != parentSpan )
{
lastSubSpan = lastSubSpan.parentNode;
}
// associate to next text node following the last sub span
if( lastSubSpan.nextSibling == null || lastSubSpan.nextSibling.nodeType != 3 )
{
textNode = document.createTextNode('');
lastSubSpan.parentNode.insertBefore( textNode, lastSubSpan.nextSibling );
}
else
{
textNode = lastSubSpan.nextSibling;
}
}
//--------]
//--------[
// update the textNode content
// number of caracters after the last opened of closed span
//nbUnchangedChars = ( lastIndex = beginStr.lastIndexOf( '>' ) ) == -1 ? beginStr.length : beginStr.length - ( lastIndex + 1 );
//nbUnchangedChars = ? beginStr.length : beginStr.substr( lastIndex + 1 ).replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&').length;
if( ( lastIndex = beginStr.lastIndexOf( '>' ) ) == -1 )
{
nbUnchangedChars = beginStr.length;
}
else
{
nbUnchangedChars = beginStr.substr( lastIndex + 1 ).replace( /&lt;/g, '<').replace( /&gt;/g, '>').replace( /&amp;/g, '&').length;
//nbUnchangedChars += beginStr.substr( ).replace( /&/g, '&amp;').replace( /</g, '&lt;').replace( />/g, '&gt;').length - beginStr.length;
}
//alert( nbUnchangedChars );
// console.log( span, textNode, nbOpendedSpan,nbClosedSpan, span.nextSibling, textNode.length, nbUnchangedChars, lastHtml, lastHtml.length, newHtml, newHtml.length );
// alert( textNode.parentNode.className +'-'+ textNode.parentNode.tagName+"\n"+ textNode.data +"\n"+ nbUnchangedChars +"\n"+ lastHtml.length +"\n"+ newHtml +"\n"+ newHtml.length );
// 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') );
// console.log( textNode.data.replace(/&/g, '&amp;') );
// IE only manage \r for cariage return in textNode and not \n or \r\n
if( t.isIE )
{
nbUnchangedChars -= ( beginStr.substr( beginStr.length - nbUnchangedChars ).split("\n").length - 1 );
//alert( textNode.data.replace(/\r/g, '_r').replace(/\n/g, '_n'));
textNode.replaceData( nbUnchangedChars, lastHtml.replace(/\n/g, '').length, newHtml.replace(/\n/g, '') );
}
else
{
textNode.replaceData( nbUnchangedChars, lastHtml.length, newHtml );
}
//--------]
}
}
// an exception shouldn't occured but if replaceData failed at least it won't break everything
catch( e )
{
// throw e;
// console.log( e );
doHtmlOpti = false;
}
}
/*** END HTML update's optimisation ***/
// end test
// console.log( (TPS6-TPS5), (TPS5-TPS4), (TPS4-TPS3), (TPS3-TPS2), (TPS2-TPS1), _CPT );
// get the new highlight content
tpsAfterOpti2 = new Date().getTime();
hightlighted_text = stay_begin + updated_highlight + stay_end;
if( !doHtmlOpti )
{
// 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*))
var new_Obj= t.content_highlight.cloneNode(false);
if( ( t.isIE && t.isIE < 8 ) || ( t.isOpera && t.isOpera < 9.6 ) )
new_Obj.innerHTML= "<pre><span class='"+ t.settings["syntax"] +"'>" + hightlighted_text + "</span></pre>";
else
new_Obj.innerHTML= "<span class='"+ t.settings["syntax"] +"'>"+ hightlighted_text +"</span>";
t.content_highlight.parentNode.replaceChild(new_Obj, t.content_highlight);
t.content_highlight= new_Obj;
}
t.last_text_to_highlight= infos["full_text"];
t.last_hightlighted_text= hightlighted_text;
tps3=new Date().getTime();
if(t.settings["debug"]){
//lineNumber=tab_text.length;
//t.debug.value+=" \nNB char: "+_$("src").value.length+" Nb line: "+ lineNumber;
t.debug.value= "Tps optimisation "+(tps_end_opti-tps_start)
+" | tps reg exp: "+ (tpsAfterReg-tps_end_opti)
+" | tps opti HTML : "+ (tpsAfterOpti2-tpsAfterReg) + ' '+ ( doHtmlOpti ? 'yes' : 'no' )
+" | tps update highlight content: "+ (tps3-tpsAfterOpti2)
+" | tpsTotal: "+ (tps3-tps_start)
+ "("+tps3+")\n"+ debug_opti;
// t.debug.value+= "highlight\n"+hightlighted_text;*/
}
};
EditArea.prototype.resync_highlight= function(reload_now){
this.reload_highlight=true;
this.last_text_to_highlight="";
this.focus();
if(reload_now)
this.check_line_selection(false);
};
+146 -145
View File
@@ -1,145 +1,146 @@
var EA_keys = {8:"Retour arriere",9:"Tabulation",12:"Milieu (pave numerique)",13:"Entrer",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"Verr Maj",27:"Esc",32:"Space",33:"Page up",34:"Page down",35:"End",36:"Begin",37:"Left",38:"Up",39:"Right",40:"Down",44:"Impr ecran",45:"Inser",46:"Suppr",91:"Menu Demarrer Windows / touche pomme Mac",92:"Menu Demarrer Windows",93:"Menu contextuel Windows",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Verr Num",145:"Arret defil"};
function keyDown(e){
if(!e){ // if IE
e=event;
}
// send the event to the plugins
for(var i in editArea.plugins){
if(typeof(editArea.plugins[i].onkeydown)=="function"){
if(editArea.plugins[i].onkeydown(e)===false){ // stop propaging
if(editArea.isIE)
e.keyCode=0;
return false;
}
}
}
var target_id=(e.target || e.srcElement).id;
var use=false;
if (EA_keys[e.keyCode])
letter=EA_keys[e.keyCode];
else
letter=String.fromCharCode(e.keyCode);
var low_letter= letter.toLowerCase();
if(letter=="Page up" && !AltPressed(e) && !editArea.isOpera){
editArea.execCommand("scroll_page", {"dir": "up", "shift": ShiftPressed(e)});
use=true;
}else if(letter=="Page down" && !AltPressed(e) && !editArea.isOpera){
editArea.execCommand("scroll_page", {"dir": "down", "shift": ShiftPressed(e)});
use=true;
}else if(editArea.is_editable==false){
// do nothing but also do nothing else (allow to navigate with page up and page down)
return true;
}else if(letter=="Tabulation" && target_id=="textarea" && !CtrlPressed(e) && !AltPressed(e)){
if(ShiftPressed(e))
editArea.execCommand("invert_tab_selection");
else
editArea.execCommand("tab_selection");
use=true;
if(editArea.isOpera || (editArea.isFirefox && editArea.isMac) ) // opera && firefox mac can't cancel tabulation events...
setTimeout("editArea.execCommand('focus');", 1);
}else if(letter=="Entrer" && target_id=="textarea"){
if(editArea.press_enter())
use=true;
}else if(letter=="Entrer" && target_id=="area_search"){
editArea.execCommand("area_search");
use=true;
}else if(letter=="Esc"){
editArea.execCommand("close_all_inline_popup", e);
use=true;
}else if(CtrlPressed(e) && !AltPressed(e) && !ShiftPressed(e)){
switch(low_letter){
case "f":
editArea.execCommand("area_search");
use=true;
break;
case "r":
editArea.execCommand("area_replace");
use=true;
break;
case "q":
editArea.execCommand("close_all_inline_popup", e);
use=true;
break;
case "h":
editArea.execCommand("change_highlight");
use=true;
break;
case "g":
setTimeout("editArea.execCommand('go_to_line');", 5); // the prompt stop the return false otherwise
use=true;
break;
case "e":
editArea.execCommand("show_help");
use=true;
break;
case "z":
use=true;
editArea.execCommand("undo");
break;
case "y":
use=true;
editArea.execCommand("redo");
break;
default:
break;
}
}
// check to disable the redo possibility if the textarea content change
if(editArea.next.length > 0){
setTimeout("editArea.check_redo();", 10);
}
setTimeout("editArea.check_file_changes();", 10);
if(use){
// in case of a control that sould'nt be used by IE but that is used => THROW a javascript error that will stop key action
if(editArea.isIE)
e.keyCode=0;
return false;
}
//alert("Test: "+ letter + " ("+e.keyCode+") ALT: "+ AltPressed(e) + " CTRL "+ CtrlPressed(e) + " SHIFT "+ ShiftPressed(e));
return true;
};
// return true if Alt key is pressed
function AltPressed(e) {
if (window.event) {
return (window.event.altKey);
} else {
if(e.modifiers)
return (e.altKey || (e.modifiers % 2));
else
return e.altKey;
}
};
// return true if Ctrl key is pressed
function CtrlPressed(e) {
if (window.event) {
return (window.event.ctrlKey);
} else {
return (e.ctrlKey || (e.modifiers==2) || (e.modifiers==3) || (e.modifiers>5));
}
};
// return true if Shift key is pressed
function ShiftPressed(e) {
if (window.event) {
return (window.event.shiftKey);
} else {
return (e.shiftKey || (e.modifiers>3));
}
};
var EA_keys = {8:"Retour arriere",9:"Tabulation",12:"Milieu (pave numerique)",13:"Entrer",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"Verr Maj",27:"Esc",32:"Space",33:"Page up",34:"Page down",35:"End",36:"Begin",37:"Left",38:"Up",39:"Right",40:"Down",44:"Impr ecran",45:"Inser",46:"Suppr",91:"Menu Demarrer Windows / touche pomme Mac",92:"Menu Demarrer Windows",93:"Menu contextuel Windows",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Verr Num",145:"Arret defil"};
function keyDown(e){
if(!e){ // if IE
e=event;
}
// send the event to the plugins
for(var i in editArea.plugins){
if(typeof(editArea.plugins[i].onkeydown)=="function"){
if(editArea.plugins[i].onkeydown(e)===false){ // stop propaging
if(editArea.isIE)
e.keyCode=0;
return false;
}
}
}
var target_id=(e.target || e.srcElement).id;
var use=false;
if (EA_keys[e.keyCode])
letter=EA_keys[e.keyCode];
else
letter=String.fromCharCode(e.keyCode);
var low_letter= letter.toLowerCase();
if(letter=="Page up" && !AltPressed(e) && !editArea.isOpera){
editArea.execCommand("scroll_page", {"dir": "up", "shift": ShiftPressed(e)});
use=true;
}else if(letter=="Page down" && !AltPressed(e) && !editArea.isOpera){
editArea.execCommand("scroll_page", {"dir": "down", "shift": ShiftPressed(e)});
use=true;
}else if(editArea.is_editable==false){
// do nothing but also do nothing else (allow to navigate with page up and page down)
return true;
}else if(letter=="Tabulation" && target_id=="textarea" && !CtrlPressed(e) && !AltPressed(e)){
if(ShiftPressed(e))
editArea.execCommand("invert_tab_selection");
else
editArea.execCommand("tab_selection");
use=true;
if(editArea.isOpera || (editArea.isFirefox && editArea.isMac) ) // opera && firefox mac can't cancel tabulation events...
setTimeout("editArea.execCommand('focus');", 1);
}else if(letter=="Entrer" && target_id=="textarea"){
if(editArea.press_enter())
use=true;
}else if(letter=="Entrer" && target_id=="area_search"){
editArea.execCommand("area_search");
use=true;
}else if(letter=="Esc"){
editArea.execCommand("close_all_inline_popup", e);
use=true;
}else if(CtrlPressed(e) && !AltPressed(e) && !ShiftPressed(e)){
switch(low_letter){
case "f":
editArea.execCommand("area_search");
use=true;
break;
case "r":
editArea.execCommand("area_replace");
use=true;
break;
case "q":
editArea.execCommand("close_all_inline_popup", e);
use=true;
break;
case "h":
editArea.execCommand("change_highlight");
use=true;
break;
case "g":
setTimeout("editArea.execCommand('go_to_line');", 5); // the prompt stop the return false otherwise
use=true;
break;
case "e":
editArea.execCommand("show_help");
use=true;
break;
case "z":
use=true;
editArea.execCommand("undo");
break;
case "y":
use=true;
editArea.execCommand("redo");
break;
default:
break;
}
}
// check to disable the redo possibility if the textarea content change
if(editArea.next.length > 0){
setTimeout("editArea.check_redo();", 10);
}
setTimeout("editArea.check_file_changes();", 10);
if(use){
// in case of a control that sould'nt be used by IE but that is used => THROW a javascript error that will stop key action
if(editArea.isIE)
e.keyCode=0;
return false;
}
//alert("Test: "+ letter + " ("+e.keyCode+") ALT: "+ AltPressed(e) + " CTRL "+ CtrlPressed(e) + " SHIFT "+ ShiftPressed(e));
return true;
};
// return true if Alt key is pressed
function AltPressed(e) {
if (window.event) {
return (window.event.altKey);
} else {
if(e.modifiers)
return (e.altKey || (e.modifiers % 2));
else
return e.altKey;
}
};
// return true if Ctrl key is pressed
function CtrlPressed(e) {
if (window.event) {
return (window.event.ctrlKey);
} else {
return (e.ctrlKey || (e.modifiers==2) || (e.modifiers==3) || (e.modifiers>5));
}
};
// return true if Shift key is pressed
function ShiftPressed(e) {
if (window.event) {
return (window.event.shiftKey);
} else {
return (e.shiftKey || (e.modifiers>3));
}
};
File diff suppressed because it is too large Load Diff
+167 -166
View File
@@ -1,166 +1,167 @@
EditAreaLoader.prototype.get_regexp= function(text_array){
//res="( |=|\\n|\\r|\\[|\\(|µ|)(";
res="(\\b)(";
for(i=0; i<text_array.length; i++){
if(i>0)
res+="|";
//res+="("+ tab_text[i] +")";
//res+=tab_text[i].replace(/(\.|\?|\*|\+|\\|\(|\)|\[|\]|\{|\})/g, "\\$1");
res+=this.get_escaped_regexp(text_array[i]);
}
//res+=")( |\\.|:|\\{|\\(|\\)|\\[|\\]|\'|\"|\\r|\\n|\\t|$)";
res+=")(\\b)";
reg= new RegExp(res);
return res;
};
EditAreaLoader.prototype.get_escaped_regexp= function(str){
return str.toString().replace(/(\.|\?|\*|\+|\\|\(|\)|\[|\]|\}|\{|\$|\^|\|)/g, "\\$1");
};
EditAreaLoader.prototype.init_syntax_regexp= function(){
var lang_style= {};
for(var lang in this.load_syntax){
if(!this.syntax[lang]) // init the regexp if not already initialized
{
this.syntax[lang]= {};
this.syntax[lang]["keywords_reg_exp"]= {};
this.keywords_reg_exp_nb=0;
if(this.load_syntax[lang]['KEYWORDS']){
param="g";
if(this.load_syntax[lang]['KEYWORD_CASE_SENSITIVE']===false)
param+="i";
for(var i in this.load_syntax[lang]['KEYWORDS']){
if(typeof(this.load_syntax[lang]['KEYWORDS'][i])=="function") continue;
this.syntax[lang]["keywords_reg_exp"][i]= new RegExp(this.get_regexp( this.load_syntax[lang]['KEYWORDS'][i] ), param);
this.keywords_reg_exp_nb++;
}
}
if(this.load_syntax[lang]['OPERATORS']){
var str="";
var nb=0;
for(var i in this.load_syntax[lang]['OPERATORS']){
if(typeof(this.load_syntax[lang]['OPERATORS'][i])=="function") continue;
if(nb>0)
str+="|";
str+=this.get_escaped_regexp(this.load_syntax[lang]['OPERATORS'][i]);
nb++;
}
if(str.length>0)
this.syntax[lang]["operators_reg_exp"]= new RegExp("("+str+")","g");
}
if(this.load_syntax[lang]['DELIMITERS']){
var str="";
var nb=0;
for(var i in this.load_syntax[lang]['DELIMITERS']){
if(typeof(this.load_syntax[lang]['DELIMITERS'][i])=="function") continue;
if(nb>0)
str+="|";
str+=this.get_escaped_regexp(this.load_syntax[lang]['DELIMITERS'][i]);
nb++;
}
if(str.length>0)
this.syntax[lang]["delimiters_reg_exp"]= new RegExp("("+str+")","g");
}
// /(("(\\"|[^"])*"?)|('(\\'|[^'])*'?)|(//(.|\r|\t)*\n)|(/\*(.|\n|\r|\t)*\*/)|(<!--(.|\n|\r|\t)*-->))/gi
var syntax_trace=[];
// /("(?:[^"\\]*(\\\\)*(\\"?)?)*("|$))/g
this.syntax[lang]["quotes"]={};
var quote_tab= [];
if(this.load_syntax[lang]['QUOTEMARKS']){
for(var i in this.load_syntax[lang]['QUOTEMARKS']){
if(typeof(this.load_syntax[lang]['QUOTEMARKS'][i])=="function") continue;
var x=this.get_escaped_regexp(this.load_syntax[lang]['QUOTEMARKS'][i]);
this.syntax[lang]["quotes"][x]=x;
//quote_tab[quote_tab.length]="("+x+"(?:\\\\"+x+"|[^"+x+"])*("+x+"|$))";
//previous working : quote_tab[quote_tab.length]="("+x+"(?:[^"+x+"\\\\]*(\\\\\\\\)*(\\\\"+x+"?)?)*("+x+"|$))";
quote_tab[quote_tab.length]="("+ x +"(\\\\.|[^"+ x +"])*(?:"+ x +"|$))";
syntax_trace.push(x);
}
}
this.syntax[lang]["comments"]={};
if(this.load_syntax[lang]['COMMENT_SINGLE']){
for(var i in this.load_syntax[lang]['COMMENT_SINGLE']){
if(typeof(this.load_syntax[lang]['COMMENT_SINGLE'][i])=="function") continue;
var x=this.get_escaped_regexp(this.load_syntax[lang]['COMMENT_SINGLE'][i]);
quote_tab[quote_tab.length]="("+x+"(.|\\r|\\t)*(\\n|$))";
syntax_trace.push(x);
this.syntax[lang]["comments"][x]="\n";
}
}
// (/\*(.|[\r\n])*?\*/)
if(this.load_syntax[lang]['COMMENT_MULTI']){
for(var i in this.load_syntax[lang]['COMMENT_MULTI']){
if(typeof(this.load_syntax[lang]['COMMENT_MULTI'][i])=="function") continue;
var start=this.get_escaped_regexp(i);
var end=this.get_escaped_regexp(this.load_syntax[lang]['COMMENT_MULTI'][i]);
quote_tab[quote_tab.length]="("+start+"(.|\\n|\\r)*?("+end+"|$))";
syntax_trace.push(start);
syntax_trace.push(end);
this.syntax[lang]["comments"][i]=this.load_syntax[lang]['COMMENT_MULTI'][i];
}
}
if(quote_tab.length>0)
this.syntax[lang]["comment_or_quote_reg_exp"]= new RegExp("("+quote_tab.join("|")+")","gi");
if(syntax_trace.length>0) // /((.|\n)*?)(\\*("|'|\/\*|\*\/|\/\/|$))/g
this.syntax[lang]["syntax_trace_regexp"]= new RegExp("((.|\n)*?)(\\\\*("+ syntax_trace.join("|") +"|$))", "gmi");
if(this.load_syntax[lang]['SCRIPT_DELIMITERS']){
this.syntax[lang]["script_delimiters"]= {};
for(var i in this.load_syntax[lang]['SCRIPT_DELIMITERS']){
if(typeof(this.load_syntax[lang]['SCRIPT_DELIMITERS'][i])=="function") continue;
this.syntax[lang]["script_delimiters"][i]= this.load_syntax[lang]['SCRIPT_DELIMITERS'];
}
}
this.syntax[lang]["custom_regexp"]= {};
if(this.load_syntax[lang]['REGEXPS']){
for(var i in this.load_syntax[lang]['REGEXPS']){
if(typeof(this.load_syntax[lang]['REGEXPS'][i])=="function") continue;
var val= this.load_syntax[lang]['REGEXPS'][i];
if(!this.syntax[lang]["custom_regexp"][val['execute']])
this.syntax[lang]["custom_regexp"][val['execute']]= {};
this.syntax[lang]["custom_regexp"][val['execute']][i]={'regexp' : new RegExp(val['search'], val['modifiers'])
, 'class' : val['class']};
}
}
if(this.load_syntax[lang]['STYLES']){
lang_style[lang]= {};
for(var i in this.load_syntax[lang]['STYLES']){
if(typeof(this.load_syntax[lang]['STYLES'][i])=="function") continue;
if(typeof(this.load_syntax[lang]['STYLES'][i]) != "string"){
for(var j in this.load_syntax[lang]['STYLES'][i]){
lang_style[lang][j]= this.load_syntax[lang]['STYLES'][i][j];
}
}else{
lang_style[lang][i]= this.load_syntax[lang]['STYLES'][i];
}
}
}
// build style string
var style="";
for(var i in lang_style[lang]){
if(lang_style[lang][i].length>0){
style+= "."+ lang +" ."+ i.toLowerCase() +" span{"+lang_style[lang][i]+"}\n";
style+= "."+ lang +" ."+ i.toLowerCase() +"{"+lang_style[lang][i]+"}\n";
}
}
this.syntax[lang]["styles"]=style;
}
}
};
editAreaLoader.waiting_loading["reg_syntax.js"]= "loaded";
EditAreaLoader.prototype.get_regexp= function(text_array){
//res="( |=|\\n|\\r|\\[|\\(|µ|)(";
res="(\\b)(";
for(i=0; i<text_array.length; i++){
if(i>0)
res+="|";
//res+="("+ tab_text[i] +")";
//res+=tab_text[i].replace(/(\.|\?|\*|\+|\\|\(|\)|\[|\]|\{|\})/g, "\\$1");
res+=this.get_escaped_regexp(text_array[i]);
}
//res+=")( |\\.|:|\\{|\\(|\\)|\\[|\\]|\'|\"|\\r|\\n|\\t|$)";
res+=")(\\b)";
reg= new RegExp(res);
return res;
};
EditAreaLoader.prototype.get_escaped_regexp= function(str){
return str.toString().replace(/(\.|\?|\*|\+|\\|\(|\)|\[|\]|\}|\{|\$|\^|\|)/g, "\\$1");
};
EditAreaLoader.prototype.init_syntax_regexp= function(){
var lang_style= {};
for(var lang in this.load_syntax){
if(!this.syntax[lang]) // init the regexp if not already initialized
{
this.syntax[lang]= {};
this.syntax[lang]["keywords_reg_exp"]= {};
this.keywords_reg_exp_nb=0;
if(this.load_syntax[lang]['KEYWORDS']){
param="g";
if(this.load_syntax[lang]['KEYWORD_CASE_SENSITIVE']===false)
param+="i";
for(var i in this.load_syntax[lang]['KEYWORDS']){
if(typeof(this.load_syntax[lang]['KEYWORDS'][i])=="function") continue;
this.syntax[lang]["keywords_reg_exp"][i]= new RegExp(this.get_regexp( this.load_syntax[lang]['KEYWORDS'][i] ), param);
this.keywords_reg_exp_nb++;
}
}
if(this.load_syntax[lang]['OPERATORS']){
var str="";
var nb=0;
for(var i in this.load_syntax[lang]['OPERATORS']){
if(typeof(this.load_syntax[lang]['OPERATORS'][i])=="function") continue;
if(nb>0)
str+="|";
str+=this.get_escaped_regexp(this.load_syntax[lang]['OPERATORS'][i]);
nb++;
}
if(str.length>0)
this.syntax[lang]["operators_reg_exp"]= new RegExp("("+str+")","g");
}
if(this.load_syntax[lang]['DELIMITERS']){
var str="";
var nb=0;
for(var i in this.load_syntax[lang]['DELIMITERS']){
if(typeof(this.load_syntax[lang]['DELIMITERS'][i])=="function") continue;
if(nb>0)
str+="|";
str+=this.get_escaped_regexp(this.load_syntax[lang]['DELIMITERS'][i]);
nb++;
}
if(str.length>0)
this.syntax[lang]["delimiters_reg_exp"]= new RegExp("("+str+")","g");
}
// /(("(\\"|[^"])*"?)|('(\\'|[^'])*'?)|(//(.|\r|\t)*\n)|(/\*(.|\n|\r|\t)*\*/)|(<!--(.|\n|\r|\t)*-->))/gi
var syntax_trace=[];
// /("(?:[^"\\]*(\\\\)*(\\"?)?)*("|$))/g
this.syntax[lang]["quotes"]={};
var quote_tab= [];
if(this.load_syntax[lang]['QUOTEMARKS']){
for(var i in this.load_syntax[lang]['QUOTEMARKS']){
if(typeof(this.load_syntax[lang]['QUOTEMARKS'][i])=="function") continue;
var x=this.get_escaped_regexp(this.load_syntax[lang]['QUOTEMARKS'][i]);
this.syntax[lang]["quotes"][x]=x;
//quote_tab[quote_tab.length]="("+x+"(?:\\\\"+x+"|[^"+x+"])*("+x+"|$))";
//previous working : quote_tab[quote_tab.length]="("+x+"(?:[^"+x+"\\\\]*(\\\\\\\\)*(\\\\"+x+"?)?)*("+x+"|$))";
quote_tab[quote_tab.length]="("+ x +"(\\\\.|[^"+ x +"])*(?:"+ x +"|$))";
syntax_trace.push(x);
}
}
this.syntax[lang]["comments"]={};
if(this.load_syntax[lang]['COMMENT_SINGLE']){
for(var i in this.load_syntax[lang]['COMMENT_SINGLE']){
if(typeof(this.load_syntax[lang]['COMMENT_SINGLE'][i])=="function") continue;
var x=this.get_escaped_regexp(this.load_syntax[lang]['COMMENT_SINGLE'][i]);
quote_tab[quote_tab.length]="("+x+"(.|\\r|\\t)*(\\n|$))";
syntax_trace.push(x);
this.syntax[lang]["comments"][x]="\n";
}
}
// (/\*(.|[\r\n])*?\*/)
if(this.load_syntax[lang]['COMMENT_MULTI']){
for(var i in this.load_syntax[lang]['COMMENT_MULTI']){
if(typeof(this.load_syntax[lang]['COMMENT_MULTI'][i])=="function") continue;
var start=this.get_escaped_regexp(i);
var end=this.get_escaped_regexp(this.load_syntax[lang]['COMMENT_MULTI'][i]);
quote_tab[quote_tab.length]="("+start+"(.|\\n|\\r)*?("+end+"|$))";
syntax_trace.push(start);
syntax_trace.push(end);
this.syntax[lang]["comments"][i]=this.load_syntax[lang]['COMMENT_MULTI'][i];
}
}
if(quote_tab.length>0)
this.syntax[lang]["comment_or_quote_reg_exp"]= new RegExp("("+quote_tab.join("|")+")","gi");
if(syntax_trace.length>0) // /((.|\n)*?)(\\*("|'|\/\*|\*\/|\/\/|$))/g
this.syntax[lang]["syntax_trace_regexp"]= new RegExp("((.|\n)*?)(\\\\*("+ syntax_trace.join("|") +"|$))", "gmi");
if(this.load_syntax[lang]['SCRIPT_DELIMITERS']){
this.syntax[lang]["script_delimiters"]= {};
for(var i in this.load_syntax[lang]['SCRIPT_DELIMITERS']){
if(typeof(this.load_syntax[lang]['SCRIPT_DELIMITERS'][i])=="function") continue;
this.syntax[lang]["script_delimiters"][i]= this.load_syntax[lang]['SCRIPT_DELIMITERS'];
}
}
this.syntax[lang]["custom_regexp"]= {};
if(this.load_syntax[lang]['REGEXPS']){
for(var i in this.load_syntax[lang]['REGEXPS']){
if(typeof(this.load_syntax[lang]['REGEXPS'][i])=="function") continue;
var val= this.load_syntax[lang]['REGEXPS'][i];
if(!this.syntax[lang]["custom_regexp"][val['execute']])
this.syntax[lang]["custom_regexp"][val['execute']]= {};
this.syntax[lang]["custom_regexp"][val['execute']][i]={'regexp' : new RegExp(val['search'], val['modifiers'])
, 'class' : val['class']};
}
}
if(this.load_syntax[lang]['STYLES']){
lang_style[lang]= {};
for(var i in this.load_syntax[lang]['STYLES']){
if(typeof(this.load_syntax[lang]['STYLES'][i])=="function") continue;
if(typeof(this.load_syntax[lang]['STYLES'][i]) != "string"){
for(var j in this.load_syntax[lang]['STYLES'][i]){
lang_style[lang][j]= this.load_syntax[lang]['STYLES'][i][j];
}
}else{
lang_style[lang][i]= this.load_syntax[lang]['STYLES'][i];
}
}
}
// build style string
var style="";
for(var i in lang_style[lang]){
if(lang_style[lang][i].length>0){
style+= "."+ lang +" ."+ i.toLowerCase() +" span{"+lang_style[lang][i]+"}\n";
style+= "."+ lang +" ."+ i.toLowerCase() +"{"+lang_style[lang][i]+"}\n";
}
}
this.syntax[lang]["styles"]=style;
}
}
};
editAreaLoader.waiting_loading["reg_syntax.js"]= "loaded";
+140 -139
View File
@@ -1,139 +1,140 @@
/*EditArea.prototype.comment_or_quotes= function(v0, v1, v2, v3, v4,v5,v6,v7,v8,v9, v10){
new_class="quotes";
if(v6 && v6 != undefined && v6!="")
new_class="comments";
return "µ__"+ new_class +"__µ"+v0+"µ_END_µ";
};*/
/* EditArea.prototype.htmlTag= function(v0, v1, v2, v3, v4,v5,v6,v7,v8,v9, v10){
res="<span class=htmlTag>"+v2;
alert("v2: "+v2+" v3: "+v3);
tab=v3.split("=");
attributes="";
if(tab.length>1){
attributes="<span class=attribute>"+tab[0]+"</span>=";
for(i=1; i<tab.length-1; i++){
cut=tab[i].lastIndexOf("&nbsp;");
attributes+="<span class=attributeVal>"+tab[i].substr(0,cut)+"</span>";
attributes+="<span class=attribute>"+tab[i].substr(cut)+"</span>=";
}
attributes+="<span class=attributeVal>"+tab[tab.length-1]+"</span>";
}
res+=attributes+v5+"</span>";
return res;
};*/
// determine if the selected text if a comment or a quoted text
EditArea.prototype.comment_or_quote= function(){
var new_class="", close_tag="", sy, arg, i;
sy = parent.editAreaLoader.syntax[editArea.current_code_lang];
arg = EditArea.prototype.comment_or_quote.arguments[0];
for( i in sy["quotes"] ){
if(arg.indexOf(i)==0){
new_class="quotesmarks";
close_tag=sy["quotes"][i];
}
}
if(new_class.length==0)
{
for(var i in sy["comments"]){
if( arg.indexOf(i)==0 ){
new_class="comments";
close_tag=sy["comments"][i];
}
}
}
// for single line comment the \n must not be included in the span tags
if(close_tag=="\n"){
return "µ__"+ new_class +"__µ"+ arg.replace(/(\r?\n)?$/m, "µ_END_µ$1");
}else{
// the closing tag must be set only if the comment or quotes is closed
reg= new RegExp(parent.editAreaLoader.get_escaped_regexp(close_tag)+"$", "m");
if( arg.search(reg)!=-1 )
return "µ__"+ new_class +"__µ"+ arg +"µ_END_µ";
else
return "µ__"+ new_class +"__µ"+ arg;
}
};
/*
// apply special tags arround text to highlight
EditArea.prototype.custom_highlight= function(){
res= EditArea.prototype.custom_highlight.arguments[1]+"µ__"+ editArea.reg_exp_span_tag +"__µ" + EditArea.prototype.custom_highlight.arguments[2]+"µ_END_µ";
if(EditArea.prototype.custom_highlight.arguments.length>5)
res+= EditArea.prototype.custom_highlight.arguments[ EditArea.prototype.custom_highlight.arguments.length-3 ];
return res;
};
*/
// return identication that allow to know if revalidating only the text line won't make the syntax go mad
EditArea.prototype.get_syntax_trace= function(text){
if(this.settings["syntax"].length>0 && parent.editAreaLoader.syntax[this.settings["syntax"]]["syntax_trace_regexp"])
return text.replace(parent.editAreaLoader.syntax[this.settings["syntax"]]["syntax_trace_regexp"], "$3");
};
EditArea.prototype.colorize_text= function(text){
//text="<div id='result' class='area' style='position: relative; z-index: 4; height: 500px; overflow: scroll;border: solid black 1px;'> ";
/*
if(this.isOpera){
// opera can't use pre element tabulation cause a tab=6 chars in the textarea and 8 chars in the pre
text= this.replace_tab(text);
}*/
text= " "+text; // for easier regExp
/*if(this.do_html_tags)
text= text.replace(/(<[a-z]+ [^>]*>)/gi, '[__htmlTag__]$1[_END_]');*/
if(this.settings["syntax"].length>0)
text= this.apply_syntax(text, this.settings["syntax"]);
// remove the first space added
return text.substr(1).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/µ_END_µ/g,"</span>").replace(/µ__([a-zA-Z0-9]+)__µ/g,"<span class='$1'>");
};
EditArea.prototype.apply_syntax= function(text, lang){
var sy;
this.current_code_lang=lang;
if(!parent.editAreaLoader.syntax[lang])
return text;
sy = parent.editAreaLoader.syntax[lang];
if(sy["custom_regexp"]['before']){
for( var i in sy["custom_regexp"]['before']){
var convert="$1µ__"+ sy["custom_regexp"]['before'][i]['class'] +"__µ$2µ_END_µ$3";
text= text.replace(sy["custom_regexp"]['before'][i]['regexp'], convert);
}
}
if(sy["comment_or_quote_reg_exp"]){
//setTimeout("_$('debug_area').value=editArea.comment_or_quote_reg_exp;", 500);
text= text.replace(sy["comment_or_quote_reg_exp"], this.comment_or_quote);
}
if(sy["keywords_reg_exp"]){
for(var i in sy["keywords_reg_exp"]){
text= text.replace(sy["keywords_reg_exp"][i], 'µ__'+i+'__µ$2µ_END_µ');
}
}
if(sy["delimiters_reg_exp"]){
text= text.replace(sy["delimiters_reg_exp"], 'µ__delimiters__µ$1µ_END_µ');
}
if(sy["operators_reg_exp"]){
text= text.replace(sy["operators_reg_exp"], 'µ__operators__µ$1µ_END_µ');
}
if(sy["custom_regexp"]['after']){
for( var i in sy["custom_regexp"]['after']){
var convert="$1µ__"+ sy["custom_regexp"]['after'][i]['class'] +"__µ$2µ_END_µ$3";
text= text.replace(sy["custom_regexp"]['after'][i]['regexp'], convert);
}
}
return text;
};
/*EditArea.prototype.comment_or_quotes= function(v0, v1, v2, v3, v4,v5,v6,v7,v8,v9, v10){
new_class="quotes";
if(v6 && v6 != undefined && v6!="")
new_class="comments";
return "µ__"+ new_class +"__µ"+v0+"µ_END_µ";
};*/
/* EditArea.prototype.htmlTag= function(v0, v1, v2, v3, v4,v5,v6,v7,v8,v9, v10){
res="<span class=htmlTag>"+v2;
alert("v2: "+v2+" v3: "+v3);
tab=v3.split("=");
attributes="";
if(tab.length>1){
attributes="<span class=attribute>"+tab[0]+"</span>=";
for(i=1; i<tab.length-1; i++){
cut=tab[i].lastIndexOf("&nbsp;");
attributes+="<span class=attributeVal>"+tab[i].substr(0,cut)+"</span>";
attributes+="<span class=attribute>"+tab[i].substr(cut)+"</span>=";
}
attributes+="<span class=attributeVal>"+tab[tab.length-1]+"</span>";
}
res+=attributes+v5+"</span>";
return res;
};*/
// determine if the selected text if a comment or a quoted text
EditArea.prototype.comment_or_quote= function(){
var new_class="", close_tag="", sy, arg, i;
sy = parent.editAreaLoader.syntax[editArea.current_code_lang];
arg = EditArea.prototype.comment_or_quote.arguments[0];
for( i in sy["quotes"] ){
if(arg.indexOf(i)==0){
new_class="quotesmarks";
close_tag=sy["quotes"][i];
}
}
if(new_class.length==0)
{
for(var i in sy["comments"]){
if( arg.indexOf(i)==0 ){
new_class="comments";
close_tag=sy["comments"][i];
}
}
}
// for single line comment the \n must not be included in the span tags
if(close_tag=="\n"){
return "µ__"+ new_class +"__µ"+ arg.replace(/(\r?\n)?$/m, "µ_END_µ$1");
}else{
// the closing tag must be set only if the comment or quotes is closed
reg= new RegExp(parent.editAreaLoader.get_escaped_regexp(close_tag)+"$", "m");
if( arg.search(reg)!=-1 )
return "µ__"+ new_class +"__µ"+ arg +"µ_END_µ";
else
return "µ__"+ new_class +"__µ"+ arg;
}
};
/*
// apply special tags arround text to highlight
EditArea.prototype.custom_highlight= function(){
res= EditArea.prototype.custom_highlight.arguments[1]+"µ__"+ editArea.reg_exp_span_tag +"__µ" + EditArea.prototype.custom_highlight.arguments[2]+"µ_END_µ";
if(EditArea.prototype.custom_highlight.arguments.length>5)
res+= EditArea.prototype.custom_highlight.arguments[ EditArea.prototype.custom_highlight.arguments.length-3 ];
return res;
};
*/
// return identication that allow to know if revalidating only the text line won't make the syntax go mad
EditArea.prototype.get_syntax_trace= function(text){
if(this.settings["syntax"].length>0 && parent.editAreaLoader.syntax[this.settings["syntax"]]["syntax_trace_regexp"])
return text.replace(parent.editAreaLoader.syntax[this.settings["syntax"]]["syntax_trace_regexp"], "$3");
};
EditArea.prototype.colorize_text= function(text){
//text="<div id='result' class='area' style='position: relative; z-index: 4; height: 500px; overflow: scroll;border: solid black 1px;'> ";
/*
if(this.isOpera){
// opera can't use pre element tabulation cause a tab=6 chars in the textarea and 8 chars in the pre
text= this.replace_tab(text);
}*/
text= " "+text; // for easier regExp
/*if(this.do_html_tags)
text= text.replace(/(<[a-z]+ [^>]*>)/gi, '[__htmlTag__]$1[_END_]');*/
if(this.settings["syntax"].length>0)
text= this.apply_syntax(text, this.settings["syntax"]);
// remove the first space added
return text.substr(1).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/µ_END_µ/g,"</span>").replace(/µ__([a-zA-Z0-9]+)__µ/g,"<span class='$1'>");
};
EditArea.prototype.apply_syntax= function(text, lang){
var sy;
this.current_code_lang=lang;
if(!parent.editAreaLoader.syntax[lang])
return text;
sy = parent.editAreaLoader.syntax[lang];
if(sy["custom_regexp"]['before']){
for( var i in sy["custom_regexp"]['before']){
var convert="$1µ__"+ sy["custom_regexp"]['before'][i]['class'] +"__µ$2µ_END_µ$3";
text= text.replace(sy["custom_regexp"]['before'][i]['regexp'], convert);
}
}
if(sy["comment_or_quote_reg_exp"]){
//setTimeout("_$('debug_area').value=editArea.comment_or_quote_reg_exp;", 500);
text= text.replace(sy["comment_or_quote_reg_exp"], this.comment_or_quote);
}
if(sy["keywords_reg_exp"]){
for(var i in sy["keywords_reg_exp"]){
text= text.replace(sy["keywords_reg_exp"][i], 'µ__'+i+'__µ$2µ_END_µ');
}
}
if(sy["delimiters_reg_exp"]){
text= text.replace(sy["delimiters_reg_exp"], 'µ__delimiters__µ$1µ_END_µ');
}
if(sy["operators_reg_exp"]){
text= text.replace(sy["operators_reg_exp"], 'µ__operators__µ$1µ_END_µ');
}
if(sy["custom_regexp"]['after']){
for( var i in sy["custom_regexp"]['after']){
var convert="$1µ__"+ sy["custom_regexp"]['after'][i]['class'] +"__µ$2µ_END_µ$3";
text= text.replace(sy["custom_regexp"]['after'][i]['regexp'], convert);
}
}
return text;
};
@@ -1,73 +1,74 @@
EditAreaLoader.prototype.start_resize_area= function(){
var d=document,a,div,width,height,father;
d.onmouseup= editAreaLoader.end_resize_area;
d.onmousemove= editAreaLoader.resize_area;
editAreaLoader.toggle(editAreaLoader.resize["id"]);
a = editAreas[editAreaLoader.resize["id"]]["textarea"];
div = d.getElementById("edit_area_resize");
if(!div){
div= d.createElement("div");
div.id="edit_area_resize";
div.style.border="dashed #888888 1px";
}
width = a.offsetWidth -2;
height = a.offsetHeight -2;
div.style.display = "block";
div.style.width = width+"px";
div.style.height = height+"px";
father= a.parentNode;
father.insertBefore(div, a);
a.style.display="none";
editAreaLoader.resize["start_top"]= calculeOffsetTop(div);
editAreaLoader.resize["start_left"]= calculeOffsetLeft(div);
};
EditAreaLoader.prototype.end_resize_area= function(e){
var d=document,div,a,width,height;
d.onmouseup="";
d.onmousemove="";
div = d.getElementById("edit_area_resize");
a= editAreas[editAreaLoader.resize["id"]]["textarea"];
width = Math.max(editAreas[editAreaLoader.resize["id"]]["settings"]["min_width"], div.offsetWidth-4);
height = Math.max(editAreas[editAreaLoader.resize["id"]]["settings"]["min_height"], div.offsetHeight-4);
if(editAreaLoader.isIE==6){
width-=2;
height-=2;
}
a.style.width = width+"px";
a.style.height = height+"px";
div.style.display = "none";
a.style.display = "inline";
a.selectionStart = editAreaLoader.resize["selectionStart"];
a.selectionEnd = editAreaLoader.resize["selectionEnd"];
editAreaLoader.toggle(editAreaLoader.resize["id"]);
return false;
};
EditAreaLoader.prototype.resize_area= function(e){
var allow,newHeight,newWidth;
allow = editAreas[editAreaLoader.resize["id"]]["settings"]["allow_resize"];
if(allow=="both" || allow=="y")
{
newHeight = Math.max(20, getMouseY(e)- editAreaLoader.resize["start_top"]);
document.getElementById("edit_area_resize").style.height= newHeight+"px";
}
if(allow=="both" || allow=="x")
{
newWidth= Math.max(20, getMouseX(e)- editAreaLoader.resize["start_left"]);
document.getElementById("edit_area_resize").style.width= newWidth+"px";
}
return false;
};
editAreaLoader.waiting_loading["resize_area.js"]= "loaded";
EditAreaLoader.prototype.start_resize_area= function(){
var d=document,a,div,width,height,father;
d.onmouseup= editAreaLoader.end_resize_area;
d.onmousemove= editAreaLoader.resize_area;
editAreaLoader.toggle(editAreaLoader.resize["id"]);
a = editAreas[editAreaLoader.resize["id"]]["textarea"];
div = d.getElementById("edit_area_resize");
if(!div){
div= d.createElement("div");
div.id="edit_area_resize";
div.style.border="dashed #888888 1px";
}
width = a.offsetWidth -2;
height = a.offsetHeight -2;
div.style.display = "block";
div.style.width = width+"px";
div.style.height = height+"px";
father= a.parentNode;
father.insertBefore(div, a);
a.style.display="none";
editAreaLoader.resize["start_top"]= calculeOffsetTop(div);
editAreaLoader.resize["start_left"]= calculeOffsetLeft(div);
};
EditAreaLoader.prototype.end_resize_area= function(e){
var d=document,div,a,width,height;
d.onmouseup="";
d.onmousemove="";
div = d.getElementById("edit_area_resize");
a= editAreas[editAreaLoader.resize["id"]]["textarea"];
width = Math.max(editAreas[editAreaLoader.resize["id"]]["settings"]["min_width"], div.offsetWidth-4);
height = Math.max(editAreas[editAreaLoader.resize["id"]]["settings"]["min_height"], div.offsetHeight-4);
if(editAreaLoader.isIE==6){
width-=2;
height-=2;
}
a.style.width = width+"px";
a.style.height = height+"px";
div.style.display = "none";
a.style.display = "inline";
a.selectionStart = editAreaLoader.resize["selectionStart"];
a.selectionEnd = editAreaLoader.resize["selectionEnd"];
editAreaLoader.toggle(editAreaLoader.resize["id"]);
return false;
};
EditAreaLoader.prototype.resize_area= function(e){
var allow,newHeight,newWidth;
allow = editAreas[editAreaLoader.resize["id"]]["settings"]["allow_resize"];
if(allow=="both" || allow=="y")
{
newHeight = Math.max(20, getMouseY(e)- editAreaLoader.resize["start_top"]);
document.getElementById("edit_area_resize").style.height= newHeight+"px";
}
if(allow=="both" || allow=="x")
{
newWidth= Math.max(20, getMouseX(e)- editAreaLoader.resize["start_left"]);
document.getElementById("edit_area_resize").style.width= newWidth+"px";
}
return false;
};
editAreaLoader.waiting_loading["resize_area.js"]= "loaded";
@@ -1,174 +1,175 @@
EditArea.prototype.show_search = function(){
if(_$("area_search_replace").style.visibility=="visible"){
this.hidden_search();
}else{
this.open_inline_popup("area_search_replace");
var text= this.area_get_selection();
var search= text.split("\n")[0];
_$("area_search").value= search;
_$("area_search").focus();
}
};
EditArea.prototype.hidden_search= function(){
/*_$("area_search_replace").style.visibility="hidden";
this.textarea.focus();
var icon= _$("search");
setAttribute(icon, "class", getAttribute(icon, "class").replace(/ selected/g, "") );*/
this.close_inline_popup("area_search_replace");
};
EditArea.prototype.area_search= function(mode){
if(!mode)
mode="search";
_$("area_search_msg").innerHTML="";
var search=_$("area_search").value;
this.textarea.focus();
this.textarea.textareaFocused=true;
var infos= this.get_selection_infos();
var start= infos["selectionStart"];
var pos=-1;
var pos_begin=-1;
var length=search.length;
if(_$("area_search_replace").style.visibility!="visible"){
this.show_search();
return;
}
if(search.length==0){
_$("area_search_msg").innerHTML=this.get_translation("search_field_empty");
return;
}
// advance to the next occurence if no text selected
if(mode!="replace" ){
if(_$("area_search_reg_exp").checked)
start++;
else
start+= search.length;
}
//search
if(_$("area_search_reg_exp").checked){
// regexp search
var opt="m";
if(!_$("area_search_match_case").checked)
opt+="i";
var reg= new RegExp(search, opt);
pos= infos["full_text"].substr(start).search(reg);
pos_begin= infos["full_text"].search(reg);
if(pos!=-1){
pos+=start;
length=infos["full_text"].substr(start).match(reg)[0].length;
}else if(pos_begin!=-1){
length=infos["full_text"].match(reg)[0].length;
}
}else{
if(_$("area_search_match_case").checked){
pos= infos["full_text"].indexOf(search, start);
pos_begin= infos["full_text"].indexOf(search);
}else{
pos= infos["full_text"].toLowerCase().indexOf(search.toLowerCase(), start);
pos_begin= infos["full_text"].toLowerCase().indexOf(search.toLowerCase());
}
}
// interpret result
if(pos==-1 && pos_begin==-1){
_$("area_search_msg").innerHTML="<strong>"+search+"</strong> "+this.get_translation("not_found");
return;
}else if(pos==-1 && pos_begin != -1){
begin= pos_begin;
_$("area_search_msg").innerHTML=this.get_translation("restart_search_at_begin");
}else
begin= pos;
//_$("area_search_msg").innerHTML+="<strong>"+search+"</strong> found at "+begin+" strat at "+start+" pos "+pos+" curs"+ infos["indexOfCursor"]+".";
if(mode=="replace" && pos==infos["indexOfCursor"]){
var replace= _$("area_replace").value;
var new_text="";
if(_$("area_search_reg_exp").checked){
var opt="m";
if(!_$("area_search_match_case").checked)
opt+="i";
var reg= new RegExp(search, opt);
new_text= infos["full_text"].substr(0, begin) + infos["full_text"].substr(start).replace(reg, replace);
}else{
new_text= infos["full_text"].substr(0, begin) + replace + infos["full_text"].substr(begin + length);
}
this.textarea.value=new_text;
this.area_select(begin, length);
this.area_search();
}else
this.area_select(begin, length);
};
EditArea.prototype.area_replace= function(){
this.area_search("replace");
};
EditArea.prototype.area_replace_all= function(){
/* this.area_select(0, 0);
_$("area_search_msg").innerHTML="";
while(_$("area_search_msg").innerHTML==""){
this.area_replace();
}*/
var base_text= this.textarea.value;
var search= _$("area_search").value;
var replace= _$("area_replace").value;
if(search.length==0){
_$("area_search_msg").innerHTML=this.get_translation("search_field_empty");
return ;
}
var new_text="";
var nb_change=0;
if(_$("area_search_reg_exp").checked){
// regExp
var opt="mg";
if(!_$("area_search_match_case").checked)
opt+="i";
var reg= new RegExp(search, opt);
nb_change= infos["full_text"].match(reg).length;
new_text= infos["full_text"].replace(reg, replace);
}else{
if(_$("area_search_match_case").checked){
var tmp_tab=base_text.split(search);
nb_change= tmp_tab.length -1 ;
new_text= tmp_tab.join(replace);
}else{
// case insensitive
var lower_value=base_text.toLowerCase();
var lower_search=search.toLowerCase();
var start=0;
var pos= lower_value.indexOf(lower_search);
while(pos!=-1){
nb_change++;
new_text+= this.textarea.value.substring(start , pos)+replace;
start=pos+ search.length;
pos= lower_value.indexOf(lower_search, pos+1);
}
new_text+= this.textarea.value.substring(start);
}
}
if(new_text==base_text){
_$("area_search_msg").innerHTML="<strong>"+search+"</strong> "+this.get_translation("not_found");
}else{
this.textarea.value= new_text;
_$("area_search_msg").innerHTML="<strong>"+nb_change+"</strong> "+this.get_translation("occurrence_replaced");
// firefox and opera doesn't manage with the focus if it's done directly
//editArea.textarea.focus();editArea.textarea.textareaFocused=true;
setTimeout("editArea.textarea.focus();editArea.textarea.textareaFocused=true;", 100);
}
};
EditArea.prototype.show_search = function(){
if(_$("area_search_replace").style.visibility=="visible"){
this.hidden_search();
}else{
this.open_inline_popup("area_search_replace");
var text= this.area_get_selection();
var search= text.split("\n")[0];
_$("area_search").value= search;
_$("area_search").focus();
}
};
EditArea.prototype.hidden_search= function(){
/*_$("area_search_replace").style.visibility="hidden";
this.textarea.focus();
var icon= _$("search");
setAttribute(icon, "class", getAttribute(icon, "class").replace(/ selected/g, "") );*/
this.close_inline_popup("area_search_replace");
};
EditArea.prototype.area_search= function(mode){
if(!mode)
mode="search";
_$("area_search_msg").innerHTML="";
var search=_$("area_search").value;
this.textarea.focus();
this.textarea.textareaFocused=true;
var infos= this.get_selection_infos();
var start= infos["selectionStart"];
var pos=-1;
var pos_begin=-1;
var length=search.length;
if(_$("area_search_replace").style.visibility!="visible"){
this.show_search();
return;
}
if(search.length==0){
_$("area_search_msg").innerHTML=this.get_translation("search_field_empty");
return;
}
// advance to the next occurence if no text selected
if(mode!="replace" ){
if(_$("area_search_reg_exp").checked)
start++;
else
start+= search.length;
}
//search
if(_$("area_search_reg_exp").checked){
// regexp search
var opt="m";
if(!_$("area_search_match_case").checked)
opt+="i";
var reg= new RegExp(search, opt);
pos= infos["full_text"].substr(start).search(reg);
pos_begin= infos["full_text"].search(reg);
if(pos!=-1){
pos+=start;
length=infos["full_text"].substr(start).match(reg)[0].length;
}else if(pos_begin!=-1){
length=infos["full_text"].match(reg)[0].length;
}
}else{
if(_$("area_search_match_case").checked){
pos= infos["full_text"].indexOf(search, start);
pos_begin= infos["full_text"].indexOf(search);
}else{
pos= infos["full_text"].toLowerCase().indexOf(search.toLowerCase(), start);
pos_begin= infos["full_text"].toLowerCase().indexOf(search.toLowerCase());
}
}
// interpret result
if(pos==-1 && pos_begin==-1){
_$("area_search_msg").innerHTML="<strong>"+search+"</strong> "+this.get_translation("not_found");
return;
}else if(pos==-1 && pos_begin != -1){
begin= pos_begin;
_$("area_search_msg").innerHTML=this.get_translation("restart_search_at_begin");
}else
begin= pos;
//_$("area_search_msg").innerHTML+="<strong>"+search+"</strong> found at "+begin+" strat at "+start+" pos "+pos+" curs"+ infos["indexOfCursor"]+".";
if(mode=="replace" && pos==infos["indexOfCursor"]){
var replace= _$("area_replace").value;
var new_text="";
if(_$("area_search_reg_exp").checked){
var opt="m";
if(!_$("area_search_match_case").checked)
opt+="i";
var reg= new RegExp(search, opt);
new_text= infos["full_text"].substr(0, begin) + infos["full_text"].substr(start).replace(reg, replace);
}else{
new_text= infos["full_text"].substr(0, begin) + replace + infos["full_text"].substr(begin + length);
}
this.textarea.value=new_text;
this.area_select(begin, length);
this.area_search();
}else
this.area_select(begin, length);
};
EditArea.prototype.area_replace= function(){
this.area_search("replace");
};
EditArea.prototype.area_replace_all= function(){
/* this.area_select(0, 0);
_$("area_search_msg").innerHTML="";
while(_$("area_search_msg").innerHTML==""){
this.area_replace();
}*/
var base_text= this.textarea.value;
var search= _$("area_search").value;
var replace= _$("area_replace").value;
if(search.length==0){
_$("area_search_msg").innerHTML=this.get_translation("search_field_empty");
return ;
}
var new_text="";
var nb_change=0;
if(_$("area_search_reg_exp").checked){
// regExp
var opt="mg";
if(!_$("area_search_match_case").checked)
opt+="i";
var reg= new RegExp(search, opt);
nb_change= infos["full_text"].match(reg).length;
new_text= infos["full_text"].replace(reg, replace);
}else{
if(_$("area_search_match_case").checked){
var tmp_tab=base_text.split(search);
nb_change= tmp_tab.length -1 ;
new_text= tmp_tab.join(replace);
}else{
// case insensitive
var lower_value=base_text.toLowerCase();
var lower_search=search.toLowerCase();
var start=0;
var pos= lower_value.indexOf(lower_search);
while(pos!=-1){
nb_change++;
new_text+= this.textarea.value.substring(start , pos)+replace;
start=pos+ search.length;
pos= lower_value.indexOf(lower_search, pos+1);
}
new_text+= this.textarea.value.substring(start);
}
}
if(new_text==base_text){
_$("area_search_msg").innerHTML="<strong>"+search+"</strong> "+this.get_translation("not_found");
}else{
this.textarea.value= new_text;
_$("area_search_msg").innerHTML="<strong>"+nb_change+"</strong> "+this.get_translation("occurrence_replaced");
// firefox and opera doesn't manage with the focus if it's done directly
//editArea.textarea.focus();editArea.textarea.textareaFocused=true;
setTimeout("editArea.textarea.focus();editArea.textarea.textareaFocused=true;", 100);
}
};
+101 -100
View File
@@ -1,100 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<title>EditArea</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>
[__CSSRULES__]
[__JSCODE__]
</head>
<body>
<div id='editor'>
<div class='area_toolbar' id='toolbar_1'>[__TOOLBAR__]</div>
<div class='area_toolbar' id='tab_browsing_area'><ul id='tab_browsing_list' class='menu'> <li> </li> </ul></div>
<div id='result'>
<div id='no_file_selected'></div>
<div id='container'>
<div id='cursor_pos' class='edit_area_cursor'>&nbsp;</div>
<div id='end_bracket' class='edit_area_cursor'>&nbsp;</div>
<div id='selection_field'></div>
<div id='line_number' selec='none'></div>
<div id='content_highlight'></div>
<div id='test_font_size'></div>
<div id='selection_field_text'></div>
<textarea id='textarea' wrap='off' onchange='editArea.execCommand("onchange");' onfocus='javascript:editArea.textareaFocused=true;' onblur='javascript:editArea.textareaFocused=false;'>
</textarea>
</div>
</div>
<div class='area_toolbar' id='toolbar_2'>
<table class='statusbar' cellspacing='0' cellpadding='0'>
<tr>
<td class='total' selec='none'>{$position}:</td>
<td class='infos' selec='none'>
{$line_abbr} <span id='linePos'>0</span>, {$char_abbr} <span id='currPos'>0</span>
</td>
<td class='total' selec='none'>{$total}:</td>
<td class='infos' selec='none'>
{$line_abbr} <span id='nbLine'>0</span>, {$char_abbr} <span id='nbChar'>0</span>
</td>
<td class='resize'>
<span id='resize_area'><img src='[__BASEURL__]images/statusbar_resize.gif' alt='resize' selec='none'></span>
</td>
</tr>
</table>
</div>
</div>
<div id='processing'>
<div id='processing_text'>
{$processing}
</div>
</div>
<div id='area_search_replace' class='editarea_popup'>
<table cellspacing='2' cellpadding='0' style='width: 100%'>
<tr>
<td selec='none'>{$search}</td>
<td><input type='text' id='area_search' /></td>
<td id='close_area_search_replace'>
<a onclick='Javascript:editArea.execCommand("hidden_search")'><img selec='none' src='[__BASEURL__]images/close.gif' alt='{$close_popup}' title='{$close_popup}' /></a><br />
</tr><tr>
<td selec='none'>{$replace}</td>
<td><input type='text' id='area_replace' /></td>
<td><img id='move_area_search_replace' onmousedown='return parent.start_move_element(event,"area_search_replace", parent.frames["frame_"+editArea.id]);' src='[__BASEURL__]images/move.gif' alt='{$move_popup}' title='{$move_popup}' /></td>
</tr>
</table>
<div class='button'>
<input type='checkbox' id='area_search_match_case' /><label for='area_search_match_case' selec='none'>{$match_case}</label>
<input type='checkbox' id='area_search_reg_exp' /><label for='area_search_reg_exp' selec='none'>{$reg_exp}</label>
<br />
<a onclick='Javascript:editArea.execCommand("area_search")' selec='none'>{$find_next}</a>
<a onclick='Javascript:editArea.execCommand("area_replace")' selec='none'>{$replace}</a>
<a onclick='Javascript:editArea.execCommand("area_replace_all")' selec='none'>{$replace_all}</a><br />
</div>
<div id='area_search_msg' selec='none'></div>
</div>
<div id='edit_area_help' class='editarea_popup'>
<div class='close_popup'>
<a onclick='Javascript:editArea.execCommand("close_all_inline_popup")'><img src='[__BASEURL__]images/close.gif' alt='{$close_popup}' title='{$close_popup}' /></a>
</div>
<div><h2>Editarea [__EA_VERSION__]</h2><br />
<h3>{$shortcuts}:</h3>
{$tab}: {$add_tab}<br />
{$shift}+{$tab}: {$remove_tab}<br />
{$ctrl}+f: {$search_command}<br />
{$ctrl}+r: {$replace_command}<br />
{$ctrl}+h: {$highlight}<br />
{$ctrl}+g: {$go_to_line}<br />
{$ctrl}+z: {$undo}<br />
{$ctrl}+y: {$redo}<br />
{$ctrl}+e: {$help}<br />
{$ctrl}+q, {$esc}: {$close_popup}<br />
{$accesskey} E: {$toggle}<br />
<br />
<em>{$about_notice}</em>
<br /><div class='copyright'>&copy; Christophe Dolivet 2007-2010</div>
</div>
</div>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<title>EditArea</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>
[__CSSRULES__]
[__JSCODE__]
</head>
<body>
<div id='editor'>
<div class='area_toolbar' id='toolbar_1'>[__TOOLBAR__]</div>
<div class='area_toolbar' id='tab_browsing_area'><ul id='tab_browsing_list' class='menu'> <li> </li> </ul></div>
<div id='result'>
<div id='no_file_selected'></div>
<div id='container'>
<div id='cursor_pos' class='edit_area_cursor'>&nbsp;</div>
<div id='end_bracket' class='edit_area_cursor'>&nbsp;</div>
<div id='selection_field'></div>
<div id='line_number' selec='none'></div>
<div id='content_highlight'></div>
<div id='test_font_size'></div>
<div id='selection_field_text'></div>
<textarea id='textarea' wrap='off' onchange='editArea.execCommand("onchange");' onfocus='javascript:editArea.textareaFocused=true;' onblur='javascript:editArea.textareaFocused=false;'>
</textarea>
</div>
</div>
<div class='area_toolbar' id='toolbar_2'>
<table class='statusbar' cellspacing='0' cellpadding='0'>
<tr>
<td class='total' selec='none'>{$position}:</td>
<td class='infos' selec='none'>
{$line_abbr} <span id='linePos'>0</span>, {$char_abbr} <span id='currPos'>0</span>
</td>
<td class='total' selec='none'>{$total}:</td>
<td class='infos' selec='none'>
{$line_abbr} <span id='nbLine'>0</span>, {$char_abbr} <span id='nbChar'>0</span>
</td>
<td class='resize'>
<span id='resize_area'><img src='[__BASEURL__]images/statusbar_resize.gif' alt='resize' selec='none'></span>
</td>
</tr>
</table>
</div>
</div>
<div id='processing'>
<div id='processing_text'>
{$processing}
</div>
</div>
<div id='area_search_replace' class='editarea_popup'>
<table cellspacing='2' cellpadding='0' style='width: 100%'>
<tr>
<td selec='none'>{$search}</td>
<td><input type='text' id='area_search' /></td>
<td id='close_area_search_replace'>
<a onclick='Javascript:editArea.execCommand("hidden_search")'><img selec='none' src='[__BASEURL__]images/close.gif' alt='{$close_popup}' title='{$close_popup}' /></a><br />
</tr><tr>
<td selec='none'>{$replace}</td>
<td><input type='text' id='area_replace' /></td>
<td><img id='move_area_search_replace' onmousedown='return parent.start_move_element(event,"area_search_replace", parent.frames["frame_"+editArea.id]);' src='[__BASEURL__]images/move.gif' alt='{$move_popup}' title='{$move_popup}' /></td>
</tr>
</table>
<div class='button'>
<input type='checkbox' id='area_search_match_case' /><label for='area_search_match_case' selec='none'>{$match_case}</label>
<input type='checkbox' id='area_search_reg_exp' /><label for='area_search_reg_exp' selec='none'>{$reg_exp}</label>
<br />
<a onclick='Javascript:editArea.execCommand("area_search")' selec='none'>{$find_next}</a>
<a onclick='Javascript:editArea.execCommand("area_replace")' selec='none'>{$replace}</a>
<a onclick='Javascript:editArea.execCommand("area_replace_all")' selec='none'>{$replace_all}</a><br />
</div>
<div id='area_search_msg' selec='none'></div>
</div>
<div id='edit_area_help' class='editarea_popup'>
<div class='close_popup'>
<a onclick='Javascript:editArea.execCommand("close_all_inline_popup")'><img src='[__BASEURL__]images/close.gif' alt='{$close_popup}' title='{$close_popup}' /></a>
</div>
<div><h2>Editarea [__EA_VERSION__]</h2><br />
<h3>{$shortcuts}:</h3>
{$tab}: {$add_tab}<br />
{$shift}+{$tab}: {$remove_tab}<br />
{$ctrl}+f: {$search_command}<br />
{$ctrl}+r: {$replace_command}<br />
{$ctrl}+h: {$highlight}<br />
{$ctrl}+g: {$go_to_line}<br />
{$ctrl}+z: {$undo}<br />
{$ctrl}+y: {$redo}<br />
{$ctrl}+e: {$help}<br />
{$ctrl}+q, {$esc}: {$close_popup}<br />
{$accesskey} E: {$toggle}<br />
<br />
<em>{$about_notice}</em>
<br /><div class='copyright'>&copy; Christophe Dolivet 2007-2010</div>
</div>
</div>
</body>
</html>