locked
Bug with $addHandler applied to element in an iFrame RRS feed

  • Question

  • User-543773283 posted

    I have two pages:

    • my first page has a ScriptManager referencing PreviewScript.js and an iframe with id="iframeFileUpload" which loads my second page
    • my second page only has a FileUpload server control with id="FileUpload".

    In my first page, I have a pageLoad function which contains the following script:

    g_UploadIFrame = $get("iframeFileUpload"); <% //Reference to the iFrame element %>
    g_FileUploadTextBox = $get("FileUpload", g_UploadIFrame.contentWindow.document); <% //Reference to the File input field%>
    $addHandler(g_FileUploadTextBox, "keyup", validateBeforeSend);
    $addHandler(g_FileUploadTextBox,
    "propertychange", validateBeforeSend);

    where g_UploadIFrame and g_FileUploadTextBox are declared globally and validateBeforeSend displays an alert for the purpose of this report.

    This code executes fine when the page loads but raises the following error when the event is raised:

    Line 2089 Char 12: Sys.ArgumentNullException: Value cannot be null. Parameter name: eventObject.

    Sunday, October 22, 2006 4:17 PM

All replies

  • User-543773283 posted
    Can anyone help with this?
    Monday, October 23, 2006 8:16 AM
  • User476740548 posted

    While I don't have an exact answer, it may be because the event is occurring in the IFrame which has its own DOM, eventing model, etc. The IFrame document really acts independently of the parent page. It is its own document with its own window, etc. Passing an event from the IFrame to the parent window is probably not supported in the framework as it's impossible for the framework to know how many levels deep the event is (an Iframe inside of an IFrame, inside of an IFrame, etc.).


    I kind of ran into this before when trying to work with multiple modal popups that contained IFrames.


    Hope this helps.

     

    Friday, October 27, 2006 1:17 AM
  • User1245178932 posted
    I'm having the same error, but it's only occuring in IE and not in Firefox.
    Friday, April 6, 2007 6:40 AM
  • User1245178932 posted

    Anybody who has a fix or workaround for this? Please let me know.

    Thanks

    Tuesday, April 10, 2007 3:40 AM
  • User232384818 posted

    hi, this is indeed a bug. If you will note the code for addHandler method in the ajax extentions library, you will note that the window object is hard coded, which makes it choke in IE if your trying to attach events to elements in your iframe. The ideal solution is to have a 4th parameter on the addHandler method that takes a window object and the problem is resolved. Note below the code in addHandler :

     

    1    if (element.attachEvent) {
    2            browserHandler = function() {
    3                return handler.call(element, new Sys.UI.DomEvent(window.event));
    4            }
    

     
    Note above the window object hardcoded and passed to DomEvent class. This is why we all have problems when we use iframe ;-)

    I hope the asp.net team update the ajax libraries addHandler method with a forth parameter. In the meantime, i have prototyped a addHandler2 method which can take a forth parameter. in the forth parameter pass it the window object of your iframe, that will be contentWindow. Following is the prototype :
     

    1    Sys.UI.DomEvent.addHandler2 = function Sys$UI$DomEvent$addHandler(element, eventName, handler, contentWindow) {
    2        /// <param name="element" domElement="true"></param>
    3        /// <param name="eventName" type="String"></param>
    4        /// <param name="handler" type="Function"></param>
    5        var e = Function._validateParams(arguments, [
    6            {name: "element", domElement: true},
    7            {name: "eventName", type: String},
    8            {name: "handler", type: Function},
    9            {name: "contentWindow", type: Object, optional: true, mayBeNull: true}
    10       ]);
    11       if (e) throw e;
    12   
    13       if (!element._events) {
    14           element._events = {};
    15       }
    16       var eventCache = element._events[eventName];
    17       if (!eventCache) {
    18           element._events[eventName] = eventCache = [];
    19       }
    20       var browserHandler;
    21       if (element.addEventListener) {
    22           browserHandler = function(e) {
    23               return handler.call(element, new Sys.UI.DomEvent(e));
    24           }
    25           element.addEventListener(eventName, browserHandler, false);
    26       }
    27       else if (element.attachEvent) {
    28           browserHandler = function() {
    29               var w = (contentWindow == null) ? window.event : contentWindow
    30               return handler.call(element, new Sys.UI.DomEvent(w.event));
    31           }
    32           element.attachEvent('on' + eventName, browserHandler);
    33       }
    34       eventCache[eventCache.length] = {handler: handler, browserHandler: browserHandler};
    35   }
    
     

    good luck
    Friday, May 18, 2007 12:05 PM
  • User-815265379 posted

    Just ran into this today, doing the exact same thing, referencing an upload form in an iframe.  Works in FF, not in IE.  Alessandro, thanks for the summary and code.

    Wednesday, December 5, 2007 5:55 PM
  • User2122420742 posted

    EDIT: My proposed alternative didn't work. Sorry.

    Thursday, January 17, 2008 7:36 AM
  • User-428661938 posted

     Thanks for the code. Were you ever able to get this to work in IE? It only works in FF for me.

    Thursday, January 17, 2008 11:11 AM
  • User232384818 posted

     Thanks for the code. Were you ever able to get this to work in IE? It only works in FF for me.

    hi, yes ofcourse. The whole point of the prototype is to get it working in IE. You need to pass the fourth parameter in the prototyped function. This parameter must be your iframes contentWindow.

    Good luck,

    Alessandro

    Thursday, January 17, 2008 11:57 AM
  • User-428661938 posted

     I created a function using your code:

        function addIframeHandler(element, eventName, handler, contentWindow) { ...

    Then I called the function as follows:

        addIframeHandler(this.frames["<%=this.ID %>iframe"].document.getElementById(elem[i].name), "click", myClickHandler, this.frames["<%=this.ID %>iframe"].document.window); 

    I then added an alert in the handler to test if the handler fires ...

        function myClickHandler(sender, args)
        {
            alert("Handler fired");
        }

    It works beautifully in FF, but the handler doesn't fire in IE. Any ideas as to why?
     

    Thursday, January 17, 2008 12:05 PM
  • User-428661938 posted

     I also tried passing the iframe contentWindow, but to no avail ...

         addIframeHandler(this.frames["<%=this.ID %>iframe"].document.getElementById(elem[i].name), "click", myClickHandler, this.frames["<%=this.ID %>iframe"].contentWindow);
     

    Thursday, January 17, 2008 2:00 PM
  • User-364673189 posted
    Just my code for workaround this bug:
     
    1    var $addHandlerEx = Sys.UI.DomEvent.addHandlerEx = function Sys$UI$DomEvent$addHandlerEx(element, eventName, handler, windowFinder) {
    2        /// <param name="element" domElement="true"></param>
    3        /// <param name="eventName" type="String"></param>
    4        /// <param name="handler" type="Function"></param>
    5        /// <param name="windowFinder" type="Function"></param>
    6        var e = Function._validateParams(arguments, [
    7                    {name: "element", domElement: true},
    8                    {name: "eventName", type: String},
    9                    {name: "handler", type: Function},
    10                   {name: "windowFinder", type: Function, optional: true, mayBeNull: true}
    11                   ]);
    12       if (e) throw e;
    13   
    14       if (!element._events) {
    15           element._events = {};
    16       }
    17       var eventCache = element._events[eventName];
    18       if (!eventCache) {
    19           element._events[eventName] = eventCache = [];
    20       }
    21       var browserHandler;
    22       if (element.addEventListener) {
    23           browserHandler = function(e) {
    24               return handler.call(element, new Sys.UI.DomEvent(e));
    25           }
    26           element.addEventListener(eventName, browserHandler, false);
    27       }
    28       else if (element.attachEvent) {
    29           browserHandler = function() {
    30               if(windowFinder == null) {
    31                   return handler.call(element, new Sys.UI.DomEvent(w.event));
    32               }
    33               else {
    34                   return handler.call(element, new Sys.UI.DomEvent(windowFinder.call().event));
    35               }       
    36           }
    37           element.attachEvent('on' + eventName, browserHandler);
    38       }
    39       eventCache[eventCache.length] = {handler: handler, browserHandler: browserHandler};
    40   }
     
     usages :
    $addHandlerEx(this.frames["<%=this.ID %>iframe"].document.getElementById(elem[i].name), "click", myClickHandler, function (){return this.frames["<%=this.ID %>iframe"].contentWindow;});
    Thursday, July 10, 2008 6:39 AM