【问题标题】:Refresh draggable containment刷新可拖动容器
【发布时间】:2010-07-19 01:07:07
【问题描述】:

我有一个将包含设置为父级的可拖动元素。这很好用,但 div 内容可以改变使其更高。无论如何都会触发拖动事件,以确保它不会从其父级内部移动。就目前而言,它可以与父级重叠,直到它被拖动,然后遏制开始。

最好的问候 标记

【问题讨论】:

    标签: jquery jquery-ui


    【解决方案1】:

    我已经实现了一个小插件,可以满足您的需求。它可以在可拖动对象更改大小后强制执行包含,甚至在您处于拖动过程中时也可以工作。我已经使用 jQuery UI 1.8.6 和 jQuery 1.4.3 对其进行了测试,但它可能会与过去或未来的版本中断,因为它必须使用内部方法。

    工作演示

    http://jsbin.com/uvino4/27

    完整来源

    插件

    /*
     * jQuery UI RefreshContainment v0.1
     *
     * A plugin for jQuery UI's Draggable. It adds a refreshContainment method to
     * every draggable which allows you to use the containment option on draggables
     * with dynamically changing sizes.
     *
     * Depends:
     *  jquery.ui.core.js
     *  jquery.ui.widget.js
     *  jquery.ui.mouse.js
     *  jquery.ui.draggable.js
     */
    
    (function ($){
      var $window = $(window);
    
      // We need to know the location of the mouse so that we can use it to
      // refresh the containment at any time.
    
      $window.data("refreshContainment", {mousePosition: {pageX: 0, pageY: 0}});
      $window.mousemove(function (event) {
        $window.data("refreshContainment", {
          mousePosition: {pageX: event.pageX, pageY: event.pageY}
        });
      });
    
      // Extend draggable with the proxy pattern.
      var proxied = $.fn.draggable;
      $.fn.draggable = (function (method){
        if (method === "refreshContainment") {
          this.each(function (){
            var inst = $(this).data("draggable");
    
            // Check if the draggable is already being dragged.
            var isDragging = inst.helper && inst.helper.is(".ui-draggable-dragging");
    
            // We are going to use the existing _mouseStart method to take care of
            // refreshing the containtment but, since we don't actually intend to
            // emulate a true _mouseStart, we have to avoid any extraneous
            // operations like the drag/drop manager and event triggering.
            // So we save the original member values and replace them with dummies.
            var ddmanager = $.ui.ddmanager;
            $.ui.ddmanager = null;
            var trigger = inst._trigger;
            inst._trigger = function () { return true; }
    
    
            var mousePosition = $window.data("refreshContainment").mousePosition;
            var fakeEvent = {
              pageX: mousePosition.pageX, pageY: mousePosition.pageY
            };
            inst._mouseStart(fakeEvent);
    
            // Return those extraneous members back to the original values.
            inst._trigger = trigger;
            $.ui.ddmanager = ddmanager;
    
            // Clear the drag, unless it was already being dragged.
            if (!isDragging) {
              inst._clear();
            }
          });
          return this;
        }
        else {
          // Delegate all other calls to the actual draggable implemenation.
          return proxied.apply(this, arguments);
        }
      });
    })(jQuery);
    

    演示 HTML

    <!DOCTYPE html>
    <html>
    <head>
    <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script>
    <meta charset=utf-8 />
    <title>JS Bin</title>
    
    <style>
      #container { width: 20em; height: 20em; border: 0.5em solid black; }
      .draggable { width: 5em; height: 5em; border: 0.2em solid black; position: absolute; }
      #one { background-color: #F55; }
      #two { background-color: #5F5; }
    </style>
    </head>
    <body>
      <div id="container">
        <div class="draggable" id="one">drag me</div>
        <div class="draggable" id="two">drag me</div>
      </div>
    </body>
    </html>
    

    演示 JavaScript

    var draggables = $('.draggable');
    
    draggables.draggable({containment: 'parent', stack: draggables});
    
    var resizeDraggables = function (){
      draggables.
        each(function (){
          var size = 5 + Math.random() * 5;
          size = size.toString() + "em";
          $(this).css({width: size, height: size});
        }).
        draggable("refreshContainment");
    };
    
    resizeDraggables();
    
    setInterval(resizeDraggables, 2000);
    

    【讨论】:

    • 稍作修改,防止鼠标悬停时出现错误:jsbin.com/uvino4/5/edit
    • @ChrisvandeSteeg 感谢您的修复!
    • 很好,布莱恩。为了让它工作,我必须做的一件事是将“mousemove”侦听器的 $(window) 更改为 $(document)。在某些浏览器(在我的情况下为 IE8)中,“mousemove”不会在“窗口”上触发。改用 document 将适用于所有浏览器。
    • 对于较新版本的 jQueryUI,将第 33 行的 data('draggable') 替换为 data('uiDraggable')
    【解决方案2】:

    这行得通吗?

    $("#yourcontainment").bind("resizestop", function () {
      $(".yourdraggables").draggable("option", "containment", $("#yourcontainment"));
    });
    

    如果你不使用 jQuery UI 的 resizable,你必须触发“resizestop”事件。

    【讨论】:

    • 谢谢!还值得注意的是,要使其正常工作,收容元素显然必须是实际元素。如果你有包含:“父”,即使 $(".yourdraggables") 选择器将包含父元素,这也不起作用。
    【解决方案3】:

    因为您正在修改 [contained] 元素的大小,所以您必须为结果实现自己的处理程序。 jQuery 知道在拖动期间要做什么,但是在 resize 期间有 许多 可能的行为:

    • 防止调整包含的大小
    • element 移动内部元素 (哪个方向)
    • 删除元素

    人们可以想象一系列针对不同 UI 约束的虚构场景。

    只需为所包含类的所有对象创建一个 PostionValidator() 方法,调用修改方法后执行即可。

    【讨论】:

      猜你喜欢
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-29
      • 2013-07-30
      • 1970-01-01
      • 2013-03-19
      • 1970-01-01
      相关资源
      最近更新 更多