More dataTables and learning the noob.

First and most fun, I had my first hacker. Someone visited the site, spammed some comments and tried to put script code in them. I am still here so I don't think he nailed me :). I did add some validation to the comment submission and will add more later.

Anyway, to the topic.

I noted at the bottom of my post DataTables, Bootstrap, JS and you that though things were working I had one small problem. If I would navigate around the site and come back to the table I was rendering using dataTables, it would just be a normal table. The search, sort and pagination features of dataTables were not there until I hit refresh.

I could see on my web server log that when I hit the page after navigating around that none of the CSS or Javascript would load. Given dataTables has all that goodness, the problem seemed to be within Rails. Turns out the problem was I'm a moron. Rails 4 was working as designed.

Turbolinks, which is native to Rails 4, speeds up your site by using Javascript to replace the HTML body of your pages to make it seem faster. In caching such pages your existing Javascript pages can have issues as mine did. My original code, as noted in my other post on this topic, was:

$  ->
    $("#customers").dataTable
    sDom: "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>"
    sPaginationType: "bootstrap"

Again with the help of Railscasts (http://railscasts.com/episodes/390-turbolinks) I saw Ryan demonstrate the exact behavior I was seeing. His solution didn't work for me because I do not have any click interaction to make this Javascript work for me. But, the Turbolinks documentation (https://github.com/rails/turbolinks) has other events.

In Ryan's Railscast the documentation for page:restore clearly pointed to it being what I needed as it said it was the event to use to load a page from client cache. The new description isn't as good, but, the event trigger worked. My new code is:

ready = ->
    $("#customers").dataTable
    sDom: "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>"
    sPaginationType: "bootstrap"

$(document).ready(ready)
$(document).on('page:load', ready)
$(document).on('page:restore', ready)

Still learning Coffeescript and Javascript so I can't exactly walk you through that, but the last two lines are important.

$(document).on('page:load', ready)

Loads things when the page is first loaded.

$(document).on('page:restore', ready)

This restores when Turbolinks caches an item, so you should be covered loading or caching. It works for me, but it may be flaky so I'll update if so. So, I think I'm pretty hot stuff. But then I hit the back button in the browser to come back to this page, rather than a back link in the application, and I get an error that DataTables can't reinitialise.

I poke around over at dataTables.net and make my code look thusly.

ready = ->
    $("#customers").dataTable
    sDom: "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>"
    sPaginationType: "bootstrap"
    "bRetrieve": true
    "bDestroy": true

$(document).ready(ready)
$(document).on('page:load', ready)
$(document).on('page:restore', ready)

The bRetrieve and bDestroy options are dataTables options which made the back error go away. I can't say I know exactly why, only that someone else did it, so I did it and I am a super, duper monkey see guy.

Now, there's also a data-no-turbolink option you tag on at the end of a div opening tag, say:

<div class="span9" data-no-turbolink>

This didn't actually work for me. I may play with it or just go with what currently works.

Back
paperclip paperclip