MarkUs Blog

MarkUs Developers Blog About Their Project

Moving from Prototype to jQuery

without comments

For a little over two weeks, I had the opportunity to learn JavaScript by working on an issue on the MarkUs’s GitHub.
This issue is about updating the MarkUs application from Prototype to jQuery. Indeed, in order for MarkUs to migrate to Rails 3.1 (it is currently implemented with Rails 3.0), it has to support the new default javascript library, jQuery, hence motivating this work.

As I had never programmed in Javascript before, the first step was to document myself on javascript, but also to learn how Prototype and jQuery worked.
Fortunately, these two libraries have a fairly extensive documentation (Prototype API & jQuery API).

Merge old Pull Request and Master

A student, @m-bodmer had already tackled this issue a while back when working on MarkUs. Thankfully, he had created a pull request, and I could easily retrieve his branch to update it with the recent changes in the codebase, and understand his patch.

He worked on the jQuery integration, while still keeping Prototype in parallel.
For this, we used the call jQuery.noConflict(); which allows us to switch between one and the other (see the
doc).

As Prototype is the default, we call it with $ (ie, the default). jQuery is simply managed with calling jQuery (e.g. jQuery('#elem') instead of $('elem')).

Problems

While working on this issue, I encountered a series of problems:

  1. The first one is MarkUs’ views. We should avoid creating so many .rjs files (more informations here).
  2. The second problem is the numbers of render of .js.erb (e.g. _boot.js.erb which is everywhere). We should, if possible, remove them all. Yet, to do so, we need to solve the following two problems. First, there are, within these files, FilterTables owned by Prototype (things that we must remove in future to benefit of jQuery DataTables). Second, these files have embedded Ruby.
    There are ways to solve these problems (for example, sending varables when calling JS or sending data with new html attributes data-something). I have solved the latter, but the former remains to be done.
  3. The third problem appears in some functional tests. The request format is not good, so I was forced to specify it (:format => :js).

Work on _boot.js.erb

First, I removed the <script> tags from JS files and placed them in the body of the .html.erb without changing the call to this file:

Then, I removed the //<![CDATA[ tags  which -for me- should not be here (cf. article on stackoverflow).
The change of Ajax request is documented here.

I removed the populate.rjs called by the request

in benefit of .done() method of Ajax.

This required an explicit call to JSON in Ajax (dataType: 'json') and an adequate response in the action:

I haven’t change the populate() JS function now called by the .done() method. It requires to change the data object -transformed by the jQuery (I haven’t tried to change its behavior)- in JSON using JSON.stringify(data).
Another problem, the call of the partial. Rails now expects a partial in JS. To change this behavior, I had to explicitly add .html.erb extension.

Work on AnnotationCategories/

This work was to change this piece of code:

First, I removed all the JS part to put it in a .js file.
Then, so that my request knows the required path, I created a variable path I send to the created function function using #{}. Which gives:

JS side, I created a file named index.js inside javascripts/AnnotationCategories/.
I think eventually, it would be wise to follow a template that would be to create for each model a .js corresponding and not to make -as I did- a folder with a view’s name inside.
So the function add_annotation_category() looks like this:

First, I cut the call to element by creating an intermediate variable category_prompt. To find out if an element exists or not -knowing that jQuery, unlike Prototype, always returns an object not null-, I use the .size() method I compare with 0 implicitly.

Regarding the Ajax request, I use variable passed as parameter for the URL and I specify the type GET.

Modals

Before I tackled this work, each time we used models, we had to recode part of the javascript.

Then, I decided to take care of modals, so that we whenever have to recode to do the same thing. Example for the file annotation_categories/_boot.js.erb:

As this is not “DRY” (do not repeat yourself, one of Rails’s moto), I decided to created a javascript class, that we can reuse. I first removed all modals not working properly. Then, I created a ModalMarkus class in the application.js file (we should place it in another file):

This “class” thus creates modals with automatic size and two methods open() & close() (I took inspiration from the implementation of bootstrap-modal.js file).
I also added a dialogClass to add a CSS rule to remove the header and the footer of modals I found unnecessary.

Thanks to this work, we can initialize modals by simply adding this piece of code in a javascript file:

And modals can be called with:

From RJS to JS.ERB

Finally, one of last things I did is the migration of files from .rjs to .js.erb -in the case that the .rjs is not easily deletable-. To do this, the jQuery & Prototype APIs are essential, but I also found help in various documents easily findable after a Google search (e.g. SlideShare).
Some examples:

From Prototype

To jQuery

Conclusion

There is still a lot of work to do, but it is, I think, interesting work to do.
Thanks to this issue, I learnt JS, but I also saw more in depth how MarkUs worked. I also gives the opportunity to appear unnecessary, poor made and replaceable code.

G.

Written by Ghislain Guiot

August 12th, 2013 at 12:39 pm

Leave a Reply