source: trunk/admin/themes/default/js/LocalStorageCache.js @ 28555

Last change on this file since 28555 was 28555, checked in by mistic100, 10 years ago

feature 3077 : fix addAlbum process when creating the first ever album, improve data API

File size: 9.9 KB
Line 
1(function($, exports) {
2  "use strict";
3 
4  /**
5   * Base LocalStorage cache
6   *
7   * @param options {object}
8   *    - key (required) identifier of the collection
9   *    - serverId (recommended) identifier of the Piwigo instance
10   *    - serverKey (required) state of collection server-side
11   *    - lifetime (optional) cache lifetime in seconds
12   *    - loader (required) function called to fetch data, takes a callback as first argument
13   *        which must be called with the loaded date
14   */
15  var LocalStorageCache = function(options) {
16    this._init(options);
17  };
18
19  /*
20   * Constructor (deported for easy inheritance)
21   */
22  LocalStorageCache.prototype._init = function(options) {
23    this.key = options.key + '_' + options.serverId;
24    this.serverKey = options.serverKey;
25    this.lifetime = options.lifetime ? options.lifetime*1000 : 3600*1000;
26    this.loader = options.loader;
27   
28    this.storage = window.localStorage;
29    this.ready = !!this.storage;
30  };
31
32  /*
33   * Get the cache content
34   * @param callback {function} called with the data as first parameter
35   */
36  LocalStorageCache.prototype.get = function(callback) {
37    var now = new Date().getTime(),
38        that = this;
39   
40    if (this.ready && this.storage[this.key] != undefined) {
41      var cache = JSON.parse(this.storage[this.key]);
42     
43      if (now - cache.timestamp <= this.lifetime && cache.key == this.serverKey) {
44        callback(cache.data);
45        return;
46      }
47    }
48   
49    this.loader(function(data) {
50      that.set.call(that, data);
51      callback(data);
52    });
53  };
54
55  /*
56   * Manually set the cache content
57   * @param data {mixed}
58   */
59  LocalStorageCache.prototype.set = function(data) {
60    if (this.ready) {
61      this.storage[this.key] = JSON.stringify({
62        timestamp: new Date().getTime(),
63        key: this.serverKey,
64        data: data
65      });
66    }
67  };
68
69  /*
70   * Manually clear the cache
71   */
72  LocalStorageCache.prototype.clear = function() {
73    if (this.ready) {
74      this.storage.removeItem(this.key);
75    }
76  };
77
78 
79  /**
80   * Abstract class containing common initialization code for selectize
81   */
82  var AbstractSelectizer = function(){};
83  AbstractSelectizer.prototype = new LocalStorageCache({});
84
85  /*
86   * Load Selectize with cache content
87   * @param $target {jQuery} may have some data attributes (create, default, value)
88   * @param options {object}
89   *    - value (optional) list of preselected items (ids, or objects with "id" attribute")
90   *    - default (optional) default value which will be forced if the select is emptyed
91   *    - create (optional) allow item user creation
92   *    - filter (optional) function called for each select before applying the data
93   *      takes two parameters: cache data, options
94   *      must return new data
95   */
96  AbstractSelectizer.prototype._selectize = function($target, globalOptions) {
97    this.get(function(data) {
98      $target.each(function() {
99        var filtered, value, defaultValue,
100            options = $.extend({}, globalOptions);
101       
102        // apply filter function
103        if (options.filter != undefined) {
104          filtered = options.filter.call(this, data, options);
105        }
106        else {
107          filtered = data;
108        }
109       
110        // active creation mode
111        if (this.hasAttribute('data-create')) {
112          options.create = true;
113        }
114        this.selectize.settings.create = !!options.create;
115
116        // load options
117        this.selectize.load(function(callback) {
118          if ($.isEmptyObject(this.options)) {
119            callback(filtered);
120          }
121        });
122
123        // load items
124        if ((value = $(this).data('value'))) {
125          options.value = value;
126        }
127        if (options.value != undefined) {
128          $.each(value, $.proxy(function(i, cat) {
129            if ($.isNumeric(cat))
130              this.selectize.addItem(cat);
131            else
132              this.selectize.addItem(cat.id);
133          }, this));
134        }
135       
136        // set default
137        if ((defaultValue = $(this).data('default'))) {
138          options.default = defaultValue;
139        }
140        if (options.default == 'first') {
141          options.default = filtered[0] ? filtered[0].id : undefined;
142        }
143       
144        if (options.default != undefined) {
145          // add default item
146          if (this.selectize.getValue() == '') {
147            this.selectize.addItem(options.default);
148          }
149
150          // if multiple: prevent item deletion
151          if (this.multiple) {
152            this.selectize.getItem(options.default).find('.remove').hide();
153           
154            this.selectize.on('item_remove', function(id) {
155              if (id == options.default) {
156                this.addItem(id);
157                this.getItem(id).find('.remove').hide();
158              }
159            });
160          }
161          // if single: restore default on blur
162          else {
163            this.selectize.on('dropdown_close', function() {
164              if (this.getValue() == '') {
165                this.addItem(options.default);
166              }
167            });
168          }
169        }
170      });
171    });
172  };
173
174
175  /**
176   * Special LocalStorage for admin categories list
177   *
178   * @param options {object}
179   *    - serverId (recommended) identifier of the Piwigo instance
180   *    - serverKey (required) state of collection server-side
181   *    - rootUrl (required) used for WS call
182   */
183  var CategoriesCache = function(options) {
184    options.key = 'categoriesAdminList';
185   
186    options.loader = function(callback) {
187      $.getJSON(options.rootUrl + 'ws.php?format=json&method=pwg.categories.getAdminList', function(data) {
188        callback(data.result.categories);
189      });
190    };
191   
192    this._init(options);
193  };
194
195  CategoriesCache.prototype = new AbstractSelectizer();
196
197  /*
198   * Init Selectize with cache content
199   * @see AbstractSelectizer._selectize
200   */
201  CategoriesCache.prototype.selectize = function($target, options) {
202    options = options || {};
203
204    $target.selectize({
205      valueField: 'id',
206      labelField: 'fullname',
207      sortField: 'global_rank',
208      searchField: ['fullname'],
209      plugins: ['remove_button']
210    });
211   
212    this._selectize($target, options);
213  };
214
215
216  /**
217   * Special LocalStorage for admin tags list
218   *
219   * @param options {object}
220   *    - serverId (recommended) identifier of the Piwigo instance
221   *    - serverKey (required) state of collection server-side
222   *    - rootUrl (required) used for WS call
223   */
224  var TagsCache = function(options) {
225    options.key = 'tagsAdminList';
226   
227    options.loader = function(callback) {
228      $.getJSON(options.rootUrl + 'ws.php?format=json&method=pwg.tags.getAdminList', function(data) {
229        var tags = data.result.tags;
230       
231        for (var i=0, l=tags.length; i<l; i++) {
232          tags[i].id = '~~' + tags[i].id + '~~';
233        }
234       
235        callback(tags);
236      });
237    };
238   
239    this._init(options);
240  };
241
242  TagsCache.prototype = new AbstractSelectizer();
243
244  /*
245   * Init Selectize with cache content
246   * @see AbstractSelectizer._selectize
247   */
248  TagsCache.prototype.selectize = function($target, options) {
249    options = options || {};
250
251    $target.selectize({
252      valueField: 'id',
253      labelField: 'name',
254      sortField: 'name',
255      searchField: ['name'],
256      plugins: ['remove_button']
257    });
258   
259    this._selectize($target, options);
260  };
261 
262 
263  /**
264   * Special LocalStorage for admin groups list
265   *
266   * @param options {object}
267   *    - serverId (recommended) identifier of the Piwigo instance
268   *    - serverKey (required) state of collection server-side
269   *    - rootUrl (required) used for WS call
270   */
271  var GroupsCache = function(options) {
272    options.key = 'groupsAdminList';
273   
274    options.loader = function(callback) {
275      $.getJSON(options.rootUrl + 'ws.php?format=json&method=pwg.groups.getList&per_page=9999', function(data) {
276        callback(data.result.groups);
277      });
278    };
279   
280    this._init(options);
281  };
282
283  GroupsCache.prototype = new AbstractSelectizer();
284
285  /*
286   * Init Selectize with cache content
287   * @see AbstractSelectizer._selectize
288   */
289  GroupsCache.prototype.selectize = function($target, options) {
290    options = options || {};
291
292    $target.selectize({
293      valueField: 'id',
294      labelField: 'name',
295      sortField: 'name',
296      searchField: ['name'],
297      plugins: ['remove_button']
298    });
299   
300    this._selectize($target, options);
301  };
302 
303 
304  /**
305   * Special LocalStorage for admin users list
306   *
307   * @param options {object}
308   *    - serverId (recommended) identifier of the Piwigo instance
309   *    - serverKey (required) state of collection server-side
310   *    - rootUrl (required) used for WS call
311   */
312  var UsersCache = function(options) {
313    options.key = 'usersAdminList';
314   
315    options.loader = function(callback) {
316      var users = [];
317     
318      // recursive loader
319      (function load(page){
320        jQuery.getJSON(options.rootUrl + 'ws.php?format=json&method=pwg.users.getList&display=username&per_page=9999&page='+ page, function(data) {
321          users = users.concat(data.result.users);
322         
323          if (data.result.paging.count == data.result.paging.per_page) {
324            load(++page);
325          }
326          else {
327            callback(users);
328          }
329        });
330      }(0));
331    };
332   
333    this._init(options);
334  };
335
336  UsersCache.prototype = new AbstractSelectizer();
337
338  /*
339   * Init Selectize with cache content
340   * @see AbstractSelectizer._selectize
341   */
342  UsersCache.prototype.selectize = function($target, options) {
343    options = options || {};
344
345    $target.selectize({
346      valueField: 'id',
347      labelField: 'username',
348      sortField: 'username',
349      searchField: ['username'],
350      plugins: ['remove_button']
351    });
352   
353    this._selectize($target, options);
354  };
355 
356 
357  /**
358   * Expose classes in global scope
359   */
360  exports.LocalStorageCache = LocalStorageCache;
361  exports.CategoriesCache = CategoriesCache;
362  exports.TagsCache = TagsCache;
363  exports.GroupsCache = GroupsCache;
364  exports.UsersCache = UsersCache;
365 
366}(jQuery, window));
Note: See TracBrowser for help on using the repository browser.