After using slice(), retrieve number of elements containing something within that slice - javascript

I want to use slice to grab every X number of elements, and then return me the count within those items that contains a certain class.
So say I had
$('.product').slice(0, 5)
and inside .product were some divs and lets say the 5 divs inside these product container div are
<div class="col-a" />
<div class="col-a" />
<div class="col-b" />
<div class="col-a" />
<div class="col-a" />
I want it to return me with the count where the slices contain the class "col-b"
So in this case I want it to return me with amountWithColB = 1
var amountWithColB = $('.product').slice(0, 5) ... stuff here {}
Do I even need to slice? Can someone tell me the solution.

Use jQuery's filter method and then take the length of the result:
var number_of_col_b_elems = $('.product div').slice(0, 5).filter(function() {
return $(this).hasClass('col-b');
}).length;

Related

Checking if the values are greater than a certain number in cypress

I have this div and want to check if all the texts within this div are greater than 800. Is there any way to do this in cypress?
<div>
<div>700</div>
<div>720</div>
<div>810</div>
<div>830</div>
<div>850</div>
</div>
it("Show cars below 700 euro", () => {
var prices=cy.get("div > div >").should()
)}
First assign a className for your div, for example value1.
<div className="value1">700</div>
Then:
cy.get(".value1").invoke('text').then(parseFloat).should('be.gte', 800)
Assuming that doing cy.get("div > div") will return you only the elements you want to check, you can simply iterate over the yielded element list, using .each()
cy.get("div > div").each((el) => {
const text = el.text();
expect(text).to.be.greaterThan(800);
})
If the div > div does not uniquely yield only the elements you want to check, you will need to find a different way to uniquely isolate these elements. Adding a className, like Ali suggests, is one way.

JavaScript possible to select all elements with classname that starts with (...)? [duplicate]

I'm trying to only show certain divs. The way I have decided to do this is to first hide all elements that start with "page" and then only show the correct divs. Here's my (simplified) code:
<form>
<input type="text" onfocus="showfields(1);">
<input type="text" onfocus="showfields(2);">
</form>
<div class="page1 row">Some content</div>
<div class="page1 row">Some content</div>
<div class="page2 row">Some content</div>
<div class="page2 row">Some content</div>
<script>
function showfields(page){
//hide all items that have a class starting with page*
var patt1 = /^page/;
var items = document.getElementsByClassName(patt1);
console.log(items);
for(var i = 0; i < items.length; i++){
items[i].style.display = "none";
}
//now show all items that have class 'page'+page
var item = document.getElementsByClassName('page' + page);
item.style.display = '';
}
</script>
When I console.log(items); I get a blank array. I'm pretty sure the regexp is right (get all items starting with 'page').
The code I'm using is old school JS, but I'm not adverse to using jQuery. Also if there is a solution that doesn't use regexp, that's fine too as I'm new to using regexp's.
getElementsByClassName only matches on classes, not bits of classes. You can't pass a regular expression to it (well, you can, but it will be type converted to a string, which is unhelpful).
The best approach is to use multiple classes…
<div class="page page1">
i.e. This div is a page, it is also a page1.
Then you can simply document.getElementsByClassName('page').
Failing that, you can look to querySelector and a substring matching attribute selector:
document.querySelectorAll("[class^=page]")
… but that will only work if pageSomething is the first listed class name in the class attribute.
document.querySelectorAll("[class*=page]")
… but that will match class attributes which mention "page" and not just those with classes which start with "page" (i.e. it will match class="not-page".
That said, you could use the last approach and then loop over .classList to confirm if the element should match.
var potentials = document.querySelectorAll("[class*=page]");
console.log(potentials.length);
elementLoop:
for (var i = 0; i < potentials.length; i++) {
var potential = potentials[i];
console.log(potential);
classLoop:
for (var j = 0; j < potential.classList.length; j++) {
if (potential.classList[j].match(/^page/)) {
console.log("yes");
potential.style.background = "green";
continue elementLoop;
}
}
console.log("no");
potential.style.background = "red";
}
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
Previous answers contain parts of the correct one, but none really gives it.
To do this, you need to combine two selectors in a single query, using the comma , separator.
The first part would be [class^="page"], which will find all the elements whose class attribute begins with page, this selector is thus not viable for elements with multiple classes, but this can be fixed by [class*=" page"] which will find all the elements whose class attribute have somewhere the string " page" (note the space at the beginning).
By combining both selectors, we have our classStartsWith selector:
document.querySelectorAll('[class^="page"],[class*=" page"]')
.forEach(el => el.style.backgroundColor = "green");
<div class="page">Yes</div>
<div class="notpage">No</div>
<div class="some page">Yes</div>
<div class="pageXXX">Yes</div>
<div class="page1">Yes</div>
<div class="some">Unmatched entirely</div>
You can use jQuery solution..
var $divs = $('div[class^="page"]');
This will get all the divs which start with classname page
$(document).ready(function () {
$("[class^=page]").show();
$("[class^=page]").hide();
});
Use this to show hide div's with specific css class it will show/hide all div's with css class mention.

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>

show and hide divs with multiple class names jquery checkboxes

I have many dives with multiple classes as
<div class="my-gallery">
<div class="LargeFace Neutral Happy"></div>
<div class="Sad Neutral Happy"></div>
<div class="LargeFace Surprise Happy"></div>
<div class="LargeFace Fear Happy"></div>
</div>
And I have multiple check boxes which have all those values. e.g LargeFace or Happy and else.
<label class="with-label">
<input id="c_b" type="checkbox" name="r1" value="Neutral" />Neutral
</label>
<label class="with-label">
<input id="c_b" type="checkbox" name="r1" value="LargeFace">Large Face
</label>
Through this code I am getting all those checkbox values to an array
$('.with-label').on "click", ->
allVals = []
$('.with-label :checked').each ->
allVals.push $(this).val()
return
console.log allVals
return
Right now I am really really struggling for filtering my divs on the basis of this array values. for example. User have selected multiple check boxes and create an array as ["Happy", "Fear"]
I want to make something which will filter #my-gallery on the basis on that array. If there are 2 those values in an array then All those divs, which contain that classes should appear and other should disappear, So for other values? Is that possible? please help I am struggling with this for so long
Instead of pushing the values in array, You can create a class selector for the value and then push it in array.
$('.with-label :checked').each ->
allVals.push("." + $(this).val())
return
which will create the array as:
[".LargeFace",".Happy"]
Then use .join() to create the class selectors, traverse to parent and show them :
$('.my-gallery > div').hide(); //hide all first
$(allVals.join(',')).show(); //show based on array values
$('.my-gallery > div').each(() => {
if ($(this).attr('class').split(' ').some(className => allVals.includes(className))) {
$(this).show();
} else {
$(this).hide();
}
});
Place this directly after you create your allVals array.
It goes through all your gallery divs and checks if at least one of the classes belongs to allVals.
Older javascript syntax:
$('.my-gallery > div').each(function() {
if ($(this).attr('class').split(' ').some(function(className) {
return allVals.indexOf(className) !== -1;
})) {
$(this).show();
} else {
$(this).hide();
}
});
Try this.
In previous function of jquery use your element which need to be tackle
$('.with-label').on('click', function(){
$(this).closest('.with-label').prev(your_element).toggle();
});

Returning a length from a list of divs, with exceptions to its children not having a certain attribute value

I have a list of divs that I need to traverse to return a particular length. I must add up all the total amount of divs that have active images. Inactive images are denoted by an alt= "missing". I need this particular length size for an ajax interactions.
Question
How can I get the length of parent divs, that do NOT have children elements with a alt tag value of missing? (sorry for the verbosity in selectors)
HTML
<div class="project-img-container">
<div class="modal-image-0">
<img alt="Florence" class="featured" src="/system/works/avatars/000/000/034/medium/florence.jpg?1374131286">
</div>
<div class="modal-image-1">
<img alt="Nexus" class="featured" src="/system/works/avatar_bs/000/000/034/medium/nexus.jpg?1374131286">
</div>
<div class="modal-image-2">
<img alt="Missing" class="featured" src="/images/medium/missing.png">
</div>
<div class="modal-image-3">
<img alt="Missing" class="featured" src="/images/medium/missing.png">
</div>
</div>
Jquery success: postImgModal
postImgModal = function(data, status) {
var activeChildren, children, imgVal;
imgVal = [];
children = $(data).find('.project-img-container').children();
/*
children will return an object list of all divs (which in this case = 4) now I must remove the parent tags that have children img tags that have alt tag's value = "missing."
Lets call this var activeChildren
*/
$.each(activeChildren, function(i, child) {
imgVal[i] = child;
console.log(imgVal[i]);
return imgVal[i];
});
/*this loop should return a length of 2. Opposed to before which was 4. This is because there were 2 missing alt tags above in this example html.*/
}
The final output should be a length of 2 for var activeChildren = 2; and imgVal should return just these two divs
<div class="modal-image-0">
<img alt="Florence" class="featured" src="/system/works/avatars/000/000/034/medium/florence.jpg?1374131286">
</div>
<div class="modal-image-1">
<img alt="Nexus" class="featured" src="/system/works/avatar_bs/000/000/034/medium/nexus.jpg?1374131286">
</div>
$(data).find('.project-img-container').children().filter(function() {
return !$(this).find('[alt="Missing"]').length;
});
FIDDLE
or just:
$(data).find('.project-img-container').children(':has([alt!="Missing"])');
I believe this should work
$('div > img:not([alt="Missing"])').length;
Or This one looks for featured images.
$('div > img.featured:not([alt="Missing"])').length;
jQuery property value is case sensitive so you have to make sure it's in the right case:
$(".project-img-container").find("img:not([alt='Missing'])")
You can just use jQuery selectors to meet your needs. Below expression should serve the purpose.
$('div.project-img-container').find('img[alt!="Missing"]').parent();

Categories

Resources