j1-template 2021.1.26 → 2021.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/_includes/themes/j1/layouts/content_generator_article_navigator.html +1 -1
  3. data/_includes/themes/j1/layouts/content_generator_blog_archive.html +6 -4
  4. data/_includes/themes/j1/layouts/content_generator_post.html +3 -0
  5. data/_includes/themes/j1/modules/navigator/generator.html +1 -1
  6. data/_includes/themes/j1/procedures/posts/collate_timeline.proc +1 -1
  7. data/_includes/themes/j1/procedures/posts/create_series_header.proc +6 -6
  8. data/_layouts/default.html +1 -0
  9. data/assets/data/mdil_icons.json +2417 -0
  10. data/assets/data/panel.html +0 -15
  11. data/assets/themes/j1/adapter/js/j1.js +6 -6
  12. data/assets/themes/j1/adapter/js/j1scroll.js +143 -46
  13. data/assets/themes/j1/core/css/icon-fonts/materialdesign-light.css +1222 -0
  14. data/assets/themes/j1/core/css/icon-fonts/materialdesign-light.min.css +1 -0
  15. data/assets/themes/j1/core/css/icon-fonts/materialdesign.css +1 -1
  16. data/assets/themes/j1/core/css/themes/uno-light/bootstrap.css +42 -0
  17. data/assets/themes/j1/core/css/themes/uno-light/bootstrap.min.css +1 -1
  18. data/assets/themes/j1/core/fonts/material_design_icons_light/fonts/eot/materialdesignicons-light-webfont.eot +0 -0
  19. data/assets/themes/j1/core/fonts/material_design_icons_light/fonts/materialdesignicons-light-webfont.woff +0 -0
  20. data/assets/themes/j1/core/fonts/material_design_icons_light/fonts/materialdesignicons-light-webfont.woff2 +0 -0
  21. data/assets/themes/j1/core/fonts/material_design_icons_light/fonts/svg/materialdesignicons-light-webfont.svg +801 -0
  22. data/assets/themes/j1/core/fonts/material_design_icons_light/fonts/ttf/materialdesignicons-light-webfont.ttf +0 -0
  23. data/assets/themes/j1/core/js/template.js +4 -4
  24. data/assets/themes/j1/core/js/template.js.map +1 -1
  25. data/assets/themes/j1/core/js/template.min.js +4 -4
  26. data/assets/themes/j1/core/js/template.min.js.map +1 -1
  27. data/assets/themes/j1/modules/j1Scroll/css/theme/uno.css +4 -50
  28. data/assets/themes/j1/modules/j1Scroll/css/theme/uno.min.css +1 -1
  29. data/assets/themes/j1/modules/j1Scroll/js/j1scroll.js +263 -188
  30. data/assets/themes/j1/modules/j1Scroll/js/j1scroll.min.js +16 -0
  31. data/assets/themes/j1/modules/mdiPreviewer/css/previewer.css +1 -1
  32. data/assets/themes/j1/modules/mdiPreviewer/css/previewer.min.css +1 -1
  33. data/assets/themes/j1/modules/mdiPreviewer/js/previewer.js +5 -15
  34. data/assets/themes/j1/modules/mdiPreviewer/js/previewer.min.js +1 -1
  35. data/assets/themes/j1/modules/mdilPreviewer/css/previewer.css +97 -0
  36. data/assets/themes/j1/modules/mdilPreviewer/css/previewer.min.css +15 -0
  37. data/assets/themes/j1/modules/mdilPreviewer/js/previewer.js +125 -0
  38. data/assets/themes/j1/modules/mdilPreviewer/js/previewer.min.js +15 -0
  39. data/assets/themes/j1/modules/showOnScroll/js/showOnScroll.js +73 -74
  40. data/assets/themes/j1/modules/showOnScroll/js/showOnScroll.min.js +15 -15
  41. data/lib/j1/commands/generate.rb +5 -8
  42. data/lib/j1/version.rb +3 -3
  43. data/lib/starter_web/Gemfile +1 -1
  44. data/lib/starter_web/_config.yml +3 -3
  45. data/lib/starter_web/_data/blocks/banner.yml +4 -5
  46. data/lib/starter_web/_data/blocks/panel.yml +217 -183
  47. data/lib/starter_web/_data/builder/blog_navigator.yml +1 -0
  48. data/lib/starter_web/_data/layouts/home.yml +20 -16
  49. data/lib/starter_web/_data/modules/defaults/navigator.yml +1 -1
  50. data/lib/starter_web/_data/modules/j1scroll.yml +67 -0
  51. data/lib/starter_web/_data/modules/navigator_menu.yml +3 -3
  52. data/lib/starter_web/_data/resources.yml +41 -44
  53. data/lib/starter_web/_includes/attributes.asciidoc +1 -1
  54. data/lib/starter_web/_plugins/lunr_index.rb +1 -1
  55. data/lib/starter_web/assets/images/modules/attics/annie-spratt-1920x1280.jpg +0 -0
  56. data/lib/starter_web/assets/images/modules/attics/antonino-visalli-1920x1280.jpg +0 -0
  57. data/lib/starter_web/assets/images/modules/attics/humble-lamb-1920x1280.jpg +0 -0
  58. data/lib/starter_web/assets/images/modules/attics/library-1920x1280.jpg +0 -0
  59. data/lib/starter_web/assets/images/modules/attics/romain-vignes-1920x1280.jpg +0 -0
  60. data/lib/starter_web/assets/images/modules/attics/sigmund-1920x1280.jpg +0 -0
  61. data/lib/starter_web/assets/images/{pages/videos → modules/attics}/szabo-viktor-1920x1280.jpg +0 -0
  62. data/lib/starter_web/assets/images/pages/asciidoc_skeletons/example-pdf-screenshot.png +0 -0
  63. data/lib/starter_web/collections/posts/public/featured/_posts/{2020-01-01-about-cookies.adoc → 2021-01-01-about-cookies.adoc} +0 -0
  64. data/lib/starter_web/collections/posts/public/featured/_posts/{2021-03-01-site-generators.adoc → 2021-02-01-site-generators.adoc} +0 -0
  65. data/lib/starter_web/collections/posts/public/{wikipedia/_posts/2016-11-20-minneapolis.adoc → series/_posts/2020-01-01-post-wiki-series.adoc} +11 -10
  66. data/lib/starter_web/collections/posts/public/{wikipedia/_posts/2016-11-24-narcisse-snake-dens.adoc → series/_posts/2020-01-02-post-wiki-series.adoc} +15 -13
  67. data/lib/starter_web/collections/posts/public/{wikipedia/_posts/2016-11-26-columbia-river.adoc → series/_posts/2020-01-03-post-wiki-series.adoc} +28 -11
  68. data/lib/starter_web/collections/posts/public/{wikipedia → series}/_posts/_includes/attributes.asciidoc +0 -0
  69. data/lib/starter_web/collections/posts/public/{wikipedia → series}/_posts/_includes/documents/readme +0 -0
  70. data/lib/starter_web/collections/posts/public/{wikipedia → series}/_posts/_includes/tables/readme +0 -0
  71. data/lib/starter_web/index.html +2 -2
  72. data/lib/starter_web/package.json +1 -1
  73. data/lib/starter_web/pages/public/asciidoc_skeletons/{book → documentation}/000_intro.adoc +5 -7
  74. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/100_converter.adoc +43 -0
  75. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/200_themes.adoc +61 -0
  76. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/attributes.asciidoc +95 -0
  77. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/000_intro.asciidoc +54 -0
  78. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/100_converter/000_basic_example.asciidoc +31 -0
  79. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/100_converter/111_about_the_converter.asciidoc +111 -0
  80. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/100_converter/112_getting_started.asciidoc +95 -0
  81. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/100_converter/113_themes.asciidoc +39 -0
  82. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/100_converter.asciidoc +8 -0
  83. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/200_themes/211_language_overview.asciidoc +122 -0
  84. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/200_themes/212_values.asciidoc +502 -0
  85. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/200_themes/213_fonts.asciidoc +261 -0
  86. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/_includes/documents/200_themes.asciidoc +8 -0
  87. data/lib/starter_web/pages/public/asciidoc_skeletons/{book → documentation}/a2p.bat +1 -1
  88. data/lib/starter_web/pages/public/asciidoc_skeletons/{book → documentation}/a2p.sh +2 -2
  89. data/lib/starter_web/pages/public/asciidoc_skeletons/{book/book.a2p → documentation/documentation.a2p} +2 -8
  90. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/documentation.adoc +86 -0
  91. data/lib/starter_web/pages/public/asciidoc_skeletons/multi-document/_includes/documents/100_chapter.asciidoc +848 -40
  92. data/lib/starter_web/pages/public/asciidoc_skeletons/multi-document/_includes/documents/200_chapter.asciidoc +149 -38
  93. data/lib/starter_web/pages/public/asciidoc_skeletons/multi-document/multi.adoc +2 -7
  94. data/lib/starter_web/pages/public/asciidoc_skeletons/simple-document/simple.adoc +312 -119
  95. data/lib/starter_web/pages/public/blog/navigator/index.html +3 -2
  96. data/lib/starter_web/pages/public/previewer/mdi_icons_preview.adoc +2 -2
  97. data/lib/starter_web/pages/public/previewer/mdil_icons_preview.adoc +76 -0
  98. data/lib/starter_web/utilsrv/_defaults/package.json +1 -1
  99. data/lib/starter_web/utilsrv/package.json +1 -1
  100. metadata +52 -59
  101. data/assets/themes/j1/adapter/js/infiniteScroll.js +0 -259
  102. data/assets/themes/j1/modules/infiniteScroll/css/theme/uno.css +0 -150
  103. data/assets/themes/j1/modules/infiniteScroll/css/theme/uno.min.css +0 -15
  104. data/assets/themes/j1/modules/infiniteScroll/js/infiniteScroll.js +0 -1915
  105. data/assets/themes/j1/modules/infiniteScroll/js/infiniteScroll.min.js +0 -17
  106. data/lib/starter_web/_data/modules/defaults/infiniteScroll.yml +0 -73
  107. data/lib/starter_web/_data/modules/infiniteScroll.yml +0 -66
  108. data/lib/starter_web/collections/posts/public/series/_posts/2020-01-01-post-test-series.adoc +0 -128
  109. data/lib/starter_web/collections/posts/public/series/_posts/2020-01-02-post-test-series.adoc +0 -131
  110. data/lib/starter_web/collections/posts/public/series/_posts/2020-01-03-post-test-series.adoc +0 -131
  111. data/lib/starter_web/collections/posts/public/series/_posts/2020-01-04-post-test-series.adoc +0 -132
  112. data/lib/starter_web/pages/infinite-scroll-tester-5.adoc +0 -119
  113. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/asciidoc-extensions/blindtext.asciidoc +0 -11
  114. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/asciidoc-extensions/font_icons.asciidoc +0 -23
  115. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/asciidoc-extensions/gallery.asciidoc +0 -5
  116. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/asciidoc-extensions/lightbox.asciidoc +0 -7
  117. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/documents/chapter_document.asciidoc +0 -9
  118. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/documents/entry_document.asciidoc +0 -3
  119. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/images/image.asciidoc +0 -6
  120. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/tables/table_2_column.asciidoc +0 -12
  121. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/tables/table_2_column_options.asciidoc +0 -30
  122. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/tables/table_3_column.asciidoc +0 -16
  123. data/lib/starter_web/pages/public/asciidoc_skeletons/_templates/tables/table_4_column.asciidoc +0 -25
  124. data/lib/starter_web/pages/public/asciidoc_skeletons/book/100_chapter.adoc +0 -62
  125. data/lib/starter_web/pages/public/asciidoc_skeletons/book/200_chapter.adoc +0 -64
  126. data/lib/starter_web/pages/public/asciidoc_skeletons/book/900_references.adoc +0 -73
  127. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/attributes.asciidoc +0 -74
  128. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/000_intro.asciidoc +0 -33
  129. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/100_chapter/100_chapter_document.asciidoc +0 -21
  130. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/100_chapter/110_chapter_document.asciidoc +0 -36
  131. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/100_chapter.asciidoc +0 -7
  132. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/200_chapter/200_chapter_document.asciidoc +0 -53
  133. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/200_chapter.asciidoc +0 -5
  134. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/900_references/000_intro.asciidoc +0 -23
  135. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/900_references/100_chapter_document.asciidoc +0 -33
  136. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/900_references/200_chapter_document.asciidoc +0 -26
  137. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/900_references/900_sources.asciidoc +0 -81
  138. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/900_references.asciidoc +0 -23
  139. data/lib/starter_web/pages/public/asciidoc_skeletons/book/_includes/documents/tables/110_material_design_icons.asciidoc +0 -102
  140. data/lib/starter_web/pages/public/asciidoc_skeletons/book/book.adoc +0 -136
  141. data/lib/starter_web/pages/public/asciidoc_skeletons/multi-document/100_chapter.asciidoc +0 -60
  142. data/lib/starter_web/pages/public/asciidoc_skeletons/multi-document/200_chapter.asciidoc +0 -59
  143. data/lib/starter_web/pages/public/asciidoc_skeletons/multi-document/_includes/documents/tables/110_material_design_icons.asciidoc +0 -102
@@ -1,1915 +0,0 @@
1
- /*!
2
- * Infinite Scroll PACKAGED v4.0.1
3
- * Automatically add next page
4
- *
5
- * Licensed GPLv3 for open source use
6
- * or Infinite Scroll Commercial License for commercial use
7
- *
8
- * https://infinite-scroll.com
9
- * Copyright 2018-2020 Metafizzy
10
- */
11
-
12
- /**
13
- * Bridget makes jQuery widgets
14
- * v3.0.0
15
- * MIT license
16
- */
17
-
18
- ( function( window, factory ) {
19
- // module definition
20
- if ( typeof module == 'object' && module.exports ) {
21
- // CommonJS
22
- module.exports = factory(
23
- window,
24
- require('jquery'),
25
- );
26
- } else {
27
- // browser global
28
- window.jQueryBridget = factory(
29
- window,
30
- window.jQuery,
31
- );
32
- }
33
-
34
- }( window, function factory( window, jQuery ) {
35
-
36
- // ----- utils ----- //
37
-
38
- // helper function for logging errors
39
- // $.error breaks jQuery chaining
40
- let console = window.console;
41
- let logError = typeof console == 'undefined' ? function() {} :
42
- function( message ) {
43
- console.error( message );
44
- };
45
-
46
- // ----- jQueryBridget ----- //
47
-
48
- function jQueryBridget( namespace, PluginClass, $ ) {
49
- $ = $ || jQuery || window.jQuery;
50
- if ( !$ ) {
51
- return;
52
- }
53
-
54
- // add option method -> $().plugin('option', {...})
55
- if ( !PluginClass.prototype.option ) {
56
- // option setter
57
- PluginClass.prototype.option = function( opts ) {
58
- if ( !opts ) return;
59
-
60
- this.options = Object.assign( this.options || {}, opts );
61
- };
62
- }
63
-
64
- // make jQuery plugin
65
- $.fn[ namespace ] = function( arg0, ...args ) {
66
- if ( typeof arg0 == 'string' ) {
67
- // method call $().plugin( 'methodName', { options } )
68
- return methodCall( this, arg0, args );
69
- }
70
- // just $().plugin({ options })
71
- plainCall( this, arg0 );
72
- return this;
73
- };
74
-
75
- // $().plugin('methodName')
76
- function methodCall( $elems, methodName, args ) {
77
- let returnValue;
78
- let pluginMethodStr = `$().${namespace}("${methodName}")`;
79
-
80
- $elems.each( function( i, elem ) {
81
- // get instance
82
- let instance = $.data( elem, namespace );
83
- if ( !instance ) {
84
- logError( `${namespace} not initialized.` +
85
- ` Cannot call method ${pluginMethodStr}` );
86
- return;
87
- }
88
-
89
- let method = instance[ methodName ];
90
- if ( !method || methodName.charAt( 0 ) == '_' ) {
91
- logError(`${pluginMethodStr} is not a valid method`);
92
- return;
93
- }
94
-
95
- // apply method, get return value
96
- let value = method.apply( instance, args );
97
- // set return value if value is returned, use only first value
98
- returnValue = returnValue === undefined ? value : returnValue;
99
- } );
100
-
101
- return returnValue !== undefined ? returnValue : $elems;
102
- }
103
-
104
- function plainCall( $elems, options ) {
105
- $elems.each( function( i, elem ) {
106
- let instance = $.data( elem, namespace );
107
- if ( instance ) {
108
- // set options & init
109
- instance.option( options );
110
- instance._init();
111
- } else {
112
- // initialize new instance
113
- instance = new PluginClass( elem, options );
114
- $.data( elem, namespace, instance );
115
- }
116
- } );
117
- }
118
-
119
- }
120
-
121
- // ----- ----- //
122
-
123
- return jQueryBridget;
124
-
125
- } ) );
126
- /**
127
- * EvEmitter v2.0.0
128
- * Lil' event emitter
129
- * MIT License
130
- */
131
-
132
- ( function( global, factory ) {
133
- // universal module definition
134
- if ( typeof module == 'object' && module.exports ) {
135
- // CommonJS - Browserify, Webpack
136
- module.exports = factory();
137
- } else {
138
- // Browser globals
139
- global.EvEmitter = factory();
140
- }
141
-
142
- }( typeof window != 'undefined' ? window : this, function() {
143
-
144
- function EvEmitter() {}
145
-
146
- let proto = EvEmitter.prototype;
147
-
148
- proto.on = function( eventName, listener ) {
149
- if ( !eventName || !listener ) return this;
150
-
151
- // set events hash
152
- let events = this._events = this._events || {};
153
- // set listeners array
154
- let listeners = events[ eventName ] = events[ eventName ] || [];
155
- // only add once
156
- if ( !listeners.includes( listener ) ) {
157
- listeners.push( listener );
158
- }
159
-
160
- return this;
161
- };
162
-
163
- proto.once = function( eventName, listener ) {
164
- if ( !eventName || !listener ) return this;
165
-
166
- // add event
167
- this.on( eventName, listener );
168
- // set once flag
169
- // set onceEvents hash
170
- let onceEvents = this._onceEvents = this._onceEvents || {};
171
- // set onceListeners object
172
- let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
173
- // set flag
174
- onceListeners[ listener ] = true;
175
-
176
- return this;
177
- };
178
-
179
- proto.off = function( eventName, listener ) {
180
- let listeners = this._events && this._events[ eventName ];
181
- if ( !listeners || !listeners.length ) return this;
182
-
183
- let index = listeners.indexOf( listener );
184
- if ( index != -1 ) {
185
- listeners.splice( index, 1 );
186
- }
187
-
188
- return this;
189
- };
190
-
191
- proto.emitEvent = function( eventName, args ) {
192
- let listeners = this._events && this._events[ eventName ];
193
- if ( !listeners || !listeners.length ) return this;
194
-
195
- // copy over to avoid interference if .off() in listener
196
- listeners = listeners.slice( 0 );
197
- args = args || [];
198
- // once stuff
199
- let onceListeners = this._onceEvents && this._onceEvents[ eventName ];
200
-
201
- for ( let listener of listeners ) {
202
- let isOnce = onceListeners && onceListeners[ listener ];
203
- if ( isOnce ) {
204
- // remove listener
205
- // remove before trigger to prevent recursion
206
- this.off( eventName, listener );
207
- // unset once flag
208
- delete onceListeners[ listener ];
209
- }
210
- // trigger listener
211
- listener.apply( this, args );
212
- }
213
-
214
- return this;
215
- };
216
-
217
- proto.allOff = function() {
218
- delete this._events;
219
- delete this._onceEvents;
220
- return this;
221
- };
222
-
223
- return EvEmitter;
224
-
225
- } ) );
226
- /**
227
- * Fizzy UI utils v3.0.0
228
- * MIT license
229
- */
230
-
231
- ( function( global, factory ) {
232
- // universal module definition
233
- if ( typeof module == 'object' && module.exports ) {
234
- // CommonJS
235
- module.exports = factory( global );
236
- } else {
237
- // browser global
238
- global.fizzyUIUtils = factory( global );
239
- }
240
-
241
- }( this, function factory( global ) {
242
-
243
- let utils = {};
244
-
245
- // ----- extend ----- //
246
-
247
- // extends objects
248
- utils.extend = function( a, b ) {
249
- return Object.assign( a, b );
250
- };
251
-
252
- // ----- modulo ----- //
253
-
254
- utils.modulo = function( num, div ) {
255
- return ( ( num % div ) + div ) % div;
256
- };
257
-
258
- // ----- makeArray ----- //
259
-
260
- // turn element or nodeList into an array
261
- utils.makeArray = function( obj ) {
262
- // use object if already an array
263
- if ( Array.isArray( obj ) ) return obj;
264
-
265
- // return empty array if undefined or null. #6
266
- if ( obj === null || obj === undefined ) return [];
267
-
268
- let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
269
- // convert nodeList to array
270
- if ( isArrayLike ) return [ ...obj ];
271
-
272
- // array of single index
273
- return [ obj ];
274
- };
275
-
276
- // ----- removeFrom ----- //
277
-
278
- utils.removeFrom = function( ary, obj ) {
279
- let index = ary.indexOf( obj );
280
- if ( index != -1 ) {
281
- ary.splice( index, 1 );
282
- }
283
- };
284
-
285
- // ----- getParent ----- //
286
-
287
- utils.getParent = function( elem, selector ) {
288
- while ( elem.parentNode && elem != document.body ) {
289
- elem = elem.parentNode;
290
- if ( elem.matches( selector ) ) return elem;
291
- }
292
- };
293
-
294
- // ----- getQueryElement ----- //
295
-
296
- // use element as selector string
297
- utils.getQueryElement = function( elem ) {
298
- if ( typeof elem == 'string' ) {
299
- return document.querySelector( elem );
300
- }
301
- return elem;
302
- };
303
-
304
- // ----- handleEvent ----- //
305
-
306
- // enable .ontype to trigger from .addEventListener( elem, 'type' )
307
- utils.handleEvent = function( event ) {
308
- let method = 'on' + event.type;
309
- if ( this[ method ] ) {
310
- this[ method ]( event );
311
- }
312
- };
313
-
314
- // ----- filterFindElements ----- //
315
-
316
- utils.filterFindElements = function( elems, selector ) {
317
- // make array of elems
318
- elems = utils.makeArray( elems );
319
-
320
- return elems
321
- // check that elem is an actual element
322
- .filter( ( elem ) => elem instanceof HTMLElement )
323
- .reduce( ( ffElems, elem ) => {
324
- // add elem if no selector
325
- if ( !selector ) {
326
- ffElems.push( elem );
327
- return ffElems;
328
- }
329
- // filter & find items if we have a selector
330
- // filter
331
- if ( elem.matches( selector ) ) {
332
- ffElems.push( elem );
333
- }
334
- // find children
335
- let childElems = elem.querySelectorAll( selector );
336
- // concat childElems to filterFound array
337
- ffElems = ffElems.concat( ...childElems );
338
- return ffElems;
339
- }, [] );
340
- };
341
-
342
- // ----- debounceMethod ----- //
343
-
344
- utils.debounceMethod = function( _class, methodName, threshold ) {
345
- threshold = threshold || 100;
346
- // original method
347
- let method = _class.prototype[ methodName ];
348
- let timeoutName = methodName + 'Timeout';
349
-
350
- _class.prototype[ methodName ] = function() {
351
- clearTimeout( this[ timeoutName ] );
352
-
353
- let args = arguments;
354
- this[ timeoutName ] = setTimeout( () => {
355
- method.apply( this, args );
356
- delete this[ timeoutName ];
357
- }, threshold );
358
- };
359
- };
360
-
361
- // ----- docReady ----- //
362
-
363
- utils.docReady = function( onDocReady ) {
364
- let readyState = document.readyState;
365
- if ( readyState == 'complete' || readyState == 'interactive' ) {
366
- // do async to allow for other scripts to run. metafizzy/flickity#441
367
- setTimeout( onDocReady );
368
- } else {
369
- document.addEventListener( 'DOMContentLoaded', onDocReady );
370
- }
371
- };
372
-
373
- // ----- htmlInit ----- //
374
-
375
- // http://bit.ly/3oYLusc
376
- utils.toDashed = function( str ) {
377
- return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
378
- return $1 + '-' + $2;
379
- } ).toLowerCase();
380
- };
381
-
382
- let console = global.console;
383
-
384
- // allow user to initialize classes via [data-namespace] or .js-namespace class
385
- // htmlInit( Widget, 'widgetName' )
386
- // options are parsed from data-namespace-options
387
- utils.htmlInit = function( WidgetClass, namespace ) {
388
- utils.docReady( function() {
389
- let dashedNamespace = utils.toDashed( namespace );
390
- let dataAttr = 'data-' + dashedNamespace;
391
- let dataAttrElems = document.querySelectorAll( `[${dataAttr}]` );
392
- let jQuery = global.jQuery;
393
-
394
- [ ...dataAttrElems ].forEach( ( elem ) => {
395
- let attr = elem.getAttribute( dataAttr );
396
- let options;
397
- try {
398
- options = attr && JSON.parse( attr );
399
- } catch ( error ) {
400
- // log error, do not initialize
401
- if ( console ) {
402
- console.error( `Error parsing ${dataAttr} on ${elem.className}: ${error}` );
403
- }
404
- return;
405
- }
406
- // initialize
407
- let instance = new WidgetClass( elem, options );
408
- // make available via $().data('namespace')
409
- if ( jQuery ) {
410
- jQuery.data( elem, namespace, instance );
411
- }
412
- } );
413
-
414
- } );
415
- };
416
-
417
- // ----- ----- //
418
-
419
- return utils;
420
-
421
- } ) );
422
- // core
423
- ( function( window, factory ) {
424
- // universal module definition
425
- if ( typeof module == 'object' && module.exports ) {
426
- // CommonJS
427
- module.exports = factory(
428
- window,
429
- require('ev-emitter'),
430
- require('fizzy-ui-utils'),
431
- );
432
- } else {
433
- // browser global
434
- window.InfiniteScroll = factory(
435
- window,
436
- window.EvEmitter,
437
- window.fizzyUIUtils,
438
- );
439
- }
440
-
441
- }( window, function factory( window, EvEmitter, utils ) {
442
-
443
- let jQuery = window.jQuery;
444
- // internal store of all InfiniteScroll intances
445
- let instances = {};
446
-
447
- function InfiniteScroll( element, options ) {
448
- let queryElem = utils.getQueryElement( element );
449
-
450
- if ( !queryElem ) {
451
- console.error( 'Bad element for InfiniteScroll: ' + ( queryElem || element ) );
452
- return;
453
- }
454
- element = queryElem;
455
- // do not initialize twice on same element
456
- if ( element.infiniteScrollGUID ) {
457
- let instance = instances[ element.infiniteScrollGUID ];
458
- instance.option( options );
459
- return instance;
460
- }
461
-
462
- this.element = element;
463
- // options
464
- this.options = { ...InfiniteScroll.defaults };
465
- this.option( options );
466
- // add jQuery
467
- if ( jQuery ) {
468
- this.$element = jQuery( this.element );
469
- }
470
-
471
- this.create();
472
- }
473
-
474
- // defaults
475
- InfiniteScroll.defaults = {
476
- // path: null,
477
- // hideNav: null,
478
- // debug: false,
479
- };
480
-
481
- // create & destroy methods
482
- InfiniteScroll.create = {};
483
- InfiniteScroll.destroy = {};
484
-
485
- let proto = InfiniteScroll.prototype;
486
- // inherit EvEmitter
487
- Object.assign( proto, EvEmitter.prototype );
488
-
489
- // -------------------------- -------------------------- //
490
-
491
- // globally unique identifiers
492
- let GUID = 0;
493
-
494
- proto.create = function() {
495
- // create core
496
- // add id for InfiniteScroll.data
497
- let id = this.guid = ++GUID;
498
- this.element.infiniteScrollGUID = id; // expando
499
- instances[ id ] = this; // associate via id
500
- // properties
501
- this.pageIndex = 1; // default to first page
502
- this.loadCount = 0;
503
- this.updateGetPath();
504
- // bail if getPath not set, or returns falsey #776
505
- let hasPath = this.getPath && this.getPath();
506
- if ( !hasPath ) {
507
- console.error('Disabling InfiniteScroll');
508
- return;
509
- }
510
- this.updateGetAbsolutePath();
511
- this.log( 'initialized', [ this.element.className ] );
512
- this.callOnInit();
513
- // create features
514
- for ( let method in InfiniteScroll.create ) {
515
- InfiniteScroll.create[ method ].call( this );
516
- }
517
- };
518
-
519
- proto.option = function( opts ) {
520
- Object.assign( this.options, opts );
521
- };
522
-
523
- // call onInit option, used for binding events on init
524
- proto.callOnInit = function() {
525
- let onInit = this.options.onInit;
526
- if ( onInit ) {
527
- onInit.call( this, this );
528
- }
529
- };
530
-
531
- // ----- events ----- //
532
-
533
- proto.dispatchEvent = function( type, event, args ) {
534
- this.log( type, args );
535
- let emitArgs = event ? [ event ].concat( args ) : args;
536
- this.emitEvent( type, emitArgs );
537
- // trigger jQuery event
538
- if ( !jQuery || !this.$element ) {
539
- return;
540
- }
541
- // namespace jQuery event
542
- type += '.infiniteScroll';
543
- let $event = type;
544
- if ( event ) {
545
- // create jQuery event
546
- /* eslint-disable-next-line new-cap */
547
- let jQEvent = jQuery.Event( event );
548
- jQEvent.type = type;
549
- $event = jQEvent;
550
- }
551
- this.$element.trigger( $event, args );
552
- };
553
-
554
- let loggers = {
555
- initialized: ( className ) => `on ${className}`,
556
- request: ( path ) => `URL: ${path}`,
557
- load: ( response, path ) => `${response.title || ''}. URL: ${path}`,
558
- error: ( error, path ) => `${error}. URL: ${path}`,
559
- append: ( response, path, items ) => `${items.length} items. URL: ${path}`,
560
- last: ( response, path ) => `URL: ${path}`,
561
- history: ( title, path ) => `URL: ${path}`,
562
- pageIndex: function( index, origin ) {
563
- return `current page determined to be: ${index} from ${origin}`;
564
- },
565
- };
566
-
567
- // log events
568
- proto.log = function( type, args ) {
569
- if ( !this.options.debug ) return;
570
-
571
- let message = `[InfiniteScroll] ${type}`;
572
- let logger = loggers[ type ];
573
- if ( logger ) message += '. ' + logger.apply( this, args );
574
- console.log( message );
575
- };
576
-
577
- // -------------------------- methods used amoung features -------------------------- //
578
-
579
- proto.updateMeasurements = function() {
580
- this.windowHeight = window.innerHeight;
581
- let rect = this.element.getBoundingClientRect();
582
- this.top = rect.top + window.scrollY;
583
- };
584
-
585
- proto.updateScroller = function() {
586
- let elementScroll = this.options.elementScroll;
587
- if ( !elementScroll ) {
588
- // default, use window
589
- this.scroller = window;
590
- return;
591
- }
592
- // if true, set to element, otherwise use option
593
- this.scroller = elementScroll === true ? this.element :
594
- utils.getQueryElement( elementScroll );
595
- if ( !this.scroller ) {
596
- throw new Error(`Unable to find elementScroll: ${elementScroll}`);
597
- }
598
- };
599
-
600
- // -------------------------- page path -------------------------- //
601
-
602
- proto.updateGetPath = function() {
603
- let optPath = this.options.path;
604
- if ( !optPath ) {
605
- console.error(`InfiniteScroll path option required. Set as: ${optPath}`);
606
- return;
607
- }
608
- // function
609
- let type = typeof optPath;
610
- if ( type == 'function' ) {
611
- this.getPath = optPath;
612
- return;
613
- }
614
- // template string: '/pages/{{#}}.html'
615
- let templateMatch = type == 'string' && optPath.match('{{#}}');
616
- if ( templateMatch ) {
617
- this.updateGetPathTemplate( optPath );
618
- return;
619
- }
620
- // selector: '.next-page-selector'
621
- this.updateGetPathSelector( optPath );
622
- };
623
-
624
- proto.updateGetPathTemplate = function( optPath ) {
625
- // set getPath with template string
626
- this.getPath = () => {
627
- let nextIndex = this.pageIndex + 1;
628
- return optPath.replace( '{{#}}', nextIndex );
629
- };
630
- // get pageIndex from location
631
- // convert path option into regex to look for pattern in location
632
- // escape query (?) in url, allows for parsing GET parameters
633
- let regexString = optPath
634
- .replace( /(\\\?|\?)/, '\\?' )
635
- .replace( '{{#}}', '(\\d\\d?\\d?)' );
636
- let templateRe = new RegExp( regexString );
637
- let match = location.href.match( templateRe );
638
-
639
- if ( match ) {
640
- this.pageIndex = parseInt( match[1], 10 );
641
- this.log( 'pageIndex', [ this.pageIndex, 'template string' ] );
642
- }
643
- };
644
-
645
- let pathRegexes = [
646
- // WordPress & Tumblr - example.com/page/2
647
- // Jekyll - example.com/page2
648
- /^(.*?\/?page\/?)(\d\d?\d?)(.*?$)/,
649
- // Drupal - example.com/?page=1
650
- /^(.*?\/?\?page=)(\d\d?\d?)(.*?$)/,
651
- // catch all, last occurence of a number
652
- /(.*?)(\d\d?\d?)(?!.*\d)(.*?$)/,
653
- ];
654
-
655
- // try matching href to pathRegexes patterns
656
- let getPathParts = InfiniteScroll.getPathParts = function( href ) {
657
- if ( !href ) return;
658
- for ( let regex of pathRegexes ) {
659
- let match = href.match( regex );
660
- if ( match ) {
661
- let [ , begin, index, end ] = match;
662
- return { begin, index, end };
663
- }
664
- }
665
- };
666
-
667
- proto.updateGetPathSelector = function( optPath ) {
668
- // parse href of link: '.next-page-link'
669
- let hrefElem = document.querySelector( optPath );
670
- if ( !hrefElem ) {
671
- console.error(`Bad InfiniteScroll path option. Next link not found: ${optPath}`);
672
- return;
673
- }
674
-
675
- let href = hrefElem.getAttribute('href');
676
- let pathParts = getPathParts( href );
677
- if ( !pathParts ) {
678
- console.error(`InfiniteScroll unable to parse next link href: ${href}`);
679
- return;
680
- }
681
-
682
- let { begin, index, end } = pathParts;
683
- this.isPathSelector = true; // flag for checkLastPage()
684
- this.getPath = () => begin + ( this.pageIndex + 1 ) + end;
685
- // get pageIndex from href
686
- this.pageIndex = parseInt( index, 10 ) - 1;
687
- this.log( 'pageIndex', [ this.pageIndex, 'next link' ] );
688
- };
689
-
690
- proto.updateGetAbsolutePath = function() {
691
- let path = this.getPath();
692
- // path doesn't start with http or /
693
- let isAbsolute = path.match( /^http/ ) || path.match( /^\// );
694
- if ( isAbsolute ) {
695
- this.getAbsolutePath = this.getPath;
696
- return;
697
- }
698
-
699
- let { pathname } = location;
700
- // query parameter #829. example.com/?pg=2
701
- let isQuery = path.match( /^\?/ );
702
- // /foo/bar/index.html => /foo/bar
703
- let directory = pathname.substring( 0, pathname.lastIndexOf('/') );
704
- let pathStart = isQuery ? pathname : directory + '/';
705
-
706
- this.getAbsolutePath = () => pathStart + this.getPath();
707
- };
708
-
709
- // -------------------------- nav -------------------------- //
710
-
711
- // hide navigation
712
- InfiniteScroll.create.hideNav = function() {
713
- let nav = utils.getQueryElement( this.options.hideNav );
714
- if ( !nav ) return;
715
-
716
- nav.style.display = 'none';
717
- this.nav = nav;
718
- };
719
-
720
- InfiniteScroll.destroy.hideNav = function() {
721
- if ( this.nav ) this.nav.style.display = '';
722
- };
723
-
724
- // -------------------------- destroy -------------------------- //
725
-
726
- proto.destroy = function() {
727
- this.allOff(); // remove all event listeners
728
- // call destroy methods
729
- for ( let method in InfiniteScroll.destroy ) {
730
- InfiniteScroll.destroy[ method ].call( this );
731
- }
732
-
733
- delete this.element.infiniteScrollGUID;
734
- delete instances[ this.guid ];
735
- // remove jQuery data. #807
736
- if ( jQuery && this.$element ) {
737
- jQuery.removeData( this.element, 'infiniteScroll' );
738
- }
739
- };
740
-
741
- // -------------------------- utilities -------------------------- //
742
-
743
- // https://remysharp.com/2010/07/21/throttling-function-calls
744
- InfiniteScroll.throttle = function( fn, threshold ) {
745
- threshold = threshold || 200;
746
- let last, timeout;
747
-
748
- return function() {
749
- let now = +new Date();
750
- let args = arguments;
751
- let trigger = () => {
752
- last = now;
753
- fn.apply( this, args );
754
- };
755
- if ( last && now < last + threshold ) {
756
- // hold on to it
757
- clearTimeout( timeout );
758
- timeout = setTimeout( trigger, threshold );
759
- } else {
760
- trigger();
761
- }
762
- };
763
- };
764
-
765
- InfiniteScroll.data = function( elem ) {
766
- elem = utils.getQueryElement( elem );
767
- let id = elem && elem.infiniteScrollGUID;
768
- return id && instances[ id ];
769
- };
770
-
771
- // set internal jQuery, for Webpack + jQuery v3
772
- InfiniteScroll.setJQuery = function( jqry ) {
773
- jQuery = jqry;
774
- };
775
-
776
- // -------------------------- setup -------------------------- //
777
-
778
- utils.htmlInit( InfiniteScroll, 'infinite-scroll' );
779
-
780
- // add noop _init method for jQuery Bridget. #768
781
- proto._init = function() {};
782
-
783
- let { jQueryBridget } = window;
784
- if ( jQuery && jQueryBridget ) {
785
- jQueryBridget( 'infiniteScroll', InfiniteScroll, jQuery );
786
- }
787
-
788
- // -------------------------- -------------------------- //
789
-
790
- return InfiniteScroll;
791
-
792
- } ) );
793
- // page-load
794
- ( function( window, factory ) {
795
- // universal module definition
796
- if ( typeof module == 'object' && module.exports ) {
797
- // CommonJS
798
- module.exports = factory(
799
- window,
800
- require('./core'),
801
- );
802
- } else {
803
- // browser global
804
- factory(
805
- window,
806
- window.InfiniteScroll,
807
- );
808
- }
809
-
810
- }( window, function factory( window, InfiniteScroll ) {
811
-
812
- let proto = InfiniteScroll.prototype;
813
-
814
- Object.assign( InfiniteScroll.defaults, {
815
- // append: false,
816
- loadOnScroll: true,
817
- checkLastPage: true,
818
- responseBody: 'text',
819
- domParseResponse: true,
820
- // prefill: false,
821
- // outlayer: null,
822
- } );
823
-
824
- InfiniteScroll.create.pageLoad = function() {
825
- this.canLoad = true;
826
- this.on( 'scrollThreshold', this.onScrollThresholdLoad );
827
- this.on( 'load', this.checkLastPage );
828
- if ( this.options.outlayer ) {
829
- this.on( 'append', this.onAppendOutlayer );
830
- }
831
- };
832
-
833
- proto.onScrollThresholdLoad = function() {
834
- if ( this.options.loadOnScroll ) this.loadNextPage();
835
- };
836
-
837
- let domParser = new DOMParser();
838
-
839
- proto.loadNextPage = function() {
840
- if ( this.isLoading || !this.canLoad ) return;
841
-
842
- let { responseBody, domParseResponse, fetchOptions } = this.options;
843
- let path = this.getAbsolutePath();
844
- this.isLoading = true;
845
- if ( typeof fetchOptions == 'function' ) fetchOptions = fetchOptions();
846
-
847
- let fetchPromise = fetch( path, fetchOptions )
848
- .then( ( response ) => {
849
- if ( !response.ok ) {
850
- let error = new Error( response.statusText );
851
- this.onPageError( error, path, response );
852
- return { response };
853
- }
854
-
855
- return response[ responseBody ]().then( ( body ) => {
856
- let canDomParse = responseBody == 'text' && domParseResponse;
857
- if ( canDomParse ) {
858
- body = domParser.parseFromString( body, 'text/html' );
859
- }
860
- if ( response.status == 204 ) {
861
- this.lastPageReached( body, path );
862
- return { body, response };
863
- } else {
864
- return this.onPageLoad( body, path, response );
865
- }
866
- } );
867
- } )
868
- .catch( ( error ) => {
869
- this.onPageError( error, path );
870
- } );
871
-
872
- this.dispatchEvent( 'request', null, [ path, fetchPromise ] );
873
-
874
- return fetchPromise;
875
- };
876
-
877
- proto.onPageLoad = function( body, path, response ) {
878
- // done loading if not appending
879
- if ( !this.options.append ) {
880
- this.isLoading = false;
881
- }
882
- this.pageIndex++;
883
- this.loadCount++;
884
- this.dispatchEvent( 'load', null, [ body, path, response ] );
885
- return this.appendNextPage( body, path, response );
886
- };
887
-
888
- proto.appendNextPage = function( body, path, response ) {
889
- let { append, responseBody, domParseResponse } = this.options;
890
- // do not append json
891
- let isDocument = responseBody == 'text' && domParseResponse;
892
- if ( !isDocument || !append ) return { body, response };
893
-
894
- let items = body.querySelectorAll( append );
895
- let promiseValue = { body, response, items };
896
- // last page hit if no items. #840
897
- if ( !items || !items.length ) {
898
- this.lastPageReached( body, path );
899
- return promiseValue;
900
- }
901
-
902
- let fragment = getItemsFragment( items );
903
- let appendReady = () => {
904
- this.appendItems( items, fragment );
905
- this.isLoading = false;
906
- this.dispatchEvent( 'append', null, [ body, path, items, response ] );
907
- return promiseValue;
908
- };
909
-
910
- // TODO add hook for option to trigger appendReady
911
- if ( this.options.outlayer ) {
912
- return this.appendOutlayerItems( fragment, appendReady );
913
- } else {
914
- return appendReady();
915
- }
916
- };
917
-
918
- proto.appendItems = function( items, fragment ) {
919
- if ( !items || !items.length ) return;
920
-
921
- // get fragment if not provided
922
- fragment = fragment || getItemsFragment( items );
923
- refreshScripts( fragment );
924
- this.element.appendChild( fragment );
925
- };
926
-
927
- function getItemsFragment( items ) {
928
- // add items to fragment
929
- let fragment = document.createDocumentFragment();
930
- if ( items ) fragment.append( ...items );
931
- return fragment;
932
- }
933
-
934
- // replace <script>s with copies so they load
935
- // <script>s added by InfiniteScroll will not load
936
- // similar to https://stackoverflow.com/questions/610995
937
- function refreshScripts( fragment ) {
938
- let scripts = fragment.querySelectorAll('script');
939
- for ( let script of scripts ) {
940
- let freshScript = document.createElement('script');
941
- // copy attributes
942
- let attrs = script.attributes;
943
- for ( let attr of attrs ) {
944
- freshScript.setAttribute( attr.name, attr.value );
945
- }
946
- // copy inner script code. #718, #782
947
- freshScript.innerHTML = script.innerHTML;
948
- script.parentNode.replaceChild( freshScript, script );
949
- }
950
- }
951
-
952
- // ----- outlayer ----- //
953
-
954
- proto.appendOutlayerItems = function( fragment, appendReady ) {
955
- let imagesLoaded = InfiniteScroll.imagesLoaded || window.imagesLoaded;
956
- if ( !imagesLoaded ) {
957
- console.error('[InfiniteScroll] imagesLoaded required for outlayer option');
958
- this.isLoading = false;
959
- return;
960
- }
961
- // append once images loaded
962
- return new Promise( function( resolve ) {
963
- imagesLoaded( fragment, function() {
964
- let bodyResponse = appendReady();
965
- resolve( bodyResponse );
966
- } );
967
- } );
968
- };
969
-
970
- proto.onAppendOutlayer = function( response, path, items ) {
971
- this.options.outlayer.appended( items );
972
- };
973
-
974
- // ----- checkLastPage ----- //
975
-
976
- // check response for next element
977
- proto.checkLastPage = function( body, path ) {
978
- let { checkLastPage, path: pathOpt } = this.options;
979
- if ( !checkLastPage ) return;
980
-
981
- // if path is function, check if next path is truthy
982
- if ( typeof pathOpt == 'function' ) {
983
- let nextPath = this.getPath();
984
- if ( !nextPath ) {
985
- this.lastPageReached( body, path );
986
- return;
987
- }
988
- }
989
- // get selector from checkLastPage or path option
990
- let selector;
991
- if ( typeof checkLastPage == 'string' ) {
992
- selector = checkLastPage;
993
- } else if ( this.isPathSelector ) {
994
- // path option is selector string
995
- selector = pathOpt;
996
- }
997
- // check last page for selector
998
- // bail if no selector or not document response
999
- if ( !selector || !body.querySelector ) return;
1000
-
1001
- // check if response has selector
1002
- let nextElem = body.querySelector( selector );
1003
- if ( !nextElem ) this.lastPageReached( body, path );
1004
- };
1005
-
1006
- proto.lastPageReached = function( body, path ) {
1007
- this.canLoad = false;
1008
- this.dispatchEvent( 'last', null, [ body, path ] );
1009
- };
1010
-
1011
- // ----- error ----- //
1012
-
1013
- proto.onPageError = function( error, path, response ) {
1014
- this.isLoading = false;
1015
- this.canLoad = false;
1016
- this.dispatchEvent( 'error', null, [ error, path, response ] );
1017
- return error;
1018
- };
1019
-
1020
- // -------------------------- prefill -------------------------- //
1021
-
1022
- InfiniteScroll.create.prefill = function() {
1023
- if ( !this.options.prefill ) return;
1024
-
1025
- let append = this.options.append;
1026
- if ( !append ) {
1027
- console.error(`append option required for prefill. Set as :${append}`);
1028
- return;
1029
- }
1030
- this.updateMeasurements();
1031
- this.updateScroller();
1032
- this.isPrefilling = true;
1033
- this.on( 'append', this.prefill );
1034
- this.once( 'error', this.stopPrefill );
1035
- this.once( 'last', this.stopPrefill );
1036
- this.prefill();
1037
- };
1038
-
1039
- proto.prefill = function() {
1040
- let distance = this.getPrefillDistance();
1041
- this.isPrefilling = distance >= 0;
1042
- if ( this.isPrefilling ) {
1043
- this.log('prefill');
1044
- this.loadNextPage();
1045
- } else {
1046
- this.stopPrefill();
1047
- }
1048
- };
1049
-
1050
- proto.getPrefillDistance = function() {
1051
- // element scroll
1052
- if ( this.options.elementScroll ) {
1053
- return this.scroller.clientHeight - this.scroller.scrollHeight;
1054
- }
1055
- // window
1056
- return this.windowHeight - this.element.clientHeight;
1057
- };
1058
-
1059
- proto.stopPrefill = function() {
1060
- this.log('stopPrefill');
1061
- this.off( 'append', this.prefill );
1062
- };
1063
-
1064
- // -------------------------- -------------------------- //
1065
-
1066
- return InfiniteScroll;
1067
-
1068
- } ) );
1069
- // scroll-watch
1070
- ( function( window, factory ) {
1071
- // universal module definition
1072
- if ( typeof module == 'object' && module.exports ) {
1073
- // CommonJS
1074
- module.exports = factory(
1075
- window,
1076
- require('./core'),
1077
- require('fizzy-ui-utils'),
1078
- );
1079
- } else {
1080
- // browser global
1081
- factory(
1082
- window,
1083
- window.InfiniteScroll,
1084
- window.fizzyUIUtils,
1085
- );
1086
- }
1087
-
1088
- }( window, function factory( window, InfiniteScroll, utils ) {
1089
-
1090
- let proto = InfiniteScroll.prototype;
1091
-
1092
- // default options
1093
- Object.assign( InfiniteScroll.defaults, {
1094
- scrollThreshold: 400,
1095
- // elementScroll: null,
1096
- } );
1097
-
1098
- // jadams
1099
- // create watchDog
1100
- //
1101
- InfiniteScroll.create.scrollWatch = function() {
1102
- // events
1103
- this.pageScrollHandler = this.onPageScroll.bind( this );
1104
- this.resizeHandler = this.onResize.bind( this );
1105
-
1106
- let scrollThreshold = this.options.scrollThreshold;
1107
- let isEnable = scrollThreshold || scrollThreshold === 0;
1108
- if ( isEnable ) this.enableScrollWatch();
1109
- };
1110
-
1111
- InfiniteScroll.destroy.scrollWatch = function() {
1112
- this.disableScrollWatch();
1113
- };
1114
-
1115
- proto.enableScrollWatch = function() {
1116
- if ( this.isScrollWatching ) return;
1117
-
1118
- this.isScrollWatching = true;
1119
- this.updateMeasurements();
1120
- this.updateScroller();
1121
- // TODO disable after error?
1122
- this.on( 'last', this.disableScrollWatch );
1123
- this.bindScrollWatchEvents( true );
1124
- };
1125
-
1126
- proto.disableScrollWatch = function() {
1127
- if ( !this.isScrollWatching ) return;
1128
-
1129
- this.bindScrollWatchEvents( false );
1130
- delete this.isScrollWatching;
1131
- };
1132
-
1133
- proto.bindScrollWatchEvents = function( isBind ) {
1134
- let addRemove = isBind ? 'addEventListener' : 'removeEventListener';
1135
- this.scroller[ addRemove ]( 'scroll', this.pageScrollHandler );
1136
- window[ addRemove ]( 'resize', this.resizeHandler );
1137
- };
1138
-
1139
- proto.onPageScroll = InfiniteScroll.throttle( function() {
1140
- let distance = this.getBottomDistance();
1141
- if ( distance <= this.options.scrollThreshold ) {
1142
- this.dispatchEvent('scrollThreshold');
1143
- }
1144
- } );
1145
-
1146
- // jadams
1147
- // calculate distances
1148
- //
1149
- proto.getBottomDistance = function() {
1150
- let bottom, scrollY;
1151
- if ( this.options.elementScroll ) {
1152
- bottom = this.scroller.scrollHeight;
1153
- scrollY = this.scroller.scrollTop + this.scroller.clientHeight;
1154
- } else {
1155
- bottom = this.top + this.element.clientHeight;
1156
- scrollY = window.scrollY + this.windowHeight;
1157
- }
1158
- return bottom - scrollY;
1159
- };
1160
-
1161
- proto.onResize = function() {
1162
- this.updateMeasurements();
1163
- };
1164
-
1165
- utils.debounceMethod( InfiniteScroll, 'onResize', 150 );
1166
-
1167
- // -------------------------- -------------------------- //
1168
-
1169
- return InfiniteScroll;
1170
-
1171
- } ) );
1172
- // history
1173
- ( function( window, factory ) {
1174
- // universal module definition
1175
- if ( typeof module == 'object' && module.exports ) {
1176
- // CommonJS
1177
- module.exports = factory(
1178
- window,
1179
- require('./core'),
1180
- require('fizzy-ui-utils'),
1181
- );
1182
- } else {
1183
- // browser global
1184
- factory(
1185
- window,
1186
- window.InfiniteScroll,
1187
- window.fizzyUIUtils,
1188
- );
1189
- }
1190
-
1191
- }( window, function factory( window, InfiniteScroll, utils ) {
1192
-
1193
- let proto = InfiniteScroll.prototype;
1194
-
1195
- Object.assign( InfiniteScroll.defaults, {
1196
- history: 'replace',
1197
- // historyTitle: false,
1198
- } );
1199
-
1200
- let link = document.createElement('a');
1201
-
1202
- // ----- create/destroy ----- //
1203
-
1204
- InfiniteScroll.create.history = function() {
1205
- if ( !this.options.history ) return;
1206
-
1207
- // check for same origin
1208
- link.href = this.getAbsolutePath();
1209
- // MS Edge does not have origin on link
1210
- // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12236493/
1211
- let linkOrigin = link.origin || link.protocol + '//' + link.host;
1212
- let isSameOrigin = linkOrigin == location.origin;
1213
- if ( !isSameOrigin ) {
1214
- console.error( '[InfiniteScroll] cannot set history with different origin: ' +
1215
- `${link.origin} on ${location.origin} . History behavior disabled.` );
1216
- return;
1217
- }
1218
-
1219
- // two ways to handle changing history
1220
- if ( this.options.append ) {
1221
- this.createHistoryAppend();
1222
- } else {
1223
- this.createHistoryPageLoad();
1224
- }
1225
- };
1226
-
1227
- proto.createHistoryAppend = function() {
1228
- this.updateMeasurements();
1229
- this.updateScroller();
1230
- // array of scroll positions of appended pages
1231
- this.scrollPages = [
1232
- // first page
1233
- {
1234
- top: 0,
1235
- path: location.href,
1236
- title: document.title,
1237
- },
1238
- ];
1239
- this.scrollPage = this.scrollPages[0];
1240
- // events
1241
- this.scrollHistoryHandler = this.onScrollHistory.bind( this );
1242
- this.unloadHandler = this.onUnload.bind( this );
1243
- this.scroller.addEventListener( 'scroll', this.scrollHistoryHandler );
1244
- this.on( 'append', this.onAppendHistory );
1245
- this.bindHistoryAppendEvents( true );
1246
- };
1247
-
1248
- proto.bindHistoryAppendEvents = function( isBind ) {
1249
- let addRemove = isBind ? 'addEventListener' : 'removeEventListener';
1250
- this.scroller[ addRemove ]( 'scroll', this.scrollHistoryHandler );
1251
- window[ addRemove ]( 'unload', this.unloadHandler );
1252
- };
1253
-
1254
- proto.createHistoryPageLoad = function() {
1255
- this.on( 'load', this.onPageLoadHistory );
1256
- };
1257
-
1258
- InfiniteScroll.destroy.history =
1259
- proto.destroyHistory = function() {
1260
- let isHistoryAppend = this.options.history && this.options.append;
1261
- if ( isHistoryAppend ) {
1262
- this.bindHistoryAppendEvents( false );
1263
- }
1264
- };
1265
-
1266
- // ----- append history ----- //
1267
-
1268
- proto.onAppendHistory = function( response, path, items ) {
1269
- // do not proceed if no items. #779
1270
- if ( !items || !items.length ) return;
1271
-
1272
- let firstItem = items[0];
1273
- let elemScrollY = this.getElementScrollY( firstItem );
1274
- // resolve path
1275
- link.href = path;
1276
- // add page data to hash
1277
- this.scrollPages.push({
1278
- top: elemScrollY,
1279
- path: link.href,
1280
- title: response.title,
1281
- });
1282
- };
1283
-
1284
- proto.getElementScrollY = function( elem ) {
1285
- if ( this.options.elementScroll ) {
1286
- return elem.offsetTop - this.top;
1287
- } else {
1288
- let rect = elem.getBoundingClientRect();
1289
- return rect.top + window.scrollY;
1290
- }
1291
- };
1292
-
1293
- proto.onScrollHistory = function() {
1294
- // cycle through positions, find biggest without going over
1295
- let scrollPage = this.getClosestScrollPage();
1296
- // set history if changed
1297
- if ( scrollPage != this.scrollPage ) {
1298
- this.scrollPage = scrollPage;
1299
- this.setHistory( scrollPage.title, scrollPage.path );
1300
- }
1301
- };
1302
-
1303
- utils.debounceMethod( InfiniteScroll, 'onScrollHistory', 150 );
1304
-
1305
- proto.getClosestScrollPage = function() {
1306
- let scrollViewY;
1307
- if ( this.options.elementScroll ) {
1308
- scrollViewY = this.scroller.scrollTop + this.scroller.clientHeight / 2;
1309
- } else {
1310
- scrollViewY = window.scrollY + this.windowHeight / 2;
1311
- }
1312
-
1313
- let scrollPage;
1314
- for ( let page of this.scrollPages ) {
1315
- if ( page.top >= scrollViewY ) break;
1316
-
1317
- scrollPage = page;
1318
- }
1319
- return scrollPage;
1320
- };
1321
-
1322
- proto.setHistory = function( title, path ) {
1323
- let optHistory = this.options.history;
1324
- let historyMethod = optHistory && history[ optHistory + 'State' ];
1325
- if ( !historyMethod ) return;
1326
-
1327
- history[ optHistory + 'State' ]( null, title, path );
1328
- if ( this.options.historyTitle ) document.title = title;
1329
- this.dispatchEvent( 'history', null, [ title, path ] );
1330
- };
1331
-
1332
- // scroll to top to prevent initial scroll-reset after page refresh
1333
- // https://stackoverflow.com/a/18633915/182183
1334
- proto.onUnload = function() {
1335
- if ( this.scrollPage.top === 0 ) return;
1336
-
1337
- // calculate where scroll position would be on refresh
1338
- let scrollY = window.scrollY - this.scrollPage.top + this.top;
1339
- // disable scroll event before setting scroll #679
1340
- this.destroyHistory();
1341
- scrollTo( 0, scrollY );
1342
- };
1343
-
1344
- // ----- load history ----- //
1345
-
1346
- // update URL
1347
- proto.onPageLoadHistory = function( response, path ) {
1348
- this.setHistory( response.title, path );
1349
- };
1350
-
1351
- // -------------------------- -------------------------- //
1352
-
1353
- return InfiniteScroll;
1354
-
1355
- } ) );
1356
- // button
1357
- ( function( window, factory ) {
1358
- // universal module definition
1359
- if ( typeof module == 'object' && module.exports ) {
1360
- // CommonJS
1361
- module.exports = factory(
1362
- window,
1363
- require('./core'),
1364
- require('fizzy-ui-utils'),
1365
- );
1366
- } else {
1367
- // browser global
1368
- factory(
1369
- window,
1370
- window.InfiniteScroll,
1371
- window.fizzyUIUtils,
1372
- );
1373
- }
1374
-
1375
- }( window, function factory( window, InfiniteScroll, utils ) {
1376
-
1377
- // -------------------------- InfiniteScrollButton -------------------------- //
1378
-
1379
- class InfiniteScrollButton {
1380
- constructor( element, infScroll ) {
1381
- this.element = element;
1382
- this.infScroll = infScroll;
1383
- // events
1384
- this.clickHandler = this.onClick.bind( this );
1385
- this.element.addEventListener( 'click', this.clickHandler );
1386
- infScroll.on( 'request', this.disable.bind( this ) );
1387
- infScroll.on( 'load', this.enable.bind( this ) );
1388
- infScroll.on( 'error', this.hide.bind( this ) );
1389
- infScroll.on( 'last', this.hide.bind( this ) );
1390
- }
1391
-
1392
- onClick( event ) {
1393
- event.preventDefault();
1394
- this.infScroll.loadNextPage();
1395
- }
1396
-
1397
- enable() {
1398
- this.element.removeAttribute('disabled');
1399
- }
1400
-
1401
- disable() {
1402
- this.element.disabled = 'disabled';
1403
- }
1404
-
1405
- hide() {
1406
- this.element.style.display = 'none';
1407
- }
1408
-
1409
- destroy() {
1410
- this.element.removeEventListener( 'click', this.clickHandler );
1411
- }
1412
-
1413
- }
1414
-
1415
- // -------------------------- InfiniteScroll methods -------------------------- //
1416
-
1417
- // InfiniteScroll.defaults.button = null;
1418
-
1419
- InfiniteScroll.create.button = function() {
1420
- let buttonElem = utils.getQueryElement( this.options.button );
1421
- if ( buttonElem ) {
1422
- this.button = new InfiniteScrollButton( buttonElem, this );
1423
- }
1424
- };
1425
-
1426
- InfiniteScroll.destroy.button = function() {
1427
- if ( this.button ) this.button.destroy();
1428
- };
1429
-
1430
- // -------------------------- -------------------------- //
1431
-
1432
- InfiniteScroll.Button = InfiniteScrollButton;
1433
-
1434
- return InfiniteScroll;
1435
-
1436
- } ) );
1437
- // status
1438
- ( function( window, factory ) {
1439
- // universal module definition
1440
- if ( typeof module == 'object' && module.exports ) {
1441
- // CommonJS
1442
- module.exports = factory(
1443
- window,
1444
- require('./core'),
1445
- require('fizzy-ui-utils'),
1446
- );
1447
- } else {
1448
- // browser global
1449
- factory(
1450
- window,
1451
- window.InfiniteScroll,
1452
- window.fizzyUIUtils,
1453
- );
1454
- }
1455
-
1456
- }( window, function factory( window, InfiniteScroll, utils ) {
1457
-
1458
- let proto = InfiniteScroll.prototype;
1459
-
1460
- // InfiniteScroll.defaults.status = null;
1461
-
1462
- InfiniteScroll.create.status = function() {
1463
- let statusElem = utils.getQueryElement( this.options.status );
1464
- if ( !statusElem ) return;
1465
-
1466
- // elements
1467
- this.statusElement = statusElem;
1468
- this.statusEventElements = {
1469
- request: statusElem.querySelector('.infinite-scroll-request'),
1470
- error: statusElem.querySelector('.infinite-scroll-error'),
1471
- last: statusElem.querySelector('.infinite-scroll-last'),
1472
- };
1473
- // events
1474
- this.on( 'request', this.showRequestStatus );
1475
- this.on( 'error', this.showErrorStatus );
1476
- this.on( 'last', this.showLastStatus );
1477
- this.bindHideStatus('on');
1478
- };
1479
-
1480
- proto.bindHideStatus = function( bindMethod ) {
1481
- let hideEvent = this.options.append ? 'append' : 'load';
1482
- this[ bindMethod ]( hideEvent, this.hideAllStatus );
1483
- };
1484
-
1485
- proto.showRequestStatus = function() {
1486
- this.showStatus('request');
1487
- };
1488
-
1489
- proto.showErrorStatus = function() {
1490
- this.showStatus('error');
1491
- };
1492
-
1493
- proto.showLastStatus = function() {
1494
- this.showStatus('last');
1495
- // prevent last then append event race condition from showing last status #706
1496
- this.bindHideStatus('off');
1497
- };
1498
-
1499
- proto.showStatus = function( eventName ) {
1500
- show( this.statusElement );
1501
- this.hideStatusEventElements();
1502
- let eventElem = this.statusEventElements[ eventName ];
1503
- show( eventElem );
1504
- };
1505
-
1506
- proto.hideAllStatus = function() {
1507
- hide( this.statusElement );
1508
- this.hideStatusEventElements();
1509
- };
1510
-
1511
- proto.hideStatusEventElements = function() {
1512
- for ( let type in this.statusEventElements ) {
1513
- let eventElem = this.statusEventElements[ type ];
1514
- hide( eventElem );
1515
- }
1516
- };
1517
-
1518
- // -------------------------- -------------------------- //
1519
-
1520
- function hide( elem ) {
1521
- setDisplay( elem, 'none' );
1522
- }
1523
-
1524
- function show( elem ) {
1525
- setDisplay( elem, 'block' );
1526
- }
1527
-
1528
- function setDisplay( elem, value ) {
1529
- if ( elem ) {
1530
- elem.style.display = value;
1531
- }
1532
- }
1533
-
1534
- // -------------------------- -------------------------- //
1535
-
1536
- return InfiniteScroll;
1537
-
1538
- } ) );
1539
- /*!
1540
- * imagesLoaded v4.1.4
1541
- * JavaScript is all like "You images are done yet or what?"
1542
- * MIT License
1543
- */
1544
-
1545
- ( function( window, factory ) { 'use strict';
1546
- // universal module definition
1547
-
1548
- /*global define: false, module: false, require: false */
1549
-
1550
- if ( typeof define == 'function' && define.amd ) {
1551
- // AMD
1552
- define( [
1553
- 'ev-emitter/ev-emitter'
1554
- ], function( EvEmitter ) {
1555
- return factory( window, EvEmitter );
1556
- });
1557
- } else if ( typeof module == 'object' && module.exports ) {
1558
- // CommonJS
1559
- module.exports = factory(
1560
- window,
1561
- require('ev-emitter')
1562
- );
1563
- } else {
1564
- // browser global
1565
- window.imagesLoaded = factory(
1566
- window,
1567
- window.EvEmitter
1568
- );
1569
- }
1570
-
1571
- })( typeof window !== 'undefined' ? window : this,
1572
-
1573
- // -------------------------- factory -------------------------- //
1574
-
1575
- function factory( window, EvEmitter ) {
1576
-
1577
- 'use strict';
1578
-
1579
- var $ = window.jQuery;
1580
- var console = window.console;
1581
-
1582
- // -------------------------- helpers -------------------------- //
1583
-
1584
- // extend objects
1585
- function extend( a, b ) {
1586
- for ( var prop in b ) {
1587
- a[ prop ] = b[ prop ];
1588
- }
1589
- return a;
1590
- }
1591
-
1592
- var arraySlice = Array.prototype.slice;
1593
-
1594
- // turn element or nodeList into an array
1595
- function makeArray( obj ) {
1596
- if ( Array.isArray( obj ) ) {
1597
- // use object if already an array
1598
- return obj;
1599
- }
1600
-
1601
- var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
1602
- if ( isArrayLike ) {
1603
- // convert nodeList to array
1604
- return arraySlice.call( obj );
1605
- }
1606
-
1607
- // array of single index
1608
- return [ obj ];
1609
- }
1610
-
1611
- // -------------------------- imagesLoaded -------------------------- //
1612
-
1613
- /**
1614
- * @param {Array, Element, NodeList, String} elem
1615
- * @param {Object or Function} options - if function, use as callback
1616
- * @param {Function} onAlways - callback function
1617
- */
1618
- function ImagesLoaded( elem, options, onAlways ) {
1619
- // coerce ImagesLoaded() without new, to be new ImagesLoaded()
1620
- if ( !( this instanceof ImagesLoaded ) ) {
1621
- return new ImagesLoaded( elem, options, onAlways );
1622
- }
1623
- // use elem as selector string
1624
- var queryElem = elem;
1625
- if ( typeof elem == 'string' ) {
1626
- queryElem = document.querySelectorAll( elem );
1627
- }
1628
- // bail if bad element
1629
- if ( !queryElem ) {
1630
- console.error( 'Bad element for imagesLoaded ' + ( queryElem || elem ) );
1631
- return;
1632
- }
1633
-
1634
- this.elements = makeArray( queryElem );
1635
- this.options = extend( {}, this.options );
1636
- // shift arguments if no options set
1637
- if ( typeof options == 'function' ) {
1638
- onAlways = options;
1639
- } else {
1640
- extend( this.options, options );
1641
- }
1642
-
1643
- if ( onAlways ) {
1644
- this.on( 'always', onAlways );
1645
- }
1646
-
1647
- this.getImages();
1648
-
1649
- if ( $ ) {
1650
- // add jQuery Deferred object
1651
- this.jqDeferred = new $.Deferred();
1652
- }
1653
-
1654
- // HACK check async to allow time to bind listeners
1655
- setTimeout( this.check.bind( this ) );
1656
- }
1657
-
1658
- ImagesLoaded.prototype = Object.create( EvEmitter.prototype );
1659
-
1660
- ImagesLoaded.prototype.options = {};
1661
-
1662
- ImagesLoaded.prototype.getImages = function() {
1663
- this.images = [];
1664
-
1665
- // filter & find items if we have an item selector
1666
- this.elements.forEach( this.addElementImages, this );
1667
- };
1668
-
1669
- /**
1670
- * @param {Node} element
1671
- */
1672
- ImagesLoaded.prototype.addElementImages = function( elem ) {
1673
- // filter siblings
1674
- if ( elem.nodeName == 'IMG' ) {
1675
- this.addImage( elem );
1676
- }
1677
- // get background image on element
1678
- if ( this.options.background === true ) {
1679
- this.addElementBackgroundImages( elem );
1680
- }
1681
-
1682
- // find children
1683
- // no non-element nodes, #143
1684
- var nodeType = elem.nodeType;
1685
- if ( !nodeType || !elementNodeTypes[ nodeType ] ) {
1686
- return;
1687
- }
1688
- var childImgs = elem.querySelectorAll('img');
1689
- // concat childElems to filterFound array
1690
- for ( var i=0; i < childImgs.length; i++ ) {
1691
- var img = childImgs[i];
1692
- this.addImage( img );
1693
- }
1694
-
1695
- // get child background images
1696
- if ( typeof this.options.background == 'string' ) {
1697
- var children = elem.querySelectorAll( this.options.background );
1698
- for ( i=0; i < children.length; i++ ) {
1699
- var child = children[i];
1700
- this.addElementBackgroundImages( child );
1701
- }
1702
- }
1703
- };
1704
-
1705
- var elementNodeTypes = {
1706
- 1: true,
1707
- 9: true,
1708
- 11: true
1709
- };
1710
-
1711
- ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
1712
- var style = getComputedStyle( elem );
1713
- if ( !style ) {
1714
- // Firefox returns null if in a hidden iframe https://bugzil.la/548397
1715
- return;
1716
- }
1717
- // get url inside url("...")
1718
- var reURL = /url\((['"])?(.*?)\1\)/gi;
1719
- var matches = reURL.exec( style.backgroundImage );
1720
- while ( matches !== null ) {
1721
- var url = matches && matches[2];
1722
- if ( url ) {
1723
- this.addBackground( url, elem );
1724
- }
1725
- matches = reURL.exec( style.backgroundImage );
1726
- }
1727
- };
1728
-
1729
- /**
1730
- * @param {Image} img
1731
- */
1732
- ImagesLoaded.prototype.addImage = function( img ) {
1733
- var loadingImage = new LoadingImage( img );
1734
- this.images.push( loadingImage );
1735
- };
1736
-
1737
- ImagesLoaded.prototype.addBackground = function( url, elem ) {
1738
- var background = new Background( url, elem );
1739
- this.images.push( background );
1740
- };
1741
-
1742
- ImagesLoaded.prototype.check = function() {
1743
- var _this = this;
1744
- this.progressedCount = 0;
1745
- this.hasAnyBroken = false;
1746
- // complete if no images
1747
- if ( !this.images.length ) {
1748
- this.complete();
1749
- return;
1750
- }
1751
-
1752
- function onProgress( image, elem, message ) {
1753
- // HACK - Chrome triggers event before object properties have changed. #83
1754
- setTimeout( function() {
1755
- _this.progress( image, elem, message );
1756
- });
1757
- }
1758
-
1759
- this.images.forEach( function( loadingImage ) {
1760
- loadingImage.once( 'progress', onProgress );
1761
- loadingImage.check();
1762
- });
1763
- };
1764
-
1765
- ImagesLoaded.prototype.progress = function( image, elem, message ) {
1766
- this.progressedCount++;
1767
- this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
1768
- // progress event
1769
- this.emitEvent( 'progress', [ this, image, elem ] );
1770
- if ( this.jqDeferred && this.jqDeferred.notify ) {
1771
- this.jqDeferred.notify( this, image );
1772
- }
1773
- // check if completed
1774
- if ( this.progressedCount == this.images.length ) {
1775
- this.complete();
1776
- }
1777
-
1778
- if ( this.options.debug && console ) {
1779
- console.log( 'progress: ' + message, image, elem );
1780
- }
1781
- };
1782
-
1783
- ImagesLoaded.prototype.complete = function() {
1784
- var eventName = this.hasAnyBroken ? 'fail' : 'done';
1785
- this.isComplete = true;
1786
- this.emitEvent( eventName, [ this ] );
1787
- this.emitEvent( 'always', [ this ] );
1788
- if ( this.jqDeferred ) {
1789
- var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
1790
- this.jqDeferred[ jqMethod ]( this );
1791
- }
1792
- };
1793
-
1794
- // -------------------------- -------------------------- //
1795
-
1796
- function LoadingImage( img ) {
1797
- this.img = img;
1798
- }
1799
-
1800
- LoadingImage.prototype = Object.create( EvEmitter.prototype );
1801
-
1802
- LoadingImage.prototype.check = function() {
1803
- // If complete is true and browser supports natural sizes,
1804
- // try to check for image status manually.
1805
- var isComplete = this.getIsImageComplete();
1806
- if ( isComplete ) {
1807
- // report based on naturalWidth
1808
- this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
1809
- return;
1810
- }
1811
-
1812
- // If none of the checks above matched, simulate loading on detached element.
1813
- this.proxyImage = new Image();
1814
- this.proxyImage.addEventListener( 'load', this );
1815
- this.proxyImage.addEventListener( 'error', this );
1816
- // bind to image as well for Firefox. #191
1817
- this.img.addEventListener( 'load', this );
1818
- this.img.addEventListener( 'error', this );
1819
- this.proxyImage.src = this.img.src;
1820
- };
1821
-
1822
- LoadingImage.prototype.getIsImageComplete = function() {
1823
- // check for non-zero, non-undefined naturalWidth
1824
- // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671
1825
- return this.img.complete && this.img.naturalWidth;
1826
- };
1827
-
1828
- LoadingImage.prototype.confirm = function( isLoaded, message ) {
1829
- this.isLoaded = isLoaded;
1830
- this.emitEvent( 'progress', [ this, this.img, message ] );
1831
- };
1832
-
1833
- // ----- events ----- //
1834
-
1835
- // trigger specified handler for event type
1836
- LoadingImage.prototype.handleEvent = function( event ) {
1837
- var method = 'on' + event.type;
1838
- if ( this[ method ] ) {
1839
- this[ method ]( event );
1840
- }
1841
- };
1842
-
1843
- LoadingImage.prototype.onload = function() {
1844
- this.confirm( true, 'onload' );
1845
- this.unbindEvents();
1846
- };
1847
-
1848
- LoadingImage.prototype.onerror = function() {
1849
- this.confirm( false, 'onerror' );
1850
- this.unbindEvents();
1851
- };
1852
-
1853
- LoadingImage.prototype.unbindEvents = function() {
1854
- this.proxyImage.removeEventListener( 'load', this );
1855
- this.proxyImage.removeEventListener( 'error', this );
1856
- this.img.removeEventListener( 'load', this );
1857
- this.img.removeEventListener( 'error', this );
1858
- };
1859
-
1860
- // -------------------------- Background -------------------------- //
1861
-
1862
- function Background( url, element ) {
1863
- this.url = url;
1864
- this.element = element;
1865
- this.img = new Image();
1866
- }
1867
-
1868
- // inherit LoadingImage prototype
1869
- Background.prototype = Object.create( LoadingImage.prototype );
1870
-
1871
- Background.prototype.check = function() {
1872
- this.img.addEventListener( 'load', this );
1873
- this.img.addEventListener( 'error', this );
1874
- this.img.src = this.url;
1875
- // check if image is already complete
1876
- var isComplete = this.getIsImageComplete();
1877
- if ( isComplete ) {
1878
- this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
1879
- this.unbindEvents();
1880
- }
1881
- };
1882
-
1883
- Background.prototype.unbindEvents = function() {
1884
- this.img.removeEventListener( 'load', this );
1885
- this.img.removeEventListener( 'error', this );
1886
- };
1887
-
1888
- Background.prototype.confirm = function( isLoaded, message ) {
1889
- this.isLoaded = isLoaded;
1890
- this.emitEvent( 'progress', [ this, this.element, message ] );
1891
- };
1892
-
1893
- // -------------------------- jQuery -------------------------- //
1894
-
1895
- ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
1896
- jQuery = jQuery || window.jQuery;
1897
- if ( !jQuery ) {
1898
- return;
1899
- }
1900
- // set local variable
1901
- $ = jQuery;
1902
- // $().imagesLoaded()
1903
- $.fn.imagesLoaded = function( options, callback ) {
1904
- var instance = new ImagesLoaded( this, options, callback );
1905
- return instance.jqDeferred.promise( $(this) );
1906
- };
1907
- };
1908
- // try making plugin
1909
- ImagesLoaded.makeJQueryPlugin();
1910
-
1911
- // -------------------------- -------------------------- //
1912
-
1913
- return ImagesLoaded;
1914
-
1915
- });