dmhy tree view

convert plain file list into a tree view

目前为 2017-04-20 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name dmhy tree view
  3. // @namespace https://greasyfork.org/zh-CN/scripts/26430-dmhy-tree-view
  4. // @license GPL version 3
  5. // @encoding utf-8
  6. // @version 0.27
  7. // @date 2017/01/11
  8. // @modified 2017/04/20
  9. // @description convert plain file list into a tree view
  10. // @author TautCony
  11. // @require http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js
  12. // @require http://cdn.bootcss.com/jstree/3.3.3/jstree.min.js
  13. // @resource customCSS http://cdn.bootcss.com/jstree/3.3.3/themes/default/style.min.css
  14. // @match https://share.dmhy.org/topics/view/*
  15. // @grant GM_addStyle
  16. // @grant GM_getResourceText
  17. // ==/UserScript==
  18. var icons = {
  19. unknown: "https://share.dmhy.org/images/icon/unknown.gif",
  20. audio: "https://share.dmhy.org/images/icon/mp3.gif",
  21. video: "https://share.dmhy.org/images/icon/mp4.gif",
  22. image: "https://share.dmhy.org/images/icon/jpg.gif",
  23. text: "https://share.dmhy.org/images/icon/txt.gif",
  24. rar: "https://share.dmhy.org/images/icon/rar.gif"
  25. };
  26. var type2Icon = {
  27. audio: ["flac", "aac", "wav", "mp3"],
  28. video: ["mkv", "mka", "mp4"],
  29. image: ["jpg", "bmp", "jpeg", "webp"],
  30. text: ["txt", "log", "cue", "ass"],
  31. rar: ["rar", "zip", "7z"],
  32. };
  33. var Dictionary = (function () {
  34. function Dictionary() {
  35. this.__data__ = {};
  36. }
  37. Dictionary.prototype.add = function (key, value) {
  38. if (key in this.__data__)
  39. return;
  40. this.__data__[key] = value;
  41. };
  42. Dictionary.prototype.clear = function () {
  43. this.__data__ = {};
  44. };
  45. Dictionary.prototype.containsKey = function (key) {
  46. return key in this.__data__;
  47. };
  48. Dictionary.prototype.get = function (key) {
  49. return this.__data__[key];
  50. };
  51. Dictionary.prototype.size = function () {
  52. return Object.keys(this.__data__).length;
  53. };
  54. Dictionary.prototype.values = function () {
  55. return this.__data__;
  56. };
  57. return Dictionary;
  58. }());
  59. var FileSize = (function () {
  60. function FileSize() {
  61. }
  62. FileSize.toLength = function (size) {
  63. if (size === undefined)
  64. return -1;
  65. size = size.toLowerCase();
  66. var head = "";
  67. var tail = "";
  68. var isNumber = function (c) { return (c >= '0' && c <= '9') || c === '.' || c === '-'; };
  69. for (var _i = 0, size_1 = size; _i < size_1.length; _i++) {
  70. var c = size_1[_i];
  71. if (isNumber(c))
  72. head += c;
  73. else
  74. tail += c;
  75. }
  76. var value = parseFloat(head);
  77. switch (tail) {
  78. case "byte": return value;
  79. case "bytes": return value;
  80. case "kb": return value * Math.pow(2, 10);
  81. case "mb": return value * Math.pow(2, 20);
  82. case "gb": return value * Math.pow(2, 30);
  83. case "tb": return value * Math.pow(2, 40);
  84. }
  85. return -1;
  86. };
  87. FileSize.format = function (length, factor, tail) {
  88. return (length / Math.pow(2, factor)).toFixed(3).toString() + tail;
  89. };
  90. FileSize.toSize = function (length) {
  91. if (length >= Math.pow(2, 40))
  92. return this.format(length, 40, "TiB");
  93. else if (length >= Math.pow(2, 30))
  94. return this.format(length, 30, "GiB");
  95. else if (length >= Math.pow(2, 20))
  96. return this.format(length, 20, "MiB");
  97. else if (length >= Math.pow(2, 10))
  98. return this.format(length, 10, "KiB");
  99. else
  100. return this.format(length, 0, "Bytes");
  101. };
  102. return FileSize;
  103. }());
  104. var TreeNode = (function () {
  105. function TreeNode(node) {
  106. this.__name__ = node;
  107. this.__length__ = 0;
  108. this.__childNode__ = new Dictionary();
  109. }
  110. TreeNode.prototype.add = function (key, value) {
  111. this.__childNode__.add(key, value);
  112. return this.__childNode__.get(key);
  113. };
  114. TreeNode.prototype.insert = function (path, size) {
  115. var currentNode = this;
  116. for (var _i = 0, path_1 = path; _i < path_1.length; _i++) {
  117. var node = path_1[_i];
  118. var next = currentNode.__childNode__.get(node);
  119. if (!currentNode.__childNode__.containsKey(node)) {
  120. next = currentNode.add(node, new TreeNode(node));
  121. next.__pareneNode__ = currentNode;
  122. }
  123. currentNode = next;
  124. }
  125. currentNode.__length__ = FileSize.toLength(size);
  126. return currentNode;
  127. };
  128. TreeNode.prototype.getIcon = function (ext) {
  129. for (var type in type2Icon) {
  130. if (type2Icon[type].indexOf(ext) > 0) {
  131. return icons[type];
  132. }
  133. }
  134. return icons.unknown;
  135. };
  136. TreeNode.prototype.toString = function () {
  137. return this.__name__ + "\t" + FileSize.toSize(this.__length__);
  138. };
  139. TreeNode.prototype.toObject = function () {
  140. var ret = {};
  141. ret.children = [];
  142. ret.length = 0;
  143. ret.text = this.__name__;
  144. ret.state = { opened: true };
  145. for (var key in this.__childNode__.values()) {
  146. var files = [];
  147. var value = this.__childNode__.get(key);
  148. if (value.__childNode__.size() === 0) {
  149. files.push(value);
  150. }
  151. else {
  152. var tmp = {};
  153. tmp.children = [];
  154. tmp.length = 0;
  155. var inner = value.toObject();
  156. for (var _i = 0, _a = inner.children; _i < _a.length; _i++) {
  157. var innerNode = _a[_i];
  158. tmp.children.push(innerNode);
  159. tmp.length += innerNode.length;
  160. }
  161. ret.length += tmp.length;
  162. value.__length__ = tmp.length;
  163. tmp.text = value.toString();
  164. ret.children.push(tmp);
  165. }
  166. for (var _b = 0, files_1 = files; _b < files_1.length; _b++) {
  167. var file = files_1[_b];
  168. var ext = file.__name__.substr(file.__name__.lastIndexOf('.') + 1).toLowerCase();
  169. ret.length += file.__length__;
  170. ret.children.push({
  171. icon: this.getIcon(ext),
  172. text: file.toString(),
  173. length: file.__length__
  174. });
  175. }
  176. }
  177. return ret;
  178. };
  179. return TreeNode;
  180. }());
  181. var GM_getResourceText = GM_getResourceText;
  182. var GM_addStyle = GM_addStyle;
  183. (function () {
  184. "use strict";
  185. if (typeof GM_getResourceText !== "undefined") {
  186. GM_addStyle(GM_getResourceText("customCSS"));
  187. }
  188. else {
  189. console.info("You may need to install http://tampermonkey.net/ to use this script.");
  190. }
  191. $('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>');
  192. $('#tabs-1').append('<input type="text" value="" style="box-shadow:inset 0 0 4px #eee; width:240px; margin:0; padding:6px 12px; border-radius:4px; border:1px solid silver; font-size:1.1em;" id="search_input" placeholder="Search" />');
  193. $('.file_list').css('width', '100%');
  194. $('.file_list').css('max-height', '600px');
  195. var data = new TreeNode($('.topic-title > h3').text());
  196. $('.file_list > ul li').each(function (index) {
  197. var text = $(this).text();
  198. var line = text.trim().replace(/\t+/i, '\t').split('\t');
  199. if (line.length == 2) {
  200. var nodes = line[0].split('/');
  201. var size = line[1];
  202. data.insert(nodes, size);
  203. }
  204. else if (line.length == 1) {
  205. //the text should be "More Than 1000 Files"
  206. data.insert(line[0].split('/'), "");
  207. }
  208. });
  209. $('.file_list').jstree({
  210. core: { data: data.toObject() },
  211. plugins: ["search"]
  212. });
  213. var id = 0;
  214. var lastVal = "";
  215. $('#search_input').keyup(function () {
  216. if (id)
  217. clearTimeout(id);
  218. id = setTimeout(function () {
  219. var val = $('#search_input').val();
  220. if (val === lastVal)
  221. return;
  222. $('.file_list').jstree(true).search(val);
  223. }, 250);
  224. });
  225. })();