Block_Obj

BLOCK_OBJ

Від 22.07.2020. Дивіться остання версія.

Цей скрипт не слід встановлювати безпосередньо. Це - бібліотека для інших скриптів для включення в мета директиву // @require https://update.greasyfork.org/scripts/407543/829361/Block_Obj.js

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(У мене вже є менеджер скриптів, дайте мені встановити його!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Block_Obj
// @namespace    https://greasyfork.org/zh-CN/users/193133-pana
// @homepage     https://www.sailboatweb.com
// @version      1.0.0
// @description  BLOCK_OBJ
// @author       pana
// @license      GNU General Public License v3.0 or later
// ==/UserScript==

const BLOCK_STYLE = `
    .block_obj_wrap_div {
        background-color: #222222;
        border-radius: 3px;
        border: 1px solid #282A36;
        bottom: 6vh;
        box-shadow: 0 0 5px #282A36;
        color: #D3D3D3;
        font-size: 13px;
        margin: 0px;
        padding: 0px;
        position: fixed;
        text-align: left;
        transition: 0.8s;
        width: 480px;
        z-index: 99999;
    }
    .block_obj_show_wrap {
        display: block;
        right: 0;
    }
    .block_obj_hidden_wrap {
        right: -490px;
    }
    .block_obj_main_fieldset {
        border-radius: 3px;
        border: 3px groove #00A1D6;
        height: auto;
        margin: 8px;
        min-width: 300px;
        padding: 4px 9px 6px 9px;
        width: auto;
    }
    .block_obj_ul_node {
        list-style: none;
        padding-left: 0;
    }
    .block_obj_checkbox_li {
        display: inline-block;
        margin-top: 5px;
    }
    .block_obj_checkbox_input {
        clip: rect(0, 0, 0, 0);
        position: absolute;
    }
    .block_obj_checkbox_label {
        cursor: pointer;
        vertical-align: middle;
    }
    .block_obj_checkbox_input + label::before {
        background-color: silver;
        border-radius: 0.1em;
        color: #FFF;
        content: "\\a0";
        display: inline-block;
        height: 1em;
        line-height: 85%;
        margin-right: 0.5em;
        text-align: center;
        vertical-align: 0.2em;
        width: 1em;
    }
    .block_obj_checkbox_input:checked + label::before {
        background-color: #00A1D6;
        content: "\\2713";
    }
    .block_obj_separator_text {
        color: #FFB86C;
        margin-bottom: 2px;
        margin-top: 2px;
    }
    .block_obj_separator_symbol {
        background-color: #303030;
        height: 2px;
        margin-bottom: 5px;
        margin-top: 5px;
        min-width: 400px;
    }
    .block_obj_input_div {
        margin-top: 5px;
    }
    .block_obj_input {
        background-color: #C0C0C0;
        border: 1px solid #C0C0C0;
        color: #000;
        font-size: 13px;
        min-height: 15px;
        margin-left: 5px;
        margin-right: 5px;
        padding-left: 4px;
    }
    .block_obj_keyword_input {
        width: 150px;
    }
    .block_obj_input_btn {
        background-color: #3da9cc;
        border-radius: 3px;
        border: 1px solid #73C9E5;
        box-shadow: 0 0 4px #73C9E5;
        color: #FFF;
        cursor: pointer;
        display: inline-block;
        min-height: 15px;
        line-height: normal;
        margin-left: 5px;
        text-align: center;
        vertical-align: bottom;
        white-space: nowrap;
        width: 30px;
    }
    .block_obj_list_div {
        margin-top: 5px;
    }
    .block_obj_list_textarea_div {
        border: 1px dotted #00A1D6;
        margin-top: 3px;
        max-height: 60px;
        min-height: 3px;
        overflow: auto;
    }
    .block_obj_list_textarea_div::-webkit-scrollbar {
        background-color: #979797;
        border-radius: 5px;
        width: 10px;
    }
    .block_obj_list_textarea_div::-webkit-scrollbar-thumb {
        background-color: #404040;
        border-radius: 5px;
    }
    .block_obj_button_clicked {
        color: #000;
    }
    .block_obj_child_span {
        background-color: #3D3D3D;
        border-radius: 5px;
        border: 1px solid #3D3D3D;
        display: inline-block;
        margin: 3px;
        padding: 2px;
        min-height: 18px;
        line-height: normal;
    }
    .block_obj_child_text {
        border-right: 1px solid #A9181C;
        margin-right: 4px;
        padding-right: 4px;
    }
    .block_obj_child_del {
        color: #A9181C;
        cursor: pointer;
    }
    .block_obj_list_textarea_expand {
        max-height: 720px;
    }
    .block_obj_li_hide {
        display: none;
    }
    .block_obj_reg_input {
        width: 100px;
    }
    .block_obj_modifier_input {
        width: 50px;
    }
    .block_obj_button {
        background-color: #FB7299;
        border-radius: 4px;
        border: 1px solid #FB7299;
        color: #FFF;
        cursor: pointer;
        margin-top: 5px;
        padding: 2px 4px;
        position: relative;
        min-height: 17px;
        line-height: normal;
    }
    .block_obj_save_button {
        float: right;
        margin-right: 5px;
    }
    .block_obj_cancel_button {
        float: left;
        margin-left: 5px;
    }
    .block_obj_expand_box {
        bottom: 0px;
        height: 6vh;
        position: fixed;
        right: -6vw;
        transition: 0.5s;
        width: 12vw;
        z-index: 99999;
    }
    .block_obj_show_expand_box {
        right: 0;
        width: 6vw;
    }
    .block_obj_expand_span {
        background-color: #00A1D6;
        border-radius: 19px;
        border: 1px solid #00A1D6;
        bottom: 1vh;
        color: #FFF;
        cursor: pointer;
        display: block;
        font-size: 13px;
        height: 38px;
        line-height: 38px;
        position: absolute;
        right: 1vw;
        text-align: center;
        width: 38px;
        z-index: 99999;
    }
    .block_obj_expand_span:hover {
        box-shadow: 0 0 5px 1px green;
    }
`;
class Block_Obj {
    constructor(config) {
        this.wrapDiv = null;
        this.mainFieldset = null;
        this.ulNode = null;
        this.style = null;
        this.saveField = [];
        this.onSave = null;
        this.field = [];
        this.config = config;
    }
    init(initialization) {
        if (! this.id) {
            this.id = initialization.id ? 'blockObj_' + initialization.id : 'blockObj_' + Block_Obj.count;
            ! initialization.id && Block_Obj.count ++;
        }
        this.display = initialization.display ? true : false;
        if (initialization.events) {
            if (typeof(initialization.events['save']) === 'function') {
                this.onSave = initialization.events['save'];
            }
        }
        this.style = document.createElement('style');
        this.style.type = 'text/css';
        this.style.innerHTML = BLOCK_STYLE;
        document.body.appendChild(this.style);
        ! this.wrapDiv && this.createSettingsPanel();
        this.field = initialization.field;
        this.settingsPanel();
        let expand_box = document.createElement('div');
        expand_box.className = 'block_obj_expand_box';
        expand_box.onmouseenter = function() {
            this.classList.add('block_obj_show_expand_box');
        };
        expand_box.onmouseleave = function() {
            this.classList.remove('block_obj_show_expand_box');
        };
        let expand_span = document.createElement('span');
        expand_span.id = this.id + '_expandSpan';
        expand_span.className = 'block_obj_expand_span';
        expand_span.textContent = '屏蔽';
        expand_span.title = '显示屏蔽设置';
        expand_span.addEventListener('click', () => this.expandWrap());
        expand_box.appendChild(expand_span);
        document.body.appendChild(expand_box);
    }
    settingsPanel() {
        if (Array.isArray(this.field)) {
            this.field.forEach(ele => {
                if (ele.id && ! this.wrapDiv.querySelector('#' + this.id + '_' + ele.id)) {
                    switch (ele.type.toLowerCase()) {
                        case 'separator':
                        case 's':
                            this.insertSeparator(ele.id, ele.label, ele.title, ele.classname);
                            break;
                        case 'input':
                        case 'i':
                            this.insertInput(ele.id, ele.list_id, false, ele.label, ele.title, ele.placeholder, ele.classname);
                            break;
                        case 'reg_input':
                        case 'ri':
                            this.insertInput(ele.id, ele.list_id, true, ele.label, ele.title, ele.placeholder, ele.classname);
                            break;
                        case 'list':
                        case 'l':
                            this.insertList(ele.id, this.config[ele.id] ? this.config[ele.id] : ele.default, ele.label, ele.title, ele.classname);
                            break;
                        case 'checkbox':
                        case 'c':
                        default:
                            this.insertCheckbox(ele.id, ele.label, ele.title, this.config[ele.id] ? this.config[ele.id] : ele.default, ele.classname);
                            break;
                    }
                }
            });
        }
        let save_button = this.createSpanBtn('block_obj_button block_obj_save_button', '保存并关闭', '保存设置并关闭设置窗口', e => {
            this.saveConfig(true);
        });
        let only_save_button = this.createSpanBtn('block_obj_button block_obj_save_button', '仅保存', '仅保存设置', e => {
            this.saveConfig(false);
            only_save_button.textContent = '已保存';
            save_timer && window.clearTimeout(save_timer);
            var save_timer = window.setTimeout(() => {
                only_save_button.textContent = '仅保存';
            }, 1500);
        });
        let cancel_button = this.createSpanBtn('block_obj_button block_obj_cancel_button', '取消', '关闭设置窗口', e => {
            this.expandWrap();
            cancel_timer && window.clearTimeout(cancel_timer);
            var cancel_timer = window.setTimeout(() => {
                this.display = false;
                this.destroyAndRebuild();
            }, 800);
            e.stopPropagation();
        });
        this.ulNode.appendChild(save_button);
        this.ulNode.appendChild(only_save_button);
        this.ulNode.appendChild(cancel_button);
        document.body.appendChild(this.wrapDiv);
    }
    getConfig() {
        return this.config;
    }
    saveConfig(close_status) {
        this.saveField.forEach(item => {
            if (item.type == 'checkbox') {
                this.config[item.key] = document.getElementById(this.id + '_' + item.key).checked;
            } else if (item.type == 'list') {
                this.config[item.key] = this.extractList(this.id + '_' + item.key);
            }
            typeof(this.onSave) === 'function' && this.onSave(this.config);
            close_status && this.expandWrap();
        });
    }
    createSettingsPanel() {
        this.wrapDiv = document.createElement('div');
        this.wrapDiv.id = this.id + '_wrapDiv';
        this.wrapDiv.className = 'block_obj_wrap_div ' + this.display ? 'block_obj_show_wrap' : 'block_obj_hidden_wrap';
        this.mainFieldset = document.createElement('fieldset');
        this.mainFieldset.id = this.id + '_mainFieldset';
        this.mainFieldset.className = 'block_obj_main_fieldset';
        this.wrapDiv.appendChild(this.mainFieldset);
        this.ulNode = document.createElement('ul');
        this.ulNode.id = this.id + '_ulNode';
        this.ulNode.className = 'block_obj_ul_node';
        this.mainFieldset.appendChild(this.ulNode);
        document.body.appendChild(this.wrapDiv);
    }
    destroyAndRebuild(new_config = null) {
        this.config = this.config || new_config;
        document.body.removeChild(this.wrapDiv);
        this.createSettingsPanel();
        this.settingsPanel();
    }
    expandWrap() {
        let panel = document.getElementById(this.id + '_wrapDiv');
        let button = document.getElementById(this.id + '_expandSpan');
        if (panel) {
            if (panel.classList.contains('block_obj_show_wrap')) {
                this.display = false;
                panel.classList.remove('block_obj_show_wrap');
                panel.classList.add('block_obj_hidden_wrap');
                if (button) {
                    button.title = '显示屏蔽设置';
                }
            } else {
                this.display = true;
                panel.classList.remove('block_obj_hidden_wrap');
                panel.classList.add('block_obj_show_wrap');
                if (button) {
                    button.title = '隐藏屏蔽设置';
                }
            }
        }
    }
    insertCheckbox(id, label = '', title = '', checked = false, classname = null) {
        let checkbox_li = document.createElement('li');
        checkbox_li.className = 'block_obj_checkbox_li';
        classname && checkbox_li.classList.add(classname);
        let checkbox_input = document.createElement('input');
        checkbox_input.type = 'checkbox';
        checkbox_input.className = 'block_obj_checkbox_input';
        checkbox_input.id = this.id + '_' + id;
        checkbox_input.checked = checked ? true : false;
        let checkbox_label = document.createElement('label');
        checkbox_label.className = 'block_obj_checkbox_label';
        checkbox_label.setAttribute('for', id);
        checkbox_label.textContent = label;
        checkbox_label.title = title;
        checkbox_li.appendChild(checkbox_input);
        checkbox_li.appendChild(checkbox_label);
        this.ulNode.appendChild(checkbox_li);
        this.saveField.push({
            'key': id,
            'type': 'checkbox'
        });
    }
    insertSeparator(id = null, label = null, title = null, li_classname = null) {
        let separator_li = document.createElement('li');
        separator_li.className = 'block_obj_separator_li';
        li_classname && separator_li.classList.add(li_classname);
        let separator_div = document.createElement('div');
        if (id) {
            separator_div.id = this.id + '_' + id;
        }
        if (label) {
            separator_div.className = 'block_obj_separator_text';
            separator_div.textContent = label;
        } else {
            separator_div.className = 'block_obj_separator_symbol';
        }
        separator_div.title = title ? title : '';
        separator_li.appendChild(separator_div);
        this.ulNode.appendChild(separator_li);
    }
    insertInput(id, list_id, is_reg = false, label = '', title = '', placeholder = '', li_classname = null) {
        let input_li = document.createElement('li');
        input_li.className = li_classname ? li_classname : '';
        let input_div = document.createElement('div');
        input_div.className = 'block_obj_input_div';
        let input_span = document.createElement('span');
        input_span.className = 'block_obj_input_span';
        input_span.textContent = label;
        input_div.appendChild(input_span);
        let input = document.createElement('input');
        input.id = this.id + '_' + id;
        input.title = title;
        input.placeholder = placeholder;
        input.type = 'text';
        input.className = is_reg ? 'block_obj_input block_obj_reg_input' : 'block_obj_input block_obj_keyword_input';
        input_span.appendChild(input);
        let modifier_span = document.createElement('span');
        modifier_span.textContent = '修饰符:';
        is_reg && input_div.appendChild(modifier_span);
        let modifier_input = document.createElement('input');
        modifier_input.placeholder = '如:gim';
        modifier_input.type = 'text';
        modifier_input.className = 'block_obj_input block_obj_modifier_input';
        modifier_span.appendChild(modifier_input);
        list_id = this.id + '_' + list_id;
        input.addEventListener('keyup', e => {
            if (e.keyCode === 13) {
                is_reg ? this.addRegListItem(input, modifier_input, list_id) : this.addListItem(input, list_id);
            }
        });
        modifier_input.addEventListener('keyup', e => {
            e.keyCode === 13 && this.addRegListItem(input, modifier_input, list_id);
        });
        let add_btn = this.createSpanBtn('block_obj_input_btn', '添加', '添加内容到列表中', e => {
            if (is_reg ? this.addRegListItem(input, modifier_input, list_id) : this.addListItem(input, list_id))
                this.buttonClicked(add_btn, '添加成功', 'block_obj_button_clicked');
        });
        let delete_btn = this.createSpanBtn('block_obj_input_btn', '删除', '从列表中删除符合的项目', e => {
            if (is_reg ? this.delRegListItem(input, modifier_input, list_id) : this.delListItem(input, list_id))
                this.buttonClicked(delete_btn, '删除成功', 'block_obj_button_clicked');
        });
        let clear_btn = this.createSpanBtn('block_obj_input_btn', '清空', '清空列表', e => {
            document.getElementById(list_id).innerHTML = '';
            this.buttonClicked(clear_btn, '清除成功', 'block_obj_button_clicked');
        });
        let copy_btn = this.createSpanBtn('block_obj_inut_btn', '复制', '复制列表', e => {
            if (typeof(GM_setClipboard) == 'function') {
                GM_setClipboard(this.extractList(list_id).toString(), 'text');
                this.buttonClicked(copy_btn, '复制成功', 'block_obj_button_clicked');
            } else {
                alert('GM_setClipboard is not an interface.');
            }
        });
        let expand_btn = this.createSpanBtn('block_obj_input_btn', '展开', '展开列表', e => {
            li_classname && this.toggleList(li_classname);
            if (expand_btn.textContent == '展开') {
                expand_btn.textContent = '恢复';
                expand_btn.title = '收缩列表';
            } else {
                expand_btn.textContent = '展开';
                expand_btn.title = '展开列表';
            }
        });
        input_div.appendChild(add_btn);
        input_div.appendChild(delete_btn);
        input_div.appendChild(clear_btn);
        input_div.appendChild(copy_btn);
        input_div.appendChild(expand_btn);
        input_li.appendChild(input_div);
        this.ulNode.appendChild(input_li);
    }
    insertList(id, save_array = [], label = '', title = '', li_classname = '') {
        let list_li = document.createElement('li');
        list_li.className = li_classname;
        let list_div = document.createElement('div');
        list_div.className = 'block_obj_list_div';
        list_div.textContent = label;
        list_div.title = title;
        let list_textarea_div = document.createElement('div');
        list_textarea_div.id = this.id + '_' + id;
        list_textarea_div.className = 'block_obj_list_textarea_div';
        for (let item of save_array) {
            item && list_div.insertAdjacentElement('afterbegin', this.createListItem(item));
        }
        list_div.appendChild(list_textarea_div);
        list_li.appendChild(list_div);
        this.ulNode.appendChild(list_li);
        this.saveField.push({
            'key': id,
            'type': 'list'
        });
    }
    addListItem(input, list_id) {
        let text_value = input.value;
        if (text_value) {
            let text_arr = this.stringToArray(text_value);
            let save_arr = this.extractList(list_id);
            text_arr.forEach(item => {
                ! save_arr.includes(item) && document.getElementById(list_id).insertAdjacentElement('afterbegin', this.createListItem(item));
            });
            input.value = '';
            return true;
        }
        return false;
    }
    delListItem(input, list_id) {
        let text_value = input.value;
        if (text_value) {
            let del_status = false;
            let text_arr = this.stringToArray(text_value);
            let save_arr = this.extractList(list_id);
            text_arr.forEach(item => {
                if (save_arr.includes(item)) {
                    let total_child = document.getElementById(list_id).getElementsByClassName('block_obj_child_span');
                    try {
                        document.getElementById(list_id).removeChild(total_child[total_child.length - 1 - save_arr.indexOf(item)]);
                        del_status = true;
                    } catch(e) {
                        del_status = false;
                        console.error('Block_Obj: Error deleting element.');
                        console.error(e);
                    }
                }
            });
            if (del_status) {
                input.value = '';
                return true;
            }
        }
        return false;
    }
    addRegListItem(reg_input, modifier_input, list_id) {
        let reg_value = reg_input.value;
        let modifier_value = modifier_input.value;
        if (reg_value) {
            try {
                let reg_obj = new RegExp(reg_value, modifier_value);
                let save_arr = this.extractList(list_id);
                ! save_arr.includes(reg_obj.toString()) && document.getElementById(list_id).insertAdjacentElement('afterbegin', this.createListItem(reg_obj.toString()));
                reg_input.value = '';
                modifier_input.value = '';
                return true;
            } catch(e) {
                console.error('Block_Obj: Invalid regular expression.');
                console.error(e);
            }
        }
        return false;
    }
    delRegListItem(reg_input, modifier_input, list_id) {
        let reg_value = reg_input.value;
        let modifier_value = modifier_input.value;
        if (reg_value) {
            let del_status = false;
            try {
                let reg_obj = new RegExp(reg_value, modifier_value);
                let save_arr = this.extractList(list_id);
                if (save_arr.includes(reg_obj.toString())) {
                    let total_child = document.getElementById(list_id).getElementsByClassName('block_obj_child_span');
                    document.getElementById(list_id).removeChild(total_child[total_child.length - 1 - save_arr.indexOf(reg_obj.toString())]);
                    del_status = true;
                }
            } catch(e) {
                del_status = false;
                console.error('Block_Obj: Invalid regular expression or error deleting element.');
                console.error(e);
            }
            if (del_status) {
                reg_input.value = '';
                modifier_input.value = '';
                return true;
            }
            return false;
        }
    }
    createSpanBtn(classname, label, title, callback) {
        let btn_span = document.createElement('span');
        btn_span.className = classname;
        btn_span.textContent = label;
        btn_span.title = title;
        btn_span.addEventListener('click', e => typeof(callback) === 'function' && callback(e));
        return btn_span;
    }
    createListItem(text_value) {
        let child_span = document.createElement('span');
        child_span.className = 'block_obj_child_span';
        let text_span = document.createElement('span');
        text_span.className = 'block_obj_child_text';
        text_span.textContent = text_value.length > 9 ? text_value.slice(0, 3) + '...' + text_value.slice(-3) : text_value;
        if (text_value.length > 9) {
            text_span.title = text_value;
        }
        let del_span = document.createElement('span');
        del_span.textContent = 'X';
        del_span.title = '移除';
        del_span.className = 'block_obj_child_del';
        del_span.addEventListener('click', e => child_span.remove());
        child_span.appendChild(text_span);
        child_span.appendChild(del_span);
        return child_span;
    }
    buttonClicked(button, click_title, click_class) {
        let original_title = button.title;
        button.title = click_title;
        click_class && button.classList.add(click_class);
        timer && window.clearTimeout(timer);
        var timer = window.setTimeout(() => {
            button.title = original_title;
            button.classList.remove(click_class);
        }, 1500);
    }
    extractList(list_id) {
        let re_arr = [];
        let list_dom = document.getElementById(list_id);
        let list_arr = list_dom.getElementsByClassName('block_obj_child_text');
        for (let i = list_arr.length - 1; i >= 0; i --) {
            list_arr[i].title ? re_arr.push(list_arr[i].title) : re_arr.push(list_arr[i].textContent);
        }
        return re_arr;
    }
    stringToArray(text_string) {
        let temp_array = text_string.split(',');
        let return_array = [];
        for (let i = 0, l = temp_array.length; i < l; i ++) {
            for (let j = i + 1; j < l; j ++) {
                if (temp_array[i] === temp_array[j]) {
                    ++ i;
                    j = i;
                }
            }
            return_array.push(temp_array[i]);
        }
        return return_array;
    }
    toggleList(li_classname) {
        for (let li of this.ulNode.querySelectorAll('li')) {
            if (li.classList.contains(li_classname)) {
                let list_textarea_div = li.querySelector('.block_obj_list_textarea_div');
                if (list_textarea_div) {
                    list_textarea_div.classList.contains('block_obj_list_textarea_expand') ? list_textarea_div.classList.remove('block_obj_list_textarea_expand') : list_textarea_div.classList.add('block_obj_list_textarea_expand');
                }
            } else {
                li.classList.contains('block_obj_li_hide') ? li.classList.remove('block_obj_li_hide') : li.classList.add('block_obj_li_hide');
            }
        }
    }
    static convertArray(string_array) {
        let re_arr = [];
        if (Array.isArray(string_array)) {            
            for (let i in string_array) {
                try {
                    let new_reg = new RegExp(string_array[i].replace(/^\/|\/[a-z]*$/gi, ''), string_array[i].replace(/^\/.*\/[^a-z]*/i, ''));
                    re_arr.push(new_reg);
                } catch(e) {
                    console.error('Block_Obj: The transformation contains invalid regular expressions.');
                    console.error(e);
                }
            }
        }
        return re_arr;
    }
}
Block_Obj.count = 0;