2011-11-13 98 views
0

我对以下Javascript函数有问题。我有两个UL,当用户点击一个LI时,我需要这个元素,这个元素转移到另一个UL。使用Javascript将HTML元素从一个列表传输到另一个列表

我已经设法将它们从onClick从列表移动到另一个,当我尝试再次移动之前在另一个UL中的LI时,出现问题,当发生这种情况时它不起作用...

function testList() { 
    usersA = document.getElementById("users-a"); 
    usersB = document.getElementById("users-b"); 

    for (var i=0; i < usersA.getElementsByTagName("li").length; i++) { 
     usersA.getElementsByTagName("li")[i].onclick = function() { 
      transfer = this.cloneNode(true); 
      usersB.appendChild(transfer); 
      usersA.removeChild(this); 
      return false; 
     } 

    } 
    for (var i=0; i < usersB.getElementsByTagName("li").length; i++) {   
     usersB.getElementsByTagName("li")[i].onclick = function() { 
      transfer = this.cloneNode(true); 
      usersA.appendChild(transfer); 
      usersB.removeChild(this); 
      return false; 
     } 

    } 

} 

我知道我的逻辑很糟糕,但这是我所能想到的。任何想法为什么它在第一次转移LI时运行,但当我尝试恢复到原来的UL时,它不起作用?

+2

我的眼睛,他们流血。我的意思是在循环的每次迭代中调用gEBTN两次。这就像你想愤怒的神。 – Raynos

回答

0

的问题是,你从列表A移动的元素列表B中后,也仍保持其旧onclick处理程序,仍然说“删除我从列表A中将我添加到列表B“。你需要改变它的onclick处理程序来说“从列表B中删除我并将我添加到列表A”。下面是解决这个问题的一种方法:

var usersA = document.getElementById("users-a"); 
var usersB = document.getElementById("users-b"); 

var onclickA; 
var onclickB = function() { 
     usersA.appendChild(this); 
     this.onclick = onclickA; 
     return false; 
    }; 
onclickA = function() { 
     usersB.appendChild(this); 
     this.onclick = onclickB; 
     return false; 
    }; 

for (var i=0; i < usersA.getElementsByTagName("li").length; i++) 
    usersA.getElementsByTagName("li")[i].onclick = onclickA; 
for (var i=0; i < usersB.getElementsByTagName("li").length; i++)  
    usersB.getElementsByTagName("li")[i].onclick = onclickB; 

(我也摆脱了cloneNode东西,正是出于这个NNNNNN给出的原因)

+0

-1用于修复一小部分代码。 – Raynos

+0

@Raynos:恩?你是说我不应该修复'cloneNode'的东西吗? – ruakh

+0

嘿伙计们,非常感谢,因为你可以看到我是一个全新的人,但这对我来说非常有用! –

3

您不是“移动”元素,而是创建副本并删除原件。尽管从用户的角度来看这看起来像是一个“移动”,但您创建的新元素没有分配处理程序。从MDN:“克隆节点将复制其所有属性及其值,但不复制事件侦听器。”

根据MDN,.appendChild()将孩子从当前父母中删除,因此您不应该需要您正在执行的两步克隆/删除操作。我没有测试过,但也许只使用.appendChild()它会保持处理程序?如果是这样,您需要删除该处理程序并分配一个新处理程序以允许它现在属于哪个列表。

或者重写你的处理器,这样他们检查该列表是当前的父(看看.parentNode),并移动到另一个列表为适当。请注意,点击事件从目标/源元素开始向上并通过父级拓扑,您可能更适合在父级<ul>元素上设置点击处理程序,然后测试点击了哪个<li>。这样您就不必担心在新子节点<li>上设置新的点击处理程序。

function testList() { 
    var usersA = document.getElementById("users-a"), 
     usersB = document.getElementById("users-b"); 

    usersA.onclick = function(e) { 
     // allow for the IE and non-IE way of handling the event object 
     if (!e) e = window.event; 
     var el = e.target || e.srcElement; 

     if (el.tagName === "li") { 
     usersB.appendChild(el); 
     } 
    } 

    usersB.onclick = function(e) { 
     // allow for the IE and non-IE way of handling the event object 
     if (!e) e = window.event; 
     var el = e.target || e.srcElement; 

     if (el.tagName === "li") { 
     usersA.appendChild(el); 
     } 
    } 
} 

另外,如果你使用.getElementsByTagName()称之为曾经在环路初始化和结果分配给一个变量,然后使用变量 - 不守再次调用该函数,并再次测试长度,或访问您的循环中各个元素:

for (var i=0, lis = usersA.getElementsByTagName("li"); i < lis.length; i++) { 
    lis[i].onclick = function() { 
     // etc 
    } 
} 
相关问题