Transfer HTML elements from one list to another with JavaScript - Stack Overflow

admin2025-04-19  0

I have a problem with the following JavaScript function. I have two UL and I need that when the user clicks on a LI, this element transfers to the other UL.

I've managed to move them onClick from on list to the other, the problem appears when I try to move again a LI that was previously in the other UL, when that happens it just doesn't work...

    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;
        }

    }
    
}

I know that my logic sucks but it's all I could e up with. Any ideas why it works the first time I transfer a LI but when I try to move back to its original UL it doesn't work?

I have a problem with the following JavaScript function. I have two UL and I need that when the user clicks on a LI, this element transfers to the other UL.

I've managed to move them onClick from on list to the other, the problem appears when I try to move again a LI that was previously in the other UL, when that happens it just doesn't work...

    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;
        }

    }
    
}

I know that my logic sucks but it's all I could e up with. Any ideas why it works the first time I transfer a LI but when I try to move back to its original UL it doesn't work?

Share edited Jul 15, 2022 at 13:06 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Nov 13, 2011 at 23:44 Roger BerganteRoger Bergante 551 silver badge11 bronze badges 1
  • 2 My eyes, they bleed. I mean calling gEBTN twice for every iteration of the loop. It's like you want to anger the gods. – Raynos Commented Nov 14, 2011 at 0:10
Add a ment  | 

2 Answers 2

Reset to default 4

You're not "moving" elements, you're creating a copy and deleting the original. Although this seems like a "move" from the user's point of view the new elements that you create do not have click handlers assigned. From MDN: "Cloning a node copies all of its attributes and their values but does not copy event listeners."

According to MDN, .appendChild() will remove the child from its current parent so you shouldn't need the two-step clone/remove that you are currently doing. I haven't tested it, but perhaps using just .appendChild() it will keep the handlers? If so you need to remove that handler and assign a new one to allow for which list it now belongs to.

Or, rewrite your handlers so that they check which list is the current parent (have a look at .parentNode) and move to the other list as appropriate.

Bearing in mind that click events "bubble up" starting from the target/source element and up through the parent heirarchy you're probably better off setting your click handlers on the parent <ul> elements and then testing which <li> was clicked. That way you don't have to worry about setting new click handlers on new child <li> elements.

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);
      }
   }
}

Also, if you're using .getElementsByTagName() call it once in the loop initialisation and assign the result to a variable, then use the variable - don't keep calling the function again and again to test the length, or to access individual elements inside your loop:

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

The problem is that even after you've moved an element from list A to list B, it still keeps its old onclick handler, which still says "remove me from list A and add me to list B". You need to change its onclick handler to say "remove me from list B and add me to list A". Here's one way to fix that:

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;

(I also got rid of the cloneNode stuff, for exactly the reasons that nnnnnn gives.)

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745054326a282305.html

最新回复(0)