NewFaceForDokiitoys

New Face For Dokiitoys

  1. // ==UserScript==
  2. // @name NewFaceForDokiitoys
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description New Face For Dokiitoys
  6. // @author Mesak
  7. // @match https://www.dokiitoys.com/faq
  8. // @match https://www.dokiitoys.com/member/wishlist
  9. // @require https://code.jquery.com/jquery-2.1.4.min.js
  10. // @require https://cdnjs.cloudflare.com/ajax/libs/template7/1.4.1/template7.min.js
  11. // @license MIT
  12. // @grant GM_addElement
  13. // @grant GM_addStyle
  14. // ==/UserScript==
  15.  
  16. (function($) {
  17. //'use strict';
  18. const BaseUrl = 'https://www.dokiitoys.com/'
  19. $('link[href^="https://hinetcdn.waca.ec"]').remove();
  20.  
  21. GM_addElement('link', {
  22. href: 'https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css',
  23. rel: 'stylesheet'
  24. });
  25. GM_addElement('link', {
  26. href: 'https://cdnjs.cloudflare.com/ajax/libs/admin-lte/3.2.0/css/adminlte.min.css',
  27. rel: 'stylesheet'
  28. });
  29.  
  30.  
  31. const appMainTmpl = `
  32. <aside class="main-sidebar sidebar-dark-primary elevation-4">
  33. <section class="sidebar os-host os-theme-light os-host-overflow os-host-overflow-y os-host-resize-disabled os-host-scrollbar-horizontal-hidden os-host-transition" id="sidebar">
  34. </section>
  35. </aside>
  36. <div class="content-wrapper">
  37. <section class="content-header">
  38. <div class="container-fluid">
  39. <div class="well well-sm">
  40. <strong>Category Title</strong>
  41. <div class="btn-group">
  42. <a href="#" id="list" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-th-list">
  43. </span>List</a> <a href="#" id="grid" class="btn btn-default btn-sm"><span
  44. class="glyphicon glyphicon-th"></span>Grid</a>
  45. </div>
  46. </div>
  47. </div>
  48. </section>
  49. <section class="content" id="content">
  50. <div class="container-fluid">
  51. <div class="card card-solid">
  52. <div class="card-body pb-0">
  53. <div class="row" id="productList"></div>
  54. <div id="moreProduct"></div>
  55. </div>
  56. </div>
  57. </div>
  58. </section>
  59. </div>
  60. `;
  61. const productListTmpl = `
  62. {{#each list}}
  63. <div class="col-12 col-sm-6 col-md-4 d-flex align-items-stretch flex-column">
  64. <div class="card bg-light d-flex flex-fill">
  65. <div class="card-header text-muted border-bottom-0">
  66. {{title}}
  67. </div>
  68. <div class="card-body pt-0">
  69. <div class="row">
  70. <div class="col">
  71. <img src="{{photo}}" alt="{{title}}" class="img-fluid w-100">
  72. </div>
  73. </div>
  74. </div>
  75. <div class="card-footer">
  76. <div class="text-right">
  77. <p class="lead">{{product_price price}}</p>
  78. <a href="{{link}}" class="btn btn-sm btn-primary">
  79. <i class="fas fa-cart"></i> 產品連結
  80. </a>
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. {{/each}}
  86. `
  87. const btnMoreProductTmpl = `<button class="btn btn-success" id="btnLoadMore" data-cid="{{cid}}" data-type="{{type}}" data-page="{{page}}">more</button>`
  88. GM_addStyle(`.glyphicon { margin-right:5px; }
  89. `)
  90. Template7.registerHelper('product_price', function (price) {
  91. return price.toString() == '0' ? '完售' : price;
  92. });
  93.  
  94. let $sidebarHTML = $('.el_nav_aside_inner').clone().attr('class','nav nav-pills nav-sidebar flex-column');
  95. $sidebarHTML.find('li').attr('class','nav-item');
  96. $sidebarHTML.find('ul').attr('class','nav');
  97. $sidebarHTML.find('a').attr('class','nav-link').removeAttr('style');
  98. $sidebarHTML.find('input').remove();
  99.  
  100. document.querySelector('body').setAttribute('class','sidebar-mini layout-fixed')
  101. document.querySelector('body').setAttribute('style','height: auto;')
  102. document.querySelector('body').innerHTML = Template7.compile(`<div id="app" class="wrapper">{{ body }}</div>`)({body:appMainTmpl});
  103. var resource = new Map();
  104. var $eleContent = $('#content')
  105. var $eleSidebar = $('#sidebar')
  106. var $eleProductList = $('#productList')
  107. var $eleMoreProduct = $('#moreProduct')
  108.  
  109. $eleSidebar.append( $sidebarHTML );
  110. $eleSidebar.on('click' , 'a', (e)=>{
  111. let url = $(e.currentTarget).attr('href')
  112. getContent( getUrl( url ) )
  113. e.preventDefault()
  114. })
  115. $eleMoreProduct.on('click','#btnLoadMore' , ()=>{
  116. if( $('#btnLoadMore').data('type') == 'category'){
  117. runGetCategory( $('#btnLoadMore').data('cid') , $('#btnLoadMore').data('page') )
  118. }else{
  119. runGetNew($('#btnLoadMore').data('page') )
  120. }
  121. })
  122. runGetNew( 1 )
  123. function getUrl( url ){
  124. return BaseUrl + url.replace(BaseUrl,'');
  125. }
  126. function getContent( url ){
  127. let RegExpObject = /category\/(\d+)/
  128. if( url.indexOf( 'category/' ) != -1 && RegExpObject.test(url)){
  129. let categoryId = url.match(RegExpObject)[1];
  130. $eleProductList.empty();
  131. runGetCategory(categoryId,1);
  132. }
  133. }
  134.  
  135. function runGetNew( page ){
  136. getProductList('newest', null , page).then( (result) => {
  137. $.each(result, (index,item) => {
  138. resource.set(item.id, item);
  139. })
  140. return {list:result}
  141. }).then( (data) => {
  142. //console.log( data )
  143. if( data.list.length == 20){
  144. $eleMoreProduct.html(Template7.compile(btnMoreProductTmpl)({page : (page+1), 'type':'newest'}))
  145. }else{
  146. $eleMoreProduct.empty();
  147. }
  148. $eleProductList.append( Template7.compile(productListTmpl)(data))
  149. })
  150. }
  151. function runGetCategory(cid, page ){
  152. getProductList('category',cid , page).then( (result) => {
  153. $.each(result, (index,item) => {
  154. resource.set(item.id, item);
  155. })
  156. return {list:result}
  157. }).then( (data) => {
  158. //console.log( data )
  159. if( data.list.length == 20){
  160. $eleMoreProduct.html(Template7.compile(btnMoreProductTmpl)({cid: cid , page : (page+1) , 'type':'category'}))
  161. setTimeout( ()=>{
  162. $('#btnLoadMore').click();
  163. },500)
  164.  
  165. }else{
  166. $eleMoreProduct.empty();
  167. }
  168. $eleProductList.append( Template7.compile(productListTmpl)(data))
  169. })
  170. }
  171.  
  172. function getProductList(type = 'category',categoryId = null , page = 1){
  173. return new Promise((resolve, reject) => {
  174. $.post( 'https://www.dokiitoys.com/productlist' ,{
  175. type: type,
  176. value: categoryId,
  177. sort: 'newest',
  178. page: page
  179. } , (response)=>{
  180. let oFragmeng = $(document.createDocumentFragment());
  181. oFragmeng.append(response);
  182. let result = [];
  183. $('li.item_block', oFragmeng).each( (key,node) => {
  184. let itemPhoto = $('span.item_photo',node);
  185. let itemLink = $('a.clearfix:first',node);
  186. let itemBtn = $('button.js_wishlist_add',node);
  187. let item = {
  188. id : itemBtn.attr('data-pid'),
  189. link : itemLink.attr('href'),
  190. photo : itemPhoto.attr('data-src'),
  191. title : itemPhoto.attr('title'),
  192. price : 0 ,
  193. }
  194. if( $('span.font_montserrat',node).length )
  195. {
  196. item.price = $('span.font_montserrat',node).text()
  197. }
  198. result.push(item)
  199. })
  200. resolve(result);
  201. })
  202. });
  203. }
  204.  
  205. })(window.jQuery);