UNPKG

jquery.bouncer

Version:

Defers event handler until a duration has lapsed or a given event has occurred.

123 lines (104 loc) 3.46 kB
/*! jQuery Bouncer - v1.0.0-beta - 2015-02-09 * https://github.com/tableau-mkt/jquery.bouncer * Copyright (c) 2015 Joel Walters; Licensed MIT */ /* jshint node:true */ /* global define:false */ (function (factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['jquery'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory; } else { // Browser globals factory(window.jQuery); } }(function ($) { 'use strict'; var pluginName = 'bouncer', defaults = { wait: 5000, events: 'click.bouncer', activeClass: 'is-processing', resolveEvent: 'bouncer:resolve', rejectEvent: 'bouncer:reject' }; function Plugin(element, options) { this.element = element; this.options = $.extend({}, defaults, options); this._defaults = defaults; this._name = pluginName; this.init(); } Plugin.prototype = { init: function () { this.$element = $(this.element); this.initTime = new Date().getTime(); this.deferred = $.Deferred(); // Default done handler. this.deferred.done($.proxy(function (options) { options = options || {}; if (!options.preserveActiveClass) { this.$element.removeClass(this.options.activeClass); } if (this.event) { delete this.event.isDefaultPrevented; delete this.event.isImmediatePropagationStopped; delete this.event.isPropagationStopped; this.$element.trigger($.Event(this.event.type, this.event)); } }, this)); // Attach events handlers. this.$element.on(this.options.events, $.proxy(this.eventHandler, this)); this.$element.on(this.options.resolveEvent, $.proxy(this.resolveHandler, this)); this.$element.on(this.options.rejectEvent, $.proxy(this.rejectHandler, this)); // Return our deferred object. return this.deferred; }, resolveHandler: function (e, data) { this.deferred.resolve(data); }, rejectHandler: function (e, data) { this.deferred.reject(data); }, eventHandler: function (e) { var _this = this, isResolved = this.deferred.state() === 'resolved', timeSinceReady, isExpired; timeSinceReady = new Date().getTime() - this.initTime; isExpired = timeSinceReady > this.options.wait; // Wait time lapsed or resolved — do not interfere. if (isExpired || isResolved) { return; } // Save the event for triggering later. this.event = e; // Prevent default handlers and cancel other click handlers. e.preventDefault(); e.stopImmediatePropagation(); // Set a timer to resolve our deferred object. if (!this.processingTimeoutId) { this.$element.addClass(this.options.activeClass); this.processingTimeoutId = setTimeout(function () { _this.deferred.resolve(); }, this.options.wait - timeSinceReady); } } }; $.fn[pluginName] = function (options) { var deferreds = [], instance; this.each(function () { if (!$.data(this, 'plugin_' + pluginName)) { instance = new Plugin(this, options); deferreds.push(instance.deferred); $.data(this, 'plugin_' + pluginName, instance); } }); return $.when.apply(this, deferreds); }; }));