简体   繁体   中英

How to remove a div without using its ID

Divs are created every update and their positions are randomized inside "levelWrapper". All these divs share a class named tree . Whenever I click a div that has tree as a class, the code runs through all existing tree classed divs and compares their positions in relation to the mouse click coordinates. If their position is within click range (which is 100px) then I want to remove said divs .

Here's what I have that already does what I want BUT bugs after the first run through the code. I think I know why it bugs, read below.

 var i = 0, a = 0; function newTree() { var newTree = document.createElement('div'); newTree.id = 'tree' + i; newTree.className = 'tree'; document.getElementById("levelWrapper").appendChild(newTree); } function positionTree() { var levelWidth = document.getElementById("levelWrapper").offsetWidth; var levelHeight = document.getElementById("levelWrapper").offsetHeight; var treeX = Math.round(Math.random() * levelWidth); var treeY = Math.round(Math.random() * levelHeight); document.getElementById("tree" + i).style.left = treeX + "px"; document.getElementById("tree" + i).style.top = treeY + "px"; } function createTree() { a += 1; if (a == 20) { newTree(); // new div positionTree(); // position div a = 0; // reset counter for new div i++; // new ID for new div } } function getMouseCoordinates(e) { var offset = $('#levelWrapper').offset(); mouseX = Math.round(e.clientX - offset.left); mouseY = Math.round(e.clientY - offset.top); } var clickRange = 100; function update() { createTree(); $('div.tree').click(function(e) { getMouseCoordinates(e); var numItems = $('.tree').length; for (g = 0; g < numItems; g++) { var p = $("#tree" + g).position(); if ((p.left > (mouseX - clickRange)) & (p.left < (mouseX + clickRange)) & (p.top > (mouseY - clickRange)) & (p.top < (mouseY + clickRange))) { p = document.getElementById("tree" + g); p.parentNode.removeChild(p); } } }); } function mainLoop() { update(); requestAnimationFrame(mainLoop); } requestAnimationFrame(mainLoop); 
 #levelWrapper { position: relative; top: 25px; width: 1100px; height: 700px; margin: auto; border: 1px solid red; } .tree { position: absolute; background: green; height: 12px; width: 12px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <div id="levelWrapper"></div> 

It bugs because on the second run, this line var p = $("#tree" + g).position(); selects a div that has been deleted so it returns a null.

New divs are still created, but the click/remove function stops working.

I could probably do something along the lines of "if (null) ..." BUT the div IDs keep increasing, easily getting up to 200+ divs that the for loop has to go through and that is visibly slow.

So instead of removing divs through their IDs, I thought of having some array referencing them and whenever I delete one div, the array "cascades" down, reducing the ammount of checking I have to do, and avoiding the null return whenever it tries to find the offset left and top of a removed div.

lets say you want to remove all elements with class name "child" from your tree:

$(".tree > .child").remove();

or to remove your tree children by index use:

var children = $(".tree").children();
[1,2,5].forEach(function(i) { children[i].remove(); });

Here you are setting the array indexes you want to remove. Be aware that this is zero based! So first element is 0. Here i am removing elements with index 1, 2 and 5. Type whatever indexes you like!

  1. test the existence:

   for (g = 0; g < numItems; g++) {
      var $div = $("#tree" + g);
      if ($div.length==0) continue;
      var p = $div.position();

      if ((p.left > (mouseX - clickRange)) &
        (p.left < (mouseX + clickRange)) &
        (p.top > (mouseY - clickRange)) &
        (p.top < (mouseY + clickRange))) {

        $div.remove();
      }
    }
  1. Delegate - You add a click handler every time you loop

 $('#levelWrapper').on('click','div.tree',function(e) {
  getMouseCoordinates(e);
  $('.tree').each(function() {
    var p = $(this).position();

 var i = 0, a = 0; function newTree() { i = $('#levelWrapper').children().length; var $newTree = $('<div/>', { 'id': 'tree' + i, 'class': 'tree' }); // .text(i); $('#levelWrapper').append($newTree); } function positionTree() { var levelWidth = document.getElementById("levelWrapper").offsetWidth; var levelHeight = document.getElementById("levelWrapper").offsetHeight; var treeX = Math.round(Math.random() * levelWidth); var treeY = Math.round(Math.random() * levelHeight); document.getElementById("tree" + i).style.left = treeX + "px"; document.getElementById("tree" + i).style.top = treeY + "px"; } function createTree() { a += 1; if (a == 20) { newTree(); // new div positionTree(); // position div a = 0; // reset counter for new div i++; // new ID for new div } } function getMouseCoordinates(e) { var offset = $('#levelWrapper').offset(); mouseX = Math.round(e.clientX - offset.left); mouseY = Math.round(e.clientY - offset.top); } var clickRange = 100; function mainLoop() { createTree(); requestAnimationFrame(mainLoop); } $(function() { $('#levelWrapper').on('click','div.tree',function(e) { getMouseCoordinates(e); $('.tree').each(function() { var p = $(this).position(); if ((p.left > (mouseX - clickRange)) & (p.left < (mouseX + clickRange)) & (p.top > (mouseY - clickRange)) & (p.top < (mouseY + clickRange))) { $(this).remove(); } }); }); requestAnimationFrame(mainLoop); }); 
 #levelWrapper { position: relative; top: 25px; width: 1100px; height: 700px; margin: auto; border: 1px solid red; } .tree { position: absolute; background: green; height: 12px; width: 12px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <div id="levelWrapper"></div> 

I believe $('.tree').remove(); is what you are looking for.

edit: Based on the comments to your question, maybe you are trying to remove the children of class="tree"?

If so that would be:

$('.tree').children().remove();

and if you wanted to remove only the additional instances of class="tree" and not the first one, then you could do:

$('.tree').slice(1).children().remove();

From the jquery documentation on .remove() :

We can also include a selector as an optional parameter. For example, we could rewrite the previous DOM removal code as follows:

 $( "div" ).remove( ".hello" ); 

I think you want to remove only the first element with class of .tree , so you could use :first-child like this:

 $(document).ready(function() { $('.tree').remove(':first-child'); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id='parent'> <div class='tree'>Tree 1</div> <div class='tree'>Tree 2</div> <div>Etc</div> </div> 

You can try this:

    var temp = $('.tree');
     $(temp[0]).detach();

Or

    var temp = $('.tree');
     $(temp[0]).remove();

The diference between detach and remove you can see at Differences between detach(), hide() and remove() - jQuery

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM