362 lines
11 KiB
JavaScript
362 lines
11 KiB
JavaScript
|
/*
|
||
|
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
|
||
|
* @version 3.1.4
|
||
|
* @link http://fooplugins.com
|
||
|
* @copyright Steven Usher & Brad Vincent 2015
|
||
|
* @license Released under the GPLv3 license.
|
||
|
*/
|
||
|
(function($, F){
|
||
|
|
||
|
// global int to use if the table has no ID
|
||
|
var _uid = 0,
|
||
|
// a hash value for the current url
|
||
|
_url_hash = (function(str){
|
||
|
var i, l, hval = 0x811c9dc5;
|
||
|
for (i = 0, l = str.length; i < l; i++) {
|
||
|
hval ^= str.charCodeAt(i);
|
||
|
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
|
||
|
}
|
||
|
return hval >>> 0;
|
||
|
})(location.origin + location.pathname);
|
||
|
|
||
|
F.State = F.Component.extend(/** @lends FooTable.State */{
|
||
|
/**
|
||
|
* The state component adds the ability for the table to remember its basic state for filtering, paging and sorting.
|
||
|
* @constructs
|
||
|
* @extends FooTable.Component
|
||
|
* @param {FooTable.Table} table - The parent {@link FooTable.Table} object for the component.
|
||
|
* @returns {FooTable.State}
|
||
|
*/
|
||
|
construct: function(table){
|
||
|
// call the constructor of the base class
|
||
|
this._super(table, table.o.state.enabled);
|
||
|
// Change this value if an update to this component requires any stored data to be reset
|
||
|
this._key = '1';
|
||
|
/**
|
||
|
* The key to use to store the state for this table.
|
||
|
* @type {(null|string)}
|
||
|
*/
|
||
|
this.key = this._key + (F.is.string(table.o.state.key) ? table.o.state.key : this._uid());
|
||
|
/**
|
||
|
* Whether or not to allow the filtering component to store it's state.
|
||
|
* @type {boolean}
|
||
|
*/
|
||
|
this.filtering = F.is.boolean(table.o.state.filtering) ? table.o.state.filtering : true;
|
||
|
/**
|
||
|
* Whether or not to allow the paging component to store it's state.
|
||
|
* @type {boolean}
|
||
|
*/
|
||
|
this.paging = F.is.boolean(table.o.state.paging) ? table.o.state.paging : true;
|
||
|
/**
|
||
|
* Whether or not to allow the sorting component to store it's state.
|
||
|
* @type {boolean}
|
||
|
*/
|
||
|
this.sorting = F.is.boolean(table.o.state.sorting) ? table.o.state.sorting : true;
|
||
|
},
|
||
|
/* PROTECTED */
|
||
|
/**
|
||
|
* Checks the supplied data and options for the state component.
|
||
|
* @instance
|
||
|
* @protected
|
||
|
* @param {object} data - The jQuery data object from the parent table.
|
||
|
* @fires FooTable.State#"preinit.ft.state"
|
||
|
* @this FooTable.State
|
||
|
*/
|
||
|
preinit: function(data){
|
||
|
var self = this;
|
||
|
/**
|
||
|
* The preinit.ft.state event is raised before the UI is created and provides the tables jQuery data object for additional options parsing.
|
||
|
* Calling preventDefault on this event will disable the component.
|
||
|
* @event FooTable.State#"preinit.ft.state"
|
||
|
* @param {jQuery.Event} e - The jQuery.Event object for the event.
|
||
|
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
|
||
|
* @param {object} data - The jQuery data object of the table raising the event.
|
||
|
*/
|
||
|
this.ft.raise('preinit.ft.state', [data]).then(function(){
|
||
|
|
||
|
self.enabled = F.is.boolean(data.state)
|
||
|
? data.state
|
||
|
: self.enabled;
|
||
|
|
||
|
if (!self.enabled) return;
|
||
|
|
||
|
self.key = self._key + (F.is.string(data.stateKey) ? data.stateKey : self.key);
|
||
|
|
||
|
self.filtering = F.is.boolean(data.stateFiltering) ? data.stateFiltering : self.filtering;
|
||
|
|
||
|
self.paging = F.is.boolean(data.statePaging) ? data.statePaging : self.paging;
|
||
|
|
||
|
self.sorting = F.is.boolean(data.stateSorting) ? data.stateSorting : self.sorting;
|
||
|
|
||
|
}, function(){
|
||
|
self.enabled = false;
|
||
|
});
|
||
|
},
|
||
|
/**
|
||
|
* Gets the state value for the specified key for this table.
|
||
|
* @instance
|
||
|
* @param {string} key - The key to get the value for.
|
||
|
* @returns {(*|null)}
|
||
|
*/
|
||
|
get: function(key){
|
||
|
return JSON.parse(localStorage.getItem(this.key + ':' + key));
|
||
|
},
|
||
|
/**
|
||
|
* Sets the state value for the specified key for this table.
|
||
|
* @instance
|
||
|
* @param {string} key - The key to set the value for.
|
||
|
* @param {*} data - The value to store for the key. This value must be JSON.stringify friendly.
|
||
|
*/
|
||
|
set: function(key, data){
|
||
|
localStorage.setItem(this.key + ':' + key, JSON.stringify(data));
|
||
|
},
|
||
|
/**
|
||
|
* Clears the state value for the specified key for this table.
|
||
|
* @instance
|
||
|
* @param {string} key - The key to clear the value for.
|
||
|
*/
|
||
|
remove: function(key){
|
||
|
localStorage.removeItem(this.key + ':' + key);
|
||
|
},
|
||
|
/**
|
||
|
* Executes the {@link FooTable.Component#readState} function on all components.
|
||
|
* @instance
|
||
|
*/
|
||
|
read: function(){
|
||
|
this.ft.execute(false, true, 'readState');
|
||
|
},
|
||
|
/**
|
||
|
* Executes the {@link FooTable.Component#writeState} function on all components.
|
||
|
* @instance
|
||
|
*/
|
||
|
write: function(){
|
||
|
this.ft.execute(false, true, 'writeState');
|
||
|
},
|
||
|
/**
|
||
|
* Executes the {@link FooTable.Component#clearState} function on all components.
|
||
|
* @instance
|
||
|
*/
|
||
|
clear: function(){
|
||
|
this.ft.execute(false, true, 'clearState');
|
||
|
},
|
||
|
/**
|
||
|
* Generates a unique identifier for the current {@link FooTable.Table} if one is not supplied through the options.
|
||
|
* This value is a combination of the url hash and either the element ID or an incremented global int value.
|
||
|
* @instance
|
||
|
* @returns {*}
|
||
|
* @private
|
||
|
*/
|
||
|
_uid: function(){
|
||
|
var id = this.ft.$el.attr('id');
|
||
|
return _url_hash + '_' + (F.is.string(id) ? id : ++_uid);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
F.components.register('state', F.State, 700);
|
||
|
|
||
|
})(jQuery, FooTable);
|
||
|
(function(F){
|
||
|
|
||
|
/**
|
||
|
* This method is called from the {@link FooTable.State#read} method and allows a component to retrieve its' stored state.
|
||
|
* @instance
|
||
|
* @protected
|
||
|
* @function
|
||
|
*/
|
||
|
F.Component.prototype.readState = function(){};
|
||
|
|
||
|
/**
|
||
|
* This method is called from the {@link FooTable.State#write} method and allows a component to write its' current state to the store.
|
||
|
* @instance
|
||
|
* @protected
|
||
|
* @function
|
||
|
*/
|
||
|
F.Component.prototype.writeState = function(){};
|
||
|
|
||
|
/**
|
||
|
* This method is called from the {@link FooTable.State#clear} method and allows a component to clear any stored state.
|
||
|
* @instance
|
||
|
* @protected
|
||
|
* @function
|
||
|
*/
|
||
|
F.Component.prototype.clearState = function(){};
|
||
|
|
||
|
})(FooTable);
|
||
|
(function(F){
|
||
|
|
||
|
/**
|
||
|
* An object containing the state options for the plugin. Added by the {@link FooTable.State} component.
|
||
|
* @type {object}
|
||
|
* @prop {boolean} enabled=false - Whether or not to allow state to be stored for the table. This overrides the individual component enable options.
|
||
|
* @prop {boolean} filtering=true - Whether or not to allow the filtering state to be stored.
|
||
|
* @prop {boolean} paging=true - Whether or not to allow the filtering state to be stored.
|
||
|
* @prop {boolean} sorting=true - Whether or not to allow the filtering state to be stored.
|
||
|
* @prop {string} key=null - The unique key to use to store the table's data.
|
||
|
*/
|
||
|
F.Defaults.prototype.state = {
|
||
|
enabled: false,
|
||
|
filtering: true,
|
||
|
paging: true,
|
||
|
sorting: true,
|
||
|
key: null
|
||
|
};
|
||
|
|
||
|
})(FooTable);
|
||
|
(function(F){
|
||
|
|
||
|
if (!F.Filtering) return;
|
||
|
|
||
|
/**
|
||
|
* Allows the filtering component to retrieve its' stored state.
|
||
|
*/
|
||
|
F.Filtering.prototype.readState = function(){
|
||
|
if (this.ft.state.filtering){
|
||
|
var state = this.ft.state.get('filtering');
|
||
|
if (F.is.hash(state) && !F.is.emptyArray(state.filters)){
|
||
|
this.filters = this.ensure(state.filters);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Allows the filtering component to write its' current state to the store.
|
||
|
*/
|
||
|
F.Filtering.prototype.writeState = function(){
|
||
|
if (this.ft.state.filtering) {
|
||
|
var filters = F.arr.map(this.filters, function (f) {
|
||
|
return {
|
||
|
name: f.name,
|
||
|
query: f.query instanceof F.Query ? f.query.val() : f.query,
|
||
|
columns: F.arr.map(f.columns, function (c) {
|
||
|
return c.name;
|
||
|
}),
|
||
|
hidden: f.hidden,
|
||
|
space: f.space,
|
||
|
connectors: f.connectors,
|
||
|
ignoreCase: f.ignoreCase
|
||
|
};
|
||
|
});
|
||
|
this.ft.state.set('filtering', {filters: filters});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Allows the filtering component to clear any stored state.
|
||
|
*/
|
||
|
F.Filtering.prototype.clearState = function(){
|
||
|
if (this.ft.state.filtering) {
|
||
|
this.ft.state.remove('filtering');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
})(FooTable);
|
||
|
(function(F){
|
||
|
|
||
|
if (!F.Paging) return;
|
||
|
|
||
|
/**
|
||
|
* Allows the paging component to retrieve its' stored state.
|
||
|
*/
|
||
|
F.Paging.prototype.readState = function(){
|
||
|
if (this.ft.state.paging) {
|
||
|
var state = this.ft.state.get('paging');
|
||
|
if (F.is.hash(state)) {
|
||
|
this.current = state.current;
|
||
|
this.size = state.size;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Allows the paging component to write its' current state to the store.
|
||
|
*/
|
||
|
F.Paging.prototype.writeState = function(){
|
||
|
if (this.ft.state.paging) {
|
||
|
this.ft.state.set('paging', {
|
||
|
current: this.current,
|
||
|
size: this.size
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Allows the paging component to clear any stored state.
|
||
|
*/
|
||
|
F.Paging.prototype.clearState = function(){
|
||
|
if (this.ft.state.paging) {
|
||
|
this.ft.state.remove('paging');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
})(FooTable);
|
||
|
(function(F){
|
||
|
|
||
|
if (!F.Sorting) return;
|
||
|
|
||
|
/**
|
||
|
* Allows the sorting component to retrieve its' stored state.
|
||
|
*/
|
||
|
F.Sorting.prototype.readState = function(){
|
||
|
if (this.ft.state.sorting) {
|
||
|
var state = this.ft.state.get('sorting');
|
||
|
if (F.is.hash(state)) {
|
||
|
var column = this.ft.columns.get(state.column);
|
||
|
if (column instanceof F.Column) {
|
||
|
this.column = column;
|
||
|
this.column.direction = state.direction;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Allows the sorting component to write its' current state to the store.
|
||
|
*/
|
||
|
F.Sorting.prototype.writeState = function(){
|
||
|
if (this.ft.state.sorting && this.column instanceof F.Column){
|
||
|
this.ft.state.set('sorting', {
|
||
|
column: this.column.name,
|
||
|
direction: this.column.direction
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Allows the sorting component to clear any stored state.
|
||
|
*/
|
||
|
F.Sorting.prototype.clearState = function(){
|
||
|
if (this.ft.state.sorting) {
|
||
|
this.ft.state.remove('sorting');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
})(FooTable);
|
||
|
(function(F){
|
||
|
|
||
|
// hook into the _construct method so we can add the state property to the table.
|
||
|
F.Table.extend('_construct', function(ready){
|
||
|
this.state = this.use(FooTable.State);
|
||
|
this._super(ready);
|
||
|
});
|
||
|
|
||
|
// hook into the _preinit method so we can trigger a plugin wide read state operation.
|
||
|
F.Table.extend('_preinit', function(){
|
||
|
var self = this;
|
||
|
return self._super().then(function(){
|
||
|
if (self.state.enabled){
|
||
|
self.state.read();
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// hook into the draw method so we can trigger a plugin wide write state operation.
|
||
|
F.Table.extend('draw', function(){
|
||
|
var self = this;
|
||
|
return self._super().then(function(){
|
||
|
if (self.state.enabled){
|
||
|
self.state.write();
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
})(FooTable);
|