Tuesday, September 10, 2013

Displaying external content in a IFRAME within a popup dialog

I recently had a requirement to display some non ADF content inside a popup dialog.   There are a number of blogs on how to do this (see this one)  so I won't rehash them here.  I did however run into one problem in that when you drag the dialog around on the page and the mouse cursor slips into the frame containing the external content, the mouse events get captured by the frame and the dialog stops dragging.  Then if you release the mouse button and move outside of the frame, the dialog is now stuck to the end of your mouse cursor because the page lost the mouse up event and still thinks the mouse button is pressed.   To fix this I had to write a javascript mouse event handler and attach it to the frame to propagate mouse events in the frame to the parent page.

I found the basis for my solution here.  mousemove-when-over-an-iframe

I modified this slightly in that my particular page didn't need to save the original onMouseMove and onMouseUp handlers.


To wire this up add a client listener to the popup
  <af:clientListener type="popupOpened"     method="popupOpened"/>
 


 
// This method attaches the frame with id of "fid" to the mouse event handler

 function popupOpened(e){
      var frame = document.getElementById( e.getSource().findComponent("fid").getClientId()+'::f');
      bubbleIframeMouseMove(frame);
  }

// iframe causes the page to lose the mouse events when dragging the dialog
// this fixes it by propagating mouse events in the iframe to the parent page

function bubbleIframeMouseMove(iframe){
 
     iframe.contentWindow.onmousemove = propagateToParent;
     iframe.contentWindow.onmouseup = propagateToParent;
      
      function propagateToParent(e){
        // Create a new event for the this window
        var evt = document.createEvent("MouseEvents");
        // We'll need this to offset the mouse move appropriately
        var boundingClientRect = iframe.getBoundingClientRect();
        // Initialize the event, copying exiting event values
        // for the most part
        evt.initMouseEvent(
            e.type,
            true, // bubbles
            false, // not cancelable
            window,
            e.detail,
            e.screenX,
            e.screenY,
            e.clientX + boundingClientRect.left,
            e.clientY + boundingClientRect.top,
            e.ctrlKey,
            e.altKey,
            e.shiftKey,
            e.metaKey,
            e.button,
            null // no related element
        );

        // Dispatch the mousemove event on the iframe element
        iframe.dispatchEvent(evt);
    };
}