10

I'm trying to create a draggable iframe in my app. When the iframe is focused, all mouse events are triggered within the inner window object.

  • I can't listen to those events within the iframe and trigger them myself, because it can be blocked by the iframe content js
  • I can't create an unvisible layer above the iframe that will catch all the events and move them forward to the iframe, because bultin events can't be triggered by script (like css hover)
  • can I catch those events in Node layer, without using webkit DOM?
yarden
  • 1,906
  • 1
  • 12
  • 16
  • Node is javascript, but it is not at the client side. It doesn't know about the DOM or mouse events, it just delivers content to the client. So, I'm going to go out on a limb here and say it's not possible. – HeadCode Apr 21 '15 at 21:53
  • Can't node communicate with native mouse events, like any native GUI app? – yarden Apr 21 '15 at 21:58
  • It doesn't look like it. It does make it easy to include node modules in the html code, but that's different than node knowing about mouse events. – HeadCode Apr 22 '15 at 00:25

3 Answers3

1

One idea I have is to place a transparent element (like a div) in front of your iframe and then intercept the click and mouse move events there to make the iframe drag around.

I've done so here in this plunker.

The code, as you see below, is just enough to get across this idea and what steps are required to get the iframe to move around. It has some flaws (move your mouse quickly) but you could do some things to resolve those issues.

<!DOCTYPE html>
<html>

  <head>
    <style>
      iframe, div {
        position: absolute;
        left: 20px;
        top: 20px;
        width: 200px;
        height: 200px;
      }
    </style>
  </head>

  <body>
    <iframe id="iframe" src="if.html"></iframe>
    <div id="div" onmousedown="startDrag(event)" onmouseup="stopDrag()" onmousemove="moveDrag(event)"></div>
  </body>


  <script>
    var objDiv = document.getElementById("div");
    var objDivCoordinates = {left: 20, top: 20};
    var objIframe = document.getElementById("iframe");
    var mouseX = null;
    var mouseY = null;
    var dragging = false;

    function startDrag(e) {
      mouseX = e.clientX;
      mouseY = e.clientY;
      dragging = true;
      objIframe.contentWindow.document.writeln("Starting Drag...<br>");
    }
    function moveDrag(e) {
      if(!dragging) return;

      var changeX = mouseX - e.clientX;
      var changeY = mouseY - e.clientY;

      objDivCoordinates.left -= changeX;
      objDivCoordinates.top -= changeY;
      objDiv.style.left = objDivCoordinates.left+"px";
      objDiv.style.top = objDivCoordinates.top+"px";
      objIframe.style.left = objDiv.style.left;
      objIframe.style.top = objDiv.style.top;

      mouseX = e.clientX;
      mouseY = e.clientY;
    }
    function stopDrag(e) {
      dragging = false;
    }
  </script>
</html>
Chris
  • 2,766
  • 1
  • 29
  • 34
  • I tried it. The prublem is that bultin events, like hover, can't be triggered by script. Maybe with node webkit you can? – yarden Apr 21 '15 at 22:22
  • Sorry, I misunderstood your question. I think I understand it better now. You want to be able to drag the iframe when it **is not** in focus, but also have events delivered into the iframe when it **is** in focus. Is that correct? – Chris Apr 21 '15 at 22:29
  • No. also when the iframe is in focus, I want being able to catch the mouse events in his parent – yarden Apr 21 '15 at 22:34
  • Well, you can do something like `objIframe.contentWindow.document.writeln("Starting Drag...
    ");` to execute some code inside of the iframe ([found here](http://stackoverflow.com/questions/251420/invoking-javascript-code-in-an-iframe-from-the-parent-page)). Any way to make it work like that?
    – Chris Apr 21 '15 at 22:37
  • If I'm listening to a mouse event by `Iframe.contentWindow.document`, another script can cancel it easily – yarden Apr 22 '15 at 21:02
1

You could try creating a plain EventEmitter and storing it on node's global object. Since global is accessible in all node-webkit contexts, the iframe could use it to emit things that it wants the parent window to know about, and the parent can likewise use it to emit events that the iframe may want to know about.

Is this a solution that might work for you?

thetoast
  • 763
  • 4
  • 9
  • The question is, how can I catch all mouse events from the iFrame, without allowing cancel the catching from there. If I'm listening to a click event by `Iframe.contentWindow.document`, another script can cancel it easily – yarden Apr 22 '15 at 21:01
1

From what I see you are the most concerned about a situation when some other script cancels execution of your listener (by calling stopPropagation), but you can prevent such situation altogether.

addEventListener(type, listener [, useCapture]) allows to pass a useCapture argument, which defaults to false. If you set it to true then you are safe:

After initiating capture, all events of the specified type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.

artur grzesiak
  • 20,230
  • 5
  • 46
  • 56