3

I have two HTML documents, b.html contains c.html using an iframe.

On b.html I need to draw some DIV (in my example id=selector), which partially cover content of c.html visualized in the iframe.

I need to get the ID of a DOM element corresponding to the mouse coordinate under the DIV selector.

At the moment Using document.elementFromPoint() directly in in c.html works partially, as when the mouse it is on DIV selector I cannot identify the underling DOM element in c.html (in this example DIV c).

I would need to know:

  • Is it possible to select element under another, using document.elementFromPoint() or any other means?
  • What could be a possible alternatively solution possibly using DOM and native API?

Example here (Please look at the console in Chrome):

http://jsfiddle.net/s94cnckm/5/

----------------------------------------------- b.html

<!doctype html>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>B</title>
    <script type="text/javascript">
        window.app = {
            start: function () {
            }
        };
    </script>
    <style>
        #selector {
            position: absolute;
            top: 150px;
            left: 150px;
            width: 250px;
            height: 250px;
            -webkit-box-shadow: 0px 0px 0px 5px yellow;
            -moz-box-shadow: 0px 0px 0px 5px yellow;
            box-shadow: 0px 0px 0px 5px yellow;
        }

        #iframe {
            width: 500px;
            height: 500px;
            border: none;
        }
    </style>
</head>
<body onload="app.start();">
    <div id="selector">SELECTOR</div>
    <iframe id="iframe" src="c.html"></iframe>
</body>
</html>

----------------------------------------------- c.html

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>C</title>
    <script type="text/javascript">
        window.app = {
            start: function () {
                document.querySelector('body').addEventListener('mousemove', function (event) {
                //console.log(event.pageX, event.pageY, event.target.id);
                var item = document.elementFromPoint(event.pageX, event.pageY);
                console.log(item.id);
                }.bind(this));
            }
        };
    </script>
    <style>
        body {
            background-color: lightslategray;
        }

        #a {
            position: absolute;
            top: 50px;
            left: 50px;
            width: 100px;
            height: 100px;
            background-color: green;
            z-index: 2;
        }

        #b {
            position: absolute;
            top: 100px;
            left: 100px;
            width: 100px;
            height: 100px;
            background-color: #ffd800;
            z-index: 1;
        }
    </style>
</head>
<body onload="app.start();">
    <h1>Content</h1>
    <div id="a">a</div>
    <div id="b">b</div>
</body>
</html>
GibboK
  • 71,848
  • 143
  • 435
  • 658
  • 2
    Here is a demo with your current code: http://jsfiddle.net/s94cnckm/2/, slightly edited (moved the js) to understand this issue a bit better. Sadly i have no more time now. Maybe someone finds this helpful. – Nico O Apr 08 '15 at 15:17
  • Thanks for your JS fiddle, I made some edit to your, in order to make it working link in my question, Here an example: http://jsfiddle.net/s94cnckm/5/ thanks for your support. Please let me know if you have any solutions. – GibboK Apr 08 '15 at 18:07
  • 1
    I'am pretty sure, that this is not what you want. But just to be sure: http://jsfiddle.net/s94cnckm/6/. I added `pointer-events: none` to `selector`. Of course the content is now close to useless, so the usage depends on the requirements of the project. Do you need to get the element out of the way or does `select` work like a "clipping mask"? – Nico O Apr 09 '15 at 12:18
  • 1
    Thanks, it solve my problem, please add it as an answer and I would be glad to accept it. Many thanks! – GibboK Apr 09 '15 at 13:17

2 Answers2

3

A possible soltion is the usage of pointer-events.

The CSS property pointer-events allows authors to control under what circumstances (if any) a particular graphic element can become the target of mouse events. When this property is unspecified, the same characteristics of the visiblePainted value apply to SVG content.

When you apply

#selector {
    /* ... */
    pointer-events: none;
 }

All content of #selector and the element itself are no more interactive. Content may not be selected and events like :hover or click are not applicable.

Here is the demo with the above css: http://jsfiddle.net/s94cnckm/6/

Nico O
  • 13,762
  • 9
  • 54
  • 69
  • Thanks for your answer, it really help me out. Nevertheless I have been looking for alternative solution, and I have posted here. Please let me know your toughs. Also knowing other alternatively solutions would be really appreciated. – GibboK Apr 09 '15 at 14:04
1

Another possible solution, is to capture the document coordinates of a mouse event fired on the masking item(DIV.selector), momentarily hide that masking item, and then ask the document what is under that coordinate position (using document.elementFromPoint(x,y)) before showing the masking item again.

The support for document.elementFromPoint() cover also old version of IE. Unfortunately pointer-events has limited support for older version of IE.

Here a working example:

http://jsfiddle.net/s94cnckm/14/

 document.getElementById('iframe').contentDocument.addEventListener('click', function (event) {
     alert(event.target.id);
 }.bind(this));

 document.getElementById('selector').addEventListener('click', function (event) {
     var selector = document.getElementById('selector');
     selector.style.display = 'none';
     var item = document.getElementById('iframe').contentDocument.elementFromPoint(event.pageX, event.pageY);
     selector.style.display = '';
     alert(item.id);
 }.bind(this));

Regarding the use of pointer-events I link to mention some related article, included a work around for older version of IE.

How to make Internet Explorer emulate pointer-events:none?

https://css-tricks.com/almanac/properties/p/pointer-events/

http://davidwalsh.name/pointer-events

http://robertnyman.com/2010/03/22/css-pointer-events-to-allow-clicks-on-underlying-elements/

This solution was inspired by this article:

http://www.vinylfox.com/forwarding-mouse-events-through-layers/

Community
  • 1
  • 1
GibboK
  • 71,848
  • 143
  • 435
  • 658