UNPKG

fuelux

Version:

Base Fuel UX styles and controls

196 lines (157 loc) 5.16 kB
/* global jQuery:true */ /* * Fuel UX Infinite Scroll * https://github.com/ExactTarget/fuelux * * Copyright (c) 2014 ExactTarget * Licensed under the BSD New license. */ // -- BEGIN UMD WRAPPER PREFACE -- // For more information on UMD visit: // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js (function umdFactory (factory) { if (typeof define === 'function' && define.amd) { // if AMD loader is available, register as an anonymous module. define(['jquery', 'fuelux/loader'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery'), require('./loader')); } else { // OR use browser globals if AMD is not present factory(jQuery); } }(function InfiniteScrollWrapper ($) { // -- END UMD WRAPPER PREFACE -- // -- BEGIN MODULE CODE HERE -- var old = $.fn.infinitescroll; // INFINITE SCROLL CONSTRUCTOR AND PROTOTYPE var InfiniteScroll = function (element, options) { this.$element = $(element); this.$element.addClass('infinitescroll'); this.options = $.extend({}, $.fn.infinitescroll.defaults, options); this.curScrollTop = this.$element.scrollTop(); this.curPercentage = this.getPercentage(); this.fetchingData = false; this.$element.on('scroll.fu.infinitescroll', $.proxy(this.onScroll, this)); this.onScroll(); }; InfiniteScroll.prototype = { constructor: InfiniteScroll, destroy: function () { this.$element.remove(); // any external bindings // [none] // empty elements to return to original markup this.$element.empty(); return this.$element[0].outerHTML; }, disable: function () { this.$element.off('scroll.fu.infinitescroll'); }, enable: function () { this.$element.on('scroll.fu.infinitescroll', $.proxy(this.onScroll, this)); }, end: function (content) { var end = $('<div class="infinitescroll-end"></div>'); if (content) { end.append(content); } else { end.append('---------'); } this.$element.append(end); this.disable(); }, getPercentage: function () { var height = (this.$element.css('box-sizing') === 'border-box') ? this.$element.outerHeight() : this.$element.height(); var scrollHeight = this.$element.get(0).scrollHeight; // If we cannot compute the height, then we end up fetching all pages (ends up #/0 = Infinity). // This can happen if the repeater is loaded, but is not in the dom if (scrollHeight === 0 || scrollHeight - this.curScrollTop === 0) { return 0; } return (height / (scrollHeight - this.curScrollTop)) * 100; }, fetchData: function (force) { var load = $('<div class="infinitescroll-load"></div>'); var self = this; var moreBtn; var fetch = function () { var helpers = { percentage: self.curPercentage, scrollTop: self.curScrollTop }; var $loader = $('<div class="loader"></div>'); load.append($loader); $loader.loader(); if (self.options.dataSource) { self.options.dataSource(helpers, function (resp) { var end; load.remove(); if (resp.content) { self.$element.append(resp.content); } if (resp.end) { end = (resp.end !== true) ? resp.end : undefined; self.end(end); } self.fetchingData = false; }); } }; this.fetchingData = true; this.$element.append(load); if (this.options.hybrid && force !== true) { moreBtn = $('<button type="button" class="btn btn-primary"></button>'); if (typeof this.options.hybrid === 'object') { moreBtn.append(this.options.hybrid.label); } else { moreBtn.append('<span class="glyphicon glyphicon-repeat"></span>'); } moreBtn.on('click.fu.infinitescroll', function () { moreBtn.remove(); fetch(); }); load.append(moreBtn); } else { fetch(); } }, onScroll: function (e) { this.curScrollTop = this.$element.scrollTop(); this.curPercentage = this.getPercentage(); if (!this.fetchingData && this.curPercentage >= this.options.percentage) { this.fetchData(); } } }; // INFINITE SCROLL PLUGIN DEFINITION $.fn.infinitescroll = function (option) { var args = Array.prototype.slice.call(arguments, 1); var methodReturn; var $set = this.each(function () { var $this = $(this); var data = $this.data('fu.infinitescroll'); var options = typeof option === 'object' && option; if (!data) { $this.data('fu.infinitescroll', (data = new InfiniteScroll(this, options))); } if (typeof option === 'string') { methodReturn = data[option].apply(data, args); } }); return (methodReturn === undefined) ? $set : methodReturn; }; $.fn.infinitescroll.defaults = { dataSource: null, hybrid: false,//can be true or an object with structure: { 'label': (markup or jQuery obj) } percentage: 95//percentage scrolled to the bottom before more is loaded }; $.fn.infinitescroll.Constructor = InfiniteScroll; $.fn.infinitescroll.noConflict = function () { $.fn.infinitescroll = old; return this; }; // NO DATA-API DUE TO NEED OF DATA-SOURCE // -- BEGIN UMD WRAPPER AFTERWORD -- })); // -- END UMD WRAPPER AFTERWORD --