closests jquery - javascript

<div class="panels">
<div>
<h2>
Test
</h2>
</div>
<div class="inner_panel statict">
Test2
</div>
</div>
I want so that when people click on Test, Test2 appears. If not, they don't see Test2, How can I make that happen using jquery?
I tried the following but it does not work.
$('.inner_panel').hide();
$('.panels').click(function () {
$(this).closest('div .inner_panel').toggle();
});
I have multiple divs with class panels in the file, so I don't want click on Test affecting the other "panels."

closest method looks up in the DOM tree, not down. You can check it here. http://api.jquery.com/closest/
Maybe you should use .children('div.inner_panel') to get your element. children method allows you to get elements, that are a single level down the DOM. Check http://api.jquery.com/children/ fo details.

You have an extra space -> $(this).closest('div .inner_panel').toggle();
This should be: $(this).closest('div.inner_panel').toggle();
But .closest() is not going to work for you because it travels up the DOM tree and not up and then down to siblings etc.
I would do this:
$('.inner_panel').hide();
$('.panels').click(function () {
$(this).find('div.inner_panel').toggle();
});
See jsbin demo

$('.inner_panel').hide();
// Within .panels get the div's which contain an H2
var containers = $('.panels h2').closest("div");
// make them clickable
containers.click(function () {
// For the clicked panel, get the next element div which
// has the inner_panel class
$(this).next('div.inner_panel').toggle();
});

Related

jQuery.toggle() not working on a div

On a web page we have a list of profiles. On the right hand side of the profile is some text, followed by an arrow img#arrow.
When img#arrow is clicked, we have the following jQuery we hope to run:
However, the corresponding .bottom-sec is not toggling.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent +' .bottom-sec').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec" style="display: none;">
<p>Initially hidden text.</p>
</div>
<img id="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
Problem
The problem with your code is exactly what the comment on your question is saying, but he didn't explain anything:
You're combining two different ways of selecting elements. One is with selectors, the other is traversing. You're using them in a way which isn't possible (the $parent + ' .bottom-sec' part). The comment linked to a jQuery page about traversing which you should definitely read! It tells you a lot about how to use traversing functions, which you could use!
Solution
There are multiple solutions to this, but I'll write down the one I think is the best:
First of all, change the HTML a bit. I've removed the element style of .bottom-sec and changed the id of the image to a class, because you have multiple images with the same id on the page, which is not a recommended thing to do. Classes can occur more than once, id's cannot.
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec">
<p>Initially hidden text.</p>
</div>
<img class="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
I've reduced the JavaScript to the following. Note that is just reduced to one line, where a click on the .arrow element goes searching for the closest .profile-right parent. If, for whatever reason, you decide to change the HTML and the .arrow element is no longer a child of the .profile-right, this code still works. The only thing it does is toggle an active class on the .profile-right.
jQuery(document).on('ready', function() {
jQuery('.arrow').on('click', function(){
jQuery(this).closest('.profile-right').toggleClass('active');
});
});
The document ready listener was added because of OP's comment.
With CSS, we can use the new .active class to show or hide the element.
.profile-right .bottom-sec {
display: none
}
.profile-right.active .bottom-sec {
display: block
}
Original Code Fix
If for some reason you wanted to use your original code, this is how it should be:
// Nothing wrong about this part.
// Your only worry should be that there could be
// multiple elements with the same ID, which is something really bad.
jQuery('#arrow').click(function(){
// This part is correct, no worries
var $parent = $(this).parent();
// Removed the $(...), because $parent is already a jQuery object
$parent.addClass('active');
// Changed the selector to a find function
$parent.find('.bottom-sec').toggle();
});
You could also combine all of the code inside the listener function to just one line:
jQuery('#arrow').click(function(){
$(this).parent().addClass('active').find('.bottom-sec').toggle();
});
Change your js code like below.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent).find('.bottom-sec').toggle();
});
In your event listener you can catch the element (the down arrow) that triggered the event. It will be referred as this.
Then you can go through the DOM tree using .next() and .parent() to access the <div> to toggle.
Note: you may need more functions than the one I explained above.
Note 2: without code or more detailed information, we can't help you further, I will edit this answer if you add details.

Adding and removing classes not working

I've used this exact code on a different div element and it works perfectly. When I went to add the same code to another div element with a different id it registers the element has been clicked but it doesn't add or remove any of the classes.
$('#quoteClick').click(function(){
$('#cbox-1').addClass('displayCboxBackground');
$('#cbox-2').removeClass('displayCboxBackground');
$('#cbox-3').removeClass('displayCboxBackground');
$('#dbox-1').addClass('displayBlock');
$('#dbox-2').removeClass('displayBlock');
$('#dbox-3').removeClass('displayBlock');
console.log("clicked");
});
The html structure is as follows:
<div id="cbox-1">
<div id="dbox-1">
content...
</div>
</div>
<div id="cbox-2">
<div id="dbox-2">
content...
</div>
</div>
<div id="cbox-3">
<div id="dbox-3">
<div id="quoteClick">
a quote
</div>
</div>
</div>
JSFiddle: https://jsfiddle.net/m81c23cx/1/
In the fiddle you can see the content will changes when each header is clicked. When the "quoteClick" element is clicked I want it to change to the second headers content exactly how it does when the second header is clicked.
I can see in Chrome's console that when I click the div element that it highlights all the classes but it doesn't change any of them. I have the jQuery inside a document.ready() function so it should be waiting for the DOM to load and it works perfectly when I just write the lines into the console.
I'm surprised that nobody actually questioned your use of ids (instead of suggesting that you should double-check for dupes). The reason why this code is hard to debug is because it's too complicated. As a result, you'll have a hard time fixing issues similar to this in the future too.
Drop it, do it better.
I didn't even go through your fiddle. Instead, I'm going to propose that you change your approach altogether.
Update your HTML and use classes instead of ids. Something similar to this:
<div class="cbox">
<div class="dbox">
content...
</div>
</div>
<div class="cbox">
<div class="dbox">
content...
</div>
</div>
<div class="cbox">
<div class="dbox">
<div id="quoteAdvert">
a quote
</div>
</div>
</div>
Update your JavaScript and use this to get the context of the current box:
$('.cbox').click( function cboxClicked () {
// Remove the previous class from all .cbox & .dbox elements; we don't care which
$('.cbox').removeClass('displayCboxBackground')
$('.dbox').removeClass('displayBlock')
// Add a new class to the clicked .cbox & it's child .dbox
$(this).addClass('displayCboxBackground')
$(this).children('.dbox').addClass('displayBlock')
})
The beauty of this? You can have 1000 boxes, it'll still work. No need to add any extra lines of code.
Here's a fiddle showing it in action.
The example code you provided is not consistent with the jsfiddle you created.
In your fiddle, you use the jquery selector $('#quoteClick') but there is no element with that id. There is a #quoteAdvert element however. Change that and you'll see the click in the console.
The classList property returns a token list of the class attribute of the element in question. Luckily for us, it also comes with a few handy methods:
add - adds a class
remove - removes a class
toggle - toggles a class
contains - checks if a class exists
// adds class "foo" to el
el.classList.add("foo");
// removes class "bar" from el
el.classList.remove("bar");
// toggles the class "foo"
el.classList.toggle("foo");
// outputs "true" to console if el contains "foo", "false" if not
console.log( el.classList.contains("foo") );
// add multiple classes to el
el.classList.add( "foo", "bar" );

How do I use jQuery to hide an element with no class or ID... when the parent has no id either?

I want to use jQuery to work with events in a given search box. My issue is that
I don't know how to build the selector correctly, so that JQuery accepts it.
I think I'm getting confused because I need the second element in the list and need to select that one.
The runtime HTML looks like this: (Adapted from Chrome Developer tools, only the relevant class and IDs are shown. There are no IDs to be shown.)
<body class=km-ios7 km-7 km-m0 km-web km-black-status-bar km-vertical km-widget km-pane>
<div class="km-widget km-view">
<!-- Begin 3rd party control -->
<div class=class="km-widget km-view">
<div km-header>
<div class="km-content km-widget km-scroll-wrapper">
<div class=km-scroll-header>
<div class=km-scroll-container>
<div class="km-listview-wrapper">
<form class="km-filter-form">
<div class="km-filter-wrap">
<input type=search >
What I've tried
Since my event wasn't firing I assume my selector was wrong. I opened chrome developer tools after I did "inspect element". The bottom of the tools listed all the parent tags used for that element (with no class or ID). As a test, I've tried hiding the search box using the following:
$("div").hide(); // hides everything...
$("div div").hide(); // hides the wrong element on the page
$("input").hide(); // nothing
$(":input").hide(); // nothing... saw this example somewhere, don't understand it
$("input:text").hide(); // nothing... saw this example (http://stackoverflow.com/q/17384218/328397), don't understand it
I looked at this W3 document, but didn't see what I was looking for (unless I missed it)
Any assistance in getting the right selector would be appreciated.
In the page you linked it's the second div under defaultHomecontent, so
$("#defaultHomeContent div:nth-child(2)")
You actually want to hide the div with class km-filter-wrap.
A safer alternative may be to not deal with selectors and instead show/hide the wrapper element for the ListViewFilter's searchInput element:
var listView = $("#local-filterable-listview").kendoMobileListView({
...
}).getKendoMobileListView();
listView._filter.searchInput.parent().hide();
or
listView.wrapper.find(".km-filter-wrap").hide();
In general, it's a good idea to use the elements that are exposed by Kendo UI controls as much as possible instead of manually building queries (since they might change in future versions).
You could also extend the ListView widget with your own API method for this:
kendo.mobile.ui.ListView.fn.filterVisible = function(value) {
var wrapper = this._filter.searchInput.parent();
if (value) {
wrapper.show();
} else {
wrapper.hide();
}
};
then you could use
listView.filterVisible(false); // hide the filter
you can use the find function. Let suppose you have input field inside footer div like this.
<div id="footer">
<div>
<div>
<input type="text" name="text" value="Search" />
</div>
</div>
</div>
You can use selector like this $("#footer input").hide() or $("#footer").find("input").hide() or $('input[name=text]', '#footer').hide();
Based on what you have added.
You could use
$("input[type='search']")
as a selector.
See if that helps. Here is an example
You could also combine the selectors in this manner:
var $container = $("div.km-widget");
var $searchBox = $container.find("input[type='search']");

Find element above another using jQuery

I'm trying to find the element using jQuery from the following html.
<ul class="gdl-toggle-box">
<li class="">
<h2 class="toggle-box-title"><span class="toggle-box-icon"></span>Volunteer Form</h2>
<div class="toggle-box-content" style="">
</div>
</li>
</ul>
What I'm looking to do is when the h2 is clicked find the li above the h2 add a class active to it. Tried a few different calls but no luck.
EDIT
The biggest issue is that there are multiple toggle boxes on a page so something like this works on pages with a single toggle but pages with multiple the result is they all open together.
var gdl_toggle_box = jQuery('ul.gdl-toggle-box');
gdl_toggle_box.find('li').each(function(){
jQuery(this).addClass('item');
});
gdl_toggle_box.find('li').not('.active').each(function(){
jQuery(this).children('.toggle-box-content').css('display', 'none');
});
gdl_toggle_box.find('h2').click(function(){
if( jQuery('.item').hasClass('active') ){
jQuery('.item').removeClass('active').children('.toggle-box-content').slideUp();
}else{
jQuery('.item').addClass('active').children('.toggle-box-content').slideDown();
}
});
You can use closest.
closest will match the first parent element that matches the selector traversing up the DOM tree.
Demo
$('h2.toggle-box-title').click(function(){
$(this).closest('li').addClass('active');
});
Try this.
$('h2.toggle-box-title').click(function(){
$(this).parent().addClass('newclass');
});
try this:
$('h2.toggle-box-title').click(function() {
$(this).parent('li').addClass('active');
});
On you click in the button you can use the event:
$("something").parent().find("h2.myClass");
// And if you want you can add class after you find you object
http://api.jquery.com/find/
Selecting an element's parent
In order to select an element parent, you can use the parent() function.
Try this:
$('h2.toggle-box-title').click(function() {
$(this).parent('li').addClass('active');
});
*to be more specific, you target the parent you would like to choose by specifying its selector
Check the jQuery API Documentation here
parent() - Get the parent of each element in the current set of matched elements,
optionally filtered by a selector.

jQuery click function using same classes

I have a dropdown function that I need to work only on the div clicked, not all (I have 14+ of the same classes on the page that need to be displayed when a certain one is clicked)
At the moment my jQuery is as follows.
$('.qacollapsed').hide();
$('.qa').click(function () {
$('.qacollapsed').slideToggle();
$(this).toggleClass('active');
});
Of course, that is toggling all qacollapsed classes when there is 14 on the page (Q&A)
Is there a way for it to only drop down the one that is clicked?
the HTML
<div class="qa">
<h4 class="question"> </h4>
</div>
<div class="qacollapsed">
<p> </p>
</div>
It would be helpful to provide a snippet of HTML here, but I'll take a guess at the structure of your markup for now..
Instead of referencing all .qacollapsed elements, you need find elements that are close to the .qa that was clicked, e.g.:
$('.qa').click(function () {
$(this) // start with the clicked element
.find('.qacollapsed') // find child .qacollapsed elements only
.slideToggle();
$(this).toggleClass('active');
});
This will work if .qacollapsed is inside .qa - if not, you might need to use next (for siblings), or one of the other jQuery tree traversal methods.
Yo could find() it or use this as a context in the selector to choose only a descendent of the clicked object
$('.qa').click(function () {
$('.qacollapsed', this).slideToggle();
//You could do $(this).find('.qacollapsed').slideToggle();
$(this).toggleClass('active');
});
Check out the jQuery selectors and why not just use $(this)?
$('.qacollapsed').hide();
$('.qa').click(function () {
$(this).toggleClass('active').next().slideToggle();
});
Personally, I'd give all the divs IDs, the clickable bit being the ID of the question in the database for example, and the answer just being id='ID_answer' or something, then use jquery to slide in the div with the id corresponding to the link clicked, ie
Var showIt = $(this).attr('id') + '_answer'
$('.qacollapsed').not('#'+showIt).hide();
$('#'+showIt).slideToggle;
That will hide all the divs without that ID and show the required one.
Dexter's use of .next above looks simpler though, I've not tried that as being relatively new to jquery too.

Categories

Resources