Sorting for TJU Drive

天大云盘排序,点击"文档名称 类型 大小 修改时间"四者之一可自定义排序方式

// ==UserScript==
// @name         Sorting for TJU Drive
// @namespace    https://github.com/8qwe24657913
// @version      0.1
// @description  天大云盘排序,点击"文档名称 类型 大小 修改时间"四者之一可自定义排序方式
// @author       8qwe24657913
// @match        http://pan.tju.edu.cn/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';
    // 默认排序优先级:文档名称(正向字符串排序) > 类型/后缀名(正向字符串排序) > 大小(由小到大) > 修改时间(由新到旧)
    const sortPrecedence = [['name', false], ['type', false], ['size', false], ['modified', true]];
    const isFolder = info => info.size === -1;
    const getSuffix = info => {
        let arr = info.name.split('.');
        return arr.length > 1 ? arr[arr.length - 1] : '';
    };
    const names = [null, 'name', 'type', 'size', 'modified']; // 文档名称 类型 大小 修改时间
    const sortFns = {
        name: (a, b) => a.name.localeCompare(b.name),
        type: (a, b) => isFolder(a) ? isFolder(b) ? 0 : 1 : isFolder(b) ? -1 : getSuffix(a).localeCompare(getSuffix(b)),
        size: (a, b) => a.size - b.size,
        modified: (a, b) => a.modified - b.modified,
    };
    const css = `
.sftd-arrow::after {
border: .5em solid transparent;
width: 0;
height: 0;
display: inline-block;
content: "";
position: relative;
left: .25em;
}
.sftd-bottom-arrow::after {
border-top-color: grey;
top: .5em;
}
.sftd-top-arrow::after {
border-bottom-color: grey;
bottom: .5em;
}
`;
    (document.head || document.documentElement).appendChild(document.createElement('style')).appendChild(document.createTextNode(css));
    function toFastProperties(obj) { // https://stackoverflow.com/questions/24987896/how-does-bluebirds-util-tofastproperties-function-make-an-objects-properties
        /*jshint -W027*/
        function f() {}
        f.prototype = obj;
        //ASSERT("%HasFastProperties", true, obj);
        return f;
        eval(obj);
    }
    let list, uploader;
    Object.defineProperty(Function.prototype, 'defaultProps', { // hook react components
        set(val) {
            Object.defineProperty(this, 'defaultProps', {
                value: val,
                writable: true,
                configurable: true,
                enumerable: true
            });
            if (typeof this.prototype.updateDocs === 'function') {
                let updateDocs = this.prototype.updateDocs;
                this.prototype.updateDocs = function (docs) {
                    return updateDocs.call(list = this, docs.sort(function (a, b) {
                        for (let [pref, reverse] of sortPrecedence) {
                            let res = sortFns[pref](a, b);
                            if (res != 0) return reverse ? -res : res;
                        }
                        return 0;
                    }));
                };
                delete Function.prototype.defaultProps;
                toFastProperties(Function.prototype);
            }
        },
        configurable: true,
        enumerable: false
    });
    let last;
    document.addEventListener('click', function (e) {
        if (!list) return;
        let th = e.target.closest('th._-ShareWebUI-src-DataGrid-style-desktop---cell');
        if (!th) return;
        if (last && last !== th) last.classList.remove('sftd-arrow', 'sftd-top-arrow', 'sftd-bottom-arrow');
        last = th;
        th.classList.add('sftd-arrow');
        let reversed = th.classList.contains('sftd-top-arrow');
        if (reversed) {
            th.classList.remove('sftd-top-arrow');
            th.classList.add('sftd-bottom-arrow');
        } else {
            th.classList.remove('sftd-bottom-arrow');
            th.classList.add('sftd-top-arrow');
        }
        let name = names[[].indexOf.call(th.parentElement.children, th)],
            index = sortPrecedence.findIndex(([str]) => str === name);
        sortPrecedence.splice(index, 1);
        sortPrecedence.unshift([name, reversed]);
        list.updateDocs(list.state.docs);
    }, false);
})();