From 886ff9878b4bb75f5147c27944aa1ac168dad3c6 Mon Sep 17 00:00:00 2001 From: layman Date: Thu, 16 Jul 2015 01:42:34 +0200 Subject: [PATCH] Hint script added --- www-client/surf/files/script.js | 318 ++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 www-client/surf/files/script.js diff --git a/www-client/surf/files/script.js b/www-client/surf/files/script.js new file mode 100644 index 0000000..927f65b --- /dev/null +++ b/www-client/surf/files/script.js @@ -0,0 +1,318 @@ +(function HintNavigation() { + + var hint_num_str = ''; + var hint_elems = []; + var hint_tags = []; + var hint_enabled = false; + + var registeredElements = []; + + var keyId = { + "U+0008" : "Backspace", + "U+0009" : "Tab", + "U+0018" : "Cancel", + "U+001B" : "Esc", + "U+0020" : "Space", + "U+0021" : "!", + "U+0023" : "#", + "U+0024" : "$", + "U+0029" : ")", + "U+002A" : "*", + "U+002B" : "+", + "U+002C" : ",", + "U+002E" : ".", + "U+002F" : "/", + "U+00C0" : "0", + "U+0026" : "1", + "U+00C9" : "2", + "U+0022" : "3", + "U+0027" : "4", + "U+0028" : "5", + "U+002D" : "6", + "U+00C8" : "7", + "U+005F" : "8", + "U+00C7" : "9", + "U+003A" : ":", + "U+003B" : ";", + "U+003C" : "<", + "U+003D" : "=", + "U+003E" : ">", + "U+003F" : "?", + "U+0040" : "@", + "U+0041" : "a", + "U+0042" : "b", + "U+0043" : "c", + "U+0044" : "d", + "U+0045" : "e", + "U+0046" : "f", + "U+0047" : "g", + "U+0048" : "h", + "U+0049" : "i", + "U+004A" : "j", + "U+004B" : "k", + "U+004C" : "l", + "U+004D" : "m", + "U+004E" : "n", + "U+004F" : "o", + "U+0050" : "p", + "U+0051" : "q", + "U+0052" : "r", + "U+0053" : "s", + "U+0054" : "t", + "U+0055" : "u", + "U+0056" : "v", + "U+0057" : "w", + "U+0058" : "x", + "U+0059" : "y", + "U+005A" : "z", + "U+00DB" : "[", + "U+00DC" : "\\", + "U+00DD" : "]", + "U+005E" : "^", + "U+0060" : "`", + "U+007B" : "{", + "U+007C" : "|", + "U+007D" : "}", + "U+007F" : "Delete", + "U+00A1" : "¡", + "U+0300" : "CombGrave", + "U+0301" : "CombAcute", + "U+0302" : "CombCircum", + "U+0303" : "CombTilde", + "U+0304" : "CombMacron", + "U+0306" : "CombBreve", + "U+0307" : "CombDot", + "U+0308" : "CombDiaer", + "U+030A" : "CombRing", + "U+030B" : "CombDblAcute", + "U+030C" : "CombCaron", + "U+0327" : "CombCedilla", + "U+0328" : "CombOgonek", + "U+0345" : "CombYpogeg", + "U+20AC" : "€", + "U+3099" : "CombVoice", + "U+309A" : "CombSVoice", +}; + + function interceptListeners(element) { + var addEvent = element.prototype.addEventListener; + var removeEvent = element.prototype.removeEventListener; + element.prototype.addEventListener = function () { + if (arguments[0] === "click" || arguments[0] === "mouseover") { + registeredElements.push(this); + } + addEvent.call(this, arguments[0], arguments[1], arguments[2]); + }; + + element.prototype.removeEventListener = function () { + if ((arguments[0] === "click" || arguments[1] === "mouseover") && registeredElements.indexOf(this)>= 0 ) { + registeredElements.splice(registeredElements.indexOf(this), 1); + } + removeEvent.call(this, arguments[0], arguments[1], arguments[2]); + }; + } + + + function start(){ + hint_enabled = true; + setHints(); + document.removeEventListener('keydown', initKeyBind, false); + document.addEventListener('keydown', hintHandler, false); + document.addEventListener('scroll', windowChanged, false); + document.addEventListener('resize', windowChanged, false); + hint_num_str = ''; + } + + function hintHandler(e){ + e.preventDefault(); //Stop Default Event + + var pressedKey = get_key(e); + var hint_num; + + if (pressedKey !== 'U+0000') { + if (pressedKey === 'Backspace') { + if (hint_num_str.length > 0) { + hint_num_str = hint_num_str.substr(0,hint_num_str.length - 1); + } + } + else if (pressedKey === 'Enter') { + if (hint_num_str === '') { + hint_num_str = '1'; + } + judgeHintNum(Number(hint_num_str)); + return; + } + else if (/[0-9]/.test(pressedKey) === false) { + stop(); + } + else if (Number(hint_num_str + pressedKey) <= hint_elems.length) { + hint_num_str += pressedKey; + hint_num = Number(hint_num_str); + + if (hint_num * 10 > hint_elems.length + 1) { + judgeHintNum(hint_num); + return; + } + } + + for (var i = 1 ; i <= hint_tags.length ; ++i ) { + var iStr = i.toString(); + + if (iStr === hint_num_str) { + hint_tags[i - 1].style.display = 'inline'; + hint_tags[i - 1].style.border = 'solid 6px blue'; + } + else if (iStr.length > hint_num_str.length && iStr.substr(0,hint_num_str.length) === hint_num_str) { + hint_tags[i - 1].style.display = 'inline'; + hint_tags[i - 1].style.border = 'none'; + } + else { + hint_tags[i - 1].style.display = 'none'; + hint_tags[i - 1].style.border = 'none'; + } + } + } + } + + function judgeHintNum(hint_num) { + var hint_elem = hint_elems[hint_num - 1]; + if (hint_elem) { + execSelect(hint_elem); + } else { + stop(); + } + } + + function execSelect(elem) { + var tag_name = elem.tagName.toLowerCase(); + var type = elem.type ? elem.type.toLowerCase() : ''; + + elem.dispatchEvent(new Event('mouseover')); + elem.dispatchEvent(new Event('click', { + 'bubbles': true, + 'cancelable': true})); + + if (tag_name === 'input' && (type === "radio" || type === "checkbox")) { + elem.checked = !elem.checked; + } + else if (tag_name === 'input' || tag_name === 'textarea') { + elem.focus(); + elem.setSelectionRange(0, elem.value.length); + } + + stop(); + } + + function setHints() { + var win_top = window.scrollY; + var win_bottom = win_top + window.innerHeight; + var win_left = window.scrollX; + var elems = document.body.querySelectorAll('a, input:not([type=hidden]), textarea, select, button, [onclick], [onmouseover], [for]'); + + var elements = []; + + for (var i = 0 ; i < elems.length ; ++i) { + elements.push(elems[i]); + } + + for (i = 0 ; i < registeredElements.length ; ++i) { + elements.push(registeredElements[i]); + } + + var div = document.createElement('div'); + div.setAttribute('highlight', 'hints'); + document.body.appendChild(div); + + for (i = 0; i < elements.length; i++) { + var elem = elements[i]; + if (!isHintDisplay(elem)) { + continue; + } + var pos = elem.getBoundingClientRect(); + var elem_top = win_top + pos.top; + var elem_bottom = win_top + pos.bottom; + var elem_left = win_left + pos.left; + + if ( elem_bottom >= win_top && elem_top <= win_bottom) { + hint_elems.push(elem); + var span = document.createElement('span'); + span.style.cssText = [ + 'left: ', elem_left, 'px;', + 'top: ', elem_top, 'px;', + 'position: absolute;', + 'font-size: 13px;', + 'background-color: red;', + 'color: white;', + 'font-weight: bold;', + 'padding: 0px 1px;', + 'z-index: 10000;' + ].join(''); + span.innerHTML = hint_elems.length; + div.appendChild(span); + hint_tags.push(span); + } + } + } + + function isHintDisplay(elem) { + var pos = elem.getBoundingClientRect(); + return (pos.height !== 0 && pos.width !== 0); + } + + function stop() { + if (!hint_enabled){ + return; + } + + hint_enabled = false; + hint_elems = []; + hint_tags = []; + hint_num_str = ''; + var div = document.body.querySelector('div[highlight=hints]'); + if (div) { + document.body.removeChild(div); + } + document.removeEventListener('keydown', hintHandler, false); + document.removeEventListener('scroll', windowChanged, false); + document.removeEventListener('resize', windowChanged, false); + document.addEventListener('keydown', initKeyBind, false); + if (refreshTimeout) { + window.clearTimeout(refreshTimeout); + } + } + + function initKeyBind(e){ + if (e.target.nodeType === 1 && e.ctrlKey){ + if (get_key(e) === 'f') { + e.preventDefault(); + start(); + } + else if (get_key(e) === 'c') { + e.preventDefault(); + stop(); + } + } + } + + var refreshTimeout; + function windowChanged(){ + if (refreshTimeout) { + window.clearTimeout(refreshTimeout); + } + + refreshTimeout = window.setTimeout(refreshHints, 200); + } + + function refreshHints() { + stop(); + start(); + refreshTimeout = undefined; + } + + function get_key(evt){ + return keyId[evt.keyIdentifier] || evt.keyIdentifier; + } + + interceptListeners(HTMLElement); + document.addEventListener( 'keydown', initKeyBind, false ); +})();