views:

962

answers:

3

Is there a way to make a HTML select element call a function each time its selection has been changed programmatically?

Both IE and FF won't fire 'onchange' when the current selection in a select box is modified with javascript. Beside, the js function wich changes the selection is part of framework so I can't change it to trigger an onchange() at then end for example.

Here's an example:

<body>
<p>
<select id="sel1" onchange="myfunction();"><option value="v1">n1</option></select>
<input type="button" onclick="test();" value="Add an option and select it." />
</p>
<script type="text/javascript">
    var inc = 1;
    var sel = document.getElementById('sel1');
    function test() {
     inc++;
     var o = new Option('n'+inc, inc);
     sel.options[sel.options.length] = o;
     o.selected = true;
     sel.selectedIndex =  sel.options.length - 1;
    }

    function myfunction() {
     document.title += '[CHANGED]';
    }
</script>
</body>

Is there any way to make test() call myfunction() without changing test() (or adding an event on the button)?

Thanks.

+1  A: 

If you can extend/modify the framework to give a hook/callback when they change the select options, it would be better (one way could be to use the dynamic capabilities of js to duck type it in?).

Failing that, there is an inefficient solution - polling. You could set up a setTimeout/setInteval call that polls the desired select option dom element, and fire off your own callback when it detects that something has changed.

as for the answer to your question

Is there any way to make test() call myfunction() without changing test() (or adding an event on the button)?

yes, by using jquery AOP http://plugins.jquery.com/project/AOP , it gives an easy-ish solution.

<body>
<p>
<select id="sel1" onchange="myfunction();"><option value="v1">n1</option></select>
<input type="button" onclick="test();" value="Add an option and select it." />
</p>
<script type="text/javascript">
    var inc = 1;
    var sel = document.getElementById('sel1');
    function test() {
        inc++;
        var o = new Option('n'+inc, inc);
        sel.options[sel.options.length] = o;
        o.selected = true;
        sel.selectedIndex =  sel.options.length - 1;
    }

    function myfunction() {
        document.title += '[CHANGED]';
    }

    //change to aop.after if you want to call afterwards       
      jQuery.aop.before( {target: window, method: 'test'}, 
        function() { 
          myfunctino(); 
        }
      );
</script>
</body>
Chii
I also thought about the second option but I'd only use the timer if this is my last resort. First solution sounds good, how could I extend/hook test without modifying its source code?
+1. Polling is an option worth considering. However you would have to accept that the code you would like to invoke on change does not run synchronously with the change.
AnthonyWJones
The jQuery.aop solution works like a charm. Thanks a lot!
A: 

The answer is .... no.

The DOM only fires the onchange event as a result of user action not code. It does not provide any additional events to hook in this regard.

You will need to customise the framework or drop your requirement.

AnthonyWJones
A: 

ahem...

you can access the event 'onpropertychange' it contains a property within the event arguments to identify which property was changed.

It detects both 'selectedIndex' and 'value' changes - simply case test 'propertyName' I'm currently working with the ASP.NET js framework here is some straight copy-paste code for that:

1) define handler:

this._selectionChangedHandler = null;

2) assign handler

this._selectionChangedHandler = Function.createDelegate(this, this._onSelectionChanged);

3) attach handler to event

$addHandler(element, "propertychange", this._selectionChangedHandler);

4) create function

_onSelectionChanged: function(ev) {

if (ev.rawEvent.propertyName == "selectedIndex")
        alert('selection changed');
},
Sean.C