I'm having a hard time converting a NodeList to an array in IE 8. The following works perfectly in Chrome, but in IE 8 toArray() is not recognized as valid:
NodeList.prototype.toArray = function() {
var a = [];
for (var i = 0, len = this.length; i < len; i++) {
a[i] = this[i];
}
return a;
}
document.all.tags("div").toArray();
I tried adding a prototype function to an array just to check my sanity and it works correctly. That makes me think IE 8 doesn't actually return a NodeList? Here's a full example:
http://jsfiddle.net/e4RbH/
What am I doing wrong?
If you're looking for a modern answer using ES6:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
var nodes = document.querySelectorAll('div');
nodes = Array.from(nodes);
Old question, but here is a tried & true method:
var nodes=document.querySelectorAll("div"); // returns a node list
nodes=Array.prototype.slice.call(nodes); // copies to an array
Explanation
document.querySelectorAll uses a CSS-style selector to find elements and returns a node list. It works as of IE 8.
The slice method copies a portion of an array-like collection (in this case all of it) into a new array.
call allows you to borrow a method from one object to use on another
To find the node list you could also have used `document.getElementsByTagName(), but this one is more flexible.
First, don't use document.all -- it's non-standard and deprecated. Use document.getElementsByTagName to get the DIV elements in your case.
Second, don't extend DOM objects such as NodeList -- built-in objects are a very strange breed and are not required to behave like any other objects that you generally work with. See this article for an in-depth explanation of this: What's wrong with extending the DOM.
IE doesn't support NodeList in the standard way. This is why you should roll your own namespace and NOT extend browser core objects.
You can do alert( typeof window.NodeList ) and see if it's undefined or not.
Related
I want to create a simple Vanilla JS horizontal stepper without the addition of CSS or JS libraries.
I have found this example but it doesnt work with IE browser.
The problem is the following line:
const bullets = [...document.querySelectorAll('.bullet')];
where he is converting the NodeList of 'divs' with class .bullet to Array.
Is there any way to make it work because I have tried "Array.prototype.slice" and copy the Nodelist in a JS array without success..
I would just iterate though the the nodeList with something like a for loop and add the nodelist item to the array . Something like this:
let bulletsArray = [];
let bullets = document.querySelectorAll('bullets');
for(let i = 0; i < bullets.length; i++) {
bulletsArray.push(bullets[i])
}
Heres a working demo: https://codepen.io/inklingboi/pen/BapmdBw?editors=1010
Note: my initial idea was to use Array.from() but after checking its compatibility list on mdn https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from i noticed that it isnt supported in IE
It seems that IE does not support addEventListener() function because I get an error at that line:
nextBtn.addEventListener('click', ()=> {..});
forEach loops are supposed to be working in IE11 and diplay
Object doesn't support property or method 'forEach'.
It should be working since it's an ECMAScript-5 function and IE11 supports it.
However, my code here is not working:
var alltable = document.querySelectorAll('*[id^="table_"]'); //Select all elements with the id starting by "table_"
alltable.forEach(function(element) {
// Do some code
});
Any idea why ?
Well myself,
forEach() is actually working on IE11, just be careful on how you call it.
querySelectorAll() is a method which return a NodeList.
And on Internet Explorer, foreach() only works on Array objects. (It works with NodeList with ES6, not supported by IE11).
To fix this, some would advice a polyfill, which could work great, but you can also simply convert your NodeList into an array with the slice.call() method: (Explained here)
var alltable = document.querySelectorAll('*[id^="table_"]'); //Select all elements with the id starting by "table_"
var alltableArray= Array.prototype.slice.call(alltable);
alltableArray.forEach(function(element) {
// Do some code
});
Or:
var alltable = Array.prototype.slice.call(document.querySelectorAll('*[id^="table_"]')); //Select all elements with the id starting by "table_"
alltable.forEach(function(element) {
// Do some code
});
To sum up:
Be sure you're using it on an Array object and not a NodeList.
Hope that can help someone.
I am trying to run a function onclick of any button with class="stopMusic". I'm getting an error in Firebug
document.getElementByClass is not a function
Here is my code:
var stopMusicExt = document.getElementByClass("stopButton");
stopButton.onclick = function() {
var ta = document.getElementByClass("stopButton");
document['player'].stopMusicExt(ta.value);
ta.value = "";
};
You probably meant document.getElementsByClassName() (and then grabbing the first item off the resulting node list):
var stopMusicExt = document.getElementsByClassName("stopButton")[0];
stopButton.onclick = function() {
var ta = document.getElementsByClassName("stopButton")[0];
document['player'].stopMusicExt(ta.value);
ta.value = "";
};
You may still get the error
document.getElementsByClassName is not a function
in older browsers, though, in which case you can provide a fallback implementation if you need to support those older browsers.
Before jumping into any further error checking please first check whether its
document.getElementsByClassName() itself.
double check its getElements and not getElement
As others have said, you're not using the right function name and it doesn't exist univerally in all browsers.
If you need to do cross-browser fetching of anything other than an element with an id with document.getElementById(), then I would strongly suggest you get a library that supports CSS3 selectors across all browsers. It will save you a massive amount of development time, testing and bug fixing. The easiest thing to do is to just use jQuery because it's so widely available, has excellent documentation, has free CDN access and has an excellent community of people behind it to answer questions. If that seems like more than you need, then you can get Sizzle which is just a selector library (it's actually the selector engine inside of jQuery and others). I've used it by itself in other projects and it's easy, productive and small.
If you want to select multiple nodes at once, you can do that many different ways. If you give them all the same class, you can do that with:
var list = document.getElementsByClassName("myButton");
for (var i = 0; i < list.length; i++) {
// list[i] is a node with the desired class name
}
and it will return a list of nodes that have that class name.
In Sizzle, it would be this:
var list = Sizzle(".myButton");
for (var i = 0; i < list.length; i++) {
// list[i] is a node with the desired class name
}
In jQuery, it would be this:
$(".myButton").each(function(index, element) {
// element is a node with the desired class name
});
In both Sizzle and jQuery, you can put multiple class names into the selector like this and use much more complicated and powerful selectors:
$(".myButton, .myInput, .homepage.gallery, #submitButton").each(function(index, element) {
// element is a node that matches the selector
});
It should be getElementsByClassName, and not getElementByClass. See this - https://developer.mozilla.org/en/DOM/document.getElementsByClassName.
Note that some browsers/versions may not support this.
My solutions is:
Change:
document.getElementsByClassName('.className')
To:
document.querySelector('.className')
you spelt it wrongly, it should be " getElementsByClassName ",
var objs = document.getElementsByClassName("stopButton");
var stopMusicExt = objs[0]; //retrieve the first node in the stack
//your remaining function goes down here..
document['player'].stopMusicExt(ta.value);
ta.value = "";
document.getElementsByClassName - returns a stack of nodes with more than one item, since CLASS attributes are used to assign to multiple objects...
it should be getElementsByClassName NOT getElementByClassName ==> you missed "s" in Elements
const collectionItems = document.getElementsByClassName('.item');
document.querySelectorAll works pretty well and allows you to further narrow down your selection.
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
document.getElementByClass is not a function
Yes, it is not a function nor method because it should be document.getElementsByClassName
enter code here
var stopMusicExt = document.getElementByClass("stopButton").value;
stopButton.onclick = function() {
var ta = document.getElementByClass("stopButton");
document['player'].stopMusicExt(ta.value);
ta.value = "";
};
// .value will hold all data from class stopButton
The getElementByClass does not exists, probably you want to use getElementsByClassName. However you can use alternative approach (used in angular/vue/react... templates)
function stop(ta) {
console.log(ta.value) // document['player'].stopMusicExt(ta.value);
ta.value='';
}
<input type="button" onclick="stop(this)" class="stopMusic" value='Stop 1'>
<input type="button" onclick="stop(this)" class="stopMusic" value='Stop 2'>
If you wrote this "getElementByClassName" then you will encounter with this error "document.getElementByClass is not a function" so to overcome that error just write "getElementsByClassName". Because it should be Elements not Element.
jQuery collections are array-like Objects with a length property and methods from Array.prototype like splice, sort, and push. I'm aware that those methods are not chainable like typical jQuery methods, but the methods do work as expected.
Are there any reasons not to manipulate jQuery collections using those Array.prototype methods such as browser compatibility or issues with other jQuery methods?
Example
In a loop, add elements to a jQuery collection for later manipulation.
var $divs = $(); // Create empty jQuery collection.
for (i = 0; i < 8; i++) {
var div = document.createElement('div');
div.innerHTML = i+1;
$divs.push(div); // Add newly created div to collection
}
$divs.addClass('red').appendTo(document.body);
View on Codepen
Using push here instead of $divs = $divs.add(div); is more succinct and seems more efficient. If jsperf were working right now, I'm sure it would show better performance with push.
Here is .add from the jQuery source:
add: function( selector, context ) {
return this.pushStack(
jQuery.uniqueSort(
jQuery.merge( this.get(), jQuery( selector, context ) )
)
);
},
In this function 3 more methods are called... .merge, .uniqueSort (which is actually SizzleJS), and .pushStack...
In addition to just .push, jQuery will:
Merge your input if it's an array of selectors. (.merge)
Remove any duplicate entries. (.uniqueSort)
Accept flexible input with DOM elements (.pushStack)
So, to conclude that, if you're worried about input, .add is good to use, since jQuery makes it flexible (regular DOM or jQuery objects work), but it also removes duplicate entries and can take in multiple items with an array.
You can pass an Array into jQuery, this means you can make full use of a native Array
// build
var j, el, ly = [];
for (j = 0; j < 3; ++j) {
el = document.createElement('span');
ly.push(el);
}
// wrap
var jq = $(ly); // jQuery object [<span>, <span>, <span>]
Adding more elements can be done with pushStack and another Array
jq.pushStack([document.createElement('div')]);
jq; // [<span>, <span>, <span>, <div>]
Or more generally using add which accepts any input the normal jQuery constructor takes
jq.add(document.createElement('hr'));
jq; // [<span>, <span>, <span>, <div>, <hr>]
I am trying to check whether the a css class is used inside the DOM or not. So, I have
var x = document.getElementsByClassName('classname');
When I print x out, I get a [object NodeList] for classes that exist on the page and classes that dont. Is there a property of x that I can access ? Like the tag name or something. Would be great if somebody can tell me the different properties of x and the ways I can access them.
Thank you :)
Notice that it's plural:
var x = document.getElementsByClassName('classname');
^
You need to iterate over x to get the individual elements:
for (var i = 0; i < x.length; i++) {
var element = x[i];
console.log(element);
}
Make sure to add fallback support for Internet Exploder: http://ejohn.org/blog/getelementsbyclassname-speed-comparison/
If you just want to check for the presence of a class in the document, you can also use querySelector.
var x = document.querySelector('.classname');
It returns null if no elements have that class, otherwise the first element with that class name. If you want all elements using classname:
var x = document.querySelectorAll('.classname');
Now x is null if the class is not used in the document, otherwise a Nodelist, containing all elements with class classname, which can be iterated the way Blender showed. In that iteration you can, for example, retrieve the elements tagName or its id. Like:
for (var i=0;i<x.lenght;(i=i+1)){
console.log(x[i].id + ': ' + x[i].tagName);
}
document.querySelector is available in all modern browsers, and for IE version 8 and up.
I almost always use document.querySelector (which: "Returns the first element within the document that matches the specified group of selectors"), which returns an element object and it's.
I don't know why but in my Chrome's console I write:
var img = document.getElementsByClassName('image__pic');
img[0]...
img[0], despite its happy existance, it doesn't generate any further attributes/methods to use in the completion window. Like there were none (even though I could use img[0].src for instance)
On the other hand:
var imgq = document.querySelector('.image__pic')
Gives me very useful autocompletion on the Console:
As far as its browser support it is phenomenal:
It is also less tricky to use, because getElementsByClassName returns an HTMLCollection, which is a little beast of its own.
Another plus for querySelector is its versatility: any kind of CSS selector goes!
On the negative side, querySelector is a bit slower, but I think it's worth it.