// ==UserScript==
// @name dmhy tree view
// @namespace https://greasyfork.org/zh-CN/scripts/26430-dmhy-tree-view
// @license GPL version 3
// @encoding utf-8
// @version 0.29
// @date 2017/01/11
// @modified 2017/05/11
// @description convert plain file list into a tree view for 动漫花园 (share.dmhy.org)
// @author TautCony
// @require http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js
// @require http://cdn.bootcss.com/jstree/3.3.3/jstree.min.js
// @resource customCSS http://cdn.bootcss.com/jstree/3.3.3/themes/default/style.min.css
// @match *://share.dmhy.org/topics/view/*
// @grant GM_addStyle
// @grant GM_getResourceText
// ==/UserScript==
var icons = {
unknown: "https://share.dmhy.org/images/icon/unknown.gif",
audio: "https://share.dmhy.org/images/icon/mp3.gif",
video: "https://share.dmhy.org/images/icon/mp4.gif",
image: "https://share.dmhy.org/images/icon/jpg.gif",
text: "https://share.dmhy.org/images/icon/txt.gif",
rar: "https://share.dmhy.org/images/icon/rar.gif"
};
var type2Icon = {
audio: ["flac", "aac", "wav", "mp3"],
video: ["mkv", "mka", "mp4"],
image: ["jpg", "bmp", "jpeg", "webp"],
text: ["txt", "log", "cue", "ass"],
rar: ["rar", "zip", "7z"],
};
var Dictionary = (function () {
function Dictionary() {
this.__data__ = {};
}
Dictionary.prototype.add = function (key, value) {
if (key in this.__data__)
return;
this.__data__[key] = value;
};
Dictionary.prototype.clear = function () {
this.__data__ = {};
};
Dictionary.prototype.containsKey = function (key) {
return key in this.__data__;
};
Dictionary.prototype.get = function (key) {
return this.__data__[key];
};
Dictionary.prototype.size = function () {
return Object.keys(this.__data__).length;
};
Dictionary.prototype.values = function () {
return this.__data__;
};
return Dictionary;
}());
var FileSize = (function () {
function FileSize() {
}
FileSize.toLength = function (size) {
if (size === undefined)
return -1;
size = size.toLowerCase();
var head = "";
var tail = "";
var isNumber = function (c) { return (c >= '0' && c <= '9') || c === '.' || c === '-'; };
for (var _i = 0, size_1 = size; _i < size_1.length; _i++) {
var c = size_1[_i];
if (isNumber(c))
head += c;
else
tail += c;
}
var value = parseFloat(head);
switch (tail) {
case "byte": return value;
case "bytes": return value;
case "kb": return value * Math.pow(2, 10);
case "mb": return value * Math.pow(2, 20);
case "gb": return value * Math.pow(2, 30);
case "tb": return value * Math.pow(2, 40);
}
return -1;
};
FileSize.format = function (length, factor, tail) {
return (length / Math.pow(2, factor)).toFixed(3).toString() + tail;
};
FileSize.toSize = function (length) {
if (length >= Math.pow(2, 40))
return this.format(length, 40, "TiB");
else if (length >= Math.pow(2, 30))
return this.format(length, 30, "GiB");
else if (length >= Math.pow(2, 20))
return this.format(length, 20, "MiB");
else if (length >= Math.pow(2, 10))
return this.format(length, 10, "KiB");
else
return this.format(length, 0, "Bytes");
};
return FileSize;
}());
var TreeNode = (function () {
function TreeNode(node) {
this.__name__ = node;
this.__length__ = 0;
this.__childNode__ = new Dictionary();
}
TreeNode.prototype.add = function (key, value) {
this.__childNode__.add(key, value);
return this.__childNode__.get(key);
};
TreeNode.prototype.insert = function (path, size) {
var currentNode = this;
for (var _i = 0, path_1 = path; _i < path_1.length; _i++) {
var node = path_1[_i];
var next = currentNode.__childNode__.get(node);
if (!currentNode.__childNode__.containsKey(node)) {
next = currentNode.add(node, new TreeNode(node));
next.__pareneNode__ = currentNode;
}
currentNode = next;
}
currentNode.__length__ = FileSize.toLength(size);
return currentNode;
};
TreeNode.prototype.getIcon = function (ext) {
for (var type in type2Icon) {
if (type2Icon[type].indexOf(ext) >= 0) {
return icons[type];
}
}
return icons.unknown;
};
TreeNode.prototype.toString = function () {
return this.__name__ + "\t" + FileSize.toSize(this.__length__);
};
TreeNode.prototype.toObject = function () {
var ret = {};
ret.children = [];
ret.length = 0;
ret.text = this.__name__;
ret.state = { opened: true };
for (var key in this.__childNode__.values()) {
var files = [];
var value = this.__childNode__.get(key);
if (value.__childNode__.size() === 0) {
files.push(value);
}
else {
var tmp = {};
tmp.children = [];
tmp.length = 0;
var inner = value.toObject();
for (var _i = 0, _a = inner.children; _i < _a.length; _i++) {
var innerNode = _a[_i];
tmp.children.push(innerNode);
tmp.length += innerNode.length;
}
ret.length += tmp.length;
value.__length__ = tmp.length;
tmp.text = value.toString();
ret.children.push(tmp);
}
for (var _b = 0, files_1 = files; _b < files_1.length; _b++) {
var file = files_1[_b];
var ext = file.__name__.substr(file.__name__.lastIndexOf('.') + 1).toLowerCase();
ret.length += file.__length__;
ret.children.push({
icon: this.getIcon(ext),
text: file.toString(),
length: file.__length__
});
}
}
return ret;
};
return TreeNode;
}());
var GM_getResourceText = GM_getResourceText;
var GM_addStyle = GM_addStyle;
(function () {
"use strict";
if (typeof GM_getResourceText !== "undefined") {
GM_addStyle(GM_getResourceText("customCSS"));
}
else {
console.info("%cYou may need to install http://tampermonkey.net/ to use this script.", "color:#e55d67;font-size:1.5em");
}
$('head').append('<style>.jstree-node, .jstree-default .jstree-icon {background-image: url(http://cdn.bootcss.com/jstree/3.3.3/themes/default/32px.png);}</style>');
$('#tabs-1').append('<input type="text" value="" style="width:240px;margin:0;padding:6px 12px;border-radius:4px;border:1px solid silver;font-size:1.1em;" id="search_input" placeholder="Search" />');
$('#tabs-1').append('<button id="switch" style="border:0;border-radius:2px;padding:8px;margin-left:10px;">Expand All</button>');
$('.file_list').css('width', '100%');
$('.file_list').css('max-height', '600px');
var data = new TreeNode($('.topic-title > h3').text());
$('.file_list > ul li').each(function (index) {
var text = $(this).text();
var line = text.trim().replace(/\t+/i, '\t').split('\t');
if (line.length == 2) {
var nodes = line[0].split('/');
var size = line[1];
data.insert(nodes, size);
}
else if (line.length == 1) {
//the text should be "More Than 1000 Files"
data.insert(line[0].split('/'), "");
}
});
$('.file_list').jstree({
core: { data: data.toObject() },
plugins: ["search", "wholerow"]
}).bind("loaded.jstree", function (event, data) {
var self = this;
var isExpended = false;
$('#switch').click(function () {
if (isExpended) {
$(this).text("Expand All");
$(self).jstree('close_all');
}
else {
$(this).text("Toggle All");
$(self).jstree('open_all');
}
isExpended = !isExpended;
});
});
var id = 0;
var lastVal = "";
$('#search_input').keyup(function () {
if (id)
clearTimeout(id);
id = setTimeout(function () {
var val = $('#search_input').val();
if (val === lastVal)
return;
$('.file_list').jstree(true).search(val);
}, 250);
});
})();