Here, I have parent div of class = "alphabets" and have child div's all with same class = "word"
<div class="alphabets">
<div class="word"> abc </div> //1st child
<div class="word"> def </div> //2nd child
<div class="word"> ghi </div> //3rd child
<div class="word"> jkl </div> //4th child
<div class="word"> mno </div> //5th child
</div>
what I need is When I clicked on 'jkl'. fun() should return its index i.e whether it is 1st child or 2ndchild or 6th child...
You can use indexOf on the children (after converting it to an array) of the parent element.
document.querySelector('.alphabets').addEventListener('click', function(e){
if (e.target.matches('.word')) console.log([...this.children].indexOf(e.target));
});
<div class="alphabets">
<div class="word"> abc (1st child)</div>
<div class="word"> def (2nd child)</div>
<div class="word"> ghi (3rd child)</div>
<div class="word"> jkl (4th child)</div>
<div class="word"> mno (5th child)</div>
</div>
Related
In my below HTML markup, I'd like to query the <div> that has a data-parent set to "true", and the contained child has data-child-gender set to "true" and inner html is "male".
<div id="grandparent">
<div id="parent1" data-parent="true">
<div id="child1" data-child-gender="false">
male
</div>
</div>
<div id="parent2" data-parent="true">
<div id="child2" data-child-gender="true">
female
</div>
</div>
<div id="parent3" data-parent="false">
<div id="child3" data-child-gender="true">
female
</div>
</div>
<div id="parent4" data-parent="true">
<div id="child4" data-child-gender="true">
male
</div>
</div>
</div>
Given the above scenario, the expected <div> is parent4.
What is the JavaScript querySelector to use?
First use querySelectorAll which will give an array. Then iterate over it and check and get element with required data attribute.
After that you can use use a if & check the content inside it
let k = document.querySelectorAll('[ data-parent=true]').forEach(function(item) {
let elem = item.querySelector('[data-child-gender=true]');
if (elem !== null && elem.innerHTML.trim() === 'male') {
console.log(item.id)
}
})
<div id="grandparent">
<div id="parent1" data-parent="true">
<div id="child1" data-child-gender="false">
male
</div>
</div>
<div id="parent2" data-parent="true">
<div id="child2" data-child-gender="true">
female
</div>
</div>
<div id="parent3" data-parent="false">
<div id="child3" data-child-gender="true">
female
</div>
</div>
<div id="parent4" data-parent="true">
<div id="child4" data-child-gender="true">
male
</div>
</div>
</div>
There isn't one querySelector you can use for this (as you can't use it to select specific text within elements). However, you can use .querySelector() with .filter() to get more specific results:
const true_children = [...document.querySelectorAll("[data-parent='true'] [data-child-gender='true']")];
const res = true_children.filter(({innerHTML:g}) => g.trim() === "male");
console.log(res);
<div id="grandparent">
<div id="parent1" data-parent="true">
<div id="child1" data-child-gender="false">
male
</div>
</div>
<div id="parent2" data-parent="true">
<div id="child2" data-child-gender="true">
female
</div>
</div>
<div id="parent3" data-parent="false">
<div id="child3" data-child-gender="true">
female
</div>
</div>
<div id="parent4" data-parent="true">
<div id="child4" data-child-gender="true">
male
</div>
</div>
</div>
The problem that the question describes, cannot be solved using query-selectors alone. This is because of following reasons:
The query selectors always works on descendants, so while evaluating that the child div has data-child-gender="true", there will be no way to return the parent element. The query-selector will return the child div.
There is no way to evaluate the inner text or contained text of an element in query-selector.
These two limitations can be worked around by using JavaScript, provided that you were going to use the query-selector in JS.
Something like the following snippet should work.
document.querySelectorAll('div[data-parent=true] div[data-child-gender=true]')
.filter(function(elem) {
return elem.innerText === 'male'; // filter the elements containing male string.
})[0].parentElement; // return the parent of matched element.
An equivalent logic could be derived for selenium too. Otherwise if this much logic is unacceptable, you can always use the much richer xpath selectors. xpath wouldn't have either of the limitations mentioned above.
I need to search for divs with class 'test' that has only button type inside hid childs or child nodes. This is the HTML that I have to filter.
<div class="test">
<div>
<button> <span>Button 1</span></button>
</div>
</div>
<div class="test">
<div>
<button> <span>Button 2</span></button>
<div>Div 1</div>
<div>Div 2</div>
<div>Div 3</div>
</div>
</div>
Based on this jQuery selector I've been testing on this fiddle but it returns me this error:
The div that I've been expecting to return is the first div.
So how can I reach it?
You can compare the length of child div elements and child div elements that have button elements in it:
var notButtonDivs = $('.test').filter(function(){
return $(this).find('div').length == $(this).find('div:has(button)').length
})
Working Demo
This one should do the trick.
var TestDivs = $(document).find(".test div button");
alert(TestDivs[0].innerHTML);
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
This is my HTML file structure:
var li = document.getElementById("myList").getElementsByTagName("li");
for (var i = 0; i < li.length; i++) {
li.onclick = function () {
alert(document.getElementsByClassName("title")[i].innerHTML);
}
}
<div class="maincontent">
<ul id="myList">
<li>
<div class="image">
<img src="http://lorempixel.com/100/100/">
<div class="button option-vertical-grid"></div>
</div>
<div class="info">
<div class="url">lorempixel.com</div>
<div class="title" id="title">M1</div>
<div class="play"><section>0</section></div>
</div>
<div class="info2">
<div class="date">30.11.2016</div>
<div class="button option-vertical"></div>
</div>
</li>
<li>
<div class="image">
<img src="http://lorempixel.com/102/100/">
<div class="button option-vertical-grid"></div>
</div>
<div class="info">
<div class="url">lorempixel.com</div>
<div class="title">M2</div>
<div class="play"><section>0</section></div>
</div>
<div class="info2">
<div class="date">30.11.2016</div>
<div class="button option-vertical"></div>
</div>
</li>
<li>
<div class="image">
<img src="http://lorempixel.com/103/100/">
<div class="button option-vertical-grid"></div>
</div>
<div class="info">
<div class="url">lorempixel.com</div>
<div class="title">M3</div>
<div class="play"><section>0</section></div>
</div>
<div class="info2">
<div class="date">30.11.2016</div>
<div class="button option-vertical"></div>
</div>
</li>
</ul>
</div>
The first task is:
On click of the list it should show an alert message with the title of the clicked list, i.e. the text in the div class "title", i.e. (M1 or M2....)
The second task is:
On click of the div class "button option-vertical" it should give me another alert containing the class title as in task above and additionally the img src value from the div class "image", for example: (http://lorempixel.com/100/100)
When showing the alert from the second task, the alert from the first task should not be shown and vice versa. Please all without jQuery, only JavaScript.
With the JavaScript I tried above, a click on the list item doesn't give me any alert message.
The getElementsByClassName()|getElementsByTagName method returns a collection of all elements in the document with the specified class|tag name, as a NodeList object.
The NodeList object represents a collection of nodes. The nodes can be accessed by index numbers. The index starts at 0.
var li = document.getElementById("myList").getElementsByTagName("li"),
len = li.length,
i;
for (i = 0; i < len; i += 1) {
li[i].onclick = function() {
//Li only has one child with class "title"
alert(this.getElementsByClassName("title")[0].innerHTML);
}
}
The Story
We have a parent (div). Parent can have n children. The number of children the parent can have is decided by a PHP variable $bigF.
So, if $bigF is 5, then parent has 5 children. If it's 10, then it's 10. But $bigF has no role in this context because once the page is loaded, parent will have n children.
It's not dynamic, you know, that's what I was trying to say.
<div id="parent">
<div id="child1" class="click" style="display:block">
Child1
<div id="grandchild1A">
grand child 1A
</div>
<div id="grandchild1B">
grand child 1B
</div>
</div>
<div id="child2" class="click" style="display:none">
Child2
<div id="grandchild2A">
grand child 2A
</div>
<div id="grandchild2B">
grand child 2B
</div>
</div>
<div id="child3" class="click" style="display:none">
Child3
<div id="grandchild3A">
grand child 3A
</div>
<div id="grandchild3B">
grand child 3B
</div>
</div>
</div>
<br><br><br>
Calling children down
<br><br>
<div class="callchild" data-count="child1"> Call Child 1</div>
<div class="callchild" data-count="child2"> Call Child 2</div>
<div class="callchild" data-count="child3"> Call Child 3</div>
In this example, parent has 3 children (div) and they are named child1,child2,child3. IDK who names a child child. That's bad parenting.
And the freaking thing about this family drama is every child has 2 children(div). And they have bizarre names like grandchild1A,grandchild1B, grandchild2A and so on....
Parent is kinda shy. She believes only 1 child should be shown to the outside world. Rest of 'em are kept hidden, may be in the basement or something.
But she has this one BIG rule written all over her face.
If I CALL OUT A CHILD, THE CHILD AND THE GRANDCHILDREN SHOULD COME.
And she has employed 3 guards- who makes her job easy.
And they are Call Child 1,Call Child 2,Call Child 3.
And this is how they do their job.
<script>
$(".callchild").on('click',function()
{
//var calling = $('div:visible').last().attr('id');
//alert(calling);
var calling = $(this).attr('data-count');
$("#parent div:visible").hide();
$('#'+calling).css("display","block");
});
</script>
But every time they call a child, something bizarre happens. Sometimes child & the grandchildren come together. And some other time, the grand children went missing.
And they tried another way also, like:
var calling = $('div:visible').last().attr('id');
and returned with nothing.
Here's the proof. Fiddle
Can anyone help me investigate this story???
I offer Thanks in return. :)
The guards are hiding the grandchildren with this line:
$("#parent div:visible").hide();
because the grandchildren are divs within the parent. You need to apply that operation to just the immediate children of the parent, using >:
$("#parent > div:visible").hide();
It's a nice story, but a little confusing :)
If your goal is to toggle the children and grandchildren using the data-count attribute, try this:
$(".callchild").on('click',function(){
var calling = $(this).attr('data-count');
$("#parent > div").hide();
$('#'+calling).css("display","block");
});
Find an updated fiddle here.
Great narration,Hatsoff.
I have modified the code little bit.
Please have a look at it.
$(".callchild").click(function()
{
var calling = $(this).attr('data-count');
$('.click').hide();
$('#'+calling).show();
});
.callchild{
background:aqua;
width:100px;
height:15px;
border-radius:15px;
padding:15px;
margin:15px;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div id="parent">
<div id="child1" class="click" style="display:block">
Child1
<div id="grandchild1A">
grand child 1A
</div>
<div id="grandchild1B">
grand child 1B
</div>
</div>
<div id="child2" class="click" style="display:none">
Child2
<div id="grandchild2A">
grand child 2A
</div>
<div id="grandchild2B">
grand child 2B
</div>
</div>
<div id="child3" class="click" style="display:none">
Child3
<div id="grandchild3A">
grand child 3A
</div>
<div id="grandchild3B">
grand child 3B
</div>
</div>
</div>
<br><br><br>
Calling children down
<br><br>
<div class="callchild" data-count="child1"> Call Child 1</div>
<div class="callchild" data-count="child2"> Call Child 2</div>
<div class="callchild" data-count="child3"> Call Child 3</div>
Another working solution:
$(".callchild").on('click',function()
{
var calling = $(this).attr('data-count');
$("#parent div:visible").hide();
$('#'+calling).css("display","block");
$('#'+calling+" div").css("display","block");
});
I came to this solution because $("#parent div:visible").hide(); also hiding children elements, so i have added $('#'+calling+" div").css("display","block"); to show respective children also.
--Working DEMO--
In you fiddle just updat $("#parent div:visible").hide(); to $("#parent > div:visible").hide();
$(".callchild").on('click',function()
{
//var calling = $('div:visible').last().attr('id');
//alert(calling);
var calling = $(this).attr('data-count');
$("#parent > div:visible").hide();
$('#'+calling).css("display","block");
});
My HTML code looks something like
<div id="partA">
<div class="myClass typeA"> blabla </div>
<div class="myClass typeA"> blabla </div>
<div class="myClass typeA"> blabla </div>
<div class="myClass typeB"> blabla </div>
</div>
<div id="partB">
<div class="myClass typeA"> blabla </div>
<div class="myClass typeA"> blabla </div>
<div class="myClass typeA"> blabla </div>
<div class="myClass typeB"> blabla </div>
</div>
I want to use javascript to count the number of elements of class myClass, but only the one that are within #partA.
When I use
$(".myClass").size()
I get 8 as result (it counts all the elements from both partA and partB).
When I use
$(".myClass.typeA").size()
I get 6 (it gets all myClass and typeA elements, from both parts)
But when I use
$("#partA.myClass").size()
I get 0.
Apparently, that javascript command only looks for elements that have both id=partA and class=myClass.
Is it possible to reformulate that command in order to count the number of myClass class that are contained within the elements with id=partA?
Thanks a lot!
You're missing a space in one of your selectors. Try:
$("#partA .myClass").size()
Alternatively you could do:
$('#partA').find('.myClass').length;
Or
var partA = $('#partA');
$('.myClass', partA).length;