Interface design input please

Interface design input please

by Mike Worth -
Number of replies: 23
I'm having trouble working out how best to layout the interface to configure parents evenings in my termreview module.

It currently consists of a fairly standard moodle form, but I need to add an extra bit to select which users are teachers with whom appointments can be booked. This is the bit that I'm unsure about.
css padding
I think it would be best to keep this as similar to the assign roles interface to make it as intuitive at possible, however I see 2 problems:
  • I can't work out a way to get that into a moodleform
  • It requires a page refresh each time it is changed
I am thinking that the second one can be solved by having the add/remove buttons trigger javascript that moves the options from one select to the other, then the final lists can be sent at the end when the form is submitted. Is there a way to have this with some form of fallback for when JS is disabled?

Another thought I was to totally separate this part of the form to a popup, it would be a bit unintuitive in that all the configuration is for the same thing split accross different pages. It does however make the technical side a lot easier

Has anyone done anything like this before? Which is the best solution? Would a 'select multiple users' mform element be useful (I can't be the only person doing this)?

Thanks,
Mike
Average of ratings: -
In reply to Mike Worth

Re: Interface design input please

by Mike Worth -
I've thought about it a bit more and couldn't figure out a good way to get 2 selects side by side, so created an interface with one select. You can see the code here.

The user simply selects all the users they want to be teachers. If javascript is available, clicking on an option doesn't deselect all other options, that option gets toggled between selected/not selected. There is also a 'show only selected' box that allows the user to check over the list before saving it.

Although it does work, there are still several big problems with it:
  1. Only seems to work in FF
  2. Jumps around when users clicked on
  3. show only selected is still selected, but all are shown after page submit
I am guessing that 1 is due to the way in which a click is dealt with. In firefox, the onmousedown event saves the selection; then when the mouse is released the default behaviour is carried out, followed by triggering the onmouseup event which restores the old selection. This must happen differently in ie and konqueror (the only other browsers I've tried).

Does anyone know how to sort any of these problems?

Thanks,
Mike
In reply to Mike Worth

Re: Interface design input please

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I can think of two possible solutions:

1. move the interface for selecting teachers onto a separate page, and then do it exactly like the assign roles UI.

2. Use a set of checkboxes, instead of a list box with multi-select. That tends to be an easier form of UI for users to manipulate.
In reply to Tim Hunt

Re: Interface design input please

by Mike Worth -
I don't particularly like the idea of yet another page (it gives the impression of being more complicated without actually being any more complicated).

The checkboxes idea does seem like a better solution (making form elements behave normally rather than weirdly is much more intuitive), can I make the checkboxes a scrollable list, the page will get very long otherwise

Thanks,
Mike
In reply to Mike Worth

Re: Interface design input please

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
I would have though overflow:scroll in CSS should do it.
In reply to Tim Hunt

Re: Interface design input please

by Mike Worth -
I've re-done it with checkboxes here, and used the overflow property here.

The only thing I could find to style was the fieldset, this isn't ideal as it scrolls the title as well; is there a way in css to define styles for divs that are children of elements with the id 'pe_teachers' (or similar)?

Also ie doesn't seem to like my 'show only selected', it claims 'teacherslist.childNodes is null or not an object'; any ideas?

Thanks,
Mike
In reply to Mike Worth

Re: Interface design input please

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Yes, you can use CSS selectors like

#pe_teachers div.classname { ... }

As for the IE bug, looks like you need to put in some Alerts to find out what it is.
In reply to Tim Hunt

Re: Interface design input please

by Mike Worth -
I knew there must have been a way to do it (I don't do graphical layout type stuff much).

I've also worked out ie's errors- firefox takes the new lines and tabs between tags to be text nodes: var teacherslist=document.getElementById('pe_teachers').childNodes[2]; in ie is equivalent to var teacherslist=document.getElementById('pe_teachers').childNodes[4]; in firefox.

I can't eliminate these 'blank' text nodes as they are inserted by formslib. Is there a way to make it work for both without detecting this behaviour and explicitly swapping between the two?

Also the showonlyselected feature takes ages in ie (about 5-7s compared to about .5s in ff) during which it uses 100% cpu. Is there any way to speed this up?

Thanks,
Mike
In reply to Mike Worth

Re: Interface design input please

by Mike Worth -
I've just been looking at optimisation, and it seems that the line that is taking the most time is teacherslist.childNodes[i].style.display='none';(and the equivilent block one). The only thing about these lines I can take out of the loops is the very first bit, which I've tried with var tmp=teacherslist.childNodes; then using tmp[i].style.display='none'; It doesn't make much difference. Have I missed some form of optimisation, or will I simply have to live with the fact that this will take several seconds?

Thanks,
Mike
In reply to Mike Worth

Re: Interface design input please

by Frank Ralf -
Hi Mike,

I am using this thread to brush up my rusty JavaScript knowledge a bit wink

To solve the problem of white space nodes you could check the "nodeType" of the retrieved childNodes. Element nodes (which you want) have a nodeType of 1, whereas text nodes (which you want to skip) have a nodeType of 3.

hth
Frank

In reply to Mike Worth

Re: Interface design input please

by Frank Ralf -
Hi Mike,

You could use "advanced checkboxes" instead of the normal ones in your form and give them class attributes. That way it might be easier to address them directly with JavaScript (getElementsByTagName) instead of fiddling with childNodes, see Development:lib/formslib.php_Form_Definition#advcheckbox.

hth
Frank
In reply to Frank Ralf

Re: Interface design input please

by Mike Worth -
Thanks for the advice, I've used the nodetype thing to get the same code to work on ff & ie.

As for the second bit, Im not sure that that will give any benefit- yes it will reduce having to navigate the node tree for the if statement, but then I'll have to navigate back up the node tree when it comes to setting the display style. While there might be a slight improvement because the more costly of the two wouldn't be run every time, testing has shown that the bit that takes the longest is actually setting the display styles

Thanks,
Mike
In reply to Mike Worth

Re: Interface design input please

by Frank Ralf -
Glad that worked. Is the code in CVS for testing? I couldn't get it to work in IE6 at all.

You're right, DOM traversing can be a real pain with pure JavaScript. For example with jQuery changing CSS requires only one line of code:

$(".pe_teacher").css("display","none");

That would hide all elements with class "pe_teacher" (see http://docs.jquery.com/Selectors/class).

Unfortunately I don't know how Moodle's JavaScript library YUI would handle this.

Cheers,
Frank


In reply to Frank Ralf

Re: Interface design input please

by Mike Worth -
It is now.

I haven't really used javascript libraries before; would it help, or would it just enable me to call a function that still does the same slow javascript functions, gaining nothing?

Thanks for looking at it,
Mike
In reply to Mike Worth

Re: Interface design input please

by Frank Ralf -
The advantages of using a (good) JavaScript library are (or at least should be):

1) leaner code by using enhanced wrapper funcitions
2) cross-browser compatibility
3) performance optimization

(Of course under the hood it's the same old JavaScript.)

The YUI DOM utility for example provides methods like "getElementsByClassName" or "addClass" which you had to write yourself when using pure JS (see http://developer.yahoo.com/yui/docs/YAHOO.util.Dom.html).

Cheers,
Frank

In reply to Frank Ralf

Re: Interface design input please

by Alan Trick -

leaner code by using enhanced wrapper funcitions

I find that the code isn't always leaner, especially when using YUI, which is IMHO a bit over-engineered.

In reply to Alan Trick

Re: Interface design input please

by Frank Ralf -
Hi Alan,

I agree with you. YUI seems to be best for rather heavy weight solutions out of the box (e.g. a TreeView control or Drag&Drop stuff), but for replacing normal JavaScript I personally would prefer jQuery, but YUI is the JS library of choice for Moodle... (see Javascript FAQ).

Cheers,
Frank
In reply to Frank Ralf

Re: Interface design input please

by Alan Trick -
Actually, TreeView is what I have the most experience with. I choose it because Moodle includes YUI, but I found out that's pretty much it's only redeeming factor. It completely throws out any hope of accessibility or sane fallbacks, it has some nasty quirks (like the fact that TextNodes actually treat their 'text' as HTML), and the developers seem to screw things up with every update (misplacing the style file, secretly changing dependancies). Most of the bugs I had were due to YUI.
In reply to Mike Worth

Re: Interface design input please

by Frank Ralf -
Hi Mike,

Gave it a quick try and it does work now in IE6. And it's as fast as in FF3 (as far as I can tell).

Frank
In reply to Mike Worth

Re: Interface design input please

by Frank Ralf -
Hi Mike,

The code as it is relies heavily on counting nodes which is not very robust because some browsers might decide to insert some more whitespace nodes or leave some out which will render your script useless. You better address the nodes directly using element or attribute names.

Frank
In reply to Frank Ralf

Re: Interface design input please

by Mike Worth -
I've just committed a version that gets the inputs, then works its way back up through parentnodes. It seems a bit better, and will be more reliable.

As for ff3 vs ie6, I've had a look and it appears that the virtual XP install is only only using 1 of my cpus while ff3 is running natively; this must be the reason for the performance difference. What is the performance like on your computer?

Thanks,
Mike
In reply to Mike Worth

Re: Interface design input please

by Frank Ralf -
Hi Mike,

I tried my hands at YUI and this is the result:

You need to include the necessary YUI libraries at the beginning of the file:

require_js(array(
    'yui_yahoo',
    'yui_dom-event')
);

Then you add a class attribute of "pe_teacher" to the check boxes:

$mform->addElement(
    'checkbox',
    'teachers['.$user->id.']',
    $user->firstname.' '.$user->lastname,
    '',      // optional label right side
    array('class'=>'pe_teacher')    // attribute for form element
);

Then you can exchange your function with this YUI version:

<script type="text/javascript">
var teachers = YAHOO.util.Dom.getElementsByClassName('pe_teacher', 'input', 'pe_teachers');

var parentseve_toggleonlyselected = function(state) {

    for (var i=0; i < teachers.length; i++){
        var formitem = YAHOO.util.Dom.getAncestorByClassName(teachers[i], 'fitem');

        if (state){                             
            if (!teachers[i].checked){
                formitem.style.display='none'; 
            }
        } else {
                formitem.style.display='inline';
        };
    };
};
</script>

Cheers,
Frank