tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

key.js (20052B)


      1 var _testing = false;
      2 
      3 // The index into _keyTable of the key currently being tested.
      4 var _currKey = 0;
      5 
      6 var _keysTotal = 0;
      7 var _keysGood = 0;
      8 var _keysBad = 0;
      9 var _keysSkipped = 0;
     10 
     11 var _modifierMode = "None";
     12 
     13 var _keydownCapture = [];
     14 var _keyupCapture = [];
     15 
     16 var CAPTURE_KEYCODE = 0;
     17 var CAPTURE_CODE = 1;
     18 var CAPTURE_KEY = 2;
     19 var CAPTURE_SHIFTKEY = 3;
     20 var CAPTURE_CONTROLKEY = 4;
     21 var CAPTURE_ALTKEY = 5;
     22 var CAPTURE_METAKEY = 6;
     23 
     24 // An array of KeyInfo for each key to be tested.
     25 var _keyTable = [];
     26 
     27 // KeyInfo fields.
     28 var KEYINFO_CODE = 0;       // |code| for this key
     29 var KEYINFO_ROW = 1;        // Keyboard row
     30 var KEYINFO_TYPE = 2;       // Key type (see below)
     31 var KEYINFO_WIDTH = 3;      // Width of key: 0=normal
     32 var KEYINFO_KEYCAP = 4;     // Keycap string to display
     33 var KEYINFO_KEY = 5;        // Unmodified key value
     34 var KEYINFO_KEY_SHIFT = 6;  // Shifted key value
     35 
     36 var KEYTYPE_NORMAL = 0;
     37 var KEYTYPE_DISABLED = 1;   // Key cannot be tested: e.g., CapsLock
     38 var KEYTYPE_END = 2;        // Used to mark end of KeyTable
     39 var KEYTYPE_MODIFIER = 3;   // Modifer key
     40 
     41 function clearChildren(e) {
     42    while (e.firstChild !== null) {
     43        e.removeChild(e.firstChild);
     44    }
     45 }
     46 
     47 function setText(e, text) {
     48    clearChildren(e);
     49    e.appendChild(document.createTextNode(text));
     50 }
     51 
     52 function setUserAgent() {
     53    var userAgent = navigator.userAgent;
     54    uaDiv = document.getElementById("useragent");
     55    setText(uaDiv, userAgent);
     56 }
     57 
     58 function addEventListener(obj, etype, handler) {
     59    if (obj.addEventListener) {
     60        obj.addEventListener(etype, handler, false);
     61    } else if (obj.attachEvent) {
     62        obj.attachEvent("on"+etype, handler);
     63    } else {
     64        obj["on"+etype] = handler;
     65    }
     66 }
     67 
     68 function addClass(obj, className) {
     69    obj.classList.add(className);
     70 }
     71 
     72 function removeClass(obj, className) {
     73    obj.classList.remove(className);
     74 }
     75 
     76 function addInnerText(obj, text) {
     77    obj.appendChild(document.createTextNode(text));
     78 }
     79 
     80 function calcLocation(loc) {
     81    if (loc == 1) return "LEFT";
     82    if (loc == 2) return "RIGHT";
     83    if (loc == 3) return "NUMPAD";
     84    return loc;
     85 }
     86 
     87 function isModifierKey(e) {
     88    // Shift, Control, Alt
     89    if (e.keyCode >= 16 && e.keyCode <= 18) {
     90        return true;
     91    }
     92    // Windows, Command or Meta key.
     93    if (e.keyCode == 224 // Right/Left: Gecko
     94        || e.keyCode == 91    // Left: WebKit/Blink
     95        || e.keyCode == 93    // Right: WebKit/Blink
     96        ) {
     97        return true;
     98    }
     99    return false;
    100 }
    101 
    102 function init(title, keytable) {
    103    _keyTable = keytable;
    104 
    105    createBody(title, keytable);
    106 
    107    setUserAgent();
    108 
    109    var input = document.getElementById("input");
    110    input.disabled = true;
    111    addEventListener(input, "keydown", onKeyDown);
    112    addEventListener(input, "keyup", onKeyUp);
    113    //addEventListener(input, "beforeInput", onBeforeInput);
    114    //addEventListener(input, "input", onInput);
    115 }
    116 
    117 function onKeyDown(e) {
    118    // Ignore modifier keys when checking modifier combinations.
    119    if (_modifierMode != "None" && isModifierKey(e)) {
    120        return;
    121    }
    122 
    123    _keydownInfo = [e.keyCode, e.code, e.key, e.shiftKey, e.ctrlKey, e.altKey, e.metaKey];
    124    if (e.keyCode == 9 || e.code == "Tab") {
    125        e.preventDefault();
    126    }
    127 }
    128 
    129 function onKeyUp(e) {
    130    // Ignore modifier keys when checking modifier combinations.
    131    if (_modifierMode != "None" && isModifierKey(e)) {
    132        return;
    133    }
    134 
    135    _keyupInfo = [e.keyCode, e.code, e.key, e.shiftKey, e.ctrlKey, e.altKey, e.metaKey];
    136 
    137    if (_testing) {
    138        verifyKey();
    139        nextKey();
    140    }
    141 }
    142 
    143 function onBeforeInput(e) {
    144 }
    145 
    146 function onInput(e) {
    147 }
    148 
    149 function addError(elem, str) {
    150    var p = document.createElement('p');
    151    p.classList.add("error2");
    152    p.textContent = str;
    153    elem.appendChild(p);
    154 }
    155 
    156 function addErrorIncorrect(elem, eventName, attrName, keyEventInfo, attr, expected) {
    157    addError(elem, "Incorrect " + eventName
    158        + " |" + attrName + "| = " + keyEventInfo[attr]
    159        + " - Expected " + expected);
    160 }
    161 
    162 function verifyKeyEventFields(eventName, keyEventInfo, code, key, error) {
    163    var verifyCode = document.getElementById("opt_attr_code").checked;
    164    var verifyKey = document.getElementById("opt_attr_key").checked;
    165    var verifyModifiers = document.getElementById("opt_attr_modifiers").checked;
    166    var good = true;
    167 
    168    if (!verifyCode && !verifyKey && !verifyModifiers) {
    169        good = false;
    170        addError(error, "Invalid test: At least one attribute must be selected for testing.");
    171    }
    172    if (verifyCode && keyEventInfo[CAPTURE_CODE] != code) {
    173        good = false;
    174        addErrorIncorrect(error, eventName, "code", keyEventInfo, CAPTURE_CODE, code);
    175    }
    176    if (verifyKey && keyEventInfo[CAPTURE_KEY] != key) {
    177        good = false;
    178        addErrorIncorrect(error, eventName, "key", keyEventInfo, CAPTURE_KEY, key);
    179    }
    180    if (verifyModifiers) {
    181        if (keyEventInfo[CAPTURE_SHIFTKEY] != (_modifierMode == "Shift")) {
    182            good = false;
    183            addErrorIncorrect(error, eventName, "shiftKey", keyEventInfo, CAPTURE_SHIFTKEY, false);
    184        }
    185        if (keyEventInfo[CAPTURE_CONTROLKEY]) {
    186            good = false;
    187            addErrorIncorrect(error, eventName, "controlKey", keyEventInfo, CAPTURE_CONTROLKEY, false);
    188        }
    189        if (keyEventInfo[CAPTURE_ALTKEY]) {
    190            good = false;
    191            addErrorIncorrect(error, eventName, "altKey", keyEventInfo, CAPTURE_ALTKEY, false);
    192        }
    193        if (keyEventInfo[CAPTURE_METAKEY]) {
    194            good = false;
    195            addErrorIncorrect(error, eventName, "metaKey", keyEventInfo, CAPTURE_METAKEY, false);
    196        }
    197    }
    198 
    199    return good;
    200 }
    201 
    202 function verifyKey() {
    203    _keysTotal++;
    204 
    205    var keyInfo = _keyTable[_currKey];
    206    var code = keyInfo[KEYINFO_CODE];
    207    var key = keyInfo[KEYINFO_KEY];
    208    var keyShift = keyInfo[KEYINFO_KEY_SHIFT];
    209 
    210    var keyCheck = key;
    211    if (_modifierMode == "Shift") {
    212        keyCheck = keyShift;
    213    }
    214 
    215    var verifyKeydown = document.getElementById("opt_event_keydown").checked;
    216    var verifyKeyup = document.getElementById("opt_event_keyup").checked;
    217 
    218    var error = document.createElement('div');
    219    error.classList.add("error");
    220    var good = true;
    221 
    222    if (verifyKeydown) {
    223        good = verifyKeyEventFields("keydown", _keydownInfo, code, keyCheck, error);
    224    }
    225    if (verifyKeyup) {
    226        good = verifyKeyEventFields("keyup", _keyupInfo, code, keyCheck, error);
    227    }
    228 
    229    if (!verifyKeydown && !verifyKeyup) {
    230        good = false;
    231        addError(error, "Invalid test: At least one event must be selected for testing.");
    232    }
    233 
    234    // Allow Escape key to skip the current key.
    235    var skipped = false;
    236    if (_keydownInfo[CAPTURE_KEYCODE] == 27 || _keydownInfo[CAPTURE_CODE] == "Escape") {
    237        good = true;
    238        skipped = true;
    239    }
    240 
    241    if (!good) {
    242        var p = document.createElement('p');
    243        p.classList.add("error1");
    244        p.textContent = "Error : " + code;
    245        error.insertBefore(p, error.firstChild);
    246    }
    247 
    248    removeNextKeyHilight();
    249    if (skipped) {
    250        _keysSkipped++;
    251        document.getElementById(code).classList.add("skippedKey")
    252    } else if (good) {
    253        _keysGood++;
    254        document.getElementById(code).classList.add("goodKey")
    255    } else {
    256        _keysBad++;
    257        document.getElementById(code).classList.add("badKey")
    258    }
    259    updateTestSummary(good ? null : error);
    260 }
    261 
    262 function updateTestSummary(error) {
    263    document.getElementById("keys-total").textContent = _keysTotal;
    264    document.getElementById("keys-good").textContent = _keysGood;
    265    document.getElementById("keys-bad").textContent = _keysBad;
    266    document.getElementById("keys-skipped").textContent = _keysSkipped;
    267 
    268    if (error) {
    269        var errors = document.getElementById("errors");
    270        errors.insertBefore(error, errors.firstChild);
    271    }
    272 }
    273 
    274 function resetTest() {
    275    _keysTotal = 0;
    276    _keysGood = 0;
    277    _keysBad = 0;
    278 
    279    _currKey = -1;
    280    nextKey();
    281 
    282    updateTestSummary();
    283 
    284    // Remove previous test results.
    285    clearChildren(document.getElementById("errors"));
    286 
    287    // Remove highlighting from keys.
    288    for (var i = 0; i < _keyTable.length; i++) {
    289        var code = _keyTable[i][KEYINFO_CODE];
    290        var type = _keyTable[i][KEYINFO_TYPE];
    291        if (type != KEYTYPE_END) {
    292            var key = document.getElementById(code);
    293            key.classList.remove("goodKey");
    294            key.classList.remove("badKey");
    295            key.classList.remove("skippedKey");
    296        }
    297    }
    298 }
    299 
    300 function startTest() {
    301    if (_testing) {
    302        // Cancel the currently running test.
    303        endTest();
    304        return;
    305    }
    306 
    307    resetTest();
    308    _testing = true;
    309    document.getElementById("start").value = "Stop Test"
    310 
    311    var input = document.getElementById("input");
    312    input.value = "";
    313    input.disabled = false;
    314    input.focus();
    315 
    316    // Show test instructions and info.
    317    document.getElementById("test-info").style.display = 'block';
    318    document.getElementById("instructions").style.display = 'block';
    319    document.getElementById("test-done").style.display = 'none';
    320 }
    321 
    322 function endTest() {
    323    _testing = false;
    324    removeNextKeyHilight();
    325    document.getElementById("start").value = "Restart Test"
    326    document.getElementById("input").disabled = true;
    327    document.getElementById("instructions").style.display = 'none';
    328    document.getElementById("test-done").style.display = 'block';
    329 }
    330 
    331 function removeNextKeyHilight() {
    332    var curr = document.getElementById(_keyTable[_currKey][KEYINFO_CODE]);
    333    if (curr) {
    334        removeClass(curr, "nextKey")
    335    }
    336 }
    337 
    338 function addNextKeyHilight() {
    339    var curr = document.getElementById(_keyTable[_currKey][KEYINFO_CODE]);
    340    if (curr) {
    341        addClass(curr, "nextKey")
    342    }
    343 }
    344 
    345 function nextKey() {
    346    var keyInfo;
    347    var keepLooking = true;
    348    do {
    349        _currKey++;
    350        keyInfo = _keyTable[_currKey];
    351        var type = keyInfo[KEYINFO_TYPE];
    352 
    353        // Skip over disabled keys.
    354        keepLooking = (type == KEYTYPE_DISABLED);
    355 
    356        // Skip over modifier keys if we're testing modifier combinations.
    357        if (_modifierMode != "None" && type == KEYTYPE_MODIFIER) {
    358            keepLooking = true;
    359        }
    360 
    361        // Skip over keys in disabled rows.
    362        if (type != KEYTYPE_END) {
    363            var row = keyInfo[KEYINFO_ROW];
    364            var rowEnabled = document.getElementById("opt_row_" + row).checked;
    365            keepLooking = keepLooking || !rowEnabled;
    366        }
    367    } while (keepLooking);
    368 
    369    if (keyInfo[KEYINFO_TYPE] == KEYTYPE_END) {
    370        endTest();
    371    } else {
    372        addNextKeyHilight();
    373    }
    374 }
    375 
    376 function toggleOptions() {
    377    var link = document.getElementById("optionstoggle");
    378    var options = document.getElementById("options");
    379    clearChildren(link);
    380    if (options.style.display == "block") {
    381        options.style.display = "none";
    382        addInnerText(link, "Show Options");
    383    }
    384    else {
    385        options.style.display = "block";
    386        addInnerText(link, "Hide Options");
    387    }
    388 }
    389 
    390 function toggleHelp() {
    391    var link = document.getElementById("helptoggle");
    392    var help = document.getElementById("help");
    393    clearChildren(link);
    394    if (help.style.display == "block") {
    395        help.style.display = "none";
    396        addInnerText(link, "Show Help");
    397    }
    398    else {
    399        help.style.display = "block";
    400        addInnerText(link, "Hide Help");
    401    }
    402 }
    403 
    404 function createBody(title, keytable) {
    405    var body = document.getElementsByTagName("body")[0];
    406    var p;
    407    var span;
    408 
    409    var h1 = document.createElement('h1');
    410    h1.textContent = "Keyboard Event Manual Test - " + title;
    411    body.appendChild(h1);
    412 
    413    // Display useragent.
    414    p = document.createElement('p');
    415    p.textContent = "UserAgent: ";
    416    var useragent = document.createElement('span');
    417    useragent.id = "useragent";
    418    p.appendChild(useragent);
    419    body.appendChild(p);
    420 
    421    // Display input textedit.
    422    p = document.createElement('p');
    423    p.textContent = "Test Input: ";
    424    var input1 = document.createElement('input');
    425    input1.id = "input";
    426    input1.type = "text";
    427    input1.size = 80;
    428    p.appendChild(input1);
    429    p.appendChild(document.createTextNode(" "));
    430    var input2 = document.createElement('input');
    431    input2.id = "start";
    432    input2.type = "button";
    433    input2.onclick = function() { startTest(); return false; }
    434    input2.value = "Start Test";
    435    p.appendChild(input2);
    436    p.appendChild(document.createTextNode(" "));
    437    var optionsToggle = document.createElement('a');
    438    optionsToggle.id = "optionstoggle";
    439    optionsToggle.href = "javascript:toggleOptions()";
    440    optionsToggle.textContent = "Show Options";
    441    p.appendChild(optionsToggle);
    442    p.appendChild(document.createTextNode(" "));
    443    var helpToggle = document.createElement('a');
    444    helpToggle.id = "helptoggle";
    445    helpToggle.href = "javascript:toggleHelp()";
    446    helpToggle.textContent = "Show Help";
    447    p.appendChild(helpToggle);
    448    body.appendChild(p);
    449 
    450    createOptions(body);
    451 
    452    createHelp(body);
    453 
    454    createKeyboard(body, keytable);
    455 
    456    // Test info and summary.
    457    var test_info = document.createElement('div');
    458    test_info.id = "test-info";
    459    test_info.style.display = "none";
    460 
    461    var instructions = document.createElement('div');
    462    instructions.id = "instructions";
    463    p = document.createElement('p');
    464    p.textContent = "Press the highlighted key.";
    465    instructions.appendChild(p);
    466    test_info.appendChild(instructions);
    467 
    468    var test_done = document.createElement('div');
    469    test_done.id = "test-done";
    470    p = document.createElement('p');
    471    p.textContent = "Test complete!";
    472    test_done.appendChild(p);
    473    test_info.appendChild(test_done);
    474 
    475    var summary = document.createElement('div');
    476    summary.id = "summary";
    477    p = document.createElement('p');
    478    summary.appendChild(document.createTextNode("Keys Tested: "));
    479    span = document.createElement('span');
    480    span.id = "keys-total";
    481    span.textContent = 0;
    482    summary.appendChild(span);
    483    summary.appendChild(document.createTextNode("; Passed "));
    484    span = document.createElement('span');
    485    span.id = "keys-good";
    486    span.textContent = 0;
    487    summary.appendChild(span);
    488    summary.appendChild(document.createTextNode("; Failed "));
    489    span = document.createElement('span');
    490    span.id = "keys-bad";
    491    span.textContent = 0;
    492    summary.appendChild(span);
    493    summary.appendChild(document.createTextNode("; Skipped "));
    494    span = document.createElement('span');
    495    span.id = "keys-skipped";
    496    span.textContent = 0;
    497    summary.appendChild(span);
    498    test_info.appendChild(summary);
    499 
    500    var errors = document.createElement('div');
    501    errors.id = "errors";
    502    test_info.appendChild(errors);
    503 
    504    body.appendChild(test_info);
    505 }
    506 
    507 function addOptionTitle(cell, title) {
    508    var span = document.createElement('span');
    509    span.classList.add("opttitle");
    510    span.textContent = title;
    511    cell.appendChild(span);
    512    cell.appendChild(document.createElement("br"));
    513 }
    514 
    515 function addOptionCheckbox(cell, id, text) {
    516    var label = document.createElement("label");
    517 
    518    var input = document.createElement("input");
    519    input.type = "checkbox";
    520    input.id = id;
    521    input.checked = true;
    522    label.appendChild(input);
    523 
    524    label.appendChild(document.createTextNode(" " + text));
    525    cell.appendChild(label);
    526 
    527    cell.appendChild(document.createElement("br"));
    528 }
    529 
    530 function addOptionRadio(cell, group, text, handler, checked) {
    531    var label = document.createElement("label");
    532 
    533    var input = document.createElement("input");
    534    input.type = "radio";
    535    input.name = group;
    536    input.value = text;
    537    input.onclick = handler;
    538    input.checked = checked;
    539    label.appendChild(input);
    540 
    541    label.appendChild(document.createTextNode(" " + text));
    542    cell.appendChild(label);
    543 
    544    cell.appendChild(document.createElement("br"));
    545 }
    546 
    547 function handleModifierGroup() {
    548    var radio = document.querySelector("input[name=opt_modifier]:checked");
    549    var oldMode = _modifierMode;
    550    _modifierMode = radio.value;
    551 
    552    if (oldMode == "Shift") {
    553        document.getElementById("ShiftLeft").classList.remove("activeModifierKey");
    554        document.getElementById("ShiftRight").classList.remove("activeModifierKey");
    555    }
    556 
    557    if (_modifierMode == "Shift") {
    558        document.getElementById("ShiftLeft").classList.add("activeModifierKey");
    559        document.getElementById("ShiftRight").classList.add("activeModifierKey");
    560    }
    561 }
    562 
    563 function createOptions(body) {
    564    var options = document.createElement('div');
    565    options.id = "options";
    566    options.style.display = "none";
    567 
    568    var table = document.createElement('table');
    569    table.classList.add("opttable");
    570    var row = document.createElement('tr');
    571    var cell;
    572 
    573    cell = document.createElement('td');
    574    cell.classList.add("optcell");
    575    addOptionTitle(cell, "Keyboard Rows");
    576    addOptionCheckbox(cell, "opt_row_0", "Row E (top)");
    577    addOptionCheckbox(cell, "opt_row_1", "Row D");
    578    addOptionCheckbox(cell, "opt_row_2", "Row C");
    579    addOptionCheckbox(cell, "opt_row_3", "Row B");
    580    addOptionCheckbox(cell, "opt_row_4", "Row A (bottom)");
    581    row.appendChild(cell);
    582 
    583    cell = document.createElement('td');
    584    cell.classList.add("optcell");
    585    addOptionTitle(cell, "Events");
    586    addOptionCheckbox(cell, "opt_event_keydown", "keydown");
    587    addOptionCheckbox(cell, "opt_event_keyup", "keyup");
    588    row.appendChild(cell);
    589 
    590    cell = document.createElement('td');
    591    cell.classList.add("optcell");
    592    addOptionTitle(cell, "Attributes");
    593    addOptionCheckbox(cell, "opt_attr_code", "code");
    594    addOptionCheckbox(cell, "opt_attr_key", "key");
    595    addOptionCheckbox(cell, "opt_attr_modifiers", "modifiers");
    596    row.appendChild(cell);
    597 
    598    cell = document.createElement('td');
    599    cell.classList.add("optcell");
    600    addOptionTitle(cell, "Modifiers");
    601    addOptionRadio(cell, "opt_modifier", "None", handleModifierGroup, true);
    602    addOptionRadio(cell, "opt_modifier", "Shift", handleModifierGroup, false);
    603    row.appendChild(cell);
    604 
    605    table.appendChild(row);
    606    options.appendChild(table);
    607 
    608    body.appendChild(options);
    609 }
    610 
    611 function addHelpText(div, text) {
    612    var p = document.createElement('p');
    613    p.classList.add("help");
    614    p.textContent = text;
    615    div.appendChild(p);
    616 }
    617 
    618 function createHelp(body) {
    619    var help = document.createElement('div');
    620    help.id = "help";
    621    help.style.display = "none";
    622 
    623    addHelpText(help, "Click on the \"Start Test\" button to begin testing.");
    624    addHelpText(help, "Press the hilighted key to test it.");
    625    addHelpText(help, "Clicking anywhere outside the \"Test Input\" editbox will pause testing. To resume, click back inside the editbox.");
    626    addHelpText(help, "To skip a key while testing, press Escape.");
    627    addHelpText(help, "When testing with modifier keys, the modifier must be pressed before the keydown and released after the keyup of the key being tested.");
    628 
    629    body.appendChild(help);
    630 }
    631 
    632 function createKeyboard(body, keytable) {
    633    var keyboard = document.createElement('div');
    634    keyboard.classList.add("keyboard");
    635 
    636    var currRow = 0;
    637    var row = document.createElement('div');
    638    row.classList.add("key-row");
    639 
    640    for (var i = 0; i < keytable.length; i++) {
    641        var code = keytable[i][KEYINFO_CODE];
    642        var rowId = keytable[i][KEYINFO_ROW];
    643        var type = keytable[i][KEYINFO_TYPE];
    644        var width = keytable[i][KEYINFO_WIDTH];
    645        var keyCap = keytable[i][KEYINFO_KEYCAP];
    646 
    647        if (type == KEYTYPE_END) {
    648            continue;
    649        }
    650 
    651        if (rowId != currRow) {
    652            keyboard.appendChild(row);
    653            row = document.createElement('div');
    654            row.classList.add("key-row");
    655            currRow = rowId;
    656        }
    657 
    658        var key = document.createElement('div');
    659        key.id = code;
    660        key.classList.add("key");
    661        if (width != 0) {
    662            key.classList.add("wide" + width);
    663        }
    664        key.textContent = keyCap;
    665 
    666        row.appendChild(key);
    667    }
    668 
    669    keyboard.appendChild(row);
    670    body.appendChild(keyboard);
    671 }