basically, and in a very schematic way, I need to target the first element who has a specific attribute relative to the element who got the event.
<div data-path="2" class="section">
... Nope.
</div>
<div data-path="1" class="section">
<a data-path="2" class="trigger" href="#">Foo</a>
</div>
<div data-path="1" class="section--2">
... Nope.
</div>
<div data-path="2" class="section--3">
I need to target this one, but not the sections previous to the trigger.
</div>
<div data-path="2" class="section--4">
... Nope.
</div>
I can't figure how to achieve this. It seems to be pretty simple but I'm just stuck on this since two days. I try to play with .next() and .nextUntil() but it doesn't work properly.
Any help are welcome and sorry for my english.
Edit : To be clear, what I need is when a click on the .trigger, I need to target the first next section who has the same data-path attribute, but not the sections before the trigger.
You may want to use the nextAll to get to the next element which has the same property value and then use the first one out of that:
Demo: http://jsfiddle.net/mUt9H/1/
Relevant Code:
$("a").on("click", function() {
var dp = $(this).data("path");
var txt = $(this).parent().nextAll("div[data-path='" + dp + "']").first().text();
alert(txt);
});
Your trigger is an anchor, so first you need to get to its parent div and then traverse to the next elements. Hence, $(this).parent()....
Edit: (regarding your comment)
Just chain a .first() to the statement and you are good to go.
.nextAll("div[data-path='" + dp + "']").first()...
Try:
$('a.trigger').click(function () {
var target = $(this).parent().nextAll('div[data-path="'+$(this).data('path')+'"]').first();
})
jsFiddle example
Related
I am hoping to get some help with finding the next type of an element after finding an image with ends a specific way. So far, I've got it locating the images and beginning to run an each() function, but I can't get it to select the next input on the page.
Here's the code I have so far:
$("img[src$='sunglasses.jpg']").each(function( index ) {
$( this ).closest(".label_box").find("input[name^=happy_]").prop('value', '1');
$( this ).nextAll("input[name^=happy_").eq(0).prop('value', '1');
});
And an example of the HTML would be something like this:
<div class="image_box">
<img src="sunglasses.jpg">
</div>
<div class="label_box">
<input name="happy_1">
</div>
Essentially, I'm trying to select the input of happy_* in another div directly after finding a matching image.
Never mind, I figured it out! I just needed to add 2 .parent() functions to get up tot he correct div.
$(this).parent().parent().next('div').find("input[name^=happy_]")
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.
I need to select the element 2 up from my current element. Normally you can use the .prev() to find the previous element but I need to find the one previous to this. Whats the simplest way to find this?
var animation = $("div.services-block").prev();
I need to find the div before services-block and load that into a variable.
My structure as an example
<div class="wrapper">
<div class="services-block-item"></div>
<div class="services-block-item-match"></div>
<div class="services-block-item"></div>
<div class="services-block"></div>
</div>
Say my current element is services-block, I need to find and grab services-block-item-match. (but this class name can change)
If your "this current element" changes, some code like the following might be useful:
I used a different example: http://jsfiddle.net/swm53ran/5/ to illustrate the ability of $(this) with the .prev().prev() that may be helpful for your problem.
$(this).prev().prev().css('color', 'red');
In this fiddle illustration, a link is clicked and then jquery changes the element that is 2 spots ahead of it to have red colored text. There are four links, so if you click 4, link 2 will be red, if you click 3, link 1 would be highlighted.
Hope this helps!
var animation = $(".services-block").prev().prev();
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.
Every time I load a page, I have a random number of elements with the same class and different(random) IDs.
I would like to know how I can keep only one element on the page and delete the others from DOM, according to their class?
Example:
<div id="joke" class="hey"></div>
<div id="joking" class="hey"></div>
<div id="jokes" class="hey"></div>
<div id="joker" class="hey"></div>
I would like to leave only id="joke" where joke (as for the other element's id values) is randomly/dynamically generated.
If you only want to keep the first one:
$('.hey').slice(1).remove();
Reference: .slice(), .remove()
If you want the first one, you can use:
$(".hey").first();
If you want a random element from those matched, you can use the :random filter implemented here and do:
$(".hey:random");
I noticed that there are only answers here that assume jQuery is available. While obviously jQuery is without a doubt perfect and should be elected president I'm going to assume that it's NOT available. Let's do this (removing all except the first element) just using the DOM shall we. (see JSfiddle)
<div id="foo">
<!-- a jocular comment -->
<div id="joke" class="hey">1</div>
<div id="joking" class="hey">2</div>
<div id="jokes" class="hey">3</div>
<div id="joker" class="hey">4</div>
</div>
js:
var parent = document.getElementById('foo'),
elems = parent.childNodes, // live list
firstElemNode,
i = 0;
while (elems[i] && elems[i].nodeType != 1) {
i++;
}
if (elems[i]) {
firstElemNode = parent.removeChild(elems[i]);
parent.innerHTML = '';
parent.appendChild(firstElemNode);
}
We look for the first node that is an element (not a text node or comment node). If we can't find one we are smart enough to do nothing.
var $els = $('.hey');
$els.not($els.eq(Math.floor(Math.random()*$els.length))).remove();
JSFiddle
Try this
$('.hey').not('#joke').remove()
$('div.hey:not(:first)').remove()
To show a random .hey element:
$('.hey').hide();
$('.hey')[Math.floor(Math.random()*$('.hey').length)].show();