Link to home
Start Free TrialLog in
Avatar of Stefan Lennerbrant
Stefan LennerbrantFlag for Sweden

asked on

Triggering events between windows in IE11 - bug in browser?

I'm opening a new "window.open" html page from a "main" html page, and the opened window is then supposed to set a field in the main window, and trigger the change event for that field.

This works perfectly well in Chrome and Firefox and in all IE versions apart from IE11.

Chrome and Firefox does of course not support the fireEvent() method, so I use dispatchEvent() for event triggering.
All ok.

IE versions before IE11 support the fireEvent() method, and I use that for event triggering. All ok.
IE11 however does not - and dispatchEvent() seems to be buggy (see below)
Possibly, the same error exists in IE9 and IE10 (which support dispatchEvent as well) but if so, that's not a problem as fireEvent works ok in IE9 and IS10.


Ok - so the problem is the following.
I attach two files fire.htm and fire2.htm

When opening fire.htm, one can click on the link "Click to trigger event" to trigger a change event.
This works perfectly well i ALL browser, including IE11.

However, if one instead clicks on the link Click to open new window", a new window (fire2.htm) is opened.
If one clicks on the link "Click to trigger event in the main window" in this "child window", then an event is triggered on a field in the "parent windows".
This works perfectly well on all browsers apart from IE11!

The problem in IE11 is that dispatchEvent() seems to break with an error when the target does not exists in the same document - but instead in the parent window.

Does anyone recognize this? Any ideas on cause and any suggestions on a workaround solution?

Thanks,
/Stefan
fire.htm
fire2.htm
Avatar of David Johnson, CD
David Johnson, CD
Flag of Canada image

when I tested it ie11 opens a new window instead of using the main window.
Avatar of Stefan Lennerbrant

ASKER

How do you mean?

Yes, the file fire.htm shall open a new window containing fire2.htm
When you click at the link in fire2.htm, a change event shall trigger in the "main window" with fire.htm

Thus, both windows shall exist on the screen, but the event shall always trigger in the fire.htm window.

Sorry, I don't really understand what happens when you try it, @David?
Could you elaborate?
ASKER CERTIFIED SOLUTION
Avatar of Michel Plungjan
Michel Plungjan
Flag of Denmark image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yes, I'm trying to do the equivalent to
  window.opener.document.TheForm.TheField.onchange()

However, I'm using "event triggering" instead.
I am not really sure why I once upon a time did not choose to use onchange() instead.
Do you mean that this will work in all platforms and browser versions, just as good as event triggers? If so, this could be a solution. I'll investigate this.

Do you however agree to that "event triggering" should be working as well. Could this be a bug in IE11
Or am I doing something wrong, should event triggers be handled otherwise?
Ok, I just tested it, and the onchange() method seems to work just as good (even better) as dispatchEvent. Thanks!
I've tested on the newest versions of IE(11), Chrome and Firefox, and on an old IE7.

I've however only tested with <input type=text> fields, not other input types or <select> and <textarea> etc.
Hopefully it all works there as well. This is good news.

But... is there any catch?

I hope it's ok to quote other resources on the net, and I find some info at the address below
(and its latter "full method" obviously - as far as I can tell - does not work with "between windows" in IE11)

Reading this I get the impression that maybe onchange() does not always work?
Do note that the statement below that it does not work when setting the event listener using an attribute to the <input> tag, is obviously wrong. The field.onchange() method works OK for me, using <input> attribute onchange="xxx"

http://stackoverflow.com/questions/2856513/how-can-i-trigger-an-onchange-event-manually

There's a couple of ways you can do this. If the onchange listener is a function set via the element.onchange property and you're not bothered about the event object or bubbling/propagation, the easiest method is to just call that function:
element.onchange();

If you need it to simulate the real event in full, or if you set the event via the html attribute or addEventListener/attachEvent, you need to do a bit of feature detection to correctly fire the event:
if ("createEvent" in document) {
    var evt = document.createEvent("HTMLEvents");
    evt.initEvent("change", false, true);
    element.dispatchEvent(evt);
}
else
    element.fireEvent("onchange");
Have a try with this.

http://jsfiddle.net/mplungjan/s11uakx7/

tested in IE10, Fx31, Chrome 40 on windows 7

I do for now see that the attachEvent/addEventlistener needs extra code.

I do not see any difference between the inline change and the other unobtrusive change.


I obviously prefer to assign eventhandlers in script and not inline in the tag

function eventTrigger(element) {
    if ("createEvent" in document) {
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent("change", false, true);
        element.dispatchEvent(evt);
    } else element.fireEvent("onchange");
}
window.onload = function () {
    document.getElementById("select2").onchange = function () {
        alert(this.value);
    }
    var sel3 = document.getElementById("select3");
    if (sel3.addEventListener) {
        sel3.addEventListener('change', function () {
            alert(this.value + " from eventListener")
        }, false);
    } else if (sel3.attachEvent) {
        sel3.attachEvent('change', function () {
            alert(this.value + " from attachEvent")
        });
    }

    document.getElementById("but").onclick = function () {
        var w = window.open("", "popup", "height=100,width=100");
        w.document.write('<button onclick="opener.document.form1.select1.onchange();">Change 1</button>' +
            '<button onclick="opener.document.form1.select2.onchange();">Change 2</button>' +
            '<button onclick="opener.eventTrigger(opener.document.form1.select3)">Change 3</button>');
        w.document.close();
    }
}

Open in new window

<form name="form1">
    <select name="select1" id="select1" onchange="alert(this.value)">
        <option value="Please select (1)">Please select</option>
        <option value="Option 1 (1)">One</option>
    </select>
    <select name="select2" id="select2">
        <option value="Please select (2)">Please select</option>
        <option value="Option 1 (2)">One</option>
    </select>
    <select name="select3" id="select3">
        <option value="Please select (3)">Please select</option>
        <option value="Option 1 (2)">One</option>
    </select>
    <button id="but">Click to pop</button>
</form>

Open in new window

@Michel, thanks a lot for the onchange() idea, and for the jsfiddle setup.
Your jsfiddle works well in IE11, even though you use dispatchEvent in the same manner as I do in my example.
However, I execute the function within the popup window, not calling a js function in the target window. Maybe that's a reason for my problems?
I have not had time to test this, putting the script itself in the target window instead.

However, your onchange() idea works well as a fallback for IE11.
I do realize, now, that I of course use createEventObject() on the popup window document, even though the "fired field" resides in the target window, in another document. Maybe that's the reason that I get problems?


Anyhow, now having the time to experiment, I now ended up with the following FireEvent "wrapper", even though it's not optimar. FYI.
Please feel free to comment :-)

function FireEvent(flt, eventname)
{
  var event;

  if(my_page_is_running_in_jquery_environment == true)
    $$('flt').trigger(eventname);  
  else if(flt.fireEvent && document.createEventObject) {
    event = document.createEventObject();
    flt.fireEvent('on'+eventname, event);
  }
  else if(flt.dispatchEvent && document.createEvent) {
    event = document.createEvent('HTMLEvents');
    event.initEvent(eventname, true, true);
    try {
      flt.dispatchEvent(event);
    } catch(e) {
      if(eventname == 'change' && flt.onchange)
        flt.onchange();
    }
  }
}