【问题标题】:Jquery accessing $(parent.document).scrollTop from iFrame and SOPJquery 从 iFrame 和 SOP 访问 $(parent.document).scrollTop
【发布时间】:2014-07-09 14:22:00
【问题描述】:

我正在尝试使用下面显示的代码从带有 src= http://www.domain.com/folder/ 的 iFrame 中访问 scrollTop 值,而包含 iFrame 的页面位于 http://sub-domain.domain.com/another-folder/,但出现以下错误:

var stopval = $(parent.document).scrollTop();

错误:

Error: Blocked a frame with origin "http://www.domain.com" from accessing a cross-origin frame.

显然这是一个 SOP 问题,所以想知道是否有任何变通方法...解决此问题的方法?我在网上搜索过,但找不到从 iFrame 页面获取 scrollTop 值而不收到此错误的解决方案。谢谢

【问题讨论】:

标签: javascript jquery html iframe


【解决方案1】:

fgshepard 提到的问题可以使用window.postmessage 解决如下:

A.在带有 src= http://www.domain.com/folder/ 的 iFrame 中添加:

<script type="text/javascript">
    window.addEventListener("message", listener, false);
    function listener(event){    
      if ( event.origin !== "http://sub-domain.domain.com" )
        return
        console.log('Message Received : '+event.data);
      }
</script>

B.在包含 http://sub-domain.domain.com/another-folder/ 的 iframe 的页面中,添加:

<script type="text/javascript">
      var win = document.getElementById("iframeid").contentWindow;
      $(window).scroll(function(){
          var wintop = $(window).scrollTop();
          win.postMessage($(window).scrollTop(), 'http://domain.com');              
      });
</script>

上述代码应将包含 iframe 的页面的 scrollTop() 值发送到 iframe src 页面。

【讨论】:

  • 我现在明白你的要求了。很高兴这有效。
【解决方案2】:

我认为您的回答主要是解释here。您可以将document.domain的值设置为当前域的后缀。

如果您的页面是 http://sub-domain.domain.com/another-folder/ 并且您会尝试 Iframe http://www.domain.com/folder/,那么以下代码应该可以帮助您:document.domain = 'domain.com'

你的情况完全相反。您的页面是 http://www.domain.com/folder/,正在评估来自 http://sub-domain.domain.com/another-folder/ 的 iframe 内容。但看起来你不能这样做 document.domain = 'sub-domain.domain.com' 因为它不是你当前域的后缀(但请尝试)。

【讨论】:

【解决方案3】:

scrollTo() 控制垂直和水平位置。希望这可能有用

parent.scrollTo(0, 0);

【讨论】:

    【解决方案4】:

    如果您可以控制这两个位置的文档,则可以为此目的使用window.postMessage。这允许您在文档之间和跨域传递消息,并且还提供一定程度的安全性。例如,在这种情况下,当您需要从父窗口中获取 scrollTop 值时,您可以向其发送消息:

    parentWindow.postMessage('scrollTop', targetOrigin, [...]);
    

    父窗口会有一个消息监听器,可以用信息响应:

    window.addEventListener("message", receiveMessage, false);
    
    function receiveMessage(event) {
        var response = null;
        if (event.origin !== "http://example.org:8080") {
            return;
        }
        if (event.data === 'scrollTop') {
            response = $(document).scrollTop();
            childWindow.postMessage(response, targetOrigin, [...]);
            return response;
        }
        return false;
    }
    

    子窗口也会有一个监听器:

    window.addEventListener("message", receiveMessage, false);
    

    receiveMessage 函数将使用接收到的信息。

    如果您想要更通用的解决方案,您的父窗口的 receiveMessage 函数可以简单地响应以下结果:

    response = $(document)[message]();
    

    其中 message 将包含您有兴趣接收的任何 jQuery 调用。当然,可以进行进一步的抽象。

    【讨论】:

    • 我刚刚尝试了您的示例,但没有成功。我得到的第一个错误是 childWindow 没有定义。请问可以提供更完整的例子吗?稍微注意一下,消息应该从父页面(包含 iframe)发送到 iframe 加载的页面,反之亦然。谢谢
    • childWindow 只是窗口的示例名称。您需要使用您在代码中建立的引用。由于您没有提供任何实际代码,因此我无权访问您的变量名。父窗口也是如此。 PS Downvoting 对我来说似乎有点激进。
    • 我的示例使用双向通信——它是双向的。孩子问,父母回应。
    • 据我所知,SO 中的大多数答案都带有 JsFiddle 示例或详细解释/示例......我在您的答案中都没有找到。然而,感谢您的简短回复,但这对我的问题并没有太大帮助,因为即使按照您的方法,我仍然面临问题中描述的 SOP 问题。
    • postMessage 将解决您的 SOP 问题,只要您可以控制这两个文档(只要您可以在其中插入必要的代码)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    相关资源
    最近更新 更多