app/scripts/ui-lib/widgets/filter.coffee

Filter

The Filter class provides a simple filtering widget.

author: Julien Ramboz version: 1.0 usage: Filter examples

AMD loader

Try loading as AMD module or fall back to default loading

((widget) -> if typeof define is "function" and define.amd define ["jslib", "core", "widget", "toolbar"], widget else widget @$, _, _.AbstractWidget, _.Toolbar ) toolbar = ($, _, AbstractWidget, Toolbar) -> "use strict"

Widget

The actual widget class

class FilterElements extends AbstractWidget

Default options for the widget

@defaultOptions:
  • form: a selector pointing to the form
form: ""
  • filters: a selector pointing to the filters
filters: ""
  • items: a selector pointing to the items
items: ""

Initialisation

Initializer function.

initialize: (options) -> super options @form = @findForm() @filters = @findFilters() @items = @findItems()

Accessibility markup

Add aria attributes

aria: () -> super()

Event handling

Attach evenets to the widget

bindEvents: () -> @form.submit () => @applyFilter() false @form.on "reset", (e) => @clear()

Filter the items

applyFilter: (paramString) -> paramString = (paramString or @element.find("form").serialize())

convert the serialized parameters to a usable filtering object

filters = paramString.split("&").reduce(((res,o) -> [key,val] = o.split("=") if val res[key] = res[key] || [] res[key].push(val) res), {})

Trigger an event before doing the acutal filtering

@element.trigger "beforeFilter", items: @items filters: filters

Do the actual filtering

@items.show() return if not Object.keys(filters).length

Update the url according to the current filters

hash = window.location.hash window.history.pushState "filter", "" , "?#{paramString}#{hash}"

Toggle corresponding items

@items.hide().filter( () -> for key, values of filters valuesArray = this.getAttribute("data-filter-#{key}").split(",") for value in values if not (value in valuesArray) return false return true).show()

Trigger an event after doing the acutal filtering

@element.trigger "afterFilter", items: @items filters: filters

Clear the filter

clear: () -> @items.show() hash = window.location.hash window.history.pushState "filter", "" , "?#{hash}"

Structure discovery

Find the widget structure using the specified configuration

Form

Find the filtering form, specified in one of the following ways:

  • using form option, specified as a selector
  • using the form descendant
findForm: () -> if @options.form $(@options.form, @element) else @element.find "form"

Filters

Find the filters, specified in one of the following ways:

  • elements with data-role="filter"
  • using filters option, specified as a selector
findFilters: () -> $filters = @element.find("[data-role='filter']") return $filters if $filters.length if @options.filters $filters = $(@options.filters, @element) else $() $filters.filter () -> not $(this).is("[role='presentation'],[data-role='label']")

Filter items

Find the filter items, specified in one of the following ways:

  • elements with data-role="filter"
  • using items option, specified as a selector
  • using elements having a data-filter-* attribute
findItems: () -> $items = @element.find("[data-role='filter-item']") return $items if $items.length if @options.items $items = $(@options.items, @element) else $items = @element.find() @element.find("*").filter () -> i = 0 while i < @attributes.length return true if @attributes[i].name.match(/data-filter-/) i++ false

Key handling

Cleanup

Cleanup the widget and remove remaining references

destructor: () ->

Installation

Install the widget into the JS library

FilterElements.install("FilterElements", () -> $("[data-widget='filter']")["#{_.namespace}filterelements"]() if window.location.search $("[data-widget='filter']")["#{_.namespace}filterelements"]("applyFilter", window.location.search.substring(1)) )