parentNode.removeChild not removing last element. But why? - javascript

I am working on a javascript code where I can clone an element, but also want to delete one on click. Cloning works, but I can't remove one.
I have the following elements.
<input list="accountsdeb" name="deblist[1]" id="deblist" autocomplete="off">
<input list="accountsdeb" name="deblist[2]" id="deblist" autocomplete="off">
And now I want to remove the last one on click (last = highest number).
function remove1() {
var dbl = document.querySelectorAll('#deblist').length;
var dbla = dbl;
var elem = document.getElementsByName("deblist["+dbla+"]");
alert(dbla);
//var last = debelelast - 1;
elem.parentNode.removeChild(elem);
}
As an orientation I used to have a look on an example from W3S and Stack. I have also seen that this works:
var elem = document.getElementById("myDiv");
elem.parentNode.removeChild(elem);
But this is random and as you can see I have tried to include this in my code.
The error I get is:
Uncaught TypeError: Cannot read property 'removeChild' of undefined
at HTMLAnchorElement.remove1 (index.php:179)
Where's the problem in my code, where is my thinking wrong?

I see two issues in the piece of code you provided,
deblist is used as id for 2 elements which is not advisable and due to this document.querySelectorAll('#deblist').length returns 2 (I am not sure if you intending to do so)
document.getElementsByName() (check here) will return a NodeList which needs to be iterated in order to access any of the returned elements. So here you need to select the child element by giving its index. In your case elem will have one element for the matched name deblist[2] and hence you need to access it like elem[0] for selecting its parent and deleting its child.
So the updated the code would be,
var dbl = document.querySelectorAll('#deblist').length;
var dbla = dbl;
// console.log('dbla', dbla);
var elem = document.getElementsByName("deblist["+dbla+"]");
// console.log('elem 0', elem[0]);
// console.log('elem parentNode', elem[0].parentNode);
//var last = debelelast - 1;
elem[0].parentNode.removeChild(elem[0]);
Check the fiddle here

If the inputs are part of a group they could share a name property or such, and the use of jQuery could help you do something like...
$("input[name='group1']").last().parent().remove()
Or if not part of a group then just....
$("input").last().parent().remove()

Related

Traversing elements in javaScript

I need to change the href of link in a box. I can only use native javaScript. Somehow I have problems traversing through the elements in order to match the correct <a> tag.
Since all the a tags inside this container are identical except for their href value, I need to use this value to get a match.
So far I have tried with this:
var box = document.getElementsByClassName('ic-Login-confirmation__content');
var terms = box.querySelectorAll('a');
if (typeof(box) != 'undefined' && box != null) {
for (var i = 0; i < terms.length; i++) {
if (terms[i].href.toLowerCase() == 'http://www.myweb.net/2/') {
terms[i].setAttribute('href', 'http://newlink.com');
}
}
}
However, I keep getting "Uncaught TypeError: box.querySelectorAll is not a function". What do I need to do in order to make this work?
Jsfiddle here.
The beauty of querySelectorAll is you dont need to traverse like that - just use
var terms = document.querySelectorAll('.ic-Login-confirmation__content a');
And then iterate those. Updated fiddle: https://jsfiddle.net/4y6k8g4g/2/
In fact, this whole thing can be much simpler
var terms = document.querySelectorAll('.ic-Login-confirmation__content a[href="http://www.myweb.net/2/"]');
if(terms.length){
terms[0].setAttribute('href', 'http://newlink.com');
}
Live example: https://jsfiddle.net/4y6k8g4g/4/
Try This:
var box = document.getElementsByClassName('ic-Login-confirmation__content')[0];
Since you are using getElementsByClassName ,it will return an array of elements.
The getElementsByClassName method returns returns a collection of all elements in the document with the specified class name, as a NodeList object.
You need to specify it as follows for this instance:
document.getElementsByClassName('ic-Login-confirmation__content')[0]
This will ensure that you are accessing the correct node in your HTML. If you console.log the box variable in your example you will see an array returned.
you can select by href attr with querySelector,
try this:
document.querySelector('a[href="http://www.myweb.net/2/"]')
instead of defining the exact href attribute you can simplify it even more :
document.querySelector('a[href?="myweb.net/2/"]'
matches only elments with href attribute that end with "myweb.net/2/"

Javascript - How to get attribute value from a tag, inside a specific div class?

Snippet of HTML code I need to retrieve values from:
<div class="elgg-foot">
<input type="hidden" value="41" name="guid">
<input class="elgg-button elgg-button-submit" type="submit" value="Save">
</div>
I need to get the value 41, which is simple enough with:
var x = document.getElementsByTagName("input")[0];
var y = x.attributes[1].value;
However I need to make sure I'm actually retrieving values from inside "elgg-foot", because there are multiple div classes in the HTML code.
I can get the class like this:
var a = document.getElementsByClassName("elgg-foot")[0];
And then I tried to combine it in various ways with var x, but I don't really know the syntax/logic to do it.
For example:
var full = a.getElementsByTagName("input")[0];
So: Retrieve value 41 from inside unique class elg-foot.
I spent hours googling for this, but couldn't find a solution (partly because I don't know exactly what to search for)
Edit: Thanks for the answers everyone, they all seem to work. I almost had it working myself, just forgot a [0] somewhere in my original code. Appreciate the JQuery as well, never used it before :-)
The easiest way is to use jQuery and use CSS selectors:
$(".elgg-foot") will indeed always get you an element with class "elgg-foot", but if you go one step further, you can use descendent selectors:
$(".elgg-foot input[name='guid']").val()
That ensures that you only get the input named guid that is a child of the element labelled with class elgg-foot.
The equivalent in modern browsers is the native querySelectorAll method:
document.querySelectorAll(".elgg-foot input[name='guid']")
or you can do what you have yourself:
var x = document.getElementsByClassName("elgg-foot")
var y = x.getElementsByTagName("input")[0];
Assuming you know it is always the first input within the div
You can combine it like this:
var a = document.getElementsByClassName("elgg-foot")[0];
var b = a.getElementsByTagName("input")[0];
var attribute = b.attributes[1].value;
console.log(attribute); // print 41
Think of the DOM as the tree that it is. You can get elements from elements in the same way you get from the root (the document).
You can use querySelector like
var x = document.querySelector(".elgg-foot input");
var y = x.value;
query the dom by selector https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
var fourty1 = document.querySelector('.elgg-foot input[name=guid]').value;
querySelector will return the first match from the selector. This selector will find the element with class elgg-foot and then look at the input element inside of that for one named guid and then take the value of the selected element.
I think the simplest way would be using JQuery. But using only javascript,
the simplest way would be:
var div = document.getElementsByClassName("elgg-foot")[0];
var input = div.getElementsByTagName("input")[0];
alert(input.value)
Take a look at this JSFiddle here: http://jsfiddle.net/2oa5evro/

Use a Selector instead of "this" in Jquery

Maybe it's a silly question. But I really can't understand it.
I'm using the Jquery Cycle2. And after some personalization I got a simple problem.
I need to know what is the "Index" of my current slide.
On the plugin's website a found this line of code that perfectly works.
$('#cycle-1 .cycle-slide').click(function(){
var index = $('#cycle-1').data('cycle.API').getSlideIndex(this);
alert(index);
});
It gives me the right index. But I'm trying to catch this Index when another element is clicked. So I can't use the parameter (this).
Then I tried this.
$('.anotherelement').click(function(){
var mycycle = $('#cycle-1 .cycle-slide');
var index = $('#cycle-1').data('cycle.API').getSlideIndex($(mycycle));
alert(index);
});
It doesn't return my current slide index. It returns "-1". Does anyone knows how I should pass the Object (selector) as a parameter to the getSlideIndex() ?
Thanks a lot :D
You can use $('.cycle-slideshow').data('cycle.opts').currSlide to get the current slide index
$('.anotherelement').click(function(){
var index = $('.cycle-slideshow').data('cycle.opts').currSlide;
var currSliderNum = index+1;
alert(currSliderNum);
return false;
});
FIDDLE
In the first piece of code this is a DOM element and not a jquery object. Try this instead:
var index = $('#cycle-1').data('cycle.API').getSlideIndex(mycycle[0]);
However, presumably, you have multiple .cycle-slide elements. This will just get the first one. In your first code you have access to a single one since only one was clicked. You need to decide which one you want to target here.

Beginner Javascript error with getAttribute

I've searched quite a bit on both google and stackoverflow, but a lack of knowledge on how to ask the question (or even if I'm asking the right question at all) is making it hard to find pertinent information.
I have a simple block of code that I am experimenting with to teach myself javascript.
var studio = document.getElementById('studio');
var contact = document.getElementById('contact');
var nav = document.getElementById('nav');
var navLinks = nav.getElementsByTagName('a');
var title = navLinks.getAttribute('title');
I want to grab the title attribute from the links in the element with the ID 'nav'.
Whenever I look at the debugger, it tells me that Object #<NodeList> has no method 'getAttribute'
I have no idea where I'm going wrong.
The nodetype and nodevalue for navLinks comes back as undefined, which I believe may be part of the problem, but I'm so new to this that I honestly have no idea.
The getElementsByTagName method returns an array of objects. So you need to loop through this array in order to get individual elements and their attributes:
var navLinks = nav.getElementsByTagName('a');
for (var i = 0; i < navLinks.length; i++) {
var link = navLinks[i];
var title = link.title;
}
Calling nav.getElementsByTagName('a') returns list of objects. And that list doesn't have getAttribute() method. You must call it on ONE object.
When you do:
navLinks[0].getAttribute('title')
then it should work - you will get title of the first matched element.
var navLinks = nav.getElementsByTagName('a');
getElementsByTagName returns multiple elements (hence Elements), because there can be multiple elements on one page with the same tag name. A NodeList (which is a collection of nodes as returned by getElementsByTagName) does not have a getAttribute method.
You need to access the property of the element that you actually need. My guess is that this will be the first element you find.
var title = navLinks[0].getAttribute('title');

Multiple class query not working

I have this HTML-element:
<div class="option default"></div>
...and I try to get to it in Dojo like this:
var el = dojo.query(".option.default");
But when I try:
alert(dojo.attr(el, "class"));
...I get undefined.
Update:
For some reason, this works:
alert(el.attr("class"));
How come the other method doesn't work?
dojo.query() returns a list of DOM nodes based on a CSS selector, not a single element.
You would need to do:
var els = dojo.query(".option.default");
var el = els[0];
alert(dojo.attr(el, "class"));
Here's a working example: http://jsfiddle.net/ArtBIT/L35k6/
Would add to the comment but I can't.
#Orolin, how does Dojo know that you know you're expecting a single Node to be returned. If it special cased single elements then anywhere you call dojo.query() and genuinely don't know how many elements you're expecting to get back, you'd have to test yourself. That would be horrid, and take more than three characters!
If you really want this functionality, just do one of the following:
dojo.queryFirst = function() {
return(dojo.query(arguments)[0]);
}
or, if you must
dojo._oldQuery = dojo.query;
dojo.query = function() {
var nodes = dojo._oldQuery(arguments);
return nodes.length > 1 ? nodes : nodes[0];
}

Categories