Created
September 27, 2016 16:13
-
-
Save gemmadlou/5d6057727b1655fff19ad63a22f7a959 to your computer and use it in GitHub Desktop.
Declarative Filtering & Sorting (with jQuery Selectors)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global jQuery */ | |
/*jshint esversion: 6 */ | |
/** | |
* Use a singleton | |
* Declare trigger options declaratively in code | |
* | |
* | |
* @TODO provide a polyfill for maps | |
* @TODO make library agnostic - especially jQuery | |
* @TODO multiple filter options | |
*/ | |
module.exports = (function(app) { | |
var $ = jQuery; | |
var settings = {}; | |
settings.numInPage = 4; | |
// Each data selector should reference the same uniqueId | |
settings.selectors = {}; | |
settings.selectors.grid = '[data-l-card]'; | |
settings.selectors.grid_items = '[data-l-card-item]'; | |
settings.selectors.filter_button = '[data-l-card-filter-button]'; | |
settings.selectors.load_button = '[data-l-card-load-button]'; | |
settings.selectors.filter = '[data-l-card-filter]'; | |
settings.classStates = {}; | |
settings.classStates.disabled = 'is-disabled'; | |
var helpers = {}; | |
helpers.classname = function(selector) { | |
return selector.replace('.', ''); | |
}; | |
helpers.dataname = function(selector) { | |
return selector.replace(/[\[\]]/g, ''); | |
}; | |
helpers.uniqueSelector = function(selector, id) { | |
var selectorString = `[${helpers.dataname(selector)}="${id}"]`; | |
return $(selectorString); | |
}; | |
var model = {}; | |
model.card = function(el, filters) { | |
return { | |
el: el, | |
filters: filters | |
} | |
}; | |
// ----- Persistence store | |
var data = { | |
index: {}, // of arrays, immutable - only change once - or on data laod | |
states: {}, // of arrays | |
filters: {}, // of strings | |
setIndex: function(uniqueId, data) { | |
this.index[uniqueId] = data; | |
}, | |
getIndex: function(uniqueId) { | |
return this.index[uniqueId] || {}; | |
}, | |
setState: function(uniqueId, newState) { | |
this.states[uniqueId] = newState; | |
}, | |
resetState: function(uniqueId) { | |
this.states[uniqueId] = []; | |
}, | |
getState: function(uniqueId) { | |
return this.states[uniqueId] || []; | |
}, | |
getStateHTML: function(uniqueId) { | |
return this.getState(uniqueId).map(function() { | |
return $(this.el)[0].outerHTML; | |
}).get().join(''); | |
}, | |
setFilter: function(uniqueId, filter) { | |
this.filters[uniqueId] = filter || ''; | |
this.resetState(uniqueId); | |
}, | |
getFilter: function(uniqueId) { | |
return this.filters[uniqueId] || ''; | |
} | |
}; | |
// ----- Functional Logic of Application | |
var filterBy = function(data, filter) { | |
if (filter === '') { | |
return data; | |
} | |
return data.filter(function(i, item) { | |
return (item.filters.indexOf(filter) > -1); | |
}); | |
}; | |
var newCumulativeArrayFromState = function(data, existingState, multiple) { | |
return data.slice(0, (existingState.length + multiple)); | |
}; | |
var filterAndLoadMore = function(data, filter, state, numInPage) { | |
return newCumulativeArrayFromState(filterBy(data, filter), state, numInPage); | |
}; | |
// ----- Impure Side of Application | |
var updateUI = function(id) { | |
// Get representation of UI | |
var uiState = filterAndLoadMore(data.getIndex(id), data.getFilter(id), data.getState(id), settings.numInPage); | |
var $grid = helpers.uniqueSelector(settings.selectors.grid, id); | |
data.setState(id, uiState); | |
// Update HTML | |
$grid.html(data.getStateHTML(id)); | |
// Check if there's any more content to load and display button | |
// @TODO create own buttonUI Function | |
var $button = helpers.uniqueSelector(settings.selectors.load_button, id); | |
if (filterBy(data.getIndex(id), data.getFilter(id)).length > data.getState(id).length) { | |
$button.removeClass(settings.classStates.disabled); | |
} else { | |
$button.addClass(settings.classStates.disabled); | |
} | |
}; | |
var initGrid = function() { | |
var id = $(this).attr(helpers.dataname(settings.selectors.grid)); | |
var $children = $(this).find(settings.selectors.grid_items); | |
var children = $children.map(function() { | |
var filter = $(this).attr(helpers.dataname(settings.selectors.filter)).split(' ') || ''; | |
return model.card(this, filter); | |
}); | |
data.setIndex(id, children); | |
data.setFilter(id); | |
// Set first UI State | |
updateUI(id); | |
}; | |
// @TODO be more particular, make select, not clickable, but changeable | |
var initFilterButtonInit = function() { | |
$(this).on('change', eventFilterButtonChange); | |
}; | |
var initLoadButtonInit = function() { | |
$(this).on('click', eventLoadButtonClick); | |
}; | |
var eventFilterButtonChange = function() { | |
var filtervalue = $(this).val(); | |
var id = $(this).attr(helpers.dataname(settings.selectors.filter_button)); | |
data.setFilter(id, filtervalue); | |
updateUI(id); | |
}; | |
var eventLoadButtonClick = function() { | |
var id = $(this).attr(helpers.dataname(settings.selectors.load_button)); | |
updateUI(id); | |
}; | |
var init = function() { | |
$(settings.selectors.grid).each(initGrid); | |
$(settings.selectors.filter_button).each(initFilterButtonInit); | |
$(settings.selectors.load_button).each(initLoadButtonInit); | |
}; | |
$(init); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment