Skip to content

Commit aa3da0d

Browse files
committed
feat(javascript): Add choice of remebering filters
Also add comments
1 parent eb24ae0 commit aa3da0d

1 file changed

Lines changed: 163 additions & 29 deletions

File tree

Resources/Public/JavaScript/ModuleDataListing.js

Lines changed: 163 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@ define([
1010
], function () {
1111
var ModuleDataListing = {
1212
settings: {
13-
ajaxUrlKey: '',
13+
// The URL called when updating the datatable
14+
ajaxUrl: '',
15+
// If set, localStorage is used for rembering filters
16+
storageKey: null,
17+
// jQuery selector of your datatable
1418
tableSelector: '#mdl-datatable',
15-
searchButtonSelector: '.mdl-search',
19+
// jQuery selector of button for filtering
20+
filterButtonSelector: '.mdl-filter-search',
21+
// jQuery selector of button for clearing filters
22+
clearButtonSelector: '.mdl-filter-clear',
1623

24+
// DataTable options
1725
dataTable: {
1826
processing: true,
1927
serverSide: true,
@@ -60,84 +68,210 @@ define([
6068
}
6169
},
6270

71+
// Setting config - merges options
6372
config: function(options = {}) {
64-
ModuleDataListing.settings = Object.assign({}, ModuleDataListing.settings, options);
73+
ModuleDataListing.settings = ModuleDataListing.utility.mergeObjects(ModuleDataListing.settings, options);
6574
}
6675
};
6776

68-
ModuleDataListing.local = {
77+
/**
78+
* Local Storage
79+
*
80+
* Only works if `storageKey` is set.
81+
*
82+
* Everything is stored in a single JSON object keyed by
83+
* ModuleDataListing.${settings.storageKey}
84+
*/
85+
ModuleDataListing.storage = {
86+
87+
/**
88+
* Get an item from localStorage
89+
*/
6990
get: function(key) {
70-
let storage = localStorage.getItem('ModuleDataListing');
71-
storage = JSON.parse(storage);
91+
if (!ModuleDataListing.settings.storageKey) {
92+
return null;
93+
}
94+
95+
let storage = localStorage.getItem(
96+
'ModuleDataListing.' + ModuleDataListing.settings.storageKey
97+
);
98+
storage = storage ? JSON.parse(storage) : {};
7299

73-
return storage[key];
100+
return storage.hasOwnProperty(key) ? storage[key] : null;
74101
},
102+
103+
/**
104+
* Add an item to localStorage
105+
*/
75106
set: function(key, data) {
76-
let storage = localStorage.getItem('ModuleDataListing') ?? '';
77-
storage = JSON.parse(storage);
107+
if (!ModuleDataListing.settings.storageKey) {
108+
return;
109+
}
78110

111+
// Load existing storage
112+
let storage = localStorage.getItem(
113+
'ModuleDataListing.' + ModuleDataListing.settings.storageKey
114+
);
115+
116+
storage = storage ? JSON.parse(storage) : {};
117+
118+
// Add our new data
79119
storage[key] = data;
80120

81-
localStorage.setItem('ModuleDataListing', JSON.stringify(storage));
121+
// Store it
122+
localStorage.setItem(
123+
'ModuleDataListing.' + ModuleDataListing.settings.storageKey,
124+
JSON.stringify(storage)
125+
);
82126
},
127+
128+
/**
129+
* Empty the localsotrage for this storage key
130+
*/
131+
clear: function() {
132+
localStorage.removeItem(
133+
'ModuleDataListing.' + ModuleDataListing.settings.storageKey
134+
)
135+
}
83136
}
84137

138+
/**
139+
* DataTable functions
140+
*
141+
* Uses https://datatables.net/
142+
*/
85143
ModuleDataListing.dataTable = {
86-
init: function(filters) {
144+
init: function(filters = null) {
145+
146+
// See if we can get filters from storage
147+
if(!filters) {
148+
filters = ModuleDataListing.storage.get('filters');
149+
}
150+
151+
// Add the dynamic options
87152
const settings = {
88153
search: {
89-
search: ''
154+
search: ModuleDataListing.storage.get('keywords')
90155
},
156+
91157
ajax: {
92-
url: TYPO3.settings.ajaxUrls[ModuleDataListing.settings.ajaxUrlKey],
158+
url: ModuleDataListing.settings.ajaxUrl,
93159
data: {
94160
filters: filters
95161
}
96162
},
97163
}
164+
165+
// Initialise the datatable
98166
const table = $(ModuleDataListing.settings.tableSelector)
99167
.DataTable(
100-
Object.assign({}, ModuleDataListing.settings.dataTable, settings)
168+
ModuleDataListing.utility.mergeObjects(ModuleDataListing.settings.dataTable, settings)
101169
);
102170

171+
// Add listener for search box to update storage
103172
table.on('search.dt', function () {
104-
// // Get the current URL
105-
// let url = new URL(window.location);
106-
// url.searchParams.set('search', table.search());
107-
// window.history.pushState({}, '', url);
173+
ModuleDataListing.storage.set('keywords', table.search());
108174
});
109175

110176
return table;
111177
},
112178

179+
// Remove datatable config
113180
destroy: function() {
114181
$(ModuleDataListing.settings.tableSelector).DataTable().destroy();
115182
},
116183

117-
restart: function(filters) {
184+
restart: function(filters = null) {
118185
ModuleDataListing.dataTable.destroy();
119186
ModuleDataListing.dataTable.init(filters);
120187
}
121188
};
122189

190+
/**
191+
* Filter
192+
*/
123193
ModuleDataListing.filters = {
194+
// Filter setup
124195
init: function () {
125-
$(ModuleDataListing.settings.searchButtonSelector).click(function () {
126-
let filters = {}
127196

128-
$('div[data-mdl-filter]').each(function () {
129-
let self = $(this);
130-
let filterData = [];
197+
// Set any filters from storage
198+
ModuleDataListing.filters.set(
199+
ModuleDataListing.storage.get('filters')
200+
);
201+
202+
// Add click listener to search button
203+
$(ModuleDataListing.settings.filterButtonSelector).click(function () {
204+
let filters = ModuleDataListing.filters.get();
205+
ModuleDataListing.storage.set('filters', filters);
206+
ModuleDataListing.dataTable.restart(filters);
207+
});
208+
209+
// Remove all filters when cleared
210+
$(ModuleDataListing.settings.clearButtonSelector).click(function () {
211+
ModuleDataListing.storage.clear();
212+
ModuleDataListing.filters.clear();
213+
ModuleDataListing.dataTable.restart({});
214+
});
215+
},
216+
217+
/**
218+
* Get an object & array of checked items
219+
*/
220+
get: function () {
221+
let filters = {};
131222

132-
self.find('input:checked').each(function () {
133-
filterData.push($(this).val());
134-
});
223+
$('div[data-mdl-filter]').each(function () {
224+
let self = $(this);
225+
let filterData = [];
135226

136-
filters[self.data('mdl-filter')] = filterData;
227+
self.find('input:checked').each(function () {
228+
filterData.push($(this).val());
137229
});
138230

139-
ModuleDataListing.dataTable.restart(filters);
231+
filters[self.data('mdl-filter')] = filterData;
140232
});
233+
234+
return filters;
235+
},
236+
237+
/**
238+
* Check any checkbox which were in the filters object
239+
*/
240+
set: function (filters = {}) {
241+
for (let filter in filters) {
242+
let container = $(`div[data-mdl-filter="${filter}"]`);
243+
for (let value of filters[filter]) {
244+
container.find(`input[value="${value}"]`).prop('checked', true);
245+
}
246+
}
247+
},
248+
249+
/**
250+
* Uncheck all checkboxes
251+
*/
252+
clear: function () {
253+
$('div[data-mdl-filter] input:checked').each(function() {
254+
$(this).prop('checked', false);
255+
})
256+
},
257+
}
258+
259+
ModuleDataListing.utility = {
260+
// Filter setup
261+
mergeObjects: function (obj1, obj2) {
262+
const result = JSON.parse(JSON.stringify(obj1));
263+
264+
for (let key in obj2) {
265+
if (obj2[key] instanceof Array && obj1[key] instanceof Array) {
266+
result[key] = obj2[key];
267+
} else if (obj2[key] instanceof Object && obj1[key] instanceof Object) {
268+
result[key] = ModuleDataListing.utility.mergeObjects(obj1[key], obj2[key]);
269+
} else {
270+
result[key] = obj2[key];
271+
}
272+
}
273+
274+
return result;
141275
}
142276
}
143277

0 commit comments

Comments
 (0)