【问题标题】:Dragging rows between tables在表格之间拖动行
【发布时间】:2015-01-18 20:08:57
【问题描述】:

这个想法很简单,几乎可以奏效。有两个表,用户可以选择在两个表之间拖动行。当将一行从 table1 拖到 table2 时,使用 ajax 以使用从 table1 中删除、添加到 table2 的数据更新数据库,并使用新数据重新显示两个表。如果将信息从表 2 拖到表 1,则同样的操作。

您可以查看代码示例here

以下是其中一张表的 Javascript 代码摘录:

var startTable = "table1";
var $tabs=$("#" + startTable);
$( "tbody.connectedSortable")
.sortable({
    connectWith: ".connectedSortable",
    items: "> tr:not(:first)",
    appendTo: $tabs,
    helper:"clone",
    cursor:"move",
    zIndex: 999990
})
.disableSelection()
;
$($tabs).droppable({
    accept: ".connectedSortable tr",
    hoverClass: "ui-state-hover",
    drop:function(event, ui){
        var start= ui.draggable.attr("id");
        var desTable = $(this).attr("id");
        if(start != desTable){
            alert("The ajax should be called");
        }
        return false;
    }
});

除了一种情况外,它工作得很好。如果将一行从 Table1 拖到 Table2,它会创建一个槽来显示当该行被放开时该行将插入的位置。换句话说,如果用户将一行从 Table1 拖到 Table2 的最后一个元素,它会创建一个开放的占位符(在 Table2 的最后一行下方)来描述放开时该行的位置。这有一个问题。如果创建了占位符,但随后将行拖到表格外并放开,则行仍会转到占位符,但从不调用 draggable 属性。

我希望发生的情况是,如果创建了一个占位符,无论该行在哪里放开,它都会转到占位符并调用与它所在的表对应的可放置代码。如果不存在占位符,则该行应该返回到它被拖动的位置,并且不会发生任何事情。

我尝试过的在两个表之间拖动行的每个示例都有相同的问题。即使将行删除到表外,你们有什么方法可以调用可删除代码吗?或者也许有更好的方法来调用 ajax 而不是将行放在表上?任何见解将不胜感激。

【问题讨论】:

  • 你可以在 sortable 中使用 update 事件而不是 drop 事件。
  • 如果就这么简单,那就太棒了。我将在大约一个小时内完成它,然后将结果发回。谢谢。
  • 更新事件看起来像我要找的。我将代码更改为使用更新,但遇到了一个错误。永远不会调用来自 table1 的更新,只调用来自 table2 的更新。另外,如果我从 table1 拖动到 table2,table2 更新会被调用两次。这是小提琴:jsfiddle.net/bhealy/t011juda/28 知道发生了什么吗?
  • 您对同一标识符 ($("tbody.connectedSortable")) 应用了两次可排序函数。一个应该用于table1,另一个应该用于table2。检查这个小提琴jsfiddle.net/t011juda/35

标签: javascript jquery-ui jquery-ui-draggable jquery-ui-sortable jquery-ui-droppable


【解决方案1】:

要在将行从一个表删除到另一个表时触发 ajax 请求,您可以使用 sortable 小部件的 receive 事件。

当已连接的可排序列表中的项目被放入另一个列表时触发此事件。后者是事件目标。

强调我的

Updated Fiddle部分结果,最终演示请参见下面的 sn-p

在接收回调中,您可以使用第二个参数 (ui.item) 的 item 属性访问已删除的行。

如果触发了接收事件回调,则表示ui.item已添加到this表($(this).closest("table.mytable"))并从另一个表($("table.mytable").not($(this).closest("table.mytable")))中删除。然后,您可以相应地触发 ajax 请求。

通过这种方式,您不必手动检查 drop 是否发生在同一个表中(如果您按照某人的建议使用 update 事件,则必须这样做)。


目前,您不必要地使用以下命令初始化可排序两次:

$( "tbody.connectedSortable").sortable({
    connectWith: ".connectedSortable",
    items: "> tr:not(:first)",
    appendTo: $tabs,
    helper:"clone",
    cursor:"move",
    zIndex: 999990
})

$("tbody.connectedSortable").sortable({
    connectWith: ".connectedSortable",
    items: "> tr:not(:first)",
    appendTo: $tabs2,
    helper:"clone",
    cursor:"move",
    zIndex: 999990
});

选择器tbody.connectedSortable 适用于两个表,因此它会简单地覆盖先前的初始化,因此,克隆助手将始终附加到第二个表($tabs2)。这可能不是您想要的 - 从外观上看,您初始化两次只是为了将克隆附加到相应的父级。 appendTo 选项的默认值为"parent",只需将其从初始化中删除即可。

此外,将标题行从 <tbody> 移动到 <thead> 元素是一个好主意,这样您就可以避免指定 items: "> tr:not(:first)" :因为 jQuery UI 没有如果未指定该选项,则不必搜索无效项目。

最后,您复制了无效的id。要对一组元素进行分组,请改用公共类。


$(document).ready(function() {
  $("tbody.connectedSortable").sortable({
    connectWith: ".connectedSortable",
    helper: "clone",
    cursor: "move",
    zIndex: 99999,
    receive: function(event, ui) {
      /* here you can access the dragged row via ui.item
         ui.item has been removed from the other table, and added to "this" table
      */
      var addedTo = $(this).closest("table.mytable"),
        removedFrom = $("table.mytable").not(addedTo);
      alert("The ajax should be called for adding to " + addedTo.attr("id") + " and removing from " + removedFrom.attr("id"));
    }
  });
});
.mytable a:link,
.mytable a:visited {
  color: #fff;
  font-weight: bold;
  text-decoration: none;
}
.mytable a:active,
.mytable a:hover {
  color: #bd5a35;
  text-decoration: underline;
}
table.mytable {
  width: 90%;
  font-family: Arial, Helvetica, sans-serif;
  color: #666;
  margin-left: auto;
  margin-right: auto;
  font-size: 12px;
  background: #eaebec;
  border: #ccc 1px solid;
  -moz-border-radius: 3px;
  -webkit-border-radius: 3px;
  border-radius: 3px;
  -moz-box-shadow: 10px 10px 5px #888;
  -webkit-box-shadow: 10px 10px 5px #888;
  box-shadow: 10px 10px 5px #888;
}
.mytable th {
  color: #fff;
  padding: 21px 25px 22px 25px;
  border-top: 1px solid #fafafa;
  border-bottom: 1px solid #e0e0e0;
  background: #191970;
}
.mytable th:first-child {
  text-align: center;
  padding-left: 20px;
}
.mytable tr {
  text-align: center;
  padding-left: 20px;
}
.mytable tr td:first-child {
  text-align: center;
  padding-left: 20px;
  border-left: 0;
}
.mytable tr td {
  padding: 18px;
  border-top: 1px solid #ffffff;
  border-bottom: 1px solid #e0e0e0;
  border-left: 1px solid #e0e0e0;
  background: #fafafa;
  background: -webkit-gradient(linear, left top, left bottom, from(#fbfbfb), to(#fafa fa));
  background: -moz-linear-gradient(top, #fbfbfb, #fafafa);
}
.mytable tr.even td {
  background: #f6f6f6;
  background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#f6f6 f6));
  background: -moz-linear-gradient(top, #f8f8f8, #f6f6f6);
}
.mytable tr:last-child td {
  border-bottom: 0;
}
.mytable tr:last-child td:first-child {
  -moz-border-radius-bottom-left: 3px;
  -webkit-border-bottom-left-radius: 3px;
  border-bottom-left-radius: 3px;
}
.mytable tr:last-child td:last-child {
  -moz-border-radius-bottom-right: 3px;
  -webkit-border-bottom-right-radius: 3px;
  border-bottom-right-radius: 3px;
}
.mytable tr:hover td {
  background: #f2f2f2;
  transform: scale(1.01);
  padding-left: 20px;
  outline: 1px solid #191970;
  -moz-box-shadow: 10px 10px 5px #888;
  -webkit-box-shadow: 10px 10px 5px #888;
  box-shadow: 10px 10px 5px #888;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<table id='table1' class="mytable">
  <thead>
    <tr class="table1">
      <th>col1</th>
      <th>col2</th>
      <th>col3</th>
      <th>col4</th>
    </tr>
  </thead>

  <tbody class="connectedSortable">

    <tr class="table1">
      <td>a</td>
      <td>b</td>
      <td>c</td>
      <td>d</td>
    </tr>
    <tr class="table1">
      <td>e</td>
      <td>f</td>
      <td>g</td>
      <td>h</td>
    </tr>
  </tbody>
</table>
<table id='table2' class="mytable">
  <thead>
    <tr class="table2">
      <th>COL1</th>
      <th>COL2</th>
      <th>COL3</th>
      <th>COL4</th>
    </tr>
  </thead>
  <tbody class="connectedSortable">

    <tr class="table2">
      <td>1</td>
      <td>2</td>
      <td>3</td>
      <td>4</td>
    </tr>
    <tr class="table2">
      <td>5</td>
      <td>6</td>
      <td>7</td>
      <td>8</td>
    </tr>
  </tbody>
</table>

旁注:我已经组合了类似的 CSS 类

disableselection() 方法已从 jQuery UI 1.9+ 中弃用

【讨论】:

  • 我真的很喜欢这个实现并感谢您为它付出的努力,但我遇到了一个问题。代码完成的方式是我有一个引用 ajax 文件来创建表的主 php 文件:一个 onload 和另一个 onclick。 ajax 文件似乎无法找到可排序函数(写入主文件中),因为表不可拖动。但是,如果这些表是在主文件中手动创建为 html 的(而不是使用任何 ajax),那么代码就可以工作。有什么想法吗?
  • @Brian 我不太明白您所说的“ajax 文件”是什么意思,但是如果您要动态创建一个全新的表,则必须在创建后将它们初始化为可排序文件,事实上您将旧表初始化为可排序不会自动使新表可排序。如果您正在谈论不被识别为可排序项目的新行,请查看refresh。如果您在谈论其他不适用于动态创建的元素的内容,则可能是event delegation 问题。
  • 在您的帮助下,我很确定我已经成功地正确实施了一切。谢谢=)
  • 嗨@TJ,你有角度的解决方案吗?
【解决方案2】:

我认为这个小提琴可以满足您的需求:http://jsfiddle.net/t011juda/31/

$(document).ready(function () {
    var startTable = "table1";
    var $tabs = $("#" + startTable);
    $("tbody.connectedSortable")
            .sortable({
                connectWith: ".connectedSortable",
                items: "> tr:not(:first)",
                appendTo: $tabs,
                helper: "clone",
                cursor: "move",
                zIndex: 999990,
                start: function (event, ui) {
                    //alert("start1");
                    var start_pos = ui.item.index();
                    ui.item.data('start_pos', start_pos);
                }

            });

    var startTable2 = "table2";
    var $tabs2 = $("#" + startTable2);

$("tbody.connectedSortable")
        .sortable({
            connectWith: ".connectedSortable",
            items: "> tr:not(:first)",
            appendTo: $tabs,
            helper: "clone",
            cursor: "move",
            zIndex: 999990,
            start: function (event, ui) {
                //alert("start2");
                var start_pos = ui.item.index();
                ui.item.data('start_pos', start_pos);
                //alert(start_pos);
            },
            update: function (event, ui) {
                if (this.id == 'table2' && this === ui.item.parent()[0] )
                    alert("update2");
                else if (this.id == 'table1' && this === ui.item.parent()[0] )
                    alert("update1");
            }
        });
    });

其实list更新两次的解释在这里:jquery Sortable connectWith calls the update method twice

请注意,table1table2 的 ID 重复了。我已删除重复的 ID,并将其中一个移至 &lt;tbody&gt;

另请注意,`update 以两种方式处理 D&D

【讨论】:

  • 谢谢!我有一个问题,如果您想从选择中排除第一项,该怎么办?我看到 "items: "> tr:not(:first)" " 排除了第一行,但我无法排除前两行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-09
  • 1970-01-01
  • 2011-04-20
  • 2011-03-21
  • 2014-10-16
相关资源
最近更新 更多