bootstrap_pager 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +18 -0
  3. data/.idea/encodings.xml +5 -0
  4. data/.idea/misc.xml +5 -0
  5. data/.idea/modules.xml +9 -0
  6. data/.idea/pager.iml +50 -0
  7. data/.idea/scopes/scope_settings.xml +5 -0
  8. data/.idea/vcs.xml +7 -0
  9. data/Gemfile +4 -0
  10. data/LICENSE +20 -0
  11. data/MIT-LICENSE +20 -0
  12. data/README.rdoc +307 -0
  13. data/Rakefile +42 -0
  14. data/app/assets/javascripts/infinitescroll.js +8 -0
  15. data/app/helpers/pager_helper.rb +5 -0
  16. data/app/views/pager/_first_page.html.erb +11 -0
  17. data/app/views/pager/_first_page.html.haml +9 -0
  18. data/app/views/pager/_first_page.html.slim +10 -0
  19. data/app/views/pager/_gap.html.erb +8 -0
  20. data/app/views/pager/_gap.html.haml +8 -0
  21. data/app/views/pager/_gap.html.slim +10 -0
  22. data/app/views/pager/_last_page.html.erb +11 -0
  23. data/app/views/pager/_last_page.html.haml +9 -0
  24. data/app/views/pager/_last_page.html.slim +10 -0
  25. data/app/views/pager/_next_page.html.erb +11 -0
  26. data/app/views/pager/_next_page.html.haml +9 -0
  27. data/app/views/pager/_next_page.html.slim +10 -0
  28. data/app/views/pager/_page.html.erb +14 -0
  29. data/app/views/pager/_page.html.haml +11 -0
  30. data/app/views/pager/_page.html.slim +13 -0
  31. data/app/views/pager/_paginator.html.erb +25 -0
  32. data/app/views/pager/_paginator.html.haml +19 -0
  33. data/app/views/pager/_paginator.html.slim +20 -0
  34. data/app/views/pager/_prev_page.html.erb +11 -0
  35. data/app/views/pager/_prev_page.html.haml +9 -0
  36. data/app/views/pager/_prev_page.html.slim +10 -0
  37. data/bootstrap_pager.gemspec +36 -0
  38. data/config/locales/pager.yml +19 -0
  39. data/gemfiles/active_record_30.gemfile +9 -0
  40. data/gemfiles/active_record_31.gemfile +7 -0
  41. data/gemfiles/active_record_32.gemfile +10 -0
  42. data/gemfiles/active_record_40.gemfile +8 -0
  43. data/gemfiles/active_record_edge.gemfile +11 -0
  44. data/gemfiles/data_mapper_12.gemfile +15 -0
  45. data/gemfiles/mongo_mapper.gemfile +10 -0
  46. data/gemfiles/mongoid_24.gemfile +7 -0
  47. data/gemfiles/mongoid_30.gemfile +12 -0
  48. data/gemfiles/sinatra_13.gemfile +13 -0
  49. data/gemfiles/sinatra_14.gemfile +13 -0
  50. data/lib/bootstrap_pager/config.rb +51 -0
  51. data/lib/bootstrap_pager/grape.rb +4 -0
  52. data/lib/bootstrap_pager/helpers/action_view_extension.rb +152 -0
  53. data/lib/bootstrap_pager/helpers/paginator.rb +186 -0
  54. data/lib/bootstrap_pager/helpers/sinatra_helpers.rb +144 -0
  55. data/lib/bootstrap_pager/helpers/tags.rb +96 -0
  56. data/lib/bootstrap_pager/hooks.rb +41 -0
  57. data/lib/bootstrap_pager/models/active_record_extension.rb +22 -0
  58. data/lib/bootstrap_pager/models/active_record_model_extension.rb +20 -0
  59. data/lib/bootstrap_pager/models/active_record_relation_methods.rb +29 -0
  60. data/lib/bootstrap_pager/models/array_extension.rb +58 -0
  61. data/lib/bootstrap_pager/models/configuration_methods.rb +48 -0
  62. data/lib/bootstrap_pager/models/data_mapper_collection_methods.rb +15 -0
  63. data/lib/bootstrap_pager/models/data_mapper_extension.rb +48 -0
  64. data/lib/bootstrap_pager/models/mongo_mapper_extension.rb +18 -0
  65. data/lib/bootstrap_pager/models/mongoid_criteria_methods.rb +23 -0
  66. data/lib/bootstrap_pager/models/mongoid_extension.rb +33 -0
  67. data/lib/bootstrap_pager/models/page_scope_methods.rb +70 -0
  68. data/lib/bootstrap_pager/models/plucky_criteria_methods.rb +18 -0
  69. data/lib/bootstrap_pager/railtie.rb +7 -0
  70. data/lib/bootstrap_pager/sinatra.rb +5 -0
  71. data/lib/bootstrap_pager/version.rb +3 -0
  72. data/lib/bootstrap_pager.rb +38 -0
  73. data/lib/generators/pager/config_generator.rb +16 -0
  74. data/lib/generators/pager/templates/pager_config.rb +10 -0
  75. data/lib/generators/pager/views_generator.rb +118 -0
  76. data/spec/config/config_spec.rb +91 -0
  77. data/spec/fake_app/active_record/config.rb +3 -0
  78. data/spec/fake_app/active_record/models.rb +57 -0
  79. data/spec/fake_app/data_mapper/config.rb +7 -0
  80. data/spec/fake_app/data_mapper/models.rb +27 -0
  81. data/spec/fake_app/log/development.log +832 -0
  82. data/spec/fake_app/mongo_mapper/config.rb +2 -0
  83. data/spec/fake_app/mongo_mapper/models.rb +9 -0
  84. data/spec/fake_app/mongoid/config.rb +16 -0
  85. data/spec/fake_app/mongoid/models.rb +22 -0
  86. data/spec/fake_app/rails_app.rb +67 -0
  87. data/spec/fake_app/sinatra_app.rb +22 -0
  88. data/spec/fake_gem.rb +4 -0
  89. data/spec/helpers/action_view_extension_spec.rb +292 -0
  90. data/spec/helpers/helpers_spec.rb +135 -0
  91. data/spec/helpers/sinatra_helpers_spec.rb +170 -0
  92. data/spec/helpers/tags_spec.rb +140 -0
  93. data/spec/models/active_record/active_record_relation_methods_spec.rb +47 -0
  94. data/spec/models/active_record/default_per_page_spec.rb +32 -0
  95. data/spec/models/active_record/max_pages_spec.rb +23 -0
  96. data/spec/models/active_record/max_per_page_spec.rb +32 -0
  97. data/spec/models/active_record/scopes_spec.rb +242 -0
  98. data/spec/models/array_spec.rb +150 -0
  99. data/spec/models/data_mapper/data_mapper_spec.rb +207 -0
  100. data/spec/models/mongo_mapper/mongo_mapper_spec.rb +84 -0
  101. data/spec/models/mongoid/mongoid_spec.rb +126 -0
  102. data/spec/requests/users_spec.rb +53 -0
  103. data/spec/spec_helper.rb +33 -0
  104. data/spec/spec_helper_for_sinatra.rb +34 -0
  105. data/spec/support/database_cleaner.rb +16 -0
  106. data/spec/support/matchers.rb +52 -0
  107. data/vendor/assets/javascripts/jquery.infinitescroll.js +814 -0
  108. data/vendor/assets/javascripts/jquery.infinitescroll.min.js +1 -0
  109. metadata +311 -0
@@ -0,0 +1,814 @@
1
+ /*jshint undef: true */
2
+ /*global jQuery: true */
3
+
4
+ /*
5
+ --------------------------------
6
+ Infinite Scroll
7
+ --------------------------------
8
+ + https://github.com/paulirish/infinite-scroll
9
+ + version 2.0b2.120519
10
+ + Copyright 2011/12 Paul Irish & Luke Shumard
11
+ + Licensed under the MIT license
12
+
13
+ + Documentation: http://infinite-scroll.com/
14
+ */
15
+
16
+ (function (window, $, undefined) {
17
+ "use strict";
18
+
19
+ $.infinitescroll = function infscr(options, callback, element) {
20
+ this.element = $(element);
21
+
22
+ // Flag the object in the event of a failed creation
23
+ if (!this._create(options, callback)) {
24
+ this.failed = true;
25
+ }
26
+ };
27
+
28
+ $.infinitescroll.defaults = {
29
+ loading: {
30
+ finished: undefined,
31
+ finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>",
32
+ img: "data:image/gif;base64,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",
33
+ msg: null,
34
+ msgText: "<em>Loading the next set of posts...</em>",
35
+ selector: null,
36
+ speed: 'fast',
37
+ start: undefined
38
+ },
39
+ state: {
40
+ isDuringAjax: false,
41
+ isInvalidPage: false,
42
+ isDestroyed: false,
43
+ isDone: false, // For when it goes all the way through the archive.
44
+ isPaused: false,
45
+ isBeyondMaxPage: false,
46
+ currPage: 1
47
+ },
48
+ debug: false,
49
+ behavior: undefined,
50
+ binder: $(window), // used to cache the selector
51
+ nextSelector: "div.navigation a:first",
52
+ navSelector: "div.navigation",
53
+ contentSelector: null, // rename to pageFragment
54
+ extraScrollPx: 150,
55
+ itemSelector: "div.post",
56
+ animate: false,
57
+ pathParse: undefined,
58
+ dataType: 'html',
59
+ appendCallback: true,
60
+ bufferPx: 40,
61
+ errorCallback: function () { },
62
+ infid: 0, //Instance ID
63
+ pixelsFromNavToBottom: undefined,
64
+ path: undefined, // Either parts of a URL as an array (e.g. ["/page/", "/"] or a function that takes in the page number and returns a URL
65
+ prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted
66
+ maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
67
+ };
68
+
69
+ $.infinitescroll.prototype = {
70
+
71
+ /*
72
+ ----------------------------
73
+ Private methods
74
+ ----------------------------
75
+ */
76
+
77
+ // Bind or unbind from scroll
78
+ _binding: function infscr_binding(binding) {
79
+
80
+ var instance = this,
81
+ opts = instance.options;
82
+
83
+ opts.v = '2.0b2.120520';
84
+
85
+ // if behavior is defined and this function is extended, call that instead of default
86
+ if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) {
87
+ this['_binding_'+opts.behavior].call(this);
88
+ return;
89
+ }
90
+
91
+ if (binding !== 'bind' && binding !== 'unbind') {
92
+ this._debug('Binding value ' + binding + ' not valid');
93
+ return false;
94
+ }
95
+
96
+ if (binding === 'unbind') {
97
+ (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid);
98
+ } else {
99
+ (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () {
100
+ instance.scroll();
101
+ });
102
+ }
103
+
104
+ this._debug('Binding', binding);
105
+ },
106
+
107
+ // Fundamental aspects of the plugin are initialized
108
+ _create: function infscr_create(options, callback) {
109
+
110
+ // Add custom options to defaults
111
+ var opts = $.extend(true, {}, $.infinitescroll.defaults, options);
112
+ this.options = opts;
113
+ var $window = $(window);
114
+ var instance = this;
115
+
116
+ // Validate selectors
117
+ if (!instance._validate(options)) {
118
+ return false;
119
+ }
120
+
121
+ // Validate page fragment path
122
+ var path = $(opts.nextSelector).attr('href');
123
+ if (!path) {
124
+ this._debug('Navigation selector not found');
125
+ return false;
126
+ }
127
+
128
+ // Set the path to be a relative URL from root.
129
+ opts.path = opts.path || this._determinepath(path);
130
+
131
+ // contentSelector is 'page fragment' option for .load() / .ajax() calls
132
+ opts.contentSelector = opts.contentSelector || this.element;
133
+
134
+ // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector
135
+ opts.loading.selector = opts.loading.selector || opts.contentSelector;
136
+
137
+ // Define loading.msg
138
+ opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');
139
+
140
+ // Preload loading.img
141
+ (new Image()).src = opts.loading.img;
142
+
143
+ // distance from nav links to bottom
144
+ // computed as: height of the document + top offset of container - top offset of nav link
145
+ if(opts.pixelsFromNavToBottom === undefined) {
146
+ opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top;
147
+ this._debug("pixelsFromNavToBottom: " + opts.pixelsFromNavToBottom);
148
+ }
149
+
150
+ var self = this;
151
+
152
+ // determine loading.start actions
153
+ opts.loading.start = opts.loading.start || function() {
154
+ $(opts.navSelector).hide();
155
+ opts.loading.msg
156
+ .appendTo(opts.loading.selector)
157
+ .show(opts.loading.speed, $.proxy(function() {
158
+ this.beginAjax(opts);
159
+ }, self));
160
+ };
161
+
162
+ // determine loading.finished actions
163
+ opts.loading.finished = opts.loading.finished || function() {
164
+ if (!opts.state.isBeyondMaxPage)
165
+ opts.loading.msg.fadeOut(opts.loading.speed);
166
+ };
167
+
168
+ // callback loading
169
+ opts.callback = function(instance, data, url) {
170
+ if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) {
171
+ instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url);
172
+ }
173
+
174
+ if (callback) {
175
+ callback.call($(opts.contentSelector)[0], data, opts, url);
176
+ }
177
+
178
+ if (opts.prefill) {
179
+ $window.bind("resize.infinite-scroll", instance._prefill);
180
+ }
181
+ };
182
+
183
+ if (options.debug) {
184
+ // Tell IE9 to use its built-in console
185
+ if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === "object") {
186
+ ["log","info","warn","error","assert","dir","clear","profile","profileEnd"]
187
+ .forEach(function (method) {
188
+ console[method] = this.call(console[method], console);
189
+ }, Function.prototype.bind);
190
+ }
191
+ }
192
+
193
+ this._setup();
194
+
195
+ // Setups the prefill method for use
196
+ if (opts.prefill) {
197
+ this._prefill();
198
+ }
199
+
200
+ // Return true to indicate successful creation
201
+ return true;
202
+ },
203
+
204
+ _prefill: function infscr_prefill() {
205
+ var instance = this;
206
+ var $window = $(window);
207
+
208
+ function needsPrefill() {
209
+ return (instance.options.contentSelector.height() <= $window.height());
210
+ }
211
+
212
+ this._prefill = function() {
213
+ if (needsPrefill()) {
214
+ instance.scroll();
215
+ }
216
+
217
+ $window.bind("resize.infinite-scroll", function() {
218
+ if (needsPrefill()) {
219
+ $window.unbind("resize.infinite-scroll");
220
+ instance.scroll();
221
+ }
222
+ });
223
+ };
224
+
225
+ // Call self after setting up the new function
226
+ this._prefill();
227
+ },
228
+
229
+ // Console log wrapper
230
+ _debug: function infscr_debug() {
231
+ if (true !== this.options.debug) {
232
+ return;
233
+ }
234
+
235
+ if (typeof console !== 'undefined' && typeof console.log === 'function') {
236
+ // Modern browsers
237
+ // Single argument, which is a string
238
+ if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') {
239
+ console.log( (Array.prototype.slice.call(arguments)).toString() );
240
+ } else {
241
+ console.log( Array.prototype.slice.call(arguments) );
242
+ }
243
+ } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') {
244
+ // IE8
245
+ Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
246
+ }
247
+ },
248
+
249
+ // find the number to increment in the path.
250
+ _determinepath: function infscr_determinepath(path) {
251
+
252
+ var opts = this.options;
253
+
254
+ // if behavior is defined and this function is extended, call that instead of default
255
+ if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) {
256
+ return this['_determinepath_'+opts.behavior].call(this,path);
257
+ }
258
+
259
+ if (!!opts.pathParse) {
260
+
261
+ this._debug('pathParse manual');
262
+ return opts.pathParse(path, this.options.state.currPage+1);
263
+
264
+ } else if (path.match(/^(.*?)\b2\b(.*?$)/)) {
265
+ path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);
266
+
267
+ // if there is any 2 in the url at all.
268
+ } else if (path.match(/^(.*?)2(.*?$)/)) {
269
+
270
+ // page= is used in django:
271
+ // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
272
+ if (path.match(/^(.*?page=)2(\/.*|$)/)) {
273
+ path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
274
+ return path;
275
+ }
276
+
277
+ path = path.match(/^(.*?)2(.*?$)/).slice(1);
278
+
279
+ } else {
280
+
281
+ // page= is used in drupal too but second page is page=1 not page=2:
282
+ // thx Jerod Fritz, vladikoff
283
+ if (path.match(/^(.*?page=)1(\/.*|$)/)) {
284
+ path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
285
+ return path;
286
+ } else {
287
+ this._debug('Sorry, we couldn\'t parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.');
288
+ // Get rid of isInvalidPage to allow permalink to state
289
+ opts.state.isInvalidPage = true; //prevent it from running on this page.
290
+ }
291
+ }
292
+ this._debug('determinePath', path);
293
+ return path;
294
+
295
+ },
296
+
297
+ // Custom error
298
+ _error: function infscr_error(xhr) {
299
+
300
+ var opts = this.options;
301
+
302
+ // if behavior is defined and this function is extended, call that instead of default
303
+ if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) {
304
+ this['_error_'+opts.behavior].call(this,xhr);
305
+ return;
306
+ }
307
+
308
+ if (xhr !== 'destroy' && xhr !== 'end') {
309
+ xhr = 'unknown';
310
+ }
311
+
312
+ this._debug('Error', xhr);
313
+
314
+ if (xhr === 'end' || opts.state.isBeyondMaxPage) {
315
+ this._showdonemsg();
316
+ }
317
+
318
+ opts.state.isDone = true;
319
+ opts.state.currPage = 1; // if you need to go back to this instance
320
+ opts.state.isPaused = false;
321
+ opts.state.isBeyondMaxPage = false;
322
+ this._binding('unbind');
323
+
324
+ },
325
+
326
+ // Load Callback
327
+ _loadcallback: function infscr_loadcallback(box, data, url) {
328
+ var opts = this.options,
329
+ callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK
330
+ result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append',
331
+ frag;
332
+
333
+ // if behavior is defined and this function is extended, call that instead of default
334
+ if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) {
335
+ this['_loadcallback_'+opts.behavior].call(this,box,data);
336
+ return;
337
+ }
338
+
339
+ switch (result) {
340
+ case 'done':
341
+ this._showdonemsg();
342
+ return false;
343
+
344
+ case 'no-append':
345
+ if (opts.dataType === 'html') {
346
+ data = '<div>' + data + '</div>';
347
+ data = $(data).find(opts.itemSelector);
348
+ }
349
+ break;
350
+
351
+ case 'append':
352
+ var children = box.children();
353
+ // if it didn't return anything
354
+ if (children.length === 0) {
355
+ return this._error('end');
356
+ }
357
+
358
+ // use a documentFragment because it works when content is going into a table or UL
359
+ frag = document.createDocumentFragment();
360
+ while (box[0].firstChild) {
361
+ frag.appendChild(box[0].firstChild);
362
+ }
363
+
364
+ this._debug('contentSelector', $(opts.contentSelector)[0]);
365
+ $(opts.contentSelector)[0].appendChild(frag);
366
+ // previously, we would pass in the new DOM element as context for the callback
367
+ // however we're now using a documentfragment, which doesn't have parents or children,
368
+ // so the context is the contentContainer guy, and we pass in an array
369
+ // of the elements collected as the first argument.
370
+
371
+ data = children.get();
372
+ break;
373
+ }
374
+
375
+ // loadingEnd function
376
+ opts.loading.finished.call($(opts.contentSelector)[0],opts);
377
+
378
+ // smooth scroll to ease in the new content
379
+ if (opts.animate) {
380
+ var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px';
381
+ $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; });
382
+ }
383
+
384
+ if (!opts.animate) {
385
+ // once the call is done, we can allow it again.
386
+ opts.state.isDuringAjax = false;
387
+ }
388
+
389
+ callback(this, data, url);
390
+
391
+ if (opts.prefill) {
392
+ this._prefill();
393
+ }
394
+ },
395
+
396
+ _nearbottom: function infscr_nearbottom() {
397
+
398
+ var opts = this.options,
399
+ pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height();
400
+
401
+ // if behavior is defined and this function is extended, call that instead of default
402
+ if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) {
403
+ return this['_nearbottom_'+opts.behavior].call(this);
404
+ }
405
+
406
+ this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom);
407
+
408
+ // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
409
+ return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom);
410
+
411
+ },
412
+
413
+ // Pause / temporarily disable plugin from firing
414
+ _pausing: function infscr_pausing(pause) {
415
+
416
+ var opts = this.options;
417
+
418
+ // if behavior is defined and this function is extended, call that instead of default
419
+ if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) {
420
+ this['_pausing_'+opts.behavior].call(this,pause);
421
+ return;
422
+ }
423
+
424
+ // If pause is not 'pause' or 'resume', toggle it's value
425
+ if (pause !== 'pause' && pause !== 'resume' && pause !== null) {
426
+ this._debug('Invalid argument. Toggling pause value instead');
427
+ }
428
+
429
+ pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle';
430
+
431
+ switch (pause) {
432
+ case 'pause':
433
+ opts.state.isPaused = true;
434
+ break;
435
+
436
+ case 'resume':
437
+ opts.state.isPaused = false;
438
+ break;
439
+
440
+ case 'toggle':
441
+ opts.state.isPaused = !opts.state.isPaused;
442
+ break;
443
+ }
444
+
445
+ this._debug('Paused', opts.state.isPaused);
446
+ return false;
447
+
448
+ },
449
+
450
+ // Behavior is determined
451
+ // If the behavior option is undefined, it will set to default and bind to scroll
452
+ _setup: function infscr_setup() {
453
+
454
+ var opts = this.options;
455
+
456
+ // if behavior is defined and this function is extended, call that instead of default
457
+ if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) {
458
+ this['_setup_'+opts.behavior].call(this);
459
+ return;
460
+ }
461
+
462
+ this._binding('bind');
463
+
464
+ return false;
465
+
466
+ },
467
+
468
+ // Show done message
469
+ _showdonemsg: function infscr_showdonemsg() {
470
+
471
+ var opts = this.options;
472
+
473
+ // if behavior is defined and this function is extended, call that instead of default
474
+ if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) {
475
+ this['_showdonemsg_'+opts.behavior].call(this);
476
+ return;
477
+ }
478
+
479
+ opts.loading.msg
480
+ .find('img')
481
+ .hide()
482
+ .parent()
483
+ .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () {
484
+ $(this).parent().fadeOut(opts.loading.speed);
485
+ });
486
+
487
+ // user provided callback when done
488
+ opts.errorCallback.call($(opts.contentSelector)[0],'done');
489
+ },
490
+
491
+ // grab each selector option and see if any fail
492
+ _validate: function infscr_validate(opts) {
493
+ for (var key in opts) {
494
+ if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
495
+ this._debug('Your ' + key + ' found no elements.');
496
+ return false;
497
+ }
498
+ }
499
+
500
+ return true;
501
+ },
502
+
503
+ /*
504
+ ----------------------------
505
+ Public methods
506
+ ----------------------------
507
+ */
508
+
509
+ // Bind to scroll
510
+ bind: function infscr_bind() {
511
+ this._binding('bind');
512
+ },
513
+
514
+ // Destroy current instance of plugin
515
+ destroy: function infscr_destroy() {
516
+ this.options.state.isDestroyed = true;
517
+ this.options.loading.finished();
518
+ return this._error('destroy');
519
+ },
520
+
521
+ // Set pause value to false
522
+ pause: function infscr_pause() {
523
+ this._pausing('pause');
524
+ },
525
+
526
+ // Set pause value to false
527
+ resume: function infscr_resume() {
528
+ this._pausing('resume');
529
+ },
530
+
531
+ beginAjax: function infscr_ajax(opts) {
532
+ var instance = this,
533
+ path = opts.path,
534
+ box, desturl, method, condition;
535
+
536
+ // increment the URL bit. e.g. /page/3/
537
+ opts.state.currPage++;
538
+
539
+ // Manually control maximum page
540
+ if ( opts.maxPage != undefined && opts.state.currPage > opts.maxPage ){
541
+ opts.state.isBeyondMaxPage = true;
542
+ this.destroy();
543
+ return;
544
+ }
545
+
546
+ // if we're dealing with a table we can't use DIVs
547
+ box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>');
548
+
549
+ desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
550
+ instance._debug('heading into ajax', desturl);
551
+
552
+ method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback';
553
+ if (opts.appendCallback && opts.dataType === 'html') {
554
+ method += '+callback';
555
+ }
556
+
557
+ switch (method) {
558
+ case 'html+callback':
559
+ instance._debug('Using HTML via .load() method');
560
+ box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) {
561
+ instance._loadcallback(box, responseText, desturl);
562
+ });
563
+
564
+ break;
565
+
566
+ case 'html':
567
+ instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
568
+ $.ajax({
569
+ // params
570
+ url: desturl,
571
+ dataType: opts.dataType,
572
+ complete: function infscr_ajax_callback(jqXHR, textStatus) {
573
+ condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === "success" || textStatus === "notmodified");
574
+ if (condition) {
575
+ instance._loadcallback(box, jqXHR.responseText, desturl);
576
+ } else {
577
+ instance._error('end');
578
+ }
579
+ }
580
+ });
581
+
582
+ break;
583
+ case 'json':
584
+ instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
585
+ $.ajax({
586
+ dataType: 'json',
587
+ type: 'GET',
588
+ url: desturl,
589
+ success: function (data, textStatus, jqXHR) {
590
+ condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === "success" || textStatus === "notmodified");
591
+ if (opts.appendCallback) {
592
+ // if appendCallback is true, you must defined template in options.
593
+ // note that data passed into _loadcallback is already an html (after processed in opts.template(data)).
594
+ if (opts.template !== undefined) {
595
+ var theData = opts.template(data);
596
+ box.append(theData);
597
+ if (condition) {
598
+ instance._loadcallback(box, theData);
599
+ } else {
600
+ instance._error('end');
601
+ }
602
+ } else {
603
+ instance._debug("template must be defined.");
604
+ instance._error('end');
605
+ }
606
+ } else {
607
+ // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback.
608
+ if (condition) {
609
+ instance._loadcallback(box, data, desturl);
610
+ } else {
611
+ instance._error('end');
612
+ }
613
+ }
614
+ },
615
+ error: function() {
616
+ instance._debug("JSON ajax request failed.");
617
+ instance._error('end');
618
+ }
619
+ });
620
+
621
+ break;
622
+ }
623
+ },
624
+
625
+ // Retrieve next set of content items
626
+ retrieve: function infscr_retrieve(pageNum) {
627
+ pageNum = pageNum || null;
628
+
629
+ var instance = this,
630
+ opts = instance.options;
631
+
632
+ // if behavior is defined and this function is extended, call that instead of default
633
+ if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) {
634
+ this['retrieve_'+opts.behavior].call(this,pageNum);
635
+ return;
636
+ }
637
+
638
+ // for manual triggers, if destroyed, get out of here
639
+ if (opts.state.isDestroyed) {
640
+ this._debug('Instance is destroyed');
641
+ return false;
642
+ }
643
+
644
+ // we dont want to fire the ajax multiple times
645
+ opts.state.isDuringAjax = true;
646
+
647
+ opts.loading.start.call($(opts.contentSelector)[0],opts);
648
+ },
649
+
650
+ // Check to see next page is needed
651
+ scroll: function infscr_scroll() {
652
+
653
+ var opts = this.options,
654
+ state = opts.state;
655
+
656
+ // if behavior is defined and this function is extended, call that instead of default
657
+ if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) {
658
+ this['scroll_'+opts.behavior].call(this);
659
+ return;
660
+ }
661
+
662
+ if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) {
663
+ return;
664
+ }
665
+
666
+ if (!this._nearbottom()) {
667
+ return;
668
+ }
669
+
670
+ this.retrieve();
671
+
672
+ },
673
+
674
+ // Toggle pause value
675
+ toggle: function infscr_toggle() {
676
+ this._pausing();
677
+ },
678
+
679
+ // Unbind from scroll
680
+ unbind: function infscr_unbind() {
681
+ this._binding('unbind');
682
+ },
683
+
684
+ // update options
685
+ update: function infscr_options(key) {
686
+ if ($.isPlainObject(key)) {
687
+ this.options = $.extend(true,this.options,key);
688
+ }
689
+ }
690
+ };
691
+
692
+
693
+ /*
694
+ ----------------------------
695
+ Infinite Scroll function
696
+ ----------------------------
697
+
698
+ Borrowed logic from the following...
699
+
700
+ jQuery UI
701
+ - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
702
+
703
+ jCarousel
704
+ - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
705
+
706
+ Masonry
707
+ - https://github.com/desandro/masonry/blob/master/jquery.masonry.js
708
+
709
+ */
710
+
711
+ $.fn.infinitescroll = function infscr_init(options, callback) {
712
+
713
+
714
+ var thisCall = typeof options;
715
+
716
+ switch (thisCall) {
717
+
718
+ // method
719
+ case 'string':
720
+ var args = Array.prototype.slice.call(arguments, 1);
721
+
722
+ this.each(function () {
723
+ var instance = $.data(this, 'infinitescroll');
724
+
725
+ if (!instance) {
726
+ // not setup yet
727
+ // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup');
728
+ return false;
729
+ }
730
+
731
+ if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
732
+ // return $.error('No such method ' + options + ' for Infinite Scroll');
733
+ return false;
734
+ }
735
+
736
+ // no errors!
737
+ instance[options].apply(instance, args);
738
+ });
739
+
740
+ break;
741
+
742
+ // creation
743
+ case 'object':
744
+
745
+ this.each(function () {
746
+
747
+ var instance = $.data(this, 'infinitescroll');
748
+
749
+ if (instance) {
750
+
751
+ // update options of current instance
752
+ instance.update(options);
753
+
754
+ } else {
755
+
756
+ // initialize new instance
757
+ instance = new $.infinitescroll(options, callback, this);
758
+
759
+ // don't attach if instantiation failed
760
+ if (!instance.failed) {
761
+ $.data(this, 'infinitescroll', instance);
762
+ }
763
+
764
+ }
765
+
766
+ });
767
+
768
+ break;
769
+
770
+ }
771
+
772
+ return this;
773
+ };
774
+
775
+
776
+
777
+ /*
778
+ * smartscroll: debounced scroll event for jQuery *
779
+ * https://github.com/lukeshumard/smartscroll
780
+ * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
781
+ * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
782
+ */
783
+
784
+ var event = $.event,
785
+ scrollTimeout;
786
+
787
+ event.special.smartscroll = {
788
+ setup: function () {
789
+ $(this).bind("scroll", event.special.smartscroll.handler);
790
+ },
791
+ teardown: function () {
792
+ $(this).unbind("scroll", event.special.smartscroll.handler);
793
+ },
794
+ handler: function (event, execAsap) {
795
+ // Save the context
796
+ var context = this,
797
+ args = arguments;
798
+
799
+ // set correct event type
800
+ event.type = "smartscroll";
801
+
802
+ if (scrollTimeout) { clearTimeout(scrollTimeout); }
803
+ scrollTimeout = setTimeout(function () {
804
+ $(context).trigger('smartscroll', args);
805
+ }, execAsap === "execAsap" ? 0 : 100);
806
+ }
807
+ };
808
+
809
+ $.fn.smartscroll = function (fn) {
810
+ return fn ? this.bind("smartscroll", fn) : this.trigger("smartscroll", ["execAsap"]);
811
+ };
812
+
813
+
814
+ })(window, jQuery);