Greasy Fork is available in English.

Pogdesign-Widgets.js

Add the core object for the Pogdesign-Widgets.user.js

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greatest.deepsurf.us/scripts/35624/891915/Pogdesign-Widgetsjs.js

  1. /* eslint-disable max-lines */
  2. // @name Pogdesign-Widgets.require
  3. // @namespace https://github.com/fabiencrassat
  4. // @version 1.1.0
  5. // @description Add the core object for the Pogdesign-Widgets.user.js
  6. // @author Fabien Crassat <fabien@crassat.com>
  7.  
  8. /* global $, fabiencrassat */
  9. 'use strict';
  10.  
  11. const checkProtocol = function checkProtocol() {
  12. const http = 'http:';
  13. const httpLenght = http.length;
  14. const https = 'https:';
  15. if (location.protocol === http) {
  16. window.location.replace(https + window.location.href.substring(httpLenght));
  17. }
  18. };
  19. checkProtocol();
  20.  
  21. const mainTools = function mainTools() {
  22. const addZeroToOneNumber = function addZeroToOneNumber(number) {
  23. const maxNumberLenght = 2;
  24. if (number.length < maxNumberLenght) {
  25. return `0${number}`;
  26. }
  27. return number;
  28. };
  29. const cleanString = function cleanString(string) {
  30. return string
  31. .replace('.', '')
  32. .replace(':', '')
  33. .replace(/^The /gmui, '');
  34. };
  35. const encodeURL = function encodeURL(urlToEncode) {
  36. return encodeURIComponent(urlToEncode).replace(/'/gu, '%27');
  37. };
  38. const getPixelStyle = function getPixelStyle(key, value) {
  39. if (key && value) {
  40. return ` ${key}: ${value}px;`;
  41. }
  42. return '';
  43. };
  44.  
  45. return {
  46. addZeroToOneNumber,
  47. cleanString,
  48. encodeURL,
  49. getPixelStyle
  50. };
  51. };
  52.  
  53. // eslint-disable-next-line max-lines-per-function
  54. const model = function model() {
  55. const tools = fabiencrassat.mainTools;
  56.  
  57. const show = {
  58. episode: '',
  59. getEpisode() {
  60. return show.episode;
  61. },
  62. getSearch() {
  63. // eslint-disable-next-line max-len
  64. return `${show.getTitle().replace(/ /gmu, '.')}.${show.getSeasonAndEpisode()}`;
  65. },
  66. getSeason() {
  67. return show.season;
  68. },
  69. getSeasonAndEpisode() {
  70. return `S${show.getSeason()}E${show.getEpisode()}`;
  71. },
  72. getTitle() {
  73. return show.title;
  74. },
  75. season: '',
  76. setEpisode(episode) {
  77. show.episode = tools.addZeroToOneNumber(episode);
  78. },
  79. setSeason(season) {
  80. show.season = tools.addZeroToOneNumber(season);
  81. },
  82. setSeasonAndEpisode(...args) {
  83. const increment = 1;
  84. let maxArgsNumber = 1;
  85. if (args.length === maxArgsNumber) {
  86. // eslint-disable-next-line no-magic-numbers
  87. show.setSeasonAndEpisodeWithOneArgument(args[0]);
  88. return;
  89. }
  90. maxArgsNumber += increment;
  91. if (args.length === maxArgsNumber) {
  92. // eslint-disable-next-line no-magic-numbers
  93. show.setSeasonAndEpisodeWithTwoArgument(args[0], args[1]);
  94. return;
  95. }
  96. throw new RangeError('Exception in setSeasonAndEpisode');
  97. },
  98. setSeasonAndEpisodeWithOneArgument(seasonAndEpisode) {
  99. // eslint-disable-next-line prefer-named-capture-group
  100. const regex = /^s(\d{1,})e(\d{1,})/giu;
  101. show.setSeason(seasonAndEpisode.replace(regex, '$1'));
  102. show.setEpisode(seasonAndEpisode.replace(regex, '$2'));
  103. },
  104. setSeasonAndEpisodeWithTwoArgument(season, episode) {
  105. show.setSeason(season);
  106. show.setEpisode(episode);
  107. },
  108. setTitle(title) {
  109. show.title = tools.cleanString(title);
  110. },
  111. title: ''
  112. };
  113.  
  114. return {
  115. show: {
  116. getSearch: show.getSearch,
  117. getSeason: show.getSeason,
  118. getSeasonAndEpisode: show.getSeasonAndEpisode,
  119. getTitle: show.getTitle,
  120. setSeasonAndEpisode: show.setSeasonAndEpisode,
  121. setTitle: show.setTitle
  122. }
  123. };
  124. };
  125.  
  126. // eslint-disable-next-line max-lines-per-function
  127. const view = function view() {
  128. const tools = fabiencrassat.mainTools;
  129. const { show } = fabiencrassat.model;
  130.  
  131. let externalLinks = '';
  132. // eslint-disable-next-line max-len
  133. fetch('https://raw.githubusercontent.com/fabiencrassat/UserScripts/master/Pogdesign/require/externalLinks.json', {
  134. method: 'get'
  135. }).then(response => response.json())
  136. .then(data => {
  137. externalLinks = data;
  138. })
  139. .catch(err => console.error(err));
  140.  
  141. const popup = {
  142. buildUrl(url) {
  143. let buildUrl = url;
  144. // eslint-disable-next-line prefer-named-capture-group
  145. buildUrl = buildUrl.replace(
  146. /\$\{getSearch\}/gu,
  147. tools.encodeURL(show.getSearch())
  148. );
  149. buildUrl = buildUrl.replace(
  150. /\$\{getTitle\}/gu,
  151. tools.encodeURL(show.getTitle())
  152. );
  153. buildUrl = buildUrl.replace(
  154. /\$\{getSeasonAndEpisode\}/gu,
  155. tools.encodeURL(show.getSeasonAndEpisode())
  156. );
  157. return buildUrl;
  158. },
  159. close() {
  160. const container = popup.getContainer();
  161. if (container) {
  162. container.remove();
  163. }
  164. },
  165. create(cssClass, cssDisplay, { left, top } = {}) {
  166. const result = `
  167. <div
  168. id='${popup.popupId}'
  169. style='
  170. position: absolute;
  171. width: 350px;
  172. z-index: 97;
  173. display: ${cssDisplay};
  174. ${tools.getPixelStyle('top', top)}
  175. ${tools.getPixelStyle('left', left)}
  176. '
  177. class='
  178. cluetip
  179. ui-widget
  180. ui-widget-content
  181. ui-cluetip
  182. clue-right-default
  183. cluetip-default
  184. ${cssClass}
  185. '
  186. >
  187. <div class='cluetip-inner ui-widget-content ui-cluetip-content'>
  188. <div id='pop'>
  189. <div id='popheader'>
  190. <a
  191. class='fcr-closePopup'
  192. href='javascript:fabiencrassat.view.externalLinks.close();'
  193. >
  194. X
  195. </a>
  196. <span>${show.getTitle()} ${show.getSeasonAndEpisode()}</span>
  197. </div>
  198. <div id='poptext'>${popup.getLinks()}</div>
  199. <div id='popfooter'>${show.getSearch()}</div>
  200. </div>
  201. </div>
  202. </div>`;
  203. return result;
  204. },
  205. getContainer() {
  206. return $(`#${popup.popupId}`);
  207. },
  208. getLinks() {
  209. let links = '<span>';
  210. externalLinks.forEach(link => {
  211. links += `${link.name}: `;
  212. link.sites.forEach((site, index) => {
  213. const firstIndex = 0;
  214. if (index !== firstIndex) {
  215. links += ' | ';
  216. }
  217. links += `<a target="_blank" href="${this.buildUrl(site.url)}">
  218. ${site.name}
  219. </a>`;
  220. });
  221. links += '<br/>';
  222. }, links);
  223. links += '</span>';
  224. return links;
  225. },
  226. popupId: 'fcr-external-links-element',
  227. removeOnOutsideClickEvent() {
  228. $(document).mouseup(event => {
  229. const container = popup.getContainer();
  230. const noEventTarget = 0;
  231. // If the target of the click isn't the container
  232. // Nor a descendant of the container
  233. if (!container.is(event.target) &&
  234. container.has(event.target).length === noEventTarget) {
  235. this.close();
  236. }
  237. });
  238. }
  239. };
  240.  
  241. return {
  242. externalLinks: {
  243. close: popup.close,
  244. create: popup.create,
  245. removeOnOutsideClickEvent: popup.removeOnOutsideClickEvent
  246. }
  247. };
  248. };
  249.  
  250. // eslint-disable-next-line max-lines-per-function
  251. const main = function main() {
  252. const { externalLinks } = fabiencrassat.view;
  253. const { show } = fabiencrassat.model;
  254.  
  255. const page = {
  256. controller: {
  257. addExternalLink(pageElement, element) {
  258. if (!page.controller.canAddExternalLink(
  259. pageElement.isInLocationPage,
  260. element
  261. )) {
  262. return;
  263. }
  264. page.controller.insertStylesheets(page.shared.stylesheets(pageElement));
  265. pageElement.insertExternalLink(element);
  266. page.controller.loadClickEventOnLinkElement(pageElement);
  267. },
  268. canAddExternalLink(isInLocationPage, element) {
  269. if (!isInLocationPage()) {
  270. return false;
  271. }
  272. const noElementValue = 0;
  273. if ($(element).length === noElementValue) {
  274. return false;
  275. }
  276. return true;
  277. },
  278. extractSeasonAndEpisode(pageElement, element) {
  279. const seasonAndEpisode = pageElement.extractSeasonAndEpisode(element);
  280. if (typeof seasonAndEpisode === 'string') {
  281. show.setSeasonAndEpisode(seasonAndEpisode);
  282. return;
  283. }
  284. show.setSeasonAndEpisode(
  285. seasonAndEpisode.season,
  286. seasonAndEpisode.episode
  287. );
  288. },
  289. extractShow(pageElement, element) {
  290. page.controller.extractTitle(pageElement, element);
  291. page.controller.extractSeasonAndEpisode(pageElement, element);
  292. },
  293. extractTitle(pageElement, element) {
  294. const title = $.trim(pageElement.extractTitle(element));
  295. show.setTitle(title);
  296. },
  297. getExternalLinksPopup(pageElement, element) {
  298. page.controller.extractShow(pageElement, element);
  299. pageElement.displayExternalLinksPopup(element);
  300. },
  301. insertStylesheets(stylesheets) {
  302. const style = document.createElement('style');
  303. style.appendChild(document.createTextNode(stylesheets));
  304. (document.body || document.head || document.documentElement)
  305. .appendChild(style);
  306. },
  307. isInLocationPage(regex) {
  308. return regex.test(window.location.href);
  309. },
  310. loadClickEventOnLinkElement(pageElement) {
  311. $(`.${page.shared.externalLinksLinkClass}`)
  312. .on('click', function onClick(event) {
  313. event.preventDefault();
  314. externalLinks.close();
  315. // eslint-disable-next-line no-invalid-this
  316. page.controller.getExternalLinksPopup(pageElement, $(this));
  317. });
  318. externalLinks.removeOnOutsideClickEvent();
  319. }
  320. },
  321. shared: {
  322. externalImageLink() {
  323. return page.shared.externalLink('fcr-externalLink-image', '');
  324. },
  325. externalLink(classText, linkText) {
  326. return `<a
  327. href="javascript:void(0)"
  328. class="${page.shared.externalLinksLinkClass} ${classText}">
  329. ${linkText}
  330. </a>`;
  331. },
  332. externalLinksLinkClass: 'fcr-externalLinksLink',
  333. externalTextLink() {
  334. return page.shared.externalLink('', '&lt;Links&gt;');
  335. },
  336. // eslint-disable-next-line max-len
  337. linkImage: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTM0A1t6AAAA20lEQVQoU33RuQrCQBDG8YgHeIIHinhgZyNWgg8iCoqIpW/jg5nG0oew8b7j/wsZCSkM/Nbs7MzuuHE8z/snhlxIyhbaGEb0MMAb9myUvMAJR1xwxQEvJLCCPVsVKKGOMqqBAipIw8UTOskv0E55WHtGyRsocYYlXC3cUEQ0WTsrWS1bPKNBx9VCQSXv8MEEHZTgr2t4oGkBdKFLGAdz/cd58O4XnBFtKRN6V8tTm2tQS7pvSwjTh9tjZDENfehY7XSHbk2/immzNVT4K5A4smghGcwb0DexHHjOFwrY3c0uEFwZAAAAAElFTkSuQmCC',
  338. stylesheets(pageElement) {
  339. return `a.fcr-closePopup {
  340. float: right;
  341. color: #66bbff !important;
  342. }${pageElement.stylesheets()}`;
  343. }
  344. }
  345. };
  346.  
  347. return {
  348. controller: {
  349. addExternalLink: page.controller.addExternalLink,
  350. isInLocationPage: page.controller.isInLocationPage
  351. },
  352. shared: {
  353. externalImageLink: page.shared.externalImageLink,
  354. externalTextLink: page.shared.externalTextLink,
  355. linkImage: page.shared.linkImage
  356. }
  357. };
  358. };
  359.  
  360. const fcrScriptElement = document.createElement('script');
  361. const initFcrScript = function initFcrScript(strValue, value) {
  362. return `var fabiencrassat = fabiencrassat || {};
  363. fabiencrassat.${strValue} = (${value})();`;
  364. };
  365. fcrScriptElement
  366. .appendChild(document.createTextNode(initFcrScript('mainTools', mainTools)));
  367. fcrScriptElement
  368. .appendChild(document.createTextNode(initFcrScript('model', model)));
  369. fcrScriptElement
  370. .appendChild(document.createTextNode(initFcrScript('view', view)));
  371. fcrScriptElement
  372. .appendChild(document.createTextNode(initFcrScript('main', main)));
  373. (document.body || document.head || document.documentElement)
  374. .appendChild(fcrScriptElement);