145 lines
3.6 KiB
JavaScript
145 lines
3.6 KiB
JavaScript
import {Feature} from './feature';
|
|
import Str from '../string';
|
|
import Event from '../event';
|
|
|
|
const global = window;
|
|
const JSON = global.JSON;
|
|
const location = global.location;
|
|
const hasHashChange = () => {
|
|
var docMode = global.documentMode;
|
|
return ('onhashchange' in global) && (docMode === undefined || docMode > 7);
|
|
};
|
|
|
|
export class Stateful extends Feature {
|
|
|
|
/**
|
|
* Makes features stateful via URL hash
|
|
* @param {Object} tf TableFilter instance
|
|
*/
|
|
constructor(tf) {
|
|
super(tf, 'stateful');
|
|
|
|
let cfg = this.config.stateful;
|
|
|
|
this.persistFilters = cfg.filters === false ? false : true;
|
|
this.persistPageNumber = Boolean(cfg.page_number);
|
|
this.persistPageLength = Boolean(cfg.page_length);
|
|
|
|
this.pageNb = null;
|
|
this.lastHash = null;
|
|
this.state = {};
|
|
this.prfxCol = 'col_';
|
|
this.pageNbKey = 'page';
|
|
this.pageResultsKey = 'results';
|
|
}
|
|
|
|
init() {
|
|
if (this.initialized || !hasHashChange()) {
|
|
return;
|
|
}
|
|
|
|
this.emitter.on(['initialized'], () => this.sync());
|
|
this.emitter.on([
|
|
'after-filtering',
|
|
'after-page-change',
|
|
'after-page-length-change'
|
|
], () => this.update());
|
|
|
|
Event.add(global, 'hashchange', () => this.sync());
|
|
|
|
this.initialized = true;
|
|
}
|
|
|
|
format() {
|
|
let tf = this.tf;
|
|
|
|
if (this.persistFilters) {
|
|
let filterValues = tf.getFiltersValue();
|
|
|
|
filterValues.forEach((val, idx) => {
|
|
let key = `${this.prfxCol}${idx}`;
|
|
|
|
if (Str.isEmpty(val)) {
|
|
if (this.state.hasOwnProperty(key)) {
|
|
this.state[key] = undefined;
|
|
}
|
|
} else {
|
|
this.state[key] = this.state[key] || {};
|
|
this.state[key].flt = val;
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
if (this.persistPageNumber) {
|
|
let pageNumber = tf.feature('paging').getPage();
|
|
this.state[this.pageNbKey] = pageNumber;
|
|
}
|
|
|
|
if (this.persistPageLength) {
|
|
|
|
}
|
|
|
|
return `#${JSON.stringify(this.state)}`;
|
|
}
|
|
|
|
parse(hash) {
|
|
if (hash.indexOf('#') === 0) {
|
|
hash = hash.substr(1);
|
|
} else {
|
|
hash = '{}';
|
|
}
|
|
return JSON.parse(hash);
|
|
}
|
|
|
|
update() {
|
|
let hash = this.format();
|
|
console.log(hash, this.lastHash, this.lastHash === hash);
|
|
if (this.lastHash === hash) {
|
|
return;
|
|
}
|
|
|
|
location.hash = hash;
|
|
this.lastHash = hash;
|
|
}
|
|
|
|
sync() {
|
|
let state = this.parse(location.hash);
|
|
let tf = this.tf;
|
|
|
|
if (this.persistFilters) {
|
|
Object.keys(state).forEach((key) => {
|
|
if (key.indexOf(this.prfxCol) !== -1) {
|
|
let colIdx = parseInt(key.replace(this.prfxCol, ''), 10);
|
|
let val = state[key].flt;
|
|
tf.setFilterValue(colIdx, val);
|
|
}
|
|
});
|
|
|
|
tf.filter();
|
|
}
|
|
|
|
if (this.persistPageNumber) {
|
|
let pageNumber = state[this.pageNbKey];
|
|
tf.feature('paging').setPage(pageNumber);
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
if (!this.initialized) {
|
|
return;
|
|
}
|
|
|
|
this.emitter.on(['initialized'], () => this.sync());
|
|
this.emitter.off([
|
|
'after-filtering',
|
|
'after-page-change',
|
|
'after-page-length-change'
|
|
], () => this.update());
|
|
|
|
Event.remove(global, 'hashchange', () => this.sync());
|
|
|
|
this.initialized = false;
|
|
}
|
|
}
|