var Filter = (function() { function Filter(element) { this._element = $(element); this._optionsContainer = this._element.find(this.constructor.optionsContainerSelector); } Filter.selector = '.filter'; Filter.optionsContainerSelector = '> div'; Filter.hideOptionsClass = 'hide-options'; Filter.enhance = function() { var klass = this; return $(klass.selector).each(function() { return new klass(this).enhance(); }); }; Filter.prototype.enhance = function() { this._buildUI(); this._bindEvents(); }; Filter.prototype._buildUI = function() { this._summaryElement = $(''). addClass('summary'). attr('data-role', 'summary'). prependTo(this._optionsContainer); this._clearSelectionButton = $(''). text('Clear'). attr('type', 'button'). insertAfter(this._summaryElement); this._optionsContainer.addClass(this.constructor.hideOptionsClass); this._updateSummary(); }; Filter.prototype._bindEvents = function() { var self = this; this._summaryElement.click(function() { self._toggleOptions(); }); this._clearSelectionButton.click(function() { self._clearSelection(); }); this._checkboxes().change(function() { self._updateSummary(); }); $('body').click(function(e) { var inFilter = $(e.target).closest(self.constructor.selector).length > 0; if (!inFilter) { self._allOptionsContainers().addClass(self.constructor.hideOptionsClass); } }); }; Filter.prototype._toggleOptions = function() { this._allOptionsContainers(). not(this._optionsContainer). addClass(this.constructor.hideOptionsClass); this._optionsContainer.toggleClass(this.constructor.hideOptionsClass); }; Filter.prototype._updateSummary = function() { var summary = 'All'; var checked = this._checkboxes().filter(':checked'); if (checked.length > 0) { summary = this._labelsFor(checked).join(', '); } this._summaryElement.text(summary); }; Filter.prototype._clearSelection = function() { this._checkboxes().each(function() { $(this).prop('checked', false); }); this._updateSummary(); }; Filter.prototype._checkboxes = function() { return this._element.find(':checkbox'); }; Filter.prototype._labelsFor = function(inputs) { return inputs.map(function() { var id = $(this).attr('id'); return $("label[for='" + id + "']").text(); }).get(); }; Filter.prototype._allOptionsContainers = function() { return $(this.constructor.selector + " " + this.constructor.optionsContainerSelector); }; return Filter; })(); $(function() { Filter.enhance(); });