Is it possible to select a div's all child divs with a specified class using jQuery?
For example:
If I click on a div it should toggle the clicked .name div's all children with .content class(div1,div2,div3).
The html:
<div class="name">
Name of div 1
<div class="content">
Content of div 1
</div>
<div class="name">
Name of div 2
<div class="content">
Content of div 2
</div>
<div class="name">
Name of div 3
<div class="content">
Content of div 3
</div>
</div>
</div>
</div>
The script:
$(function()
{
$('.name').click(function()
{
$(this).children('.content').slideToggle();
});
});
I've tried this script, but it's select the divs on the first level only.
First let me explain an issue as result what you're trying to do
If you decide to click on DIV 2 the CONTENT 2 and 3 should open,
but if than you click DIV 1 a total mess will happen:
DIV 1 will open but all the other will close.
EXAMPLE WITH ISSUE (PRESENT IN OTHER ANSWERS)
To prevent that
you should store the is clicked or not state directly into the clicked DIV
WORKING EXAMPLE
$('.name').click(function(ev){
ev.stopPropagation();
var io = this.io ^= 1; // Toggle 1/0 state
$('.content', this)[io?"slideDown":"slideUp"](function(){
$(this).closest('.name')[0].io = io; // Store state also to all other
});
});
ev.stopPropagation(); prevents the click to navigate up the DOM triggering the same function on not targeted elements (with same className)
var io = this.io ^= 1; toggles using the XOR ^ bitwise operator a 1/0 value (later used as boolean) directly into the element Object custom io (or name it as you like) property (or name it as you like).
Than what we do is: by using the Conditional Operator (?:) we use the toggled this.io value 1 or 0 as boolean, and if value is 1 (true) do a slideDown else, logically a slideUp for every $('.content', this) (.content, children of this)
if we did not used an additional function callback for the slide, you might get the issue of the need to double-click some DIV elements, cause the io value of that particular element was not up to date for it's state, so to change that we just need to set for every slided element the same io state to the .name (the toggler) (.closest()) parent.
Your code works, but the click is propagation. A click inside an inner name is also a click inside the outer name. Add this :
$('.name').click(function(e)//pass the event
{
e.stopPropagation(); // prevent the event from bubbling.
$(this).children('.content').slideToggle();
});
Also, you are using .children, which targets direct children only. If you want all childrens (descendants), use .find().
You need to stop propagating the event so that it doesn't bubble up the tree -
$('.name').click(function(e) {
e.stopPropagation();
$(this).find('.content').slideToggle();
});
http://jsfiddle.net/jayblanchard/sSRJ4/
Related
I need your support in selecting a logic. My script pulls few rows from DB and displays on screen. I want to give a feedback form for each data. These feedback forms must be hidden and should be visible on click of a text (Like reply to this) - Pls refer the picture.
I have tried with the help of java script and CSS
<script>
function hideElement()
{
document.getElementById("target").style.display="none";
}
function showElement()
{
document.getElementById("target").style.display="block";
}
</script>
// Data-1 fetched from DB goes here
<a href='#target'>Reply to this post</a>
<span id='target' style='display:none'>
// Feedback form for Data 1 here
</span>
// Data-2 fetched from DB goes here
<a href='#target'>Reply to this post</a>
<span id='target' style='display:none'>
// Feedback form for Data 2 here
</span>
But it works only for the first record, - Javascript finds the first object with the name "target" and sets display property 'none' or 'block'
What logic can I use to generate dynamic ID assigned to each record and make java sript to run for that. Are there any other better logics to do this? (I'm sure ther are)
Element IDs must be unique, but any time you find yourself generating unique IDs for repeating elements there's probably a simpler, more generic way to implement whatever you're doing.
For this type of function you don't need IDs at all, you can use classes and DOM navigation to get from the clicked item to the related span, using a single delegated event handler as follows:
// bind click handler to the document
document.addEventListener("click", function(e) {
// test if the actual clicked item has the class "reply"
if (e.target.className.match(/\breply\b/)) {
e.preventDefault();
// find the related target span
var target = e.target.parentNode.querySelector(".target");
// update its visibility
target.style.display = target.style.display === "none" ? "block" : "none";
}
});
<div> <!-- note added wrapper div -->
Reply to this post
<span class='target' style='display:none'>
Feedback form for Data 1 here
</span>
</div>
<div> <!-- note added wrapper div -->
Reply to this post
<span class='target' style='display:none'>
Feedback form for Data 2 here
</span>
</div>
I've put some comments within the above JS to explain what it's doing, but the important line is this one:
var target = e.target.parentNode.querySelector(".target");
Within the event listener, the e argument is the event object which holds various bits of information about the event being handled. e.target tells which element was clicked. Having already tested that element's class to see if it was one of the "reply" anchors, we then use the .parentNode property to get a reference to the wrapper div that I added to your markup, then from there .querySelector(".target") finds a descendant of the div that has the class target.
As you can see I've modified your html to support the above as follows:
Change the span ids to be classes
Given the anchors class="reply"
Added wrapper div elements for each group, to make the DOM navigation simple and reliable. You could navigate from the anchor to the span using e.target.nextSibling, except then you'd have to add extra code to skip over any text nodes. I find a wrapper element easier to work with. Of course, if your elements are already in some kind of wrappers for other purposes then you can just use the existing wrappers.
Note: it would be good to remove the inline styles, and to show and hide the spans by adding and removing classes rather than directly updating their styles, but that's not really the main issue here so I'll leave that as an exercise for the reader.
http://codepen.io/sheriffderek/pen/BzmAwg
Step 1: ditch those IDs
markup
<ul class="item-list">
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
</ul>
Step 2: hide the hidden stuff in CSS and not inline
styles
(this is stylus syntax.. but same point)
.item-list
list-style: none
margin: 0
padding: 0
li
background: gray
padding: .5rem
margin-bottom: 1rem
cursor: pointer
.hidden-thing
display: none // hide it
Step 3: get the thing you want to click with jquery or with vanilla JavaScript - attach event handler - use this to note what element the event happens on - with that element... traverse down the DOM and find the thing you want - then use the show method, whichs sets display: block... or fadeIn() or animate() or whatever you like.
JavaScript
$('.item-list li').on('click', function() {
$(this).find('.hidden-thing').show();
});
// or...
$('.item-list li').on('click', function() {
$('.item-list li').find('.hidden-thing').hide();
$(this).find('.hidden-thing').show();
});
If you want only one hidden thing open at a time, you can hide all the items each time first - which is kinda janky, but usual.
BUT... there is a better way to do this, where you add an active class to the whole item. This lets you style things inside it and just generally gives you a larger scope to work with. Here is an example of that. : ) It uses .closest - and passes the event into the click handler to stop the outer click action from bubbling up: http://codepen.io/sheriffderek/pen/oLoqEy
Is there any difference between a div cloned and a div generated in a loop ?
I have two situations:
div 1 :
$('.div1').clone(true).insertAfter('.created_form');
div 2 :
loop
<div class="div2"></div>
endloop
I have a button in each div, to delete the div when the button is pressed.
But the button for delete work only for the cloned div (div1).
For div 2 is not working.
My code for deleting the div is :
$('.buttons').on('click', '.minus_sign', function() {
var parent_id = $(this).parent().attr('id');
$("#"+parent_id).remove();
$("input[name='"+parent_id+"']").remove();
});
Can someone tell me why this is not working for both please ? I mention that the div is exaclty the same, only the id is different! Thank you
That's because the one created without the clone doesn't have an id attribute.
<div class="div2"></div>
However, if you were give it an id:
<div id="myDiv" class="div2"></div>
it would work.
Assuming the original element had an id attribute, the one you're creating inside the loop doesn't have an id attribute as mentioned in this answer.
Even if it has one, since you're using .clone(true), the clone will have the data and event handlers of the cloned element.
But the one created inside loop does not contain the event handler.
And the event delegation will not work since you're delegating the click of .minus_sign to the button which is also dynamically created.
You should delegate the event handler to a static element, for example
$(document).on('click', '.buttons .minus_sign', function() {
var parent_id = $(this).parent().attr('id');
$("#"+parent_id).remove();
$("input[name='"+parent_id+"']").remove();
});
BTW, Since remove() method returns the removed element, you can do the above like
$(document).on('click', '.buttons .minus_sign', function() {
var parent_id = $(this).parent().remove().attr('id');
$("input[name='"+parent_id+"']").remove();
});
I have two DIV tags.
1) Green Color is outer Div Tag which has onclick property set to alert('Clicked').
2) Yellow Color is Inner DIV Tag
Now, when I perform a click on inner div tag an alert pops up. Same repeats while selecting items from inner div tag. I'm not able to select in the inner div tags. How can this be resolved?
Further more, I will have nested div tags which are generated dynamically. I'm stuck here
You need to prevent the propagation of your click up to the outer div.
Sorry about the repost, but the answer is already located at:
event.preventDefault() vs. return false
One solution is to set an event listener on your outer container, and, when the listener is triggered, only act after you have verified that the click did not originate from any of the container's children (in this case, inner). You could tweak this solution to only exclude specific children by class, id, etc:
$(document).ready(function() {
var outer = $('.outer');
outer.on('click', handleOuterClick);
function handleOuterClick(e) {
//Assert that the click originated from the outer div, and not from
//any of its children
var origin = e.target,
children = outer.children();
if(children.index($(origin)) == -1) {
//Proceed by displaying an alert
alert("You clicked the outer div!");
}
};
});
Here's the fiddle: http://jsfiddle.net/39ssk/
Check this out. You can apply id, and use those ids to control onclick.
<html><head></head>
<body>
<script type="text/javascript">
function manualToggle(val)
{
alert(val.id);
}
</script>
<div id="test" onclick="manualToggle(this);">
<span>Allowed to click</span>
<span onclick="event.cancelBubble=true;if (event.stopPropagation) event.stopPropagation();">Not allowed to click</span>
<span>Allowed to click</span>
</div>
</body>
</html>
I am in the lookout for a script that can show one DIV at a time and Hide the rest (2 in the example I took)additionally I want the user to navigate back and forth
i.e
Once the user clicks next DIV 1 is displayed so on till DIV3
He should also be able to traverse from DIV2 - DIV1 and so on
I did find this development interesting
http://jsfiddle.net/meetrk85/Y7mfF/
Thanks a billion in advance.....
Given the following HTML:
<div class="sample">div1</div>
<div class="sample">div2</div>
<div class="sample">div3</div>
next
prev
The following jQuery seems to achieve your requirements:
// selects all the divs of class='sample',hides them, finds the first, and shows it
$('div.sample').hide().first().show();
// binds a click event-handler to a elements whose class='display'
$('a.display').on('click', function(e) {
// prevents the default action of the link
e.preventDefault();
// assigns the currently visible div.sample element to a variable
var that = $('div.sample:visible'),
// assigns the text of the clicked-link to a variable for comparison purposes
t = $(this).text();
// checks if it was the 'next' link, and ensures there's a div to show after the currently-shown one
if (t == 'next' && that.next('div.sample').length > 0) {
// hides all the div.sample elements
$('div.sample').hide();
// shows the 'next'
that.next('div.sample').show()
}
// exactly the same as above, but checking that it's the 'prev' link
// and that there's a div 'before' the currently-shown element.
else if (t == 'prev' && that.prev('div.sample').length > 0) {
$('div.sample').hide();
that.hide().prev('div.sample').show()
}
});
JS Fiddle demo.
References:
first().
hide().
next().
on().
prev().
show().
text().
:visible selector.
Addenda:
A quick explanation of why I changed the html in the linked demo:
<div name="sample">div1</div>
<div name="sample">div2</div>
<div name="sample">div3</div>
<a href="#" id="display" value="display">next</div>
<a href="#" id="display1" value="display">prev</div>
The name attribute, in a div serves no purpose. Certainly not if all the elements are sharing the same name (they're not input elements, they're linked-to by an a, so use a class name).
The value attribute has no association with an a element, and serves, so far as I can tell, no purpose. For this, in the script above, I chose, again, to use a class name, since the same 'value' of the attribute was shared, though a data-* attribute could have been used, and would have been valid.
The closing </div> tags weren't closing anything, so they were changed to </a>.
Hello I have some HTML that looks like this,
<div id="music_interests">
<ul class="interests">
<li >
<div class="interest inline">
<img src=""/>
<div class="interest_popup">
1 users have this interest.
Remove interest </div>
</div>
</li>
</ul>
When users clicks the remove button I need to select the parent div (in this case music_interests). How would I go about that?
I have tried doing the following,
$(this).parent().parent().parent().parent() but is there a more elegant way?
To complicate things futher I will not actually no the parents ID when in the app as the remove button occurs in 4 or 5 different areas on the page.
you should use closest()
$(this).closest('div#music_interests');
//find the nearest div with id "music_interests"
//if i omitted the id, it retrieves the div with class "interest_popup"
or parents()
$(this).parents('div:eq(1)');
//get ALL the ancestor divs (until it reaches root tag)
//since music_interests is just 2 levels up, use :eq(1)
If the ID of the DIV you want to remove is static you should only use the ID selector (not something like $("div#music_interests")) as the ID selector is directly mapped to the DOM function document.getElementsById which is pretty fast:
$("#music_interests").remove();
If the ID isn't static you could get the UL just like that:
$(function(){ //execute when page has been loaded
$(".remove").click(function(){ //attach click handler
var removeDiv = $(this).closest("ul").parent().remove(); //get next UL -> DIV is its parent
return false; //stop further processing of "click" event
});
});
if remove button always exist in ul tag (in all your 4 or 5 different areas) then you can use the following code.
$(this).closest("ul").parent()
in this case u don't even need to give id to DIV tags