getElementsByTagName inside GetElementById (object xraywrapper)? - javascript

I am trying to get a div that is inside another div, since the id of the second div is variable, i use
var wrappingdiv = document.getElementById('divId')
to get the wrapping div then
var insidediv = wrappingdiv.getElementsByTagName('div')
but i get the getElementsByTagName is not a function error, i guess the syntax is wrong, could you guys put me in the right direction?
Thanks in advance.
Edit : I will correct myself, I am trying to get the body of a gmail email, so :
var element = content.document.getElementsByClassName("ii gt m13fbe3a51e95e196 adP adO");
it returns an object xraywrapper[object htmlcollection]
Edit 2 :
I am using mozilla firefox, and i am developing my own extension, to access source code of Google mail i use simple javascript (content.document...)

If you doesn't have any element with the id divId then wrappingdiv will be equal null:
And when trying to get null.getElementsByTagName you will get a type error:
TypeError: Cannot read property 'getElementsByTagName' of null

In
var element = content.document.getElementsByClassName(
"ii gt m13fbe3a51e95e196 adP adO");
getElements <- the s means this returns multiple elements (in a list-like collection), not just one element.
You might just want to pick out the first one it found.
var element = content.document.getElementsByClassName(
"ii gt m13fbe3a51e95e196 adP adO")[0];
There is also a small risk that it might not be m13fbe3a51e95e196 on every page, or forever. So perhaps you should generalise your search a bit. How about just searching for class "adP"?

The syntax isn't wrong. document.getElementById('divId') probably just fails to match the id of any existing element, so it returns null (which doesn't have a getElementsByTagName method).

DEMO
var wrappingdiv = document.getElementById("divId");
var insidediv = wrappingdiv.getElementsByTagName('div');
var i = 0;
for(i=0;i<insidediv.length;i++)
alert(insidediv[i].innerHTML);

Related

parentNode.removeChild not removing last element. But why?

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()

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/

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

getElementsByName in IE7

I have some code doing this :
var changes = document.getElementsByName(from);
for (var c=0; c<changes.length; c++) {
var ch = changes[c];
var current = new String(ch.innerHTML);
etc.
}
This works fine in FF and Chrome but not in IE7. Presumably because getElementsByName isn't working in IE. What's the best workaround?
In case you don't know why this isn't working in IE, here is the MSDN documentation on that function:
When you use the getElementsByName method, all elements in the document that have the specified NAME attribute or ID attribute value are returned.
Elements that support both the NAME attribute and the ID attribute are included in the collection returned by the getElementsByName method, but elements with a NAME expando are not included in the collection; therefore, this method cannot be used to retrieve custom tags by name.
Firefox allows getElementsByName() to retrieve elements that use a NAME expando, which is why it works. Whether or not that is a Good Thing™ may be up for debate, but that is the reality of it.
So, one option is to use the getAttribute() DOM method to ask for the NAME attribute and then test the value to see if it is what you want, and if so, add it to an array. This would require, however, that you iterate over all of the nodes in the page or at least within a subsection, which wouldn't be the most efficient. You could constrain that list beforehand by using something like getElementsByTagName() perhaps.
Another way to do this, if you are in control of the HTML of the page, is to give all of the elements of interest an Id that varies only by number, e.g.:
<div id="Change0">...</div>
<div id="Change1">...</div>
<div id="Change2">...</div>
<div id="Change3">...</div>
And then have JavaScript like this:
// assumes consecutive numbering, starting at 0
function getElementsByModifiedId(baseIdentifier) {
var allWantedElements = [];
var idMod = 0;
while(document.getElementById(baseIdentifier + idMod)) { // will stop when it can't find any more
allWantedElements.push(document.getElementById(baseIdentifier + idMod++));
}
return allWantedElements;
}
// call it like so:
var changes = getElementsByModifiedId("Change");
That is a hack, of course, but it would do the job you need and not be too inefficient compare to some other hacks.
If you are using a JavaScript framework/toolkit of some kind, you options are much better, but I don't have time to get into those specifics unless you indicate you are using one. Personally, I don't know how people live without one, they save so much time, effort and frustration that you can't afford not to use one.
There are a couple of problems:
IE is indeed confusing id="" with name=""
name="" isn't allowed on <span>
To fix, I suggest:
Change all the name="" to class=""
Change your code like this:
-
var changes = document.getElementById('text').getElementsByTagName('span');
for (var c=0; c<changes.length; c++) {
var ch = changes[c];
if (ch.className != from)
continue;
var current = new String(ch.innerHTML);
It's not very common to find elements using the NAME property. I would recommend switching to the ID property.
You can however find elements with a specific name using jQuery:
$("*[name='whatevernameYouWant']");
this will return all elements with the given name.
getElementsByName is supported in IE, but there are bugs. In particular it returns elements whose ‘id’ match the given value, as well as ‘name’. Can't tell if that's the problem you're having without a bit more context, code and actual error messages though.
In general, getElementsByName is probably best avoided, because the ‘name’ attribute in HTML has several overlapping purposes which can confuse. Using getElementById is much more reliable. When specifically working with form fields, you can more reliably use form.elements[name] to retrieve the fields you're looking for.
I've had success using a wrapper to return an array of the elements. Works in IE 6, and 7 too. Keep in mind it's not 100% the exact same thing as document.getElementsByName, since it's not a NodeList. But for what I need it for, which is to just run a for loop on an array of elements to do simple things like setting .disabled = true, it works well enough.
Even though this function still uses getElementsByName, it works if used this way. See for yourself.
function getElementsByNameWrapper(name) {
a = new Array();
for (var i = 0; i < document.getElementsByName(name).length; ++i) {
a.push(document.getElementsByName(name)[i]);
}
return a;
}
Workaround
var listOfElements = document.getElementsByName('aName'); // Replace aName with the name you're looking for
// IE hack, because it doesn't properly support getElementsByName
if (listOfElements.length == 0) { // If IE, which hasn't returned any elements
var listOfElements = [];
var spanList = document.getElementsByTagName('*'); // If all the elements are the same type of tag, enter it here (e.g.: SPAN)
for(var i = 0; i < spanList.length; i++) {
if(spanList[i].getAttribute('name') == 'aName') {
listOfElements.push(spanList[i]);
}
}
}
Just another DOM bug in IE:
Bug 1: Click here
Bug 2: Click here

Categories