PlayerCoder75
PlayerCoder75

Reputation: 35

Html add/removeChild

Here is my code. This javascript function should remove the most recent traveler (traveler_count is initialized earlier to 1, an add_traveler button also updates that count +1 when it is clicked, and this function executes when a button is clicked). I am unable to get it to remove the most recent traveler. Any ideas how to fix this issue?

function remove_traveler()
    {
        //get most recent add on, removeChild() on lname, fname, phone, lbls associated

        var recent_traveler_fname = document.getElementById("trip_member_first_name_" + traveler_count); 
        var recent_traveler_lname = document.getElementById("trip_member_last_name_" + traveler_count); 
        var recent_traveler_phone = document.getElementById("trip_member_phone_number_" + traveler_count); 
        var recent_traveler_fname_lbl = document.getElementById("new_traveler_fname_label_" + traveler_count); 
        var recent_traveler_lname_lbl = document.getElementById("new_traveler_lname_label_" + traveler_count); 
        var recent_traveler_phone_lbl = document.getElementById("new_traveler_phone_label_" + traveler_count); 

        var input_area = document.getElementById("new_traveler"); 

        if(traveler_count > 1)
        {
            input_area.parentNode.removeChild(recent_traveler_fname); 
            input_area.parentNode.removeChild(recent_traveler_lname); 
            input_area.parentNode.removeChild(recent_traveler_phone); 
            input_area.parentNode.removeChild(recent_traveler_fname_lbl); 
            input_area.parentNode.removeChild(recent_traveler_lname_lbl); 
            input_area.parentNode.removeChild(recent_traveler_phone_lbl); 

            traveler_count = traveler_count - 1; 
        }

    }

Upvotes: 2

Views: 114

Answers (4)

jmbertucci
jmbertucci

Reputation: 8224

If you have the option of doing a little bit of code refactor, I would consider doing a little more of an Object Oriented approach.

Here's a proof-of-concept demo

Here's a more interactive concept demo

First, I would create a Traveler object that will contain your traveler information.

function Traveler(firstName, lastName, phone) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.phone = phone;
}

Then I would simply use an array to store my list of travelers.

var travelers = new Array();

With an array, we can easily use the JavaScript Push()/Pop() functions to create a LIFO stack. These functions can then be tied directly to your button event.

// Add Traveler
function addTraveler(traveler) {
    travelers.push(traveler);
}

// Remove Traveler (returns the removed traveler)
function removeTraveler() {
    return travelers.pop();
}

With that, all you need is a method to render your view (html). It appears your using labels, which you can still use, but I wrote this example simply as rendering a list. You can simply modify the HTML structure for your needs.

// Display Travelers
function renderTravelers() {
    var htmlList = "";
    var arrayLength = travelers.length;

    for (var i = 0; i < arrayLength; i++) {
        htmlList += 
            "<li>" + 
            travelers[i].firstName + " " + 
            travelers[i].lastName  + " " + 
            travelers[i].phone     +
            "</li>"
    }
    htmlList = "<ul>" + htmlList + "</ul>";
    htmlList += "<em>Number of Travelers: " + arrayLength + "</em>";
    document.getElementById("output").innerHTML += htmlList + "<hr>";
}

Since you're keeping your travelers in an array, you can simply use the .length property to get the current number of travelers for whatever display or business logic you need.

If you want to go the extra step, you could consider using a data-binding framework like Knockout, Ember or AngularJS.

The benefits of this proof-of-concept code is that your not constantly querying your DOM structure for each individual element and then deleting it. Instead, you're imploring more separation of code. There's still better way's to do the view but this is an idea that might help make what you're doing easier to manage.

I've also got a feeling that just replacing the innerHTML of your wrapping element might be more efficient than calling removeChild() six times, but I doubt there's much concern for minimal performance difference for the likely use cases.

Also storing your master list in an array would allow you to more easily refactor your code to do something like a paginated list, if you're going to be dealing with longer lists.

edit

If I misunderstood what you meant by "most recent traveler" and you mean you doing more of a FIFO stack, you can use shift() instead of pop() to remove the first guy from the array, instead of the last guy added to the array.

I hope that helps!

Cheers!

Upvotes: 1

KevinRyan
KevinRyan

Reputation: 51

Are you trying to delete the following elements?

recent_traveler_fname
recent_traveler_lname 
recent_traveler_phone 
recent_traveler_fname_lbl 
recent_traveler_lname_lbl 
recent_traveler_phone_lbl 

If so, the following modifications should work:

function remove_traveler()
{
    //get most recent add on, removeChild() on lname, fname, phone, lbls associated
    var recent_traveler_fname = document.getElementById("trip_member_first_name_" + traveler_count); 
    var recent_traveler_lname = document.getElementById("trip_member_last_name_" + traveler_count); 
    var recent_traveler_phone = document.getElementById("trip_member_phone_number_" + traveler_count); 
    var recent_traveler_fname_lbl = document.getElementById("new_traveler_fname_label_" + traveler_count); 
    var recent_traveler_lname_lbl = document.getElementById("new_traveler_lname_label_" + traveler_count); 
    var recent_traveler_phone_lbl = document.getElementById("new_traveler_phone_label_" + traveler_count); 


    if(traveler_count > 1)
    {
        recent_traveler_fname.parentNode.removeChild(recent_traveler_fname); 
        recent_traveler_lname.parentNode.removeChild(recent_traveler_lname); 
        recent_traveler_phone.parentNode.removeChild(recent_traveler_phone); 
        recent_traveler_fname_lbl.parentNode.removeChild(recent_traveler_fname_lbl); 
        recent_traveler_lname_lbl.parentNode.removeChild(recent_traveler_lname_lbl); 
        recent_traveler_phone_lbl.parentNode.removeChild(recent_traveler_phone_lbl); 

        traveler_count = traveler_count - 1; 
    }



}

Source: Remove element by id

Bonus: If you want to be a little more efficient, you could move all the 'get element by id' statements into the if-statement block since they are only used in the case that traveler_count > 1.

Upvotes: 1

Goran.it
Goran.it

Reputation: 6299

Here is a dummy example how you could achieve this :

// Pure JS - find all nodes with matching ID's that start with "trip_member_first_name_"
var nodes = document.querySelectorAll("[id*=trip_member_first_name_]"),
    lastNumb,
    currentNumb,
    lastIndex;

for (var i=0,len=nodes.length;i<len;i++) {
  // A bit limited regex that extracts only the last digits from the ID attribute
  currentNumb = parseInt(nodes[i].getAttribute("id").match(/\d*?$/));
  if (!lastNumb || lastNumb < currentNumb) {
    lastNumb = currentNumb;
    lastIndex = i;
  }
}
// This will print "2" inside the result as it's 
// the highest number of all "trip_member_first_name_" inputs
document.getElementById("result").innerHTML = lastNumb;

// So you could just do something like this to remove the last input :
nodes[lastIndex].parentNode.removeChild(nodes[lastIndex]);
<label id="new_traveler_fname_label_0">First Name</label><br>
<input id="trip_member_first_name_0" type="text" /><br>
<label id="new_traveler_lname_label_0">Last Name</label><br>
<input id="trip_member_last_name_0" type="text" /><br>
<label id="new_traveler_phone_label_0">Phone</label><br>
<input id="trip_member_phone_number_0" type="text" /><br>

<label id="new_traveler_fname_label_1">First Name</label><br>
<input id="trip_member_first_name_1" type="text" /><br>
<label id="new_traveler_lname_label_1">Last Name</label><br>
<input id="trip_member_last_name_1" type="text" /><br>
<label id="new_traveler_phone_label_1">Phone</label><br>
<input id="trip_member_phone_number_1" type="text" /><br>

<label id="new_traveler_fname_label_2">First Name</label><br>
<input id="trip_member_first_name_2" type="text" /><br>
<label id="new_traveler_lname_label_2">Last Name</label><br>
<input id="trip_member_last_name_2" type="text" /><br>
<label id="new_traveler_phone_label_2">Phone</label><br>
<input id="trip_member_phone_number_2" type="text" /><br>

<div id="result"></div>

Upvotes: 0

Gal Schlezinger
Gal Schlezinger

Reputation: 364

why don't use the original parents?

var removeElement = function(element) { element.parentElement.removeChild(element); };
removeElement(document.getElementById("trip_member_first_name_" + traveler_count));
removeElement(document.getElementById("trip_member_last_name_" + traveler_count));
removeElement(document.getElementById("trip_member_phone_number_" + traveler_count));
removeElement(document.getElementById("new_traveler_fname_label_" + traveler_count));
removeElement(document.getElementById("new_traveler_lname_label_" + traveler_count));
removeElement(document.getElementById("new_traveler_phone_label_" + traveler_count));

make sure your IDs are correct or it will throw an error related to function called on undefined or something.

Upvotes: 0

Related Questions