├── README.md ├── empn.user.js └── src ├── actions.js ├── css ├── md.css └── style.css ├── data.js ├── gui-prefs.js ├── gui.js ├── helpers.js ├── html ├── empn.html ├── item.html └── toast.html ├── keyboard.js ├── md.js ├── prefs.js ├── script.js └── state.js /README.md: -------------------------------------------------------------------------------- 1 | # EMPN 2 | UserScript for empornium.me 3 | 4 | ## Installation 5 | https://github.com/LenAnderson/EMPN/raw/master/empn.user.js 6 | 7 | ## Issues / Requests / Questions... 8 | To report any issues, make requests or ask questions about the script please use GitHub's issue tracker. 9 | 10 | --- 11 | -------------------------------------------------------------------------------- /empn.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name EMPN 3 | // @namespace https://github.com/LenAnderson/ 4 | // @downloadURL https://github.com/LenAnderson/EMPN/raw/master/empn.user.js 5 | // @version 0.8 6 | // @author LenAnderson 7 | // @match http://*.empornium.me/* 8 | // @match https://*.empornium.me/* 9 | // @match http://*.empornium.sx/* 10 | // @match https://*.empornium.sx/* 11 | // @match http://*.empornium.is/* 12 | // @match https://*.empornium.is/* 13 | // @grant none 14 | // ==/UserScript== 15 | 16 | 17 | 18 | 19 | 20 | 21 | /****************************************\ 22 | | $HELPERS 23 | \****************************************/ 24 | Object.prototype.addListener = function(type, func) { 25 | if (!this.listeners) { 26 | Object.defineProperty(this, 'listeners', { 27 | writable: true, 28 | value: {} 29 | }); 30 | } 31 | if (!this.listeners[type]) 32 | this.listeners[type] = []; 33 | this.listeners[type].push(func); 34 | return func; 35 | }; 36 | Object.prototype.removeListener = function(type, func) { 37 | if (!this.listeners[type]) 38 | return; 39 | for (var i=0;i offset) { 104 | this.children[offset].remove(); 105 | } 106 | }; 107 | 108 | Node.prototype.scrollToV = function(y) { 109 | var el = this; 110 | var timeLapsed = 0; 111 | var percentage = 0; 112 | var position = el.scrollTop; 113 | var distance = y - el.scrollTop; 114 | var startLocation = el.scrollTop; 115 | var interval = undefined; 116 | 117 | var pattern = function(time) { 118 | return time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; 119 | }; 120 | 121 | var start = function() { 122 | interval = setInterval(loop, 16); 123 | }; 124 | var loop = function() { 125 | timeLapsed += 16; 126 | percentage = timeLapsed / 500; 127 | percentage = percentage > 1 ? 1 : percentage; 128 | position = startLocation + (distance * pattern(percentage)); 129 | el.scrollTop = position; 130 | stop(); 131 | }; 132 | var stop = function() { 133 | if (percentage < 1) return; 134 | 135 | clearInterval(interval); 136 | }; 137 | 138 | start(); 139 | }; 140 | Node.prototype.scrollToH = function(x) { 141 | var el = this; 142 | var timeLapsed = 0; 143 | var percentage = 0; 144 | var position = el.scrollLeft; 145 | var distance = x - el.scrollLeft; 146 | var startLocation = el.scrollLeft; 147 | var interval = undefined; 148 | 149 | var pattern = function(time) { 150 | return time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; 151 | }; 152 | 153 | var start = function() { 154 | interval = setInterval(loop, 16); 155 | }; 156 | var loop = function() { 157 | timeLapsed += 16; 158 | percentage = timeLapsed / 500; 159 | percentage = percentage > 1 ? 1 : percentage; 160 | position = startLocation + (distance * pattern(percentage)); 161 | el.scrollLeft = position; 162 | stop(); 163 | }; 164 | var stop = function() { 165 | if (percentage < 1) return; 166 | 167 | clearInterval(interval); 168 | }; 169 | 170 | start(); 171 | }; 172 | 173 | function stopProp(evt) { 174 | evt.stopPropagation(); 175 | } 176 | 177 | function keyIdentifier(evt) { 178 | if (evt == null) return ''; 179 | if (typeof evt == 'string') evt = JSON.parse(evt); 180 | var key = []; 181 | if (evt.ctrlKey) key.push('Ctrl'); 182 | if (evt.shiftKey) key.push('Shift'); 183 | 184 | var ki; 185 | if (evt.keyIdentifier) { 186 | ki = evt.keyIdentifier; 187 | } else { 188 | if (evt.keyCode == 16) ki = 'Shift'; 189 | else if (evt.keyCode == 17) ki = 'Ctrl'; 190 | else if (evt.keyCode == 18) ki = 'Alt'; 191 | else if (evt.keyCode == 37) ki = 'Left'; 192 | else if (evt.keyCode == 38) ki = 'Up'; 193 | else if (evt.keyCode == 39) ki = 'Right'; 194 | else if (evt.keyCode == 40) ki = 'Down'; 195 | else if (evt.keyCode == 46) ki = 'U+007F'; // Del 196 | else if (evt.keyCode == 18) ki = 'U+0020'; // Space 197 | else if (evt.keyCode == 8) ki = 'U+0008'; // Backspace 198 | else if (evt.keyCode == 9) ki = 'U+0009'; // Tab 199 | else if (evt.keyCode == 27) ki = 'U+001B'; // Esc 200 | else ki = 'U+' + ('0000' + evt.keyCode.toString(16)).slice(-4); 201 | } 202 | if (ki == undefined) return ''; 203 | if (ki.search(/^U\+([0-9A-F]){4}$/) == 0) { 204 | if (ki == 'U+0020') 205 | key.push('Space'); 206 | else if (ki == 'U+007F') 207 | key.push('Del'); 208 | else if (ki == 'U+0008') 209 | key.push('Backspace'); 210 | else if (ki == 'U+0009') 211 | key.push('Tab'); 212 | else if (ki == 'U+001B') 213 | key.push('Esc'); 214 | else 215 | key.push(String.fromCharCode(Number.parseInt(ki.substring(2), 16).toString(10))); 216 | } else { 217 | key.push(ki); 218 | } 219 | 220 | return key.unique().join('+'); 221 | } 222 | 223 | function mapToQuery() { 224 | var params = []; 225 | for (var key in this) { 226 | if (!this.hasOwnProperty(key) || typeof this[key] == 'function') continue; 227 | params.push(encodeURIComponent(key) + '=' + encodeURIComponent(this[key])); 228 | } 229 | return params.join('&'); 230 | } 231 | 232 | function get(url) { 233 | return new Promise(function(resolve, reject) { 234 | var xhr = new XMLHttpRequest(); 235 | xhr.open('GET', url, true); 236 | xhr.addEventListener('load', function() { 237 | if (xhr.status == 200) { 238 | resolve(xhr.responseText); 239 | } else { 240 | reject(Error(xhr.statusText)); 241 | } 242 | }); 243 | xhr.send(); 244 | }); 245 | } 246 | function getResponse(url, params, headers) { 247 | params = params || {}; 248 | headers = headers || {}; 249 | return new Promise(function(resolve, reject) { 250 | var xhr = new XMLHttpRequest(); 251 | xhr.open('GET', url, true); 252 | xhr.addEventListener('load', function() { 253 | resolve(xhr.response); 254 | }) 255 | Object.keys(params).forEach(function(key) { 256 | xhr[key] = params[key]; 257 | }); 258 | Object.keys(headers).forEach(function(key) { 259 | xhr.setRequestHeader(key, headers[key]); 260 | }); 261 | xhr.send(); 262 | }); 263 | } 264 | function post(url, args) { 265 | return new Promise(function(resolve, reject) { 266 | var xhr = new XMLHttpRequest(); 267 | xhr.open('POST', url, true); 268 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 269 | xhr.addEventListener('load', function() { 270 | if (xhr.status == 200) { 271 | resolve(xhr.responseText); 272 | } else { 273 | reject(Error(xhr.statusText)); 274 | } 275 | }); 276 | if (args) { 277 | args.toString = mapToQuery; 278 | } 279 | xhr.send(args); 280 | }); 281 | } 282 | function getHTML(url) { 283 | return get(url).then( 284 | function(txt) { 285 | var html = document.createElement('div'); 286 | html.innerHTML = txt.replace(/ (src|href)=/g, ' data-$1='); 287 | return html; 288 | }); 289 | } 290 | 291 | 292 | 293 | 294 | 295 | /****************************************\ 296 | | $MD 297 | \****************************************/ 298 | var md = { 299 | init: function() { 300 | this.dialog.init($$('.empn-empn-dialog')); 301 | this.menu.init($$('.empn-empn-menu')); 302 | this.tabbar.init($$('.empn-empn-tabbar')); 303 | this.ripple.init($$('button, input[type="button"], input[type="submit"], .empn-tabbar .empn-item, .empn-menu .empn-item, .empn-toolbar .empn-item')); 304 | this.progress.bar.init($$('.empn-empn-progress-bar')); 305 | this.input.init($$('.empn-empn-input')); 306 | }, 307 | 308 | toasts: { 309 | init: function(tstss) { 310 | if (tstss instanceof Element) { 311 | tstss = [tstss]; 312 | } 313 | tstss.forEach(function(tsts) { 314 | tsts.add = function(title, desc) { 315 | return this.add(tsts, title, desc); 316 | }.bind(this); 317 | }.bind(this)); 318 | }, 319 | add: function(tsts, title, desc) { 320 | var tst = document.createElement('li'); 321 | tst.addClass('empn-toast'); 322 | var tstTitle = document.createElement('div'); 323 | tstTitle.addClass('empn-title'); 324 | var tstInfo = document.createElement('div'); 325 | tstInfo.addClass('empn-info'); 326 | tstTitle.textContent = title; 327 | tstInfo.textContent = desc; 328 | tst.appendChild(tstTitle); 329 | tst.appendChild(tstInfo); 330 | 331 | tsts.appendChild(tst); 332 | tst.style.marginTop = -tst.offsetHeight + 'px'; 333 | if (tsts.children.length > 0) { 334 | tsts.insertBefore(tst, tsts.children[0]); 335 | } else { 336 | tsts.appendChild(tst); 337 | } 338 | tst.addClass('empn-preactive'); 339 | setTimeout(function() { tst.addClass('empn-active'); }.bind(this), 1); 340 | setTimeout(function() { 341 | tst.delClass('empn-active'); 342 | setTimeout(function() { tst.remove(); }, 205); 343 | }.bind(this), 5000); 344 | } 345 | }, 346 | 347 | dialog: { 348 | init: function(dlgs) { 349 | if (dlgs instanceof Element) { 350 | dlgs = [dlgs]; 351 | } 352 | dlgs.forEach(function(dlg) { 353 | dlg.show = function(src) { 354 | return this.show(dlg, src); 355 | }.bind(this); 356 | dlg.hide = function() { 357 | return this.hide(dlg); 358 | }.bind(this); 359 | }.bind(this)); 360 | }, 361 | show: function(dlg, src) { 362 | src = src || dlg; 363 | return new Promise(function(resolve, reject) { 364 | dlg.mdDlgSrc = src; 365 | dlg.addClass('empn-preactive'); 366 | var c = dlg.$('.empn-content'); 367 | var b = c.getBoundingClientRect(); 368 | 369 | var bb; 370 | if (src instanceof MouseEvent) { 371 | bb = {top: src.clientY, height: 0, left: src.clientX, width: 0}; 372 | } else { 373 | bb = src.getBoundingClientRect(); 374 | } 375 | 376 | var y = Math.round((bb.top + bb.height * 0.5) - (b.top + b.height * 0.5)) + 'px'; 377 | var x = Math.round((bb.left + bb.width * 0.5) - (b.left + b.width * 0.5)) + 'px'; 378 | 379 | c.style.transform = 'translate('+x+', '+y+') scale(0)'; 380 | 381 | setTimeout(function() { dlg.addClass('empn-active'); }, 20); 382 | setTimeout(function() { 383 | c.style.transition = 'all 0.4s ease-in-out'; 384 | 385 | resolve(dlg); 386 | }, 500); 387 | }); 388 | }, 389 | hide: function(dlg) { 390 | return new Promise(function(resolve, reject) { 391 | var src = dlg.mdDlgSrc || dlg; 392 | var c = dlg.$('.empn-content'); 393 | var b = c.getBoundingClientRect(); 394 | 395 | var bb; 396 | if (src instanceof MouseEvent) { 397 | bb = {top: src.clientY, height: 0, left: src.clientX, width: 0}; 398 | } else { 399 | bb = src.getBoundingClientRect(); 400 | } 401 | 402 | var y = Math.round((bb.top + bb.height * 0.5) - (b.top + b.height * 0.5)) + 'px'; 403 | var x = Math.round((bb.left + bb.width * 0.5) - (b.left + b.width * 0.5)) + 'px'; 404 | 405 | c.style.transform = 'translate('+x+', '+y+') scale(0)'; 406 | 407 | dlg.delClass('empn-active'); 408 | setTimeout(function() { 409 | dlg.delClass('empn-preactive'); 410 | c.style.transform = ''; 411 | c.style.transition = ''; 412 | 413 | resolve(dlg); 414 | }, 400); 415 | }); 416 | } 417 | }, 418 | 419 | menu: { 420 | init: function(menus) { 421 | if (menus instanceof Element) { 422 | menus = [menus]; 423 | } 424 | menus.forEach(function(menu) { 425 | menu.show = function() { 426 | return this.show(menu); 427 | }.bind(this); 428 | menu.hide = function() { 429 | return this.hide(menu); 430 | }.bind(this); 431 | menu.addEventListener('click', menu.hide); 432 | menu.$('.empn-content').addEventListener('click', function(evt) { evt.stopPropagation(); }); 433 | }.bind(this)); 434 | }, 435 | show: function(menu) { 436 | return new Promise(function(resolve, reject) { 437 | menu.addClass('empn-preactive'); 438 | 439 | setTimeout(function() { 440 | // $('#app').style.transform = 'translateX(' + menu.$('.empn-content').offsetWidth + 'px' + ')'; 441 | menu.addClass('empn-active'); 442 | }, 20); 443 | setTimeout(function() { resolve(menu); }, 420); 444 | }); 445 | }, 446 | hide: function(menu) { 447 | return new Promise(function(resolve, reject) { 448 | // $('#app').style.transform = ''; 449 | menu.delClass('empn-active'); 450 | setTimeout(function() { 451 | menu.delClass('empn-preactive'); 452 | resolve(menu); 453 | }, 400); 454 | }); 455 | } 456 | }, 457 | 458 | tabbar: { 459 | init: function(bars) { 460 | if (bars instanceof Element) { 461 | bars = [bars]; 462 | } 463 | bars.forEach(function(bar) { 464 | var items = bar.$$('.empn-item'); 465 | for (var i=0;i 0; 730 | }, 731 | getRandomComment: function() { 732 | return this.comments[Math.floor(Math.random()*this.comments.length)]; 733 | }, 734 | 735 | save: function() { 736 | localStorage.setItem('empn_prefs', JSON.stringify(this)); 737 | }, 738 | load: function() { 739 | var prefs = false; 740 | try { 741 | prefs = JSON.parse(localStorage.getItem('empn_prefs')); 742 | } catch(ex) {} 743 | if (prefs && prefs.meta && prefs.meta.version) { 744 | switch(prefs.meta.version) { 745 | case 1: 746 | this.initV1(prefs); 747 | break; 748 | default: 749 | alert('Unknown preferences format (version "' + prefs.meta.version + '").\n\nPreferences will be reset to default values.'); 750 | this.save(); 751 | break; 752 | } 753 | } 754 | }, 755 | initV1: function(prefs) { 756 | for (var key in prefs) { 757 | if (prefs.hasOwnProperty(key) && this.hasOwnProperty(key)) { 758 | if (key == 'keys') { 759 | for (var _key in prefs[key]) { 760 | if (prefs[key].hasOwnProperty(_key) && this.keys.hasOwnProperty(_key)) { 761 | this.keys[_key] = prefs[key][_key]; 762 | } 763 | } 764 | } else if (key == 'latest') { 765 | this[key] = new Date(prefs[key]); 766 | } else { 767 | this[key] = prefs[key]; 768 | } 769 | } 770 | } 771 | } 772 | }; 773 | var gui = { 774 | tplItem: undefined, 775 | 776 | // elements 777 | _items: undefined, 778 | _dlgImg: undefined, 779 | _img: undefined, 780 | _dlgDesc: undefined, 781 | _dlgComm: undefined, 782 | _dlgQuality: undefined, 783 | _dlgComment: undefined, 784 | _comment: undefined, 785 | _prefs: undefined, 786 | _toast: undefined, 787 | 788 | fullsized: false, 789 | height: 0, 790 | vis: [], 791 | 792 | prefs: { 793 | _dlgComments: undefined, 794 | _commentsInput: undefined, 795 | _dlgTags: undefined, 796 | _thumbHeight: undefined, 797 | _autoTags: undefined, 798 | _tagLimit: undefined, 799 | _newestFirst: undefined, 800 | _autoThanks: undefined, 801 | _autoComments: undefined, 802 | _autoCommentsPrompt: undefined, 803 | _dlgKeys: undefined, 804 | _tblKeys: undefined, 805 | _tagsGood: undefined, 806 | _tagsBad: undefined, 807 | _tagsVGood: undefined, 808 | _tagsVBad: undefined, 809 | _combine: undefined, 810 | _combineHighest: undefined, 811 | _timeOffset: undefined, 812 | _torrentLimit: undefined, 813 | _latestTorrent: undefined, 814 | _useSearchString: undefined, 815 | _searchString: undefined, 816 | _dlgSearchString: undefined, 817 | _dlgSearchStringHelp: undefined, 818 | _nfo: undefined, 819 | 820 | init: function() { 821 | this._dlgComments = $('#dlg-prefs-comments'); 822 | this._commentsInput = $('#dlg-prefs-comments-input'); 823 | this._dlgTags = $('#dlg-prefs-tags'); 824 | this._thumbHeight = $('#prefs-thumb-height'); 825 | this._tagLimit = $('#prefs-tag-limit'); 826 | this._newestFirst = $('#prefs-newest-first'); 827 | this._autoThanks = $('#prefs-auto-thanks'); 828 | this._autoComments = $('#prefs-auto-comments'); 829 | this._autoCommentsPrompt = $('#prefs-auto-comments-prompt'); 830 | this._dlgKeys = $('#dlg-prefs-keys'); 831 | this._tblKeys = $('#dlg-prefs-keys tbody'); 832 | this._tagsGood = $('#dlg-prefs-tags-good'); 833 | this._tagsBad = $('#dlg-prefs-tags-bad'); 834 | this._tagsVGood = $('#dlg-prefs-tags-vgood'); 835 | this._tagsVBad = $('#dlg-prefs-tags-vbad'); 836 | this._autoTags = $('#prefs-auto-tags'); 837 | this._combine = $('#prefs-combine'); 838 | this._combineHighest = $('#prefs-combine-highest'); 839 | this._timeOffset = $('#prefs-timezone-offset'); 840 | this._torrentLimit = $('#prefs-torrent-limit'); 841 | this._latestTorrent = $('#prefs-latest-torrent'); 842 | this._useSearchString = $('#prefs-use-search-string'); 843 | this._searchString = $('#dlg-prefs-search-string-input'); 844 | this._dlgSearchString = $('#dlg-prefs-search-string'); 845 | this._dlgSearchStringHelp = $('#dlg-prefs-search-string-help'); 846 | this._nfo = $('#prefs-nfo'); 847 | 848 | this.initValues(); 849 | 850 | $('#prefs-comments')._('click', this._dlgComments.show); 851 | $('#prefs-tags')._('click', this._dlgTags.show); 852 | $('#prefs-thumb-height')._('click', stopProp); 853 | $('#prefs-tag-limit')._('click', stopProp); 854 | $('#prefs-timezone-offset')._('click', stopProp); 855 | $('#prefs-torrent-limit')._('click', stopProp); 856 | $('#prefs-latest-torrent')._('click', stopProp); 857 | $('#prefs-search-string')._('click', this._dlgSearchString.show); 858 | $('#prefs-search-string-help')._('click', this._dlgSearchStringHelp.show); 859 | 860 | this._newestFirst._('change', function() { 861 | prefs.setNewestFirst(this.checked); 862 | data.update(); 863 | }); 864 | 865 | this._combine._('change', function() { 866 | prefs.setCombine(this.checked); 867 | data.update(); 868 | }); 869 | this._combineHighest._('change', function() { 870 | prefs.setCombineHighest(this.checked); 871 | }); 872 | 873 | this._autoThanks._('change', function() { 874 | prefs.setAutoThanks(this.checked); 875 | }); 876 | 877 | this._autoComments._('change', function() { 878 | prefs.setAutoComments(this.checked); 879 | }); 880 | 881 | this._autoCommentsPrompt._('change', function() { 882 | prefs.setAutoCommentsPrompt(this.checked); 883 | }); 884 | 885 | this._thumbHeight._('change', function() { 886 | prefs.setThumbHeight(this.value*1); 887 | gui.repaint(true); 888 | }); 889 | 890 | this._autoTags._('change', function() { 891 | prefs.setAutoTags(this.checked); 892 | gui.repaint(true); 893 | }); 894 | 895 | this._tagLimit._('change', function() { 896 | prefs.setTagLimit(this._tagLimit.value*1); 897 | this.initValues(); 898 | gui.repaint(true); 899 | }.bind(this)); 900 | 901 | this._useSearchString._('change', function() { 902 | prefs.setUseSearchString(this.checked); 903 | }); 904 | 905 | this._nfo._('change', function() { 906 | prefs.setNfo(this.checked); 907 | }); 908 | 909 | $('#prefs-keys')._('click', this._dlgKeys.show); 910 | 911 | // dlg: comments 912 | $('#dlg-prefs-comments-ok')._('click', function() { 913 | this._dlgComments.hide(); 914 | prefs.setComments(this._commentsInput.value.split('\n###\n').map(function(it) { return it.trim(); })); 915 | }.bind(this)); 916 | $('#dlg-prefs-comments-cancel')._('click', function() { 917 | this._dlgComments.hide(); 918 | this.initValues(); 919 | }.bind(this)); 920 | 921 | // dlg: tags 922 | $('#dlg-prefs-tags-ok')._('click', function() { 923 | this._dlgTags.hide(); 924 | var tags = {}; 925 | this._tagsGood.value.split(/\s+/).map(function(it) { return it.trim(); }).forEach(function(it) { if (it.length == 0) return; tags[it] = true; }); 926 | this._tagsBad.value.split(/\s+/).map(function(it) { return it.trim(); }).forEach(function(it) { if (it.length == 0) return; tags[it] = false; }); 927 | prefs.setGoodTags(tags); 928 | 929 | tags = {}; 930 | this._tagsVGood.value.split(/\s+/).map(function(it) { return it.trim(); }).forEach(function(it) { if (it.length == 0) return; tags[it] = true; }); 931 | this._tagsVBad.value.split(/\s+/).map(function(it) { return it.trim(); }).forEach(function(it) { if (it.length == 0) return; tags[it] = false; }); 932 | prefs.setVgoodTags(tags); 933 | data.update(); 934 | gui.repaint(true); 935 | }.bind(this)); 936 | $('#dlg-prefs-tags-cancel')._('click', function() { 937 | this._dlgTags.hide(); 938 | this.initValues(); 939 | }.bind(this)); 940 | 941 | // dlg: keys 942 | $('#dlg-prefs-keys-ok')._('click', function() { 943 | this._dlgKeys.hide(); 944 | var keys = {}; 945 | this._tblKeys.$$('tr td:nth-child(1)').forEach(function(it) { 946 | keys[it.textContent] = it.getAttribute('data-key'); 947 | }); 948 | prefs.setKeys(keys); 949 | }.bind(this)); 950 | $('#dlg-prefs-keys-cancel')._('click', function() { 951 | this._dlgKeys.hide(); 952 | this.initValues(); 953 | }.bind(this)); 954 | 955 | this._timeOffset._('change', function() { 956 | prefs.setTimeOffset(this._timeOffset.value*1); 957 | this.initValues(); 958 | gui.repaint(true); 959 | }.bind(this)); 960 | 961 | this._torrentLimit._('change', function() { 962 | prefs.setTorrentLimit(this._torrentLimit.value*1); 963 | this.initValues(); 964 | }.bind(this)); 965 | 966 | this._latestTorrent._('change', function() { 967 | prefs.setLatest(this._latestTorrent.value*1); 968 | this.initValues(); 969 | }.bind(this)); 970 | 971 | // dlg: search string 972 | $('#dlg-prefs-search-string-ok')._('click', function() { 973 | this._dlgSearchString.hide(); 974 | prefs.setSearchString(this._searchString.value.trim()); 975 | }.bind(this)); 976 | $('#dlg-prefs-search-string-cancel')._('click', function() { 977 | this._dlgSearchString.hide(); 978 | this.initValues(); 979 | }.bind(this)); 980 | $('#dlg-prefs-search-string-help-close')._('click', function() { 981 | this._dlgSearchStringHelp.hide(); 982 | }.bind(this)); 983 | }, 984 | 985 | initValues: function() { 986 | this._newestFirst.checked = prefs.newestFirst; 987 | this._combine.checked = prefs.combine; 988 | this._combineHighest.checked = prefs.combineHighest; 989 | this._autoThanks.checked = prefs.autoThanks; 990 | this._autoComments.checked = prefs.autoComments; 991 | this._autoCommentsPrompt.checked = prefs.autoCommentsPrompt; 992 | this._commentsInput.value = prefs.comments.join('\n###\n'); 993 | this._thumbHeight.value = prefs.thumbHeight; 994 | md.input.blur(this._thumbHeight.parentNode); 995 | this._autoTags.checked = prefs.autoTags; 996 | this._tagLimit.value = prefs.tagLimit; 997 | md.input.blur(this._tagLimit.parentNode); 998 | this._timeOffset.value = prefs.timeOffset; 999 | md.input.blur(this._timeOffset.parentNode); 1000 | this._torrentLimit.value = prefs.torrentLimit; 1001 | md.input.blur(this._torrentLimit.parentNode); 1002 | this._latestTorrent.value = (prefs.latest || {empnFormat: function() {}}).empnFormat(); 1003 | md.input.blur(this._latestTorrent.parentNode); 1004 | this._useSearchString.checked = prefs.useSearchString; 1005 | this._searchString.value = prefs.searchString; 1006 | this._nfo.checked = prefs.nfo; 1007 | var g = []; 1008 | var b = []; 1009 | for(var tag in prefs.goodTags) { 1010 | if (!prefs.goodTags.hasOwnProperty(tag)) continue; 1011 | if (prefs.goodTags[tag]) g.push(tag); 1012 | else b.push(tag); 1013 | } 1014 | this._tagsGood.value = g.join(' '); 1015 | this._tagsBad.value = b.join(' '); 1016 | var vg = []; 1017 | var vb = []; 1018 | for(var tag in prefs.vgoodTags) { 1019 | if (!prefs.vgoodTags.hasOwnProperty(tag)) continue; 1020 | if (prefs.vgoodTags[tag]) vg.push(tag); 1021 | else vb.push(tag); 1022 | } 1023 | this._tagsVGood.value = vg.join(' '); 1024 | this._tagsVBad.value = vb.join(' '); 1025 | $('#dlg-prefs-tags-ratings tbody').removeChildren(); 1026 | var tagRows = []; 1027 | for (tag in prefs.tags) { 1028 | if (!prefs.tags.hasOwnProperty(tag)) continue; 1029 | var tr = document.createElement('tr'); 1030 | var td1 = document.createElement('td'); 1031 | td1.textContent = tag; 1032 | td1.style.backgroundColor = 'rgba(174, 213, 129, ' + (prefs.tags[tag] / prefs.tagLimit) + ')'; 1033 | tr.appendChild(td1); 1034 | var td2 = document.createElement('td'); 1035 | td2.textContent = prefs.tags[tag]; 1036 | tr.appendChild(td2); 1037 | tagRows.push(tr); 1038 | } 1039 | tagRows.sort(function(a,b) { return a.children[1].textContent*1 > b.children[1].textContent*1 ? -1 : 1; }); 1040 | tagRows.forEach(function(tr) { $('#dlg-prefs-tags-ratings tbody').appendChild(tr); }); 1041 | 1042 | this._tblKeys.removeChildren(); 1043 | for (var act in prefs.keys) { 1044 | if (!prefs.keys.hasOwnProperty(act)) continue; 1045 | (function(act) { 1046 | var tr = document.createElement('tr'); 1047 | var tdA = document.createElement('td'); 1048 | tdA.textContent = act; 1049 | tdA.setAttribute('data-key', prefs.keys[act]); 1050 | tr.appendChild(tdA); 1051 | var tdK = document.createElement('td'); 1052 | tdK.textContent = keyIdentifier(prefs.keys[act]); 1053 | tr.appendChild(tdK); 1054 | var listening = false; 1055 | addEventListener('keydown', function(evt) { 1056 | if (!listening) return; 1057 | evt.stopPropagation(); 1058 | evt.preventDefault(); 1059 | }); 1060 | addEventListener('keyup', function(evt) { 1061 | if (!listening) return; 1062 | listening = false; 1063 | evt.stopPropagation(); 1064 | evt.preventDefault(); 1065 | var key = { 1066 | ctrlKey: evt.ctrlKey, 1067 | shiftKey: evt.shiftKey, 1068 | keyIdentifier: evt.keyIdentifier 1069 | }; 1070 | tdA.setAttribute('data-key', JSON.stringify(key)); 1071 | tdK.textContent = keyIdentifier(evt); 1072 | tdK.delClass('empn-active'); 1073 | }); 1074 | tdK._('click', function() { 1075 | listening = true; 1076 | tdK.addClass('empn-active'); 1077 | }); 1078 | this._tblKeys.appendChild(tr); 1079 | }.bind(this))(act); 1080 | } 1081 | } 1082 | }, 1083 | 1084 | init: function() { 1085 | this.tplItem = document.createElement('div'); 1086 | this.tplItem.addClass('empn-item'); 1087 | this.tplItem.innerHTML = '
Date
Category
Size
Snatches
Comments
Uploaded By
'; 1088 | 1089 | document.body.innerHTML = ''; 1090 | document.title = 'EMPN :: Empornium'; 1091 | var container = document.createElement('div'); 1092 | container.innerHTML = '
Preferences
Edit Auto Comments

Separate comments with a line containing only ###

Edit Search String Help
Search String - Help
Input:
this i like
and this too
Output:
\"this i like\"|\"and this too\"
Edit Tags
TagRating
Key Bindings
ActionKey
Please leave a comment
Select Quality
Enter a Comment
 
 
'; 1093 | document.body.appendChild(container); 1094 | 1095 | var bbcode = document.createElement('script'); 1096 | bbcode.src = 'static/functions/bbcode.js?v='; 1097 | document.body.parentNode.children[0].appendChild(bbcode); 1098 | 1099 | this._items = $('#items'); 1100 | this._dlgImg = $('#dlg-img'); 1101 | this._img = this._dlgImg.$('.empn-img'); 1102 | this._dlgDesc = $('#dlg-description'); 1103 | this._dlgComm = $('#dlg-comments'); 1104 | this._dlgQuality = $('#dlg-quality'); 1105 | this._dlgComment = $('#dlg-comment'); 1106 | this._comment = $('#dlg-comment-input'); 1107 | this._prefs = $('#preferences'); 1108 | this._toast = $('.empn-toasts'); 1109 | 1110 | md.dialog.init($$('.empn-dialog')); 1111 | md.input.init($$('.empn-input')); 1112 | md.ripple.init($$('button, .empn-item-link')); 1113 | md.menu.init($$('.empn-menu')); 1114 | md.toasts.init($$('.empn-toasts')); 1115 | // md.tabbar.init($$('.empn-tabbar')); 1116 | 1117 | this.prefs.init(); 1118 | 1119 | this._dlgImg._('click', actions.hideImage); 1120 | this._img._('click', this.toggleImgSize.bind(this)); 1121 | 1122 | this._dlgDesc._('click', actions.hideDescription); 1123 | this._dlgDesc.$('.empn-content')._('click', stopProp); 1124 | 1125 | this._dlgComm._('click', actions.hideComments); 1126 | this._dlgComm.$('.empn-content')._('click', stopProp); 1127 | 1128 | this._dlgQuality._('click', this._dlgQuality.hide); 1129 | this._dlgQuality.$('.empn-content')._('click', stopProp); 1130 | 1131 | this._dlgComment._('click', this._dlgComment.hide); 1132 | this._dlgComment.$('.empn-content')._('click', stopProp); 1133 | $('#dlg-comment-ok')._('click', function() { 1134 | actions.sendComment(this._dlgComment.item, this._comment.value); 1135 | this._dlgComment.hide(); 1136 | state.listening = true; 1137 | }.bind(this)); 1138 | $('#dlg-comment-cancel')._('click', function() { 1139 | this._dlgComment.hide(); 1140 | state.listening = true; 1141 | }.bind(this)); 1142 | 1143 | $('#menu-link')._('click', $('#preferences').show); 1144 | $('#menu-link')._('click', function() { state.listening = false; }); 1145 | this._prefs._('click', function() { state.listening = true; }); 1146 | 1147 | addEventListener('resize', this.resizeListener.bind(this)); 1148 | this.resizeListener(); 1149 | 1150 | this._items._('scroll', this.scrollListener.bind(this)); 1151 | this._items.focus(); 1152 | 1153 | this.calcItemHeight(); 1154 | }, 1155 | 1156 | initItems: function() { console.info('init items'); 1157 | this._items.removeChildren(); 1158 | for (var i=0;i bottom) && (this.vis[i] || forced)) { 1290 | this.hide(i); 1291 | } else if (i*this.height > top && i*this.height < bottom && (!this.vis[i] || forced)) { 1292 | this.show(i); 1293 | } 1294 | } 1295 | }, 1296 | 1297 | scrollListener: function() { 1298 | this.repaint(); 1299 | }, 1300 | 1301 | resizeListener: function() { 1302 | var img = $('#dlg-img .empn-img'); 1303 | img.style.maxWidth = innerWidth - 48 + 'px'; 1304 | if (this.fullsized) { 1305 | img.style.maxHeight = ''; 1306 | } else { 1307 | img.style.maxHeight = innerHeight - 48 + 'px'; 1308 | } 1309 | 1310 | this.repaint(); 1311 | 1312 | this.prefs._dlgTags.$('.empn-dlg-prefs-tags-table-container').style.maxHeight = innerHeight - 17 - 59 - 301 /*this.prefs._dlgTags.$('.empn-dlg-prefs-tags-table-container').offsetTop*/ + 'px'; 1313 | this._prefs.style.display = 'block'; 1314 | this._prefs.$('.empn-items').style.top = this._prefs.$('.empn-title').getBoundingClientRect().bottom + 'px'; 1315 | this._prefs.$('.empn-content').style.width = this._prefs.$('.empn-items').getBoundingClientRect().width + 'px'; 1316 | this._prefs.style.display = ''; 1317 | }, 1318 | 1319 | tagSort: function(a,b) { 1320 | if ((prefs.vgoodTags[a] && prefs.vgoodTags[b]) || (prefs.vgoodTags[a] === false && prefs.vgoodTags[b] === false)) { 1321 | return a.toLowerCase() > b.toLowerCase() ? 1 : a.toLowerCase() < b.toLowerCase() ? -1 : 0; 1322 | } 1323 | if (prefs.vgoodTags[a]) { 1324 | return -1; 1325 | } 1326 | if (prefs.vgoodTags[b]) { 1327 | return 1; 1328 | } 1329 | if (prefs.vgoodTags[a] === false) { 1330 | return -1; 1331 | } 1332 | if (prefs.vgoodTags[b] === false) { 1333 | return 1; 1334 | } 1335 | if ((prefs.goodTags[a] && prefs.goodTags[b]) || (prefs.goodTags[a] === false && prefs.goodTags[b] === false)) { 1336 | return a.toLowerCase() > b.toLowerCase() ? 1 : a.toLowerCase() < b.toLowerCase() ? -1 : 0; 1337 | } 1338 | if (prefs.goodTags[a]) { 1339 | return -1; 1340 | } 1341 | if (prefs.goodTags[b]) { 1342 | return 1; 1343 | } 1344 | if (prefs.goodTags[a] === false) { 1345 | return -1; 1346 | } 1347 | if (prefs.goodTags[b] === false) { 1348 | return 1; 1349 | } 1350 | if (prefs.tags[a] >= prefs.tagLimit / 10 && prefs.tags[b] >= prefs.tagLimit / 10) { 1351 | if (prefs.tags[a] > prefs.tags[b]) return -1; 1352 | if (prefs.tags[a] < prefs.tags[b]) return 1; 1353 | return a.toLowerCase() > b.toLowerCase() ? 1 : a.toLowerCase() < b.toLowerCase() ? -1 : 0; 1354 | } 1355 | if (prefs.tags[a] >= prefs.tagLimit / 10) { 1356 | return -1; 1357 | } 1358 | if (prefs.tags[b] >= prefs.tagLimit / 10) { 1359 | return 1; 1360 | } 1361 | return a.toLowerCase() > b.toLowerCase() ? 1 : a.toLowerCase() < b.toLowerCase() ? -1 : 0; 1362 | } 1363 | }; 1364 | var data = { 1365 | listParams: { 1366 | page: 1, 1367 | toString: function() { 1368 | var params = []; 1369 | for (var key in this) { 1370 | if (!this.hasOwnProperty(key) || typeof this[key] == 'function') continue; 1371 | params.push(key + '=' + this[key]); 1372 | } 1373 | return params.join('&'); 1374 | } 1375 | }, 1376 | 1377 | _items: [], 1378 | items: [], 1379 | 1380 | update: function() { 1381 | var items = this._items.map(function(it) { 1382 | var item = {}; 1383 | for (var key in it) { 1384 | if (!it.hasOwnProperty(key)) continue; 1385 | item[key] = it[key]; 1386 | } 1387 | return item; 1388 | }); 1389 | 1390 | // combine torrents with same name 1391 | if (prefs.combine) { 1392 | var _items = []; 1393 | var titles = []; 1394 | items.forEach(function(item, i) { 1395 | var title = item.title.replace(/(^|[^a-z0-9])\[?(\d+[pi]|\d+x\d+|\[\d+\])\]?([^a-z0-9]|$)/i, "$1[_EMPN_RESOLUTION_]$3") 1396 | .replace(/(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$)/i, "$1_EMPN_BITRATE_$4") 1397 | .replace(/(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$)/i, "$1_EMPN_TYPE_$3"); 1398 | if (title == item.title) { 1399 | item.quality = null; 1400 | item.qualityValue = null; 1401 | item.qualities = []; 1402 | return; 1403 | } 1404 | item.quality = []; 1405 | var resolution = item.title.replace(/^.*?(^|[^a-z0-9])((\d+[pi])|(\d+x\d+)|\[(\d+)\])([^a-z0-9]|$).*$/i, "$3$4$5"); 1406 | var bitrate = item.title.replace(/^.*?(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$).*$/i, "$2"); 1407 | var type = item.title.replace(/^.*?(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$).*$/i, "$2"); 1408 | if (resolution != item.title) item.quality.push(resolution); 1409 | if (bitrate != item.title) item.quality.push(bitrate); 1410 | if (type != item.title) item.quality.push(type); 1411 | var resValue = item.title.replace(/^.*?(^|[^a-z0-9])((\d+)[pi]|\d+x(\d+)|\[(\d+)\])([^a-z0-9]|$).*$/i, "$3$4$5")*1; 1412 | var bitValue = item.title.replace(/^.*?(^|[^a-z0-9])((\d+(\.\d+)?)mb?ps)([^a-z0-9]|$).*$/i, "$3")*1; 1413 | item.qualityValue = (resValue||1)*(bitValue||1); 1414 | item.qualities = items.filter(function(itm) { 1415 | return itm.title.replace(/(^|[^a-z0-9])\[?(\d+[pi]|\d+x\d+|\[\d+\])\]?([^a-z0-9]|$)/i, "$1[_EMPN_RESOLUTION_]$3") 1416 | .replace(/(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$)/i, "$1_EMPN_BITRATE_$4") 1417 | .replace(/(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$)/i, "$1_EMPN_TYPE_$3") == title; 1418 | }); 1419 | }); 1420 | items.forEach(function(item, i) { 1421 | if (item.qualities.length > 1) { 1422 | var title = item.title.replace(/(^|[^a-z0-9])\[?(\d+[pi]|\d+x\d+|\[\d+\])\]?([^a-z0-9]|$)/i, "$1[_EMPN_RESOLUTION_]$3") 1423 | .replace(/(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$)/i, "$1_EMPN_BITRATE_$4") 1424 | .replace(/(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$)/i, "$1_EMPN_TYPE_$3"); 1425 | if (titles.lastIndexOf(title) != -1) { 1426 | return; 1427 | } 1428 | var _item = {}; 1429 | _item.qualities = item.qualities; 1430 | _item.qualities.sort(function(a,b) { return a.qualityValue > b.qualityValue ? -1 : 1; }); 1431 | _item.category = item.category; 1432 | // _item.comments = item.qualities.spread('comments').join(', '); 1433 | _item.comments = item.qualities[0].comments; 1434 | _item.description = item.qualities[0].description; 1435 | _item.date = item.date; 1436 | _item.id = item.id; 1437 | _item.idx = item.idx; 1438 | _item.quality = null; 1439 | _item.qualityValue = null; 1440 | _item.size = item.qualities.spread('size').join(', '); 1441 | _item.snatches = item.qualities.spread('snatches').join(', '); 1442 | _item.uploader = item.uploader; 1443 | _item.tags = []; 1444 | item.qualities.spread('tags').forEach(function(tags) { 1445 | _item.tags = _item.tags.concat(tags.filter(function(tag) { return _item.tags.lastIndexOf(tag) == -1; })); 1446 | }); 1447 | _item.thumbs = []; 1448 | item.qualities.spread('thumbs').forEach(function(thumbs) { 1449 | _item.thumbs = _item.thumbs.concat(thumbs.filter(function(thumb) { return _item.thumbs.lastIndexOf(thumb) == -1; })); 1450 | }); 1451 | _item.title = item.title.replace(/\[?(^|[^a-z0-9])(\d+[pi]|\d+x\d+|\[\d+\])([^a-z0-9]|$)\]?/i, "") 1452 | .replace(/\[?(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$)\]?/i, "") 1453 | .replace(/\[?(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$)\]?/i, "") + ' [' + item.qualities.spread('quality').map(function(it) { return it.join('-'); }).join(', ') + ']'; 1454 | _items.push(_item); 1455 | titles.push(title); 1456 | } else { 1457 | _items.push(item); 1458 | titles.push(title); 1459 | } 1460 | }); 1461 | items = _items; 1462 | } 1463 | 1464 | // filter out horrible tags 1465 | items = items.filter(function(item) { 1466 | var vbad = item.tags.filter(function(tag) { return prefs.vgoodTags[tag] === false; }).length > 0; 1467 | var vgood = item.tags.filter(function(tag) { return prefs.vgoodTags[tag] === true; }).length > 0; 1468 | 1469 | return !vbad || vgood; 1470 | }); 1471 | 1472 | // sort items 1473 | if (!prefs.newestFirst) 1474 | items.reverse(); 1475 | 1476 | // remove blacklisted thumbs 1477 | items.forEach(function(item) { 1478 | item.thumbs = item.thumbs.filter(function(thumb) { 1479 | var src = JSON.parse(thumb).src; 1480 | return prefs.blacklist.lastIndexOf(src) == -1; 1481 | }); 1482 | }); 1483 | 1484 | // parse thumbs (JSON) 1485 | items.forEach(function(item) { 1486 | item.thumbs = item.thumbs.map(function(thumb) { 1487 | return JSON.parse(thumb); 1488 | }); 1489 | }); 1490 | 1491 | 1492 | var change = true; 1493 | if (items.map(function(it) { return it.id; }).join(';') == this.items.map(function(it) { return it.id; }).join(';')) { 1494 | change = false; 1495 | } 1496 | 1497 | this.items = items; 1498 | 1499 | if (change) { 1500 | gui.initItems(); 1501 | } 1502 | }, 1503 | 1504 | load: function() { 1505 | if (prefs.useSearchString && prefs.searchString) { 1506 | this.listParams.action = 'advanced'; 1507 | this.listParams.searchtext = encodeURIComponent('"'+prefs.searchString.replace(/\r?\n/g, '"|"')+'"'); 1508 | } 1509 | this.loadPage().then(function(page) { 1510 | this.parsePage(page).then(function(next) { 1511 | if (next) { 1512 | this.listParams.page++; 1513 | this.load(); 1514 | } else { 1515 | this.update(); 1516 | gui.hideLoading(); 1517 | state.listening = true; 1518 | } 1519 | }.bind(this)); 1520 | }.bind(this)); 1521 | }, 1522 | 1523 | loadPage: function() { 1524 | return getHTML('torrents.php?' + this.listParams); 1525 | }, 1526 | parsePage: function(page) { 1527 | var _href = page.$('[data-href*="authkey"][data-href*="torrent_pass"]').getAttribute('data-href'); 1528 | var auth = _href.replace(/^.*authkey=([^&]+)(&|$).*$/, '$1'); 1529 | var pass = _href.replace(/^.*torrent_pass=([^&]+)(&|$).*$/, '$1'); 1530 | return new Promise(function(resolve, reject) { 1531 | var done = 0; 1532 | var doneOffset = this._items.length; 1533 | var doneSkip = 0; 1534 | var minDate = new Date().getTime(); 1535 | var rows = page.$$('#torrent_table .torrent'); 1536 | rows.forEach(function(row) { 1537 | var item = {}; 1538 | item.id = row.$('td:nth-child(2) > a').getAttribute('data-href').replace(/^.*(\?|&)id=(\d+)(&|$).*/, '$2'); 1539 | item.auth = auth; 1540 | item.pass = pass; 1541 | item.category = row.$('.cats_col img').getAttribute('data-src').replace(/^.+cat_([^\.]+)\.png/, '$1'); 1542 | item.urlDetails = row.$('td:nth-child(2) > a').getAttribute('data-href'); 1543 | // item.url = 'torrents.php?action=download&id='+item.id+'&authkey='+auth+'&torrent_pass='+item.pass; 1544 | const dlLink = row.$('a[data-href*="/torrents.php?action=download"]'); 1545 | if (dlLink) { 1546 | item.url = dlLink.getAttribute('data-href'); 1547 | } 1548 | item.title = row.$('td:nth-child(2) > a').textContent; 1549 | // item.comments = row.$('td:nth-child(4)').textContent*1; 1550 | item.comments = []; 1551 | item.size = row.$('td:nth-child(6)').textContent; 1552 | item.snatches = row.$('td:nth-child(7)').textContent*1; 1553 | item.date = new Date(Date.parse(row.$('td:nth-child(5) span').title)); 1554 | item.uploader = row.$('td.user > a, td.user > span'); 1555 | item.uploader.href = item.uploader.getAttribute('data-href'); 1556 | item.thumbs = []; 1557 | item.thumbLinks = []; 1558 | item.tags = row.$$('td:nth-child(2) > .tags > a').map(function(it) { return it.textContent; }); 1559 | if (item.date < new Date(prefs.latest)) { 1560 | doneSkip++; 1561 | console.info(done, doneSkip, rows.length, item.date, new Date(prefs.latest)); 1562 | if (done + doneSkip == rows.length) { 1563 | resolve(item.date > new Date(prefs.latest) && this._items.length < prefs.torrentLimit); 1564 | } 1565 | return; 1566 | } 1567 | this._items.push(item); 1568 | gui.updateLoading((this._items.length) + ' Torrents found'); 1569 | getHTML(item.urlDetails).then(function(html) { 1570 | var desc = html.$(`#content${item.id}`); 1571 | // var dlId = (html.$('.torrent_buttons > [title="Download"]') || html.$('.torrent_buttons > a')).href.replace(/^.+id=(\d+).*$/, '$1'); 1572 | // item.url = 'torrents.php?action=download&id='+dlId+'&authkey='+auth+'&torrent_pass='+item.pass; 1573 | // item.url = (html.$('.torrent_buttons > [title="Download"]') || html.$('.torrent_buttons > a')).href; 1574 | item.comments = html.$$('.forum_post.box.vertical_margin:not(#quickreplypreview)'); 1575 | item.description = desc.innerHTML.replace(/ data-(src|href)=/g, ' $1='); 1576 | desc.$$('img').forEach(function(it) { 1577 | var thumb = {}; 1578 | let src = it.getAttribute('data-src').replace(/\.th\.jpg$/, '.jpg'); 1579 | thumb.src = src; 1580 | if (it.parentNode.tagName == 'A') { 1581 | thumb.link = it.parentNode.getAttribute('data-href'); 1582 | } else { 1583 | thumb.link = src; 1584 | } 1585 | item.thumbs.push(JSON.stringify(thumb)); 1586 | }); 1587 | gui.updateLoadingSub(done+1+doneOffset + ' Torrents loaded'); 1588 | minDate = Math.min(minDate, item.date); 1589 | if (++done + doneSkip == rows.length) { 1590 | resolve(item.date > new Date(prefs.latest) && this._items.length < prefs.torrentLimit); 1591 | } 1592 | item.nfo = '\n\n\t'+item.title+'\n\t'+(desc.textContent.trim())+''; 1593 | if (item.tags.length > 0) { 1594 | item.nfo += '\n\t'+item.tags.join('\n\t')+''; 1595 | } 1596 | item.nfo += '\n'; 1597 | }.bind(this), 1598 | function(err) { 1599 | console.info(err); 1600 | gui.updateLoadingSub(done+1+doneOffset + ' Torrents loaded'); 1601 | minDate = Math.min(minDate, item.date); 1602 | if (++done + doneSkip == rows.length) { 1603 | resolve(item.date > new Date(prefs.latest) && this._items.length < prefs.torrentLimit); 1604 | } 1605 | }); 1606 | }.bind(this)); 1607 | }.bind(this)); 1608 | }, 1609 | }; 1610 | var actions = { 1611 | activateItem: function(idx) { 1612 | if (idx == state.torrentIndex) return; 1613 | if (state.torrentIndex != undefined) 1614 | $('#item-' + state.torrentIndex).delClass('empn-active'); 1615 | var oldIdx = state.torrentIndex; 1616 | state.torrentIndex = idx; 1617 | this.activateImage(0, oldIdx); 1618 | var el = $('#item-' + state.torrentIndex); 1619 | gui._items.scrollToV(el.offsetTop - (gui._items.offsetHeight - gui.height) / 2); 1620 | el.addClass('empn-active'); 1621 | if (gui._dlgComm.hasClass('empn-active')) { 1622 | this.showComments(); 1623 | } 1624 | if (gui._dlgDesc.hasClass('empn-active')) { 1625 | this.showDescription(); 1626 | } 1627 | if (gui._dlgQuality.hasClass('empn-active')) { 1628 | if (data.items[state.torrentIndex].qualities.length > 1) { 1629 | this.download(true); 1630 | } else { 1631 | gui._dlgQuality.hide(); 1632 | } 1633 | } 1634 | }, 1635 | 1636 | activateImage: function(idx, oldTorrentIndex) { 1637 | if (oldTorrentIndex != undefined || idx != state.imgIndex) { 1638 | var iel = $('#item-' + (oldTorrentIndex!=undefined? oldTorrentIndex : state.torrentIndex) + ' .empn-img-' + state.imgIndex); 1639 | if (iel) iel.delClass('empn-active'); 1640 | } 1641 | state.imgIndex = idx; 1642 | var el = $('#item-' + state.torrentIndex + ' .empn-img-' + state.imgIndex); 1643 | if (el) el.addClass('empn-active'); 1644 | var thumbsEl = $('#item-' + state.torrentIndex + ' .empn-thumbs'); 1645 | if (el) thumbsEl.scrollToH(el.offsetLeft + el.offsetWidth - thumbsEl.offsetWidth); 1646 | if (gui._dlgImg.hasClass('empn-active')) { 1647 | this.showImage(); 1648 | } 1649 | }, 1650 | 1651 | showHideImage: function() { 1652 | if (gui._dlgImg.hasClass('empn-active')) { 1653 | this.hideImage(); 1654 | } else { 1655 | this.showImage(); 1656 | } 1657 | }, 1658 | showImage: function() { 1659 | gui._dlgComm.hide(); 1660 | gui._dlgDesc.hide(); 1661 | gui._dlgQuality.hide(); 1662 | $('#item-' + state.torrentIndex + ' .empn-img-' + state.imgIndex).click(); 1663 | }, 1664 | hideImage: function() { 1665 | gui.fullsized = true; 1666 | gui.toggleImgSize(); 1667 | gui._dlgImg.hide(); 1668 | }, 1669 | 1670 | toggleZoom: function() { 1671 | gui.toggleImgSize(); 1672 | }, 1673 | 1674 | openImage: function() { 1675 | window.open(data.items[state.torrentIndex].thumbs[state.imgIndex].link); 1676 | }, 1677 | 1678 | nextItem: function() { 1679 | if (data.items.length <= state.torrentIndex+1) return; 1680 | this.activateItem(state.torrentIndex+1); 1681 | }, 1682 | prevItem: function() { 1683 | if (state.torrentIndex-1 < 0) return; 1684 | this.activateItem(state.torrentIndex-1); 1685 | }, 1686 | 1687 | nextImage: function() { 1688 | if (data.items[state.torrentIndex].thumbs.length <= state.imgIndex+1) return; 1689 | this.activateImage(state.imgIndex+1); 1690 | }, 1691 | prevImage: function() { 1692 | if (state.imgIndex-1 < 0) return; 1693 | this.activateImage(state.imgIndex-1); 1694 | }, 1695 | 1696 | toggleComments: function() { 1697 | if (gui._dlgComm.hasClass('empn-active')) { 1698 | this.hideComments(); 1699 | } else { 1700 | this.showComments(); 1701 | } 1702 | }, 1703 | showComments: function() { 1704 | this.hideImage(); 1705 | this.hideDescription(); 1706 | gui._dlgQuality.hide(); 1707 | gui._dlgComm.$('.empn-title').textContent = data.items[state.torrentIndex].title; 1708 | // gui._dlgComm.$('.empn-comments').innerHTML = data.items[state.torrentIndex].comments; 1709 | gui._dlgComm.$('.empn-comments').removeChildren(); 1710 | data.items[state.torrentIndex].comments.forEach(function(it) { 1711 | gui._dlgComm.$('.empn-comments').appendChild(it); 1712 | }); 1713 | gui._dlgComm.$('.empn-comments').innerHTML = gui._dlgComm.$('.empn-comments').innerHTML.replace(/ data-(src|href)=/g, ' $1='); 1714 | gui._dlgComm.show($('#item-'+state.torrentIndex)); 1715 | }, 1716 | hideComments: function() { 1717 | gui._dlgComm.hide(); 1718 | }, 1719 | 1720 | toggleDescription: function() { 1721 | if (gui._dlgDesc.hasClass('empn-active')) { 1722 | this.hideDescription(); 1723 | } else { 1724 | this.showDescription(); 1725 | } 1726 | }, 1727 | showDescription: function() { 1728 | this.hideImage(); 1729 | this.hideComments(); 1730 | gui._dlgQuality.hide(); 1731 | gui._dlgDesc.$('.empn-title').textContent = data.items[state.torrentIndex].title; 1732 | gui._dlgDesc.$('.empn-description').innerHTML = data.items[state.torrentIndex].description; 1733 | gui._dlgDesc.show($('#item-'+state.torrentIndex)); 1734 | }, 1735 | hideDescription: function() { 1736 | gui._dlgDesc.hide(); 1737 | }, 1738 | 1739 | download: function(forced) { 1740 | var itm = data.items[state.torrentIndex]; 1741 | if (prefs.combine && !prefs.combineHighest && itm.qualities.length > 1) { 1742 | if (gui._dlgQuality.hasClass('empn-active') && !forced) { 1743 | gui._dlgQuality.hide(); 1744 | return; 1745 | } 1746 | gui._dlgImg.hide(); 1747 | gui._dlgComm.hide(); 1748 | gui._dlgDesc.hide(); 1749 | gui._dlgQuality.$('.empn-actions').removeChildren(); 1750 | itm.qualities.forEach(function(it, i) { 1751 | var btn = document.createElement('button'); 1752 | btn.innerHTML = it.quality + ' (' + it.size + ')'; 1753 | gui._dlgQuality.$('.empn-actions').appendChild(btn); 1754 | md.ripple.init(btn); 1755 | btn._('click', function() { 1756 | this.doDownload(it); 1757 | gui._dlgQuality.hide(); 1758 | }.bind(this)); 1759 | }.bind(this)); 1760 | gui._dlgQuality.show($('#item-' + state.torrentIndex)); 1761 | } else if (prefs.combine && prefs.combineHighest && itm.qualities.length > 0) { 1762 | this.doDownload(itm.qualities[0]); 1763 | } else { 1764 | this.doDownload(itm); 1765 | } 1766 | }, 1767 | doDownload: function(itm) { 1768 | if (prefs.autoThanks) { 1769 | this.sendThanks(itm); 1770 | } 1771 | if (prefs.autoComments) { 1772 | if (prefs.autoCommentsPrompt) { 1773 | this.promptComment(itm); 1774 | } else { 1775 | this.sendRandomComment(itm); 1776 | } 1777 | } 1778 | if (prefs.autoTags) { 1779 | itm.tags.forEach(function(it) { 1780 | prefs.raiseTag(it); 1781 | }); 1782 | gui.prefs.initValues(); 1783 | } 1784 | getResponse(itm.url, {responseType:'blob'}).then(function(data) { 1785 | // var blob = new Blob(data, {type: "x-application/torrent"}); 1786 | var url = window.URL.createObjectURL(data); 1787 | var link = document.createElement('a'); 1788 | link.href = url; 1789 | link.download = '[Empornium]' + itm.title.replace(/[^a-z0-9\-_., ()[\]]+/ig, '_') + '.torrent'; 1790 | link.click(); 1791 | window.URL.revokeObjectURL(url); 1792 | }); 1793 | // var ifr = document.createElement('iframe'); 1794 | //TODO: iframe is not removed. onload event does not trigger with attachments. 1795 | // ifr.addEventListener('load', function() { console.info('load!'); ifr.remove(); delete ifr; }); 1796 | // ifr.src = itm.url; 1797 | // ifr.style.display = 'none'; 1798 | // document.body.appendChild(ifr); 1799 | if (prefs.nfo) { 1800 | var nfo = new Blob([itm.nfo], { 1801 | type: 'text/xml;charset=utf-8' 1802 | }); 1803 | var nfoUrl = window.URL.createObjectURL(nfo); 1804 | var nfoLink = document.createElement('a'); 1805 | nfoLink.href = nfoUrl; 1806 | nfoLink.download = itm.title + '.nfo'; 1807 | nfoLink.click(); 1808 | window.URL.revokeObjectURL(nfoUrl); 1809 | } 1810 | }, 1811 | 1812 | sendThanks: function(itm) { 1813 | itm = itm || data.items[state.torrentIndex]; 1814 | post('torrents.php?action=thank', {groupid: itm.id, action: 'thank', auth: itm.auth}).then(function() { 1815 | gui._toast.add('Thanks for the Thanks!', itm.title); 1816 | }); 1817 | }, 1818 | sendRandomComment: function(itm) { 1819 | itm = itm || data.items[state.torrentIndex]; 1820 | if (prefs.hasComments()) { 1821 | this.sendComment(itm, prefs.getRandomComment()); 1822 | } else { 1823 | this.prompComment(itm); 1824 | } 1825 | }, 1826 | sendComment: function(itm, comment) { 1827 | post('torrents.php?id=' + itm.id, {action: 'reply', auth: itm.auth, groupid: itm.id, body: comment}).then(function() { 1828 | gui._toast.add('Thanks for the Comment!', itm.title); 1829 | }); 1830 | }, 1831 | promptComment: function(itm) { 1832 | itm = itm || data.items[state.torrentIndex]; 1833 | state.listening = false; 1834 | gui._comment.value = ''; 1835 | gui._dlgComment.item = itm; 1836 | gui._dlgComment.show(); 1837 | gui._comment.focus(); 1838 | }, 1839 | 1840 | openDetails: function() { 1841 | var itm = data.items[state.torrentIndex]; 1842 | if (prefs.combine && !prefs.combineHighest && itm.qualities.length > 1) { 1843 | alert('Quality selection is not implemented!'); 1844 | } else if (prefs.combine && prefs.combineHighest && itm.qualities.length > 0) { 1845 | window.open(itm.qualities[0].urlDetails); 1846 | } else { 1847 | window.open(itm.urlDetails); 1848 | } 1849 | }, 1850 | 1851 | blockImage: function() { 1852 | prefs.blockImage(data.items[state.torrentIndex].thumbs[state.imgIndex].src); 1853 | gui.repaint(true); 1854 | }, 1855 | 1856 | catchUp: function(curr) { 1857 | var itm; 1858 | if (curr === true) itm = data.items[state.torrentIndex]; 1859 | else itm = data._items[0]; 1860 | prefs.setLatest(itm.date); 1861 | gui._toast.add('Catching Up!', ''); 1862 | } 1863 | } 1864 | var state = { 1865 | torrentIndex: 0, 1866 | imgIndex: 0, 1867 | listening: false 1868 | }; 1869 | var keyboard = { 1870 | init: function() { 1871 | addEventListener('keydown', this.reactDown); 1872 | addEventListener('keyup', this.react); 1873 | }, 1874 | 1875 | reactDown: function(evt) { 1876 | if (!state.listening) return; 1877 | 1878 | var keyMap = {}; 1879 | for (var act in prefs.keys) { 1880 | if (!prefs.keys.hasOwnProperty(act)) continue; 1881 | keyMap[keyIdentifier(prefs.keys[act])] = act; 1882 | } 1883 | 1884 | if (keyMap[keyIdentifier(evt)]) { 1885 | evt.preventDefault(); 1886 | } 1887 | }, 1888 | react: function(evt) { 1889 | if (!state.listening) return; 1890 | 1891 | var keyMap = {}; 1892 | for (var act in prefs.keys) { 1893 | if (!prefs.keys.hasOwnProperty(act)) continue; 1894 | keyMap[keyIdentifier(prefs.keys[act])] = act; 1895 | } 1896 | 1897 | if (keyMap[keyIdentifier(evt)]) { 1898 | evt.preventDefault(); 1899 | } 1900 | 1901 | console.info(keyIdentifier(evt), keyMap); 1902 | 1903 | switch(keyMap[keyIdentifier(evt)]) { 1904 | case 'Next Torrent': 1905 | actions.nextItem(); 1906 | break; 1907 | case 'Previous Torrent': 1908 | actions.prevItem(); 1909 | break; 1910 | case 'Next Image': 1911 | actions.nextImage(); 1912 | break; 1913 | case 'Previous Image': 1914 | actions.prevImage(); 1915 | break; 1916 | case 'Show / Hide Image': 1917 | actions.showHideImage(); 1918 | break; 1919 | case 'Toggle Zoom': 1920 | actions.toggleZoom(); 1921 | break; 1922 | case 'Open Image in a New Tab': 1923 | actions.openImage(); 1924 | break; 1925 | case 'Show / Hide Comments': 1926 | actions.toggleComments(); 1927 | break; 1928 | case 'Show / Hide Description': 1929 | actions.toggleDescription(); 1930 | break; 1931 | case 'Download': 1932 | actions.download(); 1933 | break; 1934 | case 'Open Details in a New Tab': 1935 | actions.openDetails(); 1936 | break; 1937 | case 'Block Image': 1938 | actions.blockImage(); 1939 | break; 1940 | case 'Send Thanks': 1941 | actions.sendThanks(); 1942 | break; 1943 | case 'Add Comment': 1944 | actions.sendRandomComment(); 1945 | break; 1946 | case 'Add Manual Comment': 1947 | actions.promptComment(); 1948 | break; 1949 | case 'Catch Up': 1950 | actions.catchUp(); 1951 | break; 1952 | case 'Catch Up to Current Torrent': 1953 | actions.catchUp(true); 1954 | break; 1955 | }; 1956 | } 1957 | }; 1958 | 1959 | 1960 | 1961 | 1962 | 1963 | 1964 | /****************************************\ 1965 | | $EMPN 1966 | \****************************************/ 1967 | function init() { 1968 | if (location.href.search(/empn.php$/) == -1) { 1969 | var orig = $('#nav_torrents'); 1970 | var node = orig.cloneNode(true); 1971 | node.id = 'nav_empn'; 1972 | var a = node.$('a'); 1973 | a.href = 'empn.php'; 1974 | a.textContent = 'EMPN'; 1975 | orig.parentNode.insertBefore(node, orig); 1976 | } else { 1977 | prefs.load(); 1978 | gui.init(); 1979 | keyboard.init(); 1980 | data.load(); 1981 | } 1982 | } 1983 | init(); -------------------------------------------------------------------------------- /src/actions.js: -------------------------------------------------------------------------------- 1 | var actions = { 2 | activateItem: function(idx) { 3 | if (idx == state.torrentIndex) return; 4 | if (state.torrentIndex != undefined) 5 | $('#item-' + state.torrentIndex).delClass('empn-active'); 6 | var oldIdx = state.torrentIndex; 7 | state.torrentIndex = idx; 8 | this.activateImage(0, oldIdx); 9 | var el = $('#item-' + state.torrentIndex); 10 | gui._items.scrollToV(el.offsetTop - (gui._items.offsetHeight - gui.height) / 2); 11 | el.addClass('empn-active'); 12 | if (gui._dlgComm.hasClass('empn-active')) { 13 | this.showComments(); 14 | } 15 | if (gui._dlgDesc.hasClass('empn-active')) { 16 | this.showDescription(); 17 | } 18 | if (gui._dlgQuality.hasClass('empn-active')) { 19 | if (data.items[state.torrentIndex].qualities.length > 1) { 20 | this.download(true); 21 | } else { 22 | gui._dlgQuality.hide(); 23 | } 24 | } 25 | }, 26 | 27 | activateImage: function(idx, oldTorrentIndex) { 28 | if (oldTorrentIndex != undefined || idx != state.imgIndex) { 29 | var iel = $('#item-' + (oldTorrentIndex!=undefined? oldTorrentIndex : state.torrentIndex) + ' .empn-img-' + state.imgIndex); 30 | if (iel) iel.delClass('empn-active'); 31 | } 32 | state.imgIndex = idx; 33 | var el = $('#item-' + state.torrentIndex + ' .empn-img-' + state.imgIndex); 34 | if (el) el.addClass('empn-active'); 35 | var thumbsEl = $('#item-' + state.torrentIndex + ' .empn-thumbs'); 36 | if (el) thumbsEl.scrollToH(el.offsetLeft + el.offsetWidth - thumbsEl.offsetWidth); 37 | if (gui._dlgImg.hasClass('empn-active')) { 38 | this.showImage(); 39 | } 40 | }, 41 | 42 | showHideImage: function() { 43 | if (gui._dlgImg.hasClass('empn-active')) { 44 | this.hideImage(); 45 | } else { 46 | this.showImage(); 47 | } 48 | }, 49 | showImage: function() { 50 | gui._dlgComm.hide(); 51 | gui._dlgDesc.hide(); 52 | gui._dlgQuality.hide(); 53 | $('#item-' + state.torrentIndex + ' .empn-img-' + state.imgIndex).click(); 54 | }, 55 | hideImage: function() { 56 | gui.fullsized = true; 57 | gui.toggleImgSize(); 58 | gui._dlgImg.hide(); 59 | }, 60 | 61 | toggleZoom: function() { 62 | gui.toggleImgSize(); 63 | }, 64 | 65 | openImage: function() { 66 | window.open(data.items[state.torrentIndex].thumbs[state.imgIndex].link); 67 | }, 68 | 69 | nextItem: function() { 70 | if (data.items.length <= state.torrentIndex+1) return; 71 | this.activateItem(state.torrentIndex+1); 72 | }, 73 | prevItem: function() { 74 | if (state.torrentIndex-1 < 0) return; 75 | this.activateItem(state.torrentIndex-1); 76 | }, 77 | 78 | nextImage: function() { 79 | if (data.items[state.torrentIndex].thumbs.length <= state.imgIndex+1) return; 80 | this.activateImage(state.imgIndex+1); 81 | }, 82 | prevImage: function() { 83 | if (state.imgIndex-1 < 0) return; 84 | this.activateImage(state.imgIndex-1); 85 | }, 86 | 87 | toggleComments: function() { 88 | if (gui._dlgComm.hasClass('empn-active')) { 89 | this.hideComments(); 90 | } else { 91 | this.showComments(); 92 | } 93 | }, 94 | showComments: function() { 95 | this.hideImage(); 96 | this.hideDescription(); 97 | gui._dlgQuality.hide(); 98 | gui._dlgComm.$('.empn-title').textContent = data.items[state.torrentIndex].title; 99 | // gui._dlgComm.$('.empn-comments').innerHTML = data.items[state.torrentIndex].comments; 100 | gui._dlgComm.$('.empn-comments').removeChildren(); 101 | data.items[state.torrentIndex].comments.forEach(function(it) { 102 | gui._dlgComm.$('.empn-comments').appendChild(it); 103 | }); 104 | gui._dlgComm.$('.empn-comments').innerHTML = gui._dlgComm.$('.empn-comments').innerHTML.replace(/ data-(src|href)=/g, ' $1='); 105 | gui._dlgComm.show($('#item-'+state.torrentIndex)); 106 | }, 107 | hideComments: function() { 108 | gui._dlgComm.hide(); 109 | }, 110 | 111 | toggleDescription: function() { 112 | if (gui._dlgDesc.hasClass('empn-active')) { 113 | this.hideDescription(); 114 | } else { 115 | this.showDescription(); 116 | } 117 | }, 118 | showDescription: function() { 119 | this.hideImage(); 120 | this.hideComments(); 121 | gui._dlgQuality.hide(); 122 | gui._dlgDesc.$('.empn-title').textContent = data.items[state.torrentIndex].title; 123 | gui._dlgDesc.$('.empn-description').innerHTML = data.items[state.torrentIndex].description; 124 | gui._dlgDesc.show($('#item-'+state.torrentIndex)); 125 | }, 126 | hideDescription: function() { 127 | gui._dlgDesc.hide(); 128 | }, 129 | 130 | download: function(forced) { 131 | var itm = data.items[state.torrentIndex]; 132 | if (prefs.combine && !prefs.combineHighest && itm.qualities.length > 1) { 133 | if (gui._dlgQuality.hasClass('empn-active') && !forced) { 134 | gui._dlgQuality.hide(); 135 | return; 136 | } 137 | gui._dlgImg.hide(); 138 | gui._dlgComm.hide(); 139 | gui._dlgDesc.hide(); 140 | gui._dlgQuality.$('.empn-actions').removeChildren(); 141 | itm.qualities.forEach(function(it, i) { 142 | var btn = document.createElement('button'); 143 | btn.innerHTML = it.quality + ' (' + it.size + ')'; 144 | gui._dlgQuality.$('.empn-actions').appendChild(btn); 145 | md.ripple.init(btn); 146 | btn._('click', function() { 147 | this.doDownload(it); 148 | gui._dlgQuality.hide(); 149 | }.bind(this)); 150 | }.bind(this)); 151 | gui._dlgQuality.show($('#item-' + state.torrentIndex)); 152 | } else if (prefs.combine && prefs.combineHighest && itm.qualities.length > 0) { 153 | this.doDownload(itm.qualities[0]); 154 | } else { 155 | this.doDownload(itm); 156 | } 157 | }, 158 | doDownload: function(itm) { 159 | if (prefs.autoThanks) { 160 | this.sendThanks(itm); 161 | } 162 | if (prefs.autoComments) { 163 | if (prefs.autoCommentsPrompt) { 164 | this.promptComment(itm); 165 | } else { 166 | this.sendRandomComment(itm); 167 | } 168 | } 169 | if (prefs.autoTags) { 170 | itm.tags.forEach(function(it) { 171 | prefs.raiseTag(it); 172 | }); 173 | gui.prefs.initValues(); 174 | } 175 | getResponse(itm.url, {responseType:'blob'}).then(function(data) { 176 | // var blob = new Blob(data, {type: "x-application/torrent"}); 177 | var url = window.URL.createObjectURL(data); 178 | var link = document.createElement('a'); 179 | link.href = url; 180 | link.download = '[Empornium]' + itm.title.replace(/[^a-z0-9\-_., ()[\]]+/ig, '_') + '.torrent'; 181 | link.click(); 182 | window.URL.revokeObjectURL(url); 183 | }); 184 | // var ifr = document.createElement('iframe'); 185 | //TODO: iframe is not removed. onload event does not trigger with attachments. 186 | // ifr.addEventListener('load', function() { console.info('load!'); ifr.remove(); delete ifr; }); 187 | // ifr.src = itm.url; 188 | // ifr.style.display = 'none'; 189 | // document.body.appendChild(ifr); 190 | if (prefs.nfo) { 191 | var nfo = new Blob([itm.nfo], { 192 | type: 'text/xml;charset=utf-8' 193 | }); 194 | var nfoUrl = window.URL.createObjectURL(nfo); 195 | var nfoLink = document.createElement('a'); 196 | nfoLink.href = nfoUrl; 197 | nfoLink.download = itm.title + '.nfo'; 198 | nfoLink.click(); 199 | window.URL.revokeObjectURL(nfoUrl); 200 | } 201 | }, 202 | 203 | sendThanks: function(itm) { 204 | itm = itm || data.items[state.torrentIndex]; 205 | post('torrents.php?action=thank', {groupid: itm.id, action: 'thank', auth: itm.auth}).then(function() { 206 | gui._toast.add('Thanks for the Thanks!', itm.title); 207 | }); 208 | }, 209 | sendRandomComment: function(itm) { 210 | itm = itm || data.items[state.torrentIndex]; 211 | if (prefs.hasComments()) { 212 | this.sendComment(itm, prefs.getRandomComment()); 213 | } else { 214 | this.prompComment(itm); 215 | } 216 | }, 217 | sendComment: function(itm, comment) { 218 | post('torrents.php?id=' + itm.id, {action: 'reply', auth: itm.auth, groupid: itm.id, body: comment}).then(function() { 219 | gui._toast.add('Thanks for the Comment!', itm.title); 220 | }); 221 | }, 222 | promptComment: function(itm) { 223 | itm = itm || data.items[state.torrentIndex]; 224 | state.listening = false; 225 | gui._comment.value = ''; 226 | gui._dlgComment.item = itm; 227 | gui._dlgComment.show(); 228 | gui._comment.focus(); 229 | }, 230 | 231 | openDetails: function() { 232 | var itm = data.items[state.torrentIndex]; 233 | if (prefs.combine && !prefs.combineHighest && itm.qualities.length > 1) { 234 | alert('Quality selection is not implemented!'); 235 | } else if (prefs.combine && prefs.combineHighest && itm.qualities.length > 0) { 236 | window.open(itm.qualities[0].urlDetails); 237 | } else { 238 | window.open(itm.urlDetails); 239 | } 240 | }, 241 | 242 | blockImage: function() { 243 | prefs.blockImage(data.items[state.torrentIndex].thumbs[state.imgIndex].src); 244 | gui.repaint(true); 245 | }, 246 | 247 | catchUp: function(curr) { 248 | var itm; 249 | if (curr === true) itm = data.items[state.torrentIndex]; 250 | else itm = data._items[0]; 251 | prefs.setLatest(itm.date); 252 | gui._toast.add('Catching Up!', ''); 253 | } 254 | } -------------------------------------------------------------------------------- /src/css/md.css: -------------------------------------------------------------------------------- 1 | .empn-dialog { 2 | background-color: rgba(0, 0, 0, 0); 3 | bottom: 0; 4 | display: none; 5 | left: 0; 6 | position: fixed; 7 | right: 0; 8 | text-align: center; 9 | top: 0; 10 | transition: 250ms; 11 | white-space: nowrap; 12 | z-index: 5; 13 | } 14 | .empn-dialog .empn-height { 15 | height: 100%; 16 | display: inline-block; 17 | vertical-align: middle; 18 | width: 0; 19 | } 20 | .empn-dialog .empn-content { 21 | box-shadow: 0 19px 60px rgba(0, 0, 0, 0.3); 22 | box-sizing: border-box; 23 | background: #ffffff; 24 | display: inline-block; 25 | max-height: 100%; 26 | overflow-x: hidden; 27 | overflow-y: auto; 28 | padding: 17px; 29 | text-align: left; 30 | vertical-align: middle; 31 | white-space: normal; 32 | } 33 | .empn-dialog .empn-content .empn-title { 34 | color: #616161; 35 | font-size: 1.25em; 36 | font-weight: bold; 37 | margin: 0.5em 0; 38 | } 39 | .empn-dialog .empn-content .empn-actions { 40 | text-align: right; 41 | } 42 | .empn-dialog.empn-preactive { 43 | display: block; 44 | } 45 | .empn-dialog.empn-active { 46 | background-color: rgba(0, 0, 0, 0.3); 47 | } 48 | .empn-dialog.empn-active .empn-content { 49 | transform: translate(0, 0) scale(1) !important; 50 | transition: all 0.4s ease-in-out; 51 | } 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | .empn-menu { 62 | background-color: rgba(0, 0, 0, 0); 63 | bottom: 0; 64 | display: none; 65 | left: 0; 66 | position: fixed; 67 | right: 0; 68 | top: 0; 69 | transition: 250ms linear; 70 | z-index: 4; 71 | } 72 | .empn-menu .empn-content { 73 | box-shadow: 0 14px 45px rgba(0, 0, 0, 0.25); 74 | background-color: #ffffff; 75 | bottom: 0; 76 | left: 0; 77 | position: absolute; 78 | top: 0; 79 | transform: translatex(-100%); 80 | transition: all 0.4s ease-in-out; 81 | } 82 | .empn-menu .empn-content .empn-title { 83 | background-color: rgb(1, 87, 155); 84 | color: #ffffff; 85 | font-size: 1.25em; 86 | font-weight: normal; 87 | margin: 0 0 0.5em 0; 88 | padding: 1em 0.5em; 89 | } 90 | .empn-menu .empn-content .empn-items { 91 | margin: 0; 92 | padding: 0; 93 | } 94 | .empn-menu .empn-content .empn-items .empn-item { 95 | margin: 0.5em 0; 96 | overflow: hidden; 97 | position: relative; 98 | } 99 | .empn-menu .empn-content .empn-items .empn-item .empn-item-link, .empn-menu .empn-content .empn-items .empn-item .empn-item-link * { 100 | cursor: pointer; 101 | } 102 | .empn-menu .empn-content .empn-items .empn-item .empn-item-link { 103 | display: block; 104 | padding: 1em 1.25em; 105 | transition: 250ms; 106 | } 107 | .empn-menu .empn-content .empn-items .empn-item .empn-item-link:hover { 108 | background-color: rgba(0, 0, 0, 0.12); 109 | } 110 | .empn-menu.empn-preactive { 111 | display: block; 112 | } 113 | .empn-menu.empn-active { 114 | background-color: rgba(0, 0, 0, 0.3); 115 | } 116 | .empn-menu.empn-active .empn-content { 117 | transform: translatex(0); 118 | } 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | .empn-input { 129 | display: inline-block; 130 | font-size: 1em; 131 | position: relative; 132 | } 133 | .empn-input input { 134 | border: none; 135 | border-bottom: 1px solid #e0e0e0; 136 | color: #616161; 137 | font: inherit; 138 | margin: 1em 0 0 0; 139 | outline: none; 140 | transition: 250ms ease-in-out; 141 | } 142 | .empn-input input:focus { 143 | border-bottom-color: rgb(1, 87, 155); 144 | } 145 | .empn-input input:invalid { 146 | border-color: #e51c23; 147 | } 148 | .empn-input .empn-placeholder { 149 | position: absolute; 150 | top: 1em; 151 | left: 0; 152 | color: #bdbdbd; 153 | transition: 250ms ease-in-out; 154 | } 155 | .empn-input.empn-focus .empn-placeholder { 156 | top: 0; 157 | font-size: 0.75em !important; 158 | color: rgb(1, 87, 155); 159 | } 160 | .empn-input.empn-has-content .empn-placeholder, 161 | .empn-input.empn-no-placeholder .empn-placeholder { 162 | top: 0; 163 | font-size: 0.75em !important; 164 | } 165 | 166 | 167 | 168 | 169 | .empn-ripple { 170 | content: ""; 171 | background-color: rgba(0, 0, 0, 0.4); 172 | border-radius: 50%; 173 | display: block; 174 | height: 500px; 175 | left: 0; 176 | opacity: 1; 177 | position: absolute; 178 | top: 0; 179 | transform: scale(0); 180 | width: 500px; 181 | } 182 | .empn-clicked .empn-ripple { 183 | opacity: 0; 184 | transform: scale(1); 185 | transition: transform 550ms ease-in-out, opacity 550ms ease-in-out; 186 | } 187 | 188 | 189 | 190 | 191 | 192 | button, 193 | input[type="button"], 194 | input[type="submit"] { 195 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24); 196 | background-color: rgb(1, 87, 155); 197 | border: none; 198 | color: white; 199 | cursor: pointer; 200 | font: inherit; 201 | margin: 1em; 202 | outline: none; 203 | overflow: hidden; 204 | padding: 0.5em; 205 | position: relative; 206 | transition: 200ms linear; 207 | vertical-align: bottom; 208 | width: 10em; 209 | } 210 | button:hover, 211 | input[type="button"]:hover, 212 | input[type="submit"]:hover { 213 | box-shadow: 0 3px 10px rgba(0, 0, 0, 0.16); 214 | background-color: rgb(2, 119, 189); 215 | transform: translate3d(0, -1px, 0); 216 | } 217 | 218 | 219 | 220 | 221 | .empn-toasts { 222 | list-style: none; 223 | margin: 0; 224 | padding: 0; 225 | position: absolute; 226 | right: 2.5em; 227 | top: 2.5em; 228 | width: 20em; 229 | } 230 | .empn-toast { 231 | background-color: rgb(255,255,255); 232 | border-top: 0.5em solid rgb(1, 87, 155); 233 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24); 234 | box-sizing: border-box; 235 | margin: 0; 236 | opacity: 0; 237 | padding: 0.5em; 238 | } 239 | .empn-toast.empn-preactive { 240 | transition: 200ms ease-in-out; 241 | } 242 | .empn-toast.empn-active { 243 | margin-top: 0.5em !important; 244 | opacity: 1; 245 | } 246 | .empn-toast > .empn-title { 247 | font-weight: bold; 248 | } 249 | .empn-toast > .empn-info { 250 | font-size: small; 251 | } 252 | 253 | 254 | 255 | 256 | 257 | .empn-toolbar { 258 | height: 2.5em; 259 | position: relative; 260 | } 261 | .empn-toolbar .empn-sect { 262 | height: 100%; 263 | position: absolute; 264 | top: 0; 265 | } 266 | .empn-toolbar .empn-sect .empn-item { 267 | box-sizing: border-box; 268 | display: inline-block; 269 | height: 100%; 270 | margin: 0 0.5em; 271 | overflow: hidden; 272 | position: relative; 273 | } 274 | .empn-toolbar .empn-sect .empn-item .empn-item-link { 275 | box-sizing: border-box; 276 | color: inherit; 277 | cursor: pointer; 278 | display: block; 279 | font-size: 1.25em; 280 | height: 100%; 281 | padding: 0.45em 0.5em 0.25em 0.5em; 282 | text-decoration: none; 283 | } 284 | .empn-toolbar .empn-sect .empn-item .empn-item-link:hover { 285 | background-color: rgba(0, 0, 0, 0.12); 286 | } 287 | .empn-toolbar .empn-sect.empn-primary { 288 | left: 0; 289 | } 290 | .empn-toolbar .empn-sect.empn-secondary { 291 | right: 0; 292 | } 293 | 294 | .empn-tabbar { 295 | height: 2.5em; 296 | position: relative; 297 | } 298 | .empn-tabbar .empn-items { 299 | height: 100%; 300 | } 301 | .empn-tabbar .empn-items .empn-item { 302 | box-sizing: border-box; 303 | display: inline-block; 304 | height: 100%; 305 | overflow: hidden; 306 | position: relative; 307 | } 308 | .empn-tabbar .empn-items .empn-item .empn-item-link { 309 | background-color: #03a9f4; 310 | box-sizing: border-box; 311 | color: #ffffff; 312 | cursor: pointer; 313 | display: block; 314 | font-size: 1.25em; 315 | height: 100%; 316 | padding: 0.25em 0.5em 0.375em 0.5em; 317 | text-align: center; 318 | } 319 | .empn-tabbar .empn-marker { 320 | background-color: #ffeb3b; 321 | bottom: 0; 322 | height: 0.25em; 323 | position: absolute; 324 | transition: 400ms ease-in-out; 325 | } 326 | .empn-tabbar.empn-bottom .empn-items .empn-item .empn-item-link { 327 | padding: 0.375em 0.5em 0.25em 0.5em; 328 | } 329 | .empn-tabbar.empn-bottom .empn-marker { 330 | bottom: auto; 331 | top: 0; 332 | } -------------------------------------------------------------------------------- /src/css/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | margin: 0; 4 | overflow: hidden; 5 | padding: 0; 6 | } 7 | body { 8 | background-color: rgb(245, 245, 245); 9 | font-family: Helvetica, sans-serif; 10 | } 11 | ul { 12 | margin: 0; 13 | padding: 0; 14 | } 15 | 16 | ${include: md.css} 17 | 18 | #app { 19 | position: absolute; 20 | top: 0; 21 | bottom: 0; 22 | right: 0; 23 | left: 0; 24 | transition: 400ms ease-in-out; 25 | } 26 | #appbar { 27 | background-color: rgb(1, 87, 155); 28 | box-shadow: 0 3px 10px rgba(0, 0, 0, 0.16); 29 | color: rgb(255,255,255); 30 | z-index: 2; 31 | } 32 | 33 | #items { 34 | bottom: 0; 35 | left: 0; 36 | overflow: auto; 37 | padding: 10px; 38 | position: absolute; 39 | right: 0; 40 | top: 40px; 41 | } 42 | #items .empn-item { 43 | background-color: rgb(255,255,255); 44 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24); 45 | margin: 0 0 16px 0; 46 | padding: 2px 2px 2px 5px; 47 | } 48 | .empn-item > .empn-title { 49 | color: rgb(117, 117, 117); 50 | display: inline-block; 51 | font-weight: bold; 52 | height: 16px; 53 | overflow: hidden; 54 | text-decoration: none; 55 | text-overflow: ellipsis; 56 | transition: 200ms; 57 | white-space: nowrap; 58 | max-width: 100%; 59 | } 60 | .empn-item.empn-active > .empn-title { 61 | color: red; 62 | height: auto; 63 | white-space: normal; 64 | } 65 | .empn-item > .empn-tags { 66 | height: 24px; 67 | list-style: none; 68 | margin: 0; 69 | overflow: hidden; 70 | padding: 0; 71 | white-space: nowrap; 72 | } 73 | .empn-item.empn-active > .empn-tags { height: auto; min-height: 24px; white-space: normal; } 74 | .empn-item > .empn-tags > li { 75 | background-color: rgb(255,255,255); 76 | border-radius: 2px; 77 | box-shadow: 0 1px 5px rgba(0, 0, 0, 0.08); 78 | display: inline-block; 79 | font-family: monospace; 80 | //font-size: 0.8em; 81 | padding: 0.125em 0.25em; 82 | margin: 0 0.25em 0.25em 0.25em; 83 | } 84 | .empn-item > .empn-tags > li > a { text-decoration: none; color: inherit; } 85 | .empn-item > .empn-tags > li.empn-good { background-color: rgb(174, 213, 129); } 86 | .empn-item > .empn-tags > li.empn-bad { background-color: rgb(249, 189, 187); } 87 | .empn-item > .empn-tags > li.empn-vgood { background-color: rgb(124, 179, 66); font-weight: bold; } 88 | .empn-item > .empn-tags > li.empn-vbad { background-color: rgb(243, 108, 96); font-weight: bold; } 89 | .empn-item > .empn-info { 90 | list-style: none; 91 | margin: 0; 92 | overflow: hidden; 93 | padding: 0; 94 | white-space: nowrap; 95 | } 96 | .empn-item > .empn-info > dt, .empn-item > .empn-info > dd { 97 | display: inline-block; 98 | font-size: 0.75em; 99 | margin: 0; 100 | } 101 | .empn-item > .empn-info > dt { 102 | color: rgb(117, 117, 117); 103 | } 104 | .empn-item > .empn-info > dt:after { 105 | content: ":"; 106 | } 107 | .empn-item > .empn-info > dd { 108 | margin: 0 1em 0 0.25em; 109 | } 110 | .empn-item > .empn-thumbs { 111 | //height: 221px; 112 | overflow-x: hidden; 113 | white-space: nowrap; 114 | } 115 | .empn-item > .empn-thumbs:hover { 116 | overflow-x: auto; 117 | } 118 | .empn-item > .empn-thumbs > .empn-img { 119 | border-bottom: 3px solid transparent; 120 | box-sizing: border-box; 121 | display: inline-block; 122 | //height: 200px; 123 | margin: 0 10px 0 0; 124 | transition: 200ms ease-in-out; 125 | } 126 | .empn-item > .empn-thumbs > .empn-img.empn-active { 127 | border-bottom: 3px solid red; 128 | } 129 | 130 | .empn-description.box, .empn-comments.box { border: none; } 131 | 132 | #dlg-img .empn-img { 133 | display: block; 134 | transition: 400ms ease-in-out; 135 | } 136 | /* 137 | #dlg-comments .empn-content{ 138 | height: 90%; 139 | width: 90%; 140 | } 141 | #dlg-comments .empn-tabs { 142 | direction: rtl; 143 | list-style: none; 144 | transition: 400ms ease-in-out; 145 | } 146 | #dlg-comments .empn-tabs .empn-tab { 147 | direction: ltr; 148 | display: inline-block; 149 | vertical-align: top; 150 | width: 99.999%; 151 | }*/ 152 | 153 | #dlg-comment-input { 154 | height: 100px; 155 | width: 95%; 156 | } 157 | 158 | #preferences > .empn-content > .empn-items { 159 | position: absolute; 160 | overflow: auto; 161 | bottom: 0; 162 | left: 0; 163 | } 164 | #preferences > .empn-content > .empn-items > .empn-item { 165 | white-space: nowrap; 166 | } 167 | 168 | 169 | 170 | #loading { 171 | background-color: rgb(255,255,255); 172 | bottom: 0; 173 | left: 0; 174 | position: fixed; 175 | right: 0; 176 | text-align: center; 177 | top: 0; 178 | white-space: nowrap; 179 | z-index: 100; 180 | } 181 | #loading .empn-height { 182 | display: inline-block; 183 | height: 100%; 184 | vertical-align: middle; 185 | width: 0; 186 | } 187 | #loading .empn-content { 188 | display: inline-block; 189 | vertical-align: middle; 190 | } 191 | 192 | #loading .empn-spinner { 193 | position: relative; 194 | display: inline-block; 195 | margin: 1em 0; 196 | } 197 | #loading .empn-spinner .empn-track { 198 | border-radius: 50%; 199 | border: 6px solid rgb(179, 229, 252); 200 | height: 50px; 201 | width: 50px; 202 | } 203 | #loading .empn-spinner .empn-blob { 204 | border-radius: 50%; 205 | background-color: rgb(79, 195, 247); 206 | height: 6px; 207 | left: 28px; 208 | position: absolute; 209 | top: 28px; 210 | width: 6px; 211 | animation-name: spinning; 212 | animation-duration: 1s; 213 | animation-iteration-count: infinite; 214 | animation-timing-function: linear; 215 | } 216 | 217 | 218 | @keyframes spinning { 219 | 0% { 220 | transform-origin: 28px 0px; 221 | transform: translate(-28px) rotateZ(0deg); 222 | } 223 | 25% { 224 | transform-origin: 28px 0px; 225 | transform: translate(-28px) rotateZ(90deg); 226 | } 227 | 50% { 228 | transform-origin: 31px 0px; 229 | transform: translate(-28px) rotateZ(180deg); 230 | } 231 | 75% { 232 | transform-origin: 31px 3px; 233 | transform: translate(-28px) rotateZ(270deg); 234 | } 235 | 100% { 236 | transform-origin: 28px 0px; 237 | transform: translate(-28px) rotateZ(360deg); 238 | } 239 | } 240 | 241 | 242 | 243 | 244 | 245 | #dlg-prefs-comments-input, #dlg-prefs-search-string-input { 246 | height: 200px; 247 | width: 500px; 248 | } 249 | #prefs-search-string-help { 250 | cursor: pointer; 251 | } 252 | #dlg-prefs-search-string-help-input, 253 | #dlg-prefs-search-string-help-output { 254 | border: 1px solid rgb(169, 169, 169); 255 | margin: 0 10px 20px 10px; 256 | } 257 | 258 | 259 | #dlg-prefs-tags label { 260 | display: inline-block; 261 | } 262 | #dlg-prefs-tags .empn-dlg-prefs-tags-container { 263 | white-space: nowrap; 264 | } 265 | #dlg-prefs-tags textarea { 266 | height: 100px; 267 | width: 250px; 268 | } 269 | #dlg-prefs-tags .empn-dlg-prefs-tags-table-container { 270 | overflow: auto; 271 | } 272 | #dlg-prefs-tags-ratings td:nth-child(2) { 273 | text-align: right; 274 | } 275 | 276 | 277 | #dlg-prefs-keys table { 278 | width: 100%; 279 | } 280 | #dlg-prefs-keys td:nth-child(2) { 281 | background-color: rgb(236, 239, 241); 282 | font-family: monospace; 283 | min-width: 50px; 284 | } 285 | #dlg-prefs-keys td:nth-child(2).empn-active { 286 | background-color: rgb(179, 229, 252); 287 | } 288 | 289 | 290 | #dlg-comment-prompt-input { 291 | display: block; 292 | height: 100px; 293 | margin: auto; 294 | width: 90%; 295 | } -------------------------------------------------------------------------------- /src/data.js: -------------------------------------------------------------------------------- 1 | var data = { 2 | listParams: { 3 | page: 1, 4 | toString: function() { 5 | var params = []; 6 | for (var key in this) { 7 | if (!this.hasOwnProperty(key) || typeof this[key] == 'function') continue; 8 | params.push(key + '=' + this[key]); 9 | } 10 | return params.join('&'); 11 | } 12 | }, 13 | 14 | _items: [], 15 | items: [], 16 | 17 | update: function() { 18 | var items = this._items.map(function(it) { 19 | var item = {}; 20 | for (var key in it) { 21 | if (!it.hasOwnProperty(key)) continue; 22 | item[key] = it[key]; 23 | } 24 | return item; 25 | }); 26 | 27 | // combine torrents with same name 28 | if (prefs.combine) { 29 | var _items = []; 30 | var titles = []; 31 | items.forEach(function(item, i) { 32 | var title = item.title.replace(/(^|[^a-z0-9])\[?(\d+[pi]|\d+x\d+|\[\d+\])\]?([^a-z0-9]|$)/i, "$1[_EMPN_RESOLUTION_]$3") 33 | .replace(/(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$)/i, "$1_EMPN_BITRATE_$4") 34 | .replace(/(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$)/i, "$1_EMPN_TYPE_$3"); 35 | if (title == item.title) { 36 | item.quality = null; 37 | item.qualityValue = null; 38 | item.qualities = []; 39 | return; 40 | } 41 | item.quality = []; 42 | var resolution = item.title.replace(/^.*?(^|[^a-z0-9])((\d+[pi])|(\d+x\d+)|\[(\d+)\])([^a-z0-9]|$).*$/i, "$3$4$5"); 43 | var bitrate = item.title.replace(/^.*?(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$).*$/i, "$2"); 44 | var type = item.title.replace(/^.*?(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$).*$/i, "$2"); 45 | if (resolution != item.title) item.quality.push(resolution); 46 | if (bitrate != item.title) item.quality.push(bitrate); 47 | if (type != item.title) item.quality.push(type); 48 | var resValue = item.title.replace(/^.*?(^|[^a-z0-9])((\d+)[pi]|\d+x(\d+)|\[(\d+)\])([^a-z0-9]|$).*$/i, "$3$4$5")*1; 49 | var bitValue = item.title.replace(/^.*?(^|[^a-z0-9])((\d+(\.\d+)?)mb?ps)([^a-z0-9]|$).*$/i, "$3")*1; 50 | item.qualityValue = (resValue||1)*(bitValue||1); 51 | item.qualities = items.filter(function(itm) { 52 | return itm.title.replace(/(^|[^a-z0-9])\[?(\d+[pi]|\d+x\d+|\[\d+\])\]?([^a-z0-9]|$)/i, "$1[_EMPN_RESOLUTION_]$3") 53 | .replace(/(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$)/i, "$1_EMPN_BITRATE_$4") 54 | .replace(/(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$)/i, "$1_EMPN_TYPE_$3") == title; 55 | }); 56 | }); 57 | items.forEach(function(item, i) { 58 | if (item.qualities.length > 1) { 59 | var title = item.title.replace(/(^|[^a-z0-9])\[?(\d+[pi]|\d+x\d+|\[\d+\])\]?([^a-z0-9]|$)/i, "$1[_EMPN_RESOLUTION_]$3") 60 | .replace(/(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$)/i, "$1_EMPN_BITRATE_$4") 61 | .replace(/(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$)/i, "$1_EMPN_TYPE_$3"); 62 | if (titles.lastIndexOf(title) != -1) { 63 | return; 64 | } 65 | var _item = {}; 66 | _item.qualities = item.qualities; 67 | _item.qualities.sort(function(a,b) { return a.qualityValue > b.qualityValue ? -1 : 1; }); 68 | _item.category = item.category; 69 | // _item.comments = item.qualities.spread('comments').join(', '); 70 | _item.comments = item.qualities[0].comments; 71 | _item.description = item.qualities[0].description; 72 | _item.date = item.date; 73 | _item.id = item.id; 74 | _item.idx = item.idx; 75 | _item.quality = null; 76 | _item.qualityValue = null; 77 | _item.size = item.qualities.spread('size').join(', '); 78 | _item.snatches = item.qualities.spread('snatches').join(', '); 79 | _item.uploader = item.uploader; 80 | _item.tags = []; 81 | item.qualities.spread('tags').forEach(function(tags) { 82 | _item.tags = _item.tags.concat(tags.filter(function(tag) { return _item.tags.lastIndexOf(tag) == -1; })); 83 | }); 84 | _item.thumbs = []; 85 | item.qualities.spread('thumbs').forEach(function(thumbs) { 86 | _item.thumbs = _item.thumbs.concat(thumbs.filter(function(thumb) { return _item.thumbs.lastIndexOf(thumb) == -1; })); 87 | }); 88 | _item.title = item.title.replace(/\[?(^|[^a-z0-9])(\d+[pi]|\d+x\d+|\[\d+\])([^a-z0-9]|$)\]?/i, "") 89 | .replace(/\[?(^|[^a-z0-9])(\d+(\.\d+)?mb?ps)([^a-z0-9]|$)\]?/i, "") 90 | .replace(/\[?(^|[^a-z0-9])(mp4|wmv|mkv)([^a-z0-9]|$)\]?/i, "") + ' [' + item.qualities.spread('quality').map(function(it) { return it.join('-'); }).join(', ') + ']'; 91 | _items.push(_item); 92 | titles.push(title); 93 | } else { 94 | _items.push(item); 95 | titles.push(title); 96 | } 97 | }); 98 | items = _items; 99 | } 100 | 101 | // filter out horrible tags 102 | items = items.filter(function(item) { 103 | var vbad = item.tags.filter(function(tag) { return prefs.vgoodTags[tag] === false; }).length > 0; 104 | var vgood = item.tags.filter(function(tag) { return prefs.vgoodTags[tag] === true; }).length > 0; 105 | 106 | return !vbad || vgood; 107 | }); 108 | 109 | // sort items 110 | if (!prefs.newestFirst) 111 | items.reverse(); 112 | 113 | // remove blacklisted thumbs 114 | items.forEach(function(item) { 115 | item.thumbs = item.thumbs.filter(function(thumb) { 116 | var src = JSON.parse(thumb).src; 117 | return prefs.blacklist.lastIndexOf(src) == -1; 118 | }); 119 | }); 120 | 121 | // parse thumbs (JSON) 122 | items.forEach(function(item) { 123 | item.thumbs = item.thumbs.map(function(thumb) { 124 | return JSON.parse(thumb); 125 | }); 126 | }); 127 | 128 | 129 | var change = true; 130 | if (items.map(function(it) { return it.id; }).join(';') == this.items.map(function(it) { return it.id; }).join(';')) { 131 | change = false; 132 | } 133 | 134 | this.items = items; 135 | 136 | if (change) { 137 | gui.initItems(); 138 | } 139 | }, 140 | 141 | load: function() { 142 | if (prefs.useSearchString && prefs.searchString) { 143 | this.listParams.action = 'advanced'; 144 | this.listParams.searchtext = encodeURIComponent('"'+prefs.searchString.replace(/\r?\n/g, '"|"')+'"'); 145 | } 146 | this.loadPage().then(function(page) { 147 | this.parsePage(page).then(function(next) { 148 | if (next) { 149 | this.listParams.page++; 150 | this.load(); 151 | } else { 152 | this.update(); 153 | gui.hideLoading(); 154 | state.listening = true; 155 | } 156 | }.bind(this)); 157 | }.bind(this)); 158 | }, 159 | 160 | loadPage: function() { 161 | return getHTML('torrents.php?' + this.listParams); 162 | }, 163 | parsePage: function(page) { 164 | var _href = page.$('[data-href*="authkey"][data-href*="torrent_pass"]').getAttribute('data-href'); 165 | var auth = _href.replace(/^.*authkey=([^&]+)(&|$).*$/, '$1'); 166 | var pass = _href.replace(/^.*torrent_pass=([^&]+)(&|$).*$/, '$1'); 167 | return new Promise(function(resolve, reject) { 168 | var done = 0; 169 | var doneOffset = this._items.length; 170 | var doneSkip = 0; 171 | var minDate = new Date().getTime(); 172 | var rows = page.$$('#torrent_table .torrent'); 173 | rows.forEach(function(row) { 174 | var item = {}; 175 | item.id = row.$('td:nth-child(2) > a').getAttribute('data-href').replace(/^.*(\?|&)id=(\d+)(&|$).*/, '$2'); 176 | item.auth = auth; 177 | item.pass = pass; 178 | item.category = row.$('.cats_col img').getAttribute('data-src').replace(/^.+cat_([^\.]+)\.png/, '$1'); 179 | item.urlDetails = row.$('td:nth-child(2) > a').getAttribute('data-href'); 180 | // item.url = 'torrents.php?action=download&id='+item.id+'&authkey='+auth+'&torrent_pass='+item.pass; 181 | const dlLink = row.$('a[data-href*="/torrents.php?action=download"]'); 182 | if (dlLink) { 183 | item.url = dlLink.getAttribute('data-href'); 184 | } 185 | item.title = row.$('td:nth-child(2) > a').textContent; 186 | // item.comments = row.$('td:nth-child(4)').textContent*1; 187 | item.comments = []; 188 | item.size = row.$('td:nth-child(6)').textContent; 189 | item.snatches = row.$('td:nth-child(7)').textContent*1; 190 | item.date = new Date(Date.parse(row.$('td:nth-child(5) span').title)); 191 | item.uploader = row.$('td.user > a, td.user > span'); 192 | item.uploader.href = item.uploader.getAttribute('data-href'); 193 | item.thumbs = []; 194 | item.thumbLinks = []; 195 | item.tags = row.$$('td:nth-child(2) > .tags > a').map(function(it) { return it.textContent; }); 196 | if (item.date < new Date(prefs.latest)) { 197 | doneSkip++; 198 | console.info(done, doneSkip, rows.length, item.date, new Date(prefs.latest)); 199 | if (done + doneSkip == rows.length) { 200 | resolve(item.date > new Date(prefs.latest) && this._items.length < prefs.torrentLimit); 201 | } 202 | return; 203 | } 204 | this._items.push(item); 205 | gui.updateLoading((this._items.length) + ' Torrents found'); 206 | getHTML(item.urlDetails).then(function(html) { 207 | var desc = html.$(`#content${item.id}`); 208 | // var dlId = (html.$('.torrent_buttons > [title="Download"]') || html.$('.torrent_buttons > a')).href.replace(/^.+id=(\d+).*$/, '$1'); 209 | // item.url = 'torrents.php?action=download&id='+dlId+'&authkey='+auth+'&torrent_pass='+item.pass; 210 | // item.url = (html.$('.torrent_buttons > [title="Download"]') || html.$('.torrent_buttons > a')).href; 211 | item.comments = html.$$('.forum_post.box.vertical_margin:not(#quickreplypreview)'); 212 | item.description = desc.innerHTML.replace(/ data-(src|href)=/g, ' $1='); 213 | desc.$$('img').forEach(function(it) { 214 | var thumb = {}; 215 | let src = it.getAttribute('data-src').replace(/\.th\.jpg$/, '.jpg'); 216 | thumb.src = src; 217 | if (it.parentNode.tagName == 'A') { 218 | thumb.link = it.parentNode.getAttribute('data-href'); 219 | } else { 220 | thumb.link = src; 221 | } 222 | item.thumbs.push(JSON.stringify(thumb)); 223 | }); 224 | gui.updateLoadingSub(done+1+doneOffset + ' Torrents loaded'); 225 | minDate = Math.min(minDate, item.date); 226 | if (++done + doneSkip == rows.length) { 227 | resolve(item.date > new Date(prefs.latest) && this._items.length < prefs.torrentLimit); 228 | } 229 | item.nfo = '\n\n\t'+item.title+'\n\t'+(desc.textContent.trim())+''; 230 | if (item.tags.length > 0) { 231 | item.nfo += '\n\t'+item.tags.join('\n\t')+''; 232 | } 233 | item.nfo += '\n'; 234 | }.bind(this), 235 | function(err) { 236 | console.info(err); 237 | gui.updateLoadingSub(done+1+doneOffset + ' Torrents loaded'); 238 | minDate = Math.min(minDate, item.date); 239 | if (++done + doneSkip == rows.length) { 240 | resolve(item.date > new Date(prefs.latest) && this._items.length < prefs.torrentLimit); 241 | } 242 | }); 243 | }.bind(this)); 244 | }.bind(this)); 245 | }, 246 | }; -------------------------------------------------------------------------------- /src/gui-prefs.js: -------------------------------------------------------------------------------- 1 | { 2 | _dlgComments: undefined, 3 | _commentsInput: undefined, 4 | _dlgTags: undefined, 5 | _thumbHeight: undefined, 6 | _autoTags: undefined, 7 | _tagLimit: undefined, 8 | _newestFirst: undefined, 9 | _autoThanks: undefined, 10 | _autoComments: undefined, 11 | _autoCommentsPrompt: undefined, 12 | _dlgKeys: undefined, 13 | _tblKeys: undefined, 14 | _tagsGood: undefined, 15 | _tagsBad: undefined, 16 | _tagsVGood: undefined, 17 | _tagsVBad: undefined, 18 | _combine: undefined, 19 | _combineHighest: undefined, 20 | _timeOffset: undefined, 21 | _torrentLimit: undefined, 22 | _latestTorrent: undefined, 23 | _useSearchString: undefined, 24 | _searchString: undefined, 25 | _dlgSearchString: undefined, 26 | _dlgSearchStringHelp: undefined, 27 | _nfo: undefined, 28 | 29 | init: function() { 30 | this._dlgComments = $('#dlg-prefs-comments'); 31 | this._commentsInput = $('#dlg-prefs-comments-input'); 32 | this._dlgTags = $('#dlg-prefs-tags'); 33 | this._thumbHeight = $('#prefs-thumb-height'); 34 | this._tagLimit = $('#prefs-tag-limit'); 35 | this._newestFirst = $('#prefs-newest-first'); 36 | this._autoThanks = $('#prefs-auto-thanks'); 37 | this._autoComments = $('#prefs-auto-comments'); 38 | this._autoCommentsPrompt = $('#prefs-auto-comments-prompt'); 39 | this._dlgKeys = $('#dlg-prefs-keys'); 40 | this._tblKeys = $('#dlg-prefs-keys tbody'); 41 | this._tagsGood = $('#dlg-prefs-tags-good'); 42 | this._tagsBad = $('#dlg-prefs-tags-bad'); 43 | this._tagsVGood = $('#dlg-prefs-tags-vgood'); 44 | this._tagsVBad = $('#dlg-prefs-tags-vbad'); 45 | this._autoTags = $('#prefs-auto-tags'); 46 | this._combine = $('#prefs-combine'); 47 | this._combineHighest = $('#prefs-combine-highest'); 48 | this._timeOffset = $('#prefs-timezone-offset'); 49 | this._torrentLimit = $('#prefs-torrent-limit'); 50 | this._latestTorrent = $('#prefs-latest-torrent'); 51 | this._useSearchString = $('#prefs-use-search-string'); 52 | this._searchString = $('#dlg-prefs-search-string-input'); 53 | this._dlgSearchString = $('#dlg-prefs-search-string'); 54 | this._dlgSearchStringHelp = $('#dlg-prefs-search-string-help'); 55 | this._nfo = $('#prefs-nfo'); 56 | 57 | this.initValues(); 58 | 59 | $('#prefs-comments')._('click', this._dlgComments.show); 60 | $('#prefs-tags')._('click', this._dlgTags.show); 61 | $('#prefs-thumb-height')._('click', stopProp); 62 | $('#prefs-tag-limit')._('click', stopProp); 63 | $('#prefs-timezone-offset')._('click', stopProp); 64 | $('#prefs-torrent-limit')._('click', stopProp); 65 | $('#prefs-latest-torrent')._('click', stopProp); 66 | $('#prefs-search-string')._('click', this._dlgSearchString.show); 67 | $('#prefs-search-string-help')._('click', this._dlgSearchStringHelp.show); 68 | 69 | this._newestFirst._('change', function() { 70 | prefs.setNewestFirst(this.checked); 71 | data.update(); 72 | }); 73 | 74 | this._combine._('change', function() { 75 | prefs.setCombine(this.checked); 76 | data.update(); 77 | }); 78 | this._combineHighest._('change', function() { 79 | prefs.setCombineHighest(this.checked); 80 | }); 81 | 82 | this._autoThanks._('change', function() { 83 | prefs.setAutoThanks(this.checked); 84 | }); 85 | 86 | this._autoComments._('change', function() { 87 | prefs.setAutoComments(this.checked); 88 | }); 89 | 90 | this._autoCommentsPrompt._('change', function() { 91 | prefs.setAutoCommentsPrompt(this.checked); 92 | }); 93 | 94 | this._thumbHeight._('change', function() { 95 | prefs.setThumbHeight(this.value*1); 96 | gui.repaint(true); 97 | }); 98 | 99 | this._autoTags._('change', function() { 100 | prefs.setAutoTags(this.checked); 101 | gui.repaint(true); 102 | }); 103 | 104 | this._tagLimit._('change', function() { 105 | prefs.setTagLimit(this._tagLimit.value*1); 106 | this.initValues(); 107 | gui.repaint(true); 108 | }.bind(this)); 109 | 110 | this._useSearchString._('change', function() { 111 | prefs.setUseSearchString(this.checked); 112 | }); 113 | 114 | this._nfo._('change', function() { 115 | prefs.setNfo(this.checked); 116 | }); 117 | 118 | $('#prefs-keys')._('click', this._dlgKeys.show); 119 | 120 | // dlg: comments 121 | $('#dlg-prefs-comments-ok')._('click', function() { 122 | this._dlgComments.hide(); 123 | prefs.setComments(this._commentsInput.value.split('\n###\n').map(function(it) { return it.trim(); })); 124 | }.bind(this)); 125 | $('#dlg-prefs-comments-cancel')._('click', function() { 126 | this._dlgComments.hide(); 127 | this.initValues(); 128 | }.bind(this)); 129 | 130 | // dlg: tags 131 | $('#dlg-prefs-tags-ok')._('click', function() { 132 | this._dlgTags.hide(); 133 | var tags = {}; 134 | this._tagsGood.value.split(/\s+/).map(function(it) { return it.trim(); }).forEach(function(it) { if (it.length == 0) return; tags[it] = true; }); 135 | this._tagsBad.value.split(/\s+/).map(function(it) { return it.trim(); }).forEach(function(it) { if (it.length == 0) return; tags[it] = false; }); 136 | prefs.setGoodTags(tags); 137 | 138 | tags = {}; 139 | this._tagsVGood.value.split(/\s+/).map(function(it) { return it.trim(); }).forEach(function(it) { if (it.length == 0) return; tags[it] = true; }); 140 | this._tagsVBad.value.split(/\s+/).map(function(it) { return it.trim(); }).forEach(function(it) { if (it.length == 0) return; tags[it] = false; }); 141 | prefs.setVgoodTags(tags); 142 | data.update(); 143 | gui.repaint(true); 144 | }.bind(this)); 145 | $('#dlg-prefs-tags-cancel')._('click', function() { 146 | this._dlgTags.hide(); 147 | this.initValues(); 148 | }.bind(this)); 149 | 150 | // dlg: keys 151 | $('#dlg-prefs-keys-ok')._('click', function() { 152 | this._dlgKeys.hide(); 153 | var keys = {}; 154 | this._tblKeys.$$('tr td:nth-child(1)').forEach(function(it) { 155 | keys[it.textContent] = it.getAttribute('data-key'); 156 | }); 157 | prefs.setKeys(keys); 158 | }.bind(this)); 159 | $('#dlg-prefs-keys-cancel')._('click', function() { 160 | this._dlgKeys.hide(); 161 | this.initValues(); 162 | }.bind(this)); 163 | 164 | this._timeOffset._('change', function() { 165 | prefs.setTimeOffset(this._timeOffset.value*1); 166 | this.initValues(); 167 | gui.repaint(true); 168 | }.bind(this)); 169 | 170 | this._torrentLimit._('change', function() { 171 | prefs.setTorrentLimit(this._torrentLimit.value*1); 172 | this.initValues(); 173 | }.bind(this)); 174 | 175 | this._latestTorrent._('change', function() { 176 | prefs.setLatest(this._latestTorrent.value*1); 177 | this.initValues(); 178 | }.bind(this)); 179 | 180 | // dlg: search string 181 | $('#dlg-prefs-search-string-ok')._('click', function() { 182 | this._dlgSearchString.hide(); 183 | prefs.setSearchString(this._searchString.value.trim()); 184 | }.bind(this)); 185 | $('#dlg-prefs-search-string-cancel')._('click', function() { 186 | this._dlgSearchString.hide(); 187 | this.initValues(); 188 | }.bind(this)); 189 | $('#dlg-prefs-search-string-help-close')._('click', function() { 190 | this._dlgSearchStringHelp.hide(); 191 | }.bind(this)); 192 | }, 193 | 194 | initValues: function() { 195 | this._newestFirst.checked = prefs.newestFirst; 196 | this._combine.checked = prefs.combine; 197 | this._combineHighest.checked = prefs.combineHighest; 198 | this._autoThanks.checked = prefs.autoThanks; 199 | this._autoComments.checked = prefs.autoComments; 200 | this._autoCommentsPrompt.checked = prefs.autoCommentsPrompt; 201 | this._commentsInput.value = prefs.comments.join('\n###\n'); 202 | this._thumbHeight.value = prefs.thumbHeight; 203 | md.input.blur(this._thumbHeight.parentNode); 204 | this._autoTags.checked = prefs.autoTags; 205 | this._tagLimit.value = prefs.tagLimit; 206 | md.input.blur(this._tagLimit.parentNode); 207 | this._timeOffset.value = prefs.timeOffset; 208 | md.input.blur(this._timeOffset.parentNode); 209 | this._torrentLimit.value = prefs.torrentLimit; 210 | md.input.blur(this._torrentLimit.parentNode); 211 | this._latestTorrent.value = (prefs.latest || {empnFormat: function() {}}).empnFormat(); 212 | md.input.blur(this._latestTorrent.parentNode); 213 | this._useSearchString.checked = prefs.useSearchString; 214 | this._searchString.value = prefs.searchString; 215 | this._nfo.checked = prefs.nfo; 216 | var g = []; 217 | var b = []; 218 | for(var tag in prefs.goodTags) { 219 | if (!prefs.goodTags.hasOwnProperty(tag)) continue; 220 | if (prefs.goodTags[tag]) g.push(tag); 221 | else b.push(tag); 222 | } 223 | this._tagsGood.value = g.join(' '); 224 | this._tagsBad.value = b.join(' '); 225 | var vg = []; 226 | var vb = []; 227 | for(var tag in prefs.vgoodTags) { 228 | if (!prefs.vgoodTags.hasOwnProperty(tag)) continue; 229 | if (prefs.vgoodTags[tag]) vg.push(tag); 230 | else vb.push(tag); 231 | } 232 | this._tagsVGood.value = vg.join(' '); 233 | this._tagsVBad.value = vb.join(' '); 234 | $('#dlg-prefs-tags-ratings tbody').removeChildren(); 235 | var tagRows = []; 236 | for (tag in prefs.tags) { 237 | if (!prefs.tags.hasOwnProperty(tag)) continue; 238 | var tr = document.createElement('tr'); 239 | var td1 = document.createElement('td'); 240 | td1.textContent = tag; 241 | td1.style.backgroundColor = 'rgba(174, 213, 129, ' + (prefs.tags[tag] / prefs.tagLimit) + ')'; 242 | tr.appendChild(td1); 243 | var td2 = document.createElement('td'); 244 | td2.textContent = prefs.tags[tag]; 245 | tr.appendChild(td2); 246 | tagRows.push(tr); 247 | } 248 | tagRows.sort(function(a,b) { return a.children[1].textContent*1 > b.children[1].textContent*1 ? -1 : 1; }); 249 | tagRows.forEach(function(tr) { $('#dlg-prefs-tags-ratings tbody').appendChild(tr); }); 250 | 251 | this._tblKeys.removeChildren(); 252 | for (var act in prefs.keys) { 253 | if (!prefs.keys.hasOwnProperty(act)) continue; 254 | (function(act) { 255 | var tr = document.createElement('tr'); 256 | var tdA = document.createElement('td'); 257 | tdA.textContent = act; 258 | tdA.setAttribute('data-key', prefs.keys[act]); 259 | tr.appendChild(tdA); 260 | var tdK = document.createElement('td'); 261 | tdK.textContent = keyIdentifier(prefs.keys[act]); 262 | tr.appendChild(tdK); 263 | var listening = false; 264 | addEventListener('keydown', function(evt) { 265 | if (!listening) return; 266 | evt.stopPropagation(); 267 | evt.preventDefault(); 268 | }); 269 | addEventListener('keyup', function(evt) { 270 | if (!listening) return; 271 | listening = false; 272 | evt.stopPropagation(); 273 | evt.preventDefault(); 274 | var key = { 275 | ctrlKey: evt.ctrlKey, 276 | shiftKey: evt.shiftKey, 277 | keyIdentifier: evt.keyIdentifier 278 | }; 279 | tdA.setAttribute('data-key', JSON.stringify(key)); 280 | tdK.textContent = keyIdentifier(evt); 281 | tdK.delClass('empn-active'); 282 | }); 283 | tdK._('click', function() { 284 | listening = true; 285 | tdK.addClass('empn-active'); 286 | }); 287 | this._tblKeys.appendChild(tr); 288 | }.bind(this))(act); 289 | } 290 | } 291 | } -------------------------------------------------------------------------------- /src/gui.js: -------------------------------------------------------------------------------- 1 | var gui = { 2 | tplItem: undefined, 3 | 4 | // elements 5 | _items: undefined, 6 | _dlgImg: undefined, 7 | _img: undefined, 8 | _dlgDesc: undefined, 9 | _dlgComm: undefined, 10 | _dlgQuality: undefined, 11 | _dlgComment: undefined, 12 | _comment: undefined, 13 | _prefs: undefined, 14 | _toast: undefined, 15 | 16 | fullsized: false, 17 | height: 0, 18 | vis: [], 19 | 20 | prefs: ${include: gui-prefs.js}, 21 | 22 | init: function() { 23 | this.tplItem = document.createElement('div'); 24 | this.tplItem.addClass('empn-item'); 25 | this.tplItem.innerHTML = '${include-min-esc: html/item.html}'; 26 | 27 | document.body.innerHTML = ''; 28 | document.title = 'EMPN :: Empornium'; 29 | var container = document.createElement('div'); 30 | container.innerHTML = '${include-min-esc: html/empn.html}'; 31 | document.body.appendChild(container); 32 | 33 | var bbcode = document.createElement('script'); 34 | bbcode.src = 'static/functions/bbcode.js?v='; 35 | document.body.parentNode.children[0].appendChild(bbcode); 36 | 37 | this._items = $('#items'); 38 | this._dlgImg = $('#dlg-img'); 39 | this._img = this._dlgImg.$('.empn-img'); 40 | this._dlgDesc = $('#dlg-description'); 41 | this._dlgComm = $('#dlg-comments'); 42 | this._dlgQuality = $('#dlg-quality'); 43 | this._dlgComment = $('#dlg-comment'); 44 | this._comment = $('#dlg-comment-input'); 45 | this._prefs = $('#preferences'); 46 | this._toast = $('.empn-toasts'); 47 | 48 | md.dialog.init($$('.empn-dialog')); 49 | md.input.init($$('.empn-input')); 50 | md.ripple.init($$('button, .empn-item-link')); 51 | md.menu.init($$('.empn-menu')); 52 | md.toasts.init($$('.empn-toasts')); 53 | // md.tabbar.init($$('.empn-tabbar')); 54 | 55 | this.prefs.init(); 56 | 57 | this._dlgImg._('click', actions.hideImage); 58 | this._img._('click', this.toggleImgSize.bind(this)); 59 | 60 | this._dlgDesc._('click', actions.hideDescription); 61 | this._dlgDesc.$('.empn-content')._('click', stopProp); 62 | 63 | this._dlgComm._('click', actions.hideComments); 64 | this._dlgComm.$('.empn-content')._('click', stopProp); 65 | 66 | this._dlgQuality._('click', this._dlgQuality.hide); 67 | this._dlgQuality.$('.empn-content')._('click', stopProp); 68 | 69 | this._dlgComment._('click', this._dlgComment.hide); 70 | this._dlgComment.$('.empn-content')._('click', stopProp); 71 | $('#dlg-comment-ok')._('click', function() { 72 | actions.sendComment(this._dlgComment.item, this._comment.value); 73 | this._dlgComment.hide(); 74 | state.listening = true; 75 | }.bind(this)); 76 | $('#dlg-comment-cancel')._('click', function() { 77 | this._dlgComment.hide(); 78 | state.listening = true; 79 | }.bind(this)); 80 | 81 | $('#menu-link')._('click', $('#preferences').show); 82 | $('#menu-link')._('click', function() { state.listening = false; }); 83 | this._prefs._('click', function() { state.listening = true; }); 84 | 85 | addEventListener('resize', this.resizeListener.bind(this)); 86 | this.resizeListener(); 87 | 88 | this._items._('scroll', this.scrollListener.bind(this)); 89 | this._items.focus(); 90 | 91 | this.calcItemHeight(); 92 | }, 93 | 94 | initItems: function() { console.info('init items'); 95 | this._items.removeChildren(); 96 | for (var i=0;i bottom) && (this.vis[i] || forced)) { 228 | this.hide(i); 229 | } else if (i*this.height > top && i*this.height < bottom && (!this.vis[i] || forced)) { 230 | this.show(i); 231 | } 232 | } 233 | }, 234 | 235 | scrollListener: function() { 236 | this.repaint(); 237 | }, 238 | 239 | resizeListener: function() { 240 | var img = $('#dlg-img .empn-img'); 241 | img.style.maxWidth = innerWidth - 48 + 'px'; 242 | if (this.fullsized) { 243 | img.style.maxHeight = ''; 244 | } else { 245 | img.style.maxHeight = innerHeight - 48 + 'px'; 246 | } 247 | 248 | this.repaint(); 249 | 250 | this.prefs._dlgTags.$('.empn-dlg-prefs-tags-table-container').style.maxHeight = innerHeight - 17 - 59 - 301 /*this.prefs._dlgTags.$('.empn-dlg-prefs-tags-table-container').offsetTop*/ + 'px'; 251 | this._prefs.style.display = 'block'; 252 | this._prefs.$('.empn-items').style.top = this._prefs.$('.empn-title').getBoundingClientRect().bottom + 'px'; 253 | this._prefs.$('.empn-content').style.width = this._prefs.$('.empn-items').getBoundingClientRect().width + 'px'; 254 | this._prefs.style.display = ''; 255 | }, 256 | 257 | tagSort: function(a,b) { 258 | if ((prefs.vgoodTags[a] && prefs.vgoodTags[b]) || (prefs.vgoodTags[a] === false && prefs.vgoodTags[b] === false)) { 259 | return a.toLowerCase() > b.toLowerCase() ? 1 : a.toLowerCase() < b.toLowerCase() ? -1 : 0; 260 | } 261 | if (prefs.vgoodTags[a]) { 262 | return -1; 263 | } 264 | if (prefs.vgoodTags[b]) { 265 | return 1; 266 | } 267 | if (prefs.vgoodTags[a] === false) { 268 | return -1; 269 | } 270 | if (prefs.vgoodTags[b] === false) { 271 | return 1; 272 | } 273 | if ((prefs.goodTags[a] && prefs.goodTags[b]) || (prefs.goodTags[a] === false && prefs.goodTags[b] === false)) { 274 | return a.toLowerCase() > b.toLowerCase() ? 1 : a.toLowerCase() < b.toLowerCase() ? -1 : 0; 275 | } 276 | if (prefs.goodTags[a]) { 277 | return -1; 278 | } 279 | if (prefs.goodTags[b]) { 280 | return 1; 281 | } 282 | if (prefs.goodTags[a] === false) { 283 | return -1; 284 | } 285 | if (prefs.goodTags[b] === false) { 286 | return 1; 287 | } 288 | if (prefs.tags[a] >= prefs.tagLimit / 10 && prefs.tags[b] >= prefs.tagLimit / 10) { 289 | if (prefs.tags[a] > prefs.tags[b]) return -1; 290 | if (prefs.tags[a] < prefs.tags[b]) return 1; 291 | return a.toLowerCase() > b.toLowerCase() ? 1 : a.toLowerCase() < b.toLowerCase() ? -1 : 0; 292 | } 293 | if (prefs.tags[a] >= prefs.tagLimit / 10) { 294 | return -1; 295 | } 296 | if (prefs.tags[b] >= prefs.tagLimit / 10) { 297 | return 1; 298 | } 299 | return a.toLowerCase() > b.toLowerCase() ? 1 : a.toLowerCase() < b.toLowerCase() ? -1 : 0; 300 | } 301 | }; -------------------------------------------------------------------------------- /src/helpers.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /****************************************\ 7 | | $HELPERS 8 | \****************************************/ 9 | Object.prototype.addListener = function(type, func) { 10 | if (!this.listeners) { 11 | Object.defineProperty(this, 'listeners', { 12 | writable: true, 13 | value: {} 14 | }); 15 | } 16 | if (!this.listeners[type]) 17 | this.listeners[type] = []; 18 | this.listeners[type].push(func); 19 | return func; 20 | }; 21 | Object.prototype.removeListener = function(type, func) { 22 | if (!this.listeners[type]) 23 | return; 24 | for (var i=0;i offset) { 89 | this.children[offset].remove(); 90 | } 91 | }; 92 | 93 | Node.prototype.scrollToV = function(y) { 94 | var el = this; 95 | var timeLapsed = 0; 96 | var percentage = 0; 97 | var position = el.scrollTop; 98 | var distance = y - el.scrollTop; 99 | var startLocation = el.scrollTop; 100 | var interval = undefined; 101 | 102 | var pattern = function(time) { 103 | return time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; 104 | }; 105 | 106 | var start = function() { 107 | interval = setInterval(loop, 16); 108 | }; 109 | var loop = function() { 110 | timeLapsed += 16; 111 | percentage = timeLapsed / 500; 112 | percentage = percentage > 1 ? 1 : percentage; 113 | position = startLocation + (distance * pattern(percentage)); 114 | el.scrollTop = position; 115 | stop(); 116 | }; 117 | var stop = function() { 118 | if (percentage < 1) return; 119 | 120 | clearInterval(interval); 121 | }; 122 | 123 | start(); 124 | }; 125 | Node.prototype.scrollToH = function(x) { 126 | var el = this; 127 | var timeLapsed = 0; 128 | var percentage = 0; 129 | var position = el.scrollLeft; 130 | var distance = x - el.scrollLeft; 131 | var startLocation = el.scrollLeft; 132 | var interval = undefined; 133 | 134 | var pattern = function(time) { 135 | return time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; 136 | }; 137 | 138 | var start = function() { 139 | interval = setInterval(loop, 16); 140 | }; 141 | var loop = function() { 142 | timeLapsed += 16; 143 | percentage = timeLapsed / 500; 144 | percentage = percentage > 1 ? 1 : percentage; 145 | position = startLocation + (distance * pattern(percentage)); 146 | el.scrollLeft = position; 147 | stop(); 148 | }; 149 | var stop = function() { 150 | if (percentage < 1) return; 151 | 152 | clearInterval(interval); 153 | }; 154 | 155 | start(); 156 | }; 157 | 158 | function stopProp(evt) { 159 | evt.stopPropagation(); 160 | } 161 | 162 | function keyIdentifier(evt) { 163 | if (evt == null) return ''; 164 | if (typeof evt == 'string') evt = JSON.parse(evt); 165 | var key = []; 166 | if (evt.ctrlKey) key.push('Ctrl'); 167 | if (evt.shiftKey) key.push('Shift'); 168 | 169 | var ki; 170 | if (evt.keyIdentifier) { 171 | ki = evt.keyIdentifier; 172 | } else { 173 | if (evt.keyCode == 16) ki = 'Shift'; 174 | else if (evt.keyCode == 17) ki = 'Ctrl'; 175 | else if (evt.keyCode == 18) ki = 'Alt'; 176 | else if (evt.keyCode == 37) ki = 'Left'; 177 | else if (evt.keyCode == 38) ki = 'Up'; 178 | else if (evt.keyCode == 39) ki = 'Right'; 179 | else if (evt.keyCode == 40) ki = 'Down'; 180 | else if (evt.keyCode == 46) ki = 'U+007F'; // Del 181 | else if (evt.keyCode == 18) ki = 'U+0020'; // Space 182 | else if (evt.keyCode == 8) ki = 'U+0008'; // Backspace 183 | else if (evt.keyCode == 9) ki = 'U+0009'; // Tab 184 | else if (evt.keyCode == 27) ki = 'U+001B'; // Esc 185 | else ki = 'U+' + ('0000' + evt.keyCode.toString(16)).slice(-4); 186 | } 187 | if (ki == undefined) return ''; 188 | if (ki.search(/^U\+([0-9A-F]){4}$/) == 0) { 189 | if (ki == 'U+0020') 190 | key.push('Space'); 191 | else if (ki == 'U+007F') 192 | key.push('Del'); 193 | else if (ki == 'U+0008') 194 | key.push('Backspace'); 195 | else if (ki == 'U+0009') 196 | key.push('Tab'); 197 | else if (ki == 'U+001B') 198 | key.push('Esc'); 199 | else 200 | key.push(String.fromCharCode(Number.parseInt(ki.substring(2), 16).toString(10))); 201 | } else { 202 | key.push(ki); 203 | } 204 | 205 | return key.unique().join('+'); 206 | } 207 | 208 | function mapToQuery() { 209 | var params = []; 210 | for (var key in this) { 211 | if (!this.hasOwnProperty(key) || typeof this[key] == 'function') continue; 212 | params.push(encodeURIComponent(key) + '=' + encodeURIComponent(this[key])); 213 | } 214 | return params.join('&'); 215 | } 216 | 217 | function get(url) { 218 | return new Promise(function(resolve, reject) { 219 | var xhr = new XMLHttpRequest(); 220 | xhr.open('GET', url, true); 221 | xhr.addEventListener('load', function() { 222 | if (xhr.status == 200) { 223 | resolve(xhr.responseText); 224 | } else { 225 | reject(Error(xhr.statusText)); 226 | } 227 | }); 228 | xhr.send(); 229 | }); 230 | } 231 | function getResponse(url, params, headers) { 232 | params = params || {}; 233 | headers = headers || {}; 234 | return new Promise(function(resolve, reject) { 235 | var xhr = new XMLHttpRequest(); 236 | xhr.open('GET', url, true); 237 | xhr.addEventListener('load', function() { 238 | resolve(xhr.response); 239 | }) 240 | Object.keys(params).forEach(function(key) { 241 | xhr[key] = params[key]; 242 | }); 243 | Object.keys(headers).forEach(function(key) { 244 | xhr.setRequestHeader(key, headers[key]); 245 | }); 246 | xhr.send(); 247 | }); 248 | } 249 | function post(url, args) { 250 | return new Promise(function(resolve, reject) { 251 | var xhr = new XMLHttpRequest(); 252 | xhr.open('POST', url, true); 253 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 254 | xhr.addEventListener('load', function() { 255 | if (xhr.status == 200) { 256 | resolve(xhr.responseText); 257 | } else { 258 | reject(Error(xhr.statusText)); 259 | } 260 | }); 261 | if (args) { 262 | args.toString = mapToQuery; 263 | } 264 | xhr.send(args); 265 | }); 266 | } 267 | function getHTML(url) { 268 | return get(url).then( 269 | function(txt) { 270 | var html = document.createElement('div'); 271 | html.innerHTML = txt.replace(/ (src|href)=/g, ' data-$1='); 272 | return html; 273 | }); 274 | } -------------------------------------------------------------------------------- /src/html/empn.html: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 | 10 | 13 |
14 | 15 | 16 |
17 |
18 |
19 | 20 |
21 |
22 |
23 | 24 |
25 |
26 | 27 | 28 |
29 |
30 |
Preferences
31 |
    32 |
  • 33 | 35 |
  • 36 |
  • 37 | 40 |
  • 41 |
  • 42 | 43 |
  • 44 |
  • 45 | 48 |
  • 49 |
  • 50 | Edit Comments 51 |
  • 52 |
  • 53 | 58 |
  • 59 |
  • 60 | 61 |
  • 62 |
  • 63 | 68 |
  • 69 |
  • 70 | Edit Tags 71 |
  • 72 |
  • 73 | Key Bindings 74 |
  • 75 |
  • 76 | 81 |
  • 82 |
  • 83 | 88 |
  • 89 |
  • 90 | 93 |
  • 94 |
  • 95 | Edit Search String 96 |
  • 97 |
  • 98 | 101 |
  • 102 |
  • 103 | 108 |
  • 109 |
110 |
111 |
112 | 113 | 114 |
115 |
116 |
117 |
Edit Auto Comments
118 |
119 |

Separate comments with a line containing only ###

120 | 122 |
123 |
124 | 125 | 126 |
127 |
128 |
129 | 130 | 131 |
132 |
133 |
134 |
Edit Search String Help
135 |
136 | 138 |
139 |
140 | 141 | 142 |
143 |
144 |
145 | 146 |
147 |
148 |
149 |
Search String - Help
150 | Input:
151 |
this i like
and this too
152 | Output:
153 |
"this i like"|"and this too"
154 |
155 | 156 |
157 |
158 |
159 | 160 | 161 |
162 |
163 |
164 |
Edit Tags
165 |
166 | 170 | 174 |
175 |
176 | 180 | 184 |
185 |
186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 |
TagRating
195 |
196 |
197 | 198 | 199 |
200 |
201 |
202 | 203 | 204 |
205 |
206 |
207 |
Key Bindings
208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 |
ActionKey
217 |
218 | 219 | 220 |
221 |
222 |
223 | 224 | 225 |
226 |
227 |
228 |
Please leave a comment
229 | 230 |
231 | 232 | 233 | 234 |
235 |
236 |
237 | 238 | 239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 | 247 | 248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 | 256 | 257 |
258 |
259 |
260 |
Select Quality
261 |
262 |
263 |
264 | 265 | 266 |
267 |
268 |
269 |
Enter a Comment
270 |
271 |
272 | 273 | 274 |
275 |
276 |
277 | 278 | 279 |
    280 |
281 | 282 | 283 |
284 |
285 |
286 |
 
287 |
288 |
289 |
290 |
291 |
 
292 |
293 |
-------------------------------------------------------------------------------- /src/html/item.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 |
    Date
    5 |
    Category
    6 |
    Size
    7 |
    Snatches
    8 |
    Comments
    9 |
    Uploaded By
    10 |
    11 |
    -------------------------------------------------------------------------------- /src/html/toast.html: -------------------------------------------------------------------------------- 1 |
    2 |
    -------------------------------------------------------------------------------- /src/keyboard.js: -------------------------------------------------------------------------------- 1 | var keyboard = { 2 | init: function() { 3 | addEventListener('keydown', this.reactDown); 4 | addEventListener('keyup', this.react); 5 | }, 6 | 7 | reactDown: function(evt) { 8 | if (!state.listening) return; 9 | 10 | var keyMap = {}; 11 | for (var act in prefs.keys) { 12 | if (!prefs.keys.hasOwnProperty(act)) continue; 13 | keyMap[keyIdentifier(prefs.keys[act])] = act; 14 | } 15 | 16 | if (keyMap[keyIdentifier(evt)]) { 17 | evt.preventDefault(); 18 | } 19 | }, 20 | react: function(evt) { 21 | if (!state.listening) return; 22 | 23 | var keyMap = {}; 24 | for (var act in prefs.keys) { 25 | if (!prefs.keys.hasOwnProperty(act)) continue; 26 | keyMap[keyIdentifier(prefs.keys[act])] = act; 27 | } 28 | 29 | if (keyMap[keyIdentifier(evt)]) { 30 | evt.preventDefault(); 31 | } 32 | 33 | console.info(keyIdentifier(evt), keyMap); 34 | 35 | switch(keyMap[keyIdentifier(evt)]) { 36 | case 'Next Torrent': 37 | actions.nextItem(); 38 | break; 39 | case 'Previous Torrent': 40 | actions.prevItem(); 41 | break; 42 | case 'Next Image': 43 | actions.nextImage(); 44 | break; 45 | case 'Previous Image': 46 | actions.prevImage(); 47 | break; 48 | case 'Show / Hide Image': 49 | actions.showHideImage(); 50 | break; 51 | case 'Toggle Zoom': 52 | actions.toggleZoom(); 53 | break; 54 | case 'Open Image in a New Tab': 55 | actions.openImage(); 56 | break; 57 | case 'Show / Hide Comments': 58 | actions.toggleComments(); 59 | break; 60 | case 'Show / Hide Description': 61 | actions.toggleDescription(); 62 | break; 63 | case 'Download': 64 | actions.download(); 65 | break; 66 | case 'Open Details in a New Tab': 67 | actions.openDetails(); 68 | break; 69 | case 'Block Image': 70 | actions.blockImage(); 71 | break; 72 | case 'Send Thanks': 73 | actions.sendThanks(); 74 | break; 75 | case 'Add Comment': 76 | actions.sendRandomComment(); 77 | break; 78 | case 'Add Manual Comment': 79 | actions.promptComment(); 80 | break; 81 | case 'Catch Up': 82 | actions.catchUp(); 83 | break; 84 | case 'Catch Up to Current Torrent': 85 | actions.catchUp(true); 86 | break; 87 | }; 88 | } 89 | }; -------------------------------------------------------------------------------- /src/md.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /****************************************\ 7 | | $MD 8 | \****************************************/ 9 | var md = { 10 | init: function() { 11 | this.dialog.init($$('.empn-empn-dialog')); 12 | this.menu.init($$('.empn-empn-menu')); 13 | this.tabbar.init($$('.empn-empn-tabbar')); 14 | this.ripple.init($$('button, input[type="button"], input[type="submit"], .empn-tabbar .empn-item, .empn-menu .empn-item, .empn-toolbar .empn-item')); 15 | this.progress.bar.init($$('.empn-empn-progress-bar')); 16 | this.input.init($$('.empn-empn-input')); 17 | }, 18 | 19 | toasts: { 20 | init: function(tstss) { 21 | if (tstss instanceof Element) { 22 | tstss = [tstss]; 23 | } 24 | tstss.forEach(function(tsts) { 25 | tsts.add = function(title, desc) { 26 | return this.add(tsts, title, desc); 27 | }.bind(this); 28 | }.bind(this)); 29 | }, 30 | add: function(tsts, title, desc) { 31 | var tst = document.createElement('li'); 32 | tst.addClass('empn-toast'); 33 | var tstTitle = document.createElement('div'); 34 | tstTitle.addClass('empn-title'); 35 | var tstInfo = document.createElement('div'); 36 | tstInfo.addClass('empn-info'); 37 | tstTitle.textContent = title; 38 | tstInfo.textContent = desc; 39 | tst.appendChild(tstTitle); 40 | tst.appendChild(tstInfo); 41 | 42 | tsts.appendChild(tst); 43 | tst.style.marginTop = -tst.offsetHeight + 'px'; 44 | if (tsts.children.length > 0) { 45 | tsts.insertBefore(tst, tsts.children[0]); 46 | } else { 47 | tsts.appendChild(tst); 48 | } 49 | tst.addClass('empn-preactive'); 50 | setTimeout(function() { tst.addClass('empn-active'); }.bind(this), 1); 51 | setTimeout(function() { 52 | tst.delClass('empn-active'); 53 | setTimeout(function() { tst.remove(); }, 205); 54 | }.bind(this), 5000); 55 | } 56 | }, 57 | 58 | dialog: { 59 | init: function(dlgs) { 60 | if (dlgs instanceof Element) { 61 | dlgs = [dlgs]; 62 | } 63 | dlgs.forEach(function(dlg) { 64 | dlg.show = function(src) { 65 | return this.show(dlg, src); 66 | }.bind(this); 67 | dlg.hide = function() { 68 | return this.hide(dlg); 69 | }.bind(this); 70 | }.bind(this)); 71 | }, 72 | show: function(dlg, src) { 73 | src = src || dlg; 74 | return new Promise(function(resolve, reject) { 75 | dlg.mdDlgSrc = src; 76 | dlg.addClass('empn-preactive'); 77 | var c = dlg.$('.empn-content'); 78 | var b = c.getBoundingClientRect(); 79 | 80 | var bb; 81 | if (src instanceof MouseEvent) { 82 | bb = {top: src.clientY, height: 0, left: src.clientX, width: 0}; 83 | } else { 84 | bb = src.getBoundingClientRect(); 85 | } 86 | 87 | var y = Math.round((bb.top + bb.height * 0.5) - (b.top + b.height * 0.5)) + 'px'; 88 | var x = Math.round((bb.left + bb.width * 0.5) - (b.left + b.width * 0.5)) + 'px'; 89 | 90 | c.style.transform = 'translate('+x+', '+y+') scale(0)'; 91 | 92 | setTimeout(function() { dlg.addClass('empn-active'); }, 20); 93 | setTimeout(function() { 94 | c.style.transition = 'all 0.4s ease-in-out'; 95 | 96 | resolve(dlg); 97 | }, 500); 98 | }); 99 | }, 100 | hide: function(dlg) { 101 | return new Promise(function(resolve, reject) { 102 | var src = dlg.mdDlgSrc || dlg; 103 | var c = dlg.$('.empn-content'); 104 | var b = c.getBoundingClientRect(); 105 | 106 | var bb; 107 | if (src instanceof MouseEvent) { 108 | bb = {top: src.clientY, height: 0, left: src.clientX, width: 0}; 109 | } else { 110 | bb = src.getBoundingClientRect(); 111 | } 112 | 113 | var y = Math.round((bb.top + bb.height * 0.5) - (b.top + b.height * 0.5)) + 'px'; 114 | var x = Math.round((bb.left + bb.width * 0.5) - (b.left + b.width * 0.5)) + 'px'; 115 | 116 | c.style.transform = 'translate('+x+', '+y+') scale(0)'; 117 | 118 | dlg.delClass('empn-active'); 119 | setTimeout(function() { 120 | dlg.delClass('empn-preactive'); 121 | c.style.transform = ''; 122 | c.style.transition = ''; 123 | 124 | resolve(dlg); 125 | }, 400); 126 | }); 127 | } 128 | }, 129 | 130 | menu: { 131 | init: function(menus) { 132 | if (menus instanceof Element) { 133 | menus = [menus]; 134 | } 135 | menus.forEach(function(menu) { 136 | menu.show = function() { 137 | return this.show(menu); 138 | }.bind(this); 139 | menu.hide = function() { 140 | return this.hide(menu); 141 | }.bind(this); 142 | menu.addEventListener('click', menu.hide); 143 | menu.$('.empn-content').addEventListener('click', function(evt) { evt.stopPropagation(); }); 144 | }.bind(this)); 145 | }, 146 | show: function(menu) { 147 | return new Promise(function(resolve, reject) { 148 | menu.addClass('empn-preactive'); 149 | 150 | setTimeout(function() { 151 | // $('#app').style.transform = 'translateX(' + menu.$('.empn-content').offsetWidth + 'px' + ')'; 152 | menu.addClass('empn-active'); 153 | }, 20); 154 | setTimeout(function() { resolve(menu); }, 420); 155 | }); 156 | }, 157 | hide: function(menu) { 158 | return new Promise(function(resolve, reject) { 159 | // $('#app').style.transform = ''; 160 | menu.delClass('empn-active'); 161 | setTimeout(function() { 162 | menu.delClass('empn-preactive'); 163 | resolve(menu); 164 | }, 400); 165 | }); 166 | } 167 | }, 168 | 169 | tabbar: { 170 | init: function(bars) { 171 | if (bars instanceof Element) { 172 | bars = [bars]; 173 | } 174 | bars.forEach(function(bar) { 175 | var items = bar.$$('.empn-item'); 176 | for (var i=0;i 0; 138 | }, 139 | getRandomComment: function() { 140 | return this.comments[Math.floor(Math.random()*this.comments.length)]; 141 | }, 142 | 143 | save: function() { 144 | localStorage.setItem('empn_prefs', JSON.stringify(this)); 145 | }, 146 | load: function() { 147 | var prefs = false; 148 | try { 149 | prefs = JSON.parse(localStorage.getItem('empn_prefs')); 150 | } catch(ex) {} 151 | if (prefs && prefs.meta && prefs.meta.version) { 152 | switch(prefs.meta.version) { 153 | case 1: 154 | this.initV1(prefs); 155 | break; 156 | default: 157 | alert('Unknown preferences format (version "' + prefs.meta.version + '").\n\nPreferences will be reset to default values.'); 158 | this.save(); 159 | break; 160 | } 161 | } 162 | }, 163 | initV1: function(prefs) { 164 | for (var key in prefs) { 165 | if (prefs.hasOwnProperty(key) && this.hasOwnProperty(key)) { 166 | if (key == 'keys') { 167 | for (var _key in prefs[key]) { 168 | if (prefs[key].hasOwnProperty(_key) && this.keys.hasOwnProperty(_key)) { 169 | this.keys[_key] = prefs[key][_key]; 170 | } 171 | } 172 | } else if (key == 'latest') { 173 | this[key] = new Date(prefs[key]); 174 | } else { 175 | this[key] = prefs[key]; 176 | } 177 | } 178 | } 179 | } 180 | }; -------------------------------------------------------------------------------- /src/script.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name EMPN 3 | // @namespace https://github.com/LenAnderson/ 4 | // @downloadURL https://github.com/LenAnderson/EMPN/raw/master/empn.user.js 5 | // @version 0.8 6 | // @author LenAnderson 7 | // @match http://*.empornium.me/* 8 | // @match https://*.empornium.me/* 9 | // @match http://*.empornium.sx/* 10 | // @match https://*.empornium.sx/* 11 | // @match http://*.empornium.is/* 12 | // @match https://*.empornium.is/* 13 | // @grant none 14 | // ==/UserScript== 15 | 16 | ${include: helpers.js} 17 | ${include: md.js} 18 | ${include: prefs.js} 19 | ${include: gui.js} 20 | ${include: data.js} 21 | ${include: actions.js} 22 | ${include: state.js} 23 | ${include: keyboard.js} 24 | 25 | 26 | 27 | 28 | 29 | 30 | /****************************************\ 31 | | $EMPN 32 | \****************************************/ 33 | function init() { 34 | if (location.href.search(/empn.php$/) == -1) { 35 | var orig = $('#nav_torrents'); 36 | var node = orig.cloneNode(true); 37 | node.id = 'nav_empn'; 38 | var a = node.$('a'); 39 | a.href = 'empn.php'; 40 | a.textContent = 'EMPN'; 41 | orig.parentNode.insertBefore(node, orig); 42 | } else { 43 | prefs.load(); 44 | gui.init(); 45 | keyboard.init(); 46 | data.load(); 47 | } 48 | } 49 | init(); -------------------------------------------------------------------------------- /src/state.js: -------------------------------------------------------------------------------- 1 | var state = { 2 | torrentIndex: 0, 3 | imgIndex: 0, 4 | listening: false 5 | }; --------------------------------------------------------------------------------