NJPW World Infinite Video Scrolling

Infinite scrolling for the NJPW World video library, powered by Metafizzy's Infinite-Scroll.js

目前为 2018-10-12 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name NJPW World Infinite Video Scrolling
  3. // @version 1.0.2
  4. // @description Infinite scrolling for the NJPW World video library, powered by Metafizzy's Infinite-Scroll.js
  5. // @namespace http://about.me/daveyjacobson
  6. // @author Davey Jacobson <daveyjake21@gmail.com>
  7. // @match *://njpwworld.com/search/latest*
  8. // @require https://unpkg.com/infinite-scroll@3/dist/infinite-scroll.pkgd.min.js
  9. // @grant none
  10. // @noframes
  11. // ==/UserScript==
  12. (function( win, undefined ) {
  13. 'use strict';
  14.  
  15. // Standard globals.
  16. var doc = document,
  17. html = doc.documentElement,
  18. head = doc.head,
  19. body = doc.body;
  20.  
  21. // Begin NJPW Infinite Scroll.
  22. var njpwInfScroll = {
  23. containerParent: '.contents-left',
  24. container: '.second-movie-box',
  25. target: '.movieArea',
  26. paginate: '.pager',
  27. nextPage: 'a.next',
  28. pageLoadStatusClass: '.page-load-status',
  29. pageLoadStatus: '<style id="infAnimation">.loader-wheel{font-size:64px;position:relative;height:1em;width:1em;padding-left:.45em;overflow:hidden;margin:0 auto;animation:loader-wheel-rotate .5s steps(12) infinite}.loader-wheel i{display:block;position:absolute;height:.3em;width:.1em;border-radius:.05em;background:#333;opacity:.8;transform:rotate(-30deg);transform-origin:center .5em}@keyframes loader-wheel-rotate{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}</style><p class="infinite-scroll-request"><div class="loader-wheel"><i><i><i><i><i><i><i><i><i><i><i><i></i></i></i></i></i></i></i></i></i></i></i></i></div></p><p class="infinite-scroll-last">End of content</p><p class="infinite-scroll-error">No more pages to load</p>',
  30.  
  31. /**
  32. * jQuery's `$.extend` in pure vanilla JS.
  33. *
  34. * @author Chris Ferdinandi <chris@gomakethings.com>
  35. * @see {@link https://gomakethings.com/vanilla-javascript-version-of-jquery-extend}
  36. *
  37. * For a deep extend, set the `deep` argument to `true`.
  38. */
  39. extend: function () {
  40. // Variables
  41. var extended = {},
  42. deep = false,
  43. i = 0,
  44. length = arguments.length;
  45.  
  46. // Check if a deep merge
  47. if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) {
  48. deep = arguments[0];
  49. i++;
  50. }
  51. // Merge the object into the extended object
  52. var merge = function (obj) {
  53. for ( var prop in obj ) {
  54. if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) {
  55. // If deep merge and property is an object, merge properties
  56. if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) {
  57. extended[prop] = extend( true, extended[prop], obj[prop] );
  58. } else {
  59. extended[prop] = obj[prop];
  60. }
  61. }
  62. }
  63. };
  64. // Loop through each object and conduct a merge
  65. for ( ; i < length; i++ ) {
  66. var obj = arguments[i];
  67. merge(obj);
  68. }
  69.  
  70. return extended;
  71. },
  72.  
  73. /**
  74. * New Mutation Observer
  75. *
  76. * @memberof njpwInfScroll
  77. * @function
  78. * @requires njpwInfScroll#parseArgs
  79. *
  80. * @param {Object} args {
  81. * Default function arguments.
  82. *
  83. * @type {String} targetNode Element selector string.
  84. * @type {Function|String} callback Custom callback function.
  85. * @type {Bool} foundation Checks if `callback` is Foundation selector.
  86. * }
  87. */
  88. mutant: function( args ) {
  89. var defaults = {
  90. 'targetNode': '',
  91. 'callback': '',
  92. 'foundation': false,
  93. 'childList': true,
  94. 'attributes': false,
  95. 'subtree': true
  96. };
  97.  
  98. args = this.parseArgs( args, defaults );
  99.  
  100. // Check for any abnormalities.
  101. var // Make sure we know the node selector we're dealing with.
  102. isClass = ( '#' === args.targetNode.charAt(0) ? false : true ),
  103. // Get the proper method based on the node.
  104. method = ( false === isClass ? 'getElementById' : 'getElementsByClassName' ),
  105. // Clean up the selector.
  106. selector = ( null !== args.targetNode.charAt(0).match( /(\#|\.)/ ) ? args.targetNode.slice(1) : args.targetNode ),
  107. // Select the node that will be observed for mutations.
  108. element = ( 'getElementById' === method ? doc[ method ]( selector ) : doc[ method ]( selector )[0] ),
  109. // Options for the observer (which mutations to observe).
  110. config = { attributes: args.attributes, childList: args.childList, subtree: args.subtree };
  111.  
  112. // Listener function to execute when mutations are observed.
  113. var listen = function( mutationsList, observer ) {
  114. for ( var mutation of mutationsList ) {
  115. if ( args.childList && 'childList' === mutation.type )
  116. {
  117. if ( ! args.foundation && args.callback && 'function' === typeof( args.callback ) )
  118. {
  119. args.callback();
  120. }
  121. else
  122. {
  123. mutation.addedNodes.forEach( function( el ) {
  124. $( el ).find( args.callback ).foundation();
  125. });
  126. }
  127. }
  128. else if ( args.attributes && 'attributes' === mutation.type )
  129. {
  130. console.log( mutation.attributeName );
  131. }
  132. else
  133. {
  134. console.log( mutation );
  135. }
  136. }
  137. };
  138. // Create an observer instance linked to the callback function
  139. win.observer = new MutationObserver( listen );
  140. // Start observing the target node for configured mutations
  141. observer.observe( element, config );
  142. },
  143.  
  144. /**
  145. * Disconnect `mutant` listener.
  146. *
  147. * @return void
  148. */
  149. mutantDisconnect: function() {
  150. if ( ! win.observer ) {
  151. return;
  152. }
  153. else {
  154. observer.disconnect();
  155. }
  156. },
  157.  
  158. /**
  159. * `ParseArgs` for JavaScript; like `wp_parse_args`.
  160. *
  161. * @memberof njpwInfScroll
  162. * @function
  163. *
  164. * @param {Object} args Function parameters.
  165. * @param {Object} defaults Function parameter default values.
  166. */
  167. parseArgs: function( args, defaults ) {
  168. if ( typeof args !== 'object' )
  169. {
  170. args = {};
  171. }
  172.  
  173. if ( typeof defaults !== 'object' )
  174. {
  175. defaults = {};
  176. }
  177. return this.extend( {}, defaults, args );
  178. },
  179.  
  180. /**
  181. * Add the necessary nodes and styles.
  182. *
  183. * @memberof njpwInfScroll
  184. * @function
  185. */
  186. stylesAndSettings: function() {
  187. var self = this;
  188. // The node location to insert the actual `spinning wheel` HTML.
  189. var videoWall = doc.querySelectorAll( self.containerParent )[0],
  190. videoPaged = videoWall.children[3],
  191. spinWheel = doc.createElement( 'div' );
  192. // Spinning Wheel attributes.
  193. spinWheel.className = this.pageLoadStatusClass.slice(1);
  194. spinWheel.innerHTML = this.pageLoadStatus;
  195. spinWheel.style.marginTop = '-25px';
  196. spinWheel.style.marginBottom = '25px';
  197. spinWheel.style.textAlign = 'center';
  198. // Insert `spinning wheel`.
  199. videoWall.insertBefore( spinWheel, videoPaged );
  200. },
  201. init: function() {
  202. var self = this,
  203. loadInfScroll = function() {
  204. if ( win.InfiniteScroll ) {
  205. var infScroll = new InfiniteScroll( self.container, {
  206. path: 'latest?page={{#}}',
  207. append: self.target,
  208. checkLastPage: self.nextPage,
  209. hideNav: self.paginate,
  210. status: self.pageLoadStatusClass,
  211. debug: false
  212. });
  213. }
  214. },
  215. args = {
  216. targetNode: self.container,
  217. callback: loadInfScroll
  218. };
  219.  
  220. this.stylesAndSettings();
  221. this.mutant( args );
  222.  
  223. if ( '/search/latest' !== location.pathname ) {
  224. this.mutantDisconnect();
  225. }
  226. }
  227. };
  228. njpwInfScroll.init();
  229. })(window);