Select and de-select all checkboxes using jQuery

On almost every application I’ve worked on, there was a similar user story:
When i visit the page showing the list of unpaid/unprocessed things, I want to be able to select some of them to process automatically.

The best way to do this is with checkboxes, and a simple form that will submit to a given path, collecting the items you need to process.

Basically the next user story after that one is: I want to be able to select all checkboxes, so I don’t have to click each one if there are plenty of them.
This is where the story would get complicated, but it is really easy to do.
Let’s say that you have a check_box with an id of #select-all-checkboxes and that your form contains checkboxes with a class of .selectable-checkbox like this:

<input id="select-all-checkboxes" type='checkbox' value=1/>

<form action="/action" method="post">
  <input class='.selectable-checkbox' name='checkbox_name&#91;&#93;' type='checkbox' value='1'/>
  <input class='.selectable-checkbox' name='checkbox_name&#91;&#93;' type='checkbox' value='2'/>
</form>

The solution to toggle them all is very easy, with JavaScript:

$('#select-all-checkboxes').change(function() {
  var is_checked = this.checked;
  $('.selectable-checkbox').each(function() {
    this.checked = is_checked;
  });
});

or with CoffeeScript:

$('input#select-all-checkboxes').change ->
  is_checked = @.checked
  $('.selectable-checkbox').each ->
    @.checked = is_checked
    return

And that is about it, now you have select/de-select all checkboxes working on your site. Be sure to wrap the above code in a $(document).ready(function() {}); or some other initialiser that is fit for your application.

Dynamically moving div with jQuery

Surely there has been a instance when you are creating an application that
has a sidebar and a main content div. In the case of content being too long,
the useful sidebar info can get left behind when you scroll down to see the other content.

In that case, you need to have some solution to scroll the sidebar content
down as the user scrolls down. You can go with something like:

.movable-div {
  position: fixed:
}

And that will work, if the sidebar content is fixed to the top of the page. If
not, you need something to know when to stick the content to the top of the
page and when to unstick it, as the users srolls up.

Think of Yelp search page, and their map that smartly sticks to the top of the
page when you scroll. So you need to use some JavaScript to achieve that. I
chose jQuery for that job and wrote a simple helper to achieve that.


// we need to fix the distance from our div to the browser top
var baseTop = $(“div#sticky”).offset().top;
$(window).scroll(function () {
var top = $(window).scrollTop();
if (top >= baseTop) {
$(“div#sticky”).css({
“position”: “fixed”,
“top”: “2px”
});
} else if (top < baseTop) { $("div#sticky").css({ "position": "", "top": "" }); } }); [/javascript] For this to work, your #sticky div must be nested inside another one in the sidebar, let’s call it #sidebar so it wont pop out to the left while you scroll down. I’ve made a jsfiddle so you can take
a look at it in action. I’m really no front-end guy so please don’t take my
div coloring skills against me.

Resources:
Sticky div jsfiddle

Integrating turbolinks in your Rails application

We are all excited in a new addition to rails plugins family that is turbolinks.

If you have tried to include it in your application, you may have noticed that turbolinks doesn’t trigger your $.ready, because there is no full page reload. As a consequence your javascripts that are bound to $.ready won’t trigger. I will only hack the finished event that is “page:change” which occurs when the page is refreshed. You have other events and their descriptions on the turbolinks github page. Here is a fast hack that i came with. Some of the code is taken from turbolinks library.

First have your $.ready trigger the “page:change” event. This is done, so we can bind everything that is now bound to document.ready to “page:change”

$.ready ->
  triggerEvent "page:change"

triggerEvent = (name) ->
  event = document.createEvent 'Events'
  event.initEvent name, true, true
  document.dispatchEvent event

Now when we have $.ready calling “page:change” we can use it in our application like this

document.addEventListener "page:change", ->
  alert "I am called from $.ready and page:change"

Will Paginate in Rails using remote request

Have you ever wondered why is there no remote option for will_paginate gem? It’s too complex and data dependent to handle all possible situations. I have made a workaround that can help you implement simple ajax pagination for your rails application. I will be replacing the whole yield part here, but you can customize it whatever way you like.

Step 1. Extract your required view into a partial so you have
index.html.erb

<!-- app/views/posts/index.html.erb -->
< %= render "index" %>

_index.html.erb

<!-- app/views/posts/_index.html.erb -->
<h1>Listing posts</h1>
<table id="posts">
  <tr>
    <th>Title</th>
    <th>Body</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>
 < %= render partial: 'post', collection: @posts %>
</table>
< %= will_paginate @posts, remote: true %>
<br />
< %= link_to 'New Post', new_post_path, remote: true %>

Note the remote: true part of the will_paginate call, we will bind the javascript to it in an instance.

2. Add a div surrounding your yield tag in your layout

<!-- app/views/layouts/application.html.erb -->
<div id="content>
  < %= yield %>
</div>

3. Create index.js.erb which will replace the contents of the div with paged table data.

// app/views/posts/index.js.erb
$("div#content").html('< %= escape_javascript(render "index") %>');

4. Bind the will_paginate link click to the rails remote call using coffeescript in

# app/assets/javascripts/posts.js.coffee
$('.pagination[remote=true] a').live 'click', ->
  window.history.pushState(null, 'hi', $(this).attr("href"))
  $.rails.handleRemote($(this))
  return false

We also change the address in the navigation bar with PushState, because it can happen someone will press F5 or something and reload with a different params[:page].

Update: As my coworker Oliver mentioned, i forgot to include responding to js in our controller for the index action

def index
  @posts = Post.paginate(per_page: 8, page: params[:page]
  respond_to do |format|
    format.html
    format.js
  end
end

Preventing users from exiting a form on your website with JQuery

I have encountered a problem with users on a webapp that i co-created. The users would click back after entering data in a form, or close the current tab or something. They were so used to client-server workflow, with open connections to the database that prevented that kind of actions. So i got handed the assignment to prevent the users from doing almost anything but submitting on a data entry form without a notice.

It seemed as a hell of a solution, but i managed to make a simple plugin that works on all major browsers, except Opera. Using window.onbeforeunload, we can prevent the user from doing anything that would hurt their unsaved data. you just load the javascript file, put a tag into your forms that you want to protect and it works out of the box with JQuery.

var isSubmitted = false;
window.onbeforeunload = function() {
  var message = "You could have unsaved changes!";
  if ($('form[data-validate-exit="true"]').length > 0)
  {
    if (!isSubmitted)
    {
      return message;
    }
  }
}
document.ready = function() {
  $('form[data-validate-exit="true"]').find('button[type="submit"]').click(function() {
    window.isSubmitted = true;
  });
}

The message doesn’t show on firefox, but a convenient one will show, enough to warn the user on his actions.

The html code in your form should be like this:


<form data-validate-exit="true">

Your html here

</form>

One friendly suggestion if you follow this path, after you implement this on any of your web apps, use Opera for development, or comment the stuff out for your own sake, you will loose your mind clicking on the leave validations.