2

Obviously, if I have a 'select' element, I can add an event listener for changes using some basic JS:

document.querySelector('select').addEventListener('change', function(ev){
  console.log('Changed', ev.target.value)
})

Click the 'select' element, modify the value, the log fires. Simple stuff.

However I'm working on a library for styled select boxes - like chosen or select2 without the jQuery dependency.

In my library, clicking the styled select box changes the .value of the real select box:

query('select').value = newValue;

I can see this is working if I make the real select box visible.

However, changing the value of the select box through JS doesn't trigger the select boxes 'change' event.

Is there a way I can change the select boxes value though JS and still have change events attached to the select box fire?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • Trying to reproduce yours I get: `TypeError: Argument 1 of EventTarget.dispatchEvent is not an object.` Try: `realSelect.dispatchEvent(changeEvent);` (without name argument); – Martin Ernst Sep 22 '14 at 12:07
  • @MartinErnst You're right, I've changed my code alternatively (and moved it to a separate answer so people actually see it). – mikemaccana Sep 24 '14 at 10:04

3 Answers3

1

Javascript

function fireEvent(element, event) {
    if (document.createEventObject) {
        // dispatch for IE
        var evt = document.createEventObject();
        return element.fireEvent('on' + event, evt)
    } else {
        // dispatch for firefox + others
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent(event, true, true); // event type,bubbling,cancelable
        return !element.dispatchEvent(evt);
    }
}

document.querySelector('select').addEventListener('change', function (ev) {
    console.log('Changed', ev.target.value)
});

btn.onclick = function () {
    select.selectedIndex = 2;
    var obj = document.querySelector('select');
    fireEvent(obj, 'change');
}

User call

var yourPlugin=new CustomSelect(options);
yourPlugin.value("3");

Plugin function

function value(val) {
    if (!val) return select.value;
    select.value = val;
    fireEvent(select, 'change');
}

DEMO

Hamix
  • 1,323
  • 7
  • 18
  • Thanks, that's exactly what I'm looking for. I tweaked your JSFiddle a little and created http://jsfiddle.net/mkctp8ut/3/ which uses Event constructors (MDN thinks document.createEvent is out of date). Thanks for all your help! – mikemaccana Sep 22 '14 at 13:04
  • It's really simple. Good luck. – Hamix Sep 22 '14 at 13:13
0

Just an idea: Trigger the event by yourself after changing the value:

var el = query('select');
el.value = newValue;
el.dispatchEvent(new Event('change'));
Martin Ernst
  • 3,199
  • 1
  • 12
  • 12
  • That's certainly possible, but the library is intended for other people and I don't want to require that users add additional event handlers - I simply want to fire the select boxes existing handlers when the styled select is changed. – mikemaccana Sep 22 '14 at 11:37
0

Based on @Hamix's excellent answer, and some advice from MDN about createEvent() being out of date, I eventually went with:

var changeEvent = new Event('change');
realSelect.dispatchEvent(changeEvent);

Here's a demo - again based on @Hamix's jsfiddle so go give him an upvote.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494