Friday, September 25, 2009

Problem rendering AJAX PopupExtender over ActiveX in IE 7, IE 8 and FireFox.

If you happen to have some sort of ActiveX control on your page in an IFrame, such as PDF viewer, then some of the AJAX controls which use PopupExtender will be obscured by the ActiveX or any other browser plug-in which rendering happens out of the main page context.

For example menus, and CalendarExtender suffer this problem, since they inherit PopupBehavior.

What happens is Ajax PopupExtender behavior explicitly checks for browser version, in particular IE 6. In IE 6 there was a known problem with z-index so you had to use IFrames to render some popup controls, so PopupBehavior checks whether browser is IE 6 and creates an IFrame around control, otherwise no IFrame created, hence the problem in newer IEs and FireFox with browser plug-ins.

To fix this problem, first download source code for AJAX Control Toolkit from CodePlex. And find PopupExtender folder in VS project. Then find this function:

addBackgroundIFrame : function()

Remember to duplicate your effort for debug and release versions of code, since there are two separate files.

Now lets take a look at the original code:

addBackgroundIFrame : function() {
/// <summary>
/// Add an empty IFRAME behind the popup (for IE6 only) so that SELECT, etc., won't
/// show through the popup.
/// </summary>

// Get the child frame
var element = this.get_element();
if ((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.version < 7)) {
var childFrame = element._hideWindowedElementsIFrame;

// Create the child frame if it wasn't found
if (!childFrame) {
childFrame = document.createElement("iframe");
childFrame.src = "javascript:'<html></html>';";
childFrame.style.position = "absolute";
childFrame.style.display = "none";
childFrame.scrolling = "no";
childFrame.frameBorder = "0";
childFrame.tabIndex = "-1";
childFrame.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)";
element.parentNode.insertBefore(childFrame, element);
element._hideWindowedElementsIFrame = childFrame;
this._moveHandler = Function.createDelegate(this, this._onMove);
Sys.UI.DomEvent.addHandler(element, "move", this._moveHandler);
}

// Position the frame exactly behind the element
$common.setBounds(childFrame, $common.getBounds(element));

childFrame.style.left = element.style.left;
childFrame.style.top = element.style.top;

childFrame.style.display = element.style.display;

if (element.currentStyle && element.currentStyle.zIndex) {
childFrame.style.zIndex = element.currentStyle.zIndex;
} else if (element.style.zIndex) {
childFrame.style.zIndex = element.style.zIndex;
}
}
},

Notice the section above, which has IF statement.

Remove that IF statement completely. Recompile your AjaxControlToolKit project and reference this new dll in your ASP.NET project. Drum roll… it works! ActiveX does not render over your popup control anymore.

Keep in mind, if you have many IFrames on your page it would slower rendering, so try to keep number of IFrames to a minimum.

Another ISolvable problem :).

5 comments:

  1. Did you remember to duplicate your effort for debug and release versions of code, since there are two separate files?
    Release version is more compact, because it gets downloaded into a client machine in production environment and thus all the comments, extra spaces and returnes are removed, it is somewhat hard to edit such code.

    ReplyDelete
  2. Hello Ivan,
    Nice article, really helped me after my clickonce deployment broke and I needed a VBS file to run on the machines to remove it!

    However, if there have been updates in the past, the ApplicationName Maintenance window has a restore option - (which it defaults to) so when i sendkeys "OK" it performs the restore action instead of the remove :(

    I naively tried a SendKeys call with "Remove the application from this computer" with no joy.

    Can you think of a way that I can change the selected option to "Remove the application from this computer"?

    Thanks for any help in advance!

    Kind Regards,
    Matt

    ReplyDelete
  3. @Matt,
    I moved your comment in here http://isolvable.blogspot.com/2010/01/uninstalling-clickonce.html
    and replied to it.

    ReplyDelete
  4. Ivan, Thank you very much. You solved my problem. It works great.

    ReplyDelete