Javascript If between appendChild and replaceChild not working - javascript

I am dynamically generating a table and after that I want to append it as a child to a div. The problem is every time i regenerate the table it gets appended in the same div without the old table removed.
if(context.children.length == 0){
context.appendChild(table);
}else{
context.replaceChild(table);
}
I tried with checking if the child already exists and if it does i replace it with the new element.
But I get the error The argument is not optional and I don't know how to do it otherwise. Any ideas?

That's not how replaceChild() works, You should, paremtElement.replaceChild(new element, element to be replaced) https://developer.mozilla.org/en-US/docs/Web/API/Node/replaceChild

You need to provide the second argument as the child to be replaced in Node#replaceChild method.
if(context.children.length == 0){
context.appendChild(table);
}else{
context.replaceChild(table, context.children[0]);
}

Related

Javascript - remove specific element from dynamically created array

I have a page where users can create tags (much like here in stackoverflow), which are then sent(POST) to the back end to be stored in a database. The user can make tags but also remove them before finally hitting Submit.
In the DOM the tags are generated along with an 'x' button. The 'x' button removes the element from the DOM, but the trouble comes when removing from the array. The closest I could get to a solution was this question, however I couldn't get it to quite work for me.
Here's the codepen
Here's the javascript (i'm using JQuery)
window.tag_array = [];
$( "#addtag" ).click(function() {
var tag = $("#input-tag").val();
//if tag is empty
if(!$('#input-tag').val()) {
alert("can't be empty");
} else {
//put tag.val into an array
tag_array.push(tag);
//add to DOM
$( "#tagsbox" )
.append( "<div class='displaytag'><i>"+tag+"</i><input type='hidden' class='tag' value="+tag+"><button onClick='return false;' class='removetag'>x</button></div>" );
//reset value in text area to null
$("#input-tag").val("");
//remove tag onclick
$('.removetag').click(function() {
$(this).parent().remove(); //remove tag from DOM
//splice from array
tag_array.splice( this, 1 ); //<--HERE IS PROBLEM (i think)
});
} //end else
alert(tag_array); //check array
});
The end result is the splice takes out too many array items.
I have also tried
tag_array.splice(tag_array.indexOf(tag),1);
to a similar result.
Please help! Thanks in advance
You should probably use something like .indexOf() to get an index of the element and then splice an array:
tag_array.splice(tag_array.indexOf(elm),1);
Working demo
The splice part is OK. The problem is that you're adding a click callback to .removetag too many times.
Everytime you append a new element, you are adding another click event to every .removetag item that is already on the page.
$('.removetag').click(function()
This way, whenever you click on one element, all the others were assign to fire the click callback too.
Solution
Instead, when creating the tag, set the click event only to the last added .removetag element:
$('.removetag').last().click(function()
Updated CODEPEN

How do you hide the first element in the first table?

I know that to hide the first element in a table is simply do (':first-child') but is there a way to specify that only the first element of the first TABLE needs to be removed?
In my situation the first element of every table is being hidden and I need to fix this.
I suppose you just target the first table, and then the first element, whatever that is ?
document.querySelector('table tr').style.display = 'none';
FIDDLE
as querySelector gets the first matching element, or in jQuery
$('table:first tr:first').hide()
FIDDLE
target the first table and the first td.
$('table:first td:first').hide()
DEMO
You can get a collection of all tables using document.getElementsByTagName("table"). Element zero of that collection ([0]) is the first table. You can then apply your first-child solution to element zero.
This does not require jQuery, nor that you assign an ID attribute to a specific table. (Assigning an ID attribute is probably more efficient if you know in advance which table is going to be first.)
Edited to add: I've tested this and it works, although it is revised from my first "it works" post. The first child element of TABLE is TBODY for a table that starts with a tr element, so what is really wanted is the first child of TBODY. It is probably better to descend the firstElementChild tree looking exspressly for a nodeName of "TR" and hide that. Look further down in this post for that approach.
Here is the simple code that works:
document.getElementsByTagName("table")[0].firstElementChild.firstElementChild.style.display = "none";
This is pure JavaScript, with no need for jQuery. Note that document.getElementsByTagName returns a live collection, so even if a table is added to the DOM, this will get the first one.
Do remember that the first element child of <table> (and then TBODY) is not necessarily <tr>. If you can be sure it is, or if you want the first element regardless, then what I've given will work for you. If you want to be sure it's a <tr> then a little more work will be needed.
This code finds and hides the first <tr> but will be less efficient because it gets two HTML collections:
document.getElementsByTagName("table")[0].getElementsByTagName("tr")[0].style.display = "none";
const tables = document.getElementsByTagName("table")
const firstTable = tables[0];
const firstRow = firstTable.rows[0];
firstRow.style.visibility = "hidden"; //hide
firstRow.style.visibility = "visible"; //visible
Here is a referrence.

JavaScript lastChild issue

When I add text in my text field before and after the existing paragraphs the remove button functions perfectly. However, if I click the remove button before adding elements you have to click TWICE to remove the paragraphs that were not created by a function.
What could be wrong here? I watch the DOM in Firebug as I'm adding and removing, and before the new elements are added, my remove button does not target "firstDiv" on the first click, but does so on the second click.
Here is the problem function:
function removeIt() {
firstDiv.removeChild(firstDiv.lastChild);
}
Here is the fiddle: http://jsfiddle.net/nxpeD/2/
Thanks for the help!
That's because you have text nodes (spaces) at the end, so the last paragraph isn't the last child (it is the last element child).
Then, use
function removeIt() {
firstDiv.removeChild(firstDiv.lastElementChild);
}
Demo: http://jsfiddle.net/nxpeD/6/
Compatibility: To make it work on old browsers, you could also use
function removeIt() {
if (firstDiv.lastElementChild) {
firstDiv.removeChild(firstDiv.lastElementChild);
} else {
var last;
while((last = firstDiv.lastChild).nodeType !== 1) {
firstDiv.removeChild(last);
}
firstDiv.removeChild(last);
}
}
References
lastChild
lastElementChild
Use:
firstDiv.removeChild(firstDiv.lastElementChild);
Since there are formatting new line chars in your html, that will be considered as a child as well of the div. So you need to use lastElementChild to get the element and ignore the formatting and and other text nodes outside.
Demo
The last_child returned is a node. If its parent is an element, then the child is generally an Element node, a Text node, or a Comment node. Returns null if there are no child elements.
lastElementChild

Variable with HTML content parsing

I have this variable called $reservas that contains a string with HTML Tables. I want to remove parts of the tables (.tdRemove), BEFORE I assign them to the div #cenas.
if ($reservas){
$($reservas).find('.tdRemove').each(function(){
console.log($(this).html());
$(this).remove();
});
$("#cenas").html($reservas);
}
I tried this, but it doesn't seem to remove anything.
I've also tried:
$($reservas).find('.tdRemove').remove(); and $($reservas).remove('.tdRemove');
Nothing works. Any suggestions?
Is there any way to tell jQuery that the variable holds html content, and should be parsed as that? If so, how? ..
After converting your string to a jQuery object, it is now a series of DOM objects (in a document fragment) held in the jQuery object. After removing the .tdRemove objects in that fragment, you can then just append that directly to your DOM. No need to go back to HTML:
if ($reservas){
var item = $($reservas);
item.find('.tdRemove').remove();
$("#cenas").empty().append(item);
}
Also, your code didn't work because the $reservas string of HTML was never modified.
I think, from what the documentation tells me, you can only remove() what is already inside the DOM.
Remove the set of matched elements from the DOM.
Maybe you want to add your table first, set it to ? display: none`, then filter for elements to remove and finally display the table.
if ($reservas) {
$("#cenas")
.hide()
.html($reservas)
.find('.tdRemove').each(function(){
console.log($(this).html());
$(this).remove();
})
.show();
}

jquery: Finding the last child from a selector

For example, I've got a selector here
var $myNeeds = $('.history');
This selector would have multiple divs inside, and now I want to get the last child from it, how to do this?
I tried $myNeeds.last(), this won't work!
Alternatively....
$myNeeds.find('>:last-child')
jsFiddle.
You're almost there...
$myNeeds.children().last()
The last method gets the last element in your set.
You want the last child of your set, so you need to get a new set with the children.
You could also write
$('.history > :last-child')
or
$myNeeds.children(":last")

Categories