字母导航

提供网页元素的字母导航

目前為 2018-11-04 提交的版本,檢視 最新版本

// ==UserScript==
// @name         字母导航
// @namespace    https://www.zhihu.com/people/yin-xiao-bo-11
// @version      0.1
// @description  提供网页元素的字母导航
// @author       Veg
// @include    http://*/*
// @include    https://*/*
// @grant        GM_xmlhttpRequest
// ==/UserScript==

//TTS 函数
function navigationTTS(TTStext) {
    var zhText = encodeURI(TTStext);
    var parameter = "&vol=7&per=0&spd=9&pit=7";
    var voicebbUrl = "https://tsn.baidu.com/text2audio?lan=zh&ctp=1&cuid=xiaobo&tok=" + navigationTTSToken + "&tex=" + zhText + parameter;
    var audio = document.querySelector('audio.audio-navigation'); {
        if (audio !== null) {
            audio.src = voicebbUrl;
            audio.playbackRate = 1.4;
            audio.play();
        }
    }
}

let fEight = true;
let element = [];
function switchCtrl(k) {
    if (k.keyCode == 119) {
        if (fEight == true) {
            fEight = false;
            navigationTTS('关闭字母导航');
        }
        else {
            fEight = true;
            navigationTTS('开启字母导航');
        }
    }
    if (fEight == true)
        if (k.keyCode !== 66 &&
            k.keyCode !== 67 &&
            k.keyCode !== 69 &&
            k.keyCode !== 75 &&
            k.keyCode !== 88 &&
            k.keyCode !== 119) {
            return false;
        }
        else {
            var all = document.all;
            for (var i = 0, l = all.length; i < l; i++) {
                if (all[i].nodeType == 1) {
                    element.push(all[i]);
                }
            }
            nFES = getArraySubscript(element, document.activeElement);
            lnavigation(k);
        }
}
document.body.addEventListener('keydown', function (k) {
//keydown
//keyup
    switchCtrl(k);
}, null);
//获取数组下标
function getArraySubscript(arrays, obj) {
    var i = arrays.length;
    while (i--) {
        if (arrays[i] === obj) {
            return i;
        }
    }
    return false;
}

function lnavigation(k) {
    //链接导航
    let linkSubscript = [];
    var links = element.map(function (t) {
        if (t.tagName == 'A' ||
            t.hasAttribute && t.hasAttribute('role') && t.getAttribute('role') == 'link') {
            if (!t.hasAttribute('disabled') &&
                t.getAttribute('role') !== 'button' &&
                t.getAttribute('aria-hidden') !== 'true')
                if (t.tabIndex >= 0 || t.hasAttribute && t.hasAttribute('tabindex') && t.getAttribute('tabindex') == '-1') {
                    if (t.offsetParent !== null) {
                        var targetSubscript = getArraySubscript(element, t);
                        linkSubscript.push(targetSubscript);
                        return t;
                    }
                }
        }
    });
    var link = links.filter(function (n) { return n; });
    //按钮导航
    let buttonSubscript = [];
    var buttons = element.map(function (t) {
        if (t.tagName == 'BUTTON' ||
            t.hasAttribute && t.hasAttribute('role') && t.getAttribute('role') == 'button' ||
            (t.getAttribute('type') == 'button' || t.getAttribute('type') == 'submit') && t.tagName == 'INPUT') {
            if (!t.hasAttribute('disabled') &&
                t.getAttribute('aria-hidden') !== 'true')
                if (t.tabIndex >= 0 || t.hasAttribute && t.hasAttribute('tabindex') && t.getAttribute('tabindex') == '-1') {
                    if (t.offsetParent !== null) {
                        //var style = window.getComputedStyle(t);
                        //if (style.width !== 0 && style.height !== 0 && style.opacity !== 0 && style.display !== 'none' && style.visibility !== 'hidden')
                        var targetSubscript = getArraySubscript(element, t);
                        buttonSubscript.push(targetSubscript);
                        return t;
                    }
                }
        }
    });
    var button = buttons.filter(function (n) { return n; })
    //复选框导航
    let checkSubscript = [];
    var checkbox = element.map(function (t) {
        if (t.tagName == 'INPUT' && t.getAttribute('type') == 'checkbox' ||
            t.hasAttribute && t.hasAttribute('role') && t.getAttribute('role') == 'checkbox') {
            if (!t.hasAttribute('disabled') &&
                t.getAttribute('aria-hidden') !== 'true')
                if (t.tabIndex >= 0 || t.hasAttribute && t.hasAttribute('tabindex') && t.getAttribute('tabindex') == '-1') {
                    if (t.offsetParent !== null) {
                        var targetSubscript = getArraySubscript(element, t);
                        checkSubscript.push(targetSubscript);
                        return t;
                    }
                }
        }
    });
    var check = checkbox.filter(function (n) { return n; })
    //文本框导航
    let textSubscript = [];
    var textbox = element.map(function (t) {
        if (t.tagName == 'INPUT' && t.getAttribute('type') == 'text' ||
t.tagName == 'INPUT' && t.getAttribute('type') == null || 
            t.tagName == 'TEXTAREA' ||
            t.hasAttribute && t.hasAttribute('role') && t.getAttribute('role') == 'textbox') {
            if (!t.hasAttribute('disabled') &&
                t.getAttribute('aria-hidden') !== 'true')
                if (t.tabIndex >= 0 || t.hasAttribute && t.hasAttribute('tabindex') && t.getAttribute('tabindex') == '-1') {
                    if (t.offsetParent !== null) {
                        var targetSubscript = getArraySubscript(element, t);
                        textSubscript.push(targetSubscript);
                        return t;
                    }
                }
        }
    });
    var text = textbox.filter(function (n) { return n; })
    //组合框导航
    let comboSubscript = [];
    var combobox = element.map(function (t) {
        if (t.tagName == 'SELECT' ||
            t.hasAttribute && t.hasAttribute('role') && t.getAttribute('role') == 'combobox') {
            if (!t.hasAttribute('disabled') &&
                t.getAttribute('aria-hidden') !== 'true')
                if (t.tabIndex >= 0 || t.hasAttribute && t.hasAttribute('tabindex') && t.getAttribute('tabindex') == '-1') {
                    if (t.offsetParent !== null) {
                        var targetSubscript = getArraySubscript(element, t);
                        comboSubscript.push(targetSubscript);
                        return t;
                    }
                }
        }
    });
    var combo = combobox.filter(function (n) { return n; })

    element.length = 0;
    //反向切换
    if (k.shiftKey && k.keyCode == 75) {
        for (var i = 0, l = link.length || linkSubscript.length; i < l; i++) {
            if (nFES > linkSubscript[l - 1] || nFES <= linkSubscript[0]) {
                link[l - 1].focus();
                break;
            }
            else {
                if (nFES <= linkSubscript[i]) {
                    var xv = getArraySubscript(link, link[i]);
                    link[xv - 1].focus();
                    reverseAccident(link, xv);
                    break;
                }
            }
        }
    }

    if (k.shiftKey && k.keyCode == 66) {
        for (var i = 0, l = button.length || buttonSubscript.length; i < l; i++) {
            if (nFES > buttonSubscript[l - 1] || nFES <= buttonSubscript[0]) {
                button[l - 1].focus();
                break;
            }
            else {
                if (nFES <= buttonSubscript[i]) {
                    var xv = getArraySubscript(button, button[i]);
                    button[xv - 1].focus();
                    reverseAccident(button, xv);
                    break;
                }
            }
        }
    }
    if (k.shiftKey && k.keyCode == 88) {
        for (var i = 0, l = check.length || checkSubscript.length; i < l; i++) {
            if (nFES > checkSubscript[l - 1] || nFES <= checkSubscript[0]) {
                check[l - 1].focus();
                break;
            }
            else {
                if (nFES <= checkSubscript[i]) {
                    var xv = getArraySubscript(check, check[i]);
                    check[xv - 1].focus();
                    reverseAccident(check, xv);
                    break;
                }
            }
        }
    }

    if (k.shiftKey && k.keyCode == 69) {
        for (var i = 0, l = text.length || textSubscript.length; i < l; i++) {
            if (nFES > textSubscript[l - 1] || nFES <= textSubscript[0]) {
                text[l - 1].focus();
                break;
            }
            else {
                if (nFES <= textSubscript[i]) {
                    var xv = getArraySubscript(text, text[i]);
                    text[xv - 1].focus();
                    reverseAccident(text, xv);
                    break;
                }
            }
        }
    }

    if (k.shiftKey && k.keyCode == 67) {
        for (var i = 0, l = combo.length || comboSubscript.length; i < l; i++) {
            if (nFES > comboSubscript[l - 1] || nFES <= comboSubscript[0]) {
                combo[l - 1].focus();
                break;
            }
            else {
                if (nFES <= comboSubscript[i]) {
                    var xv = getArraySubscript(combo, combo[i]);
                    combo[xv - 1].focus();
                    reverseAccident(combo, xv);
                    break;
                }
            }
        }
    }

    //正向切换
    if (k.altKey || k.ctrlKey || k.shiftKey) return false;
    if (k.keyCode == 75) {
        for (var i = 0, l = link.length || linkSubscript.length; i < l; i++) {
            if (nFES < linkSubscript[i]) {
                var xv = getArraySubscript(link, link[i]);
                link[xv].focus();
                positiveAccident(link, xv);
                break;
            }
            else {
                if (nFES < linkSubscript[0] || nFES >= linkSubscript[l - 1]) {
                    link[0].focus();
                    break;
                }
            }
        }
    }

    if (k.keyCode == 66) {
        for (var i = 0, l = button.length || buttonSubscript.length; i < l; i++) {
            if (nFES < buttonSubscript[i]) {
                var xv = getArraySubscript(button, button[i]);
                button[xv].focus();
                positiveAccident(button, xv);
                break;
            }
            else {
                if (nFES < buttonSubscript[0] || nFES >= buttonSubscript[l - 1]) {
                    button[0].focus();
                    break;
                }
            }
        }
    }

    if (k.keyCode == 88) {
        for (var i = 0, l = check.length || checkSubscript.length; i < l; i++) {
            if (nFES < checkSubscript[i]) {
                var xv = getArraySubscript(check, check[i]);
                check[xv].focus();
                positiveAccident(check, xv);
                break;
            }
            else {
                if (nFES < checkSubscript[0] || nFES >= checkSubscript[l - 1]) {
                    check[0].focus();
                    break;
                }
            }
        }
    }


    if (k.keyCode == 69) {
        for (var i = 0, l = text.length || textSubscript.length; i < l; i++) {
            if (nFES < textSubscript[i]) {
                var xv = getArraySubscript(text, text[i]);
                text[xv].focus();
                positiveAccident(text, xv);
                break;
            }
            else {
                if (nFES < textSubscript[0] || nFES >= textSubscript[l - 1]) {
                    text[0].focus();
                    break;
                }
            }
        }
    }

    if (k.keyCode == 67) {
        for (var i = 0, l = combo.length || comboSubscript.length; i < l; i++) {
            if (nFES < comboSubscript[i]) {
                var xv = getArraySubscript(combo, combo[i]);
                combo[xv].focus();
                positiveAccident(combo, xv);
                break;
            }
            else {
                if (nFES < comboSubscript[0] || nFES >= comboSubscript[l - 1]) {
                    combo[0].focus();
                    break;
                }
            }
        }
    }

}

(function () {
    //插入播放器
    var audio = document.createElement('audio');
    audio.className = 'audio-navigation';
    audio.volume = 0.6;
    document.body.appendChild(audio);
    GM_xmlhttpRequest({
        method: "GET",
        headers: { "Accept": "Content-Type:application/json" },
        url: "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=DmRzeWmTGgwPuPrFyHPhxLFH&client_secret=iYUz9bmANfuDBhlpacObRCq4qutDHfSe",
        onload: function (response) {
            var data = response.responseText;
            var datas = JSON.parse(data);
            navigationTTSToken = datas.access_token;

            setTimeout(function () {
                //navigationTTS('字母导航准备好了');
            }, 50);

        }
    });
})();

function reverseAccident(e, xv) {
    var ev = e[xv - 1].innerText;
    while (ev !== document.activeElement.innerText) {
        xv--
        e[xv - 1].focus();
        ev = e[xv - 1].innerText;
    }
}
function positiveAccident(e, xv) {
    var ev = e[xv].innerText;
    while (ev !== document.activeElement.innerText) {
        xv++
        e[xv].focus();
        ev = e[xv].innerText;
    }
}
var audio = new Audio("https://veg.ink/music/sound.mp3");
audio.volume = 0.15;
audio.play();