Skip to content

Instantly share code, notes, and snippets.

@gemmadlou
Created September 27, 2016 16:13
Show Gist options
  • Save gemmadlou/5d6057727b1655fff19ad63a22f7a959 to your computer and use it in GitHub Desktop.
Save gemmadlou/5d6057727b1655fff19ad63a22f7a959 to your computer and use it in GitHub Desktop.
Declarative Filtering & Sorting (with jQuery Selectors)
/* 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