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

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

redefine selectize templates without escaping + translate "Add"

File size: 10.8 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  // redefine Selectize templates without escape
175  AbstractSelectizer.getRender = function(field_label, lang) {
176    lang = lang || { 'Add': 'Add' };
177
178        return {
179      'option': function(data, escape) {
180        return '<div class="option">' + data[field_label] + '</div>';
181      },
182      'item': function(data, escape) {
183        return '<div class="item">' + data[field_label] + '</div>';
184      },
185      'option_create': function(data, escape) {
186        return '<div class="create">' + lang['Add'] + ' <strong>' + data.input + '</strong>&hellip;</div>';
187      }
188    };
189  };
190
191
192  /**
193   * Special LocalStorage for admin categories list
194   *
195   * @param options {object}
196   *    - serverId (recommended) identifier of the Piwigo instance
197   *    - serverKey (required) state of collection server-side
198   *    - rootUrl (required) used for WS call
199   */
200  var CategoriesCache = function(options) {
201    options.key = 'categoriesAdminList';
202   
203    options.loader = function(callback) {
204      $.getJSON(options.rootUrl + 'ws.php?format=json&method=pwg.categories.getAdminList', function(data) {
205        callback(data.result.categories);
206      });
207    };
208   
209    this._init(options);
210  };
211
212  CategoriesCache.prototype = new AbstractSelectizer();
213
214  /*
215   * Init Selectize with cache content
216   * @see AbstractSelectizer._selectize
217   */
218  CategoriesCache.prototype.selectize = function($target, options) {
219    options = options || {};
220
221    $target.selectize({
222      valueField: 'id',
223      labelField: 'fullname',
224      sortField: 'global_rank',
225      searchField: ['fullname'],
226      plugins: ['remove_button'],
227      render: AbstractSelectizer.getRender('fullname', options.lang)
228    });
229   
230    this._selectize($target, options);
231  };
232
233
234  /**
235   * Special LocalStorage for admin tags list
236   *
237   * @param options {object}
238   *    - serverId (recommended) identifier of the Piwigo instance
239   *    - serverKey (required) state of collection server-side
240   *    - rootUrl (required) used for WS call
241   */
242  var TagsCache = function(options) {
243    options.key = 'tagsAdminList';
244   
245    options.loader = function(callback) {
246      $.getJSON(options.rootUrl + 'ws.php?format=json&method=pwg.tags.getAdminList', function(data) {
247        var tags = data.result.tags;
248       
249        for (var i=0, l=tags.length; i<l; i++) {
250          tags[i].id = '~~' + tags[i].id + '~~';
251        }
252       
253        callback(tags);
254      });
255    };
256   
257    this._init(options);
258  };
259
260  TagsCache.prototype = new AbstractSelectizer();
261
262  /*
263   * Init Selectize with cache content
264   * @see AbstractSelectizer._selectize
265   */
266  TagsCache.prototype.selectize = function($target, options) {
267    options = options || {};
268
269    $target.selectize({
270      valueField: 'id',
271      labelField: 'name',
272      sortField: 'name',
273      searchField: ['name'],
274      plugins: ['remove_button'],
275      render: AbstractSelectizer.getRender('name', options.lang)
276    });
277   
278    this._selectize($target, options);
279  };
280 
281 
282  /**
283   * Special LocalStorage for admin groups list
284   *
285   * @param options {object}
286   *    - serverId (recommended) identifier of the Piwigo instance
287   *    - serverKey (required) state of collection server-side
288   *    - rootUrl (required) used for WS call
289   */
290  var GroupsCache = function(options) {
291    options.key = 'groupsAdminList';
292   
293    options.loader = function(callback) {
294      $.getJSON(options.rootUrl + 'ws.php?format=json&method=pwg.groups.getList&per_page=9999', function(data) {
295        callback(data.result.groups);
296      });
297    };
298   
299    this._init(options);
300  };
301
302  GroupsCache.prototype = new AbstractSelectizer();
303
304  /*
305   * Init Selectize with cache content
306   * @see AbstractSelectizer._selectize
307   */
308  GroupsCache.prototype.selectize = function($target, options) {
309    options = options || {};
310
311    $target.selectize({
312      valueField: 'id',
313      labelField: 'name',
314      sortField: 'name',
315      searchField: ['name'],
316      plugins: ['remove_button'],
317      render: AbstractSelectizer.getRender('name', options.lang)
318    });
319   
320    this._selectize($target, options);
321  };
322 
323 
324  /**
325   * Special LocalStorage for admin users list
326   *
327   * @param options {object}
328   *    - serverId (recommended) identifier of the Piwigo instance
329   *    - serverKey (required) state of collection server-side
330   *    - rootUrl (required) used for WS call
331   */
332  var UsersCache = function(options) {
333    options.key = 'usersAdminList';
334   
335    options.loader = function(callback) {
336      var users = [];
337     
338      // recursive loader
339      (function load(page){
340        jQuery.getJSON(options.rootUrl + 'ws.php?format=json&method=pwg.users.getList&display=username&per_page=9999&page='+ page, function(data) {
341          users = users.concat(data.result.users);
342         
343          if (data.result.paging.count == data.result.paging.per_page) {
344            load(++page);
345          }
346          else {
347            callback(users);
348          }
349        });
350      }(0));
351    };
352   
353    this._init(options);
354  };
355
356  UsersCache.prototype = new AbstractSelectizer();
357
358  /*
359   * Init Selectize with cache content
360   * @see AbstractSelectizer._selectize
361   */
362  UsersCache.prototype.selectize = function($target, options) {
363    options = options || {};
364
365    $target.selectize({
366      valueField: 'id',
367      labelField: 'username',
368      sortField: 'username',
369      searchField: ['username'],
370      plugins: ['remove_button'],
371      render: AbstractSelectizer.getRender('username', options.lang)
372    });
373   
374    this._selectize($target, options);
375  };
376 
377 
378  /**
379   * Expose classes in global scope
380   */
381  exports.LocalStorageCache = LocalStorageCache;
382  exports.CategoriesCache = CategoriesCache;
383  exports.TagsCache = TagsCache;
384  exports.GroupsCache = GroupsCache;
385  exports.UsersCache = UsersCache;
386 
387}(jQuery, window));
Note: See TracBrowser for help on using the repository browser.