JSConf 2012
0 notes

capybara-webkit is hanging on requests like ‘http://localhost/#/posts/new’

Hi, everyone!

if someone will have issue with hanging browser on steps like


visit "http://localhost/#/posts/new"

You can replace this steps with the next following code and it works for me in capybara-webkit 0.8.0


def visit_script url
  page.execute_script("window.location = '#{url}'")
end

9 notes

poltergeist

Some days ago I’ve got task to test our offline application with cucumber scenarios.

It was very difficult to do it because in our project we are using capybara-webkit and unfortunately it doesn’t support html5 a lot of features in this webkit server implementation. After digging into forks of capybara-webkit I found one fork with html5 support features via custom ‘set_attribute’ for browser:


page.driver.browser.set_attribute("LocalStorageEnabled", true)

I’ve made merge with master of capybara-webkit in my own fork and then we’ve started to use this fork. But then I found another problem connecting with routing through the application using backbone routers concept with ‘#’ in the routes.

It looks like:

http://localhost/#/posts
http://localhost/#/posts/new

When I tried to visit this links webkit_server was always hanging without throwing messages by timeout. It makes me upset and I’ve decided to replace capybara-webkit driver at all.

I am trying to use poltergeist

Continue…

1 note

backbone-queues

Hi everyone!

I have just published very small library for backbone.

May be it will helps someone.

https://github.com/oivoodoo/backbone-queues

html5 offline application

2 days ago I’ve lost my internet connection at home. But I had very important emails for me on the gmail. But I thought I have offline application for gmail developed by google.

I’ve installed this chrome app just for checking possible implementation for offline apps. because on my current work we are working on the creation with the same functionnality application. Offline gmail is using web sqlite storage for saving cached / synced data.

it looks like

Time to completely client side applications. Yeah, it’s really awesome. But for less complex applications it’s pretty simple to use localStorage for saving synced data.

Also as I see guys in google added syncing process on the background and refresh button for manually syncing by user action. 

For opening application they are using html5 application manifest for caching resources like css/js/images. In Rails we are using rack-offline for generating same manifest file choosing files for caching.

10 notes

mutex js gist

var Mutex = function() {
  this.queues = [];
  this.locked = false;
};
Mutex.prototype = {
  push: function(callback) {
    var self = this;
    this.queues.push(callback);
    if (!this.locked) {
      this.locked = true;
      var f = this.queues.pop();
      try {
        f(function() {
          self.locked = false;
        });
      } catch(ex) {
        self.locked = false;
      }
    }
  }
};
view raw mutex.js This Gist brought to you by GitHub.
12 notes

backbone js snippets

Hi, everyone.

Not far a long time ago I’ve started to work on one project where we was using backbone for creating offline website version. It means we have a goal to create possibility to delay our requests to the server and works without postbacks.

We took example with backbone localstorage from backbone docs website(http://documentcloud.github.com/backbone/docs/backbone-localstorage.html). it’s very nice sources. But I’ve found that if you will decide to clear properly local storage you need to create extension.

The first extension for more pleasure removing keys from localstorage:


Store.destroy = function() {
  var models = [].slice.call(arguments, 0);
  for(var i = 0; i < models.length; i++)
    localStorage.removeItem(models[i]);
};

The second extension for changing removing collection from localstorage using sync method. As you can at first I am iterating through collection and then executing save method for localstorage.


_.extend(Store.prototype, {
  // ...
  destroy_all: function(collection) {
    var self = this;
    collection.each(function(model) {
      delete self.data[model.id];
    });
    this.save();
    return collection;
  }
});

Backbone.sync = function(method, model, options) {
  // ...
    case "delete_all": resp = store.destroy_all(model);
  }
  // ...
};

Backbone.Collection.prototype.destroy_all = function(options) {
  options = options || {};
  var collection = this;
  var success = options.success;
  options.success = function(resp) {
    collection.trigger('destroy_all', collection, options);
    if (success) success(collection, resp);
  };
  options.error = (function(onError, c, options) {
    return function(resp) {
      if (onError) {
        onError(model, resp, options);
      } else {
        model.trigger('error', c, resp, options);
      }
    };
  })(options.error, collection, options);
  return (this.sync || Backbone.sync).call(this, 'delete_all', this, options);
};

Also I want to provide very small snippet how to override fetch method for collecitons. Sometimes it’s very helpfull for filtering values by another collection. Let’s check example:


var Post = Backbone.Model.extend({
  initialize: function() {
    this.localStorage = new Store('posts');
  }
});

var Comment = Backbone.Model.extend({
  initialize: function() {
    this.localStorage = new Store('comments');
  }
});

var Comments = Backbone.Collection.extend({
  model: Comment,
  
  initialize: function(posts) {
    this.localStorage = new Store('comments');
    this.posts = posts;
    
    this._parent_fetch = Backbone.Collection.prototype.fetch;
  },
  
  fetch: function() {
    options = options || {};
    var self = this;

    this._parent_fetch.call(this, {
      success: function() {
        self.reset(self.find_by_posts(self.posts));
        options.success.call(self, self);
      },
      error: options.error
    });
  },
  
  find_by_posts: function(posts) {
    var ids = posts.map(function(post) { return post.id; });

    return this.filter(function(comment) {
      return _.include(ids, comment.get('post_id'));
    });
  }
});


// Example:
var posts = new Posts();
posts.fetch({
  success: function() {
    var comments = new Comments(posts.models);
    comments.fetch({
      success: function() {
        comments.each(function(comment){
          // show comments related to posts
          console.log(comment.id);
          console.log(comment.get('post_id'));
        });
      }
    });
  }
});

That’s it

20 notes