Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node webkit- catch iframe mouse events from parent window

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?
like image 536
yarden Avatar asked Apr 08 '15 12:04

yarden


3 Answers

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>
like image 90
Chris Avatar answered Nov 17 '22 05:11

Chris


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?

like image 1
thetoast Avatar answered Nov 17 '22 06:11

thetoast


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.

like image 1
artur grzesiak Avatar answered Nov 17 '22 05:11

artur grzesiak