onchange event for SELECT element trouble with Internet Explorermouse wheel

J

jezaustin

Hi guys,
I'm using the onchange event on a SELECT element to pull extra inputs
into a form based on the value in the SELECT. It works fine in both
firefox and explorer: user selects an option and relevant extra fields
appear / disappear immediately.

However, explorer has a feature that allows a user to scroll through
the options in a select field using the onmousewheel, and the onchange
function appears not to fire.

What's the simplest way around this? I've considered the following:
1) trap the onmousewheel event
a) update the fields there and then
b) repress the change in the SELECT on the mousewheel

2) alter the server side code to offer a second round of questioning
if there's a discrepancy between the selected options and the
dependent fields offered.



2) is definitely doable, but I feel is a degraded user experience.
I've attempted both 1a) and 1b) but I can't make either work.
With 1a) I do seem to be able to trigger the function on a mouse
scroll, but it doesn't do the actual DOM work. I don't know why, I
believe it should work, I'm not using "this" or the event object at
all. See below for code, am I doing something stupid?
With 1b) I've just had no luck at all. Returning false doesn't stop
the scroll wheel altering values in the SELECT. Anybody know how or if
you can do this? Or is there another solution to this that I haven't
thought of?

I'd be very grateful for any help or advice, general or specific.

Thanks,
Jez Austin.

Here's the function:
<pre>
function
select_traits(i)
{
// i is
integer
// usually called from "measure"+i
onchange
var elem =
document.getElementById("measure"+i);

// record array of selected
measures
var selected_measures =
[];
var
measureIndex;
for (var j=1; j<5; j+
+)
if (0 != (measureIndex
=

document.getElementById("measure"+j).selectedIndex))
// all measure selects have the same
options

selected_measures.push(elem.options[measureIndex].value);

// hide irrelevent traits
// that is, move them to a hidden div outside the
form
var traits = get_trait_fieldset(); // returns the fieldset
element, creates it if it doesn't yet
exist
var hidden_traits =
document.getElementById("traits_hidden");

var row_div =
traits.firstChild;
while (row_div)
{
if ("div" != row_div.nodeName.toLowerCase())
{
row_div =
row_div.nextSibling;

continue;
}

// Each of these spans has an attribute "measures",
// a comma separated list of the measures it is associated
with
var my_measures
=
row_div.getElementsByTagName("span")
[0].getAttribute("measures").split(",");
if (array_overlap(my_measures, selected_measures))
{
row_div =
row_div.nextSibling;

continue;
}

var next_div =
row_div.nextSibling;

hidden_traits.appendChild(row_div);
row_div =
next_div;
}


// reveal relevent
inputs
row_div =
hidden_traitts.firstChild;
while (row_div)
{
if ("div" != row_div.nodeName.toLowerCase())
{
row_div =
row_div.nextSibling;

continue;
}

var my_measures
=
row_div.getElementsByTagName("span")
[0].getAttribute("measures").split(",");

if (! array_overlap(my_measures, selected_measures))
{
row_div =
row_div.nextSibling;

continue;
}

var next_div =
row_div.nextSibling;

traits.appendChild(row_div);
row_div =
next_div;
}

if (0 ==
traits.getElementsByTagName('div').length)

traits.parentNode.removeChild(traits);

// test: is this called be wheel
code?
return 'called select_traits('+i+')';
// needn't / shouldn't return
anything
}
</pre>

and here's where I set the onchange events
<pre>
for (var i=1; i<5; i++)
{
var measure_select =
document.getElementById("measure"+i);

measure_select.onchange = measure_select.onleave = function(evt)
{
// alert("hello
world");

refuse_duplicates();

evt = (evt) ? evt : ( (event) ? event :
null );
if(evt)
{
var elem = (evt.target) ?
evt.target :
((evt.srcElement) ? evt.srcElement :
null);
if(elem)
{
elem = (elem.nodeType==1 || elem.nodeType==9) ? elem :
elem.parentNode;

select_traits(elem.id.substring(7));
}
}
};
}
select_traits(1);
</pre>
That last line pulls in the relevant traits when editing an existing
record, and proves that the function works in IE both when called
explicitly and when called by the event.

Here's how I attach it to the onmousewheel event
<pre>
var soc_id =
null;
function update_on_wheel_for_ie( code, delay )
{
delay = delay || 1000; // default
1s

window.clearTimeout( soc_id );
// appears as though the select_traits function isn't getting
purchase on the DOM elements when called this
way... ??
//
alert(select_traits(1));
soc_id = window.setTimeout( code,
delay );
}

document.onmousewheel = window.onmousewheel = function()
{
// alert("hello
world");
update_on_wheel_for_ie('refuse_duplicates(); select_traits(1);
select_traits(\
2); select_traits(3);
select_traits(4);');

//'document.getElementById("measure1").onchange();');
return
true;
};
</pre>

Sorry if this bit isn't very clear, I've just been trying out a few
things, thought I'd include it though.
 
D

David Mark

Hi guys,
I'm using the onchange event on a SELECT element to pull extra inputs
into a form based on the value in the SELECT. It works fine in both
firefox and explorer: user selects an option and relevant extra fields
appear / disappear immediately.

The change event won't fire in some browsers until the SELECT element
loses focus. IIRC, most fire it immediately when a pointing device is
used, IE fires immediately when using the keyboard as well. I thought
for sure that IE did the same when using the mousewheel.
However, explorer has a feature that allows a user to scroll through
the options in a select field using the onmousewheel, and the onchange
function appears not to fire.

What's the simplest way around this? I've considered the following:
1) trap the onmousewheel event
  a) update the fields there and then
  b) repress the change in the SELECT on the mousewheel
No.


2) alter the server side code to offer a second round of questioning
if there's a discrepancy between the selected options and the
dependent fields offered.

You should do that anyway. You can't count on client-side script to
guarantee valid input.
2) is definitely doable, but I feel is a degraded user experience.
I've attempted both 1a) and 1b) but I can't make either work.
With 1a) I do seem to be able to trigger the function on a mouse
scroll, but it doesn't do the actual DOM work. I don't know why, I
believe it should work, I'm not using "this" or the event object at
all. See below for code, am I doing something stupid?
With 1b) I've just had no luck at all. Returning false doesn't stop
the scroll wheel altering values in the SELECT. Anybody know how or if
you can do this? Or is there another solution to this that I haven't
thought of?

You don't want to block mousewheel input. Can't the application wait
until the use changes focus (in which case the change event should
certainly fire?)
 
J

jezaustin

The change event won't fire in some browsers until the SELECT element
loses focus. IIRC, most fire it immediately when a pointing device is
used, IE fires immediately when using the keyboard as well. I thought
for sure that IE did the same when using the mousewheel.

Well, based on your surprise I decided to test on a different setup
(I'd been using explorer using wine under linux) and it seems that
explorer acts as you say, and onchange does happen during mousewheel
scrolls.
So this is just a bug on an unsupported operating system, and can be
reasonably ignored.

Anyhow, I'll use both onchange and onleave events for extra safety.
You should do that anyway. You can't count on client-side script to
guarantee valid input.

Yep, of course.

Thanks for the help David,

Jez.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top