tags:

views:

46

answers:

2

In this site, for example, there are 3 SELECT elements (Step 1, Step 2 and Step 3). I'm able to change the value of the first one with selectElement.value = selectElement.options[i].value;, but when I change it the Step 2 doesn't update it's options as it would if I would select it with the mouse. Is there any way to force it to update?

+2  A: 

The best way to do this is to have a function that updates the contents of the second select box, and call that function when you update the value of the first one. You'd then have a change handler (or a click handler, or a timer; depends on what you prefer for a UX) on the first select box that calls that function when its value changes. E.g. (in near-pseudocode):

<select id='box1' onchange='fillBox2();'>...</select>
<select id='box2'>...</select>
<select id='box3'>...</select>

function setValueInBox1(val) {
    var box1 = document.getElementById('box1');
    box1.value = val;
    fillBox2();
}

So both the event and your logic call the same routine, fillBox2.

People routinely try to trigger the actual event handler of box1 (the change event in the above), but that can be difficult and error-prone. By having a common function that both the event handler and your logic can call, you avoid that issue.


If for whatever reason the above is impossible, if you're doing it specifically in IE and not worrying about cross-browser behavior (from your comment), you might look at the fireEvent method. For other browsers, you might look at the DOM dispatchEvent method.

T.J. Crowder
+1 - this not only avoids the issue of programmatically invoking the event, but is also a better design as everything is not forcefully channeled through a user or DOM event.
Anurag
I can't change the contents of the HTML code for my case. Is there any way to do it with pure JavaScript?
jsoldi
@jsoldi: The above *is* pure JavaScript. You don't have to change the HTML, you just have to change the JavaScript in the event handler that's being called. In the Crucial site you linked to, that's being hooked up dynamically (not via an `onchange` attribute) and in fact is calling a function called `loadDDL2RAMPL`, which you can just call directly. It's possible to call handlers hooked up the old "DOM0" way (`onchange=`), but when you get into handlers attached via `addEventListener` or `attachEvent` as with that site, it gets into browser-specific stuff very quickly. Cont'd...
T.J. Crowder
@jsoldi: (continuing) Now, it happens that that Crucial site is using Prototype, and Prototype keeps a list of all of the event handlers attached to elements when you use it to attach them. So as an alternative, it would be *possible* to do this in a Prototype-specific way by diving into Prototype's internals (which sounds scary, but they aren't all *that* complicated).
T.J. Crowder
Tried calling `loadDDL2RAMPL()` right after changing the value of the SELECT element but still didn't update the next SELECT. Anyway, is there any way to invoke event handlers that have been attached with `addEventListener`/`attachEvent`? (I'm using IE).
jsoldi
@jsoldi: See update above, if you're just using IE and don't care about other browsers, you might be able to do it with `fireEvent`. (And there's a similar DOM standard method `dispatchEvent` for other browsers, but my understanding is that this is a complicated cross-browser area. If you're just worried about IE, though...)
T.J. Crowder
That worked!. Thank you, saved my life!
jsoldi
@jsoldi: LOL No worries
T.J. Crowder
A: 

Well , you could always invoke the method like

document.getElementById('x').onchange();

, where 'x' is the id of the select element

amal
Just tried that. Didn't work, don't know why. Could the page be using another event to update the next select bot?
jsoldi
That will only work for handlers hooked up the old "DOM0" way (`onchange=`), not with the DOM2 stuff `addEventListener`/`attachEvent`. It also doesn't work cross-browser, some browsers return a string rather than a function from the `onchange` reflected property and you have to `eval` it to call it.
T.J. Crowder