jQuery hasClass 'is not a function' - javascript

I want to check with jQuery which li element from a list of li elements is the active one (they represent a menu, and I want to check which menu item is currently active).
So, I store all the li items in a variable, myElements. Then I ask the length of myElements, and apply some style changes to them, up to here everything works. Apparently this way my variable myElements is a Nodelist, not an array, so I declare another variable; myElements_array, which contains the same elements as myElements and is an array (also tested and it works).
Then I try to check which of the elements from myElements_array has the 'current-menu-item' class, but it doesn't work and the google chrome console says there's an error: 'Uncaught TypeError: myElements_array[j].hasClass is not a function'. Does anyone have an idea what the reason might be?
<script type='text/javascript'>
var myElements = jQuery("#navbar > ul > li");
var count = myElements.length;
for (var i = 0; i < myElements.length; i++) {
myElements[i].style.width = (100/count)+'%';
}
var myElements_array = [];
for(var i = myElements.length; i--; myElements_array.unshift(myElements[i]));
var j = 0;
while (! myElements_array[j].hasClass('current-menu-parent') ) {
j++;
}
document.write(j);
</script>

Problem is the index you are pulling from the array is a DOM node when you use bracket notation and it is not a jQuery object. DOM does not have hasClass.
You can either store the jQuery version or change it to jQuery
while (! $(myElements_array[j]).hasClass('current-menu-parent') ) {
or use classList contains
while (! myElements_array[j].classList.contains('current-menu-parent') ) {
or use eq() instead of referencing the DOM
while (! myElements_array.eq(j).hasClass('current-menu-parent') ) {

When you access a jQuery object as if it's an array, it returns the raw DOM element object, not a jQuery object. If you want a jQuery object, use .eq() rather than an array index:
while (myElements.eq(j).hasClass('current-menu-parent') ) {
j++;
}
You could also use:
j = myElements.index(myElements.find(".current-menu-parent:first"));

You shouldn't loop through elements inside an jQuery object like that. You're tyring to use jQuery methods on normal dom objects. Use this instead:
$("#navbar > ul > li").each(function(){
$(this).hasClass("current-menu-parent");
});

Related

getElementsByClassName isn't returning all elements

I'm creating a button that I should highlight certain words within a specified class, but I am having issues with it returning all elements within the class. It will only work if I specify an index, so I'm assuming there may be something wrong with the existing "for loop". Any help is appreciated!
This will work, but only "highlights" the first element in the class, of course:
var bodyText = document.getElementsByClassName('test')[0].innerHTML;
for (var i = 0; i < searchArray.length; i++) {
bodyText = doHighlight(bodyText, searchArray[i], highlightStartTag,
highlightEndTag);}
document.getElementsByClassName('test')[0].innerHTML = bodyText;
return true;
This will not work at all:
var bodyText = document.getElementsByClassName('test').innerHTML;
for (var i = 0; i < searchArray.length; i++) {
bodyText = doHighlight(bodyText, searchArray[i], highlightStartTag,
highlightEndTag);}
document.getElementsByClassName('test').innerHTML = bodyText;
return true;
If you want to replace multiple words in multiple elements, you need two loops:
const testElements = document.getElementsByClassName('test');
for (const element of testElements) {
for (const search of searchArray) {
element.innerHTML = doHighlight(element.innerHTML, search, highlightStartTag, highlightEndTag);
}
}
As you can see getElementsByClassName is pluralized (Elements). Indeed a same class can be assigned to multiple HTML elements. You won't find any way to ommit the [0] and you shouldn't anyway as it might mean you're getting data from the wrong node. If you need data from a specific element that you can ensure is unique then you need to give it an id and use getElementById instead.
You cannot access innerHTML in something which returns an htmlcollection
document.getElementsByClassName('test').innerHTML
Because it's written in plain english: getElementsByClassName. plural.
"Elements".
with an "s" at the end...
meaning it's a (sort of) Array (an htmlcollection)

getAttribute function not working

I am trying to compare a custom attribute of a given element to that custom attribute of all other elements with a specific class... here is what I have
function choose(el){
var text = $(el).getAttribute("data-custom");
var list = document.getElementsByClassName("class");
for (var i = 0; i < list.length ; i++) {
if (list[i].getAttribute("data-custom") == text) {
/*DO STUFF*/
}
}
}
html
<div onclick="choose(this)">STUFF</div>
Currently I get a "$(...).getAttribute is not a function" error.
The jQuery version is $().attr('data-custom'). Note that to access data-* attributes, you can use $().data('custom').
Or you could ditch jQuery (you didn't use it in the very next line) and use
el.getAttribute('data-custom');
// If el is not a DOM element
$(el)[0].getAttribute('data-custom');
Even better, if you don't have to support IE < 11, you can use dataset
el.dataset.custom
You are mixing javascript and jquery.
$(...).attr('your_attr')

Select and add class in javascript

Cross Platform if possible, how can I select classes in Javascript (but not Jquery please -MooTools is fine though-) on code that I can't add an ID?
Specifically, I want to add the class "cf" on any li below:
HTML
<div class="itemRelated">
<ul>
<li class="even">
<li class="odd">
<li class="even">
I tried to fiddle it but something is missing:
Javascript
var list, i;
list = document.getElementsByClassName("even, odd");
for (i = 0; i < list.length; ++i) {
list[index].setAttribute('class', 'cf');
}
JSFiddle
ps. This question phenomenally has possible duplicates, (another one) but none of the answers makes it clear.
Using plain javascript:
var list;
list = document.querySelectorAll("li.even, li.odd");
for (var i = 0; i < list.length; ++i) {
list[i].classList.add('cf');
}
Demo
For older browsers you could use this:
var list = [];
var elements = document.getElementsByTagName('li');
for (var i = 0; i < elements.length; ++i) {
if (elements[i].className == "even" || elements[i].className == "odd") {
list.push(elements[i]);
};
}
for (var i = 0; i < list.length; ++i) {
if (list[i].className.split(' ').indexOf('cf') < 0) {
list[i].className = list[i].className + ' cf';
}
}
Demo
Using Mootools:
$$('.itemRelated li').addClass('cf');
Demo
or if you want to target specific by Class:
$$('li.even, li.odd').addClass('cf');
Demo
I know this is old, but is there any reason not to simply do this (besides potential browser support issues)?
document.querySelectorAll("li.even, li.odd").forEach((el) => {
el.classList.add('cf');
});
Support: https://caniuse.com/#feat=es5
Using some newer browser objects and methods.
Pure JS:
Details: old fashioned way, declaring stuff at the beginging than iterating in one big loop over elements with index 'i', no big science here. One thing is using classList object which is a smart way to add/remove/check classes inside arrays.
var elements = document.querySelectorAll('.even','.odd'),
i, length;
for(i = 0, length = elements.length; i < length; i++) {
elements[i].classList.add('cf');
}
Pure JS - 2:
Details: document.querySelectorAll returns an array-like object which can be accessed via indexes but has no Array methods. Calling slice from Array.prototype returns an array of fetched elements instantly (probably the fastest NodeList -> Array conversion). Than you can use a .forEach method on newly created array object.
Array.prototype.slice.call(document.querySelectorAll('.even','.odd'))
.forEach(function(element) {
element.classList.add('cf');
});
Pure JS - 3:
Details: this is quite similar to v2, [].map is roughly that same as Array.prototype.map except here you declare an empty array to call the map method. It's shorter but more (ok little more) memory consuming. .map method runs a function on every element from the array and returns a new array (adding return in inside function would cause filling the returned values, here it's unused).
[].map.call(document.querySelectorAll('.even','.odd'), function(element) {
element.classList.add('cf');
});
Pick one and use ;)
querySelectorAll is supported in IE8, getElementsByClassName is not, which does not get two classes at the same time either. None of them work in iE7, but who cares.
Then it's just a matter of iterating and adding to the className property.
var list = document.querySelectorAll(".even, .odd");
for (var i = list.length; i--;) {
list[i].className = list[i].className + ' cf';
}
FIDDLE
As others mention for selecting the elements you should use .querySelectorAll() method. DOM also provides classList API which supports adding, removing and toggling classes:
var list, i;
list = document.querySelectorAll('.even, .foo');
for (i = 0; i < list.length; i++) {
list[i].classList.add('cf');
}
As always IE9 and bellow don't support the API, if you want to support those browsers you can use a shim, MDN has one.
If you want to select elements with different classes all together then the best choice is querySelectorAll.
querySelectorAll uses CSS selectors to select elements. As we add the same CSS properties to different elements by separating them by a comma in the same way we can select those elements using this.
.even, .odd {
font-weight: bold;
}
Both elements with class 'even' and 'odd' get bold.
let list = document.querySelectorAll('.even, .odd');
Now, both the elements are selected.
+Point: you should use classList.add() method to add class.
Here is the complete code for you.
let list = document.querySelectorAll('.even, .odd');
for (i = 0; i < list.length; ++i) {
list.classList.add('cf');
}

Get all files for all .uploadedFiles

Im looking for a javascript/jquery (doesn't matter which way) to collect all the files i've uploaded.
I have the following code, where .afbeelding is the class for a couple of file input fields
var geuploadeAfbeeldingen = $('.afbeeldingen').files;
for (var i = 0; i < geuploadeAfbeeldingen.length; i++) {
}
This somehow doesnt seem to work. When i try document.getElementsByClassName it also doesn't work. The funny thing however is, that document.getElementById seem to work on one input field
Any ideas?
This should do what you want
var files = [],
geuploadeAfbeeldingen = $('.afbeeldingen').each(function(){
for (var i = 0; i < this.files.length; i++){
files.push(this.files[i]);
}
});
You end up with an array (files) that holds each file you have selected through the input elements..
Demo at http://jsfiddle.net/gaby/GJW7Y/1/
If you only want the filenames then change
files.push(this.files[i]);
with
files.push(this.files[i].name);
Try this way :
var geuploadeAfbeeldingen = $('.afbeeldingen');
for (var i = 0; i < geuploadeAfbeeldingen.length; i++) {
alert(geuploadeAfbeeldingen[i].files[0].name);
}
This may help you.
Edit :
$('.afbeeldingen').files is not work and document.getElementById().files is worked because first one return JQuery object( array of objects) and second one return DOM object.The jQuery object (created by the $ method) is a wrapper around a DOM element or a set of DOM elements. The normal properties and methods are not available with JQuery object.
You need to loop through each input element and return the files property.
Something like this is probably the shortest way, using map to iterate through an array:
var geuploadeAfbeeldingen = $('.afbeeldingen').map(function(k, v) { return v.files[0]; }).get();

How to hide all elements of class?

I found this function:
document.getElementsByClassName = function(c){
for(var i=0,a=[],o;o=document.body.getElementsByTagName('*')[i++];){
if(RegExp('\\b'+c+'\\b','gi').test(o.className)){
a.push(o);
}
}
return a;
}
How can I hide all elements by class?
I tried:
var array = document.getElementsByClassName("hide");
for(var i = 0; i < array.length; i++)
{
$(array[i]).hide();
}
But I got error:
Could not convert JavaScript argument arg 0 [nsIDOMWindow.getComputedStyle]
jQuery allows CSS selectors to be used, doing away with the need for hand-built loops and regular expressions. To hide an element with class fooey, just do
$('.fooey').hide();
If you're using vanilla JavaScript, then:
var array = document.getElementsByClassName("hide");
for(var i = 0; i < array.length; i++)
{
array[i].style.display = 'none';
array[i].onclick = function(){
// do stuff
};
/* or:
array[i].addEventListener('click',functionToCall);
*/
}
But, given that you're using jQuery, I don't understand why you're complicating things for yourself, just use:
$('.hide').hide();
Further to the above, given your comment:
Because I must add event "click" for each element.
Simply use:
$(elementSelector).click(
function(){
// do stuff
});
Assuming you want to hide, and bind a click-event to, the same elements:
$('.hide').hide().click(
function(){
// do stuff
});
What you get from getElementsByClassName is NOT an array, but a NodeList, hence the error when trying to loop.
However, you can still loop over a NodeList using the following:
var nodeList = document.getElementsByClassName("hide");
for(var x in nodeList){}

Categories

Resources