Вход Регистрация
Файл: upload/static/jscript/editarea/autocompletion.js
Строк: 624
<?php
/**
 * 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);
?>
Онлайн: 1
Реклама