Jcontroller

Rails controller based javascript to keep your javascript outside of your views.
Based off Paul Irish's DOM-based Routing (or Garber-Irish Implementation). Works with turbolinks.
How it works
Jcontroller.create('users', {
html: {
// executes whenever users#index with html format is executed
index: function() {}
}
});
No other code is needed.
Installation
Add gem 'jcontroller' to your application's Gemfile and run the bundle command, then add this to your app/assets/javascripts/application.js
//= require jcontroller
Controllers
Namespaces
Jcontroller creation and finding are based off the controller path.
// for Admin::UsersController
Jcontroller.create('admin/users', {});
Filters
Jcontrollers can be created with before and after filters like so:
Jcontroller.create('users', {
html: {
// executes for all html format responses for UsersController, before the specific action
before: function() {}
// executes whenever users#index with html format is executed
index: function() {}
// executes for all html format responses for UsersController, after the specific action
after: function() {}
}
});
Inheritance
By default, jcontrollers inherit from the application jcontroller and will execute it if it exists, such as:
Jcontroller.create('application', {
html: {
before: function() {}
index: function() {}
after: function() {}
}
});
So with the jcontrollers above the order of execution is:
application.beforeusers.beforeapplication.indexusers.indexapplication.afterusers.after
You can also set your own inhertance chain:
Jcontroller.create('users', {
parent_path: 'users_base',
...
});
Parameters
Access
Parameters are accessed from this.params or as the first parameter:
Jcontroller.create('users', {
html: {
index: function(params, state) {
//this.params === params
console.log(this.params);
//this.state === state
console.log(this.state);
}
}
});
The request state (controller_path, action_name, jcontroller, etc.) are also given in this.state or the second parameter.
Manual
Use the js method with the params option.
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
js { :params => { :id => @user.id } }
end
end
From view template
You can also create parameters using a JSON DSL (such as jbuilder) by creating a template named <action_name>_params.js.<DSL suffix>:
# app/views/users/show_params.js.jbuilder
json.id @user.id
Controlling javascript execution
Stop
Stop all execution of all filters and methods for the action:
class UsersController < ApplicationController
def index
js false
end
end
Different jcontroller
Execute a different jcontroller:
class UsersController < ApplicationController
def index
# same as "users#index.html", parameters and options are optional
js "users/show.html", { :params => { ... } }
end
end
HTML view
Execute all filters and actions related to a action:
<!-- same as "users#index.html", parameters and options are optional -->
<%= execute_jaction "users/show.html", { :params => { ... } } %>
Manually filter in Javascript
You can use the given state to stop execution of functions:
Jcontroller.create('application', {
html: {
before: function() {
if (this.state.action_name === 'destroy') { }
}
}
});
Redirect
You can execute all filters and functions of the current action before the redirected action using:
class UsersController < ApplicationController
def index
js { :redirect => true }
redirect_to user_path(User.first)
end
end
So users/index.html will be executed before users/show.html.
Ajax
You can optionally execute jcontrollers for ajax instead of writing javascript in views by turning it in config/application.rb:
Jcontroller.ajax = true
Jcontrollers will automatically execute with parameters given by the template with a JSON DSL:
# app/views/users/show.js.jbuilder
json.id @user.id
Credits
Extracted out of Placemark. Originally called dom_routes. An alternative is paloma.