您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically sort teaser images on /videos, /images, /subscriptions, /users, /playlist, and sidebars using customizable sort function. Can load and sort multiple pages at once.
当前为
// ==UserScript== // @name Iwara Custom Sort // @name:ja Iwara Custom ソート // @version 0.209 // @grant GM.setValue // @grant GM.getValue // @grant GM.deleteValue // @run-at document-end // @match https://ecchi.iwara.tv/* // @match https://www.iwara.tv/* // @match http://ecchi.iwara.tv/* // @match http://www.iwara.tv/* // eslint-disable-next-line max-len // @description Automatically sort teaser images on /videos, /images, /subscriptions, /users, /playlist, and sidebars using customizable sort function. Can load and sort multiple pages at once. // eslint-disable-next-line max-len // @description:ja /videos、/images、/subscriptions、/users、/playlistとサイドバーのサムネイルを自動的にソートします。ソート方法はカスタマイズすることができます、一度に複数のページを読み込んでソートすることができます。 // @license AGPL-3.0-or-later // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js#sha256-4/EaXPJ/6N3TkeW1FnAqmfV7JNVmnIFQ3bllkklPJ9U= // @require https://unpkg.com/[email protected]/dist/loglevel.min.js#sha384-Op9lLc4V1M516+nNY8VWsadxPqqnzIpcU8UqrxIqJeVa+jbqbsAjsttJPJyACagp // @require https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.min.js#sha256-ofji4RA7ZKBd+T/Ij8gVhRYyfvqark3dhZ/wD+/wkPg= // @namespace https://greasyfork.org/users/245195 // ==/UserScript== /* jshint esversion: 6 */ /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 4); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports) { module.exports = log; /***/ }), /* 1 */ /***/ (function(module, exports) { module.exports = rxjs.operators; /***/ }), /* 2 */ /***/ (function(module, exports) { module.exports = rxjs; /***/ }), /* 3 */ /***/ (function(module, exports) { module.exports = Swal; /***/ }), /* 4 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); // EXTERNAL MODULE: external "log" var external_log_ = __webpack_require__(0); // EXTERNAL MODULE: external "Swal" var external_Swal_ = __webpack_require__(3); var external_Swal_default = /*#__PURE__*/__webpack_require__.n(external_Swal_); // EXTERNAL MODULE: external "rxjs" var external_rxjs_ = __webpack_require__(2); // EXTERNAL MODULE: external "rxjs.operators" var external_rxjs_operators_ = __webpack_require__(1); // CONCATENATED MODULE: ./src/sort_component/index.ts const createNumberInput = (value, min, max, step, width, ...className) => { const input = document.createElement('input'); input.type = 'number'; input.value = value.toString(); input.min = min.toString(); input.max = max.toString(); input.step = step.toString(); input.setAttribute('required', ''); input.style.width = width; input.classList.add(...className); return input; }; const createLabel = (text, ...className) => { const label = document.createElement('label'); label.innerHTML = text; label.classList.add(...className); return label; }; const createTextInput = (text, maxLength, size, ...className) => { const input = document.createElement('input'); input.type = 'text'; input.value = text; input.maxLength = maxLength; input.size = size; input.classList.add(...className); return input; }; const createButton = (text, ...className) => { const button = document.createElement('button'); button.innerHTML = text; button.classList.add(...className); return button; }; /* harmony default export */ var sort_component = (class { constructor(initialSortValue, defaultSortValue, pageCount) { this.label1 = createLabel('', 'text-primary'); this.loadedPageCount = 0; this.sortValueInput = createTextInput(initialSortValue, 120, 65, 'form-control', 'input-sm'); this.sortButton = createButton('Sort', 'btn', 'btn-sm', 'btn-primary'); this.sort$ = Object(external_rxjs_["fromEvent"])(this.sortButton, 'click').pipe(Object(external_rxjs_operators_["map"])(() => this.sortValueInput.value)); this.sortValueInput.addEventListener('keyup', (event) => { if (event.key === 'Enter') { this.sortButton.click(); } }); const resetDefaultButton = createButton('Default', 'btn', 'btn-sm', 'btn-info'); Object(external_rxjs_["fromEvent"])(resetDefaultButton, 'click').subscribe(() => { this.sortValueInput.value = defaultSortValue; GM.setValue('sortValue', defaultSortValue); }); const label3 = createLabel('', 'text-primary'); const pageCountInput = createNumberInput(pageCount, 1, 300, 1, '7rem', 'form-control', 'input-sm'); pageCountInput.addEventListener('change', async (event) => { await GM.setValue('pageCount', Number.parseInt(event.target.value, 10)); label3.innerHTML = 'Refresh to apply the change.'; }); const label2 = createLabel('pages loaded', 'text-primary'); this.UI = document.createElement('div'); this.UI.style.display = 'inline-block'; this.UI.classList.add('form-inline', 'container'); this.UI.append(this.sortValueInput, resetDefaultButton, this.sortButton, this.label1, pageCountInput, label2, label3); this.UI.childNodes.forEach((node) => { node.style.margin = '5px 2px'; }); this.loadedPageCount = 0; } sort() { this.sortButton.click(); } addLoadedPageCount() { this.loadedPageCount += 1; this.label1.innerHTML = `${this.loadedPageCount} of `; } }); // CONCATENATED MODULE: ./src/teaser_element_selector/index.ts /* harmony default export */ var teaser_element_selector = ('.node-teaser, .node-sidebar_teaser, .node-wide_teaser'); // CONCATENATED MODULE: ./src/sort_teasers/index.ts const getTeaserValue = (info, expression) => { const getSortParamPairs = [ ['index', info.initialIndex], ['views', info.viewCount], ['likes', info.likeCount], ['ratio', Math.min(info.likeCount / Math.max(1, info.viewCount), 1)], ['image', info.imageFactor], ['gallery', info.galleryFactor], ['private', info.privateFactor], ]; // eslint-disable-next-line no-new-func return new Function(...getSortParamPairs.map(([name]) => name), `return (${expression})`)(...getSortParamPairs.map((pairs) => pairs[1])); }; const sortContainer = (container, valueExpression) => { const viewsIconSelector = '.glyphicon-eye-open'; const likesIconSelector = '.glyphicon-heart'; const imageFieldSelector = '.field-type-image'; const galleryIconSelector = '.glyphicon-th-large'; const privateDivSelector = '.private-video'; const teaserDivs = Array.from(container.querySelectorAll(teaser_element_selector)); const sortedTeaserCount = container.dataset.sortedTeaserCount ? parseInt(container.dataset.sortedTeaserCount, 10) : 0; teaserDivs.filter((div) => !div.dataset.initialIndex) .forEach((div, index) => { div.dataset.initialIndex = (sortedTeaserCount + index).toString(); }); container.dataset.sortedTeaserCount = teaserDivs.length.toString(); const getNearbyNumber = (element) => { const parsePrefixed = (str) => Number.parseFloat(str) * (str.includes('k') ? 1000 : 1); return element ? parsePrefixed(element.nextSibling.wholeText.replace(/,/g, '')) : 0; }; const teaserInfos = teaserDivs.map((div) => ({ initialIndex: parseInt(div.dataset.initialIndex, 10), viewCount: getNearbyNumber(div.querySelector(viewsIconSelector)), likeCount: getNearbyNumber(div.querySelector(likesIconSelector)), imageFactor: div.querySelector(imageFieldSelector) ? 1 : 0, galleryFactor: div.querySelector(galleryIconSelector) ? 1 : 0, privateFactor: div.querySelector(privateDivSelector) ? 1 : 0, })); const divValuePairs = teaserInfos.map((info, index) => [ teaserDivs[index], getTeaserValue(info, valueExpression), ]); divValuePairs.sort((itemA, itemB) => itemB[1] - itemA[1]); teaserDivs.forEach((div) => div.after(document.createElement('span'))); teaserDivs.map((div) => div.nextSibling).forEach((anchor, index) => anchor.replaceWith(divValuePairs[index][0])); }; /* harmony default export */ var sort_teasers = ((containers, valueExpression) => { GM.setValue('sortValue', valueExpression); containers.forEach((container) => { sortContainer(container, valueExpression); }); external_log_["info"](`${containers.length} grids sorted`); }); // CONCATENATED MODULE: ./src/get_teaser_containers/index.ts /* harmony default export */ var get_teaser_containers = ((node) => { const containerSelector = '.views-responsive-grid, .node-playlist .field-name-field-videos'; return Array.from(node.querySelectorAll(containerSelector)) .filter((grid) => Boolean(grid.querySelector(teaser_element_selector))); }); // CONCATENATED MODULE: ./src/get_page_param/index.ts const getNumberParam = (URL_, name) => { const param = URL_.searchParams.get(name); return param ? Number.parseInt(param, 10) : 0; }; /* harmony default export */ var get_page_param = ((URL_) => getNumberParam(URL_, 'page')); // CONCATENATED MODULE: ./src/teaser_added_message/index.ts /* harmony default export */ var teaser_added_message = ('iwara custom sort: teasersAdded'); // CONCATENATED MODULE: ./src/init_parent/index.ts const changePageParam = (anchor, value) => { const anchorURL = new URL(anchor.href, window.location.href); anchorURL.searchParams.set('page', value.toString()); anchor.href = anchorURL.href; }; const groupCurrentPageItems = (currentPageItems) => { const parentItem = document.createElement('li'); currentPageItems[0].before(parentItem); currentPageItems[0].style.marginLeft = '0'; const groupList = document.createElement('ul'); groupList.style.display = 'inline'; groupList.style.backgroundColor = 'hsla(0, 0%, 75%, 50%)'; currentPageItems.forEach((item) => { item.classList.replace('pager-item', 'pager-current'); groupList.append(item); }); parentItem.append(groupList); }; const adjustPageAnchors = (container, pageCount) => { const currentPage = get_page_param(new URL(window.location.href)); if (currentPage > 0) { const previousPageAnchor = container.querySelector('.pager-previous a'); changePageParam(previousPageAnchor, Math.max(0, currentPage - pageCount)); } const nextPage = currentPage + pageCount; { const lastPageAnchor = container.querySelector('.pager-last a'); const nextPageAnchor = container.querySelector('.pager-next a'); if (nextPageAnchor) { changePageParam(nextPageAnchor, nextPage); } if (lastPageAnchor && get_page_param(new URL(lastPageAnchor.href, window.location.href)) < nextPage) { nextPageAnchor.remove(); lastPageAnchor.remove(); } } const currentPageAnchors = Array.from(container.querySelectorAll('.pager-item a')) .filter((anchor) => { const page = get_page_param(new URL(anchor.href, window.location.href)); return page >= currentPage && page < nextPage; }); if (currentPageAnchors.length > 0) { const currentPageItems = [ container.querySelector('.pager-current'), ...currentPageAnchors.map(({ parentElement }) => parentElement), ]; groupCurrentPageItems(currentPageItems); } }; const fixImages = () => { const brokenImages = get_teaser_containers(document).flatMap((container) => Array.from(container.querySelectorAll('img'))).filter((img) => img.complete && img.naturalWidth === 0); brokenImages.forEach((img) => { img.src = img.src; external_log_["info"]('Reload a broken image'); }); }; const createPages = (startURL, pageCount, userAgent) => { const currentURL = startURL; const params = currentURL.searchParams; const firstPage = get_page_param(currentURL); const pages = []; for (let currentPage = firstPage + 1; currentPage < firstPage + pageCount; currentPage += 1) { params.set('page', currentPage.toString()); const nextPage = (() => (document.createElement(userAgent.indexOf('Firefox') > -1 ? 'embed' : 'iframe')))(); nextPage.src = currentURL.toString(); nextPage.style.display = 'none'; pages.push(nextPage); external_log_["info"]('Add page:', nextPage.src); } return pages; }; /* harmony default export */ var init_parent = (async () => { const defaultSortValue = '(ratio / (private * 2.0 + 1) + Math.log(likes) / 250) / (image + 8.0)'; const initialSortValue = await GM.getValue('sortValue', defaultSortValue); const pageCount = await GM.getValue('pageCount', 1); const sortComponent = new sort_component(initialSortValue, defaultSortValue, pageCount); document.querySelector('#user-links').after(sortComponent.UI); if (get_teaser_containers(document).length === 0) { return; } const haveMorePages = document.querySelector('.pager') && !document.querySelector('#comments'); if (haveMorePages) { document.querySelectorAll('.pager').forEach((list) => adjustPageAnchors(list, pageCount)); } const pages = haveMorePages ? createPages(new URL(window.location.href), pageCount, window.navigator.userAgent) : []; sortComponent.sort$.subscribe((sortValue) => { try { sort_teasers(get_teaser_containers(document), sortValue); } catch (error) { external_Swal_default.a.fire('Sorting Failed', `An error accured while sorting: ${error.toString()}`); pages.forEach((page) => { page.src = ''; page.remove(); }); } }); const addPage$ = Object(external_rxjs_["fromEvent"])(window, 'message').pipe(Object(external_rxjs_operators_["filter"])((event) => (new URL(event.origin).hostname === window.location.hostname && event.data === teaser_added_message && pages.length > 0)), Object(external_rxjs_operators_["map"])((event) => event.source.frameElement)); addPage$.subscribe((element) => { element.src = ''; element.remove(); }); const addTeasers$ = addPage$.pipe(Object(external_rxjs_operators_["mapTo"])(0), Object(external_rxjs_operators_["startWith"])(0)); addTeasers$.subscribe(() => { sortComponent.sort(); sortComponent.addLoadedPageCount(); }); document.body.append(...pages); external_log_["debug"](pages); addTeasers$.pipe(Object(external_rxjs_operators_["mergeMap"])(() => Object(external_rxjs_["timer"])(0, 8000).pipe(Object(external_rxjs_operators_["take"])(2))), Object(external_rxjs_operators_["auditTime"])(6000)).subscribe(() => fixImages()); }); // CONCATENATED MODULE: ./src/timeout/index.ts /* harmony default export */ var timeout = ((delay) => new Promise((resolve) => { setTimeout(resolve, delay); })); // CONCATENATED MODULE: ./src/init_child/index.ts const addContainersToParents = (children, parents) => { const addContainerToParent = (child, parent) => { child.className = ''; parent.prepend(child); }; let i = 0; parents.forEach((parent) => { if (parent.className === children[i].className) { addContainerToParent(children[i], parent); i += 1; } }); }; /* harmony default export */ var init_child = (async () => { const teaserContainers = get_teaser_containers(document); if (teaserContainers.length === 0) { return; } await timeout(500); addContainersToParents(teaserContainers, get_teaser_containers(window.parent.document)); window.parent.postMessage(teaser_added_message, window.location.origin); }); // CONCATENATED MODULE: ./src/initialize/index.ts /* harmony default export */ var initialize = (async () => { const isParent = (window === window.parent); external_log_["debug"](`isParent: ${isParent}.`, window.location); await (isParent ? init_parent() : init_child()); }); // CONCATENATED MODULE: ./src/index.ts (async () => { external_log_["setLevel"]('trace'); external_log_["debug"](`Parsed: ${document.readyState}`); try { await initialize(); } catch (error) { external_log_["error"](error); } })(); /***/ }) /******/ ]);