Recursion of .children() to search for id attribute - javascript

I'm new to jQuery, familiar with PHP & CSS. I have nested, dynamically generated div's which I wish to send (the id's) to a server-side script to update numbers for. I want to check everything in the .content class. Only div's with id's should be sent for processing; however I'm having trouble making a recursive children() check...this is the best (non-recursively) I could do:
$(".content").children().each(function() {
if ($(this).attr('id').length == 0) {
$(this).children().each(function() {
if ($(this).attr('id').length == 0) {
$(this).children().each(function() {
if ($(this).attr('id').length == 0) {
$(this).children().each(function() {
alert($(this).attr('id'));
});
}
});
}
});
}
});
and it just alert()'s the id's of everything at the level where they should be. There must be a better way to do this...thank you in advance for any advice.
-Justin

Try:
var ids = $('.content div[id]').map(function() {
return this.id;
}).get();
.content div[id] will select you all div descendants (at any level) of .content with non-empty ID attributes. The [id] part is an example of the Has Attribute selector.
I have used .map. to extract the IDs of the matches, and .get() to convert the resulting object into a basic array.
Try it here: http://jsfiddle.net/M96yK/

You can do:
$(".content div[id]");
This will return a jQuery object that contains all div's which have id's specified

Related

Wildcards in jQuery attribute's name selector?

How can I select all elements which contain data attributes starting with "data-my-" in the following code? I'm not going to add wildcards to attribute value, It's attribute's name.
<p data-my-data="aa">foo</p>
<p data-my-info="bb">bar</p>
What I tried and failed:
$("[data-my-*]").addClass("myClass");
You can't write a selector with a wildcard for attribute names. There isn't a syntax for that in the standard, and neither in jQuery.
There isn't a very efficient way to get just the elements you want without looping through every element in the DOM. It's best that you have some other way of narrowing down your selection to elements that are most likely to have these namespaced data attributes, and examine just these elements, to reduce overhead. For example, if we assume only p elements have these attributes (of course, you may need to change this to suit your page):
$("p").each(function() {
const data = $(this).data();
for (const i in data) {
if (i.indexOf("my") === 0) {
$(this).addClass("myClass");
break;
}
}
});
.myClass {
color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p data-my-data="aa">foo</p>
<p data-my-info="bb">bar</p>
<p>baz</p>
there is no wildcarding for attribute names.so u can get result like below
$( "p" ).each(function( i ) {
element=this;
$.each(this.attributes, function() {
if(this.name.indexOf('data-my-') != -1) $(element).addClass("myClass");
});
});
Just a slightly shorter, but otherwise very similar version to #BoltClock's.
Note: using ES6 syntax.
$('p')
.filter((_, el) => Object.keys($(el).data()).find(dataKey => dataKey.indexOf('my') === 0))
.addClass('myClass');
.myClass { color: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p data-my-data="aa">foo</p>
<p data-my-info="bb">bar</p>
<p>baz</p>

Select element by tag/classname length

I'd like to select an element using javascript/jquery in Tampermonkey.
The class name and the tag of the elements are changing each time the page loads.
So I'd have to use some form of regex, but cant figure out how to do it.
This is how the html looks like:
<ivodo class="ivodo" ... </ivodo>
<ivodo class="ivodo" ... </ivodo>
<ivodo class="ivodo" ... </ivodo>
The tag always is the same as the classname.
It's always a 4/5 letter random "code"
I'm guessing it would be something like this:
$('[/^[a-z]{4,5}/}')
Could anyone please help me to get the right regexp?
You can't use regexp in selectors. You can pick some container and select its all elements and then filter them based on their class names. This probably won't be super fast, though.
I made a demo for you:
https://codepen.io/anon/pen/RZXdrL?editors=1010
html:
<div class="container">
<abc class="abc">abc</abc>
<abdef class="abdef">abdef</abdef>
<hdusf class="hdusf">hdusf</hdusf>
<ueff class="ueff">ueff</ueff>
<asdas class="asdas">asdas</asdas>
<asfg class="asfg">asfg</asfg>
<aasdasdbc class="aasdasdbc">aasdasdbc</aasdasdbc>
</div>
js (with jQuery):
const $elements = $('.container *').filter((index, element) => {
return (element.className.length === 5);
});
$elements.css('color', 'red');
The simplest way to do this would be to select those dynamic elements based on a fixed parent, for example:
$('#parent > *').each(function() {
// your logic here...
})
If the rules by which these tags are constructed are reliably as you state in the question, then you could select all elements then filter out those which are not of interest, for example :
var $elements = $('*').filter(function() {
return this.className.length === 5 && this.className.toUpperCase() === this.tagName.toUpperCase();
});
DEMO
Of course, you may want initially to select only the elements in some container(s). If so then replace '*' with a more specific selector :
var $elements = $('someSelector *').filter(function() {
return this.className.length === 5 && this.className.toUpperCase() === this.tagName.toUpperCase();
});
You can do this in vanilla JS
DEMO
Check the demo dev tools console
<body>
<things class="things">things</things>
<div class="stuff">this is not the DOM element you're looking for</div>
</body>
JS
// Grab the body children
var bodyChildren = document.getElementsByTagName("body")[0].children;
// Convert children to an array and filter out everything but the targets
var targets = [].filter.call(bodyChildren, function(el) {
var tagName = el.tagName.toLowerCase();
var classlistVal = el.classList.value.toLowerCase();
if (tagName === classlistVal) { return el; }
});
targets.forEach(function(el) {
// Do stuff
console.log(el)
})

check if class does not exist on any of data- items

I have a list of div elements with a data-windows attribute:
I basically want to check if any of these are not hidden (and doing something if they are all hidden)
I'm looping through them like so, this works but I'm wondering if there's a more efficient way:
$("[data-windows]").each(function () {
if (!$(this).hasClass('hidden')) {
isSomethingShown = true;
return false;
}
});
You can use :visible pseudo selector :
if($("[data-windows]:visible").length){
//Atleast 1 is visible
}else{
//All hiden
}
or
var isSomethingShown = !!$("[data-windows]:visible").length; // Bang!Bang! [!!] convert into a boolean
Of course, if you want to explicitly check the class, both selector can be change to (and maybe should be for faster performance) $("[data-windows].hidden")
how bout this oneliner:
return $("[data-windows].hidden").length == 0 ? false : true;

Check if any childnodes exist using jquery / javascript

I have a DOM structure with div, p and span tags. I want to count the 'p' tags with children nodes and that without any children. I read a solution in this forum, but it doesn't work for me: How to check if element has any children in Javascript?.
Fiddle demo
$('#test').blur(function(){
var test= $('.check p').filter(function (){
if ($(this).childNodes.length > 0)
return this
});
alert(test.lenght)
})
it should be
$('#test').blur(function(){
var test= $('.check p').filter(function (){
return this.childNodes.length > 0; // as HMR pointed out in the comments if you are looking for child elements then $(this).children().length will do
})
alert(test.length)
})
Demo: Fiddle
Did you try this?
$('p:empty')
Should select all your empty p tags.
$('p').not(':empty')
Should select all your non empty p tags.
Here: http://jsfiddle.net/QN3aM/9/
$('#test').blur(function () {
var test = $('.check p').filter(function () {
return ($(this).children().length)
});
alert(test.length);
})
You just need to return true within filter, 0 is a falsey value and anything else will be truthy. also you spelt length wrong.
childNodes is a property of an element. as you were converting the element into a jquery object, you'd have to use the jquery method children()

Use jquery to change the class of a target element from array

I have a List li of elements that I used .toArray(). I now need to loop through them to find the desired element and change its style Class.
I am not sure what I am doing wrong, but I cannot seem to get the class of the index item, but I can retrieve the innerHTML no problem.
var viewsIndex = $('#viewsList li').toArray()
for(i=0; i < viewsIndex.length; i++) {
if(viewsIndex[i].innerHTML == selectedTab) {
console.log(viewsIndex[i].attr('style')); //This does NOT work
console.log(viewsIndex[i].innerHTML); //This does work
}
else
{
}
}
Once I target the Element, I want to use .removeClass and .addClass to change the style.
This is the DOM object which doesn't have jQuery functions:
viewsIndex[i]
This is the jQuery object which has the attr function:
$(viewsIndex[i]).attr('style')
Anyway, your code could be a lot simpler with this:
$('#viewsList li').filter(function(){
return this.innerHTML == selectedTab;
}).removeClass('foo').addClass('bar');
You are trying to call jQuery function on DOM object convert it to jQuery object first.
Change
viewsIndex[i].attr('style')
To
$(viewsIndex[i]).attr('style')
couldn't you use .each()?
$('#viewLists li').each(function(i){
if($(this).html == selectedTab){
$(this).removeClass('foo').addClass('bar');
}
});
Loop over the elements using jQuery each and then access them as $(this). This way you'll have access to jQuery methods on each item.
$('#viewsList li').each(function(){
var element = $(this);
if(element.html() == selectedTab){
console.log(element.attr('style')
} else {
}
}

Categories