// Make-Button.js
// Created by Higeorange
// Last updated : 2006/07/29 23:22 

window.onload = function() {
    $('ac').focus();
    $('ac').onkeyup = handle;
    $('ac').onkeypess = handle;
    $('ac').onkeydown = handle;
    $('part').onclick = handle;
    $('former').onclick = handle;
    $('latter').onclick = handle;
    $('make').onclick = makeButton;
    $('clear').onclick = clearButton;
    suggest.init();
};

// Action List ( Maybe not all actions )
var Actions = ['Activate element','Add contact','Add nick to contact','Add all to bookmarks','Add panel','Add to bookmarks',
    'Back','Backspace','Backspace word','Bookmark all open pages',
    'Cancel current voice','Cascade','Check all','Check for upgrade','Clear disk cache','Close all','Close other','Close page','Close window','Compose mail','Content block details','Content block mode on','Content block mode off','Copy','Copy document address','Copy frame address','Copy image','Copy to note','Create linked window','Customize Toolbars','Cut','Cycle to next page','Cycle to next window','Cycle to previous page','Cycle to previous window',
    'Delete','Delete mail','Delete private data','Delete word','Deselect all','Disable cookies','Disable display images','Disable embedded audio','Disable GIF animation','Disable handheld mode','Disable Java','Disable javascript','Disable menu bar','Disable mediumscreenmode','Disable plugins','Disable popup windows','Disable proxy servers','Disable referrer logging','Disable scroll bars','Download URL','Download URL as','Duplicate page',
    'Edit properties','Empty trash','Empty spam','Enable automatic reload','Enable cookies','Enable display images','Enable embedded audio','Enable GIF animation','Enable handheld mode','Enable Java','Enable javascript','Enable menu bar','Enable plugins','Enable popup windows','Enable popup windows in background','Enable proxy servers','Enable referrer logging','Enable requested popup windows','Enable scroll bars','Enter fullscreen','Enter access key mode','Execute program','Exit',
    'Fast forward','Find','Find inline','Find next','Find previous','Focus next widget','Focus previous widget','Forward','Forward mail',
    'Get mail','Go','Go to end','Go to homepage','Go to link element','Go to page','Go to start','Go to nickname','Go to parent directory',
    'Hide opera','Hide panel','Highlight bookmark','Highlight next block','Highlight previous block','Highlight next element','Highlight previous element','Highlight next frame','Highlight previous frame','Highlight next heding','Highlight previous heading','Highlight next URL','Highlight previous URL',
    'Identify as','Insert',
    'Join chat room',
    'Leave access key mode','Leave chat','Leave fullscreen','Leave print preview','Load all images','Lock page',
    'Manage','Mark as read','Mark all as read','Maximize all','Maximaze page','Maximize window','Minimize all','Minimize page','Minimize window',
    'Navigate down','Navigate left','Navigate right','Navigate up','New bookmark','New browser window','New chat room',
    'Open','Open document',
    'Page down','Page left','Page right','Page up','Paste','Paste and go','Paste to note','Paste mouse selection','Print document','Print preview',
    'Quick reply',
    'Redo','Reload','Reload all pages','Reload frame','Remove all finished transfers','Remove transfer','Reopen page','Reply','Reply all','Report site problem','Restart transfer','Restore all','Restore window','Resume transfer','Rewind',
    'Save','Save document as','Save document with images as','Save frame as','Scroll','Scroll down','Scroll left','Scroll right','Scroll up','Search','Select all','Seect author mode','Select next unread','Select previous unread','Select user mode','Send address in mail','Send document address in mail','Sene frame address in mail','Send mail','Send text in mail','Set preference','Set widget mode','Set widget style','Show context menu','Show Java console','Show javascript console','Show message console','Show panel','Show popup menu','Show hidden popup menu','Show preferences','Show print options','Show print preview activate frame','Show print preview as screen','Show print preview one frame per sheet','Show print setup','Show quick preferences','Show web search','Speak selection','Speak from selection','Stop','Stop speaking','Switch to next page','Switch to previous page',
    'Tile horizontally','Tile vertically','Toggle SSR',
    'Undo','Unlock page',
    'Validate document source','Validate frame source','View frame source',
    'Wand','Work offline','Work online',
    'Zoom in','Zoom out','Zoom to','Enable mideumscreen mode'];

Actions.sort();

function Suggest() {
    this.picked = 0;
    this.init = function() {
        this.tabfocus = 0; // ptess tab key, this property is 1;pres other key, this prop is 0
        ssAcList = []; // suggest action list
    };
}
var suggest = new Suggest();

function makeSuggList (str) {
    suggest.init();
    var ex;
    str = str.trim();
//    opera.postError('\"'+str+'\"');

//make regular expression to match action list
    if($('former').checked) {
        ex =new RegExp('^'+str.toLowerCase());
    } else if($('latter').checked) {
        ex = new RegExp(str.toLowerCase()+'$');
    } else {
        ex = new RegExp(str.toLowerCase());
    }
//Don't use for in, cause conflict OOo.user.js reported by Kuruma
    for(var j=0,len=Actions.length;j<len;j++) {
        if(Actions[j].toLowerCase().match(ex)) {
            ssAcList.push(Actions[j]);
        }
    }
    var ul = document.createElement('ul');
    ul.id = 'sgstn';
    for(var i=0,k=ssAcList.length;i<k;i++) {
        var li = document.createElement('li');
        //tab select
        if(suggest.picked == i) {
            li.className = 'picked';
        } else {
            li.className = 'notpicked';
        }
        var anc = document.createElement('a');
        anc.href = 'javascript:insert(\"' + ssAcList[i] + '\")';
        anc.appendChild(document.createTextNode(ssAcList[i]));
        li.appendChild(anc);
        ul.appendChild(li);
    }
    $('sugg').appendChild(ul);
}

//// move tab select action, hilight blue background color
//// On second time(input separator like &), background color isn't changed.
//// I have no idea why not.
//function pckdAct(){
//    var target_li = $('sgstn').getElementsByTagName('li');
//    for(var i=0,len=target_li.length;i<len;i++) {
//        if (i == suggest.picked) {
//            target_li[i].className = 'picked';
//        } else {
//            target_li[i].className = 'notpicked';
//        }
//    }
//}

function makeButton() {
    var a = $('ac').value.trim();
    var t = $('ti').value.trim();
    var p = document.createElement('p');
    if(a != '' && t != '') {
        var anc = document.createElement('a');
        anc.style.marginBottom = '3px';
        anc.href = 'opera:/button/'+escape(a);
        anc.title = t;
        anc.appendChild(document.createTextNode(t));
        p.appendChild(anc);
        $('m').appendChild(p);
        $('link').value = '<a href="opera:/button/'+escape(a)+'" title="'+t+'">'+t+'</a>';
    } else {
        p.appendChild(document.createTextNode('Please imput both action and Display words.'));
        $('m').appendChild(p);
    }
}

function clearButton() {
    $('m').innerHTML = '';
}

function handle(e) {
    //opera.postError('1:'+e.type+':'+$('ac').value);
    if(e.type == 'keydown') {
        switch(e.keyCode){
            case 38: //UpArrow 
                if(suggest.picked +1 < ssAcList.length) {
                    suggest.picked ++;
                    suggesting();
                } else {
                    suggest.picked = 0;
                    suggesting();
                }
                break;
            case 40: //DownArrow 
                if(suggest.picked > 0) {
                    suggest.picked --;
                    suggesting();
                } else if (suggest.picked == 0){
                    suggest.picked = ssAcList.length -1;
                    suggesting();
                }
                break;
            case 9 : //Tab
                if(suggest.tabfocus === 0) {
                    $('ac').focus();
                }
                break;
        }
        // keypress event maybe does not work. it is no need?
    } else if (e.type == 'keypress'){
        switch(e.keyCode){
            case 38: case 40: 
                if(e.preventDefault && e.originalTarget) {
                    e.preventDefault();
                }
                break;
            case 9: //Tab
                break;
        }
    } else if (e.type == 'keyup') {
        switch (e.keyCode) {
            case 38: break;
            case 40: break;
            case 9:
                     insert(ssAcList[suggest.picked]);
                     //when tab was pressed again, focus move next widget
                     //I would like to use preventDefault() method like del.icio.us, but they don't work. I have no idea I solve that probrem.
                     suggest.tabfocus ++;
                     break;
            default: 
                     suggest.init();
                     suggest.picked = 0;
                     suggesting();
        }
    } else {
        suggest.init();
        suggest.picked = 0;
        suggesting();
    }
}

function suggesting() {
    //delete all suggest list
    if($('sugg').hasChildNodes()){
        $('sugg').removeChild($('sugg').childNodes[0]);
    }
// change start (fututure update)
    var words = cutWord();
    var inpl = words[2];
//change end (future update)
    inp = inpl.split(',')[0];
    inp = inp.trim();
    if(inp.length > 0){
        makeSuggList(inp);
    }
}

function insert(a) {
    var iwl = a.length;

    var words = cutWord();
    var fword = words[0];
    var lword = words[1];

//    opera.postError('f:' + fword + ',n:' + words[1] + ',l:'+ lword);
    $('ac').value = (fword) ? fword + ' ' + a + ' ' + lword : a + ' ' + lword;
    $('ac').focus();

    setCaretPosition($('ac'),fword.length+iwl+2);
    suggest.init();	
    suggesting();
}

//output caret postion 
function cutWord(){
    var cutwords = [];
    var inp = $('ac').value;

    var carp = doGetCaretPosition($('ac'));
    var inpf = inp.substring(0,carp);
    var sf_nums = [inpf.lastIndexOf('&'),
            inpf.lastIndexOf('+'),
            inpf.lastIndexOf('>'),
            inpf.lastIndexOf('|')
            ];
    sf_nums.sort();
    var fn = sf_nums.pop() + 1;
    cutwords.push(inp.substring(0,fn));

    var inpl = inp.substring(carp,inp.length);
    var sl_nums = [inpl.indexOf('&'),
            inpl.indexOf('+'),
            inpl.indexOf('>'),
            inpl.indexOf('|')
            ];
    sl_nums.sort();
    var ln = -1;
    for(var i=0,len=sl_nums.length;i<len;i++){
        if(sl_nums[i] != -1){ //cant'find separator
            ln = sl_nums[i];
            break;
        }
    }
    if(ln != -1){
        cutwords.push(inpl.substring(ln,inpl.length));
    } else {
        cutwords.push('');
    }

    var nwl = (ln == -1) ? inp.length : ln-1;
    cutwords.push(inp.substring(fn,carp+nwl));

    return cutwords;
}

// http://blog.vishalon.net/Post/57.aspx

function doGetCaretPosition (ctrl) {
    var CaretPos = 0;
    // IE Support
    if (document.selection) {
        ctrl.focus();
        var Sel = document.selection.createRange();
        Sel.moveStart ('character', -ctrl.value.length);
        CaretPos = Sel.text.length;
    }
    // Firefox support
    else if (ctrl.selectionStart || ctrl.selectionStart == '0')
        CaretPos = ctrl.selectionStart;
    return (CaretPos);
}

function setCaretPosition(ctrl, pos) {
    if(ctrl.setSelectionRange) {
        ctrl.focus();
        ctrl.setSelectionRange(pos,pos);
    }
    else if (ctrl.createTextRange) {
        var range = ctrl.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
    }
}

//function $(id) {
//    return document.getElementById(id);
//}

//http://jsgt.org/mt/archives/01/001175.html
function $(e){
    return $[e]||($[e]=(document.getElementById(e)||e));
}


String.prototype.trim = function (){
    return this.replace(/^\s+|\s+$/,'');
}


//bench Function speed
//http://d.hatena.ne.jp/nazoking/20050916/1126868725
//To use: FuncName = FuncName.bench("Time:");

Function.prototype.bench = function(st){
    var self = this; // 実行時間を計りたい関数
    return function(){
        var start = new Date().getTime();
        var res = self.apply(this,arguments);
        var end = new Date().getTime();
        opera.postError(st+":"+(end-start)); // output to js console 
        return res;
    }
}
