@@ -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