How to check if an element with .Attr has a particular class? - javascript

This is the HTML structure:
<div data-step="1"></div>
<div data-step"2" class="active"></div>
Something along those lines (the following is obviously wrong, it's just to provide an idea)
if($("div").attr("data-step", "2").hasClass("active")) {
//do this...
}

Use attribute equals selector to get the element with a certain attribute value. With attr() method it simply sets the attribute value and returns the jQuery element object.
if($("div[data-step='2']").hasClass("active"))
// or simply combine the class with selector and
// check existance simply by checking its length
if($("div[data-step='2'].active").length)

Related

How do you grab an element relative to an Element instance with a selector?

I am writing a small library where I am in need of selecting a relative element to the targeted element through querySelector method.
For example:
HTML
<div class="target"></div>
<div class="relative"></div>
<!-- querySelector will select only this .target element -->
<div class="target"></div>
<div class="relative"></div>
<div class="target"></div>
<div class="relative"></div>
JavaScript
var target = document.querySelectorAll('.target')[1];
// Something like this which doesn't work actually
var relativeElement = target.querySelector('this + .relative');
In the above example, I am trying to select the .relative class element relative only to the .target element whose value is stored in target variable. No styles should apply to the other .relative class elements.
PS: the selectors can vary. So, I can't use JavaScript's predefined methods like previousElementSibling or nextElementSibling.
I don't need solution in jQuery or other JavaScript libraries.
Well it should be ideally:
var relativeElement = target.querySelector('.relative');
But this will actually try to select something inside the target element.
therefore this would only work if your html structure is something like:
<div class="target">
<div class="relative"></div>
</div>
Your best bet would probably in this case be to use nextElementSibling which I understand is difficult for you to use.
You cannot.
If you insist on using the querySelector of the subject element, the answers is there is no way.
The spec and MDN both says clearly that Element.querySelector must return "a descendant of the element on which it is invoked", and the object element you want does not meet this limitation.
You must go up and use other elements, e.g. document.querySelector, if you want to break out.
You can always override Element.prototype.querySelector to do your biddings, including implementing your own CSS engine that select whatever element you want in whatever syntax you want.
I didn't mention this because you will be breaking the assumption of a very important function, easily breaking other libraries and even normal code, or at best slowing them down.
target.querySelector('.relative');
By using querySelector on the target instead of document, you scope the DOM traversal to the target element.
It is not entirely clear from your explanation, but by related i assume you mean descendant?
To get all target elements you can use
document.querySelectorAll('.target')
And then iterate the result
I found a way which will work for my library.
I will replace "this " in the querySelector with a unique custom attribute value. Something like this:
Element.prototype.customQuerySelector = function(selector){
// Adding a custom attribute to refer for selector
this.setAttribute('data-unique-id', '1');
// Replace "this " string with custom attribute's value
// You can also add a unique class name instead of adding custom attribute
selector = selector.replace("this ", '[data-unique-id="1"] ');
// Get the relative element
var relativeElement = document.querySelector(selector);
// After getting the relative element, the added custom attribute is useless
// So, remove it
this.removeAttribute('data-unique-id');
// return the fetched element
return relativeElement;
}
var element = document.querySelectorAll('.target')[1];
var targetElement = element.customQuerySelector('this + .relative');
// Now, do anything with the fetched relative element
targetElement.style.color = "red";
Working Fiddle

jQuery does not differentiate between span and label

This is interesting.
HTML:
<label name="foo"></label>
<span name="foo"></span>
Javascript:
var foo = $('[name="foo"]');
if (foo.is("span")) {
foo.html('haha');
}
Both the label and span will have the same HTML text. However, if you delete the <span>, than the label will not have its HTML altered. Any reason why, and any way to properly differentiate between them? This is also true if you change if(foo.is("span")) to if(foo.is("label"))
When you use
var foo = $('[name="foo"]');
a collection of elements matching the selector will be returned. To select individual element form it, iterate over it. Using is on a jQuery object will return true if any element in matched set satisfies the condition.
.is()
Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
Use .each():
$('[name="foo"]').each(function() {
if ($(this).is("span")) {
$(this).html('haha');
}
});
The above code is just for the Demo purpose, the following code is equivalent of the above.
$('span[name="foo"]').html('haha');
Agree with Tushar, just use
$('span[name="foo"]')
instead of
$('[name="foo"]')

Get aria-expanded value

I didn't find a way to get aria-expanded value from DOM.
<a class="accordion-toggle collapsed" href="#collapse-One" data-parent="#accordion-1" data-toggle="collapse" aria-expanded="false">
<i class="fa fa-search-plus"></i>
test
</a>
I want to test if it's true then I can change <i> class to fa-search-minus. I tried this but I always get an undefined value:
console.log($(this).find('a.aria-expanded').val());
I wanted to add in a second pure javascript way to get the aria-expanded attribute
document.getElementById('test').getAttribute('aria-expanded')
The above will get the element by id after that you can get any attribute by name.
aria-expanded is an attribute on the element, not a class, so the selector is incorrect. Secondly, you should use the attr() function to get the value of that attribute. val() is intended to retrieve the value attribute from form related elements, such as input and textarea. Try this:
console.log($(this).find('a[aria-expanded]').attr('aria-expanded'));
You can use JavaScript to achieve this:
document.getElementsByTagName('a')[0].attributes[4].value
Step by step explanation:
Get the wanted element, by using some selector - here I use the
document.getElementsByTagName('a')[0]
but you can use any other selector you like.
Access the attributes array of the element and find the position of the wanted attribute - in this case that will be 4, because aria-expanded is the 5th attribute of the tag.
From there you just get the value, and that should give you "false" (in this case).
The only problem with this method is that it's a bit hard-coded, so if you add some more attributes to the tag, the position in the attributes array for the aria-expanded attribute might change.
UPDATE
Instead of using the index for accessing the Aria Expanded property, you can use the name:
document.getElementsByTagName('a')[0].attributes['aria-expanded'].value
This way you will always get the value for the Area Expanded property, regardless of it's position in the HTML tag.
Update 02/2023:
ariaExpanded property still does not work on Firefox. It will be undefined.
Another way to get aria values is to reference the properties directly:
For your instance, you could do something like this:
let firstAnchorTag = document.getElementsByTagName('a')[0]; // I don't know your situation but I recommend adding an id to this element, or making this an iterable array.
console.log(firstAnchorTag.ariaExpanded); // Should log 'false' for your example.
To get:
let el = document.getElementById('foobar');
console.log(el.ariaExpanded); // Should log the current value of aria-expanded.
To set:
let el = document.getElementById('foobar');
el.ariaExpanded = 'true';
console.log(el.ariaExpanded); // Should log 'true'.
Reference: Element.ariaExpanded MDN
In 2020, I could do:
document.querySelector('[aria-expanded]')?.getAttribute('aria-expanded')
to grab the first value and maybe something like:
Array.from(document.querySelectorAll('[aria-expanded]'))?
.map(el => el.getAttribute('aria-expanded'))
to make an array of all aria-expanded values.
attr() function is used to get value of attribute whereas val() is used to retrieve the value attribute from form the related elements, i.e. textbox,input etc. Also aria-expanded is an attribute not a class so you are using incorrect selector.
So you should use attr() instead of val().
Use this:
console.log($(this).find('a[aria-expanded]').attr('aria-expanded'))
You can get the element by the class name "accordion-toggle" (if you have it just one time), or better add an ID to the element, and then get the attribute.
$('.accordion-toggle').attr('aria-expanded')
Or
$('#id-name').attr('aria-expanded')

What is the difference between the selectors #id and [id$='id']?

What is the difference between two statements:
$("span[id$='id']").text(var);
// And
$("#id").text(var);
HTML code is : <span class="normal11" id="id"></span>
The first one is using ends with selector while the second one is using just normal id selector.
Attribute Ends With Selector [name$="value"]
ID Selector ("#id")
By the documentation on JQuery:
$("#id") uses the JavaScript function document.getElementById(), which is extremely efficient. Link.
So, the second way should be faster and should be used.
Some different between id selector and attribute selector is
Since id selector called document.getElementById(),
it only return the first element that have a id equal to that.
However, if you use attribute selector, it will return all elements that have the id attribute that equals to that.
But duplicated id is actually invalid in HTML, and should never used.
if you really want to do that, use class instead.
example
$("#id-selector").click(function(){
$("#test").css("color", "red");
});
$("#attr-selector").click(function(){
$("*[id=test]").css("color", "blue");
});
http://jsfiddle.net/toucyqas/1/

jquery hasClass, can it be given the beginning of class name, to get the full class name

I'm trying to do something similar to this question, but it's a bit different, so the solution there isn't working for me.
<span class="a-class another-class test-top-left"></span>
I have an element (this code shows a span but it could be div span or anything). This element has a class beginning with test- (test-top-left, test-top-right etc.) I've triggered a click event on classes starting with test- and saved the clicked object as var object = this;. Simple stuff so far.
What I'm trying to do now is get the full name of that class (test-top-left). I know it starts with test- but what's the full name. The thing is that there are other classes a-class another-class and test-top-left. Can hasClass be used to get the full name of the class? I'd prefer not to use find() or filter() just because there may be additional elements within that also have class="test-"
Edit:
The code I have now is, but it gives me ALL the classes. What I need is the single class beginning with test-.
var object = this;
$(object).attr('class');
So now I for loop through all the classes and test each one separately, which seems like a lot of unnecessary code. I'm hoping jQuery has a clever way to get the exact class that was clicked right away.
Description
You can use jQuerys Attribute Contains Selector, .attr() and .click() method.
Attribute Contains Selector - Selects elements that have the specified attribute with a value containing the a given substring.
.attr() - Get the value of an attribute for the first element in the set of matched elements.
.click() - Bind an event handler to the "click" JavaScript event, or trigger that event on an element.
Sample
html
<span class="anyclass test-hello">Hello World</span>​
jQuery
$("[class*='test']").click(function() {
var object = $(this);
alert(object.attr("class").match(/(test-.*?)(?:\s+|$)/)[1])
;});
Check out the updated jsFiddle
Update
If you dont want to use regex you can do this.
$("[class*='test']").click(function() {
var object = $(this);
alert("test-" + object.attr("class").split("test-")[1].split("-"))
;});
​
More Information
jQuery - Attribute Contains Selector
jQuery - .attr()
jQuery - .click()
jsFiddle Demonstration
This should work for you:
var object = this;
var className = object.className.match(/(test-.*?)(?:\s+|$)/)[1];
Class name is the name of the class you are looking for.
If you don't want to use split or regex, you can try having the class in a separate attribute
<span class="someclass test-something" _rel="test-something">test<span>
or
<span class="someclass" _rel="test-something">test<span>
with the script
$("[_rel*='test-']").click(....
And to retrieve the attribute, use $(this).attr("_rel")

Categories

Resources