Analvids/LegalPorno Enhancer

Adds extra functionality to Analvids (formerly known as LegalPorno) and Pornbox. Easily filter out unwanted categories. Also adds tags on top of every scene.

Устаревшая версия за 22.12.2021. Перейдите к последней версии.

  1. // ==UserScript==
  2. // @name Analvids/LegalPorno Enhancer
  3. // @namespace https://www.analvids.com/forum/viewtopic.php?f=96&t=24238
  4. // @description Adds extra functionality to Analvids (formerly known as LegalPorno) and Pornbox. Easily filter out unwanted categories. Also adds tags on top of every scene.
  5. // @match http*://*.analvids.com/*
  6. // @exclude http*://account.analvids.com/*
  7. // @match http*://*pornbox.com/*
  8. // @exclude http*://forum.pornbox.com/*
  9. // @version 1.2.16
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_addStyle
  13. // @run-at document-start
  14. // ==/UserScript==
  15.  
  16. const is_lp = !!window.location.href.match(/(analvids|pornworld)/);
  17.  
  18. let glo_filters = {
  19. studios: {
  20. 'Giorgio Grandi': true,
  21. 'Gonzo.com': true,
  22. 'NRX-Studio': true,
  23. "Giorgio's Lab": true,
  24. 'Yummy estudio': true,
  25. 'Busted T-Girls': true,
  26. 'VK Studio': true,
  27. 'Black in White': true,
  28. 'N&F studio': true,
  29. XfreaX: true,
  30. 'Interracial Vision': true,
  31. 'Angelo Godshack Original': true,
  32. 'Sineplex SOS': true,
  33. 'Sineplex CZ': true,
  34. 'PISSING E ANAL FANTASY': true,
  35. 'LATIN TEENS productions': true,
  36. 'Natasha Teen Productions': true,
  37. 'Mambo Perv': true,
  38. 'American Anal': true,
  39. 'Rock Corp': true,
  40. 'TheWonderToys Training Studio': true,
  41. 'Vira Gold Films': true,
  42. 'Anal Maniacs by Lady Dee': true,
  43. 'Eden does': true,
  44. 'Pineapples Studio': true,
  45. 'Porn World': false,
  46. 'Show Everything': false,
  47. },
  48. categories: {
  49. Piss: true,
  50. 'Piss Drink': true,
  51. Fisting: true,
  52. Prolapse: true,
  53. Trans: true,
  54. },
  55. };
  56.  
  57. const studio_colors = {
  58.  
  59. 'Gonzo.com': { bg: '#e90000a5', text: '#ffeeee' },
  60. 'Giorgio Grandi': { bg: '#2313d3a5', text: '#EEE' },
  61. 'Interracial Vision': { bg: '#242424a5', text: '#e6e6e6' },
  62. 'American Anal': { bg: '#0C5326a5', text: '#d1f3e8' },
  63. "Giorgio's Lab": { bg: '#3DB8DCa5', text: '#EEEEEE' },
  64. 'NRX-Studio': { bg: '#24f6d0a5', text: '#424d4b' },
  65. 'N&F studio': { bg: '#1091c4a5', text: '#EEEEEE' },
  66. 'Yummy estudio': { bg: '#0a11e4a5', text: '#ffff25' },
  67. 'Busted T-Girls': { bg: '#BDF619a5', text: '#3485A6' },
  68. 'VK Studio': { bg: '#d7fbaaa5', text: '#3a531b' },
  69. 'Black in White': { bg: '#EEEEEEa5', text: '#000000' },
  70. 'N&F studio': { bg: '#8D15CAa5', text: '#EEEEEE' },
  71. XfreaX: { bg: '#93076Aa5', text: '#EEEEEE' },
  72. 'Angelo Godshack Original': { bg: '#6ba2d4a5', text: '#EEEEEE' },
  73. 'Sineplex SOS': { bg: '#9C44EEa5', text: '#EEEEEE' },
  74. 'Sineplex CZ': { bg: '#8A0EB3a5', text: '#EEEEEE' },
  75. 'PISSING E ANAL FANTASY': { bg: '#ff5e00a5', text: '#fbf275' },
  76. 'LATIN TEENS productions': { bg: '#1AFB54a5', text: '#555555' },
  77. 'Natasha Teen Productions': { bg: '#EE1788a5', text: '#EEEEEE' },
  78. 'Mambo Perv': { bg: '#C729A5a5', text: '#EEEEEE' },
  79. 'Rock Corp': { bg: '#6D1644a5', text: '#83C650' },
  80. 'TheWonderToys Training Studio': { bg: '#ACEACFa5', text: '#5F546A' },
  81. 'Vira Gold Films': { bg: '#F7AF7Ca5', text: '#662a35' },
  82. 'Anal Maniacs by Lady Dee': { bg: '#4B7039a5', text: '#EEEEEE' },
  83. 'Eden does': { bg: '#378B03a5', text: '#EEEEEE' },
  84. 'Pineapples Studio': { bg: '#674ABAa5', text: '#EEEEEE' },
  85. 'Porn World': { bg: '#C1015Aa5', text: '#E2E316' },
  86. };
  87.  
  88. // Uncomment the following line to reset global filters
  89. // GM_setValue('user_filters', JSON.stringify(glo_filters));
  90.  
  91. validateUserFilters = filters => {
  92. if (!filters.studios || !filters.categories) return false;
  93. if (
  94. Object.keys(filters.studios).length !==
  95. Object.keys(glo_filters.studios).length
  96. )
  97. return false;
  98. if (
  99. Object.keys(filters.categories).length !==
  100. Object.keys(glo_filters.categories).length
  101. )
  102. return false;
  103. if (
  104. Object.keys(filters.categories)
  105. .sort()
  106. .some(
  107. (val, idx) => val !== Object.keys(glo_filters.categories).sort()[idx]
  108. )
  109. )
  110. return false;
  111. if (
  112. Object.keys(filters.studios)
  113. .sort()
  114. .some((val, idx) => val !== Object.keys(glo_filters.studios).sort()[idx])
  115. )
  116. return false;
  117. return true;
  118. };
  119.  
  120. try {
  121. const user_config = GM_getValue('user_filters');
  122. if (!user_config)
  123. throw new Error('No user filters found. Using default ones.');
  124. user_filters = JSON.parse(user_config);
  125. if (!validateUserFilters(user_filters))
  126. throw new Error('Invalid user settings.');
  127. glo_filters = user_filters;
  128. } catch (e) {}
  129.  
  130. const studios = {
  131. Interracial: 'Interracial Vision',
  132. 'Hard Porn World': 'Porn World',
  133. };
  134.  
  135. const icon_categories = {
  136. interracial: 'IR',
  137. 'double anal (DAP)': 'DAP',
  138. fisting: 'Fisting',
  139. prolapse: 'Prolapse',
  140. transsexual: 'Trans',
  141. trans: 'Trans',
  142. 'triple anal (TAP)': 'TAP',
  143. piss: 'Piss',
  144. squirting: 'Squirt',
  145. '3+ on 1': '3+on1',
  146. 'double vaginal (DPP)': 'DPP',
  147. 'first time': '1st',
  148. 'triple penetration': 'TP',
  149. '0% pussy': '0% Pussy',
  150. 'cum swallowing': 'Cum Swallow',
  151. 'piss drinking': 'Piss Drink',
  152. 'anal creampies': 'Anal Creampie',
  153. '1 on 1': '1on1',
  154. milf: 'Milf',
  155. 'facial cumshot': 'Facial',
  156. };
  157.  
  158. GM_addStyle(`
  159. .hiddenScene {
  160. display: none !important;
  161. }
  162.  
  163. .hide_element {
  164. display: none !important;
  165. }
  166.  
  167. .thumbnail-duration {
  168. top: 0 !important;
  169. right: 0 !important;
  170. left: unset !important;
  171. bottom: unset !important;
  172. margin: 5px !important;
  173. }
  174.  
  175. .enhanced_categories_container {
  176. width: 100%;
  177. display: flex;
  178. flex-wrap: wrap-reverse;
  179. position: absolute;
  180. bottom:0; left: 0;
  181. z-index: 3;
  182. padding: 3px 5px;
  183. }
  184.  
  185. .enchanced_icon {
  186. border-radius: 3px;
  187. background-color: #616161;
  188. color: #eee;
  189. opacity: 0.9;
  190. padding: 2px 7px;
  191. margin-right: 2px;
  192. margin-top: 2px;
  193. font-size: 13px;
  194. }
  195.  
  196. .enhanced--studio {
  197. position: absolute;
  198. top: 0;
  199. left: 0;
  200. z-index: 3;
  201. display: flex;
  202. margin: 4px 6px;
  203. font-family: sans-serif;
  204. font-weight: 600;
  205. font-size: 0.98em;
  206. background-color: #a76523c9;
  207. border-radius: 3px;
  208. padding: 2px 7px;
  209. color: white;
  210. // text-shadow: 1px 1px #00000080;
  211. margin-right: 4px;
  212. }
  213.  
  214. .enhanced_views_label {
  215. position: absolute;
  216. top: 28px;
  217. right: 5px;
  218. font-size: 11px;
  219. display: flex;
  220. }
  221.  
  222. .enhanced--views {
  223. background-color: rgba(102,102,102,0.6);
  224. padding: 2px 6px;
  225. border-radius: 3px;
  226. color: #fff;
  227. display: flex;
  228. height: 100%;
  229. align-items: center;
  230. justify-content: center;
  231. }
  232.  
  233. .enhanced--views > i {
  234. margin-right: 5px;
  235. }
  236.  
  237. .item__img:hover > div {
  238. display: none;
  239. }
  240.  
  241. .item__img-labels-bottom {
  242. top: 3px;
  243. right: 3px;
  244. left: unset;
  245. bottom: unset;
  246. display: flex
  247. }
  248.  
  249. .img-label {
  250. margin-top: unset;
  251. margin-left: 2px;
  252. }
  253.  
  254. .item__img-labels {
  255. display: flex;
  256. flex-direction: row-reverse;
  257. left: unset;
  258. right: 3px;
  259. top: 23px;
  260. }
  261.  
  262. /* Filter Css Begin */
  263. .filters_container_lp {
  264. margin-left: -15px;
  265. margin-right: -15px;
  266. }
  267.  
  268. .filters_container--main {
  269. width: 100%;
  270. display: flex;
  271. justify-content: center;
  272. background: linear-gradient(
  273. 0deg,
  274. #babcbc 0%,
  275. #dfe1e1 2%,
  276. #dfe1e1 98%,
  277. #babcbc 100%
  278. );
  279. }
  280.  
  281. .filters_card {
  282. margin: 0 25px;
  283. padding-bottom: 15px;
  284. display: flex;
  285. flex-direction: column;
  286. align-items: center;
  287. position: relative;
  288. }
  289.  
  290. .filters_selections {
  291. display: grid;
  292. grid-template-columns: repeat(3, 1fr);
  293. margin-bottom: 10px;
  294. }
  295.  
  296. .filters--divider {
  297. width: 1px;
  298. background-color: rgb(0, 0, 0, 0.25);
  299. height: 50px;
  300. margin-top: 15px;
  301. align-self: center;
  302. }
  303.  
  304. .filters--selection {
  305. padding: 1px 10px 0 0;
  306. min-width: 140px;
  307. display: flex;
  308. align-items: center;
  309. }
  310.  
  311. .filters--selection > label,
  312. .filters--selection > input[type="checkbox"] {
  313. margin: 0 2px 0 0;
  314. font-weight: bold;
  315. }
  316.  
  317. .fitlers--header {
  318. padding: 5px 0 5px 0;
  319. align-self: center;
  320. font-weight: bold;
  321. }
  322.  
  323. .enhanced_toggle {
  324. background: -webkit-linear-gradient(
  325. top,
  326. #a9a9a9 0%,
  327. #d97575 5%,
  328. #563434 100%
  329. ) !important;
  330. // height: 100%;
  331. border: 1px solid #722424 !important;
  332. color: white;
  333. padding: 7px 11px;
  334. font-weight: 700;
  335. border: none !important;
  336. }
  337.  
  338. .enhanced_toggle_pb {
  339. height: 100%;
  340. padding: 7px 11px;
  341. border-radius: 300px;
  342. position: absolute;
  343. margin-left: 4px;
  344. }
  345.  
  346. .enhanced_toggle_lp {
  347. border-radius: 200px;
  348. margin-left: 4px;
  349. }
  350.  
  351. .enhanced_toggle:hover {
  352. cursor: pointer;
  353. }
  354.  
  355. .enhanced_toggle > i {
  356. font-size: 12px;
  357. }
  358. /* Filter Css End */
  359.  
  360. .enhanced--sort {
  361. display: grid;
  362. grid-template-columns: 1fr 1fr;
  363. justify-items: center;
  364. grid-gap: 2px;
  365. position: absolute;
  366.  
  367. top: -4px;
  368. right: 210px;
  369. }
  370.  
  371. .enhanced--sort--navbar {
  372. right: 25px;
  373. top: 6px;
  374. }
  375.  
  376. .enhanced--sort > span {
  377. grid-column-end: span 2;
  378. color: #fff;
  379. }
  380.  
  381. .enhanced--sort > button {
  382. width: 70px;
  383. height: 23px;
  384. justify-content: center;
  385. align-items: center;
  386. text-align: center;
  387. padding: 0;
  388. margin: 0;
  389. }
  390.  
  391. .page-section {
  392. position: relative !important;
  393. }
  394. `);
  395.  
  396. const getSceneInfo = scene => {
  397. const info = {
  398. studio: null,
  399. categories: null,
  400. date: null,
  401. views: null,
  402. };
  403.  
  404. info.studio = scene.querySelector(
  405. '.rating-studio-name, a[href^="/application/studio/"]'
  406. );
  407. info.studio = info.studio ? info.studio.innerText : null;
  408. if (studios[info.studio]) {
  409. info.studio = studios[info.studio];
  410. }
  411. info.categories = [...scene.querySelectorAll('a[href*="niche/"]')]
  412. .filter(cat => cat.innerText && icon_categories[cat.innerText])
  413. .map(cat => icon_categories[cat.innerText])
  414. .sort();
  415. // info.categories = info.categories.filter(
  416. // cat => !(cat === 'Piss' && info.categories.includes('Piss Drink'))
  417. // );
  418. info.categories = Array.from(new Set(info.categories));
  419.  
  420. const views = scene.querySelector('.rating-views');
  421. const date = scene.querySelector('.glyphicon-calendar');
  422.  
  423. if (views) {
  424. info.views = parseInt(views.innerText.replace('VIEWS:', '').trim(), 10);
  425. }
  426. if (date) {
  427. try {
  428. info.date = new Date(
  429. date.parentElement.innerText.replace('RELEASE:', '').trim()
  430. );
  431. } catch (e) {}
  432. }
  433.  
  434. return info;
  435. };
  436.  
  437. const formatViews = n => {
  438. if (n >= 1e3 && n < 1e6) return +(n / 1e3).toFixed(0) + 'k';
  439. if (n >= 1e6 && n < 1e9) return +(n / 1e6).toFixed(0) + 'm';
  440. if (n >= 1e9 && n < 1e12) return +(n / 1e9).toFixed(0) + 'b';
  441. // if (n >= 1e12) return +(n / 1e12).toFixed(1) + "T";
  442. return n;
  443. };
  444.  
  445. const enhanceScene = scene => {
  446. // Remove icons from thumnail. ("4k" and "new")
  447. const icons = scene.querySelectorAll('.icon, .thumbnail-price');
  448. for (const icon of icons) {
  449. icon.classList.add('hide_element');
  450. }
  451.  
  452. const { studio, categories, views, date } = getSceneInfo(scene);
  453.  
  454. if (studio) {
  455. const studioLabel = document.createElement('div');
  456. studioLabel.classList.add('enhanced--studio');
  457. studioLabel.innerHTML = studio;
  458.  
  459. if (studio_colors[studio]) {
  460. studioLabel.style = `
  461. background-color: ${studio_colors[studio]['bg']}; color: ${studio_colors[studio]['text']};
  462. `;
  463. }
  464.  
  465. if (views) {
  466. const viewsLabel = document.createElement('div');
  467. viewsLabel.innerHTML = `
  468. <div class='enhanced--views'><i class='fa fa-eye'></i>${formatViews(
  469. views
  470. )}</div>`;
  471. viewsLabel.classList.add('enhanced_views_label');
  472. if (scene.querySelector('.thumbnail-image')) {
  473. scene.querySelector('.thumbnail-image').appendChild(viewsLabel);
  474. }
  475. }
  476.  
  477. // studioLabel.classList.add('enhanced_title_tags');
  478. scene
  479. .querySelector('.thumbnail-image, .item__img')
  480. .appendChild(studioLabel);
  481. }
  482. if (categories.length) {
  483. const cat_div = document.createElement('div');
  484. cat_div.classList.add('enhanced_categories_container');
  485. for (const cat of categories) {
  486. const icon = document.createElement('div');
  487. icon.classList.add('enchanced_icon');
  488. icon.innerHTML = cat;
  489. cat_div.appendChild(icon);
  490. }
  491.  
  492. if (scene.querySelector('.thumbnail-image, .item__img')) {
  493. scene.querySelector('.thumbnail-image, .item__img').appendChild(cat_div);
  494. }
  495. }
  496. };
  497.  
  498. const isStudioFiltered = studio => {
  499. for (const key of Object.keys(glo_filters.studios)) {
  500. if (studio && studio.includes(key) && glo_filters.studios[key])
  501. return false;
  502. }
  503. return true;
  504. };
  505.  
  506. const isSceneFiltered = scene => {
  507. const { studio, categories, views, date } = getSceneInfo(scene);
  508.  
  509. if (!glo_filters.studios['Show Everything']) {
  510. if (isStudioFiltered(studio)) return true;
  511. }
  512.  
  513. for (const key of Object.keys(glo_filters.categories)) {
  514. if (categories && categories.includes(key) && !glo_filters.categories[key])
  515. return true;
  516. }
  517.  
  518. return false;
  519. };
  520.  
  521. const filterScene = scene => {
  522. if (isSceneFiltered(scene)) {
  523. scene.classList.add('hiddenScene');
  524. }
  525. };
  526.  
  527. const updateFilters = () => {
  528. GM_setValue('user_filters', JSON.stringify(glo_filters));
  529. const scenes = document.querySelectorAll('.thumbnail, .block-item');
  530. for (const scene of scenes) {
  531. if (scene.classList.contains('hiddenScene'))
  532. scene.classList.remove('hiddenScene');
  533. filterScene(scene);
  534. }
  535. };
  536.  
  537. const getStudiosCheckboxes = () => {
  538. return [
  539. ...document.querySelectorAll(
  540. 'input[name="studios"]:not(input[id="Show Everything"])'
  541. ),
  542. ];
  543. };
  544.  
  545. const createFilterElement = () => {
  546. const { studios, categories } = glo_filters;
  547.  
  548. const studioHtml = Object.keys(studios).reduce(
  549. (acc, studio) =>
  550. (acc += `<div class="filters--selection">
  551. <input type="checkbox" name="studios" id="${studio}"
  552. ${studios[studio] ? 'checked="checked"' : ''}
  553. ${
  554. studios['Show Everything'] && studio !== 'Show Everything'
  555. ? 'disabled=true"'
  556. : ''
  557. }
  558. />
  559. <label for="${studio}"
  560. ${studio == 'Show Everything' ? 'style= "color:#f83600;"' : ''}>
  561. ${studio}</label>
  562. </div>`),
  563. ''
  564. );
  565.  
  566. const categoriesHtml = Object.keys(categories).reduce(
  567. (acc, cat) =>
  568. (acc += `<div class="filters--selection">
  569. <input type="checkbox" name="categories" id="${cat}"
  570. ${categories[cat] ? 'checked="checked"' : ''}
  571. />
  572. <label for="${cat}">${cat}</label>
  573. </div>`),
  574. ''
  575. );
  576.  
  577. const form = document.createElement('form');
  578. form.classList.add('filters_container', 'hide_element');
  579. if (is_lp) form.classList.add('filters_container_lp');
  580. form.innerHTML = `<div class="filters_container--main">
  581. <div class="filters_card">
  582. <div class="fitlers--header">Studios:</div>
  583. <div class="filters_selections">
  584. ${studioHtml}
  585. </div>
  586. <div>
  587. <input type="button" value="Select All">
  588. <input type="button" value="Clear">
  589. </div>
  590. </div>
  591. <!-- -->
  592. <div class="filters--divider"></div>
  593. <!-- -->
  594. <div class="filters_card">
  595. <div class="fitlers--header">Categories:</div>
  596. <div class="filters_selections">
  597. ${categoriesHtml}
  598. </div>
  599. </div>
  600. </div>`;
  601.  
  602. form.addEventListener('click', e => {
  603. if (!e.target.type) return;
  604.  
  605. if (e.target.type == 'button') {
  606. if (e.target.value === 'Select All') {
  607. getStudiosCheckboxes().forEach(n => {
  608. n.checked = true;
  609. });
  610.  
  611. Object.keys(glo_filters.studios).forEach(studio => {
  612. if (studio === 'Show Everything') return;
  613. glo_filters.studios[studio] = true;
  614. });
  615. }
  616. if (e.target.value === 'Clear') {
  617. getStudiosCheckboxes().forEach(n => {
  618. n.checked = false;
  619. });
  620. Object.keys(glo_filters.studios).forEach(studio => {
  621. glo_filters.studios[studio] = false;
  622. });
  623. }
  624. // glo_filters[e.target.name][e.target.id] = e.target.checked;
  625. }
  626.  
  627. if (e.target.type == 'checkbox') {
  628. glo_filters[e.target.name][e.target.id] = e.target.checked;
  629. }
  630.  
  631. if (e.target.id === 'Show Everything') {
  632. getStudiosCheckboxes().forEach(el => {
  633. el.disabled = !el.disabled;
  634. });
  635. }
  636.  
  637. updateFilters();
  638. });
  639.  
  640. const lp_header = document.querySelector('.header');
  641. const pb_header = document.querySelector('#wrap-container');
  642.  
  643. if (lp_header) lp_header.insertBefore(form, lp_header.childNodes[2]);
  644. if (pb_header) pb_header.insertBefore(form, pb_header.childNodes[0]);
  645. createFilterToggle();
  646. };
  647.  
  648. const createFilterToggle = () => {
  649. const toggleFilterBtn = document.createElement('button');
  650. toggleFilterBtn.classList.add('enhanced_toggle');
  651. toggleFilterBtn.classList.add(`enhanced_toggle_${is_lp ? 'lp' : 'pb'}`);
  652.  
  653. toggleFilterBtn.innerHTML = `<i class="fa fa-filter"></i>`;
  654.  
  655. toggleFilterBtn.addEventListener('click', () => {
  656. const filters_container = document.querySelector('.filters_container');
  657. if (filters_container) {
  658. filters_container.classList.toggle('hide_element');
  659. }
  660. });
  661.  
  662. const search_container = document.querySelector(
  663. '.nav-search-container, .header-block:nth-of-type(3)'
  664. );
  665. is_lp ? (search_container.style = 'display: flex;') : null;
  666. search_container.appendChild(toggleFilterBtn);
  667. };
  668.  
  669. const callback = mutationsList => {
  670. for (let mutation of mutationsList) {
  671. for (const node of mutation.addedNodes) {
  672. if (node.nodeType === 1) {
  673. if (node.nodeName === 'DIV') {
  674. if (
  675. node.classList.contains('block-item') ||
  676. node.classList.contains('thumbnail')
  677. ) {
  678. enhanceScene(node);
  679. filterScene(node);
  680. }
  681. }
  682. }
  683. }
  684. }
  685. };
  686.  
  687. const config = { childList: true, subtree: true, attributes: true };
  688. const observer = new MutationObserver(callback);
  689. observer.observe(window.document, config);
  690.  
  691. const sortScenes = ({ date = false, views = false, asc = true } = {}) => {
  692. const node = document.querySelector('.thumbnails');
  693. [...node.children]
  694. .sort((a, b) => {
  695. const infoA = getSceneInfo(a);
  696. const infoB = getSceneInfo(b);
  697.  
  698. let order = -1;
  699.  
  700. if (date) {
  701. order = infoA.date > infoB.date ? -1 : 1;
  702. } else if (views) {
  703. order = infoA.views > infoB.views ? -1 : 1;
  704. } else {
  705. order = 0;
  706. }
  707.  
  708. if (a.classList.contains('button--load-more')) return 0;
  709. if (b.classList.contains('button--load-more')) return 0;
  710.  
  711. return !asc ? order : order * -1;
  712. })
  713. .map(scene => {
  714. node.appendChild(scene);
  715. node.appendChild(document.createTextNode(' '));
  716. });
  717. };
  718.  
  719. const sortBtns = () => {
  720. const sortDiv = document.createElement('div');
  721. sortDiv.classList.add('enhanced--sort');
  722. sortDiv.innerHTML = `
  723. <span>Sort By:</span>
  724. <button asc="false">Date</button>
  725. <button asc="false">Views</button>
  726. `;
  727.  
  728. sortDiv.addEventListener('click', e => {
  729. if (e.target.tagName === 'BUTTON') {
  730. const asc = e.target.getAttribute('asc') === 'true';
  731. e.target.setAttribute('asc', !asc);
  732. const sortObj = { asc };
  733. sortObj[e.target.innerText.toLowerCase()] = true;
  734. sortScenes(sortObj);
  735. }
  736. });
  737.  
  738. const navbar = document.querySelectorAll('.navbar > .container-fluid');
  739. if (navbar.length) {
  740. navbar[navbar.length - 1].appendChild(sortDiv);
  741. sortDiv.classList.add('enhanced--sort--navbar');
  742. return;
  743. }
  744.  
  745. const cont = document.querySelector('.page-section');
  746. if (cont) {
  747. sortDiv.children[0].style = 'color: #000;';
  748. cont.appendChild(sortDiv);
  749. }
  750. };
  751.  
  752. document.addEventListener('DOMContentLoaded', () => {
  753. if (!is_lp && !document.querySelector('.nav-search-container')) return;
  754. createFilterElement();
  755. sortBtns();
  756.  
  757. const nodes = document.querySelectorAll('.block-item, .thumbnail');
  758. [...nodes].map(node => {
  759. enhanceScene(node);
  760. filterScene(node);
  761. });
  762. });