HTML5 可拖动列表 - 多个 setData?
HTML5 Draggable List - multiple setData?
所以,我有一个要组织成 运行 顺序的波段列表,如下所示:
<li data-band-id='1' draggable='true' class='band-name'>Metallica</li>
<li data-band-id='2' draggable='true' class='band-name'>Slayer</li>
<li data-band-id='3' draggable='true' class='band-name'>Paradise Lost</li>
<li data-band-id='4' draggable='true' class='band-name'>Gojira</li>
我希望能够拖动这些列表项来更改整个列表中每个波段的位置。到目前为止,我有以下 JavaScript 来执行此操作:
var dragSatMS = null;
function handleDragStart(e) {
//this.style.color = 'green';
dragSatMS = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text', this.innerHTML);
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'move';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
//this.style.color = '#333';
}
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (dragSatMS != this) {
dragSatMS.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text');
}
return false;
}
function handleDragEnd(e) {
[].forEach.call(mssatCols, function (mSatCol) {
mSatCol.classList.remove('over');
//mSatCol.style.color = '#333';
});
}
var mssatCols = document.querySelectorAll('#ms-saturday .band-name');
[].forEach.call(mssatCols, function(msSatCol) {
msSatCol.addEventListener('dragstart', handleDragStart, false);
msSatCol.addEventListener('dragenter', handleDragEnter, false);
msSatCol.addEventListener('dragover', handleDragOver, false);
msSatCol.addEventListener('dragleave', handleDragLeave, false);
msSatCol.addEventListener('drop', handleDrop, false);
msSatCol.addEventListener('dragend', handleDragEnd, false);
});
这非常有效,我可以拖放列表让它们改变位置,乐队的名字也会适当地交换。但是,'data-band-id' 属性的值保持不变。我知道这正是我所拥有的代码所做的,这就是我的问题。我想修改代码,以便被拖放的乐队名称 和 'data-band-id' 属性的值被交换。
我用 Google 搜索了很多,但没有找到任何可以告诉我如何在多个值上设置数据的信息,非常感谢任何帮助。
您可以查询两个项目的 attributes
属性 并访问 data-band-id
的值。获得两个值后,您可以调用 setAttribute("name", "value")
来更新 data-band-id
。您更新后的 handleDrop
方法将是:
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (dragSatMS != this) {
dragSatMS.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text');
//Get the data-band-id of both items.
itemToReplaceAttr = this.attributes["data-band-id"].value;
draggedItemAttr = dragSatMS.attributes["data-band-id"].value;
//Call "setAttribute" to update the attributes.
this.setAttribute("data-band-id", draggedItemAttr);
dragSatMS.setAttribute("data-band-id", itemToReplaceAttr);
}
return false;
}
这里有一个很好的演示:Fiddle
亚斯的回答是解决问题的一种方法。
但我现在将向您介绍另一种方法,我看到的所有关于拖放的教程都小心避免 - 我相信拖放的用法 API 提供了一个理想的场景,其中事件委派应该大放异彩 - 然而,到目前为止(据我所知)none 的流行教程已经探讨了这种方法。
如果您急于看到我的建议奏效,请参阅 this fiddle。
因此,您可以将拖动事件的处理委托给项目的父级,ul
。而不是将拖动元素的 innerHtml
与元素放置的 innerHtml
交换,而是交换 outerHtml
.
var draggedItem = null;
var ul = document.getElementById('ms-saturday');
// delegate event handling to the parent of the list items
ul.addEventListener('dragstart', buffer(handleDragStart), false);
ul.addEventListener('dragover', buffer(handleDragOver), false);
ul.addEventListener('drop', buffer(handleDrop), false);
function handleDragStart(e) {
draggedItem = e.target;
e.dataTransfer.effectAllowed = 'move';
// dataTransfer is not really required, but I think IE may need it.
// Also, not that if you must use dataTransfer API,
// IE strongly requires that the mime type must be 'text'.
e.dataTransfer.setData('text', this.innerHTML);
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'move';
return false;
}
function handleDrop(e) {
var tmp;
if (e.stopPropagation) {
e.stopPropagation();
}
if (draggedItem !== e.target) {
// swapp outerHtml here
tmp = draggedItem.outerHTML;
draggedItem.outerHTML = e.target.outerHTML;
e.target.outerHTML = tmp;;
}
return false;
}
// this is used to create the handlers so that there won't be
// a need to repeat 'if (e.target === ul) {...' for as many times
// as there are handlers needed.
function buffer(fn) {
return function(e) {
// ignore drag-and-drop on the parent element itself
if (e.target === ul) {
return;
}
fn.call(this, e);
};
}
我让你根据自己的口味改进这种方法。
所以,我有一个要组织成 运行 顺序的波段列表,如下所示:
<li data-band-id='1' draggable='true' class='band-name'>Metallica</li>
<li data-band-id='2' draggable='true' class='band-name'>Slayer</li>
<li data-band-id='3' draggable='true' class='band-name'>Paradise Lost</li>
<li data-band-id='4' draggable='true' class='band-name'>Gojira</li>
我希望能够拖动这些列表项来更改整个列表中每个波段的位置。到目前为止,我有以下 JavaScript 来执行此操作:
var dragSatMS = null;
function handleDragStart(e) {
//this.style.color = 'green';
dragSatMS = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text', this.innerHTML);
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'move';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
//this.style.color = '#333';
}
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (dragSatMS != this) {
dragSatMS.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text');
}
return false;
}
function handleDragEnd(e) {
[].forEach.call(mssatCols, function (mSatCol) {
mSatCol.classList.remove('over');
//mSatCol.style.color = '#333';
});
}
var mssatCols = document.querySelectorAll('#ms-saturday .band-name');
[].forEach.call(mssatCols, function(msSatCol) {
msSatCol.addEventListener('dragstart', handleDragStart, false);
msSatCol.addEventListener('dragenter', handleDragEnter, false);
msSatCol.addEventListener('dragover', handleDragOver, false);
msSatCol.addEventListener('dragleave', handleDragLeave, false);
msSatCol.addEventListener('drop', handleDrop, false);
msSatCol.addEventListener('dragend', handleDragEnd, false);
});
这非常有效,我可以拖放列表让它们改变位置,乐队的名字也会适当地交换。但是,'data-band-id' 属性的值保持不变。我知道这正是我所拥有的代码所做的,这就是我的问题。我想修改代码,以便被拖放的乐队名称 和 'data-band-id' 属性的值被交换。
我用 Google 搜索了很多,但没有找到任何可以告诉我如何在多个值上设置数据的信息,非常感谢任何帮助。
您可以查询两个项目的 attributes
属性 并访问 data-band-id
的值。获得两个值后,您可以调用 setAttribute("name", "value")
来更新 data-band-id
。您更新后的 handleDrop
方法将是:
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (dragSatMS != this) {
dragSatMS.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text');
//Get the data-band-id of both items.
itemToReplaceAttr = this.attributes["data-band-id"].value;
draggedItemAttr = dragSatMS.attributes["data-band-id"].value;
//Call "setAttribute" to update the attributes.
this.setAttribute("data-band-id", draggedItemAttr);
dragSatMS.setAttribute("data-band-id", itemToReplaceAttr);
}
return false;
}
这里有一个很好的演示:Fiddle
亚斯的回答是解决问题的一种方法。
但我现在将向您介绍另一种方法,我看到的所有关于拖放的教程都小心避免 - 我相信拖放的用法 API 提供了一个理想的场景,其中事件委派应该大放异彩 - 然而,到目前为止(据我所知)none 的流行教程已经探讨了这种方法。
如果您急于看到我的建议奏效,请参阅 this fiddle。
因此,您可以将拖动事件的处理委托给项目的父级,ul
。而不是将拖动元素的 innerHtml
与元素放置的 innerHtml
交换,而是交换 outerHtml
.
var draggedItem = null;
var ul = document.getElementById('ms-saturday');
// delegate event handling to the parent of the list items
ul.addEventListener('dragstart', buffer(handleDragStart), false);
ul.addEventListener('dragover', buffer(handleDragOver), false);
ul.addEventListener('drop', buffer(handleDrop), false);
function handleDragStart(e) {
draggedItem = e.target;
e.dataTransfer.effectAllowed = 'move';
// dataTransfer is not really required, but I think IE may need it.
// Also, not that if you must use dataTransfer API,
// IE strongly requires that the mime type must be 'text'.
e.dataTransfer.setData('text', this.innerHTML);
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'move';
return false;
}
function handleDrop(e) {
var tmp;
if (e.stopPropagation) {
e.stopPropagation();
}
if (draggedItem !== e.target) {
// swapp outerHtml here
tmp = draggedItem.outerHTML;
draggedItem.outerHTML = e.target.outerHTML;
e.target.outerHTML = tmp;;
}
return false;
}
// this is used to create the handlers so that there won't be
// a need to repeat 'if (e.target === ul) {...' for as many times
// as there are handlers needed.
function buffer(fn) {
return function(e) {
// ignore drag-and-drop on the parent element itself
if (e.target === ul) {
return;
}
fn.call(this, e);
};
}
我让你根据自己的口味改进这种方法。