jquery droppable iframe offset

时间:2013-12-08 10:27:41

标签: jquery iframe knockout.js

我正在尝试使用knockout将html绑定到iframe。

主页面包含一个可拖动的页面,iframe包含一个droppable。我遇到的问题是该物品在错误的地方掉落,例如:

绿色是我希望掉落的地方,但是红色是实际出现下降的位置 - 它似乎位于正确的坐标处,但没有考虑主页面上的iframes位置。 green - where I would like to drop, red - actual drop

我尝试将iframefix应用于draggable和droppable,但它没有帮助:

iframe.find('.sim-row').droppable({
      iframeFix: true,
      drop: function (event, ui) {
           console.log("dropped");
      }
});

$('#drag').draggable({
     iframeFix: true,
     helper: "clone"
});

有人想知道是否有一些基于iframes位置创建'偏移'并将其传递给draggable以便它可以计算出它的位置?

一些小提琴: 主页 - http://jsfiddle.net/D26CQ/1/

iFrame - http://jsfiddle.net/cMfMq/

5 个答案:

答案 0 :(得分:7)

我能找到的最简单的解决方案是修改jqueryUI可拖动函数以考虑偏移量:

$ .ui.ddmanager函数中的

添加以下行:

        m[i].offset.top -= m[i].element.parents().find("html,body").scrollTop();
        m[i].offset.left -= m[i].element.parents().find("html,body").scrollLeft();

        // iframe positioning 
        if (this.current.options.iframeOffset) {
            m[i].offset.top += this.current.options.iframeOffset.top;
            m[i].offset.left += this.current.options.iframeOffset.left;
        }

就在之前:

        m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };

答案 1 :(得分:2)

我无法发表评论,但是...... @ kiwijus的回答对我们来说非常合适。丢失的一个文档是在调用draggable时必须指定iframeOffset。

$('.your-draggable-content').draggable({
        helper: "clone",
        iframeFix: true,
        iframeOffset: $('#your-iframe').offset()
 });

答案 2 :(得分:1)

我在bootstrap中使用iframe时遇到了类似的问题,我通过修改droppable类来修复iframe并存储对它的引用并更新了交叉函数来检测拖拽何时在iframe上并调整相交以匹配iframe的滚动和偏移。

在这里演示:https://dl.dropboxusercontent.com/u/10953135/droppable/index.html

经过测试:Chrome,Firefox和IE10

请参阅以下内容以了解我的更改。

提交

https://github.com/Azerothian/jquery-ui/commit/57456ff345fbd119b63524df2e2ede72502dcf9a

DIFF

@@ -53,7 +53,20 @@ $.widget( "ui.droppable", {

        this.isover = false;
        this.isout = true;
 -
 +      if(o.iframeFix)
 +      {
 +          windowTest = this.window.length && this.window.length > 0 ? this.window[0] : this.window;
 +          if(windowTest !== undefined && windowTest !== null)
 +          {
 +              this.iframe = windowTest.frameElement
 +              if(this.iframe === undefined || this.iframe === null)
 +              {
 +                  throw "[Droppable] You are specifing iframe fix for a object that does not exist inside a iframe";
 +              }
 +          } else {
 +              throw "[IframeFix] Window is not defined.. lets blow up because we are unable to find the iframe.";
 +          }
 +      }
        this.accept = $.isFunction( accept ) ? accept : function( d ) {
            return d.is( accept );
        };
 @@ -244,6 +257,25 @@ $.ui.intersect = (function() {
            t = droppable.offset.top,
            r = l + droppable.proportions().width,
            b = t + droppable.proportions().height;
 +   
 +      if (droppable.options.iframeFix)
 +      {
 +        var iframeOffset = $(droppable.iframe).offset(),
 +              iframeWidth = $(droppable.iframe).width(),
 +              iframeHeight = $(droppable.iframe).height(),
 +              iframeScrollTop = $(droppable.iframe).contents().scrollTop(),
 +              iframeScrollLeft = $(droppable.iframe).contents().scrollLeft();
 +        
 +          if (y1 < iframeOffset.top || x1 < iframeOffset.left || x1 + draggable.helperProportions.width > iframeOffset.left + iframeWidth || y1 + draggable.helperProportions.height > iframeOffset.top + iframeHeight) // outside iframe;
 +          {
 +          return false;
 +          }
 +          l = (iframeOffset.left + droppable.offset.left) - iframeScrollLeft;
 +          r = l + droppable.proportions().width;
 +          t = (iframeOffset.top + droppable.offset.top) - iframeScrollTop;
 +          b = t + droppable.proportions().height;
 +      }
 +

        switch ( toleranceMode ) {
        case "fit":

答案 3 :(得分:0)

此代码对我有用

 $.ui.ddmanager.frameOffsets = {};

    // Override the native `prepareOffsets` method. This is almost
    // identical to the un-edited method, except for the last part!
    $.ui.ddmanager.prepareOffsets = function (t, event) {
        var i, j,
            m = $.ui.ddmanager.droppables[t.options.scope] || [],
            type = event ? event.type : null, // workaround for #2317
            list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(),
            doc, frameOffset;

        droppablesLoop: for (i = 0; i < m.length; i++) {

            //No disabled and non-accepted
            if (m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0], (t.currentItem || t.element)))) {
                continue;
            }

            // Filter out elements in the current dragoged item
            for (j = 0; j < list.length; j++) {
                if (list[j] === m[i].element[0]) {
                    m[i].proportions().height = 0;
                    continue droppablesLoop;
                }
            }

            m[i].visible = m[i].element.css("display") !== "none";
            if (!m[i].visible) {
                continue;
            }

            //Activate the droppable if used directly from draggables
            if (type === "mousedown") {
                m[i]._activate.call(m[i], event);
            }

            // Re-calculate offset
            m[i].offset = m[i].element.offset();

            // Re-calculate proportions (jQuery UI ~1.10 introduced a `proportions` cache method, so support both here!)
            proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
            typeof m[i].proportions === 'function' ? m[i].proportions(proportions) : (m[i].proportions = proportions);

            /* ============ Here comes the fun bit! =============== */

            // If the element is within an another document...
            if ((doc = m[i].document[0]) !== document) {
                // Determine in the frame offset using cached offset (if already calculated)
                frameOffset = $.ui.ddmanager.frameOffsets[doc];
                if (!frameOffset) {
                    // Calculate and cache the offset in our new `$.ui.ddmanager.frameOffsets` object
                    frameOffset = $.ui.ddmanager.frameOffsets[doc] = $(
                        // Different browsers store it on different properties (IE...)
                        (doc.defaultView || doc.parentWindow).frameElement
                    ).offset();
                }

                // Add the frame offset to the calculated offset
                m[i].offset.left += frameOffset.left;
                m[i].offset.top += frameOffset.top;
            }
        }
    };

答案 4 :(得分:-1)

我找到的最佳解决方案是在这里:http://maxazan.github.io/jquery-ui-droppable-iframe/

只需链接js文件,它就可以绝对完美地工作