prototypejs / prototype

Prototype JavaScript framework
http://prototypejs.org/
Other
3.53k stars 639 forks source link

Element.visible() not working from a different document. #319

Closed yunosh closed 7 years ago

yunosh commented 8 years ago

See comments on commit 548580c. This is an example of visible() not working correctly anymore:


<html>
  <head>
    <title>IFRAME test</title>
    <style type="text/css">
    </style>
  </head>
  <body>
    <div id="target"></div>
  </body>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/prototype/1.7.3.0/prototype.js"></script>
  <script type="text/javascript">
    $('target').update('<iframe id="iframe" style="width:100%;border:1px solid #000" src="javascript:false" frameborder="0" style="display:none;height:auto;"></iframe>');
    var i = $('iframe'),
        d = i.contentDocument || (i.contentWindow && i.contentWindow.document),
        p;
    d.open();
    d.write('<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta http-equiv="x-dns-prefetch-control" value-equiv="off"></head><body style="overflow-y:hidden;width:auto !important"><p id="paragraph">Hello World</p></body></html>');
    d.close();
    i.show();
    p = Prototype.Selector.select('P', d).findAll(Element.visible);
    console.log(p);
  </script>
</html>
savetheclocktower commented 7 years ago

I'll have to investigate this. If it's reproducible, it would suggest that getStyle isn’t working as expected, either.

savetheclocktower commented 7 years ago

The core issue here is that $ does not add Prototype's methods to nodes that come from a different document than the one that loaded Prototype.

I can’t say whether this is a feature or a bug because this was not a use case that anyone thought about or tried to support. It's true that Element.visible worked before because it read only the inline style and didn't try to call one of Prototype's element instance methods.

Your use case probably works in a pre-1.7.3 version, but I don't think we've ever placed our methods onto elements owned by another document — except, perhaps, by accident in IE. I don't think a future version will do so either.

But I can offer two changes that should fix this use case:

  1. Element.visible will call Element.getStyle rather than the getStyle instance method.
  2. Element.getStyle will get the computed style from the node's ownerDocument instead of always looking for it on our own document object.

The goal here is that it should always be safe to run a node through the generic methods defined on Element. If other things like this are also currently broken, we can handle them on a case-by-case basis.