jQuery拖动选择,约束到元素,而不是典型的拖动框

时间:2012-06-23 10:00:55

标签: jquery drag-and-drop

我想使用拖动来选择要素,而不是选择屏幕上的方形区域,并选择该方块内的任何内容,我想选择我的初始选择和我发布点击之间的任何元素。< / p>

最佳视觉解释。我想要这样做:

What I don't want to do

相反,我想这样做:

What I want to do

3 个答案:

答案 0 :(得分:3)

如果你的盒子在列表结构(ul或ol)中,你可以检测到鼠标被拖过的第一个和最后一个盒子,并使用它们的标识符作为第一个和最后一个索引来迭代整个集合,以便在必要时突出显示。 / p>

答案 1 :(得分:1)

在上一次尝试失败之后,我现在想出了一个有效的解决方案。似乎jQuery UI selectable不合适,因为它使用了矩形选择,所以我不得不自己动手。

在下面的示例中(有关完整代码,请参阅jsFiddle),可选元素为a.date。这些元素应设置为position: relative

首先,我添加了一个带有.drag-proxy类的子元素。这绝对定位,并覆盖与孩子相同的区域。它没有任何内容,所以它透明地位于上方。

这些代理元素是可拖动和可放置的。

当元素被拖放到另一个元素上时,它会移回到它的起始点(以便后续选择工作)。

然后我们循环遍历所有代理元素,识别选择范围中的元素,然后在父a.date元素上设置一个类。

$(function() {
  $('a.date').each(function() {
  $(this).append('<a href="' + $(this).attr('href') + '" class="drag-proxy" id="proxy_' + $(this).attr('id') + '"></a>');
  });

  var $currentlyDragged;

  $('.drag-proxy').draggable({
    start: function() {
      $currentlyDragged = $(this);
    },
    // Once drag has finished, return the drag-proxy to its original position
    stop: function() { 
      $(this).css('top', 0).css('left', 0);
      $currentlyDragged = null;
    }
  });

  $('.drag-proxy').droppable({
    over: function(e, ui) {
      var from_id = $currentlyDragged.attr('id');
      var to_id = $(this).attr('id');

      $('.date').removeClass('selected');

      var started = selecting = false;
      $('.drag-proxy').each(function() {
        var $this = $(this);
        var this_id = $this.attr('id');
        if (started === false && (this_id == from_id || this_id == to_id)) {
          selecting = true;
        }
        if (selecting) {
          $this.parent().addClass('selected');
          if (started === true && (this_id == from_id || this_id == to_id)) {
            selecting = false;
          }
        }
        if (started === false && (this_id == from_id || this_id == to_id)) {
          started = true;
        }
      });
    },

    drop: function(e, ui) {
      // do whatever you need to do once selection ends
    }
  });


});
​

有关完整示例,请参阅jsFiddle

答案 2 :(得分:0)

请注意 - 这个答案是不正确的,但是我要离开它,因为它显示了jQuery UI可以选择的程度,以及为什么它不起作用。请参阅已接受的答案,了解自定义工作解决方案。

感谢FrédéricHamidi指向this forum thread的指针,我已经解决了这个问题,如下所示。我在问题中未提及的其他要求是,可选元素必须位于多个容器中(最终这将是日历中的日期,包含在各个月中)。

给出以下HTML:

<div id="selectable">
  <div>
    <span id="a1">1</span>
    <span id="a2">2</span>
    <span id="a3">3</span>
    <span id="a4">4</span>
    <span id="a5">5</span>
    <span id="a6">6</span>
    <span id="a7">7</span>
    <span id="a8">8</span>
    <span id="a9">9</span>
    <span id="a10">10</span>
  </div>

  <div>
    <span id="b1">1</span>
    <span id="b2">2</span>
    <span id="b3">3</span>
    <span id="b4">4</span>
    <span id="b5">5</span>
    <span id="b6">6</span>
    <span id="b7">7</span>
    <span id="b8">8</span>
    <span id="b9">9</span>
    <span id="b10">10</span>
  </div>
</div>

然后这个javascript解决了它。请注意,链接的帖子使用slice(start, end)但由于我的多个容器要求,我不能这样做。所以我使用each()循环遍历所有可排序元素,并根据我们是否已达到第一个元素并且尚未到达最后一个元素来切换selecting

我设置filter: 'span'是为了防止#selectable的其他子元素变为可选。

$(function() {
  var rangeSelecting = function(event, ui) {
    var start = $(".ui-selecting", this).first();
    var end = $(".ui-selecting", this).last();
    var selecting = false;
    $(this).find('span').removeClass("range-selecting").each(function() {
      var $this = $(this);
      var this_id = $this.attr('id');
      if (start.attr('id') === this_id) selecting = true;
      if (selecting) $this.addClass('range-selecting');
      if (end.attr('id') === this_id) selecting = false;
    });
  }
  $("#selectable").selectable({
    filter: 'span',
    selecting: rangeSelecting, 
    unselecting: rangeSelecting,
    stop: function(event, ui) { $(".range-selecting", this).addClass("ui-selected").removeClass("range-selecting"); }
  });

});

有关工作示例,请参阅此jsfiddle