Đào Thanh Tú (Front-end Developer) https://pavelkomiagin.me Personal site Mon, 25 Nov 2019 06:53:31 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.15 How to shuffle a JavaScript array https://pavelkomiagin.me/how-to-shuffle-a-javascript-array/ https://pavelkomiagin.me/how-to-shuffle-a-javascript-array/#respond Mon, 19 Sep 2016 06:39:03 +0000 https://pavelkomiagin.me/?p=100 Every programmer can face the challenge of array shuffling. Of course, sometimes it is possible to use a library (e.g. underscore). But it is useful also to have the snippets for this task. Shuffle that modifies a given array: The array isn’t a primitive so Arrays are passed by reference. It means that array passed as […]

The post How to shuffle a JavaScript array appeared first on Đào Thanh Tú (Front-end Developer).

]]>
Every programmer can face the challenge of array shuffling. Of course, sometimes it is possible to use a library (e.g. underscore). But it is useful also to have the snippets for this task.

Shuffle that modifies a given array:

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;
}

Shuffle that don’t modify a given array:

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;
}

How to use:

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).

]]>
https://pavelkomiagin.me/how-to-shuffle-a-javascript-array/feed/ 0
Codepen.io – Animated folding (notifications concept) https://pavelkomiagin.me/codepen-io-animated-folding-notifications-concept/ https://pavelkomiagin.me/codepen-io-animated-folding-notifications-concept/#respond Sun, 10 Jan 2016 05:40:47 +0000 https://pavelkomiagin.me/?p=310 See the Pen Animated folding (notifications concept) by Đào Thanh Tú (@pavel_komiagin) on CodePen.

The post Codepen.io – Animated folding (notifications concept) appeared first on Đào Thanh Tú (Front-end Developer).

]]>
See the Pen Animated folding (notifications concept) by Đào Thanh Tú (@pavel_komiagin) on CodePen.

The post Codepen.io – Animated folding (notifications concept) appeared first on Đào Thanh Tú (Front-end Developer).

]]>
https://pavelkomiagin.me/codepen-io-animated-folding-notifications-concept/feed/ 0
Codepen.io – Matrix animated filling using different approaches https://pavelkomiagin.me/codepen-io-matrix-animated-filling-using-different-approaches/ https://pavelkomiagin.me/codepen-io-matrix-animated-filling-using-different-approaches/#respond Mon, 14 Dec 2015 09:37:13 +0000 https://pavelkomiagin.me/?p=307 See the Pen Matrix animated filling using different approaches by Đào Thanh Tú (@pavel_komiagin) on CodePen.

The post Codepen.io – Matrix animated filling using different approaches appeared first on Đào Thanh Tú (Front-end Developer).

]]>
See the Pen Matrix animated filling using different approaches by Đào Thanh Tú (@pavel_komiagin) on CodePen.

The post Codepen.io – Matrix animated filling using different approaches appeared first on Đào Thanh Tú (Front-end Developer).

]]>
https://pavelkomiagin.me/codepen-io-matrix-animated-filling-using-different-approaches/feed/ 0
Codepen.io – Alarm clock concept https://pavelkomiagin.me/codepen-io-alarm-clock-concept/ https://pavelkomiagin.me/codepen-io-alarm-clock-concept/#respond Fri, 30 Oct 2015 09:32:55 +0000 https://pavelkomiagin.me/?p=302 Inspired by https://dribbble.com/shots/2158902-Sport-App See the Pen Alarm Clock Concept by Đào Thanh Tú (@pavel_komiagin) on CodePen.

The post Codepen.io – Alarm clock concept appeared first on Đào Thanh Tú (Front-end Developer).

]]>
Inspired by https://dribbble.com/shots/2158902-Sport-App

See the Pen Alarm Clock Concept by Đào Thanh Tú (@pavel_komiagin) on CodePen.

The post Codepen.io – Alarm clock concept appeared first on Đào Thanh Tú (Front-end Developer).

]]>
https://pavelkomiagin.me/codepen-io-alarm-clock-concept/feed/ 0
Codepen.io – Chat concept https://pavelkomiagin.me/codepen-io-chat-concept/ https://pavelkomiagin.me/codepen-io-chat-concept/#respond Thu, 15 Oct 2015 07:30:40 +0000 https://pavelkomiagin.me/?p=294 Inspired by https://dribbble.com/shots/2293029-Hello-Dribbble See the Pen Chat Concept by Đào Thanh Tú (@pavel_komiagin) on CodePen.

The post Codepen.io – Chat concept appeared first on Đào Thanh Tú (Front-end Developer).

]]>
Inspired by https://dribbble.com/shots/2293029-Hello-Dribbble

See the Pen Chat Concept by Đào Thanh Tú (@pavel_komiagin) on CodePen.

The post Codepen.io – Chat concept appeared first on Đào Thanh Tú (Front-end Developer).

]]>
https://pavelkomiagin.me/codepen-io-chat-concept/feed/ 0
How to cache Backbone.js collections and models in LocalStorage https://pavelkomiagin.me/how-to-cache-backbone-js-collections-and-models-in-localstorage/ https://pavelkomiagin.me/how-to-cache-backbone-js-collections-and-models-in-localstorage/#respond Wed, 07 Oct 2015 09:08:29 +0000 https://pavelkomiagin.me/?p=291 Working on project Foxford as a front-end developer I wanted to reduce the number of requests to the server. For example, we have filters containing a list of disciplines, a list of learning objectives, and a list of classes. They are used on several pages and are changed rarely so I wanted to cache the received data. […]

The post How to cache Backbone.js collections and models in LocalStorage appeared first on Đào Thanh Tú (Front-end Developer).

]]>
Working on project Foxford as a front-end developer I wanted to reduce the number of requests to the server. For example, we have filters containing a list of disciplines, a list of learning objectives, and a list of classes. They are used on several pages and are changed rarely so I wanted to cache the received data. Since we use Backbone, I decided to extend the models and the collections by adding the method cachedFetch like the native fetch.

Step 1

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);
      }
    }
  };
};

Step 2

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:

  1. If LocalStorage is unavailable then call normal fetch()
  2. If there is a valid cache then we use it, otherwise, we receive and cache new data.
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);
    }
  }
});

Step 3

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).

]]>
https://pavelkomiagin.me/how-to-cache-backbone-js-collections-and-models-in-localstorage/feed/ 0