﻿/* ********************************************************************
 **********************************************************************
 * HTML Virtual Keyboard Interface Script - v1.43
 *   Copyright (c) 2010
 *
  */
var VKI_attach, VKI_close;
(function VKI_buildKeyboardInputs() {
    var self = this;

    this.VKI_version = "1.43";
    this.VKI_showVersion = false;
    this.VKI_target = false;
    this.VKI_shift = this.VKI_shiftlock = false;
    this.VKI_altgr = this.VKI_altgrlock = false;
    this.VKI_dead = false;
    this.VKI_deadBox = false; // Show the dead keys checkbox
    this.VKI_deadkeysOn = false;  // Turn dead keys on by default
    this.VKI_numberPad = false;  // Allow user to open and close the number pad
    this.VKI_numberPadOn = false;  // Show number pad by default
    this.VKI_kts = this.VKI_kt = "فارسی";  // Default keyboard layout
    this.VKI_langAdapt = true;  // Use lang attribute of input to select keyboard
    this.VKI_size = 2;  // Default keyboard size (1-5)
    this.VKI_sizeAdj = true;  // Allow user to adjust keyboard size
    this.VKI_clearPasswords = false;  // Clear password fields on focus
    this.VKI_imageURI = "/Keyboard/keyboard.gif";  // If empty string, use imageless mode
    this.VKI_clickless = 0;  // 0 = disabled, > 0 = delay in ms
    this.VKI_keyCenter = 3;

    this.VKI_isIE = /*@cc_on!@*/false;
    this.VKI_isIE6 = /*@if(@_jscript_version == 5.6)!@end@*/false;
    this.VKI_isIElt8 = /*@if(@_jscript_version < 5.8)!@end@*/false;
    this.VKI_isWebKit = RegExp("KHTML").test(navigator.userAgent);
    this.VKI_isOpera = RegExp("Opera").test(navigator.userAgent);
    this.VKI_isMoz = (!this.VKI_isWebKit && navigator.product == "Gecko");

    /* ***** i18n text strings ************************************* */
    this.VKI_i18n = {
        '00': "نمايش اعداد",
        '01': "نمايش صفحه کليد مجازي",
        '02': "انتخاب زبان",
        '03': "Dead keys",
        '04': "روشن",
        '05': "خاموش",
        '06': "بستن صفحه کليد",
        '07': "پاک کردن",
        '08': "پاک کردن اين فيلد",
        '09': "نسخه",
        '10': "کاهش اندازه صفحه کليد",
        '11': "افزايش اندازه صفحه کليد"
    };


    /* ***** Create keyboards ************************************** */
    this.VKI_layout = {};

    this.VKI_layout['\u0641\u0627\u0631\u0633\u06cc'] = {
        'name': "Farsi", 'keys': [
      [["\u067e", "\u0651 "], ["1", "!", "\u00a1", "\u00b9"], ["2", "@", "\u00b2"], ["3", "#", "\u00b3"], ["4", "$", "\u00a4", "\u00a3"], ["5", "%", "\u20ac"], ["6", "^", "\u00bc"], ["7", "&", "\u00bd"], ["8", "*", "\u00be"], ["9", "(", "\u2018"], ["0", ")", "\u2019"], ["-", "_", "\u00a5"], ["=", "+", "\u00d7", "\u00f7"], ["Bksp", "Bksp"]],
      [["Tab", "Tab"], ["\u0636", "\u064e"], ["\u0635", "\u064b"], ["\u062b", "\u064f"], ["\u0642", "\u064c"], ["\u0641", "\u0644"], ["\u063a", "\u0625"], ["\u0639", "\u2018"], ["\u0647", "\u00f7"], ["\u062e", "\u00d7"], ["\u062d", "\u061b"], ["\u062c", "<"], ["\u0686", ">"], ["\u0698", "|"]],
      [["Caps", "Caps"], ["\u0634", "\u0650"], ["\u0633", "\u064d"], ["\u06cc", "]"], ["\u0628", "["], ["\u0644", "\u0644"], ["\u0627", "\u0623"], ["\u062a", "\u0640"], ["\u0646", "\u060c"], ["\u0645", "\\"], ["\u06a9", '"'], ["\u06af", ":"], ["Enter", "Enter"]],
      [["Shift", "Shift"], ["\u0638", "~"], ["\u0637", "\u0652"], ["\u0632", "}"], ["\u0631", "{"], ["\u0630", "\u0644"], ["\u062f", "\u0622"], ["\u0621", "\u0621"], ["\u0648", ","], [".", "."], ["/", "\u061f"], ["Shift", "Shift"]],
      [[" ", " ", " ", " "], ["Alt", "Alt"]]
    ], 'lang': ["fa"]
    };


    /* ***** Define Dead Keys ************************************** */
    this.VKI_deadkey = {};


    this.VKI_deadkey['"'] = this.VKI_deadkey['\u00a8'] = this.VKI_deadkey['\u309B'] = { // Umlaut / Diaeresis / Greek Dialytika / Hiragana/Katakana Voiced Sound Mark
        'a': "\u00e4", 'e': "\u00eb", 'i': "\u00ef", 'o': "\u00f6", 'u': "\u00fc", 'y': "\u00ff", '\u03b9': "\u03ca", '\u03c5': "\u03cb", '\u016B': "\u01D6", '\u00FA': "\u01D8", '\u01D4': "\u01DA", '\u00F9': "\u01DC",
        'A': "\u00c4", 'E': "\u00cb", 'I': "\u00cf", 'O': "\u00d6", 'U': "\u00dc", 'Y': "\u0178", '\u0399': "\u03aa", '\u03a5': "\u03ab", '\u016A': "\u01D5", '\u00DA': "\u01D7", '\u01D3': "\u01D9", '\u00D9': "\u01DB",
        '\u304b': "\u304c", '\u304d': "\u304e", '\u304f': "\u3050", '\u3051': "\u3052", '\u3053': "\u3054", '\u305f': "\u3060", '\u3061': "\u3062", '\u3064': "\u3065", '\u3066': "\u3067", '\u3068': "\u3069",
        '\u3055': "\u3056", '\u3057': "\u3058", '\u3059': "\u305a", '\u305b': "\u305c", '\u305d': "\u305e", '\u306f': "\u3070", '\u3072': "\u3073", '\u3075': "\u3076", '\u3078': "\u3079", '\u307b': "\u307c",
        '\u30ab': "\u30ac", '\u30ad': "\u30ae", '\u30af': "\u30b0", '\u30b1': "\u30b2", '\u30b3': "\u30b4", '\u30bf': "\u30c0", '\u30c1': "\u30c2", '\u30c4': "\u30c5", '\u30c6': "\u30c7", '\u30c8': "\u30c9",
        '\u30b5': "\u30b6", '\u30b7': "\u30b8", '\u30b9': "\u30ba", '\u30bb': "\u30bc", '\u30bd': "\u30be", '\u30cf': "\u30d0", '\u30d2': "\u30d3", '\u30d5': "\u30d6", '\u30d8': "\u30d9", '\u30db': "\u30dc"
    };

    /* ***** Define Symbols **************************************** */
    this.VKI_symbol = {
        '\u00a0': "NB\nSP", '\u200b': "ZW\nSP", '\u200c': "ZW\nNJ", '\u200d': "ZW\nJ"
    };


    /* ***** Layout Number Pad ************************************* */
    this.VKI_numpad = [
    [["$"], ["\u00a3"], ["\u20ac"], ["\u00a5"]],
    [["7"], ["8"], ["9"], ["/"]],
    [["4"], ["5"], ["6"], ["*"]],
    [["1"], ["2"], ["3"], ["-"]],
    [["0"], ["."], ["="], ["+"]]
  ];


    /* ****************************************************************
    * Attach the keyboard to an element
    *
    */
    this.VKI_attachKeyboard = VKI_attach = function(elem) {
        if (elem.getAttribute("VKI_attached")) return false;
        if (this.VKI_imageURI) {
            var keybut = document.createElement('img');
            keybut.src = this.VKI_imageURI;
            keybut.alt = this.VKI_i18n['00'];
            keybut.className = "keyboardInputInitiator";
            keybut.title = this.VKI_i18n['01'];
            keybut.elem = elem;
            keybut.onclick = function(e) {
                e = e || event;
                if (e.stopPropagation) { e.stopPropagation(); } else e.cancelBubble = true;
                self.VKI_show(this.elem);
            };
            elem.parentNode.insertBefore(keybut, (elem.dir == "rtl") ? elem : elem.nextSibling);
        } else elem.onfocus = function() { if (self.VKI_target != this) self.VKI_show(this); };
        elem.setAttribute("VKI_attached", 'true');
        if (this.VKI_isIE) {
            elem.onclick = elem.onselect = elem.onkeyup = function(e) {
                if ((e || event).type != "keyup" || !this.readOnly)
                    this.range = document.selection.createRange();
            };
        }
        VKI_addListener(elem, 'click', function(e) {
            if (self.VKI_target == this) {
                e = e || event;
                if (e.stopPropagation) { e.stopPropagation(); } else e.cancelBubble = true;
            } return false;
        }, false);
    };


    /* ***** Find tagged input & textarea elements ***************** */
    var inputElems = [
    document.getElementsByTagName('input'),
    document.getElementsByTagName('textarea')
  ];
    for (var x = 0, elem; elem = inputElems[x++]; )
        for (var y = 0, ex; ex = elem[y++]; )
        if ((ex.nodeName == "TEXTAREA" || ex.type == "text" || ex.type == "password") && ex.className.indexOf("keyboardInput") > -1)
        this.VKI_attachKeyboard(ex);

    VKI_addListener(document.documentElement, 'click', function(e) { self.VKI_close(); }, false);


    /* ****************************************************************
    * Common mouse event actions
    *
    */
    function VKI_mouseEvents(elem) {
        if (elem.nodeName == "TD") {
            if (!elem.click) elem.click = function() {
                var evt = this.ownerDocument.createEvent('MouseEvents');
                evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
                this.dispatchEvent(evt);
            };
            elem.VKI_clickless = 0;
            VKI_addListener(elem, 'dblclick', function() { return false; }, false);
        }
        VKI_addListener(elem, 'mouseover', function() {
            if (this.nodeName == "TD" && self.VKI_clickless) {
                var _self = this;
                clearTimeout(this.VKI_clickless);
                this.VKI_clickless = setTimeout(function() { _self.click(); }, self.VKI_clickless);
            }
            if (self.VKI_isIE) this.className += " hover";
        }, false);
        VKI_addListener(elem, 'mouseout', function() {
            if (this.nodeName == "TD") clearTimeout(this.VKI_clickless);
            if (self.VKI_isIE) this.className = this.className.replace(/ ?(hover|pressed) ?/g, "");
        }, false);
        VKI_addListener(elem, 'mousedown', function() {
            if (this.nodeName == "TD") clearTimeout(this.VKI_clickless);
            if (self.VKI_isIE) this.className += " pressed";
        }, false);
        VKI_addListener(elem, 'mouseup', function() {
            if (this.nodeName == "TD") clearTimeout(this.VKI_clickless);
            if (self.VKI_isIE) this.className = this.className.replace(/ ?pressed ?/g, "");
        }, false);
    }


    /* ***** Build the keyboard interface ************************** */
    this.VKI_keyboard = document.createElement('table');
    this.VKI_keyboard.id = "keyboardInputMaster";
    this.VKI_keyboard.dir = "ltr";
    this.VKI_keyboard.cellSpacing = "0";
    this.VKI_keyboard.reflow = function() {
        this.style.width = "50px";
        var foo = this.offsetWidth;
        this.style.width = "";
    };
    VKI_addListener(this.VKI_keyboard, 'click', function(e) {
        e = e || event;
        if (e.stopPropagation) { e.stopPropagation(); } else e.cancelBubble = true;
        return false;
    }, false);

    if (!this.VKI_layout[this.VKI_kt])
        return alert('No keyboard named "' + this.VKI_kt + '"');

    var thead = document.createElement('thead');
    var tr = document.createElement('tr');
    var th = document.createElement('th');
    th.colSpan = "2";

    var kbSelect = document.createElement('div');
    kbSelect.title = this.VKI_i18n['02'];
    VKI_addListener(kbSelect, 'click', function() {
        var ol = this.getElementsByTagName('ol')[0];
        if (!ol.style.display) {
            ol.style.display = "block";
            var li = ol.getElementsByTagName('li');
            for (var x = 0, scr = 0; x < li.length; x++) {
                if (VKI_kt == li[x].firstChild.nodeValue) {
                    li[x].className = "selected";
                    scr = li[x].offsetTop - li[x].offsetHeight * 2;
                } else li[x].className = "";
            } setTimeout(function() { ol.scrollTop = scr; }, 0);
        } else ol.style.display = "";
    }, false);
    kbSelect.appendChild(document.createTextNode(this.VKI_kt));
    kbSelect.appendChild(document.createTextNode(this.VKI_isIE6 ? " \u2193" : " \u25be"));
    var ol = document.createElement('ol');

    for (ktype in this.VKI_layout) {
        if (typeof this.VKI_layout[ktype] == "object") {
            if (!this.VKI_layout[ktype].lang) this.VKI_layout[ktype].lang = [];
            var li = document.createElement('li');

            li.title = this.VKI_layout[ktype].name;
            VKI_addListener(li, 'click', function(e) {
                e = e || event;
                if (e.stopPropagation) { e.stopPropagation(); } else e.cancelBubble = true;
                this.parentNode.style.display = "";
                self.VKI_kts = self.VKI_kt = kbSelect.firstChild.nodeValue = this.firstChild.nodeValue;
                self.VKI_buildKeys();
                self.VKI_position(true);
            }, false);
            VKI_mouseEvents(li);
            li.appendChild(document.createTextNode(ktype));
            ol.appendChild(li);
        }
    } kbSelect.appendChild(ol);
    th.appendChild(kbSelect);

    //Remove Language Selection Feature By AliReza Esmaeili
    kbSelect.style.display = 'none';

    if (this.VKI_numberPad) {
        var span = document.createElement('span');
        span.appendChild(document.createTextNode("#"));
        span.title = this.VKI_i18n['00'];
        VKI_addListener(span, 'click', function() {
            kbNumpad.style.display = (!kbNumpad.style.display) ? "none" : "";
            self.VKI_position(true);
        }, false);
        VKI_mouseEvents(span);
        th.appendChild(span);
    }

    this.VKI_kbsize = function(e) {
        self.VKI_size = Math.min(5, Math.max(1, self.VKI_size));
        self.VKI_keyboard.className = self.VKI_keyboard.className.replace(/ ?keyboardInputSize\d ?/, "");
        if (self.VKI_size != 2) self.VKI_keyboard.className += " keyboardInputSize" + self.VKI_size;
        self.VKI_position(true);
        if (self.VKI_isOpera) self.VKI_keyboard.reflow();
    };
    if (this.VKI_sizeAdj) {
        var small = document.createElement('small');
        small.title = this.VKI_i18n['10'];
        VKI_addListener(small, 'click', function() {
            --self.VKI_size;
            self.VKI_kbsize();
        }, false);
        VKI_mouseEvents(small);
        small.appendChild(document.createTextNode(this.VKI_isIE6 ? "\u2193" : "\u21d3"));
        th.appendChild(small);
        var big = document.createElement('big');
        big.title = this.VKI_i18n['11'];
        VKI_addListener(big, 'click', function() {
            ++self.VKI_size;
            self.VKI_kbsize();
        }, false);
        VKI_mouseEvents(big);
        big.appendChild(document.createTextNode(this.VKI_isIE6 ? "\u2191" : "\u21d1"));
        th.appendChild(big);
    }

    var span = document.createElement('span');
    span.appendChild(document.createTextNode(this.VKI_i18n['07']));
    span.title = this.VKI_i18n['08'];
    VKI_addListener(span, 'click', function() {
        self.VKI_target.value = "";
        self.VKI_target.focus();
        return false;
    }, false);
    VKI_mouseEvents(span);
    th.appendChild(span);

    var strong = document.createElement('strong');
    strong.appendChild(document.createTextNode('X'));
    strong.title = this.VKI_i18n['06'];
    VKI_addListener(strong, 'click', function() { self.VKI_close(); }, false);
    VKI_mouseEvents(strong);
    th.appendChild(strong);

    tr.appendChild(th);
    thead.appendChild(tr);
    this.VKI_keyboard.appendChild(thead);

    var tbody = document.createElement('tbody');
    var tr = document.createElement('tr');
    var td = document.createElement('td');
    var div = document.createElement('div');

    if (this.VKI_deadBox) {
        var label = document.createElement('label');
        var checkbox = document.createElement('input');
        checkbox.type = "checkbox";
        checkbox.title = this.VKI_i18n['03'] + ": " + ((this.VKI_deadkeysOn) ? this.VKI_i18n['04'] : this.VKI_i18n['05']);
        checkbox.defaultChecked = this.VKI_deadkeysOn;
        VKI_addListener(checkbox, 'click', function() {
            this.title = self.VKI_i18n['03'] + ": " + ((this.checked) ? self.VKI_i18n['04'] : self.VKI_i18n['05']);
            self.VKI_modify("");
            return true;
        }, false);
        label.appendChild(checkbox);
        checkbox.checked = this.VKI_deadkeysOn;
        div.appendChild(label);
        this.VKI_deadkeysOn = checkbox;
    } else this.VKI_deadkeysOn.checked = this.VKI_deadkeysOn;

    if (this.VKI_showVersion) {
        var vr = document.createElement('var');
        vr.title = this.VKI_i18n['09'] + " " + this.VKI_version;
        vr.appendChild(document.createTextNode("v" + this.VKI_version));
        div.appendChild(vr);
    } td.appendChild(div);
    tr.appendChild(td);

    var kbNumpad = document.createElement('td');
    kbNumpad.id = "keyboardInputNumpad";
    if (!this.VKI_numberPadOn) kbNumpad.style.display = "none";
    var ntable = document.createElement('table');
    ntable.cellSpacing = "0";
    var ntbody = document.createElement('tbody');
    for (var x = 0; x < this.VKI_numpad.length; x++) {
        var ntr = document.createElement('tr');
        for (var y = 0; y < this.VKI_numpad[x].length; y++) {
            var ntd = document.createElement('td');
            VKI_addListener(ntd, 'click', VKI_keyClick, false);
            VKI_mouseEvents(ntd);
            ntd.appendChild(document.createTextNode(this.VKI_numpad[x][y]));
            ntr.appendChild(ntd);
        } ntbody.appendChild(ntr);
    } ntable.appendChild(ntbody);
    kbNumpad.appendChild(ntable);
    tr.appendChild(kbNumpad);
    tbody.appendChild(tr);
    this.VKI_keyboard.appendChild(tbody);

    if (this.VKI_isIE6) {
        this.VKI_iframe = document.createElement('iframe');
        this.VKI_iframe.style.position = "absolute";
        this.VKI_iframe.style.border = "0px none";
        this.VKI_iframe.style.filter = "mask()";
        this.VKI_iframe.style.zIndex = "999999";
        this.VKI_iframe.src = this.VKI_imageURI;
    }


    /* ****************************************************************
    * Private table cell attachment function for generic characters
    *
    */
    function VKI_keyClick() {
        var done = false, character = "\xa0";
        if (this.firstChild.nodeName.toLowerCase() != "small") {
            if ((character = this.firstChild.nodeValue) == "\xa0") return false;
        } else character = this.firstChild.getAttribute('char');
        if (self.VKI_deadkeysOn.checked && self.VKI_dead) {
            if (self.VKI_dead != character) {
                if (character != " ") {
                    if (self.VKI_deadkey[self.VKI_dead][character]) {
                        self.VKI_insert(self.VKI_deadkey[self.VKI_dead][character]);
                        done = true;
                    }
                } else {
                    self.VKI_insert(self.VKI_dead);
                    done = true;
                }
            } else done = true;
        } self.VKI_dead = false;

        if (!done) {
            if (self.VKI_deadkeysOn.checked && self.VKI_deadkey[character]) {
                self.VKI_dead = character;
                this.className += " dead";
                if (self.VKI_shift) self.VKI_modify("Shift");
                if (self.VKI_altgr) self.VKI_modify("AltGr");
            } else self.VKI_insert(character);
        } self.VKI_modify("");
        return false;
    }


    /* ****************************************************************
    * Build or rebuild the keyboard keys
    *
    */
    this.VKI_buildKeys = function() {
        this.VKI_shift = this.VKI_shiftlock = this.VKI_altgr = this.VKI_altgrlock = this.VKI_dead = false;
        var container = this.VKI_keyboard.tBodies[0].getElementsByTagName('div')[0];
        var tables = container.getElementsByTagName('table');
        for (var x = tables.length - 1; x >= 0; x--) container.removeChild(tables[x]);

        for (var x = 0, hasDeadKey = false, lyt; lyt = this.VKI_layout[this.VKI_kt].keys[x++]; ) {
            var table = document.createElement('table');
            table.cellSpacing = "0";
            if (lyt.length <= this.VKI_keyCenter) table.className = "keyboardInputCenter";
            var tbody = document.createElement('tbody');
            var tr = document.createElement('tr');
            for (var y = 0, lkey; lkey = lyt[y++]; ) {
                var td = document.createElement('td');
                if (this.VKI_symbol[lkey[0]]) {
                    var text = this.VKI_symbol[lkey[0]].split("\n");
                    var small = document.createElement('small');
                    small.setAttribute('char', lkey[0]);
                    for (var z = 0; z < text.length; z++) {
                        if (z) small.appendChild(document.createElement("br"));
                        small.appendChild(document.createTextNode(text[z]));
                    } td.appendChild(small);
                } else td.appendChild(document.createTextNode(lkey[0] || "\xa0"));

                var className = [];
                if (this.VKI_deadkeysOn.checked)
                    for (key in this.VKI_deadkey)
                    if (key === lkey[0]) { className.push("deadkey"); break; }
                if (lyt.length > this.VKI_keyCenter && y == lyt.length) className.push("last");
                if (lkey[0] == " " || lkey[1] == " ") className.push("space");

                //HACK: Gooya, disable these key
                //Shift, Alt, Tab, Caps
                if (lkey[0] == "Shift" || lkey[1] == "Shift") className.push("disableKeys");
                if (lkey[0] == "Alt" || lkey[1] == "Alt") className.push("disableKeys");
                if (lkey[0] == "Tab" || lkey[1] == "Tab") className.push("disableKeys");
                if (lkey[0] == "Caps" || lkey[1] == "Caps") className.push("disableKeys");
                
                td.className = className.join(" ");

                

                switch (lkey[1]) {
                    case "Shift":
                    case "Caps":
                    case "Alt": case "AltGr": case "AltLk":
                        //VKI_addListener(td, 'click', (function(type) { return function() { self.VKI_modify(type); return false; }})(lkey[1]), false);
                        break;
                    case "Tab":
                        //VKI_addListener(td, 'click', function() { self.VKI_insert("\t"); return false; }, false);
                        break;
                    case "Bksp":
                        VKI_addListener(td, 'click', function() {
                            self.VKI_target.focus();
                            if (self.VKI_target.setSelectionRange && !self.VKI_target.readOnly) {
                                var rng = [self.VKI_target.selectionStart, self.VKI_target.selectionEnd];
                                if (rng[0] < rng[1]) rng[0]++;
                                self.VKI_target.value = self.VKI_target.value.substr(0, rng[0] - 1) + self.VKI_target.value.substr(rng[1]);
                                self.VKI_target.setSelectionRange(rng[0] - 1, rng[0] - 1);
                            } else if (self.VKI_target.createTextRange && !self.VKI_target.readOnly) {
                                try {
                                    self.VKI_target.range.select();
                                } catch (e) { self.VKI_target.range = document.selection.createRange(); }
                                if (!self.VKI_target.range.text.length) self.VKI_target.range.moveStart('character', -1);
                                self.VKI_target.range.text = "";
                            } else self.VKI_target.value = self.VKI_target.value.substr(0, self.VKI_target.value.length - 1);
                            if (self.VKI_shift) self.VKI_modify("Shift");
                            if (self.VKI_altgr) self.VKI_modify("AltGr");
                            self.VKI_target.focus();
                            return true;
                        }, false);
                        break;
                    case "Enter":
                        VKI_addListener(td, 'click', function() {
                            if (self.VKI_target.nodeName != "TEXTAREA") {
                                if (self.VKI_target.form) {
                                    for (var z = 0, subm = false; z < self.VKI_target.form.elements.length; z++)
                                        if (self.VKI_target.form.elements[z].type == "submit") subm = true;
                                    if (!subm) self.VKI_target.form.submit();
                                }
                                self.VKI_close();
                            } else self.VKI_insert("\n");
                            return true;
                        }, false);
                        break;
                    default:
                        VKI_addListener(td, 'click', VKI_keyClick, false);

                } VKI_mouseEvents(td);
                tr.appendChild(td);
                for (var z = 0; z < 4; z++)
                    if (this.VKI_deadkey[lkey[z] = lkey[z] || ""]) hasDeadKey = true;
            } tbody.appendChild(tr);
            table.appendChild(tbody);
            container.appendChild(table);
        }
        if (this.VKI_deadBox)
            this.VKI_deadkeysOn.style.display = (hasDeadKey) ? "inline" : "none";
        if (this.VKI_isIE6) {
            this.VKI_iframe.style.width = this.VKI_keyboard.offsetWidth + "px";
            this.VKI_iframe.style.height = this.VKI_keyboard.offsetHeight + "px";
        }
    };

    this.VKI_buildKeys();
    VKI_addListener(this.VKI_keyboard, 'selectstart', function() { return false; }, false);
    this.VKI_keyboard.unselectable = "on";
    if (this.VKI_isOpera)
        VKI_addListener(this.VKI_keyboard, 'mousedown', function() { return false; }, false);


    /* ****************************************************************
    * Controls modifier keys
    *
    */
    this.VKI_modify = function(type) {
        switch (type) {
            case "Alt":
            case "AltGr": this.VKI_altgr = !this.VKI_altgr; break;
            case "AltLk": this.VKI_altgr = 0; this.VKI_altgrlock = !this.VKI_altgrlock; break;
            case "Caps": this.VKI_shift = 0; this.VKI_shiftlock = !this.VKI_shiftlock; break;
            case "Shift": this.VKI_shift = !this.VKI_shift; break;
        } var vchar = 0;
        if (!this.VKI_shift != !this.VKI_shiftlock) vchar += 1;
        if (!this.VKI_altgr != !this.VKI_altgrlock) vchar += 2;

        var tables = this.VKI_keyboard.tBodies[0].getElementsByTagName('div')[0].getElementsByTagName('table');
        for (var x = 0; x < tables.length; x++) {
            var tds = tables[x].getElementsByTagName('td');
            for (var y = 0; y < tds.length; y++) {
                var className = [], lkey = this.VKI_layout[this.VKI_kt].keys[x][y];

                switch (lkey[1]) {
                    case "Alt":
                    case "AltGr":
                        if (this.VKI_altgr) className.push("pressed");
                        break;
                    case "AltLk":
                        if (this.VKI_altgrlock) className.push("pressed");
                        break;
                    case "Shift":
                        if (this.VKI_shift) className.push("pressed");
                        break;
                    case "Caps":
                        if (this.VKI_shiftlock) className.push("pressed");
                        break;
                    case "Tab": case "Enter": case "Bksp": break;
                    default:
                        if (type) {
                            tds[y].removeChild(tds[y].firstChild);
                            if (this.VKI_symbol[lkey[vchar]]) {
                                var text = this.VKI_symbol[lkey[vchar]].split("\n");
                                var small = document.createElement('small');
                                small.setAttribute('char', lkey[vchar]);
                                for (var z = 0; z < text.length; z++) {
                                    if (z) small.appendChild(document.createElement("br"));
                                    small.appendChild(document.createTextNode(text[z]));
                                } tds[y].appendChild(small);
                            } else tds[y].appendChild(document.createTextNode(lkey[vchar] || "\xa0"));
                        }
                        if (this.VKI_deadkeysOn.checked) {
                            var character = tds[y].firstChild.nodeValue || tds[y].firstChild.className;
                            if (this.VKI_dead) {
                                if (character == this.VKI_dead) className.push("pressed");
                                if (this.VKI_deadkey[this.VKI_dead][character]) className.push("target");
                            }
                            if (this.VKI_deadkey[character]) className.push("deadkey");
                        }
                }

                if (y == tds.length - 1 && tds.length > this.VKI_keyCenter) className.push("last");
                if (lkey[0] == " " || lkey[1] == " ") className.push("space");

                //HACK: Gooya, disable these key
                //Shift, Alt, Tab, Caps
                if (lkey[0] == "Shift" || lkey[1] == "Shift") className.push("disableKeys");
                if (lkey[0] == "Alt" || lkey[1] == "Alt") className.push("disableKeys");
                if (lkey[0] == "Tab" || lkey[1] == "Tab") className.push("disableKeys");
                if (lkey[0] == "Caps" || lkey[1] == "Caps") className.push("disableKeys");
                
                tds[y].className = className.join(" ");
            }
        }
    };


    /* ****************************************************************
    * Insert text at the cursor
    *
    */
    this.VKI_insert = function(text) {
        this.VKI_target.focus();
        if (this.VKI_target.maxLength) this.VKI_target.maxlength = this.VKI_target.maxLength;
        if (typeof this.VKI_target.maxlength == "undefined" ||
        this.VKI_target.maxlength < 0 ||
        this.VKI_target.value.length < this.VKI_target.maxlength) {
            if (this.VKI_target.setSelectionRange && !this.VKI_target.readOnly && !this.VKI_isIE) {
                var rng = [this.VKI_target.selectionStart, this.VKI_target.selectionEnd];
                this.VKI_target.value = this.VKI_target.value.substr(0, rng[0]) + text + this.VKI_target.value.substr(rng[1]);
                if (text == "\n" && this.VKI_isOpera) rng[0]++;
                this.VKI_target.setSelectionRange(rng[0] + text.length, rng[0] + text.length);
            } else if (this.VKI_target.createTextRange && !this.VKI_target.readOnly) {
                try {
                    this.VKI_target.range.select();
                } catch (e) { this.VKI_target.range = document.selection.createRange(); }
                this.VKI_target.range.text = text;
                this.VKI_target.range.collapse(true);
                this.VKI_target.range.select();
            } else this.VKI_target.value += text;
            if (this.VKI_shift) this.VKI_modify("Shift");
            if (this.VKI_altgr) this.VKI_modify("AltGr");
            this.VKI_target.focus();
        } else if (this.VKI_target.createTextRange && this.VKI_target.range)
            this.VKI_target.range.select();
    };


    /* ****************************************************************
    * Show the keyboard interface
    *
    */
    this.VKI_show = function(elem) {
        if (!this.VKI_target) {
            this.VKI_target = elem;
            if (this.VKI_langAdapt && this.VKI_target.lang) {
                var chg = false, sub = [];
                for (ktype in this.VKI_layout) {
                    if (typeof this.VKI_layout[ktype] == "object") {
                        for (var x = 0; x < this.VKI_layout[ktype].lang.length; x++) {
                            if (this.VKI_layout[ktype].lang[x].toLowerCase() == this.VKI_target.lang.toLowerCase()) {
                                chg = kbSelect.firstChild.nodeValue = this.VKI_kt = ktype;
                                break;
                            } else if (this.VKI_layout[ktype].lang[x].toLowerCase().indexOf(this.VKI_target.lang.toLowerCase()) == 0)
                                sub.push([this.VKI_layout[ktype].lang[x], ktype]);
                        }
                    } if (chg) break;
                } if (sub.length) {
                    sub.sort(function(a, b) { return a[0].length - b[0].length; });
                    chg = kbSelect.firstChild.nodeValue = this.VKI_kt = sub[0][1];
                } if (chg) this.VKI_buildKeys();
            }
            if (this.VKI_isIE) {
                if (!this.VKI_target.range) {
                    this.VKI_target.range = this.VKI_target.createTextRange();
                    this.VKI_target.range.moveStart('character', this.VKI_target.value.length);
                } this.VKI_target.range.select();
            }
            try { this.VKI_keyboard.parentNode.removeChild(this.VKI_keyboard); } catch (e) { }
            if (this.VKI_clearPasswords && this.VKI_target.type == "password") this.VKI_target.value = "";

            var elem = this.VKI_target;
            this.VKI_target.keyboardPosition = "absolute";
            do {
                if (VKI_getStyle(elem, "position") == "fixed") {
                    this.VKI_target.keyboardPosition = "fixed";
                    break;
                }
            } while (elem = elem.offsetParent);

            if (this.VKI_isIE6) document.body.appendChild(this.VKI_iframe);
            document.body.appendChild(this.VKI_keyboard);
            this.VKI_keyboard.style.position = this.VKI_target.keyboardPosition;
            if (this.VKI_isOpera) this.VKI_keyboard.reflow();

            this.VKI_position(true);
            if (self.VKI_isMoz || self.VKI_isWebKit) this.VKI_position(true);
            this.VKI_target.blur();
            this.VKI_target.focus();
        } else this.VKI_close();
    };


    /* ****************************************************************
    * Position the keyboard
    *
    */
    this.VKI_position = function(force) {
        if (self.VKI_target) {
            var kPos = VKI_findPos(self.VKI_keyboard), wDim = VKI_innerDimensions(), sDis = VKI_scrollDist();
            var place = false, fudge = self.VKI_target.offsetHeight + 3;
            if (force !== true) {
                if (kPos[1] + self.VKI_keyboard.offsetHeight - sDis[1] - wDim[1] > 0) {
                    place = true;
                    fudge = -self.VKI_keyboard.offsetHeight - 3;
                } else if (kPos[1] - sDis[1] < 0) place = true;
            }
            if (place || force === true) {
                var iPos = VKI_findPos(self.VKI_target);
                self.VKI_keyboard.style.top = iPos[1] - ((self.VKI_target.keyboardPosition == "fixed" && !self.VKI_isIE && !self.VKI_isMoz) ? sDis[1] : 0) + fudge + "px";
                self.VKI_keyboard.style.left = Math.max(10, Math.min(wDim[0] - self.VKI_keyboard.offsetWidth - 25, iPos[0])) + "px";
                if (self.VKI_isIE6) {
                    self.VKI_iframe.style.width = self.VKI_keyboard.offsetWidth + "px";
                    self.VKI_iframe.style.height = self.VKI_keyboard.offsetHeight + "px";
                    self.VKI_iframe.style.top = self.VKI_keyboard.style.top;
                    self.VKI_iframe.style.left = self.VKI_keyboard.style.left;
                }
            }
            if (force === true) self.VKI_position();
        }
    };


    /* ****************************************************************
    * Close the keyboard interface
    *
    */
    this.VKI_close = VKI_close = function() {
        if (this.VKI_target) {
            try {
                this.VKI_keyboard.parentNode.removeChild(this.VKI_keyboard);
                if (this.VKI_isIE6) this.VKI_iframe.parentNode.removeChild(this.VKI_iframe);
            } catch (e) { }
            if (this.VKI_kt != this.VKI_kts) {
                kbSelect.firstChild.nodeValue = this.VKI_kt = this.VKI_kts;
                this.VKI_buildKeys();
            } kbSelect.getElementsByTagName('ol')[0].style.display = ""; ;
            this.VKI_target.focus();
            if (this.VKI_isIE) {
                setTimeout(function() { self.VKI_target = false; }, 0);
            } else this.VKI_target = false;
        }
    };


    /* ***** Private functions *************************************** */
    function VKI_addListener(elem, type, func, cap) {
        if (elem.addEventListener) {
            elem.addEventListener(type, function(e) { func.call(elem, e); }, cap);
        } else if (elem.attachEvent)
            elem.attachEvent('on' + type, function() { func.call(elem); });
    }

    function VKI_findPos(obj) {
        var curleft = curtop = 0;
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
        return [curleft, curtop];
    }

    function VKI_innerDimensions() {
        if (self.innerHeight) {
            return [self.innerWidth, self.innerHeight];
        } else if (document.documentElement && document.documentElement.clientHeight) {
            return [document.documentElement.clientWidth, document.documentElement.clientHeight];
        } else if (document.body)
            return [document.body.clientWidth, document.body.clientHeight];
        return [0, 0];
    }

    function VKI_scrollDist() {
        var html = document.getElementsByTagName('html')[0];
        if (html.scrollTop && document.documentElement.scrollTop) {
            return [html.scrollLeft, html.scrollTop];
        } else if (html.scrollTop || document.documentElement.scrollTop) {
            return [html.scrollLeft + document.documentElement.scrollLeft, html.scrollTop + document.documentElement.scrollTop];
        } else if (document.body.scrollTop)
            return [document.body.scrollLeft, document.body.scrollTop];
        return [0, 0];
    }

    function VKI_getStyle(obj, styleProp) {
        if (obj.currentStyle) {
            var y = obj.currentStyle[styleProp];
        } else if (window.getComputedStyle)
            var y = window.getComputedStyle(obj, null)[styleProp];
        return y;
    }


    VKI_addListener(window, 'resize', this.VKI_position, false);
    VKI_addListener(window, 'scroll', this.VKI_position, false);
    this.VKI_kbsize();
    VKI_addListener(window, 'load', VKI_buildKeyboardInputs, false);
})();
