0.0
No commit activity in last 3 years
No release in over 3 years
DOM-based Routing for Rails controller based javascript.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

 Project Readme

Jcontroller Gem Version Build Status Code Climate

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.before
  • users.before
  • application.index
  • users.index
  • application.after
  • users.after

You can also set your own inhertance chain:

Jcontroller.create('users', { 
    parent_path: 'users_base',
    ...
});

API

  • Parameters are accessed from this.params or as the first parameter
  • The request state (controller_path, action_name, jcontroller, etc.) are also given in this.state or the second parameter
  • And other methods to work with jcontrollers
Jcontroller.create('users', {
    html: {
        index: function(params, state) {
            //this.params === params
            console.log(this.params);
            //this.state === state
            console.log(this.state);
            
            var jcontroller = JController.find('application');
            self.parent(); // === jcontroller
            
            //excute application_jcontroller for this state and params again
            jcontroller.execute_jaction(this.params, this.state);
            //execute application_jcontroller html.index function
            jcontroller.html.index();
        }
    }
});

With ruby, you could also access the state in jaction to make action specific CSS:

<body data-controller="<%= jaction.controller_path %>" data-action="<%= jaction.action_name %>">
...
</body>

Organization

I like having a jcontrollers directory and calling my files as jcontroller files (ex. users_jcontroller.js).

Parameters

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.