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");
});
Related
I have child div inside its parent.
How to remove parent div leaving only its child untouched?
I don't use jQuery.
<div id="parent">
<div id="child">
</div>
</div>
to become
<div id="child"></div>
Get the element, get its parentNode, replace it with the child.
var child = document.getElementById('child');
child.parentNode.replaceWith(child);
<div id="parent">
<div id="child">
A
</div>
</div>
If you have support issues with replaceWith you can try the insertBefore approach.
var child = document.getElementById('child');
var parent = child.parentNode;
parent.parentNode.insertBefore(child, parent);
parent.parentNode.removeChild(parent);
<div id="parent">
<div id="child">
A
</div>
</div>
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 can be sound little confusing but here it is.
What i want is to find the children(OF CLASS PARENT ) when user clicks on class target.
Important: I am not aware of children class & child inside html structure.Target class can be after 'blah' like in first case OR can be directly after children like in second case.
Information available: class "PARENt" and $(this) [class target]
Find: Children(ID) of class PARENT (you cannot use class .children)
<div class="parent">
<div class="children" id="1">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
<div class="children" id="2">
<div class="target">TARGET</div>
</div>
<div class="children" id="3">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
Example:
Clicking Target 1 would produce: ID = 1
Clicking Target 2 would produce: ID = 2
Clicking Target 3 would produce: ID = 3
If you want to find only ONE ID use:
$('.target').click(function() {
var found = false;
var parent;
var previous;
while(!found) {
if (previous) {
parent = previous.parent();
} else {
parent = $(this).parent();
}
if (parent.hasClass('parent')) {
found = previous;
}
previous = parent;
}
console.log(found.attr('id'));
});
Demo.
To literally answer your question:
$(".parent *") will give you ALL of the children of .parent no matter how many layers deep
To practically answer your question:
Limit possible elements, classes, IDs, etc.
$(".parent div, .parent span, .parent .child ...etc")
You can also grab only the immediate children of an element or set of elements by using the > CSS selector:
$(".parent > *") for example, will give you ALL of the immediate children of .parent
In the context of your problem
$(".target").on("click", function () {
$(this).closest(".parent").children();
// OR
$(this).closest(".parent").find("*");
});
To get the specific ID Given your current DOM structure...
$(".target").on("click", function () {
var id = $(this).closest("[id]").attr("id");
console.log(id);
});
Use .parentsUntil() to get the set of all parents up to (but not including) .parent. Then get the last element of this to get the child of the parent.
$(".target").click(function() {
var child = $(this).parentsUntil(".parent").last();
console.log(child.attr('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="parent">
<div class="children" id="1">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
<div class="children" id="2">
<div class="target">TARGET</div>
</div>
<div class="children" id="3">
<div class="blah">
<div class="target">TARGET</div>
</div>
</div>
</div>
Another
How can I use jQuery to find out how many children an element has?
Say I have the following structure:
<div id="container">
<div id="column1">
<div id="asset1"></div>
<div id="asset2"></div>
</div>
<div id="column2">
<div id="asset1"></div>
<div id="asset2"></div>
</div>
</div>
I want to find out how many children the div element: container, has. In this case it would return 2...
Use children and length:
$("#container").children().length
Use the direct children selector (>) and the length property:
$('#container > *').length
Example - http://jsfiddle.net/TtV8d/
I have html code that looks roughly like this:
<div id="id1">
<div id="id2">
<p>some html</p>
<span>maybe some more</span>
</div>
<div id="id3">
<p>different text here</p>
<input type="text">
<span>maybe even a form item</span>
</div>
</div>
Obviously there's more to it than that, but that's the basic idea. What I need to do is switch the location of #id2 and #id3, so the result is:
<div id="id1">
<div id="id3">...</div>
<div id="id2">...</div>
</div>
Does anyone know of a function (I'm sure I'm not the first person to require this functionality) that can read and write the two nodes (and all their children) so as to swap their location in the DOM?
In this case, document.getElementById('id1').appendChild(document.getElementById('id2')); should do the trick.
More generally you can use insertBefore().
This function takes any node that is passed into it and wraps it with the tag given. In the example code snippet I wrapped a span tag with a section tag.
function wrap(node, tag) {
node.parentNode.insertBefore(document.createElement(tag), node);
node.previousElementSibling.appendChild(node);
}
function wrap(node, tag) {
node.parentNode.insertBefore(document.createElement(tag), node);
node.previousElementSibling.appendChild(node);
}
let toWrap = document.querySelector("#hi");
wrap(toWrap, "section");
console.log(document.querySelector("section > #hi"), " section wrapped element");
<span id="hi">hello there!</span>
You can use
insertAdjacentElement instead of appendChild to have more control about the position of element with respect to a target element.
Syntax: targetElement.insertAdjacentElement(position, element).
It has four position codes as:
'beforebegin': Before the targetElement itself.
'afterbegin': Just inside the targetElement, before its first child.
'beforeend': Just inside the targetElement, after its last child.
'afterend': After the targetElement itself.
it appears as:
//beforebegin
<p>
//afterbegin
foo
//beforeend
</p>
//afterend
In your case, you can write the code as:
document.getElementById('id2').insertAdjacentElement('beforebegin', document.getElementById('id3'));
Note that this way, you don't need reference the parent (container) element!
Also consider You have more elements than id2, id3, eg: id4, id5, id6. Now, if you want to reposition for example id5 after id2, its as simple as:
function changePosition() {
document.getElementById('id2').insertAdjacentElement('afterend', document.getElementById('id5'));
}
<div id='container'>
<div id='id1'>id1</div>
<div id='id2'><u>id2</u></div>
<div id='id3'>id3</div>
<div id='id4'>id4</div>
<div id='id5'><b>id5</b></div>
<div id='id6'>id6</div>
</div>
<p><input type='button' onclick="changePosition()" value="change position"></p>
In my opinion is worth adding that if you need just a visual change (the DOM will stay the same but I will change in the UI) you can use the CSS order property.
It is probably more efficient that working on the DOM like the other answers, althought again doesn't really change the DOM structure so of course is not a real answer to this question.
Example:
document.addEventListener("DOMContentLoaded", function () {
const btnEl = document.getElementById('btn-swap');
const elToSwap = document.getElementById('id2');
btnEl.addEventListener('click', e => {
elToSwap.classList.toggle("first");
});
});
.container {
display: flex;
flex-direction: column;
}
.first {
order: -1;
}
<div class="container">
<div id="id1">first DIV</div>
<div id="id2">second DIV</div>
</div>
<button id="btn-swap">swap divs</button>
Short
I just add button (at the bottom) and js to your html
id3.after(id2);
function swap() {
id3.after(id2);
}
<div id="id1">
<div id="id2">
<p>some html</p>
<span>maybe some more</span>
</div>
<div id="id3">
<p>different text here</p>
<input type="text">
<span>maybe even a form item</span>
</div>
</div>
<button onclick="swap()">swap</button>