getAttribute function not working - javascript

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

Related

jQuery hasClass 'is not a function'

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");
});

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

JavaScript selector for data-event?

Is there a way to select an element based on the data-event attribute?
Here is what I have:
<button data-event="5456293788" class="id-button-yes greenBtn list-buy-buttons">Buy now!</button>
Looking for something like:
document.getElementByDataEvent('5456293788')
Possible?
Something like this?
document.querySelector("button[data-event='5456293788']");
See in JSFiddle
It has quite a wide browser support (even IE 8 supports it)
Use the attribute selector
http://jsfiddle.net/QTNzf/
JS
document.querySelector('button[data-event="5456293788"]' );
CSS
button[data-devent="5456293788"] {
background-color: #eee;
}
The attribute selector does spring to mind, and you don't need jQuery to use that.
It probably won't work on older browsers, though.
If you really want, you can add a getElementsByDataEvent to the document object (not sure if all browsers allow this):
document.getElementsByDataEvent = function(dataEvent)
{
return document.querySelectorAll('[data-event="'+dataEvent+'"]');
};
But as you can see, this is a bit unnecessary, since it's just returning the return-value of a querySelectorAll call. What's more, if you use querySelectorAll directly, you can do something like this
document.querySelectorAll('a[data-event="foo"]');//only links will be retured
//or, with some other data-* thing, along the lines of:
document.querySelectorAll('[class="greenBtn"]');
Use the attribute equals selector in jQuery:
$('[data-event="5456293788"]')
or with document.querySelectorAll:
document.querySelectorAll('[data-event="5456293788"]');
For backwards compatibility, you'd have to iterate through all the elements checking the attribute values. This is a case where a library such as jQuery really helps.
backwards compatible raw js:
function getElementsByAttr(attr, val) {
var nodes,
node,
i,
ret;
val = '' + val;
nodes = document.getElementsByTagName('*');
ret = [];
for (i = 0; i < nodes.length; i += 1) {
node = nodes[i];
if (node.getAttribute(attr) === val) {
ret.push(node);
}
}
return ret;
}
de = getElementsByAttr('data-event', '5456293788');

Getting element by a custom attribute using JavaScript

I have an XHTML page where each HTML element has a unique custom attribute, like this:
<div class="logo" tokenid="14"></div>
I need a way to find this element by ID, similar to document.getElementById(), but instead of using a general ID, I want to search for the element using my custom "tokenid" attribute. Something like this:
document.getElementByTokenId('14');
Is that possible? If yes - any hint would be greatly appreciated.
Thanks.
It is not good to use custom attributes in the HTML. If any, you should use HTML5's data attributes.
Nevertheless you can write your own function that traverses the tree, but that will be quite slow compared to getElementById because you cannot make use of any index:
function getElementByAttribute(attr, value, root) {
root = root || document.body;
if(root.hasAttribute(attr) && root.getAttribute(attr) == value) {
return root;
}
var children = root.children,
element;
for(var i = children.length; i--; ) {
element = getElementByAttribute(attr, value, children[i]);
if(element) {
return element;
}
}
return null;
}
In the worst case, this will traverse the whole tree. Think about how to change your concept so that you can make use browser functions as much as possible.
In newer browsers you use of the querySelector method, where it would just be:
var element = document.querySelector('[tokenid="14"]');
This will be much faster too.
Update: Please note #Andy E's comment below. It might be that you run into problems with IE (as always ;)). If you do a lot of element retrieval of this kind, you really should consider using a JavaScript library such as jQuery, as the others mentioned. It hides all these browser differences.
<div data-automation="something">
</div>
document.querySelector("div[data-automation]")
=> finds the div
document.querySelector("div[data-automation='something']")
=> finds the div with a value
If you're using jQuery, you can use some of their selector magic to do something like this:
$('div[tokenid=14]')
as your selector.
You can accomplish this with JQuery:
$('[tokenid=14]')
Here's a fiddle for an example.
If you're willing to use JQuery, then:
var myElement = $('div[tokenid="14"]').get();
Doing this with vanilla JavaScript will do the trick:
const something = document.querySelectorAll('[data-something]')
Use this more stable Function:
function getElementsByAttribute(attr, value) {
var match = [];
/* Get the droids we are looking for*/
var elements = document.getElementsByTagName("*");
/* Loop through all elements */
for (var ii = 0, ln = elements.length; ii < ln; ii++) {
if (elements[ii].nodeType === 1){
if (elements[ii].name != null){
/* If a value was passed, make sure it matches the elements */
if (value) {
if (elements[ii].getAttribute(attr) === value)
match.push(elements[ii]);
} else {
/* Else, simply push it */
match.push(elements[ii]);
}
}
}
}
return match;
};

Get class list for element with jQuery

Is there a way in jQuery to loop through or assign to an array all of the classes that are assigned to an element?
ex.
<div class="Lorem ipsum dolor_spec sit amet">Hello World!</div>
I will be looking for a "special" class as in "dolor_spec" above. I know that I could use hasClass() but the actual class name may not necessarily be known at the time.
You can use document.getElementById('divId').className.split(/\s+/); to get you an array of class names.
Then you can iterate and find the one you want.
var classList = document.getElementById('divId').className.split(/\s+/);
for (var i = 0; i < classList.length; i++) {
if (classList[i] === 'someClass') {
//do something
}
}
jQuery does not really help you here...
var classList = $('#divId').attr('class').split(/\s+/);
$.each(classList, function(index, item) {
if (item === 'someClass') {
//do something
}
});
Why has no one simply listed.
$(element).attr("class").split(/\s+/);
EDIT: Split on /\s+/ instead of ' ' to fix #MarkAmery's objection. (Thanks #YashaOlatoto.)
On supporting browsers, you can use DOM elements' classList property.
$(element)[0].classList
It is an array-like object listing all of the classes the element has.
If you need to support old browser versions that don't support the classList property, the linked MDN page also includes a shim for it - although even the shim won't work on Internet Explorer versions below IE 8.
Here is a jQuery plugin which will return an array of all the classes the matched element(s) have
;!(function ($) {
$.fn.classes = function (callback) {
var classes = [];
$.each(this, function (i, v) {
var splitClassName = v.className.split(/\s+/);
for (var j = 0; j < splitClassName.length; j++) {
var className = splitClassName[j];
if (-1 === classes.indexOf(className)) {
classes.push(className);
}
}
});
if ('function' === typeof callback) {
for (var i in classes) {
callback(classes[i]);
}
}
return classes;
};
})(jQuery);
Use it like
$('div').classes();
In your case returns
["Lorem", "ipsum", "dolor_spec", "sit", "amet"]
You can also pass a function to the method to be called on each class
$('div').classes(
function(c) {
// do something with each class
}
);
Here is a jsFiddle I set up to demonstrate and test http://jsfiddle.net/GD8Qn/8/
Minified Javascript
;!function(e){e.fn.classes=function(t){var n=[];e.each(this,function(e,t){var r=t.className.split(/\s+/);for(var i in r){var s=r[i];if(-1===n.indexOf(s)){n.push(s)}}});if("function"===typeof t){for(var r in n){t(n[r])}}return n}}(jQuery);
You should try this one:
$("selector").prop("classList")
It returns a list of all current classes of the element.
var classList = $(element).attr('class').split(/\s+/);
$(classList).each(function(index){
//do something
});
$('div').attr('class').split(' ').each(function(cls){ console.log(cls);})
Update:
As #Ryan Leonard pointed out correctly, my answer doesn't really fix the point I made my self... You need to both trim and remove double spaces with (for example) string.replace(/ +/g, " ").. Or you could split the el.className and then remove empty values with (for example) arr.filter(Boolean).
const classes = element.className.split(' ').filter(Boolean);
or more modern
const classes = element.classList;
Old:
With all the given answers, you should never forget to user .trim() (or $.trim())
Because classes gets added and removed, it can happen that there are multiple spaces between class string.. e.g. 'class1 class2 class3'..
This would turn into ['class1', 'class2','','','', 'class3']..
When you use trim, all multiple spaces get removed..
Might this can help you too. I have used this function to get classes of childern element..
function getClickClicked(){
var clickedElement=null;
var classes = null;<--- this is array
ELEMENT.on("click",function(e){//<-- where element can div,p span, or any id also a class
clickedElement = $(e.target);
classes = clickedElement.attr("class").split(" ");
for(var i = 0; i<classes.length;i++){
console.log(classes[i]);
}
e.preventDefault();
});
}
In your case you want doler_ipsum class u can do like this now calsses[2];.
Thanks for this - I was having a similar issue, as I'm trying to programatically relate objects will hierarchical class names, even though those names might not necessarily be known to my script.
In my script, I want an <a> tag to turn help text on/off by giving the <a> tag [some_class] plus the class of toggle, and then giving it's help text the class of [some_class]_toggle. This code is successfully finding the related elements using jQuery:
$("a.toggle").toggle(function(){toggleHelp($(this), false);}, function(){toggleHelp($(this), true);});
function toggleHelp(obj, mode){
var classList = obj.attr('class').split(/\s+/);
$.each( classList, function(index, item){
if (item.indexOf("_toggle") > 0) {
var targetClass = "." + item.replace("_toggle", "");
if(mode===false){$(targetClass).removeClass("off");}
else{$(targetClass).addClass("off");}
}
});
}
Try This. This will get you the names of all the classes from all the elements of document.
$(document).ready(function() {
var currentHtml="";
$('*').each(function() {
if ($(this).hasClass('') === false) {
var class_name = $(this).attr('class');
if (class_name.match(/\s/g)){
var newClasses= class_name.split(' ');
for (var i = 0; i <= newClasses.length - 1; i++) {
if (currentHtml.indexOf(newClasses[i]) <0) {
currentHtml += "."+newClasses[i]+"<br>{<br><br>}<br>"
}
}
}
else
{
if (currentHtml.indexOf(class_name) <0) {
currentHtml += "."+class_name+"<br>{<br><br>}<br>"
}
}
}
else
{
console.log("none");
}
});
$("#Test").html(currentHtml);
});
Here is the working example: https://jsfiddle.net/raju_sumit/2xu1ujoy/3/
For getting the list of classes applied to element we can use
$('#elementID').prop('classList')
For adding or removing any classes we can follow as below.
$('#elementID').prop('classList').add('yourClassName')
$('#elementID').prop('classList').remove('yourClassName')
And for simply checking if the class is present or not we can use hasClass
I had a similar issue, for an element of type image. I needed to check whether the element was of a certain class. First I tried with:
$('<img>').hasClass("nameOfMyClass");
but I got a nice "this function is not available for this element".
Then I inspected my element on the DOM explorer and I saw a very nice attribute that I could use: className. It contained the names of all the classes of my element separated by blank spaces.
$('img').className // it contains "class1 class2 class3"
Once you get this, just split the string as usual.
In my case this worked:
var listOfClassesOfMyElement= $('img').className.split(" ");
I am assuming this would work with other kinds of elements (besides img).
Hope it helps.
javascript provides a classList attribute for a node element in dom. Simply using
element.classList
will return a object of form
DOMTokenList {0: "class1", 1: "class2", 2: "class3", length: 3, item: function, contains: function, add: function, remove: function…}
The object has functions like contains, add, remove which you can use
A bit late, but using the extend() function lets you call "hasClass()" on any element, e.g.:
var hasClass = $('#divId').hasClass('someClass');
(function($) {
$.extend({
hasClass: new function(className) {
var classAttr = $J(this).attr('class');
if (classAttr != null && classAttr != undefined) {
var classList = classAttr.split(/\s+/);
for(var ix = 0, len = classList.length;ix < len;ix++) {
if (className === classList[ix]) {
return true;
}
}
}
return false;
}
}); })(jQuery);
The question is what Jquery is designed to do.
$('.dolor_spec').each(function(){ //do stuff
And why has no one given .find() as an answer?
$('div').find('.dolor_spec').each(function(){
..
});
There is also classList for non-IE browsers:
if element.classList.contains("dolor_spec") { //do stuff

Categories

Resources