Pixiv Previewer

显示预览图(支持单图,多图,动图);动图压缩包下载;搜索页按热门度(收藏数)排序并显示收藏数,适配11月更新

目前为 2019-12-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Pixiv Previewer
  3. // @namespace https://github.com/Ocrosoft/PixivPreviewer
  4. // @version 3.0.10
  5. // @description 显示预览图(支持单图,多图,动图);动图压缩包下载;搜索页按热门度(收藏数)排序并显示收藏数,适配11月更新
  6. // @author Ocrosoft
  7. // @match *://www.pixiv.net/*
  8. // @grant none
  9. // @compatible Chrome
  10. // ==/UserScript==
  11.  
  12. // 测试 JQuery,如果不支持就插入
  13. //var $ = function () { };
  14. try {
  15. $();
  16. } catch (e) {
  17. var script = document.createElement('script');
  18. script.src = 'https://code.jquery.com/jquery-2.2.4.min.js';
  19. document.head.appendChild(script);
  20. }
  21.  
  22. var Languages = {
  23. // 中文-中国大陆
  24. zh_CN: 0,
  25. // 英语-美国
  26. en_US: 1,
  27. };
  28. var LogLevel = {
  29. None: 0,
  30. Error: 1,
  31. Warning: 2,
  32. Info: 3,
  33. Elements: 4,
  34. };
  35. function DoLog(level, msgOrElement) {
  36. if (level <= g_logLevel) {
  37. var prefix = '%c';
  38. var param = '';
  39.  
  40. if (level == LogLevel.Error) {
  41. prefix += '[Error]';
  42. param = 'color:#ff0000';
  43. } else if (level == LogLevel.Warning) {
  44. prefix += '[Warning]';
  45. param = 'color:#ffa500';
  46. } else if (level == LogLevel.Info) {
  47. prefix += '[Info]';
  48. param = 'color:#000000';
  49. } else if (level == LogLevel.Elements) {
  50. prefix += 'Elements';
  51. param = 'color:#000000';
  52. }
  53.  
  54. if (level != LogLevel.Elements) {
  55. console.log(prefix + msgOrElement, param);
  56. } else {
  57. console.log(msgOrElement);
  58. }
  59.  
  60. if (++g_logCount > 512) {
  61. console.clear();
  62. g_logCount = 0;
  63. }
  64. }
  65. }
  66.  
  67. // 版本号,第三位不需要跟脚本的版本号对上,第三位更新只有需要弹更新提示的时候才需要更新这里
  68. var g_version = '3.0.6';
  69. // 添加收藏需要这个
  70. var g_csrfToken = '';
  71. // 打的日志数量,超过一定数值清空控制台
  72. var g_logCount = 0;
  73. // 当前页面类型
  74. var g_pageType = -1;
  75. // 图片详情页的链接,使用时替换 #id#
  76. var g_artworkUrl = '/artworks/#id#';
  77. // 获取图片链接的链接
  78. var g_getArtworkUrl = '/ajax/illust/#id#/pages';
  79. // 获取动图下载链接的链接
  80. var g_getUgoiraUrl = '/ajax/illust/#id#/ugoira_meta';
  81. // 鼠标位置
  82. var g_mousePos = { x: 0, y: 0 };
  83. // 加载中图片
  84. var g_loadingImage = 'https://pp-1252089172.cos.ap-chengdu.myqcloud.com/loading.gif';
  85. // 页面打开时的 url
  86. var initialUrl = location.href;
  87. // 默认设置,仅用于首次脚本初始化
  88. var g_defaultSettings = {
  89. 'enablePreview': 1,
  90. 'enableSort': 1,
  91. 'enableAnimeDownload': 1,
  92. 'original': 0,
  93. 'pageCount': 2,
  94. 'favFilter': 0,
  95. 'hideFavorite': 0,
  96. 'linkBlank': 1,
  97. 'pageByKey': 0,
  98. 'logLevel': 1,
  99. 'version': g_version,
  100. };
  101. // 设置
  102. var g_settings;
  103. // 日志等级
  104. var g_logLevel = LogLevel.Warning;
  105. // 排序时同时请求收藏量的 Request 数量,没必要太多,并不会加快速度
  106. var g_maxXhr = 10;
  107.  
  108. // 页面相关的一些预定义,包括处理页面元素等
  109. var PageType = {
  110. // 搜索
  111. Search: 0,
  112. // 关注的新作品
  113. BookMarkNew: 1,
  114. // 发现
  115. Discovery: 2,
  116. // 用户主页
  117. Member: 3,
  118. // 首页
  119. Home: 4,
  120. // 排行榜
  121. Ranking: 5,
  122. // 大家的新作品
  123. NewIllust: 6,
  124. // R18
  125. R18: 7,
  126. // 自己的收藏页
  127. BookMark: 8,
  128. // 动态
  129. Stacc: 9,
  130. // 作品详情页(处理动图预览及下载)
  131. Artwork: 10,
  132.  
  133. // 总数
  134. PageTypeCount: 11,
  135. };
  136. var Pages = {};
  137. /* Pages 必须实现的函数
  138. * PageTypeString: string,字符串形式的 PageType
  139. * bool CheckUrl: function(string url),用于检查一个 url 是否是当前页面的目标 url
  140. * ReturnMap ProcessPageElements: function(),处理页面(寻找图片元素、添加属性等),返回 ReturnMap
  141. * ReturnMap GetProcessedPageElements: function(), 返回上一次 ProcessPageElements 的返回值(如果没有上次调用则调用一次)
  142. * Object GetToolBar: function(), 返回工具栏元素(右下角那个,用来放设置按钮)
  143. * HasAutoLoad: bool,表示这个页面是否有自动加载功能
  144. */
  145. var ReturnMapSample = {
  146. // 页面是否加载完成,false 意味着后面的成员无效
  147. loadingComplete: false,
  148. // 控制元素,每个图片的鼠标响应元素
  149. controlElements: [],
  150. };
  151. var ControlElementsAttributesSample = {
  152. // 图片信息,内容如下:
  153. // [必需] 图片 id
  154. illustId: 0,
  155. // [必需] 图片类型(0:普通图片,2:动图)
  156. illustType: 0,
  157. // [必需] 页数
  158. pageCount: 1,
  159. // [可选] 标题
  160. title: '',
  161. // [可选] 作者 id
  162. userId: 0,
  163. // [可选] 作者昵称
  164. userName: '',
  165. // [可选] 收藏数
  166. bookmarkCount: 0,
  167. };
  168.  
  169. Pages[PageType.Search] = {
  170. PageTypeString: 'SearchPage',
  171. CheckUrl: function (url) {
  172. return /^https?:\/\/www.pixiv.net\/tags\/.*\/artworks/.test(url) ||
  173. /^https?:\/\/www.pixiv.net\/en\/tags\/.*\/artworks/.test(url);
  174. },
  175. ProcessPageElements: function () {
  176. var returnMap = {
  177. loadingComplete: false,
  178. controlElements: [],
  179. };
  180.  
  181. var sections = $('section');
  182. DoLog(LogLevel.Info, 'Page has ' + sections.length + ' <section>.');
  183. DoLog(LogLevel.Elements, sections);
  184. // 先对 section 进行评分
  185. var sectionIndex = -1;
  186. var bestScore = -99;
  187. sections.each(function (i, e) {
  188. var section = $(e);
  189. var score = 0;
  190. if (section.find('ul').length > 0) {
  191. var childrenCount = section.children().length;
  192. if (childrenCount != 2) {
  193. DoLog(LogLevel.Warning, '<ul> was found in this <section>, but it has ' + childrenCount + ' children!');
  194. score--;
  195. }
  196. var ul = section.find('ul');
  197. if (ul.length > 1) {
  198. DoLog(LogLevel.Warning, 'This section has more than one <ul>?');
  199. score--;
  200. }
  201. if ($(ul.parent().get(0)).css('display') == 'none' || $(ul.get(0)).css('display') == 'none') {
  202. DoLog(LogLevel.Info, '<ul> or it\'s parentNode is not visible now, continue waiting.');
  203. sectionIndex = -1;
  204. bestScore = 999;
  205. return false;
  206. }
  207. if ($(ul.get(0)).next().length === 0) {
  208. DoLog(LogLevel.Info, 'Page selector not exists, continue waiting.');
  209. sectionIndex = -1;
  210. bestScore = 999;
  211. return false;
  212. }
  213. var lis = ul.find('li');
  214. if (lis.length === 0) {
  215. DoLog(LogLevel.Info, 'This <ul> has 0 children, will be skipped.');
  216. return false;
  217. }
  218. if ($(lis.get(0)).find('figure').length > 0) {
  219. DoLog(LogLevel.Warning, '<figure> was found in the first <li>, continue waiting.');
  220. sectionIndex = -1;
  221. bestScore = 999;
  222. return false;
  223. }
  224. if (lis.length > 4) {
  225. score += 5;
  226. }
  227. if (score > bestScore) {
  228. bestScore = score;
  229. sectionIndex = i;
  230. }
  231. } else {
  232. DoLog(LogLevel.Info, 'This section(' + i + ' is not has <ul>, will be skipped.');
  233. }
  234. });
  235.  
  236. if (sectionIndex == -1) {
  237. if (bestScore < 100) {
  238. DoLog(LogLevel.Error, 'No suitable <section>!');
  239. }
  240. return returnMap;
  241. }
  242.  
  243. var lis = $(sections[sectionIndex]).find('ul').find('li');
  244. lis.each(function (i, e) {
  245. var li = $(e);
  246. var control = li.children('div:first');
  247.  
  248. // 只填充必须的几个,其他的目前用不着
  249. var ctlAttrs = {
  250. illustId: 0,
  251. illustType: 0,
  252. pageCount: 1,
  253. };
  254.  
  255. var img = $(li.find('img').get(0));
  256. var imageLink = img.parent().parent();
  257. var additionDiv = img.parent().prev();
  258. var animationSvg = img.parent().find('svg');
  259. var pageCountSpan = additionDiv.find('span');
  260.  
  261. if (img == null || imageLink == null) {
  262. DoLog(LogLevel.Warning, 'Can not found img or imageLink, skip this.');
  263. return;
  264. }
  265.  
  266. var link = imageLink.attr('href');
  267. if (link == null) {
  268. DoLog(LogLevel.Warning, 'Invalid href, skip this.');
  269. return;
  270. }
  271. var linkMatched = link.match(/artworks\/(\d+)/);
  272. var illustId = '';
  273. if (linkMatched) {
  274. ctlAttrs.illustId = linkMatched[1];
  275. } else {
  276. DoLog(LogLevel.Error, 'Get illustId failed, skip this list item!');
  277. return;
  278. }
  279. if (animationSvg.length > 0) {
  280. ctlAttrs.illustType = 2;
  281. }
  282. if (pageCountSpan.length > 0) {
  283. ctlAttrs.pageCount = parseInt(pageCountSpan.text());
  284. }
  285.  
  286. // 添加 attr
  287. li.attr({
  288. 'illustId': ctlAttrs.illustId,
  289. 'illustType': ctlAttrs.illustType,
  290. 'pageCount': ctlAttrs.pageCount
  291. });
  292.  
  293. li.addClass('pp-control');
  294. });
  295. returnMap.controlElements = $('.pp-control');
  296. this.private.pageSelector = $($(sections[sectionIndex]).find('ul').get(0)).next().get(0);
  297. returnMap.loadingComplete = true;
  298. this.private.imageListConrainer = $(sections[sectionIndex]).find('ul').get(0);
  299.  
  300. DoLog(LogLevel.Info, 'Process page elements complete.');
  301. DoLog(LogLevel.Elements, returnMap);
  302.  
  303. this.private.returnMap = returnMap;
  304. return returnMap;
  305. },
  306. GetProcessedPageElements: function () {
  307. if (this.private.returnMap == null) {
  308. return this.ProcessPageElements();
  309. }
  310. return this.private.returnMap;
  311. },
  312. GetToolBar: function () {
  313. return $('#root').children('div:last').prev().find('li:first').parent().get(0);
  314. },
  315. // 搜索页有 lazyload,不开排序的情况下,最后几张图片可能会无法预览。这里把它当做自动加载处理
  316. HasAutoLoad: true,
  317. GetImageListContainer: function () {
  318. return this.private.imageListConrainer;
  319. },
  320. GetFirstImageElement: function () {
  321. return $(this.private.imageListConrainer).find('li').get(0);
  322. },
  323. GetPageSelector: function () {
  324. return this.private.pageSelector;
  325. },
  326. private: {
  327. imageListContainer: null,
  328. pageSelector: null,
  329. returnMap: null,
  330. },
  331. };
  332. Pages[PageType.BookMarkNew] = {
  333. PageTypeString: 'BookMarkNewPage',
  334. CheckUrl: function (url) {
  335. return /^https:\/\/www.pixiv.net\/bookmark_new_illust.php.*/.test(url);
  336. },
  337. ProcessPageElements: function () {
  338. var returnMap = {
  339. loadingComplete: false,
  340. controlElements: [],
  341. };
  342.  
  343. var containerDiv = $('#js-mount-point-latest-following').children('div:first');
  344. if (containerDiv.length > 0) {
  345. DoLog(LogLevel.Info, 'Found container div.');
  346. DoLog(LogLevel.Elements, containerDiv);
  347. } else {
  348. DoLog(LogLevel.Error, 'Can not found container div.');
  349. return returnMap;
  350. }
  351.  
  352. containerDiv.children().each(function (i, e) {
  353. var _this = $(e);
  354.  
  355. var figure = _this.find('figure');
  356. if (figure.length === 0) {
  357. DoLog(LogLevel.Warning, 'Can not found <fingure>, skip this element.');
  358. return;
  359. }
  360.  
  361. var link = figure.children('div:first').children('a:first');
  362. if (link.length === 0) {
  363. DoLog(LogLevel.Warning, 'Can not found <a>, skip this element.');
  364. return;
  365. }
  366.  
  367. var ctlAttrs = {
  368. illustId: 0,
  369. illustType: 0,
  370. pageCount: 1,
  371. };
  372.  
  373. var href = link.attr('href');
  374. if (href == null || href === '') {
  375. DoLog(LogLevel.Warning, 'No href found, skip.');
  376. return;
  377. } else {
  378. var matched = href.match(/artworks\/(\d+)/);
  379. if (matched) {
  380. ctlAttrs.illustId = matched[1];
  381. } else {
  382. DoLog(LogLevel.Warning, 'Can not found illust id, skip.');
  383. return;
  384. }
  385. }
  386.  
  387. if (link.children().length > 1) {
  388. if (link.children('div:first').find('span').length > 0) {
  389. var span = link.children('div:first').children('span:first');
  390. if (span.length === 0) {
  391. DoLog(LogLevel.Warning, 'Can not found <span>, skip this element.');
  392. return;
  393. }
  394. ctlAttrs.pageCount = span.text();
  395. } else {
  396. ctlAttrs.illustType = 2;
  397. }
  398. }
  399.  
  400. _this.attr({
  401. 'illustId': ctlAttrs.illustId,
  402. 'illustType': ctlAttrs.illustType,
  403. 'pageCount': ctlAttrs.pageCount
  404. });
  405.  
  406. returnMap.controlElements.push(e);
  407. });
  408.  
  409. DoLog(LogLevel.Info, 'Process page elements complete.');
  410. DoLog(LogLevel.Elements, returnMap);
  411.  
  412. returnMap.loadingComplete = true;
  413. this.private.returnMap = returnMap;
  414. return returnMap;
  415. },
  416. GetProcessedPageElements: function () {
  417. if (this.private.returnMap == null) {
  418. return this.ProcessPageElements();
  419. }
  420. return this.private.returnMap;
  421. },
  422. GetToolBar: function () {
  423. return $('._toolmenu').get(0);
  424. },
  425. HasAutoLoad: false,
  426. private: {
  427. returnMap: null,
  428. },
  429. };
  430. Pages[PageType.Discovery] = {
  431. PageTypeString: 'DiscoveryPage',
  432. CheckUrl: function (url) {
  433. return /^https?:\/\/www.pixiv.net\/discovery.*/.test(url);
  434. },
  435. ProcessPageElements: function () {
  436. var returnMap = {
  437. loadingComplete: false,
  438. controlElements: [],
  439. };
  440.  
  441. var containerDiv = $('.gtm-illust-recommend-zone');
  442. if (containerDiv.length > 0) {
  443. DoLog(LogLevel.Info, 'Found container div.');
  444. DoLog(LogLevel.Elements, containerDiv);
  445. } else {
  446. DoLog(LogLevel.Error, 'Can not found container div.');
  447. return returnMap;
  448. }
  449.  
  450. containerDiv.children().each(function (i, e) {
  451. var _this = $(e);
  452.  
  453. var figure = _this.find('figure');
  454. if (figure.length === 0) {
  455. DoLog(LogLevel.Warning, 'Can not found <fingure>, skip this element.');
  456. return;
  457. }
  458.  
  459. var link = figure.children('div:first').children('a:first');
  460. if (link.length === 0) {
  461. DoLog(LogLevel.Warning, 'Can not found <a>, skip this element.');
  462. return;
  463. }
  464.  
  465. var ctlAttrs = {
  466. illustId: 0,
  467. illustType: 0,
  468. pageCount: 1,
  469. };
  470.  
  471. var href = link.attr('href');
  472. if (href == null || href === '') {
  473. DoLog(LogLevel.Warning, 'No href found, skip.');
  474. return;
  475. } else {
  476. var matched = href.match(/artworks\/(\d+)/);
  477. if (matched) {
  478. ctlAttrs.illustId = matched[1];
  479. } else {
  480. DoLog(LogLevel.Warning, 'Can not found illust id, skip.');
  481. return;
  482. }
  483. }
  484.  
  485. if (link.children().length > 1) {
  486. if (link.children('div:first').find('span').length > 0) {
  487. var span = link.children('div:first').children('span:first');
  488. if (span.length === 0) {
  489. DoLog(LogLevel.Warning, 'Can not found <span>, skip this element.');
  490. return;
  491. }
  492. ctlAttrs.pageCount = span.text();
  493. } else if (link.children('div:last').find('svg').length > 0) {
  494. ctlAttrs.illustType = 2;
  495. }
  496. }
  497.  
  498. _this.attr({
  499. 'illustId': ctlAttrs.illustId,
  500. 'illustType': ctlAttrs.illustType,
  501. 'pageCount': ctlAttrs.pageCount
  502. });
  503.  
  504. returnMap.controlElements.push(e);
  505. });
  506.  
  507. DoLog(LogLevel.Info, 'Process page elements complete.');
  508. DoLog(LogLevel.Elements, returnMap);
  509.  
  510. returnMap.loadingComplete = true;
  511. this.private.returnMap = returnMap;
  512. return returnMap;
  513. },
  514. GetProcessedPageElements: function () {
  515. if (this.private.returnMap == null) {
  516. return this.ProcessPageElements();
  517. }
  518. return this.private.returnMap;
  519. },
  520. GetToolBar: function () {
  521. return $('._toolmenu').get(0);
  522. },
  523. HasAutoLoad: true,
  524. private: {
  525. returnMap: null,
  526. },
  527. };
  528. Pages[PageType.Member] = {
  529. PageTypeString: 'MemberPage/MemberIllustPage/MemberBookMark',
  530. CheckUrl: function (url) {
  531. return /^https?:\/\/www.pixiv.net\/member.php\?id=.*/.test(url) ||
  532. /^https:\/\/www.pixiv.net\/member_illust.php.*/.test(url) ||
  533. /^https:\/\/www.pixiv.net\/bookmark.php\?.*/.test(url);
  534. },
  535. ProcessPageElements: function () {
  536. var returnMap = {
  537. loadingComplete: false,
  538. controlElements: [],
  539. };
  540.  
  541. var sections = $('section');
  542. DoLog(LogLevel.Info, 'Page has ' + sections.length + ' <section>.');
  543. DoLog(LogLevel.Elements, sections);
  544.  
  545. var lis = sections.find('ul').find('li');
  546. lis.each(function (i, e) {
  547. var li = $(e);
  548. var control = li.children('div:first');
  549.  
  550. // 只填充必须的几个,其他的目前用不着
  551. var ctlAttrs = {
  552. illustId: 0,
  553. illustType: 0,
  554. pageCount: 1,
  555. };
  556.  
  557. var img = $(li.find('img').get(0));
  558. var imageLink = img.parent().parent();
  559. var additionDiv = img.parent().prev();
  560. var animationSvg = img.parent().find('svg');
  561. var pageCountSpan = additionDiv.find('span');
  562.  
  563. if (!img || !imageLink) {
  564. DoLog(LogLevel.Warning, 'Can not found img or imageLink, skip this.');
  565. return;
  566. }
  567.  
  568. var link = imageLink.attr('href');
  569. if (link == null) {
  570. DoLog(LogLevel.Warning, 'Can not found illust id, skip this.');
  571. return;
  572. }
  573.  
  574. var linkMatched = link.match(/artworks\/(\d+)/);
  575. var illustId = '';
  576. if (linkMatched) {
  577. ctlAttrs.illustId = linkMatched[1];
  578. } else {
  579. DoLog(LogLevel.Error, 'Get illustId failed, skip this list item!');
  580. return;
  581. }
  582. if (animationSvg.length > 0) {
  583. ctlAttrs.illustType = 2;
  584. }
  585. if (pageCountSpan.length > 0) {
  586. ctlAttrs.pageCount = parseInt(pageCountSpan.text());
  587. }
  588.  
  589. // 添加 attr
  590. li.attr({
  591. 'illustId': ctlAttrs.illustId,
  592. 'illustType': ctlAttrs.illustType,
  593. 'pageCount': ctlAttrs.pageCount
  594. });
  595.  
  596. li.addClass('pp-control');
  597. });
  598. returnMap.controlElements = $('.pp-control');
  599. returnMap.loadingComplete = true;
  600.  
  601. DoLog(LogLevel.Info, 'Process page elements complete.');
  602. DoLog(LogLevel.Elements, returnMap);
  603.  
  604. this.private.returnMap = returnMap;
  605. return returnMap;
  606. },
  607. GetProcessedPageElements: function () {
  608. if (this.private.returnMap == null) {
  609. return this.ProcessPageElements();
  610. }
  611. return this.private.returnMap;
  612. },
  613. GetToolBar: function () {
  614. var div = $('#root').children('div');
  615. for (var i = div.length - 1; i >= 0; i--) {
  616. if ($(div.get(i)).children('ul').length > 0) {
  617. return $(div.get(i)).children('ul').get(0);
  618. }
  619. }
  620. },
  621. // 跟搜索页一样的情况
  622. HasAutoLoad: true,
  623. private: {
  624. returnMap: null,
  625. },
  626. };
  627. Pages[PageType.Home] = {
  628. PageTypeString: 'HomePage',
  629. CheckUrl: function (url) {
  630. return /https?:\/\/www.pixiv.net\/?$/.test(url) ||
  631. /https?:\/\/www.pixiv.net\/en\/?$/.test(url);
  632. },
  633. ProcessPageElements: function () {
  634. var returnMap = {
  635. loadingComplete: false,
  636. controlElements: [],
  637. };
  638.  
  639. var uls = $('._image-items');
  640.  
  641. DoLog(LogLevel.Info, 'This page has ' + uls.length + ' <ul>.');
  642. if (uls.length < 1) {
  643. DoLog(LogLevel.Warning, 'Less than 1 <ul>, continue waiting.');
  644. return returnMap;
  645. } else if (uls.length != 4) {
  646. DoLog(LogLevel.Warning, 'Normaly, should found 4 <ul>.');
  647. }
  648.  
  649. uls.each(function (i, e) {
  650. var _this = $(e);
  651.  
  652. var li = _this.find('.image-item');
  653. if (li.length < 1) {
  654. DoLog(LogLevel.Warning, 'This <ul> has 0 <li>, will be skipped.');
  655. return;
  656. }
  657.  
  658. li.each(function (j, ee) {
  659. var __this = $(ee);
  660.  
  661. var ctlAttrs = {
  662. illustId: 0,
  663. illustType: 0,
  664. pageCount: 1,
  665. };
  666.  
  667. var illustId = __this.find('a:first').attr('data-gtm-recommend-illust-id') || __this.find('img:first').attr('data-id');
  668. if (illustId == null) {
  669. DoLog(LogLevel.Warning, 'Can not found illust id of this image, skip.');
  670. return;
  671. } else {
  672. ctlAttrs.illustId = illustId;
  673. }
  674. var pageCount = __this.find('.page-count');
  675. if (pageCount.length > 0) {
  676. pageCount = parseInt(pageCount.find('span').text());
  677. }
  678. if (__this.find('a:first').hasClass('ugoku-illust')) {
  679. ctlAttrs.illustType = 2;
  680. }
  681.  
  682. __this.attr({
  683. 'illustId': ctlAttrs.illustId,
  684. 'illustType': ctlAttrs.illustType,
  685. 'pageCount': ctlAttrs.pageCount
  686. });
  687.  
  688. returnMap.controlElements.push(ee);
  689. });
  690. });
  691.  
  692. DoLog(LogLevel.Info, 'Process page elements complete.');
  693. DoLog(LogLevel.Elements, returnMap);
  694.  
  695. returnMap.loadingComplete = true;
  696. this.private.returnMap = returnMap;
  697. return returnMap;
  698. },
  699. GetProcessedPageElements: function () {
  700. if (this.private.returnMap == null) {
  701. return this.ProcessPageElements();
  702. }
  703. return this.private.returnMap;
  704. },
  705. GetToolBar: function () {
  706. return $('._toolmenu').get(0);
  707. },
  708. HasAutoLoad: false,
  709. private: {
  710. returnMap: null,
  711. },
  712. };
  713. Pages[PageType.Ranking] = {
  714. PageTypeString: 'RankingPage',
  715. CheckUrl: function (url) {
  716. return /^https?:\/\/www.pixiv.net\/ranking.php.*/.test(url);
  717. },
  718. ProcessPageElements: function () {
  719. var returnMap = {
  720. loadingComplete: false,
  721. controlElements: [],
  722. };
  723.  
  724. var works = $('._work');
  725.  
  726. DoLog(LogLevel.Info, 'Found .work, length: ' + works.length);
  727. DoLog(LogLevel.Elements, works);
  728.  
  729. works.each(function (i, e) {
  730. var _this = $(e);
  731.  
  732. var ctlAttrs = {
  733. illustId: 0,
  734. illustType: 0,
  735. pageCount: 1,
  736. };
  737.  
  738. var href = _this.attr('href');
  739.  
  740. if (href == null || href === '') {
  741. DoLog('Can not found illust id, skip this.');
  742. return;
  743. }
  744.  
  745. var matched = href.match(/artworks\/(\d+)/);
  746. if (matched) {
  747. ctlAttrs.illustId = matched[1];
  748. } else {
  749. DoLog('Can not found illust id, skip this.');
  750. return;
  751. }
  752.  
  753. if (_this.hasClass('multiple')) {
  754. ctlAttrs.pageCount = _this.find('.page-count').find('span').text();
  755. }
  756.  
  757. if (_this.hasClass('ugoku-illust')) {
  758. ctlAttrs.illustType = 2;
  759. }
  760.  
  761. // 添加 attr
  762. _this.attr({
  763. 'illustId': ctlAttrs.illustId,
  764. 'illustType': ctlAttrs.illustType,
  765. 'pageCount': ctlAttrs.pageCount
  766. });
  767.  
  768. returnMap.controlElements.push(e);
  769. });
  770.  
  771. returnMap.loadingComplete = true;
  772.  
  773. DoLog(LogLevel.Info, 'Process page elements complete.');
  774. DoLog(LogLevel.Elements, returnMap);
  775.  
  776. this.private.returnMap = returnMap;
  777. return returnMap;
  778. },
  779. GetProcessedPageElements: function () {
  780. if (this.private.returnMap == null) {
  781. return this.ProcessPageElements();
  782. }
  783. return this.private.returnMap;
  784. },
  785. GetToolBar: function () {
  786. return $('._toolmenu').get(0);
  787. },
  788. HasAutoLoad: false,
  789. private: {
  790. returnMap: null,
  791. },
  792. };
  793. Pages[PageType.NewIllust] = {
  794. PageTypeString: 'NewIllustPage',
  795. CheckUrl: function (url) {
  796. return /^https?:\/\/www.pixiv.net\/new_illust.php.*/.test(url);
  797. },
  798. ProcessPageElements: function () {
  799. var returnMap = {
  800. loadingComplete: false,
  801. controlElements: [],
  802. };
  803.  
  804. var firstDiv = $('#root').children('div:first');
  805. if (firstDiv.length === 0) {
  806. DoLog(LogLevel.Error, 'Can not found images\' container div!');
  807. return returnMap;
  808. }
  809.  
  810. var ul = firstDiv.children('div:last').find('ul');
  811. if (ul.length === 0) {
  812. DoLog(LogLevel.Error, 'Can not found <ul>!');
  813. return returnMap;
  814. }
  815.  
  816. ul.find('li').each(function (i, e) {
  817. var _this = $(e);
  818.  
  819. var link = _this.find('a:first');
  820. var href = link.attr('href');
  821. if (href == null || href === '') {
  822. DoLog(LogLevel.Error, 'Can not found illust id, skip this.');
  823. return;
  824. }
  825.  
  826. var ctlAttrs = {
  827. illustId: 0,
  828. illustType: 0,
  829. pageCount: 1,
  830. };
  831.  
  832. var matched = href.match(/artworks\/(\d+)/);
  833. if (matched) {
  834. ctlAttrs.illustId = matched[1];
  835. } else {
  836. DoLog(LogLevel.Warning, 'Can not found illust id, skip this.');
  837. return;
  838. }
  839.  
  840. if (link.children().length > 1) {
  841. var span = link.find('svg').next();
  842. if (span.length > 0) {
  843. ctlAttrs.pageCount = span.text();
  844. } else if (link.find('svg').length > 0) {
  845. ctlAttrs.illustType = 2;
  846. }
  847. }
  848.  
  849. _this.attr({
  850. 'illustId': ctlAttrs.illustId,
  851. 'illustType': ctlAttrs.illustType,
  852. 'pageCount': ctlAttrs.pageCount
  853. });
  854.  
  855. returnMap.controlElements.push(e);
  856. });
  857.  
  858. returnMap.loadingComplete = true;
  859.  
  860. DoLog(LogLevel.Info, 'Process page elements complete.');
  861. DoLog(LogLevel.Elements, returnMap);
  862.  
  863. this.private.returnMap = returnMap;
  864. return returnMap;
  865. },
  866. GetProcessedPageElements: function () {
  867. if (this.private.returnMap == null) {
  868. return this.ProcessPageElements();
  869. }
  870. return this.private.returnMap;
  871. },
  872. GetToolBar: function () {
  873. var div = $('#root').children('div');
  874. for (var i = div.length - 1; i >= 0; i--) {
  875. if ($(div.get(i)).children('ul').length > 0) {
  876. return $(div.get(i)).children('ul').get(0);
  877. }
  878. }
  879. },
  880. HasAutoLoad: true,
  881. private: {
  882. returnMap: null,
  883. },
  884. };
  885. Pages[PageType.R18] = {
  886. PageTypeString: 'R18Page',
  887. CheckUrl: function (url) {
  888. return /^https?:\/\/www.pixiv.net\/cate_r18.php.*/.test(url);
  889. },
  890. ProcessPageElements: function () {
  891. //
  892. },
  893. GetToolBar: function () {
  894. //
  895. },
  896. HasAutoLoad: false,
  897. };
  898. Pages[PageType.BookMark] = {
  899. PageTypeString: 'BookMarkPage',
  900. CheckUrl: function (url) {
  901. return /^https:\/\/www.pixiv.net\/bookmark.php\/?$/.test(url);
  902. },
  903. ProcessPageElements: function () {
  904. var returnMap = {
  905. loadingComplete: false,
  906. controlElements: [],
  907. };
  908.  
  909. var images = $('.image-item');
  910. DoLog(LogLevel.Info, 'Found images, length: ' + images.length);
  911. DoLog(LogLevel.Elements, images);
  912.  
  913. images.each(function (i, e) {
  914. var _this = $(e);
  915.  
  916. var work = _this.find('._work');
  917. if (work.length === 0) {
  918. DoLog(LogLevel.Warning, 'Can not found ._work, skip this.');
  919. return;
  920. }
  921.  
  922. var ctlAttrs = {
  923. illustId: 0,
  924. illustType: 0,
  925. pageCount: 1,
  926. };
  927.  
  928. var href = work.attr('href');
  929. if (href == null || href === '') {
  930. DoLog(LogLevel.Warning, 'Can not found illust id, skip this.');
  931. return;
  932. }
  933.  
  934. var matched = href.match(/illust_id=(\d+)/);
  935. if (matched) {
  936. ctlAttrs.illustId = matched[1];
  937. } else {
  938. DoLog(LogLevel.Warning, 'Can not found illust id, skip this.');
  939. return;
  940. }
  941.  
  942. if (work.hasClass('multiple')) {
  943. ctlAttrs.pageCount = _this.find('.page-count').find('span').text();
  944. }
  945.  
  946. if (work.hasClass('ugoku-illust')) {
  947. ctlAttrs.illustType = 2;
  948. }
  949.  
  950. // 添加 attr
  951. _this.attr({
  952. 'illustId': ctlAttrs.illustId,
  953. 'illustType': ctlAttrs.illustType,
  954. 'pageCount': ctlAttrs.pageCount
  955. });
  956.  
  957. returnMap.controlElements.push(e);
  958. });
  959.  
  960. returnMap.loadingComplete = true;
  961.  
  962. DoLog(LogLevel.Info, 'Process page elements complete.');
  963. DoLog(LogLevel.Elements, returnMap);
  964.  
  965. this.private.returnMap = returnMap;
  966. return returnMap;
  967. },
  968. GetProcessedPageElements: function () {
  969. if (this.private.returnMap == null) {
  970. return this.ProcessPageElements();
  971. }
  972. return this.private.returnMap;
  973. },
  974. GetToolBar: function () {
  975. return $('._toolmenu').get(0);
  976. },
  977. HasAutoLoad: false,
  978. private: {
  979. returnMap: null,
  980. },
  981. };
  982. Pages[PageType.Stacc] = {
  983. PageTypeString: 'StaccPage',
  984. CheckUrl: function (url) {
  985. return /^https:\/\/www.pixiv.net\/stacc.*/.test(url);
  986. },
  987. ProcessPageElements: function () {
  988. var returnMap = {
  989. loadingComplete: false,
  990. controlElements: [],
  991. };
  992.  
  993. var works = $('._work');
  994.  
  995. DoLog(LogLevel.Info, 'Found .work, length: ' + works.length);
  996. DoLog(LogLevel.Elements, works);
  997.  
  998. works.each(function (i, e) {
  999. var _this = $(e);
  1000.  
  1001. var ctlAttrs = {
  1002. illustId: 0,
  1003. illustType: 0,
  1004. pageCount: 1,
  1005. };
  1006.  
  1007. var href = _this.attr('href');
  1008.  
  1009. if (href == null || href === '') {
  1010. DoLog('Can not found illust id, skip this.');
  1011. return;
  1012. }
  1013.  
  1014. var matched = href.match(/illust_id=(\d+)/);
  1015. if (matched) {
  1016. ctlAttrs.illustId = matched[1];
  1017. } else {
  1018. DoLog('Can not found illust id, skip this.');
  1019. return;
  1020. }
  1021.  
  1022. if (_this.hasClass('multiple')) {
  1023. ctlAttrs.pageCount = _this.find('.page-count').find('span').text();
  1024. }
  1025.  
  1026. if (_this.hasClass('ugoku-illust')) {
  1027. ctlAttrs.illustType = 2;
  1028. }
  1029.  
  1030. // 添加 attr
  1031. _this.attr({
  1032. 'illustId': ctlAttrs.illustId,
  1033. 'illustType': ctlAttrs.illustType,
  1034. 'pageCount': ctlAttrs.pageCount
  1035. });
  1036.  
  1037. returnMap.controlElements.push(e);
  1038. });
  1039.  
  1040. returnMap.loadingComplete = true;
  1041.  
  1042. DoLog(LogLevel.Info, 'Process page elements complete.');
  1043. DoLog(LogLevel.Elements, returnMap);
  1044.  
  1045. this.private.returnMap = returnMap;
  1046. return returnMap;
  1047. },
  1048. GetProcessedPageElements: function () {
  1049. if (this.private.returnMap == null) {
  1050. return this.ProcessPageElements();
  1051. }
  1052. return this.private.returnMap;
  1053. },
  1054. GetToolBar: function () {
  1055. return $('._toolmenu').get(0);
  1056. },
  1057. HasAutoLoad: true,
  1058. private: {
  1059. returnMap: null,
  1060. },
  1061. };
  1062. Pages[PageType.Artwork] = {
  1063. PageTypeString: 'ArtworkPage',
  1064. CheckUrl: function (url) {
  1065. return /^https:\/\/www.pixiv.net\/artworks\/.*/.test(url) ||
  1066. /^https:\/\/www.pixiv.net\/en\/artworks\/.*/.test(url);
  1067. },
  1068. ProcessPageElements: function () {
  1069. var returnMap = {
  1070. loadingComplete: false,
  1071. controlElements: [],
  1072. };
  1073.  
  1074. // 是动图
  1075. var canvas = $('main').find('figure').find('canvas');
  1076. if ($('main').find('figure').find('canvas').length > 0) {
  1077. this.private.needProcess = true;
  1078. canvas.addClass('pp-canvas');
  1079. }
  1080.  
  1081. returnMap.loadingComplete = true;
  1082. return returnMap;
  1083. },
  1084. GetToolBar: function () {
  1085. var div = $('#root').children('div');
  1086. for (var i = div.length - 1; i >= 0; i--) {
  1087. if ($(div.get(i)).children('ul').length > 0) {
  1088. return $(div.get(i)).children('ul').get(0);
  1089. }
  1090. }
  1091. },
  1092. HasAutoLoad: false,
  1093. Work: function () {
  1094. function AddDownloadButton(div, button, offsetToOffsetTop) {
  1095. if (!g_settings.enableAnimeDownload) {
  1096. return;
  1097. }
  1098.  
  1099. var cloneButton = button.clone().css({ 'bottom': '50px', 'margin': 0, 'padding': 0, 'width': '48px', 'height': '48px', 'opacity': '0.4', 'cursor': 'pointer' });
  1100. cloneButton.get(0).innerHTML = '<svg viewBox="0 0 120 120" style="width: 40px; height: 40px; stroke-width: 10; stroke-linecap: round; stroke-linejoin: round; border-radius: 24px; background-color: black; stroke: limegreen; fill: none;" class="_3Fo0Hjg"><polyline points="60,30 60,90"></polyline><polyline points="30,60 60,90 90,60"></polyline></svg></button>';
  1101.  
  1102. function MoveButton() {
  1103. function getOffset(e) {
  1104. if (e.offsetParent) {
  1105. var offset = getOffset(e.offsetParent);
  1106. return {
  1107. offsetTop: e.offsetTop + offset.offsetTop,
  1108. offsetLeft: e.offsetLeft + offset.offsetLeft,
  1109. };
  1110. } else {
  1111. return {
  1112. offsetTop: e.offsetTop,
  1113. offsetLeft: e.offsetLeft,
  1114. };
  1115. }
  1116. }
  1117.  
  1118. var offset = getOffset(button.get(0));
  1119. DoLog(LogLevel.Info, 'offset of download button: ' + offset.offsetTop + ', ' + offset.offsetLeft);
  1120. DoLog(LogLevel.Elements, offset);
  1121.  
  1122. cloneButton.css({ 'position': 'absolute', 'left': offset.offsetLeft, 'top': offset.offsetTop - 50 - offsetToOffsetTop }).show();
  1123. }
  1124.  
  1125. MoveButton();
  1126. $(window).on('resize', MoveButton);
  1127. div.append(cloneButton);
  1128.  
  1129. cloneButton.mouseover(function () {
  1130. $(this).css('opacity', '0.2');
  1131. }).mouseleave(function () {
  1132. $(this).css('opacity', '0.4');
  1133. }).click(function () {
  1134. var illustId = '';
  1135.  
  1136. var matched = location.href.match(/artworks\/(\d+)/);
  1137. if (matched) {
  1138. illustId = matched[1];
  1139. DoLog(LogLevel.Info, 'IllustId=' + illustId);
  1140. } else {
  1141. DoLog(LogLevel.Error, 'Can not found illust id!');
  1142. return;
  1143. }
  1144.  
  1145. $.ajax(g_getUgoiraUrl.replace('#id#', illustId), {
  1146. method: 'GET',
  1147. success: function (json) {
  1148. DoLog(LogLevel.Elements, json);
  1149.  
  1150. if (json.error == true) {
  1151. DoLog(LogLevel.Error, 'Server response an error: ' + json.message);
  1152. return;
  1153. }
  1154.  
  1155. // 因为浏览器会拦截不同域的 open 操作,绕一下
  1156. var newWindow = window.open('_blank');
  1157. newWindow.location = json.body.originalSrc;
  1158. },
  1159. error: function () {
  1160. DoLog(LogLevel.Error, 'Request zip file failed!');
  1161. }
  1162. });
  1163. });
  1164. }
  1165.  
  1166. if (this.private.needProcess) {
  1167. var canvas = $('.pp-canvas');
  1168.  
  1169. // 预览模式,需要调成全屏,并且添加下载按钮到全屏播放的 div 里
  1170. if (location.href.indexOf('#preview') != -1) {
  1171. canvas.click();
  1172.  
  1173. $('#root').remove();
  1174.  
  1175. var callbackInterval = setInterval(function () {
  1176. var div = $('div[role="presentation"]');
  1177. if (div.length < 1) {
  1178. return;
  1179. }
  1180.  
  1181. DoLog(LogLevel.Info, 'found <div>, continue to next step.');
  1182.  
  1183. clearInterval(callbackInterval);
  1184.  
  1185. var presentationCanvas = div.find('canvas');
  1186. if (presentationCanvas.length < 1) {
  1187. DoLog(LogLevel.Error, 'Can not found canvas in the presentation div.');
  1188. return;
  1189. }
  1190.  
  1191. var width = 0, height = 0;
  1192. var tWidth = presentationCanvas.attr('width');
  1193. var tHeight = presentationCanvas.attr('height');
  1194. if (tWidth && tHeight) {
  1195. width = parseInt(tWidth);
  1196. height = parseInt(tHeight);
  1197. } else {
  1198. tWidth = presentationCanvas.css('width');
  1199. tHeight = presentationCanvas.css('height');
  1200. width = parseInt(tWidth);
  1201. height = parseInt(this);
  1202. }
  1203.  
  1204. var parent = presentationCanvas.parent();
  1205. for (var i = 0; i < 3; i++) {
  1206. parent.get(0).className = '';
  1207. parent = parent.parent();
  1208. }
  1209. presentationCanvas.css({ 'width': width + 'px', 'height': height + 'px', 'cursor': 'default' }).addClass('pp-presentationCanvas');
  1210. var divForStopClick = $('<div class="pp-disableClick"></div>').css({
  1211. 'width': width + 'px', 'height': height + 'px',
  1212. 'opacity': 0,
  1213. 'position': 'absolute', 'top': '0px', 'left': '0px', 'z-index': 99999,
  1214. });
  1215. div.append(divForStopClick);
  1216. div.append(presentationCanvas.next().css('z-index', 99999));
  1217. presentationCanvas.next().remove();
  1218. // 防止预览图消失
  1219. $('html').addClass('pp-main');
  1220.  
  1221. // 调整 canvas 大小的函数
  1222. window.ResizeCanvas = function (newWidth, newHeight) {
  1223. DoLog(LogLevel.Info, 'Resize canvas: ' + newWidth + 'x' + newHeight);
  1224. $('.pp-disableClick').css({ 'width': newWidth, 'height': newHeight });
  1225. $('.pp-presentationCanvas').css({ 'width': newWidth, 'height': newHeight });
  1226. };
  1227. window.GetCanvasSize = function () {
  1228. return {
  1229. width: width,
  1230. height: height,
  1231. };
  1232. }
  1233.  
  1234. // 添加下载按钮
  1235. AddDownloadButton(div, divForStopClick.next(), 0);
  1236.  
  1237. window.parent.PreviewCallback(width, height);
  1238. }, 500);
  1239. }
  1240. // 普通模式,只需要添加下载按钮到内嵌模式的 div 里
  1241. else {
  1242. var div = $('div[role="presentation"]');
  1243. var button = div.find('button');
  1244.  
  1245. var headerRealHeight = parseInt($('header').css('height')) +
  1246. parseInt($('header').css('padding-top')) + parseInt($('header').css('padding-bottom')) +
  1247. parseInt($('header').css('margin-top')) + parseInt($('header').css('margin-bottom')) +
  1248. parseInt($('header').css('border-bottom-width')) + parseInt($('header').css('border-top-width'));
  1249.  
  1250. AddDownloadButton(div, button, headerRealHeight);
  1251. }
  1252. }
  1253. },
  1254. private: {
  1255. needProcess: false,
  1256. },
  1257. };
  1258.  
  1259. function CheckUrlTest() {
  1260. var urls = [
  1261. 'http://www.pixiv.net',
  1262. 'http://www.pixiv.net',
  1263. 'https://www.pixiv.net',
  1264. 'https://www.pixiv.net/',
  1265. 'https://www.pixiv.net/?lang=en',
  1266. 'https://www.pixiv.net/search.php?s_mode=s_tag&word=miku',
  1267. 'https://www.pixiv.net/search.php?word=VOCALOID&s_mode=s_tag_full',
  1268. 'https://www.pixiv.net/discovery',
  1269. 'https://www.pixiv.net/discovery?x=1',
  1270. 'https://www.pixiv.net/member.php?id=3207350',
  1271. 'https://www.pixiv.net/member_illust.php?id=3207350&type=illust',
  1272. 'https://www.pixiv.net/bookmark.php?id=3207350&rest=show',
  1273. 'https://www.pixiv.net/ranking.php?mode=daily&content=ugoira',
  1274. 'https://www.pixiv.net/ranking.php?mode=daily',
  1275. 'https://www.pixiv.net/new_illust.php',
  1276. 'https://www.pixiv.net/new_illust.php?x=1',
  1277. 'https://www.pixiv.net/cate_r18.php',
  1278. 'https://www.pixiv.net/cate_r18.php?x=1',
  1279. 'https://www.pixiv.net/bookmark.php',
  1280. 'https://www.pixiv.net/bookmark.php?x=1',
  1281. 'https://www.pixiv.net/stacc?mode=unify',
  1282. 'https://www.pixiv.net/artworks/77996773',
  1283. 'https://www.pixiv.net/artworks/77996773#preview',
  1284. ];
  1285.  
  1286. for (var j = 0; j < urls.length; j++) {
  1287. for (var i = 0; i < PageType.PageTypeCount; i++) {
  1288. if (Pages[i].CheckUrl(urls[j])) {
  1289. console.log(urls[j]);
  1290. console.log('[' + j + '] is ' + Pages[i].PageTypeString);
  1291. }
  1292. }
  1293. }
  1294. }
  1295.  
  1296. /* ---------------------------------------- 预览 ---------------------------------------- */
  1297. function PixivPreview() {
  1298. var autoLoadInterval = null;
  1299.  
  1300. // 开启预览功能
  1301. function ActivePreview() {
  1302. var returnMap = Pages[g_pageType].GetProcessedPageElements();
  1303. if (!returnMap.loadingComplete) {
  1304. DoLog(LogLevel.Error, 'Page not load, should not call Preview!');
  1305. return;
  1306. }
  1307.  
  1308. // 鼠标进入
  1309. $(returnMap.controlElements).mouseenter(function (e) {
  1310. // 按住 Ctrl键 不显示预览图
  1311. if (e.ctrlKey) {
  1312. return;
  1313. }
  1314.  
  1315. var _this = $(this);
  1316. var illustId = _this.attr('illustId');
  1317. var illustType = _this.attr('illustType');
  1318. var pageCount = _this.attr('pageCount');
  1319.  
  1320. if (illustId == null) {
  1321. DoLog(LogLevel.Error, 'Can not found illustId in this element\'s attrbutes.');
  1322. return;
  1323. }
  1324. if (illustType == null) {
  1325. DoLog(LogLevel.Error, 'Can not found illustType in this element\'s attrbutes.');
  1326. return;
  1327. }
  1328. if (pageCount == null) {
  1329. DoLog(LogLevel.Error, 'Can not found pageCount in this element\'s attrbutes.');
  1330. return;
  1331. }
  1332.  
  1333. // 鼠标位置
  1334. g_mousePos = { x: e.pageX, y: e.pageY };
  1335. // 预览 Div
  1336. var previewDiv = $(document.createElement('div')).addClass('pp-main').attr('illustId', illustId)
  1337. .css({
  1338. 'position': 'absolute', 'z-index': '999999', 'left': g_mousePos.x + 'px', 'top': g_mousePos.y + 'px',
  1339. 'border-style': 'solid', 'border-color': '#6495ed', 'border-width': '2px', 'border-radius': '20px',
  1340. 'width': '48px', 'height': '48px',
  1341. 'background-image': 'url(https://pp-1252089172.cos.ap-chengdu.myqcloud.com/transparent.png)',
  1342. });
  1343. // 添加到 body
  1344. $('.pp-main').remove();
  1345. $('body').append(previewDiv);
  1346.  
  1347. // 加载中图片
  1348. var loadingImg = $(new Image()).addClass('pp-loading').attr('src', g_loadingImage).css({
  1349. 'position': 'absolute', 'border-radius': '20px',
  1350. });
  1351. previewDiv.append(loadingImg);
  1352.  
  1353. // 要显示的预览图节点
  1354. var loadImg = $(new Image()).addClass('pp-image').css({ 'height': '0px', 'width': '0px', 'display': 'none', 'border-radius': '20px' });
  1355. previewDiv.append(loadImg);
  1356.  
  1357. // 原图(笑脸)图标
  1358. var originIcon = $(new Image()).addClass('pp-original').attr('src', 'https://source.pixiv.net/www/images/pixivcomic-favorite.png')
  1359. .css({ 'position': 'absolute', 'bottom': '5px', 'right': '5px', 'display': 'none' });
  1360. previewDiv.append(originIcon);
  1361.  
  1362. // 点击图标新网页打开原图
  1363. originIcon.click(function () {
  1364. window.open($(previewDiv).children('img')[1].src);
  1365. });
  1366.  
  1367. // 右上角张数标记
  1368. var pageCountHTML = '<div class="pp-pageCount" style="display: flex;-webkit-box-align: center;align-items: center;box-sizing: border-box;margin-left: auto;height: 20px;color: rgb(255, 255, 255);font-size: 10px;line-height: 12px;font-weight: bold;flex: 0 0 auto;padding: 4px 6px;background: rgba(0, 0, 0, 0.32);border-radius: 10px;margin-top:5px;margin-right:5px;">\<svg viewBox="0 0 9 10" width="9" height="10" style="stroke: none;line-height: 0;font-size: 0px;fill: currentcolor;"><path d="M8,3 C8.55228475,3 9,3.44771525 9,4 L9,9 C9,9.55228475 8.55228475,10 8,10 L3,10 C2.44771525,10 2,9.55228475 2,9 L6,9 C7.1045695,9 8,8.1045695 8,7 L8,3 Z M1,1 L6,1 C6.55228475,1 7,1.44771525 7,2 L7,7 C7,7.55228475 6.55228475,8 6,8 L1,8 C0.44771525,8 0,7.55228475 0,7 L0,2 C0,1.44771525 0.44771525,1 1,1 Z"></path></svg><span style="margin-left:2px;" class="pp-page">0/0</span></div>';
  1369. var pageCountDiv = $(pageCountHTML)
  1370. .css({ 'position': 'absolute', 'top': '0px', 'display': 'none', 'right': '0px', 'display': 'none' });
  1371. previewDiv.append(pageCountDiv);
  1372.  
  1373. $('.pp-main').mouseleave(function (e) {
  1374. $(this).remove();
  1375. });
  1376.  
  1377. var url = '';
  1378. if (illustType == 2) {
  1379. // 动图
  1380. var screenWidth = document.documentElement.clientWidth;
  1381. var screenHeight = document.documentElement.clientHeight;
  1382. previewDiv.get(0).innerHTML = '<iframe class="pp-iframe" style="width: 48px; height: 48px; display: none; border-radius: 20px;" src="https://www.pixiv.net/artworks/' + illustId + '#preview" />';
  1383. previewDiv.append(loadingImg);
  1384. } else {
  1385. url = g_getArtworkUrl.replace('#id#', illustId);
  1386.  
  1387. // 获取图片链接
  1388. $.ajax(url, {
  1389. method: 'GET',
  1390. success: function (json) {
  1391. DoLog(LogLevel.Info, 'Got artwork urls:');
  1392. DoLog(LogLevel.Elements, json);
  1393.  
  1394. if (json.error === true) {
  1395. DoLog(LogLevel.Error, 'Server responsed an error: ' + json.message);
  1396. return;
  1397. }
  1398.  
  1399. var regular = [];
  1400. var original = [];
  1401. for (var i = 0; i < json.body.length; i++) {
  1402. regular.push(json.body[i].urls.regular);
  1403. original.push(json.body[i].urls.original);
  1404. }
  1405.  
  1406. DoLog(LogLevel.Info, 'Process urls complete.');
  1407. DoLog(LogLevel.Elements, regular);
  1408. DoLog(LogLevel.Elements, original);
  1409.  
  1410. ViewImages(regular, 0, original, g_settings.original);
  1411. },
  1412. error: function (data) {
  1413. DoLog(LogLevel.Error, 'Request image urls failed!');
  1414. if (data) {
  1415. DoLog(LogLevel.Elements, data);
  1416. }
  1417. }
  1418. });
  1419. }
  1420. });
  1421.  
  1422. // 鼠标移出图片
  1423. $(returnMap.controlElements).mouseleave(function (e) {
  1424. var _this = $(this);
  1425. var illustId = _this.attr('illustId');
  1426. var illustType = _this.attr('illustType');
  1427. var pageCount = _this.attr('pageCount');
  1428.  
  1429. var moveToElement = $(e.relatedTarget);
  1430. var isMoveToPreviewElement = false;
  1431. // 鼠标移动到预览图上
  1432. while (true) {
  1433. if (moveToElement.hasClass('pp-main') && moveToElement.attr('illustId') == illustId) {
  1434. isMoveToPreviewElement = true;
  1435. }
  1436.  
  1437. if (moveToElement.parent().length < 1) {
  1438. break;
  1439. }
  1440.  
  1441. moveToElement = moveToElement.parent();
  1442. }
  1443. if (!isMoveToPreviewElement) {
  1444. // 非预览图上
  1445. $('.pp-main').remove();
  1446. }
  1447. });
  1448.  
  1449. // 鼠标移动,调整位置
  1450. $(returnMap.controlElements).mousemove(function (e) {
  1451. // Ctrl 和 中键 都可以禁止预览图移动,这样就可以单手操作了
  1452. if (e.ctrlKey || e.buttons & 4) {
  1453. return;
  1454. }
  1455. var screenWidth = document.documentElement.clientWidth;
  1456. var screenHeight = document.documentElement.clientHeight;
  1457. g_mousePos.x = e.pageX; g_mousePos.y = e.pageY;
  1458.  
  1459. AdjustDivPosition();
  1460. });
  1461.  
  1462. // 这个页面有自动加载
  1463. if (Pages[g_pageType].HasAutoLoad && autoLoadInterval == null) {
  1464. autoLoadInterval = setInterval(ProcessAutoLoad, 1000);
  1465. DoLog(LogLevel.Info, 'Auto load interval set.');
  1466. }
  1467.  
  1468. // 插一段回调函数
  1469. window.PreviewCallback = PreviewCallback;
  1470. DoLog(LogLevel.Info, 'Callback function was inserted.');
  1471. DoLog(LogLevel.Elements, window.PreviewCallback);
  1472.  
  1473. DoLog(LogLevel.Info, 'Preview enable succeed!');
  1474. }
  1475.  
  1476. // 关闭预览功能,不是给外部用的
  1477. function DeactivePreview() {
  1478. var returnMap = Pages[g_pageType].GetProcessedPageElements();
  1479. if (!returnMap.loadingComplete) {
  1480. DoLog(LogLevel.Error, 'Page not load, should not call Preview!');
  1481. return;
  1482. }
  1483.  
  1484. // 只需要取消绑定事件, attrs 以及回调都不需要删除
  1485. $(returnMap.controlElements).unbind('mouseenter').unbind('mouseleave').unbind('mousemove');
  1486.  
  1487. if (autoLoadInterval) {
  1488. clearInterval(autoLoadInterval);
  1489. autoLoadInterval = null;
  1490. }
  1491.  
  1492. DoLog(LogLevel.Info, 'Preview disable succeed!');
  1493. }
  1494.  
  1495. // iframe 的回调函数
  1496. function PreviewCallback(canvasWidth, canvasHeight) {
  1497. DoLog(LogLevel.Info, 'iframe callback, width: ' + canvasWidth + ', height: ' + canvasHeight);
  1498.  
  1499. var size = AdjustDivPosition();
  1500.  
  1501. $('.pp-loading').hide();
  1502. $('.pp-iframe').css({ 'width': size.width, 'height': size.height }).show();
  1503. }
  1504.  
  1505. // 调整预览 Div 的位置
  1506. function AdjustDivPosition() {
  1507. // 鼠标到预览图的距离
  1508. var fromMouseToDiv = 30;
  1509.  
  1510. var screenWidth = document.documentElement.clientWidth;
  1511. var screenHeight = document.documentElement.clientHeight;
  1512. var left = 0;
  1513. var top = document.body.scrollTop + document.documentElement.scrollTop;
  1514.  
  1515. var width = 0, height = 0;
  1516. if ($('.pp-main').find('iframe').length > 0) {
  1517. var iframe = $('.pp-main').find('iframe').get(0);
  1518. if (iframe.contentWindow.GetCanvasSize) {
  1519. var canvasSize = iframe.contentWindow.GetCanvasSize();
  1520. width = canvasSize.width;
  1521. height = canvasSize.height;
  1522. } else {
  1523. width = 0;
  1524. height = 0;
  1525. }
  1526. } else {
  1527. $('.pp-image').css({ 'width': '', 'height': '' });
  1528. width = $('.pp-image').get(0) == null ? 0 : $('.pp-image').get(0).width;
  1529. height = $('.pp-image').get(0) == null ? 0 : $('.pp-image').get(0).height;
  1530. }
  1531.  
  1532. var isShowOnLeft = g_mousePos.x > screenWidth / 2;
  1533.  
  1534. var newWidth = 48, newHeight = 48;
  1535. if (width > 0 && height > 0) {
  1536. newWidth = isShowOnLeft ? g_mousePos.x - fromMouseToDiv : screenWidth - g_mousePos.x - fromMouseToDiv;
  1537. newHeight = height / width * newWidth;
  1538. // 高度不足以完整显示,只能让两侧留空了
  1539. if (newHeight > screenHeight) {
  1540. newHeight = screenHeight;
  1541. newWidth = newHeight / height * width;
  1542. }
  1543. newWidth -= 5;
  1544. newHeight -= 5;
  1545.  
  1546. // 设置新的宽高
  1547. if ($('.pp-main').find('iframe').length > 0) {
  1548. var iframe = $('.pp-main').find('iframe');
  1549. iframe.get(0).contentWindow.ResizeCanvas(newWidth, newHeight);
  1550. iframe.css({ 'width': newWidth, 'height': newHeight });
  1551. }
  1552. else {
  1553. $('.pp-image').css({ 'height': newHeight + 'px', 'width': newWidth + 'px' });
  1554. }
  1555.  
  1556. // 调整下一次 loading 出现的位置
  1557. $('.pp-loading').css({ 'left': newWidth / 2 - 24 + 'px', 'top': newHeight / 2 - 24 + 'px' });
  1558. }
  1559.  
  1560. // 图片宽度大于高度很多时,会显示在页面顶部,鼠标碰不到,把它移动到下面
  1561. if (top + newHeight <= g_mousePos.y) {
  1562. top = (g_mousePos.y - newHeight - fromMouseToDiv);
  1563. }
  1564. // 调整DIV的位置
  1565. left = isShowOnLeft ? g_mousePos.x - newWidth - fromMouseToDiv : g_mousePos.x + fromMouseToDiv;
  1566.  
  1567. $('.pp-main').css({ 'left': left + 'px', 'top': top + 'px', 'width': newWidth, 'height': newHeight });
  1568.  
  1569. // 返回新的宽高
  1570. return {
  1571. width: newWidth,
  1572. height: newHeight,
  1573. };
  1574. }
  1575.  
  1576. // 显示预览图
  1577. function ViewImages(regular, index, original, isShowOriginal) {
  1578. if (!regular || regular.length === 0) {
  1579. DoLog(LogLevel.Error, 'Regular url array is null, can not view images!');
  1580. return;
  1581. }
  1582. if (index == null || index < 0 || index >= regular.length) {
  1583. DoLog(LogLevel.Error, 'Index(' + index + ') out of range, can not view images!');
  1584. return;
  1585. }
  1586. if (original == null || original.length === 0) {
  1587. DoLog(LogLevel.Warning, 'Original array is null, replace it with regular array.');
  1588. original = regular;
  1589. }
  1590. if (original.length < regular) {
  1591. DoLog(LogLevel.Warning, 'Original array\'s length is less than regular array, replace it with regular array.');
  1592. original = regular;
  1593. }
  1594. if (isShowOriginal == null) {
  1595. isShowOriginal = false;
  1596. }
  1597.  
  1598. if (original.length > 1) {
  1599. $('.pp-page').text((index + 1) + '/' + regular.length);
  1600. $('.pp-pageCount').show();
  1601. }
  1602. if (isShowOriginal) {
  1603. $('.pp-image').addClass('original');
  1604. } else {
  1605. $('.pp-image').removeClass('original');
  1606. }
  1607. g_settings.original = isShowOriginal ? 1 : 0;
  1608.  
  1609. // 隐藏页数和原图标签
  1610. $('.pp-original, .pp-pageCount').hide();
  1611.  
  1612. // 第一次需要绑定事件
  1613. if ($('.pp-image').attr('index') == null) {
  1614. // 绑定点击事件,Ctrl+左键 单击切换原图
  1615. $('.pp-image').on('click', function (ev) {
  1616. var _this = $(this);
  1617. var isOriginal = _this.hasClass('original');
  1618. var index = _this.attr('index');
  1619. if (index == null) {
  1620. index = 0;
  1621. } else {
  1622. index = parseInt(index);
  1623. }
  1624.  
  1625. if (ev.ctrlKey) {
  1626. // 按住 Ctrl 来回切换原图
  1627. isOriginal = !isOriginal;
  1628. ViewImages(regular, index, original, isOriginal);
  1629. }
  1630. else if (ev.shiftKey) {
  1631. // 按住 Shift 点击图片新标签页打开原图
  1632. window.open(original[index]);
  1633. } else {
  1634. if (regular.length == 1) {
  1635. return;
  1636. }
  1637. // 如果是多图,点击切换下一张
  1638. if (++index >= regular.length) {
  1639. index = 0;
  1640. }
  1641. ViewImages(regular, index, original, isOriginal);
  1642. // 预加载
  1643. for (var i = index + 1; i < regular.length && i <= index + 3; i++) {
  1644. var image = new Image();
  1645. image.src = isOriginal ? original[i] : regular[i];;
  1646. }
  1647. }
  1648. });
  1649.  
  1650. // 图片预加载完成
  1651. $('.pp-image').on('load', function () {
  1652. // 调整图片位置和大小
  1653. var _this = $(this);
  1654. var size = AdjustDivPosition();
  1655. var isShowOriginal = _this.hasClass('original');
  1656.  
  1657. $('.pp-loading').css('display', 'none');
  1658. // 显示图像、页数、原图标签
  1659. $('.pp-image').css('display', '');
  1660. if (regular.length > 1) {
  1661. $('.pp-pageCount').show();
  1662. }
  1663. if (isShowOriginal) {
  1664. $('.pp-original').show();
  1665. }
  1666.  
  1667. // 预加载
  1668. for (var i = index + 1; i < regular.length && i <= index + 3; i++) {
  1669. var image = new Image();
  1670. image.src = isShowOriginal ? original[i] : regular[i];;
  1671. }
  1672. }).on('error', function () {
  1673. DoLog(LogLevel.Error, 'Load image failed!');
  1674. });
  1675. }
  1676.  
  1677. $('.pp-image').attr('src', isShowOriginal ? original[index] : regular[index]).attr('index', index);
  1678. }
  1679.  
  1680. // 处理自动加载
  1681. function ProcessAutoLoad() {
  1682. if (Pages[g_pageType].GetProcessedPageElements() == null) {
  1683. DoLog(LogLevel.Error, 'Call ProcessPageElements first!');
  1684. return;
  1685. }
  1686.  
  1687. var oldReturnMap = Pages[g_pageType].GetProcessedPageElements();
  1688. var newReturnMap = Pages[g_pageType].ProcessPageElements();
  1689.  
  1690. if (newReturnMap.loadingComplete) {
  1691. if (oldReturnMap.controlElements.length < newReturnMap.controlElements.length) {
  1692. DoLog(LogLevel.Info, 'Page loaded ' + (newReturnMap.controlElements.length - oldReturnMap.controlElements.length) + ' new work(s).');
  1693.  
  1694. if (g_settings.linkBlank) {
  1695. $(newReturnMap.controlElements).find('a').attr('target', '_blank');
  1696. }
  1697.  
  1698. DeactivePreview();
  1699. ActivePreview();
  1700.  
  1701. return;
  1702. } else if (oldReturnMap.controlElements.length > newReturnMap.controlElements.length) {
  1703. DoLog(LogLevel.Warning, 'works become less?');
  1704.  
  1705. Pages[g_pageType].private.returnMap = oldReturnMap;
  1706.  
  1707. return;
  1708. }
  1709. }
  1710.  
  1711. DoLog(LogLevel.Info, 'Page not change.');
  1712. }
  1713.  
  1714. // 开启预览
  1715. ActivePreview();
  1716. }
  1717. /* ---------------------------------------- 排序 ---------------------------------------- */
  1718. function PixivSK(callback) {
  1719. // 不合理的设定
  1720. if (g_settings.pageCount < 1 || g_settings.favFilter < 0) {
  1721. g_settings.pageCount = 1;
  1722. g_settings.favFilter = 0;
  1723. }
  1724. // 当前已经取得的页面数量
  1725. var currentGettingPageCount = 0;
  1726. // 当前加载的页面 URL
  1727. var currentUrl = 'https://www.pixiv.net/ajax/search/artworks/';
  1728. // 当前加载的是第几张页面
  1729. var currentPage = 0;
  1730. // 获取到的作品
  1731. var works = [];
  1732.  
  1733. // 仅搜索页启用
  1734. if (g_pageType != PageType.Search) {
  1735. return;
  1736. }
  1737.  
  1738. // 获取第 currentPage 页的作品
  1739. var getWorks = function (onloadCallback) {
  1740. currentUrl = currentUrl.replace(/p=\d+/, 'p=' + currentPage);
  1741. DoLog(LogLevel.Info, 'Current url: ' + currentUrl);
  1742.  
  1743. var req = new XMLHttpRequest();
  1744. req.open('GET', currentUrl, true);
  1745. req.onload = function (event) {
  1746. onloadCallback(req);
  1747. };
  1748. req.onerror = function (event) {
  1749. DoLog(LogLevel.Error, 'Request search page error!');
  1750. };
  1751.  
  1752. req.send(null);
  1753. };
  1754.  
  1755. // 排序和筛选
  1756. var filterAndSort = function () {
  1757. DoLog(LogLevel.Info, 'Start sort.');
  1758. DoLog(LogLevel.Elements, works);
  1759. // 收藏量低于 FAV_FILTER 的作品不显示
  1760. var tmp = [];
  1761. $(works).each(function (i, work) {
  1762. var bookmarkCount = work.bookmarkCount ? work.bookmarkCount : 0;
  1763. if (bookmarkCount >= g_settings.favFilter && !(g_settings.hideFavorite && work.bookmarkData)) {
  1764. tmp.push(work);
  1765. }
  1766. });
  1767. works = tmp;
  1768.  
  1769. // 排序
  1770. works.sort(function (a, b) {
  1771. var favA = a.bookmarkCount;
  1772. var favB = b.bookmarkCount;
  1773. if (!favA) {
  1774. favA = 0;
  1775. }
  1776. if (!favB) {
  1777. favB = 0;
  1778. }
  1779. if (favA > favB) {
  1780. return -1;
  1781. }
  1782. if (favA < favB) {
  1783. return 1;
  1784. }
  1785. return 0;
  1786. });
  1787. DoLog(LogLevel.Info, 'Sort complete.');
  1788. DoLog(LogLevel.Elements, works);
  1789. };
  1790.  
  1791. if (currentPage === 0) {
  1792. var url = location.href;
  1793.  
  1794. if (url.indexOf('&p=') == -1 && url.indexOf('?p=') == -1) {
  1795. DoLog(LogLevel.Warning, 'Can not found page in url.');
  1796. if (url.indexOf('?') == -1) {
  1797. url += '?p=1';
  1798. DoLog(LogLevel.Info, 'Add "?p=1": ' + url);
  1799. } else {
  1800. url += '&p=1';
  1801. DoLog(LogLevel.Info, 'Add "&p=1": ' + url);
  1802. }
  1803. }
  1804. var wordMatch = url.match(/\/tags\/([^/]*)\/artworks/);
  1805. var searchWord = '';
  1806. if (wordMatch) {
  1807. DoLog(LogLevel.Info, 'Search key word: ' + searchWord);
  1808. searchWord = wordMatch[1];
  1809. } else {
  1810. DoLog(LogLevel.Error, 'Can not found search key word!');
  1811. return;
  1812. }
  1813.  
  1814. // page
  1815. var page = url.match(/p=(\d*)/)[1];
  1816. currentPage = parseInt(page);
  1817. DoLog(LogLevel.Info, 'Current page: ' + currentPage);
  1818.  
  1819. currentUrl += searchWord + '?word=' + searchWord + '&p=' + currentPage;
  1820. DoLog(LogLevel.Info, 'Current url: ' + currentUrl);
  1821. } else {
  1822. DoLog(LogLevel.Error, '???');
  1823. }
  1824.  
  1825. var imageContainer = Pages[PageType.Search].GetImageListContainer();
  1826. // loading
  1827. $(imageContainer).hide().before('<div id="loading" style="width:50px;margin-left:auto;margin-right:auto;"><img src="' + g_loadingImage + '" /><p id="progress" style="text-align: center;font-size: large;font-weight: bold;padding-top: 10px;">0%</p></div>');
  1828.  
  1829. // page
  1830. if (true) {
  1831. var pageSelectorDiv = Pages[PageType.Search].GetPageSelector();
  1832. if (pageSelectorDiv == null) {
  1833. DoLog(LogLevel.Error, 'Can not found page selector!');
  1834. return;
  1835. }
  1836.  
  1837. if ($(pageSelectorDiv).find('a').length > 2) {
  1838. var pageButton = $(pageSelectorDiv).find('a').get(1);
  1839. var newPageButtons = [];
  1840. var pageButtonString = 'Previewer';
  1841. for (var i = 0; i < 9; i++) {
  1842. var newPageButton = pageButton.cloneNode(true);
  1843. $(newPageButton).find('span').text(pageButtonString[i]);
  1844. newPageButtons.push(newPageButton);
  1845. }
  1846.  
  1847. $(pageSelectorDiv).find('button').remove();
  1848. while ($(pageSelectorDiv).find('a').length > 2) {
  1849. $(pageSelectorDiv).find('a:first').next().remove();
  1850. }
  1851.  
  1852. for (i = 0; i < 9; i++) {
  1853. $(pageSelectorDiv).find('a:last').before(newPageButtons[i]);
  1854. }
  1855.  
  1856. $(pageSelectorDiv).find('a').attr('href', 'javascript:;');
  1857.  
  1858. var pageUrl = location.href;
  1859. if (pageUrl.indexOf('&p=') == -1 && pageUrl.indexOf('?p=') == -1) {
  1860. if (pageUrl.indexOf('?') == -1) {
  1861. pageUrl += '?p=1';
  1862. } else {
  1863. pageUrl += '&p=1';
  1864. }
  1865. }
  1866. var prevPageUrl = pageUrl.replace(/p=\d+/, 'p=' + (currentPage - g_settings.pageCount > 1 ? currentPage - g_settings.pageCount : 1));
  1867. var nextPageUrl = pageUrl.replace(/p=\d+/, 'p=' + (currentPage + g_settings.pageCount));
  1868. DoLog(LogLevel.Info, 'Previous page url: ' + prevPageUrl);
  1869. DoLog(LogLevel.Info, 'Next page url: ' + nextPageUrl);
  1870. // 重新插入一遍清除事件绑定
  1871. var prevButton = $(pageSelectorDiv).find('a:first');
  1872. prevButton.before(prevButton.clone());
  1873. prevButton.remove();
  1874. var nextButton = $(pageSelectorDiv).find('a:last');
  1875. nextButton.before(nextButton.clone());
  1876. nextButton.remove();
  1877. $(pageSelectorDiv).find('a:first').attr('href', prevPageUrl).addClass('pp-prevPage');
  1878. $(pageSelectorDiv).find('a:last').attr('href', nextPageUrl).addClass('pp-nextPage');
  1879. }
  1880.  
  1881. var onloadCallback = function (req) {
  1882. try {
  1883. var json = JSON.parse(req.responseText);
  1884. if (json.hasOwnProperty('error')) {
  1885. if (json.error === false) {
  1886. var data = json.body.illustManga.data;
  1887. works = works.concat(data);
  1888. } else {
  1889. DoLog(LogLevel.Error, 'ajax error!');
  1890. return;
  1891. }
  1892. } else {
  1893. DoLog(LogLevel.Error, 'Key "error" not found!');
  1894. return;
  1895. }
  1896. } catch (e) {
  1897. DoLog(LogLevel.Error, 'A invalid json string!');
  1898. DoLog(LogLevel.Info, req.responseText);
  1899. }
  1900.  
  1901. currentPage++;
  1902. currentGettingPageCount++;
  1903. // 设定数量的页面加载完成
  1904. if (currentGettingPageCount == g_settings.pageCount) {
  1905. DoLog(LogLevel.Info, 'Load complete, start to load bookmark count.');
  1906. DoLog(LogLevel.Elements, works);
  1907.  
  1908. // 获取到的作品里面可能有广告,先删掉,否则后面一些处理需要做判断
  1909. var tempWorks = [];
  1910. for (var i = 0; i < works.length; i++) {
  1911. if (works[i].illustId) {
  1912. tempWorks.push(works[i]);
  1913. }
  1914. }
  1915. works = tempWorks;
  1916. DoLog(LogLevel.Info, 'Clear ad container complete.');
  1917. DoLog(LogLevel.Elements, works);
  1918.  
  1919. GetBookmarkCount(0);
  1920. } else {
  1921. getWorks(onloadCallback);
  1922. }
  1923. };
  1924.  
  1925. getWorks(onloadCallback);
  1926. }
  1927.  
  1928. var xhrs = [];
  1929. var currentRequestGroupMinimumIndex = 0;
  1930. function FillXhrsArray() {
  1931. xhrs.length = 0;
  1932. var onloadFunc = function (event) {
  1933. var matched = event.currentTarget.responseText.match(/bookmarkCount":(\d+)/);
  1934. if (matched) {
  1935. var bookmarkCount = matched[1];
  1936. var illustId = '';
  1937. var illustIdMatched = event.currentTarget.responseURL.match(/artworks\/(\d+)/);
  1938. if (illustIdMatched) {
  1939. illustId = illustIdMatched[1];
  1940. } else {
  1941. DoLog(LogLevel.Error, 'Can not get illust id from url!');
  1942. return;
  1943. }
  1944. var indexOfThisRequest = -1;
  1945. for (var j = 0; j < g_maxXhr; j++) {
  1946. if (xhrs[j].illustId == illustId) {
  1947. indexOfThisRequest = j;
  1948. break;
  1949. }
  1950. }
  1951. if (indexOfThisRequest == -1) {
  1952. DoLog('This url not match any request!');
  1953. return;
  1954. }
  1955. xhrs[indexOfThisRequest].complete = true;
  1956.  
  1957. works[currentRequestGroupMinimumIndex + indexOfThisRequest].bookmarkCount = parseInt(bookmarkCount);
  1958. DoLog(LogLevel.Info, 'IllustId: ' + illustId + ', bookmarkCount: ' + bookmarkCount);
  1959.  
  1960. var completeCount = 0;
  1961. for (j = 0; j < g_maxXhr; j++) {
  1962. if (xhrs[j].complete) {
  1963. completeCount++;
  1964. }
  1965. }
  1966. if (completeCount == g_maxXhr) {
  1967. $('#loading').find('#progress').text(parseInt((currentRequestGroupMinimumIndex + 1) * 1.0 / works.length * 100) + '%');
  1968. currentRequestGroupMinimumIndex += g_maxXhr;
  1969. GetBookmarkCount(currentRequestGroupMinimumIndex);
  1970. }
  1971. }
  1972. };
  1973. var onerrorFunc = function (event) {
  1974. var illustId = '';
  1975. var illustIdMatched = event.currentTarget.responseUrl.match(/artworks\/(\d+)/);
  1976. if (illustIdMatched) {
  1977. illustId = illustIdMatched[1];
  1978. } else {
  1979. DoLog(LogLevel.Error, 'Can not get illust id from url!');
  1980. return;
  1981. }
  1982.  
  1983. DoLog(LogLevel.Error, 'Send request failed, set this illust(' + illustId + ')\'s bookmark count to 0!');
  1984.  
  1985. var indexOfThisRequest = -1;
  1986. for (var j = 0; j < g_maxXhr; j++) {
  1987. if (xhrs[j].illustId == illustId) {
  1988. indexOfThisRequest = j;
  1989. break;
  1990. }
  1991. }
  1992. if (indexOfThisRequest == -1) {
  1993. DoLog('This url not match any request!');
  1994. return;
  1995. }
  1996. xhrs[indexOfThisRequest].complete = true;
  1997.  
  1998. var completeCount = 0;
  1999. for (j = 0; j < g_maxXhr; j++) {
  2000. if (xhrs[j].complete) {
  2001. completeCount++;
  2002. }
  2003. }
  2004. if (completeCount == g_maxXhr) {
  2005. $('#loading').find('#progress').text(parseInt((currentRequestGroupMinimumIndex + 1) * 1.0 / works.length * 100) + '%');
  2006. GetBookmarkCount(currentRequestGroupMinimumIndex + g_maxXhr);
  2007. }
  2008. };
  2009. for (var i = 0; i < g_maxXhr; i++) {
  2010. xhrs.push({
  2011. xhr: new XMLHttpRequest(),
  2012. illustId: '',
  2013. complete: false,
  2014. });
  2015. xhrs[i].xhr.onload = onloadFunc;
  2016. xhrs[i].xhr.onerror = onerrorFunc;
  2017. }
  2018. }
  2019.  
  2020. var GetBookmarkCount = function (index) {
  2021. if (index >= works.length) {
  2022. clearAndUpdateWorks();
  2023. return;
  2024. }
  2025.  
  2026. if (xhrs.length === 0) {
  2027. FillXhrsArray();
  2028. }
  2029.  
  2030. for (var i = 0; i < g_maxXhr; i++) {
  2031. if (index + i >= works.length) {
  2032. xhrs[i].complete = true;
  2033. continue;
  2034. }
  2035.  
  2036. var illustId = works[index + i].illustId;
  2037. var url = 'https://www.pixiv.net/artworks/' + illustId;
  2038. xhrs[i].illustId = illustId;
  2039. xhrs[i].complete = false;
  2040. xhrs[i].xhr.open('GET', url, true);
  2041. xhrs[i].xhr.send(null);
  2042. }
  2043. };
  2044.  
  2045. /*
  2046. li
  2047. -div
  2048. --div
  2049. ---div
  2050. ----div
  2051. -----div
  2052. ------a
  2053. -------div: 多图标签、R18标签
  2054. -------div: 里面是 img (以及 svg 动图标签)
  2055. ------div: 里面是 like 相关的元素
  2056. ---a: 作品标题,跳转链接
  2057. ---div: 作者头像和昵称
  2058. */
  2059. var clearAndUpdateWorks = function () {
  2060. filterAndSort();
  2061.  
  2062. var container = Pages[PageType.Search].GetImageListContainer();
  2063. var firstImageElement = Pages[PageType.Search].GetFirstImageElement();
  2064. var imageElementTemplate = firstImageElement.cloneNode(true);
  2065. // 清理模板
  2066. if (true) {
  2067. // image
  2068. var img = $($(imageElementTemplate).find('img').get(0));
  2069. var imageDiv = img.parent();
  2070. var imageLink = imageDiv.parent();
  2071. var imageLinkDiv = imageLink.parent();
  2072. var titleLink = imageLinkDiv.parent().next();
  2073. if (img == null || imageDiv == null || imageLink == null || imageLinkDiv == null || titleLink == null) {
  2074. DoLog(LogLevel.Error, 'Can not found some elements!');
  2075. }
  2076.  
  2077. // author
  2078. var authorDiv = titleLink.next();
  2079. var authorLinks = authorDiv.find('a'); // 点击头像和昵称都可以
  2080. var authorName = $(authorLinks.children('div'));
  2081. authorName.each(function (i, e) {
  2082. if ($(e).children().length === 0) {
  2083. authorName = $(e);
  2084. return false;
  2085. }
  2086. });
  2087. var authorImage = $(authorDiv.find('img').get(0));
  2088.  
  2089. // others
  2090. var bookmarkDiv = imageLink.next();
  2091. var bookmarkSvg = bookmarkDiv.find('svg');
  2092. var additionTagDiv = imageDiv.prev();
  2093. var animationTag = imageDiv.find('svg');
  2094.  
  2095. var bookmarkCountDiv = additionTagDiv.clone();
  2096. bookmarkCountDiv.css({ 'top': 'auto', 'bottom': '0px', 'width': '50%' });
  2097. additionTagDiv.parent().append(bookmarkCountDiv);
  2098.  
  2099. // 添加 class,方便后面修改内容
  2100. img.addClass('ppImg');
  2101. imageLink.addClass('ppImageLink');
  2102. titleLink.addClass('ppTitleLink');
  2103. authorLinks.addClass('ppAuthorLink');
  2104. authorName.addClass('ppAuthorName');
  2105. authorImage.addClass('ppAuthorImage');
  2106. bookmarkSvg.addClass('ppBookmarkSvg');
  2107. additionTagDiv.addClass('ppAdditionTag');
  2108. bookmarkCountDiv.addClass('ppBookmarkCount');
  2109.  
  2110. img.attr('src', '');
  2111. additionTagDiv.empty();
  2112. bookmarkCountDiv.empty();
  2113. animationTag.remove();
  2114. bookmarkSvg.find('path:first').css('fill', 'rgb(31, 31, 31)');
  2115. bookmarkSvg.find('path:last').css('fill', 'rgb(255, 255, 255)');
  2116.  
  2117. if (g_settings.linkBlank) {
  2118. imageLink.attr('target', '_blank');
  2119. titleLink.attr('target', '_blank');
  2120. authorLinks.attr('target', '_blank');
  2121. }
  2122. }
  2123.  
  2124. $(container).empty();
  2125. for (var i = 0; i < works.length; i++) {
  2126. var li = $(imageElementTemplate.cloneNode(true));
  2127.  
  2128. li.find('.ppImg').attr('src', works[i].url);
  2129. li.find('.ppImageLink').attr('href', '/artworks/' + works[i].illustId);
  2130. li.find('.ppTitleLink').attr('href', '/artworks/' + works[i].illustId).text(works[i].title);
  2131. li.find('.ppAuthorLink').attr('href', '/member.php?id=' + works[i].userId);
  2132. li.find('.ppAuthorName').text(works[i].userName);
  2133. li.find('.ppAuthorImage').attr('src', works[i].profileImageUrl);
  2134. li.find('.ppBookmarkSvg').attr('illustId', works[i].illustId);
  2135. if (works[i].bookmarkData) {
  2136. li.find('.ppBookmarkSvg').find('path').css('fill', 'rgb(255, 64, 96)');
  2137. li.find('.ppBookmarkSvg').attr('bookmarkId', works[i].bookmarkData.id);
  2138. }
  2139. if (works[i].xRestrict !== 0) {
  2140. var R18HTML = '<div style="margin-top: 2px; margin-left: 2px;"><div style="color: rgb(255, 255, 255);font-weight: bold;font-size: 10px;line-height: 1;padding: 3px 6px;border-radius: 3px;background: rgb(255, 64, 96);">R-18</div></div>';
  2141. li.find('.ppAdditionTag').append(R18HTML);
  2142. }
  2143. if (works[i].pageCount > 1) {
  2144. var pageCountHTML = '<div style="display: flex;-webkit-box-align: center;align-items: center;box-sizing: border-box;margin-left: auto;height: 20px;color: rgb(255, 255, 255);font-size: 10px;line-height: 12px;font-weight: bold;flex: 0 0 auto;padding: 4px 6px;background: rgba(0, 0, 0, 0.32);border-radius: 10px;">\<svg viewBox="0 0 9 10" width="9" height="10" style="stroke: none;line-height: 0;font-size: 0px;fill: currentcolor;"><path d="M8,3 C8.55228475,3 9,3.44771525 9,4 L9,9 C9,9.55228475 8.55228475,10 8,10 L3,10 C2.44771525,10 2,9.55228475 2,9 L6,9 C7.1045695,9 8,8.1045695 8,7 L8,3 Z M1,1 L6,1 C6.55228475,1 7,1.44771525 7,2 L7,7 C7,7.55228475 6.55228475,8 6,8 L1,8 C0.44771525,8 0,7.55228475 0,7 L0,2 C0,1.44771525 0.44771525,1 1,1 Z"></path></svg><span class="sc-fzXfOw bAzGJW">' + works[i].pageCount + '</span></div>';
  2145. li.find('.ppAdditionTag').append(pageCountHTML);
  2146. }
  2147. var bookmarkCountHTML = '<div style="margin-bottom: 6px; margin-left: 2px;"><div style="color: rgb(7, 95, 166);font-weight: bold;font-size: 13px;line-height: 1;padding: 3px 6px;border-radius: 3px;background: rgb(204, 236, 255);">' + works[i].bookmarkCount + ' likes</div></div>';
  2148. li.find('.ppBookmarkCount').append(bookmarkCountHTML);
  2149. if (works[i].illustType == 2) {
  2150. var animationHTML = '<svg viewBox="0 0 24 24" style="width: 48px; height: 48px;stroke: none;fill: rgb(255, 255, 255);line-height: 0;font-size: 0px;vertical-align: middle;position:absolute;"><circle cx="12" cy="12" r="10" style="fill: rgb(0, 0, 0);fill-opacity: 0.4;"></circle><path d="M9,8.74841664 L9,15.2515834 C9,15.8038681 9.44771525,16.2515834 10,16.2515834 C10.1782928,16.2515834 10.3533435,16.2039156 10.5070201,16.1135176 L16.0347118,12.8619342 C16.510745,12.5819147 16.6696454,11.969013 16.3896259,11.4929799 C16.3034179,11.3464262 16.1812655,11.2242738 16.0347118,11.1380658 L10.5070201,7.88648243 C10.030987,7.60646294 9.41808527,7.76536339 9.13806578,8.24139652 C9.04766776,8.39507316 9,8.57012386 9,8.74841664 Z"></path></svg>';
  2151. li.find('.ppImg').after(animationHTML);
  2152. }
  2153.  
  2154. $(container).append(li);
  2155. }
  2156.  
  2157. // 监听加入书签点击事件,监听父节点,但是按照 <svg> 节点处理
  2158. $('.ppBookmarkSvg').parent().on('click', function () {
  2159. if (g_csrfToken == '') {
  2160. DoLog(LogLevel.Error, 'No g_csrfToken, failed to add bookmark!');
  2161. alert('获取 Token 失败,无法添加,请到详情页操作。');
  2162. return;
  2163. }
  2164.  
  2165. var _this = $(this).children('svg:first');
  2166. var illustId = _this.attr('illustId');
  2167. var bookmarkId = _this.attr('bookmarkId');
  2168. if (bookmarkId == null || bookmarkId == '') {
  2169. DoLog(LogLevel.Info, 'Add bookmark, illustId: ' + illustId);
  2170. $.ajax('/ajax/illusts/bookmarks/add', {
  2171. method: 'POST',
  2172. contentType: 'application/json;charset=utf-8',
  2173. headers: { 'x-csrf-token': g_csrfToken },
  2174. data: '{"illust_id":"' + illustId + '","restrict":0,"comment":"","tags":[]}',
  2175. success: function (data) {
  2176. DoLog(LogLevel.Info, 'addBookmark result: ');
  2177. DoLog(LogLevel.Elements, data);
  2178. if (data.error) {
  2179. DoLog(LogLevel.Error, 'Server returned an error: ' + data.message);
  2180. return;
  2181. }
  2182. var bookmarkId = data.body.last_bookmark_id;
  2183. DoLog(LogLevel.Info, 'Add bookmark success, bookmarkId is ' + bookmarkId);
  2184. _this.attr('bookmarkId', bookmarkId);
  2185. _this.find('path').css('fill', 'rgb(255, 64, 96)');
  2186. }
  2187. });
  2188. } else {
  2189. DoLog(LogLevel.Info, 'Delete bookmark, bookmarkId: ' + bookmarkId);
  2190. $.ajax('/rpc/index.php', {
  2191. method: 'POST',
  2192. headers: { 'x-csrf-token': g_csrfToken },
  2193. data: { "mode": "delete_illust_bookmark", "bookmark_id": bookmarkId },
  2194. success: function (data) {
  2195. DoLog(LogLevel.Info, 'addBookmark result: ');
  2196. DoLog(LogLevel.Elements, data);
  2197. if (data.error) {
  2198. DoLog(LogLevel.Error, 'Server returned an error: ' + data.message);
  2199. return;
  2200. }
  2201. DoLog(LogLevel.Info, 'Delete bookmark success.');
  2202. _this.attr('bookmarkId', '');
  2203. _this.find('path:first').css('fill', 'rgb(31, 31, 31)');
  2204. _this.find('path:last').css('fill', 'rgb(255, 255, 255)');
  2205. }
  2206. });
  2207. }
  2208.  
  2209. _this.parent().focus();
  2210. });
  2211.  
  2212. if (works.length === 0) {
  2213. $('.column-search-result')[0].innerHTML = '<div class="_no-item">未找到任何相关结果</div>';
  2214. }
  2215.  
  2216. // 恢复显示
  2217. $('#loading').remove();
  2218. $(container).show();
  2219.  
  2220. Pages[PageType.Search].ProcessPageElements();
  2221.  
  2222. // 监听键盘的左右键,用来翻页
  2223. $(document).keydown(function (e) {
  2224. if (e.keyCode == 39) {
  2225. var btn = $('.pp-nextPage');
  2226. if (btn.length < 1 || btn.attr('hidden') == 'hidden') {
  2227. return;
  2228. }
  2229. // 很奇怪不能用 click()
  2230. location.href = btn.attr('href');
  2231. } else if (e.keyCode == 37) {
  2232. var btn = $('.pp-prevPage');
  2233. if (btn.length < 1 || btn.attr('hidden') == 'hidden') {
  2234. return;
  2235. }
  2236. location.href = btn.attr('href');
  2237. }
  2238. });
  2239.  
  2240. if (callback) {
  2241. callback();
  2242. }
  2243. }
  2244. }
  2245. /* ---------------------------------------- 设置 ---------------------------------------- */
  2246. function SetCookie(name, value) {
  2247. var Days = 180;
  2248. var exp = new Date();
  2249. exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
  2250. var str = JSON.stringify(value);
  2251. document.cookie = name + "=" + str + ";expires=" + exp.toGMTString() + ';path=\/';
  2252. }
  2253. function GetCookie(name) {
  2254. var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
  2255. if (arr = document.cookie.match(reg)) {
  2256. return unescape(arr[2]);
  2257. }
  2258. else {
  2259. return null;
  2260. }
  2261. }
  2262. function ShowInstallMessage() {
  2263. $('#pp-bg').remove();
  2264. var bg = $('<div id="pp-bg"></div>').css({
  2265. 'width': document.documentElement.clientWidth + 'px', 'height': document.documentElement.clientHeight + 'px', 'position': 'fixed',
  2266. 'z-index': 999999, 'background-color': 'rgba(0,0,0,0.8)',
  2267. 'left': '0px', 'top': '0px'
  2268. });
  2269. $('body').append(bg);
  2270.  
  2271. bg.get(0).innerHTML = '<img id="pps-close"src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/Close.png"style="position: absolute; right: 35px; top: 20px; width: 32px; height: 32px; cursor: pointer;"><div style="position: absolute;width: 40%;left: 30%;top: 25%;font-size: 25px; text-align: center; color: white;">欢迎使用 PixivPreviewer v' + g_version + '</div><br><div style="position: absolute;width: 40%;left: 30%;top: 30%;font-size: 20px; color: white;"><p style="text-indent: 2em;">小版本更新(v3.0.6),排序后的页面现在可以使用键盘的←→键进行翻页,默认关闭,需要在设置中开启。</p><p style="text-indent: 2em;"> v3.0.x 是对 v2.08 进行了大量改动后的版本,因此可能不稳定,如果发现问题,请到<a style="color: green;" href="https://greasyfork.org/zh-CN/scripts/30766-pixiv-previewer/feedback" target="_blank"> 反馈页面 </a>反馈,我会尽快修复,也欢迎提出建议,非常感谢!</p><p style="text-indent: 2em;">排序功能会比之前的版本慢,具体时间视Pixiv的加载速度而定,原因是新的搜索页面不会再显示排序所必须的收藏量。</p><p style="text-indent: 2em;">如果您是第一次使用,推荐到<a style="color: green;" href="https://greasyfork.org/zh-CN/scripts/30766-pixiv-previewer" target="_blank"> 详情页 </a>查看脚本介绍。</p></div>';
  2272. $('#pps-close').click(function () {
  2273. $('#pp-bg').remove();
  2274. });
  2275. }
  2276. function GetSettings() {
  2277. var settings;
  2278.  
  2279. var cookie = GetCookie('PixivPreview');
  2280. // 新安装
  2281. if (cookie == null || cookie == 'null') {
  2282. settings = g_defaultSettings;
  2283. SetCookie('PixivPreview', settings);
  2284.  
  2285. ShowInstallMessage();
  2286. } else {
  2287. settings = JSON.parse(cookie);
  2288. }
  2289.  
  2290. // 升级
  2291. if (settings.version != g_version) {
  2292. ShowInstallMessage();
  2293. }
  2294.  
  2295. if (settings.version == null || settings.version != g_version) {
  2296. settings.version = g_version;
  2297. SetCookie('PixivPreview', settings);
  2298. }
  2299.  
  2300. return settings;
  2301. }
  2302. function ShowSetting() {
  2303. var screenWidth = document.documentElement.clientWidth;
  2304. var screenHeight = document.documentElement.clientHeight;
  2305.  
  2306. $('#pp-bg').remove();
  2307. var bg = $('<div id="pp-bg"></div>').css({
  2308. 'width': screenWidth + 'px', 'height': screenHeight + 'px', 'position': 'fixed',
  2309. 'z-index': 999999, 'background-color': 'rgba(0,0,0,0.8)',
  2310. 'left': '0px', 'top': '0px'
  2311. });
  2312. $('body').append(bg);
  2313.  
  2314. var settings = GetSettings();
  2315.  
  2316. var settingHTML = '<div style="color: white; font-size: 1em;"><img id="pps-close" src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/Close.png" style="position: absolute; right: 35px; top: 20px; width: 32px; height: 32px; cursor: pointer;"><div style="position: absolute; width: 30%; left: 30%; top: 25%;"><ul style="list-style: none; padding: 0; margin: 0;"><li style="height: 32px; font-size: 25px;">预览</li><li style="height: 32px; font-size: 25px;">排序(仅搜索页生效)</li><li style="height: 32px; font-size: 25px;">动图下载(动图预览及详情页生效)</li><li style="height: 32px; font-size: 25px;">预览时优先显示原图(慢)</li><li style="height: 32px; font-size: 25px;"></li><li style="height: 32px; font-size: 25px;">每次排序时统计的最大页数</li><li style="height: 32px; font-size: 25px;">隐藏收藏数少于设定值的作品</li><li style="height: 32px; font-size: 25px;">排序时隐藏已收藏的作品</li><li style="height: 32px; font-size: 25px;">使用新标签页打开作品详情页</li><li style="height: 32px; font-size: 25px;">使用键盘←→进行翻页(排序后的搜索页)</li></ul></div><div id="pps-right" style="position: absolute; width: 10%; right: 30%; text-align: right; top: 25%;"><ul style="list-style: none; padding: 0; margin: 0;"><li style="height: 32px;"><img id="pps-preview" src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/On.png" style="height: 32px; cursor: pointer;"></li><li style="height: 32px;"><img id="pps-sort" src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/On.png" style="height: 32px; cursor: pointer;"></li><li style="height: 32px;"><img id="pps-anime" src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/On.png" style="height: 32px; cursor: pointer;"></li><li style="height: 32px;"><img id="pps-original" src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/On.png" style="height: 32px; cursor: pointer;"></li><li style="height: 32px;"></li><li style="height: 32px;"><input id="pps-maxPage" style="height: 28px; font-size: 24px; padding: 0px; margin: 0px; border-width: 0px; width: 64px; text-align: center;"></li><li style="height: 32px;"><input id="pps-hideLess" style="height: 28px; font-size: 24px; padding: 0px; margin: 0px; border-width: 0px; width: 64px; text-align: center;"></li><li style="height: 32px;"><img id="pps-hideBookmarked" src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/On.png" style="height: 32px; cursor: pointer;"></li><li style="height: 32px;"><img id="pps-newTab" src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/On.png" style="height: 32px; cursor: pointer;"></li><li style="height: 32px;"><img id="pps-pageKey" src="https://pp-1252089172.cos.ap-chengdu.myqcloud.com/On.png" style="height: 32px; cursor: pointer;"></li></ul></div><div style="margin-top: 10px;position: absolute;bottom: 30%;width: 100%;text-align: center;"><button id="pps-save" style="font-size: 25px;border-radius: 15px;height: 48px;width: 128px;background-color: green;color: white;margin: 0 32px 0 32px;cursor: pointer;border: none;">保存设置</button><button id="pps-reset" style="font-size: 25px;border-radius: 15px;height: 48px;width: 128px;background-color: darkred;color: white;margin: 0 32px 0 32px;cursor: pointer;border: none;">重置脚本</button></div></div>';
  2317.  
  2318. bg.get(0).innerHTML = settingHTML;
  2319.  
  2320. var imgOn = 'https://pp-1252089172.cos.ap-chengdu.myqcloud.com/On.png';
  2321. var imgOff = 'https://pp-1252089172.cos.ap-chengdu.myqcloud.com/Off.png'
  2322. $('#pps-preview').attr('src', settings.enablePreview ? imgOn : imgOff).addClass(settings.enablePreview ? 'on' : 'off');
  2323. $('#pps-sort').attr('src', settings.enableSort ? imgOn : imgOff).addClass(settings.enableSort ? 'on' : 'off');
  2324. $('#pps-anime').attr('src', settings.enableAnimeDownload ? imgOn : imgOff).addClass(settings.enableAnimeDownload ? 'on' : 'off');
  2325. $('#pps-original').attr('src', settings.original ? imgOn : imgOff).addClass(settings.original ? 'on' : 'off');
  2326. $('#pps-maxPage').val(settings.pageCount);
  2327. $('#pps-hideLess').val(settings.favFilter);
  2328. $('#pps-hideBookmarked').attr('src', settings.hideFavorite ? imgOn : imgOff).addClass(settings.hideFavorite ? 'on' : 'off');
  2329. $('#pps-newTab').attr('src', settings.linkBlank ? imgOn : imgOff).addClass(settings.linkBlank ? 'on' : 'off');
  2330. $('#pps-pageKey').attr('src', settings.pageByKey ? imgOn : imgOff).addClass(settings.pageByKey ? 'on' : 'off');
  2331.  
  2332. $('#pps-right').find('img').click(function () {
  2333. var _this = $(this);
  2334.  
  2335. if (_this.hasClass('on')) {
  2336. _this.attr('src', imgOff).removeClass('on').addClass('off');
  2337. } else {
  2338. _this.attr('src', imgOn).removeClass('off').addClass('on');
  2339. }
  2340. });
  2341.  
  2342. $('#pps-save').click(function () {
  2343. if ($('#pps-maxPage').val() === '') {
  2344. $('#pps-maxPage').val(g_defaultSettings.pageCount);
  2345. }
  2346. if ($('#pps-hideLess').val() == '') {
  2347. $('#pps-hideLess').val(g_defaultSettings.favFilter);
  2348. }
  2349.  
  2350. var settings = {
  2351. 'enablePreview': $('#pps-preview').hasClass('on') ? 1 : 0,
  2352. 'enableSort': $('#pps-sort').hasClass('on') ? 1 : 0,
  2353. 'enableAnimeDownload': $('#pps-anime').hasClass('on') ? 1 : 0,
  2354. 'original': $('#pps-original').hasClass('on') ? 1 : 0,
  2355. 'pageCount': parseInt($('#pps-maxPage').val()),
  2356. 'favFilter': parseInt($('#pps-hideLess').val()),
  2357. 'hideFavorite': $('#pps-hideBookmarked').hasClass('on') ? 1 : 0,
  2358. 'linkBlank': $('#pps-newTab').hasClass('on') ? 1 : 0,
  2359. 'pageBytKey': $('#pps-pageKey').hasClass('on') ? 1 : 0,
  2360. 'version': g_version,
  2361. }
  2362.  
  2363. SetCookie('PixivPreview', settings);
  2364.  
  2365. location.href = location.href;
  2366. });
  2367.  
  2368. $('#pps-reset').click(function () {
  2369. var comfirmText = "这会删除所有设置,相当于重新安装脚本,确定要重置吗?";
  2370. if (confirm(comfirmText)) {
  2371. SetCookie('PixivPreview', null);
  2372. location.href = location.href;
  2373. }
  2374. });
  2375.  
  2376. $('#pps-close').click(function () {
  2377. $('#pp-bg').remove();
  2378. });
  2379. }
  2380. /* --------------------------------------- 主函数 --------------------------------------- */
  2381. var loadInterval = setInterval(function () {
  2382. // 匹配当前页面
  2383. for (var i = 0; i < PageType.PageTypeCount; i++) {
  2384. if (Pages[i].CheckUrl(location.href)) {
  2385. g_pageType = i;
  2386. break;
  2387. }
  2388. }
  2389. if (g_pageType >= 0) {
  2390. DoLog(LogLevel.Info, 'Current page is ' + Pages[g_pageType].PageTypeString);
  2391. } else {
  2392. DoLog(LogLevel.Info, 'Unsupported page.');
  2393. clearInterval(loadInterval);
  2394. return;
  2395. }
  2396.  
  2397. // 设置按钮
  2398. var toolBar = Pages[g_pageType].GetToolBar();
  2399. if (toolBar) {
  2400. DoLog(LogLevel.Elements, toolBar);
  2401. clearInterval(loadInterval);
  2402. } else {
  2403. DoLog(LogLevel.Warning, 'Get toolbar failed.');
  2404. return;
  2405. }
  2406.  
  2407. toolBar.appendChild(toolBar.firstChild.cloneNode(true));
  2408. toolBar.lastChild.outerHTML = '<button style="background-color: rgb(0, 0, 0);margin-top: 5px;opacity: 0.8;cursor: pointer;border: none;padding: 12px;border-radius: 24px;width: 48px;height: 48px;"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve" style="fill: white;"><metadata> Svg Vector Icons : http://www.sfont.cn </metadata><g><path d="M377.5,500c0,67.7,54.8,122.5,122.5,122.5S622.5,567.7,622.5,500S567.7,377.5,500,377.5S377.5,432.3,377.5,500z"></path><path d="M990,546v-94.8L856.2,411c-8.9-35.8-23-69.4-41.6-100.2L879,186L812,119L689,185.2c-30.8-18.5-64.4-32.6-100.2-41.5L545.9,10h-94.8L411,143.8c-35.8,8.9-69.5,23-100.2,41.5L186.1,121l-67,66.9L185.2,311c-18.6,30.8-32.6,64.4-41.5,100.3L10,454v94.8L143.8,589c8.9,35.8,23,69.4,41.6,100.2L121,814l67,67l123-66.2c30.8,18.6,64.5,32.6,100.3,41.5L454,990h94.8L589,856.2c35.8-8.9,69.4-23,100.2-41.6L814,879l67-67l-66.2-123.1c18.6-30.7,32.6-64.4,41.5-100.2L990,546z M500,745c-135.3,0-245-109.7-245-245c0-135.3,109.7-245,245-245s245,109.7,245,245C745,635.3,635.3,745,500,745z"></path></g></svg></button>';
  2409. $(toolBar.lastChild).css('margin-top', '10px');
  2410. $(toolBar.lastChild).css('opacity', '0.8');
  2411. $(toolBar.lastChild).click(function () {
  2412. ShowSetting();
  2413. });
  2414.  
  2415. // 读取设置
  2416. g_settings = GetSettings();
  2417.  
  2418. // g_csrfToken
  2419. if (g_pageType == PageType.Search) {
  2420. $.get(location.href, function (data) {
  2421. var matched = data.match(/token":"([a-z0-9]{32})/);
  2422. if (matched.length > 0) {
  2423. g_csrfToken = matched[1];
  2424. DoLog(LogLevel.Info, 'Got g_csrfToken: ' + g_csrfToken);
  2425. } else {
  2426. DoLog(LogLevel.Error, 'Can not get g_csrfToken, so you can not add works to bookmark when sorting has enabled.');
  2427. }
  2428. });
  2429. }
  2430.  
  2431. // 现在 P站点击一些按钮不会重新加载页面了,脚本也不会重新加载,会导致一些问题。如果检测到 url 变了,就刷新一下
  2432. setInterval(function () {
  2433. if (location.href != initialUrl) {
  2434. location.href = location.href;
  2435. }
  2436. }, 1000);
  2437.  
  2438. // 排序、预览
  2439. var itv = setInterval(function () {
  2440. var returnMap = Pages[g_pageType].ProcessPageElements();
  2441. if (!returnMap.loadingComplete) {
  2442. return;
  2443. }
  2444.  
  2445. DoLog(LogLevel.Info, 'Process page comlete, sorting and prevewing begin.');
  2446. DoLog(LogLevel.Elements, returnMap);
  2447.  
  2448. clearInterval(itv);
  2449.  
  2450. if (g_settings.linkBlank) {
  2451. $(returnMap.controlElements).find('a').attr('target', '_blank');
  2452. }
  2453.  
  2454. try {
  2455. if (g_pageType == PageType.Artwork) {
  2456. Pages[g_pageType].Work();
  2457. }
  2458. else if (g_pageType == PageType.Search) {
  2459. if (g_settings.enableSort) {
  2460. PixivSK(g_settings.enablePreview ? PixivPreview : null);
  2461. } else if (g_settings.enablePreview) {
  2462. PixivPreview();
  2463. }
  2464. } else if (g_settings.enablePreview) {
  2465. PixivPreview();
  2466. }
  2467. }
  2468. catch (e) {
  2469. DoLog(LogLevel.Error, 'Unknown error: ' + e);
  2470. }
  2471. }, 500);
  2472. }, 1000);