2015-04-24 23:21:13 +08:00
**Important**
- `master` branch contains the bleeding edge development code.
- check `branches` or `tags` for the latest stable release or specific versions.
2013-10-12 20:48:18 +08:00
# Paloma
2015-04-24 23:08:20 +08:00
Page-specific javascript for Rails done right.
2013-10-13 10:08:49 +08:00
2013-10-12 20:48:18 +08:00
## Advantages
* Choose what specific javascript code to run per page.
2013-01-26 11:08:50 +08:00
* Easily make ruby variables available on your javascript files.
2015-04-24 23:10:03 +08:00
* Can be written using vanilla javascript, coffeescript, and anything that compiles to js.
* Easy to understand (*because it is patterned after Rails' controller module*).
2013-10-12 20:55:14 +08:00
2013-10-12 20:48:18 +08:00
## Quick Example
2012-12-19 15:56:52 +08:00
2013-10-12 20:55:14 +08:00
Paloma controller.
2012-12-19 15:56:52 +08:00
```javascript
2013-10-12 21:05:06 +08:00
var UsersController = Paloma.controller('Users');
2013-10-12 20:55:14 +08:00
2013-10-13 10:39:27 +08:00
// Executes when Rails User#new is executed.
2013-10-12 21:05:06 +08:00
UsersController.prototype.new = function(){
2013-10-12 20:55:14 +08:00
alert('Hello Sexy User!' );
};
2012-12-19 15:56:52 +08:00
```
The Rails controller `app/controllers/users_controller.rb` :
```ruby
def UsersController < ApplicationController
def new
2016-03-02 11:52:54 +08:00
# nothing special
2013-10-12 21:24:40 +08:00
@user = User.new
2012-12-19 15:56:52 +08:00
end
end
```
That's it! Simply Sexy!
2013-10-13 10:39:27 +08:00
## Minimum Requirements
2012-12-19 15:56:52 +08:00
* Rails 3.1 or higher
2012-12-18 17:47:24 +08:00
2013-10-12 20:55:14 +08:00
## Install
2016-03-02 11:52:54 +08:00
1. Install gem.
- Without bundler: `sudo gem install paloma` .
- With bundler, add this to your Gemfile: `gem 'paloma'`
2015-04-25 17:30:33 +08:00
1. Require `paloma` in your `application.js` : `//= require paloma`
2016-03-02 11:52:54 +08:00
1. In your layouts insert Paloma's hook.
2015-04-25 17:30:33 +08:00
`application.html.erb`
```html
< html >
< head >
< / head >
< body >
< %= yield %>
< %= insert_paloma_hook %>
< / body >
< / html >
```
2013-10-12 21:12:10 +08:00
2016-03-02 11:52:54 +08:00
1. Start Paloma. *Most of the time this will be inside `document.ready`* .
```js
$(document).ready(function(){
Paloma.start();
});
```
2013-10-13 10:39:27 +08:00
## Controllers
2013-10-12 21:05:06 +08:00
2013-10-13 10:52:21 +08:00
Controllers are just classes that handle requests made by Rails Controllers. Each Rails Controller's action will be mapped to a specific Paloma Controller's action.
2013-10-12 21:24:40 +08:00
2013-10-13 10:39:27 +08:00
### Creating a Controller
2013-10-12 21:24:40 +08:00
2014-02-15 19:25:44 +08:00
A Controller constructor is created or accessed (if it already exists), using `Paloma.controller()` method.
2013-10-12 21:24:40 +08:00
```javascript
2013-10-13 18:25:12 +08:00
var ArticlesController = Paloma.controller('Articles');
2013-10-12 21:24:40 +08:00
```
2013-10-13 10:39:27 +08:00
It will return the constructor function of your controller.
2013-10-12 21:24:40 +08:00
2014-02-15 19:25:44 +08:00
Note: Using `Paloma.controller` method, you can access the same controller constructor across different files.
2013-10-12 21:24:40 +08:00
2013-10-13 10:39:27 +08:00
### Handling Actions
2013-10-12 21:24:40 +08:00
2014-02-15 19:34:15 +08:00
Every time a request to Paloma is made (A Rails Controller action is executed), an instance of a Paloma controller is created and the method responsible for the request will be invoked.
2013-10-13 10:39:27 +08:00
2013-10-12 21:24:40 +08:00
```javascript
2013-10-13 18:25:12 +08:00
var ArticlesController = Paloma.controller('Articles');
2013-10-12 21:24:40 +08:00
ArticlesController.prototype.new = function(){
// Handle new articles
};
ArticlesController.prototype.edit = function(){
// Handle edit articles
};
```
2013-10-12 21:05:06 +08:00
2014-02-15 19:34:15 +08:00
## Advanced Usage
2014-02-15 20:08:17 +08:00
You can manipulate what controller/action should Paloma execute by calling `js` method **before** rendering.
2014-02-15 19:34:15 +08:00
1. Changing controller
2014-02-15 20:08:17 +08:00
2014-02-15 19:40:22 +08:00
```ruby
class UsersController < ApplicationController
def new
@user = User.new
js 'Accounts' # will use Accounts controller instead of Users controller
end
end
```
2014-02-15 19:34:15 +08:00
2014-02-15 19:40:22 +08:00
2. Changing action
2014-02-15 20:08:17 +08:00
2014-02-15 19:40:22 +08:00
You can use the symbol syntax:
```ruby
2014-02-15 19:34:15 +08:00
def new
@user = User.new
2014-02-15 19:40:22 +08:00
js :register # will execute register method instead of new
2014-02-15 19:34:15 +08:00
end
2014-02-15 19:40:22 +08:00
```
Or the string syntax:
```ruby
def new
@user = User.new
js '#register '
end
```
2014-02-15 19:34:15 +08:00
2014-02-15 20:08:17 +08:00
3. Changing controller and action.
2014-02-15 19:40:22 +08:00
```ruby
def new
@user = User.new
js 'Accounts#register ' # will execute Accounts#register instead of Users#new
end
```
2014-02-15 19:34:15 +08:00
2014-02-15 20:08:17 +08:00
4. Changing controller with namespace.
2014-02-15 19:40:22 +08:00
Paloma supports namespaces using '/' as delimiter.
2014-02-15 19:34:15 +08:00
2014-02-15 19:40:22 +08:00
```ruby
def new
@user = User.new
js `Admin/Accounts` # will use Admin/Accounts controller instead of Users controller
end
```
```ruby
def new
@user = User.new
js 'Admin/Accounts#register ' # will execute Admin/Accounts#register instead of Users#new
end
```
2014-02-15 20:08:17 +08:00
## Passing Parameters
You can access the parameters on your Paloma Controller using `this.params` object.
1. Parameters only.
`users_controller.rb`
```ruby
def destroy
user = User.find params[:id]
user.destroy
js :id => user.id
end
```
Paloma controller.
```javascript
var UsersController = Paloma.controller('Users');
UsersController.prototype.destroy = function(){
alert('User ' + this.params['id'] + ' is deleted.');
};
```
2. Path with parameters.
```ruby
def destroy
user = User.find params[:id]
user.destroy
js 'Accounts#delete ', :id => user.id
end
```
2013-10-13 10:39:27 +08:00
## Preventing Paloma Execution
2013-03-03 00:15:44 +08:00
2013-10-13 10:39:27 +08:00
If you want to Paloma not to execute in a specific Rails Controller action you need to pass `false` as the Paloma parameter.
2013-03-03 00:15:44 +08:00
2013-10-12 21:36:38 +08:00
```ruby
def edit
@user = User.find params[:id]
js false
end
2013-03-03 00:36:36 +08:00
```
2013-03-03 00:33:26 +08:00
2012-12-19 18:39:30 +08:00
2014-02-15 20:08:17 +08:00
## Controller-wide setup
You can call `js` outside Rails controller actions for global or controller-wide settings.
**Example:**
```ruby
class UsersController < ApplicationController
js 'Accounts' # use Accounts controller instead of Users for all actions.
def new
@user = User.new
end
def show
@user = User.find params[:id]
end
end
```
Like `before_filter` you can also pass `only` and `except` options.
```ruby
class UsersController < ApplicationController
js 'Admin/Accounts', :except => :destroy # Use Admin/Accounts except for destroy method
end
```
**IMPORTANT NOTE:**
If you are going to pass parameters for Controller-wide settings, put them inside a `:params` hash.
```ruby
class UsersController < ApplicationController
js 'Accounts', :params => {:x => 1, :y => 2, :z => 3}, :only => :show
end
```
### Overriding Controller-wide setup
If you want to override the controller-wide setup, just call `js` again inside a controller action. From there you can override the controller/action or pass additional parameters.
```ruby
class UsersController < ApplicationController
js 'Accounts', :params => {:x => 1}
def new
@user = User.new
js :register, :y => 2 # will execute Accounts#register with params {:x => 1, :y => 2}
end
end
```
2015-04-25 17:52:53 +08:00
## Hook
`insert_paloma_hook` is a helper method that you can use in your views to insert Paloma's HTML hook.
2015-04-25 17:56:35 +08:00
Inside this HTML hook is where the magic happens. This is the reason why Paloma can magically know what Javascript controller/action to execute. To further understand how Paloma works, you can inspect the HTML hook, by checking the generated HTML (*inspect element*) and locate the `div` element that has the class `js-paloma-hook` .
2015-04-25 17:52:53 +08:00
Ideally, you just need to call `insert_paloma_hook` in your layouts, since the layout will always be included in every rendered view. But if you are rendering a view without a layout, make sure to call `insert_paloma_hook` in that view.
2014-06-07 19:47:00 +08:00
2015-05-01 13:06:56 +08:00
## AJAX
1. Make sure that the AJAX response contains the html hook. (use `insert_paloma_hook` )
2016-03-02 11:52:54 +08:00
2. Start Paloma on complete/success.
2015-05-01 13:06:56 +08:00
```js
$.get('http://example.com', function(response){
$('#result ').html(response);
2016-03-02 11:52:54 +08:00
Paloma.start();
2015-05-01 13:06:56 +08:00
});
```
2014-06-07 19:47:00 +08:00
## Turbolinks Support
As of version `4.1.0` , Paloma is compatible with Turbolinks without additional setup.
### Execute Paloma when user hits `Back` or `Forward` button.
Paloma executes page-specific javascript by adding a `<script>` tag to the response body. Turbolinks, by default, executes any inline javascript in the response body when you visit a page, so the `<script>` tag appended by Paloma will automatically be executed. However, when Turbolinks restores a page from cache (*this happens when a user hits `Back` or `Forward` button in his browser*) any **inline javascript will not be executed** anymore. This is the intentional behavior of Turbolinks, and it is not a bug. If you want to execute Paloma again when Turbolinks restores a page, do something like this:
```js
$(document).on('page:restore', function(){
2016-03-02 11:52:54 +08:00
Paloma.start();
2014-06-07 19:47:00 +08:00
});
```
2014-09-25 23:35:00 +08:00
### Turbolinks without `jquery.turbolinks` gem
You need to manually run Paloma every page load if you are not using `jquery.turbolinks` gem.
In your `application.js`
```js
$(document).on('page:load', function(){
2016-03-02 11:52:54 +08:00
Paloma.start();
2014-09-25 23:35:00 +08:00
});
```
2013-10-12 21:36:38 +08:00
## Gotchas
2012-12-19 18:39:30 +08:00
2015-04-25 17:30:33 +08:00
* Make sure that the rendered view has the paloma hook (*use `insert_paloma_hook` *) for Paloma to execute.
2013-10-12 21:36:38 +08:00
2014-05-29 22:52:19 +08:00
* It will cause conflicts if you have a controller and a module that has the same name.
Example:
```js
var AdminController = Paloma.controller('Admin');
// This will override the AdminController and replace it
// with a module named 'Admin'.
var UsersController = Paloma.controller('Admin/Users');
```
2013-10-12 21:36:38 +08:00
2013-10-12 22:09:02 +08:00
## Where to put code?
2013-10-13 10:39:27 +08:00
Again, Paloma is now flexible and doesn't force developers to follow specific directory structure.
2014-02-15 20:08:17 +08:00
You have the freedom to create controllers anywhere in your application.
2013-10-12 22:09:02 +08:00
2014-02-15 19:25:44 +08:00
Personally, I prefer having a javascript file for each controller.
2015-04-17 11:36:24 +08:00
## Contribute
1. Fork.
2. Do awesome things.
3. Submit Pull-Request to `master` branch.
4. Add short summary of changes on your PR.