Note: You are currently viewing documentation for Moodle 3.2. Up-to-date documentation for the latest stable version of Moodle is probably available here: Frank Ralf/JavaScript2.

YUI vs. jQuery - The big challenge!

"If you really want to convince me, I would like to see a conversion of http://cvs.moodle.org/moodle/user/selector/script.js?view=markup (it is used on the assign roles and add group members pages). That is a serious application of JavaScript. However, that is also a lot of code, so it is not really fair to ask for a conversion just as a proof of concept."
--Tim Hunt 04:52, 21 July 2009 (UTC)

  • Look Frank Ralf/JavaScript1 for the background for this challenge...
  • Feel free to add comments on the talk!
  • We will tackle this big task step by step ...

AJAX based selecting of users

Screenshot

For those who don't have a current installation of the brand new Moodle 2.0 at hand here's a screenshot so you get an idea what this is all about:

Moodle 2.0 Assign role with AJAX.png

While you are entering text in the search field the database is queried in real-time in the background for matching users. This is done using AJAX without any page re-loading required.

For comparison here's the same page with JavaScript turned off:

Moodle 2.0 Assign role without JavaScript.png

The underlying code

Getting ready for jQuery

If you want to play along you first have to add jQuery to your Moodle installation. Just download the library (56 KB) and copy it into the /user/selector folder. Then you add jQuery to the list of required JavaScript in /user/selector/lib.php:

// Required JavaScript code. $PAGE->requires->yui_lib('json'); $PAGE->requires->yui_lib('connection'); $PAGE->requires->yui_lib('datasource'); // Adding jQuery before other JS files of the module $PAGE->requires->js('user/selector/jquery-1.3.2.min.js'); $PAGE->requires->js('user/selector/script.js');

A) DOM manipulation - moving, adding and deleting HTML elements

A very common task when using JavaScript for modifying HTML is moving, adding and deleting HTML elements. So that's where we will start our venture.

The task

Following the principle of Unobtrusive JavaScript the form must also be usable with JavaScript turned off.

So without JavaScript the form contains a search field and two submit buttons: one for executing the search and one for clearing the search field. Clicking any of those two buttons triggers a request to the server which will execute the function and sends a new page back to the browser.

Without JavaScript
Buttons without JavaScript.png

For the AJAX version the search is done automatically and asynchronously (remember the "A" of "AJAX") while typing in the search field. Therefore the form should not be sent and the search button will be replaced by a simple label which will be placed to the left of the search field. This is the first task we will tackle.

AJAX version
Buttons with AJAX.png

The current solution

Here's the original code. We're creating a label, inserting it before the search field and then delete the search button.

// Hide the search button and replace it with a label. var searchbutton = document.getElementById(this.name + '_searchbutton');

var label = document.createElement('label'); label.htmlFor = this.name + '_searchtext'; label.appendChild(document.createTextNode(searchbutton.value)); this.searchfield.parentNode.insertBefore(label, this.searchfield); searchbutton.parentNode.removeChild(searchbutton);

You might be wondering why there's no sign of YUI. Well, YUI hasn't entered the ring yet. It might come as a surprise, but YUI's DOM utility doesn't provide any methods for creating and moving HTML elements. YUI's Element utility provides rudimentary support, but most of the time we have to resort to JavaScript's build in methods, which are not the most intuitive. - Some consider this a feature, not a bug ;-)

The jQuery solution

jQuery on the other hand provides a whole bunch of methods for manipulating the DOM tree. So we can accomplish the same task with the following code.

Note that the order of the steps is slightly different from the above version. Here we're first moving the search button to the left of the search field and then replace it with a label.

var searchbutton = document.getElementById(this.name + '_searchbutton');

$(searchbutton)

   .insertBefore(this.searchfield)
   .replaceWith('<label>' + searchbutton.value + '</label>');

B) Modifying the clear button

[TODO]

See also