jQuery select if multiple elements has the same class - javascript

Example HTML:
<div class="elem-1"></div>
<div class="elem-2"></div>
<div class="elem-2"></div>
<div class="elem-3"></div>
<div class="elem-4"></div>
<div class="elem-4"></div>
<div class="elem-4"></div>
Needed:
How can I select the div's which has "elem-2"s and "elem-4"s with jQuery selectors? (multiple elements has same class)

You can use , to separate different selectors:
$(".elem-2, .elem-4")

selector will be given the value that you desire
http://jsfiddle.net/mMEN5/1
var selector = $();
var list = $('[class]').toArray().reduce(function(p, e){
p = p || {};
var classes = $(e).prop('class').split(/\s/);
$.each(classes, function(i,c){
p[c] = p[c] || [];
p[c].push(e);
});
return p;
}, {})
for (el in list) if (list[el].length > 1) selector=selector.add(list[el]);
​

$('.elem-2, .elem-4').hide() // or any other jquery method
By the way, it's not a jQuery selector, it's just a CSS selector, see this article for an explanation

Even though you have asked for css selector, we can also use the attributeStartsWith selector
I will just mention the selector usage. you can use to for any internal DOM chnage
alert($('div[class^="elem-2"], div[class^="elem-4"]').length);
here i have used .length just to give a correct count. Use can use above with id attributes also.

Related

querySelectorAll for grouped data-attributes

Suppose I have the following markup...
<div data-namespace-title="foo"></div>
<div data-namespace-description="bar"></div>
<div data-namespace-button="foo"></div>
Is there anyway in which I can select of them with a querySelectorAll?
I've tried document.querySelectorAll([data-namespace-*]), but that doesn't work of course
There is no easy way to do it, simply because the browser does not implement wildcard selectors on the attribute name/key (only on its value). What you can do is to simply iterate through your element set (in this case, their common denominator is div), and then filter them out.
You can access the list of attributes of each DOM node by calling <Node>.attributes, and then convert that into an array, and check if one or more of each attribute's name matches the regex pattern /^data-namespace-.*/gi:
var els = document.querySelectorAll("div");
var filteredEls = Array.prototype.slice.call(els).filter(function(el) {
var attributes = Array.prototype.slice.call(el.attributes);
// Determine if attributes matches 'data-namespace-*'
// We can break the loop once we encounter the first attribute that matches
for (var i = 0; i < attributes.length; i++) {
var attribute = attributes[i];
// Return the element if it contains a match, and break the loop
if (attribute.name.match(/^data-namespace-.*/gi))
return el;
}
});
console.log(filteredEls);
<div data-namespace-title="foo">title</div>
<div data-namespace-description="bar">description</div>
<div data-namespace-button="foobar">button</div>
<div data-dummy>dummy</div>
Update: if you're familiar with ES6, it gets a lot cleaner, because:
We can use Array.from in place of the cumbersome Array.prototype.slice.call(...). Pro-tip: you can also use the spread operator, i.e. const els = [...document.querySelectorAll("div")].
We can use Array.some in place of manually creating a for loop with return logic
const els = Array.from(document.querySelectorAll("div"));
const filteredEls = els.filter(el => {
const attributes = Array.from(el.attributes);
return attributes.some(attribute => attribute.name.match(/^data-namespace-.*/gi));
});
console.log(filteredEls);
<div data-namespace-title="foo">title</div>
<div data-namespace-description="bar">description</div>
<div data-namespace-button="foobar">button</div>
<div data-dummy>dummy</div>
Not sure if you would be up for changing the format of you attributes, but making them all the same and adding an extra attribute could be of use if you want to using querySelectorAll
Array.from(document.querySelectorAll('[data-namespace]')).forEach(el => {
console.log(el.getAttribute('data-value'))
})
<div data-namespace="title" data-value="foo"></div>
<div data-namespace="description" data-value="bar"></div>
<div data-ns="button" data-value="foo"></div>
<div data-namespace="button" data-value="foo"></div>
Your other option is to use xpath.
Note: When using iterateNext() it will break if you modify the document before calling it.
var divs = document.evaluate('//#*[starts-with(name(.), "data-namespace")]', document, null, XPathResult.ANY_TYPE, null);
var div = divs.iterateNext()
while (div) {
alert(div.ownerElement.textContent)
div = divs.iterateNext()
}
<div data-namespace-title="foo">Foo</div>
<div data-namespace-description="bar">Bar</div>
<div data-ns-button="foo">NS Foo</div>
<div data-namespace-button="foo">Foo</div>
There's no built-in selector for such a thing, but you can still accomplish it easily enough, by selecting all elements and then filtering for those which have an attribute that starts with data-namespace:
console.log(
[...document.querySelectorAll('*')]
.filter(({ attributes }) =>
[...attributes].some(({ name }) => name.startsWith('data-namespace'))
)
);
<div data-baz="baz"></div>
<div data-namespace-title="foo"></div>
<div data-namespace-description="bar"></div>
<div data-namespace-button="foo"></div>

How to get class name of element has specific text using javascript/jquery?

I need a JavaScript or jQuery way of extracting the Class name of DIV element by the text it contains.
Let's illustrate. If I had let's say following code:
<div class="_className">UniqueText</div>
I need to to know how to programmatically do something like this:
getClassNameWhereText("UniqueText");
In this case output should be:
_className
Is there a way to do this?
JQuery :contains selector select element has specific text but it isn't exact. For example
$("div:contains(UniqueText)")
Select both of bottom divs
<div class="_className">UniqueText</div>
<div class="_className2">UniqueText2</div>
You can use .filter() to filter selected element by text.
var className = $("*").filter(function(){
return $(this).text() == "UniqueText";
}).attr("class");
var className = $("*").filter(function(){
return $(this).text() == "UniqueText";
}).attr("class");
console.log(className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_className">UniqueText</div>
<div class="_className2">UniqueText2</div>
By getting all the div with each function you can search through all the divs and place a condition in which you the value of the div is equal to the particular text that you want to find. Then get the class name by using .attr('class').
$( "div" ).each(function(){
if($(this).text() == "UniqueText"){
var output = $(this).attr('class');
$(".output").html(output);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_classname">UniqueText</div>
<div class="output"></div>
It might be a bit long for a code but it gets the work done nicely. :)
You can use :contains(word)
var className = $( "div:contains('John')" ).attr("class");
console.log(className)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">John Resig</div>
<div class="bar">George Martin</div>
<div class="foo">Malcom John Sinclair</div>
<div class="baz">J. Ohn</div>
You can keep an id for your div, as per your information your text will be unique.
<div id="UniqueText" class="_className">UniqueText</div>
and the js code will be
function getClassNameWhereText(text){
var className = $('#'+text).attr('class');
console.log(className);
}
UPDATE : if you want to using contains
then you can do this,
function getClassNameWhereText(text){
var val = document.getElementById(text).value;
if(text.indexOf(val)>=0){
var className = $('#'+text).attr('class');
console.log(className);
}
}
This should be faster than using jQuery (but a bit more to type):
var xpath = "//div[text()='UniqueText']";
var result = document.evaluate(xpath,
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE);
var node = result.singleNodeValue;
if (node) {
console.log(node.className);
} else {
console.error("Not found!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_className">UniqueText</div>
The reason is, browser's CSS selectors don't support :contains selector, and jQuery needs to emulate it by checking every node matching the rest of the selector. Ditto for using .filter. But XPath is done natively by the browser.
You also cannot specify exact match using the jQuery :contains, like here. If substring matching was indeed needed, you can change the XPath:
var xpath = "//div[contains(text(),'UniqueText')]";
XPath is very powerful, but a bit finicky and largely unknown, so I find it is very under-utilised, even when its use would be a perfect fit.

How to hide class in a div

I have several instances of a class in a div. I know the id of the div. I can't get it to work.
$('#ContactPersonChildListDiv').children().filter('.lrml').hide()
This doesn't work.
So I need to hide all the children of the div with id='ContactPersonChildListDiv', that belong to the class lrml.
To hide all the children with that class use > selector:
$('#ContactPersonChildListDiv > .lrml').hide();
If you want to hide all descendants with that class use:
$('#ContactPersonChildListDiv .lrml').hide();
Selecting elements with jQuery is very close (in this case, the same) like you select them with CSS selectors:
E F Matches any F element that is a descendant of an E element. Descendant selectors
E > F Matches any F element that is a child of an element E.
What's your HTML code?
You posted that the id of div is
id='#ContactPersonChildListDiv'
Be sure that # doesn't be in this id, like
<div id='ContactPersonChildListDiv'>
try this:
$('#ContactPersonChildListDiv').children('.lrml').hide();
Fiddle
The HTML:
<div id='ContactPersonChildListDiv'>
<div class='aaa'>AAA</div>
<div class='lrml'>LRML</div>
<div class='bbb'>BBB</div>
</div>
<input type='button' onclick='hideSomeClass()'>
AND JS:
function hideSomeClass(){
var pdiv=document.getElementById('ContactPersonChildListDiv');
var divs=pdiv.children;
for (var i = divs.length - 1; i >= 0; i--) {
if(divs[i].className=='lrml'){
divs[i].style.display='none';
}
};
}
Well, you didn't provide any HTML but this may help you.
Try this:
$('#ContactPersonChildListDiv').find('.lrml').hide();
Youl could also do this way:
$('#ContactPersonChildListDiv .lrml').hide();

jQuery to loop through elements with the same class

I have a load of divs with the class testimonial and I want to use jquery to loop through them to check for each div if a specific condition is true. If it is true, it should perform an action.
Does anyone know how I would do this?
Use each: 'i' is the postion in the array, obj is the DOM object that you are iterating (can be accessed through the jQuery wrapper $(this) as well).
$('.testimonial').each(function(i, obj) {
//test
});
Check the api reference for more information.
try this...
$('.testimonial').each(function(){
//if statement here
// use $(this) to reference the current div in the loop
//you can try something like...
if(condition){
}
});
It's pretty simple to do this without jQuery these days.
Without jQuery:
Just select the elements and use the .forEach() method to iterate over them:
const elements = document.querySelectorAll('.testimonial');
Array.from(elements).forEach((element, index) => {
// conditional logic here.. access element
});
In older browsers:
var testimonials = document.querySelectorAll('.testimonial');
Array.prototype.forEach.call(testimonials, function(element, index) {
// conditional logic here.. access element
});
Try this example
Html
<div class="testimonial" data-index="1">
Testimonial 1
</div>
<div class="testimonial" data-index="2">
Testimonial 2
</div>
<div class="testimonial" data-index="3">
Testimonial 3
</div>
<div class="testimonial" data-index="4">
Testimonial 4
</div>
<div class="testimonial" data-index="5">
Testimonial 5
</div>
When we want to access those divs which has data-index greater than 2 then we need this jquery.
$('div[class="testimonial"]').each(function(index,item){
if(parseInt($(item).data('index'))>2){
$(item).html('Testimonial '+(index+1)+' by each loop');
}
});
Working example fiddle
you can do it this way
$('.testimonial').each(function(index, obj){
//you can use this to access the current item
});
jQuery's .eq() can help you traverse through elements with an indexed approach.
var testimonialElements = $(".testimonial");
for(var i=0; i<testimonialElements.length; i++){
var element = testimonialElements.eq(i);
//do something with element
}
divs = $('.testimonial')
for(ind in divs){
div = divs[ind];
//do whatever you want
}
I may be missing part of the question, but I believe you can simply do this:
$('.testimonial').each((index, element) => {
if (/* Condition */) {
// Do Something
}
});
This uses jQuery's each method: https://learn.jquery.com/using-jquery-core/iterating/
You can do this concisely using .filter. The following example will hide all .testimonial divs containing the word "something":
$(".testimonial").filter(function() {
return $(this).text().toLowerCase().indexOf("something") !== -1;
}).hide();
With a simple for loop:
var testimonials= $('.testimonial');
for (var i = 0; i < testimonials.length; i++) {
// Using $() to re-wrap the element.
$(testimonials[i]).text('a');
}
Without jQuery updated
document.querySelectorAll('.testimonial').forEach(function (element, index) {
element.innerHTML = 'Testimonial ' + (index + 1);
});
<div class="testimonial"></div>
<div class="testimonial"></div>
You could use the jQuery $each method to loop through all the elements with class testimonial.
i => is the index of the element in collection and val gives you the object of that particular element and you can use "val" to further access the properties of your element and check your condition.
$.each($('.testimonal'), function(i, val) {
if(your condition){
//your action
}
});
In JavaScript ES6 .forEach()
over an array-like NodeList collection given by Element.querySelectorAll()
document.querySelectorAll(".testimonial").forEach((el, idx) => {
el.style.color = "red";
console.log(`${idx} Element ${el.tagName} with ID #${el.id} says: ${el.textContent}` );
});
<p class="testimonial" id="1">This is some text</p>
<div class="testimonial" id="2">Lorem ipsum</div>
$('.testimonal').each(function(i,v){
if (condition) {
doSomething();
}
});
More precise:
$.each($('.testimonal'), function(index, value) {
console.log(index + ':' + value);
});

How to use jquery to select all elements that have two specific attributes

I have some markup where a lot of id's have an id attribute, as well as innerText. I want to select each of these elements, performing a function on the id.
How do I do that?
Something like this?
$('[id]:not(:empty)').each(function(i, el) {
// do stuff
});
Give them a common class:
HTML
<div id="first" class="all"></div>
<div id="second" class="all"></div>
<div id="third" class="all"></div>
jQuery
$('div.all').each(function(index){
processid(this.id);
});
If you are talking about selecting elements whose id (or some permutation of it) is included in its text then
$('[id]').filter(function(){
return $(this).text().indexOf( this.id ) >= 0; // the this.id should be altered to match the permutation you seek ..
}).css('color','red'); // turn those to red
After you comment to #lonesomeday (at the question comments) here is what to do ..
$('[id]').each(function(){
processid(this.id);
});
First select by a regular ID selector and then loop over that selection by filtering .text() non-empty.
$("[id]").each(function() {
if ($(this).text() != "") {
// do stuff
}
});

Categories

Resources