The post How to shuffle a JavaScript array appeared first on Đào Thanh Tú (Front-end Developer).
]]>The array isn’t a primitive so Arrays are passed by reference. It means that array passed as a parameter will be changed when we will modify it inside the function:
// Initial array will be changed after shuffle
function mutableShuffle(arr) {
var j;
var temp
for (var i = 0, max = arr.length; i < max; i++) {
j = Math.floor(Math.random() * max);
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
}
The function above doesn’t modify a given array. It creates, fills and returns a new array:
// Initial array will NOT be changed after shuffle
function immutableShuffle(arr) {
var result = [];
var j;
var temp;
for (var i = 0, max = arr.length; i < max; i++) {
j = Math.floor(Math.random() * max);
temp = arr[i];
result[i] = arr[j];
result[j] = temp;
}
return result;
}
var mutableArr = [1, 2, 3]; console.log(mutableShuffle(mutableArr)); console.log(mutableArr); // will be changed var immutableArr = [1, 2, 3]; console.log(immutableShuffle(immutableArr)); console.log(immutableArr); // will NOT be changed
You can try and modify it on codepen.
The post How to shuffle a JavaScript array appeared first on Đào Thanh Tú (Front-end Developer).
]]>The post Codepen.io – Animated folding (notifications concept) appeared first on Đào Thanh Tú (Front-end Developer).
]]>The post Codepen.io – Animated folding (notifications concept) appeared first on Đào Thanh Tú (Front-end Developer).
]]>The post Codepen.io – Matrix animated filling using different approaches appeared first on Đào Thanh Tú (Front-end Developer).
]]>The post Codepen.io – Matrix animated filling using different approaches appeared first on Đào Thanh Tú (Front-end Developer).
]]>The post Codepen.io – Alarm clock concept appeared first on Đào Thanh Tú (Front-end Developer).
]]>The post Codepen.io – Alarm clock concept appeared first on Đào Thanh Tú (Front-end Developer).
]]>The post Codepen.io – Chat concept appeared first on Đào Thanh Tú (Front-end Developer).
]]>
The post Codepen.io – Chat concept appeared first on Đào Thanh Tú (Front-end Developer).
]]>The post How to cache Backbone.js collections and models in LocalStorage appeared first on Đào Thanh Tú (Front-end Developer).
]]>At first, write a simple wrapper for caching of JS-objects in the LocalStorage with the ability to specify the duration of the cache:
var StoreWithExpiration = function() {
return {
set: function(key, value, expireTime) {
var item = {
value: value,
expireTime: expireTime,
cachedAt: new Date().getTime()
};
try {
localStorage.setItem(key, JSON.stringify(item));
} catch(e) {}
},
get: function(key) {
try {
var info = JSON.parse(localStorage.getItem(key));
if (!info || new Date().getTime() - info.cachedAt > info.expireTime)
return null;
return info.value;
} catch(e) {
localStorage.removeItem(key);
}
}
};
};
Then extend Backbone.Collection by the method cachedFetch. A lifetime of the cache can be set by parameter expireTime (default lifetime equals 1 hour). The logic is simple:
var expirationStore = new StoreWithExpiration();
Backbone.Collection = Backbone.Collection.extend({
cachedFetch: function(options) {
options = options || {};
var expireTime = options.expireTime || 60 * 60 * 1000;
var cacheKey = 'bbCollection_' + this.url;
if (!window.localStorage)
return this.fetch(options);
var cachedData = expirationStore.get(cacheKey);
var cachedModels = cachedData ? cachedData.value : [];
var success = options.success;
if (!cachedData) {
options.success = _.bind(function (resp) {
if (success)
success.call(options.context, this, resp, options);
expirationStore.set(cacheKey, this.models, expireTime);
}, this);
return this.fetch(options);
} else {
options = _.extend({parse: true}, options);
var method = options.reset ? 'reset' : 'set';
this[method](cachedModels, options);
if (success)
success.call(options.context, this, cachedModels, options);
this.trigger('sync', this, cachedModels, options);
return this.sync('cachedRead', this, options);
}
}
});
And for the models:
Backbone.Model = Backbone.Model.extend({
cachedFetch: function(options) {
options = options || {};
var expireTime = options.expireTime || 60 * 60 * 1000;
var cacheKey = 'bbModel_' + this.url + '_' + this.id;
if (!window.localStorage)
return this.fetch(options);
var cachedData = expirationStore.get(cacheKey);
var cachedModel = cachedData ? cachedData.value : {};
var success = options.success;
if (!cachedData) {
options.success = _.bind(function (resp) {
if (success)
success.call(options.context, this, resp, options);
expirationStore.set(cacheKey, this.models, expireTime);
}, this);
return this.fetch(options);
} else {
options = _.extend({parse: true}, options);
var serverAttrs = options.parse ? model.parse(cachedModel, options) : cachedModel;
if (!model.set(serverAttrs, options))
return false;
if (success)
success.call(options.context, this, cachedModel, options);
this.trigger('sync', this, cachedModel, options);
return this.sync('cachedRead', this, options);
}
}
});
And finally, patch Backbone.Sync to support our caching:
var _sync = Backbone.sync;
Backbone.sync = function(method, model, options) {
if (method === 'cachedRead') {
var _getCacheKey = function() {
return model.collection ? 'bbModel_' + model.url + '_' + model.id : 'bbCollection_' + model.url;
};
var _getCachedValue = function() {
var cachedData = expirationStore.get(_getCacheKey());
var empty = model.collection ? {} : [];
return cachedData ? cachedData.value : empty;
};
if (options.success)
options.success(_getCachedValue());
} else {
return _sync.apply(this, arguments);
}
}
The full source code for this plugin you can find on github.
The post How to cache Backbone.js collections and models in LocalStorage appeared first on Đào Thanh Tú (Front-end Developer).
]]>