this parent jQuery - javascript

jQuery
$(".drop-down h3").click(function(e) {
e.preventDefault();
$(this).parent(".drop-down").find($("ul")).stop().slideToggle();
$(this).parent(".drop-down").find($(".divider-aside")).stop().toggle("slow");
$(this).parent(".drop-down").find($(".arrow")).stop().toggleClass("rotate1 rotate2");
});
HTML
<div id="categories">
<div class="drop-down">
<h3>Categories</h3>
</div>
<div class="divider-aside"></div>
<ul>
<li>123</li>
<li>12323</li>
<li>1231</li>
<li>523</li>
<li>31</li>
</ul>
</div>
I'd like to hide everything in .drop-down class excluding <h3> by clicking on <h3>. In this case only .arrow toggleClass works.

Use closest instead of parent
$(this).closest("#categories")
parent will only go back 1 level , i.e, the immediate parent. But you gotta get the container that encloses all the 3 elements
So $(this).parent(".drop-down")
supposed to be either
$(this).parent().parent() // this will break if there is an extra
// parent container gets added
or
$(this).closest("#categories") // This will work even if the no of
// parent container keep chaning

if you need toggle them all but the .drop-down .siblings is just what you need
$("div.drop-down > h3").click(function(){
var $t = $(this);
$t.parent().siblings().toggle();
});

Related

Targeting Multiple Elements with One Function

I have a function that assigns dynamic classes to my div's. This function is a that runs on the page. After the page loads, all 10 of my primary 's have classes ".info1" or ".info2" etc...
I am trying to write a Jquery function that changes the class of the div you click on, and only that one. Here is what I have attempted:
$(".info" + (i ++)).click(function(){
$(".redditPost").toggleClass("show")
});
I have also tried:
$(".info" + (1 + 1)).click(function(){
$(".redditPost").toggleClass("show")
});
And
$(".info" + (i + 1)).click(function(){
$(".redditPost").toggleClass("show")
});
EDITED MY HTML: DIV RedditPost is actually a sibling to Info's parent
<div class="listrow news">
<div class="newscontainer read">
<div class=".info1"></div>
<div class="redditThumbnail"></div>
<div class="articleheader read">
</div>
<div class="redditPost mediumtext"></div>
</div>
My issue is two fold.
The variable selection for ".info" 1 - 10 isn't working because i doesn't have a value.
If I did target the correct element it would change all ".redditPost" classes instead of just targeting the nearest div.
Try like this.
$("[class^='info']").click(funtion(){
$(this).parent().find('.redditPost').toggleClass("show");
});
Alternative:
$('.listrow').each(function(){
var trigger = $(this).find("[class^='info']");
var target = $(this).find('.redditPost');
trigger.click(function(){
target.toggleClass("show");
});
});
Try this
$("div[class*='info']").click(function(){
$(this).parent().find(".redditPost").toggleClass("show")
});
Explanation:
$("div[class*='info'])
Handles click for every div with a class containing the string 'info'
$(this).parent().find(".redditPost")
Gets the redditPost class of the current clicked div
Since the class attribute can have several classes separated by spaces, you want to use the .filter() method with a RegEx to narrow down the element selection as follows:
$('div[class*="info"]').filter(function() {
return /\binfo\d+\b/g.test( $(this).attr('class') );
}).on('click', function() {
$(this).siblings('.redditPost').toggleClass('show');
});
.show {
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="listrow news">
<div class="newscontainer read">
<div class="info1">1</div>
<div class="redditThumbnailinfo">2</div>
<div class="articleheader read">3</div>
<div class="redditPost mediumtext">4</div>
</div>
</div>

jQuery - Add class to parent container based on content of child container

I would like to add a class to the outer (parent) container based on the content of a child container. I am able to add a class to the child container based on its content, but If I try to add the class to the parent container, it does it to all of the containers on the page instead of just the current container. Could someone help me update my code so that it only adds the class to the parent container and not all containers that share the same class? Thanks.
jQuery:
$('div.promotion-type').each(function () {
var promotion = $(this).html();
console.log(promotion);
if (promotion === "Special Event") {
$("div.calendar-event").addClass("special-event"); // this is the only one with a class created for it so far
} else if (promotion === "Daily Promotion") {
$("div.calendar-event").addClass("daily-promotion");
}
});
HTML: (1 of many containers)
<li class="hidden-xs col-sm-6 col-md-4">
<div class="calendar-event">
<div class="event-details-container">
<div class=" col-xs-4 calendar-thumbnail">
<a href="/warroad-calendar/canadian-day">
<img src="/_images/warroad/calendar/may-june-2014/canadianDay.jpg" border="0" alt="" />
</a>
</div>
<h3>Canadian Day</h3>
<h4>8 a.m. - 6 p.m.</h4>
<strong></strong><br />
<div class="hidden-xs hidden-sm hidden-md hidden-lg promotion-type">Daily Promotion</div>
</div>
</div>
</li>
Change this:
$("div.calendar-event").addClass("special-event");
to this:
$(this).parents("div.calendar-event").addClass("special-event");
As it appears you already know, using the selector $("div.calendar-event") is going to select all <div> elements with the class calendar-event.
By using $(this).parents("div.calendar-event"), you're going to look through all parents of the starting <li> element, starting with the closest parent and progressing outwards. When it finds the parent that is a <div> element with the class calendar-event, it's going to call .addClass() on that parent element.
The problem is that you are doing a new selection instead of using the current element. Try...
$(this).parent().parent().addClass(...);
...or possibly...
$(this).parents('div.calendar-event').addClass(...);
...instead.
Instead of this-
$("div.calendar-event", this).addClass("special-event");
try this:
this.find("div.calendar-event").addClass("special-event");
Use text() instead of html()
remove the classes first
use $(this)
Code:
$('div.promotion-type').each(function () {
var promotion = $(this).text();
console.log(promotion);
$(this).parent().removeClass("special-event");
$(this).parent().removeClass("daily-promotion");
$(this).parent().addClass(
promotion === "Special Event" ? 'special-event': 'daily-promotion');
});

How can I hide parent element of all elements with a given class, but the parent element also has a specific class?

I want to hide all instances of an li element with class parent that have an immediate child div element with class child-1. Here's a pseudocode example, where the method hideParent() would hide the parent of the selected element(s):
$("li.parent > div.child-1").hideParent();
The following is an example of my HTML, in which the second and third li.parent elements should be hidden.
<li class="parent">
<div class="child-0"> ... </div>
</li>
<li class="parent">
<div class="child-1"> ... </div>
</li>
<li class="parent">
<div class="child-1"> ... </div>
</li>
Try this:
$("li.parent > div.child-1").parent().hide();
Select the relevant child elements directly, target their parents (filtered by the relevant selector), then hide them.
$("div.child-1").parent('li.parent').hide();
See:
parent Documentation
Another option is with using filter:
$("li").filter(function () {
var $this = $(this);
var isParent = $this.hasClass("parent");
var childMatchCount = $this.children("div").filter(".child-1").length;
return isParent && childMatchCount;
}).hide();
DEMO: http://jsfiddle.net/GEhfP/
Although this can be optimized in several ways. But to me, it's more "readable", in a very explicit sense. Using jsperf, the quickest I can get filter to work is with:
$("li.parent").filter(function () {
return $(this).children("div.child-1").length;
}).hide();
#Joe's answer was the fastest with: $("li.parent > div.child-1").parent()

div onmouseover loses when going over other divs inside main div

I have a li,some other elements like divs, inputs inside this li,and everything inside the gridview.
I have a onmouseover="calcRoute();" on li.
PROBLEM : I have noticed that on hovering on inside element divs and coming out of element divs to the parent div causes the calcRoute(); to execute again ,ie bind google maps again, which causes a flickering due to map rebind.
TRIED : onmouseenter and onmouseleave,but it wont support in all browsers
<li onmouseover="calcRoute(8.4572136,76.94017529999996);return false; ">
<div class="li-inner">
<input type="image" name="ctl00$ContentPlaceHolder1$FESearchListingControl1$dlPhotoView$ctl01$imgPhotoView" id="ctl00_ContentPlaceHolder1_FESearchListingControl1_dlPhotoView_ctl01_imgPhotoView" src="../UploadedImages/House2469-22-8-2012.jpg" style="height:142px;width:219px;border-width:0px;">
<div class="title">
<a id="ctl00_ContentPlaceHolder1_FESearchListingControl1_dlPhotoView_ctl01_lblPropName" href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$FESearchListingControl1$dlPhotoView$ctl01$lblPropName','')">Halloween</a>
<div class="star"></div>
</div>
<div class="address">
<div class="left-location">
<span id="ctl00_ContentPlaceHolder1_FESearchListingControl1_dlPhotoView_ctl01_lblDistrict">Trivandrum</span>
</div>
<div class="right-price"><span class="WebRupee">Rs</span>
<span id="ctl00_ContentPlaceHolder1_FESearchListingControl1_dlPhotoView_ctl01_lblPrice">500.00</span>
</div>
</div>
</div>
</li>
You can attach an id to the li elements and pass this id to the calcRoute function.
onmouseover="calcRoute(8.4572136,76.94017529999996, this.id);
Then, in this function you can set a flag for this li element that it's been hovered before.
var hoveredItems = {}; // this is a global object
function calcRoute(x,y,id) {
// put this control on top so that recurring operations will be prevented from being run.
if(hoveredItems[id]) return;
else hoveredItems[id] = true;
..
}
Maybe this helps...

How do I use a function argument for this jquery code, or is there a better solution?

I have about 50 p tags and next to these are again 50 divs. on click of each p tag, its div should be shown and the rest hidden. How do i acheive this. I can use something like below:
$(function() {
$('.p1').click(function(){
$('.div1').show();
$('.div2','.div3','.div4','.div5','.div6',.........,'.div50').hide()
})
$('.p2').click(function(){
$('.div2').show();
$('.div1','.div3','.div4','.div5','.div6',.........,'.div50').hide()
})
//////////////
//////
})
but as you see that this is not an effiecient solution. I am also not sure how the jquery each can be leveraged here or how can this implementation be done using arrays. Can somebody point me in the right direction. I think we should use a function and pass that no. as a parameter, but I dont know how to use custom functions in jquery.
UPDATE:
This is what I have done
$(function() {
$('.p1').click(function() {
$('.div').hide();
$('.d1').show();
})
})
I have added the class div to all of my 50 divs and I am showing d1 on click of p1. Now how do I replace 1 for each instance till 50.
I would have a common class to all div and p so that the binding the handler and the hide can be simple. And for the div, I would associate a data-tag to each p to link each p tag to div
<p class="p1 pclass" data-showdiv="div1">
...
</p>
<p class="p2 pclass" data-showdiv="div2">
..
<div class="mydiv div1" ..>
..
</div>
<div class="mydiv div2" ..>
..
</div>
And the script would be,
$(function() {
$('.pclass').click(function(){
$('.mydiv').hide();
$('.' + $(this).data('showdiv')).show();
});
});
As Jason told,
Use this
$('p').click(function() {
$('div').hide();
$(this).next('div').show();
});
If the div is next to each paragraph.
But, if there's an element between p and div, it wont work.
For you problem, you can do,
$('p').click(function() {
$('div').hide();
var divClass = $(this).attr("class").replace('p','div');
$('.' + divClass).show();
});
provided you have only p1, p2 .... in paragrah classes ;)
Update
See this fiddle
Notice , we have <br> tags between <p> and <div> as you wanted.
Assuming your HTML structure is
<p>Some text</p>
<div>More text to hide and show</div>
<p>Some text</p>
<div>More text to hide and show</div>
<p>Some text</p>
<div>More text to hide and show</div>
....
Use the following in your $(function(){}); method:
$('p').click(function() {
$('div').hide();
$(this).next('div').show();
});
var dvs = ['.div1','.div2','.div3','.div4','.div5','.div6',.........,'.div50'];
$('p').click(function() {
var index = parseInt(this.className.replace('p','')) - 1;
$(dvs[index]).show();
$(dvs.join(', ')).not(dvs[index]).hide();
});
The jQuery click event will automatically be registered on all elements that match the selector, so you shouldn't have to use the each() method. I would suggest having two CSS classes to distinguish between elements that have this toggling behaviour and elements that are primary (i.e. should be shown when their parent is clicked).
The markup:
<body>
<p class="togglable">
<div class="primary">
This is the primary div that will be shown when our parent is clicked.
</div>
<div>Regular div child</div>
<p>Nested paragraph</p>
<ul>
<li>A list perhaps</li>
</ul>
</p>
<p class="togglable">
<div class="primary">
This is the primary div that will be shown when our parent is clicked.
</div>
<div>Regular div child</div>
<p>Nested paragraph</p>
<ul>
<li>A list perhaps</li>
</ul>
</p>
<p>This is a normal paragraph</p>
</body>
The code:
$(function () {
$('.togglable').click(function () {
// hide all our children
$(this).children().hide();
// now only show our primary chlid
// NOTE: we pass 'this' as the second argument
// so that the selector will only apply to the
// children of the element that was clicked
// (i.e. we are providing a custom context for the selector).
$('.primary', this).show();
// You could even use the position of the child as well:
// $(this).children().first().show();
// This will show the first child element.
});
});
In this example all elements with the class togglable will show their primary child element when clicked and hide all other child elements.

Categories