I have a container with multiple divs and in each div I have a handler on which you can click.
The requirement is to return the index of the div in the container for further processing.
I've simplified the code for readability purposes.
The HTML:
<div class="container">
<div class="block">
<div class="handler">
Click
</div>
</div>
<div class="block">
<div class="handler">
Click
</div>
</div>
<div class="block">
<div class="handler">
Click
</div>
</div>
<div class="block">
<div class="handler">
Click
</div>
</div>
</div>
The Javascript code I tried so far but I always get -1 as the index:
$(document).ready(function(){
$('.handler').click(function(e) {
let index = Array.prototype.indexOf.call($('.container'), $(this).parents('.block'));
console.log(index);
});
});
I also created a fiddle.
So what am I doing wrong here?
You can do the following,
$('.handler').click(function(e) {
var el = e.target;
console.log([].indexOf.call(el.parentNode.parentNode.children, el.parentNode));
});
However if you want to know what was wrong in your code,
Array.prototype.indexOf.call($('.container')[0].children, $(this).parents('.block')[0])
This part should fix the problem in your code. You have been doing it all right, but for the parameter of indexOf we needed the children array of .container and clicked element.
You were passing the container element and current clicked element as an array. That is Array.prototype.indexOf.call('[Container Element]', ['current clicked div']) Which is not right. You should pass something like this,
Array.prototype.indexOf.call('[children, children, children...]', 'current clicked div element').
It was happening because the $('.container') returns an array with the element having a class name .container. But we needed all the children array of the element that contains container class.
And $(this).parents('.block') returns an array with the matching elements even if it is only one.
You can access the index using the index method on parent element of selection.
$(document).ready(function(){
$('.handler').click(function(e) {
console.log($(this).parent().index())
});
});
You can do that like this. Find the index of the closest element of the clicked element, which is also a direct child of .handler. To find index, use index().
$(document).ready(function() {
$('.handler').click(function(e) {
let index = $(this).closest('.block').index()
console.log(index);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="block">
<div class="handler">
Click
</div>
</div>
<div class="block">
<div class="handler">
Click
</div>
</div>
<div class="block">
<div class="handler">
Click
</div>
</div>
<div class="block">
<div class="handler">
Click
</div>
</div>
</div>
You're checking at the wrong level of nesting in your HTML. I believe what you're trying to do is check from one level higher, at ".container" and get the index of the ".block" element that was clicked.
This code works in your Fiddle:
$(document).ready(function(){
$('.handler').click(function(e) {
const p = e.target.parentElement.parentElement;
const index = Array.prototype.indexOf.call(p.children, e.target.parentElement);
console.log(p.className) // "container"
console.log(index)
});
});
This can be done simply using delegate in jQuery.
I modify your JSFiddle code.
$(".container").delegate('.block', 'click', function () {
console.log( $(this).index() );
})
u can use a id
<div class="container">
<div class="block">
<div id='0' class="handler">
Click
</div>
</div>
<div class="block">
<div id='1' class="handler">
Click
</div>
</div>
<div class="block">
<div id='2' class="handler">
Click
</div>
</div>
<div class="block">
<div id='3' class="handler">
Click
</div>
</div>
</div>
$(document).ready(function(){
$('.handler').click(function(e) {
let index = this.id
console.log(index);
});
});
https://jsfiddle.net/vhrt596x/2/
Related
what I'm trying to do is to check if my inner <div> has a text for example Ended and then remove if it has a text. I have multiple <div> with the same class name. I tried using .filter(). I would like to remove the div container_one that contains the found element.
Here is my HTML:
var $filstatus = $('.status').filter(function() {
return $(this).text() == 'Ended';
});
$filstatus.remove();
<div class="main_container">
<div class="container_one">
<div class="inner_container">
<div class="status">Ended</div>
</div>
</div>
<div class="container_one">
<div class="inner_container">
<div class="status">On going</div>
</div>
</div>
<div class="container_one">
<div class="inner_container">
<div class="status">Ended</div>
</div>
</div>
</div>
Thank you for the help!
I would use the jQuery's selector by content
combined with .closest(). This might be the shortest way:
$('.status:contains("Ended")', $('.main_container')).closest('.container_one').remove();
First ('.status:contains("Ended")') will select all elements that have a class status, contain the text "Ended" and are children of main_container (not needed but is recommended to speed up selection of elements on complex pages).
Then the method .closest('container_one') will climb up the parents tree for each of the elements from the previous step and select the first parent element with class 'container_one'.
At last it will remove all elements found.
Note: all those methods work both with single element and collections of elements, so no need of any for/foreach.
Working JSFiddle Demo
Pure JavaScript solution with forEach:
var div = document.querySelectorAll('.container_one');
div.forEach(function(el){
var target = el.querySelector('.status');
if(target.textContent == 'Ended'){
el.remove();
};
})
<div class="main_container">
<div class="container_one">
<div class="inner_container">
<div class="status">Ended</div>
</div>
</div>
<div class="container_one">
<div class="inner_container">
<div class="status">On going</div>
</div>
</div>
<div class="container_one">
<div class="inner_container">
<div class="status">Ended</div>
</div>
</div>
</div>
Try this
$filstatus.parent().parent().remove();
filter will return an array , then use each to loop over that and delete the element. In this case it will remove that specific div but the parent div will still be in dom
var $filstatus = $('.status').filter(function() {
return $(this).text().trim() === 'Ended';
});
$filstatus.each(function(index, elem) {
$(elem).remove();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main_container">
<div class="container_one">
<div class="inner_container">
<div class="status">Ended</div>
</div>
</div>
<div class="container_one">
<div class="inner_container">
<div class="status">On going</div>
</div>
</div>
<div class="container_one">
<div class="inner_container">
<div class="status">Ended</div>
</div>
</div>
</div>
If you want to remove .container_one whose inner child has the text Ended, try
const ended = $('.status').filter((index, element) => $(element).text() === 'Ended')
ended.parents('.container_one').remove()
Since you want to remove the closest ansistor with class .container_one, you will need to use closest
$filstatus.closest(".container_one").remove();
Check this: https://jsfiddle.net/n3d5fwqj/1/
https://api.jquery.com/closest/
Try using this if you don't need $filstatus in other places
$('.status').each(function(){
if ($(this).text() == "Ended"){
$(this).parent().parent().remove();
}
})
I see your problem is you are able to remove the child div status but what you want is to remove the entire parent div with class container_one
you can use $.each for that and use closest(class_name) to remove the parent including its child
$.each($('.status'), function(idx, div) {
if ($(this).text() == 'Ended') {
$(this).closest('.container_one').remove();
}
});
Demo
or you can continue your filter and just add .closest('.container_one') to your jquery selector
var $filstatus = $('.status').filter(function() {
return $(this).text() == 'Ended';
});
$filstatus.closest('.container_one').remove();
Demo
Sorry my english bad, for example I have 2 columns, every column when click div.open-model will show a model have a value is h3.title, I used jQuery but i cannot get value h3.title every column
$(document).ready(function() {
$('.open_modal').click(function(e) {
var h3title = $(this).find('.parent .title').html();
console.log('h3title');
e.preventDefault();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<h3 class="title">Title1</h3>
</div>
<div class="open-model">Open model</div>
<div class="parent">
<h3 class="title">Title2</h3>
</div>
<div class="open-model">Open model</div>
Try prev().
var h3title = $(this).prev('.parent').find(".title").text();
And after fixing other errors
$(document).ready(function() {
$('.open-model').click(function(e) {
var h3title = $(this).prev('.parent').find(".title").text();
console.log(h3title);
e.preventDefault();
});
});
You've got several issues here:
The class on the element is open-model so your selector of open_modal is incorrect
find() looks for child elements, yet the target you want to find is a child of a sibling, so you need prev().find() instead
h3title is a variable, so you don't need to wrap it in quotes when passing it as an argument to console.log().
Try this:
$(document).ready(function() {
$('.open-model').click(function(e) {
e.preventDefault();
var h3title = $(this).prev('.parent').find('.title').text();
console.log(h3title);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<h3 class="title">Title1</h3>
</div>
<div class="open-model">Open model</div>
<div class="parent">
<h3 class="title">Title2</h3>
</div>
<div class="open-model">Open model</div>
spelling of selector is wrong on click
use .prev() instead of .find()
$('.open-model').click(function(e) {// fix selector
var h3title = $(this).prev('.parent').find('.title').html();//use prev()
console.log(h3title);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<h3 class="title">Title1</h3>
</div>
<div class="open-model">Open model</div>
<div class="parent">
<h3 class="title">Title2</h3>
</div>
<div class="open-model">Open model</div>
Change it to
$(document).ready(function(){
$('.open-modal').click(function(e){
e.preventDefault();
var h3title = $(this).prev().find('.title').text();
console.log('h3title');
});
});
In the example below we are getting the the previous DOM element and as we can see in the structure we want to get the inner text of its child element.
$('.open-model').on('click', function(){
console.log($(this).prev().children().text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<h3 class="title">Title1</h3>
</div>
<div class="open-model">Open model</div>
<div class="parent">
<h3 class="title">Title2</h3>
</div>
<div class="open-model">Open model</div>
I'm learning Javascript and jQuery and I'm stuck at this one problem. Let's say my code looks like this:
<div id="hey"> hey </div>
<div id="how"> how </div>
<div id="are"> are </div>
<div id="you"> you </div>
Now, if i click one of the div's, i want the other ones to disappear.
I know, I could create 4 functions for each one of them with on.click hey and display none with how , are and you. But is there a easier way? I bet there is, with classes maybe?
Thanks for responding!
Use siblings to get reference to its "brothers".
Given a jQuery object that represents a set of DOM elements, the .siblings() method allows us to search through the siblings of these elements in the DOM tree and construct a new jQuery object from the matching elements.
$('div').click(function(){
$(this).siblings().hide();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hey"> hey </div>
<div id="how"> how </div>
<div id="are"> are </div>
<div id="you"> you </div>
Or you can hide all the other div which not the clicked element using not
Remove elements from the set of matched elements.
$('div').click(function() {
$('div').not(this).hide();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hey"> hey </div>
<div id="how"> how </div>
<div id="are"> are </div>
<div id="you"> you </div>
You can just hide siblings() of clicked div.
$('div').click(function() {
$(this).siblings().fadeOut()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hey">hey</div>
<div id="how">how</div>
<div id="are">are</div>
<div id="you">you</div>
Yeah there are some easier ways and I could tell a one from it,
Set a common class to all the elements that you are gonna target,
<div class="clickable" id="hey"> hey </div>
<div class="clickable" id="how"> how </div>
<div class="clickable" id="are"> are </div>
<div class="clickable" id="you"> you </div>
And you have to bind a single click event by using a class selector,
$(".clickable").on("click", function(){ });
Now use the .siblings() functions to hide the required elements,
$(".clickable").on("click", function(){
$(this).siblings(".clickable").hide();
});
But using a toggle instead of hide would sounds logical,
$(".clickable").on("click", function(){
$(this).siblings(".clickable").toggle();
});
Since you can do the same operation over all the elements.
You can use not to avoid element and this will indicate current instance.
$(document).ready(function(){
$("div").on("click",function(){
$("div").not(this).hide("slow");
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hey"> hey </div>
<div id="how"> how </div>
<div id="are"> are </div>
<div id="you"> you </div>
Assign a class to each of the elements:
<div id="hey" class='sth'> hey </div>
<div id="how" class='sth'> how </div>
<div id="are" class='sth'> are </div>
<div id="you"class='sth' > you </div>
And write a js function onclick.
Remove class 'sth' from 'this' element in this function
Hide all elements with class 'sth' $('.sth').hide();
For this example - you don't need to add any further selectors to target the div's although in reality - this solution wwould cause all divs on the page to be affectecd - adding classes would be my actual suggestion: - but this works for this example. Click a div and all divs are hidden then the clicked one is shown. I also added a reset button to allow all divs to reappear.
$('div').click(function(){
$('div').hide();
$(this).show();
});
$('#reset').click(function(){
$('div').show();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hey"> hey </div>
<div id="how"> how </div>
<div id="are"> are </div>
<div id="you"> you </div>
<hr/>
<button type="button" id="reset">Reset</button>
$(document).ready(function(){
$("div").on("click",function(){
$("div").not(this).toggle("slow");
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hey"> hey </div>
<div id="how"> how </div>
<div id="are"> are </div>
<div id="you"> you </div>
I have a set of divs, and need to clone the link from the top and insert into the last div (mobile-link). It is either cloning the links from all of the divs, and then inserting all of them at once, or if I use :eq(0), it's putting the first link into all of the divs.
<div class="course">Accounting</div>
<div class="start-date">1-1-2017</div>
<div class="credits">4</div>
<div class="location">Online</div>
<div class="mobile-link"></div>
<div class="course">Business</div>
<div class="start-date">1-1-2017</div>
<div class="credits">3</div>
<div class="location">Online/Campus</div>
<div class="mobile-link"></div>
<script>
$(".course a:eq(0)").clone().appendTo(".mobile-link");
</script>
What do I need to change to make this work properly?
You need to process each anchor separately:
$(".course").each(function() {
var myLink = $(this).find('a').clone();
$(this).nextAll('.mobile-link').first().append(myLink);
});
Demo fiddle
Append method can take a function as argument, and here it is appending to the each .mobile-link first <a> from his previous .course div
$(".mobile-link").append(function(){
return $(this).prevAll('.course:first').find('a:first').clone();
});
Check the below snippet
$(".mobile-link").append(function(i) {
return $(this).prevAll('.course:first').find('a:first').clone();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="course">Accounting
</div>
<div class="start-date">1-1-2017</div>
<div class="credits">4</div>
<div class="location">Online</div>
<div class="mobile-link"></div>
<div class="course">Business
</div>
<div class="start-date">1-1-2017</div>
<div class="credits">3</div>
<div class="location">Online/Campus</div>
<div class="mobile-link"></div>
I beleive that you should use last (If I understood question correctly):
var lastDiv = $(".mobile-link").last();
$(".course a:eq(0)").clone().appendTo(lastDiv);
Here is jsfiddle: fiddle
I have a div setup like so:
<div class="content">
<button class="show-comments" id="content1"></button>
</div>
<div class="comments-wrapper" id="comment1"></div>
<div class="content">
<button class="show-comments" id="content2"></button>
</div>
<div class="comments-wrapper" id="comment2"></div>
I have the following code:
$('.show-comments').click(function(e){
e.preventDefault();
$('.comments-wrapper').slideToggle('slow');
});
As you would assume, the code works but on a class basis. I'd like for it to open up only the .comments-wrapper of its associated id (i.e. open slideToggle comments2 if content 2 button is clicked and so on and so on).
How would I do this?
$('.show-comments').click(function(e){
e.preventDefault();
$(this).closest(".content").next('.comments-wrapper').slideToggle('slow');
});
Note that this is dependent on the .content element being immediately followed by the .comments-wrapper.
If you have access to modify the html itself, I would suggest adding a wrapper element and then doing the following to avoid the reliance on the exact order of elements:
<div class="wrapper">
<div class="content">
<button class="show-comments" id="content1"></button>
</div>
<div class="comments-wrapper" id="comment1"></div>
</div>
<div class="wrapper">
<div class="content">
<button class="show-comments" id="content2"></button>
</div>
<div class="comments-wrapper" id="comment2"></div>
</div>
$(this).closest(".wrapper").find('.comments-wrapper').slideToggle('slow');
This way, if you add an element between the .content and the .comments-wrapper it does not break the code.
You can do this:
$(this).parent("div").next('.comments-wrapper').slideToggle('slow');
This will find the related div of class .comments-wrapper and slide toggle.
And a fiddle: http://jsfiddle.net/xCJQB/
$('.show-comments').click(function (e) {
e.preventDefault();
var num = this.id.match(/\d+$/)[0];
$("#comment" + num).slideToggle('slow');
});
Demo ---> http://jsfiddle.net/7pkyk/1/
Use this context
$(this).closest('.comments').next('.comments-wrapper').slideToggle('slow');
If it is not the immediate element then you might try this as well
$(this).closest('.comments')
.nextAll('.comments-wrapper').first().slideToggle('slow');
you can add a common class to associate a button with a div.
html:
<div class="content">
<button class="show-comments group1" id="content1"></button>
</div>
<div class="comments-wrapper group1" id="comment1">1</div>
<div class="content">
<button class="show-comments group2" id="content2"></button>
</div>
<div class="comments-wrapper group2" id="comment2">2</div>
javascript:
$('.show-comments').click(function(e){
var associate = $(this).attr('class').match(/group\d+/).pop();
var selector = '.comments-wrapper.' + associate;
e.preventDefault();
$(selector).slideToggle('slow');
});
http://jsfiddle.net/uMNfJ/