Deselect all

Deselect all

by Gustav W Delius -
Number of replies: 1
Moodle pages load a javascript library 'javascript-static.js' that among other things contains a function checkall() that checks all checkboxes on the page. It does not take any arguments. I think it would be nice to make this function just a bit more powerful: I would like to be able to restrict it to a particular form and I would like to be able to use it also to uncheck all checkboxes. The current function is:

function checkall() {
  void(d=document);
  void(el=d.getElementsByTagName('INPUT'));
  for(i=0;i<el.length;i++)
    void(el[i].checked=1)
}

Perhaps someone with javascript knowledge can tell me how to best expand this to do what I want?
Average of ratings: -
In reply to Gustav W Delius

Re: Deselect all

by John Papaioannou -
Hi Gustav,

I 've just added a function filterByParent (in /lib/container.js, it's automatically included with each page) that is very powerful and will do your job. A few pointers on how to use it:

  1. Get an array of elements, say all INPUT elements like in your example.
  2. Call filterByParent(collection, parentFinder) to get back a smaller, filtered array.
  3. Iterate on the new array to do whatever you want.

The first argument of filterByParent is obvious, but the second can be a bit difficult to grasp. Basically filterByParent tries, for each element in the given array, to find a parent element (which may be the initial element itself; "parent" is used in the broader sense "parent or self") with specific characteristics. If no such parent element is found, the element is filtered out.

parentFinder, therefore, is a function that returns a parent element that has some specific characteristics, or the BODY element if none (this results in the filtering out).

You do not have to write parentFinder yourself. There is a powerful function findParentNode (element, elName, elClass, elID) which starts from element and tries to find a "parent or self" element with the specified tag name, class, and id (you can omit as many of those as you like). You can easily build on that, making a "specialized" version of it:

function myFinder(el) {
return findParentNode(el, "FORM", "", "myformid");
}

Now, if you have an array of elements and say

filtered = filterByParent(myCollection, myFinder);

what will happen is that the filtered array will contain only those elements who happen to be descendants of a FORM tag with id="myformid".

You can also get fancy and write myFinder inline:

filtered = filterByParent(
myCollection,
function(el) {return findParentNode (el, "FORM", "", "myformid");}
);

This will do the exact same thing.

As a last, practical example, here is a function that when executed will check all the "attempt" checkboxes in the quiz overview page based on the principle that they are in a FORM. If you try to add some checkboxes outside a FORM in the same page (this is useless practically, but enough for an example), you will see that they don't get checked (i.e., the filtering works).

function checkattempts() {
var inputs = document.getElementsByTagName('INPUT');
inputs = filterByParent(inputs, function(el) {return findParentNode(el, 'FORM');});
for(var i = 0; i < inputs.length; ++i) {
inputs[i].checked = 'checked';
}
}

"Deselect all" would of course be

        inputs[i].checked = '';

instead.

Jon