3 // (c) 2013 Michal Kuklis
4 // Licensed under The MIT License
5 // http://opensource.org/licenses/MIT
7 (function (name, root, factory) {
8 if (typeof exports == 'object') {
9 module.exports = factory();
10 } else if (typeof define == 'function' && define.amd) {
13 root[name] = factory();
15 }("depot", this, function () {
23 save: function (record) {
26 if (!record[this.idAttribute]) {
27 record[this.idAttribute] = guid();
30 id = record[this.idAttribute] + '';
32 if (this.ids.indexOf(id) < 0) {
34 this.storageAdaptor.setItem(this.name, this.ids.join(","));
37 this.storageAdaptor.setItem(getKey(this.name, id), JSON.stringify(record));
42 update: function (id, data) {
43 if (typeof data == 'undefined') {
45 id = data[this.idAttribute];
48 var record = this.get(id);
51 record = extend(record, data);
58 updateAll: function (data) {
59 var records = this.all();
61 records.forEach(function (record) {
62 record = extend(record, data);
69 find: function (criteria) {
70 var key, match, record;
74 if (!criteria) return this.all();
76 return this.ids.reduce(function (memo, id) {
77 record = jsonData(self.storageAdaptor.getItem(getKey(name, id)));
78 match = findMatch(criteria, record);
89 return jsonData(this.storageAdaptor.getItem(getKey(this.name, id)));
93 var record, self = this, name = this.name;
95 return this.ids.reduce(function (memo, id) {
96 record = self.storageAdaptor.getItem(getKey(name, id));
99 memo.push(jsonData(record));
106 destroy: function (record) {
108 var id = (record[this.idAttribute]) ? record[this.idAttribute] : record;
109 var key = getKey(this.name, id);
111 record = jsonData(this.storageAdaptor.getItem(key));
112 this.storageAdaptor.removeItem(key);
114 index = this.ids.indexOf(id);
115 if (index != -1) this.ids.splice(index, 1);
116 this.storageAdaptor.setItem(this.name, this.ids.join(","));
121 destroyAll: function (criteria) {
122 var attr, id, match, record, key;
124 for (var i = this.ids.length - 1; i >= 0; i--) {
126 key = getKey(this.name, id);
130 record = jsonData(this.storageAdaptor.getItem(key));
131 match = findMatch(criteria, record);
134 this.storageAdaptor.removeItem(key);
135 this.ids.splice(i, 1);
140 this.storageAdaptor.removeItem(key);
145 this.storageAdaptor.setItem(this.name, this.ids.join(","));
148 this.storageAdaptor.removeItem(this.name);
154 return this.ids.length;
160 function jsonData(data) {
161 return data && JSON.parse(data);
164 function getKey(name, id) {
165 return name + "-" + id;
168 function findMatch(criteria, record) {
171 if (typeof criteria == 'function') {
172 match = criteria(record);
176 for (attr in criteria) {
177 match &= (criteria[attr] === record[attr]);
185 return Math.floor((1 + Math.random()) * 0x10000)
186 .toString(16).substring(1);
190 return s4() + s4() + '-' + s4() + '-' + s4() +
191 '-' +s4() + '-' + s4() + s4() + s4();
194 function extend(dest, source) {
195 for (var key in source) {
196 if (source.hasOwnProperty(key)) {
197 dest[key] = source[key];
204 function depot(name, options) {
209 getItem: function (key) { return data[key]; },
210 setItem: function (key, value) {
215 removeItem: function (key) {
219 key: function (index) {
221 for (var key in data) {
233 storageAdaptor: localStorage
236 if (!options.storageAdaptor) throw new Error("No storage adaptor was found");
238 store = options.storageAdaptor.getItem(name);
239 ids = (store && store.split(",")) || [];
241 return Object.create(api, {
242 name: { value: name },
243 store: { value: store },
244 ids: { value: ids, writable: true },
245 idAttribute: { value: options.idAttribute },
246 storageAdaptor: { value: options.storageAdaptor }