Support-Groups/media/footable/js/footable.memory.js

430 lines
12 KiB
JavaScript

/**
* Footable Memory
*
* Version 1.1.0
*
* Requires browser support for localStorage. Fallback to cookies using
* jQuery Cookie (https://github.com/carhartl/jquery-cookie)
*
* Stores table state in a cookie and reloads state when page is refreshed.
*
* Supports common FooTable features:
* - Pagination
* - Sorting
* - Filtering
* - Expansion
*
* Written to be compatible with multiple FooTables per page and with
* JavaScript libraries like AngularJS and Ember that use hash based URLs.
*
* Disabled by default, to enable add the following section to the footable
* options:
*
* $('#table').footable({
* memory: {
* enabled: true
* }
* });
*
* Based on FooTable Plugin Bookmarkable by Amy Farrell (https://github.com/akf)
*
* Created by Chris Laskey (https://github.com/chrislaskey)
*/
(function ($, w, undefined) {
if (w.footable === undefined || w.foobox === null) {
throw new Error('Please check and make sure footable.js is included in the page and is loaded prior to this script.');
}
var defaults = {
memory: {
enabled: false
}
};
var storage;
var storage_engines = {};
storage_engines.local_storage = (function($){
'use strict';
var path_page = function(){
return location.pathname;
};
var path_subpage = function(){
return location.hash || 'root';
};
var storage_key = function(index){
return path_page() + '/' + path_subpage() + '/index-' + index;
};
var get = function(index){
var key = storage_key(index),
as_string = localStorage.getItem(key);
return as_string ? JSON.parse(as_string) : {};
};
var set = function(index, item){
var key = storage_key(index),
as_string = JSON.stringify(item);
localStorage.setItem(key, as_string);
};
return {
get: function(index){
return get(index);
},
set: function(index, item){
set(index, item);
}
};
})($);
storage_engines.cookie = (function($){
'use strict';
/**
* Stores footable bookmarkable data in a cookie
*
* By default will store each page in its own cookie.
* Supports multiple FooTables per page.
* Supports JS frameworks that use hashmap URLs (AngularJS, Ember, etc).
*
* For example take an example application:
*
* http://example.com/application-data (2 FooTables on this page)
* http://example.com/application-data/#/details (1 FooTable on this page)
* http://example.com/other-data (1 FooTable on this page)
*
* Would be stored like this:
*
* cookie['/application-data'] = {
* '/': {
* 1: {
* key1: value1,
* key2: value2
* },
* 2: {
* key1: value1,
* key2: value2
* }
* },
* '#/details': {
* 1: {
* key1: value1,
* key2: value2
* }
* }
* };
*
* cookie['/other-data'] = {
* '/': {
* 1: {
* key1: value1,
* key2: value2
* },
* }
* }
*
*/
if( $.cookie ){
$.cookie.json = true;
}
var days_to_keep_data = 7;
var path_page = function(){
return location.pathname;
};
var path_subpage = function(){
return location.hash || '/';
};
var get_data = function(){
var page = path_page(),
data = $.cookie(page);
return data || {};
};
var get_table = function(index){
var subpage = path_subpage(),
data = get_data();
if( data[subpage] && data[subpage][index] ){
return data[subpage][index];
} else {
return {};
}
};
var set = function(index, item){
var page = path_page(),
subpage = path_subpage(),
data = get_data(),
options;
if( !data[subpage] ){
data[subpage] = {};
}
data[subpage][index] = item;
options = {
path: page,
expires: days_to_keep_data
};
$.cookie(page, data, options);
};
return {
get: function(index){
return get_table(index);
},
set: function(index, item){
set(index, item);
}
};
})($);
var set_storage_engine = (function(){
var test = 'footable-memory-plugin-storage-test';
try {
localStorage.setItem(test, test);
localStorage.removeItem(test);
storage = storage_engines.local_storage;
} catch(e) {
try {
$.cookie(test, test);
storage = storage_engines.cookie;
} catch(e) {
throw new Error('FooTable Memory requires either localStorage or cookie support via jQuery $.cookie plugin (https://github.com/carhartl/jquery-cookie)');
}
}
})($);
var state = (function($){
'use strict';
/**
* Gets and sets current table state
*/
var vars = {};
var get = {};
var set = {};
set.vars = function(ft){
vars.ft = ft;
vars.table = $(ft.table);
};
get.descending = function(){
var descending = false;
$.each(vars.table.find('th'), function(index){
if( $(this).hasClass('footable-sorted-desc') ){
descending = true;
}
});
return descending;
};
get.expanded = function(){
var indexes = [];
$.each(vars.ft.table.rows, function(index, value){
if( $(this).hasClass('footable-detail-show') ){
indexes.push(index);
}
});
return indexes;
};
set.expanded = function(data){
if( data.expanded ){
$.each(data.expanded, function(index, value){
// var row = $(vars.ft.table.rows[value]);
// row.find('> td:first').trigger('footable_toggle_row');
// Trying to execute the lines above, but the expanded row
// shows raw AngularJS template (with {{ values }}) instead
// of the fully rendered result.
//
// Best guess is some things happen after
// 'footable_initialized' event and row expanding can not
// occur until after those fire.
//
// A hack to get around this is to wait an interval before
// executing the intended commands. Wrapped in an
// immediately executing function to ensure ft is the
// current value.
(function(ft){
setTimeout(function(){
var row = $(ft.table.rows[value]);
row.find('> td:first').trigger('footable_toggle_row');
}, 150);
})(vars.ft);
});
}
};
get.filter = function(){
return vars.table.data('filter') ? $(vars.table.data('filter')).val() : '';
};
set.filter = function(data){
if( data.filter ){
$(vars.table.data('filter'))
.val(data.filter)
.trigger('keyup');
}
};
get.page = function(){
return vars.ft.pageInfo && vars.ft.pageInfo.currentPage !== undefined ? vars.ft.pageInfo.currentPage : 0;
};
set.page = function(data){
if( data.page ){
vars.table.data('currentPage', data.page);
// Delay triggering table until sort is updated, since both effect
// pagination.
}
};
get.shown = function(){
return vars.table
.find('tbody')
.find('tr:not(.footable-row-detail)')
.filter(':visible').length;
};
get.sorted = function(){
if( vars.table.data('sorted') !== undefined ){
return vars.table.data('sorted');
} else {
return -1;
}
};
set.sorted = function(data){
if( data.sorted >= 0 ) {
// vars.table.data('footable-sort').doSort(data.sorted, !data.descending);
// Trying to execute the line above, but only sort icon on the
// <th> element gets set. The rows themselves do not get sorted.
//
// Best guess is some things happen after 'footable_initialized' event
// and sorting can not occur until after those fire.
//
// A hack to get around this is to wait an interval before executing
// the intended commands. Wrapped in an immediately executing
// function to ensure ft is the current value.
(function(ft){
setTimeout(function(){
$(ft.table).data('footable-sort').doSort(data.sorted, !data.descending);
}, 150);
})(vars.ft);
} else {
vars.table.trigger('footable_setup_paging');
}
};
get.total = function(){
return vars.table
.find('tbody')
.find('tr:not(.footable-row-detail, .footable-filtered)').length;
};
var get_state = function(){
return {
descending: get.descending(),
expanded: get.expanded(),
filter: get.filter(),
page: get.page(),
shown: get.shown(),
sorted: get.sorted(),
total: get.total()
};
};
var set_state = function(data){
set.filter(data);
set.page(data);
set.sorted(data);
set.expanded(data);
};
return {
get: function(ft){
set.vars(ft);
return get_state();
},
set: function(ft, data){
set.vars(ft);
return set_state(data);
}
};
})($);
var is_enabled = function(ft){
return ft.options.memory.enabled;
};
var update = function(ft, event) {
var index = ft.id,
data = state.get(ft);
storage.set(index, data);
};
var load = function(ft){
var index = ft.id,
data = storage.get(index);
state.set(ft, data);
ft.memory_plugin_loaded = true;
};
function Memory() {
var p = this;
p.name = 'Footable Memory';
p.init = function(ft) {
if (is_enabled(ft)) {
$(ft.table).bind({
'footable_initialized': function(){
load(ft);
},
'footable_page_filled footable_redrawn footable_filtered footable_sorted footable_row_expanded footable_row_collapsed': function(e) {
if (ft.memory_plugin_loaded) {
update(ft, e);
}
}
});
}
};
}
w.footable.plugins.register(Memory, defaults);
})(jQuery, window);