jQuery可拖拽处理程序在IFrame内部

7

这真是有点拗口。

基本上,我有一个父级<div>,里面包含一个<iframe>。 我需要一个位于 iframe 内部的元素来拖动父 div。 这个可能吗?

我尝试过:

$(node).draggable("option","handle",$('iframe',node).contents().find('#handle'));
$(node).draggable("option","handle",$('iframe',node).contents().find('#handle')[0]);

它的目标是正确的DOM元素,但它就是无法拖动。也许可以在iframe上覆盖一个隐藏的div,但我发现当位置为absolute时,iframe会接管div的事件。奇怪。


使用 iFrameFix 进行拖动对我来说仍然很卡顿。如果对话框是可接受的解决方案,则效果更好。它仍然可以被拖动,但也可以关闭。 - user420667
3个回答

9

试试这个

$('#Div').draggable({ iframeFix: true });

这应该可以工作


7
我决定尝试一下,使用内部iframe节点作为句柄时,进展很少,工作量也很大。无论如何,这里有两个解决方案,第一个并不是很好用,但如果您能让它正常运行,可能更理想。
main.html(从演示中抄袭)
<div id="draggable" class="ui-widget-content" style="position:relative;">
    <p class="ui-widget-header">I can be dragged only by this handle</p>
    <iframe name="iframe1" src="inner-handle.html" height=50 width=80></iframe>
</div>

inner-handle.html

<html>
    <head>
        <script type="text/javascript" src="../../jquery-1.4.2.js"></script>
    </head>
    <body>
        <div id="innerHandle">handle</div>
    </body>
</html>

JavaScript

$(function () {
    var moveEvent;
    $(document).mousemove(function (e) {
        moveEvent = e;
    });

    $("#draggable").draggable();
    $('iframe', '#draggable').load(function () {
        $('iframe', '#draggable')[0].contentWindow.$('#innerHandle').mousedown(function (e) {
            $('#draggable').draggable().data('draggable')._mouseDown(moveEvent);
            return false;
        });
    });
});

我找了一段时间才找到一些“可行”的东西。问题在于,由于mousedown事件发生在iframe内的一个元素上,鼠标事件是相对于iframe而不是主文档的。解决方法是在文档上有一个移动事件,并从那里获取鼠标位置。问题又来了,如果鼠标在iframe内部,则根据父文档,“它”并没有移动。这意味着只有当鼠标到达iframe边缘进入父文档时,拖动事件才会发生。
其中的一种解决方法可能是手动生成带有iframe相对其鼠标移动的计算位置的事件。因此,当鼠标在iframe内移动时,使用iframe到父文档的坐标计算其移动。这意味着您需要使用mousedown事件而不是mousemove事件的事件。
$('iframe', '#draggable')[0].contentWindow.$('#innerHandle').mousedown(function (e) {
    // do something with e
    $('#draggable').draggable().data('draggable')._mouseDown(e);
    return false;
});

第二种解决方案是您提到的方式,即在 iframe 上方放置一个绝对定位的 div。我没有问题让 div 在 iframe 的上方,也就是说:
<div id="draggable" class="ui-widget-content" style="position:relative;">
    <p class="ui-widget-header">I can be dragged only by this handle</p>
    <iframe name="iframe1" src="inner-handle.html" height=50 width=80></iframe>
    <div style="position: absolute; height: 30px; width: 30px; background-color: black; z-index: 1000;"></div>
</div>
您的div在iframe后面可能是因为z-index设置不正确。如果您在iframe前声明了div并且没有指定z-index,则iframe将位于顶部。
无论您选择哪种方式,祝您好运!

哇,谢谢你的辛勤工作。我想我会尝试第二个解决方案。我认为第一个会有太多漏洞。非常感谢! - Louis
我想基于这个解决方案进行构建。由于简单性,我最终选择了选项2。然而,我注意到当我的鼠标进入iframe(超出绝对定位的“手柄”)时,我会失去自由拖动的能力。我发现的一个可行的解决方案是在单击“手柄”和释放鼠标时,删除并添加指针事件到iframe中。我从https://stackoverflow.com/a/42391645/12853985得到了灵感。 这使得行为感觉非常好,而且只需要几行代码! - Zen

0

当您激活firebug时,会发生什么:

var frameContent = $('iframe',node).contents()
var handle = frameContent.find('#handle');
console.debug(frameContent, handle)

handle 是否包含元素列表?如果是的话,请仔细查看 Document 对象,即 frameContent - URL 是否为 "about:blank"?这只是一个猜测,但如果您得到这些输出,它可能在框架内容加载之前执行了 jQuery 选择器(即在 #handle 元素存在之前)。

在这种情况下,您可以向 IFRAME 的文档添加事件,并通过 window.parent 与父框架通信。


现在无法测试,所以我会尽快尝试,但我正在更改iframe中window.onload的选项,因此我认为它已经准备好了。当我记录找到的内容时,它是正确的DOM元素。也许这只是不可能的。 - Louis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接