Jquery: if any .siblings().position().top is equal to $(this).position().top - javascript

I have the following html:
<div class="container" id="1"></div>
<div class="container" id="2"></div>
<div class="container" id="3"></div>
<div class="details" id="1"></div>
<div class="details" id="2"></div>
<div class="details" id="3"></div>
and jQuery:
$(document).ready(function () {
$('.container').each(function () {
$(this).click(function () {
var elem = $(this),
containerId = elem.attr('id'),
activeId = $(containerId + '.active');
$(this).toggleClass('active').siblings().removeClass('active');
$('#details-' + containerId).toggleClass('visible').siblings().removeClass('visible');
});
});
});
What I'm trying to do is see if any other .container div has the same position top as the active container (the one I just clicked). If they don't have the same top position, then I'll slide them down and display the details in full width.
So I'm thinking that something like this should work - $(this) meaning the active .container div :
if($(this).siblings().position().top == $(this).position().top) {
// add some class to EACH sibling that has equal top position
}
but I'm not entirely sure how to do it. Any help would be greatly appreciated!

You need to something like
var top = $(this).position().top;
var $sibs = $(this).siblings().filter(function(){
return $(this).position().top == top
})
//do something with the matching siblings refferred by $sibs
$(this).siblings().position().top will return the top value of the first sibling elements, it will not check the value of rest of the siblings.

Related

How to run jQuery function for multiple elements individually?

I can't make my jQuery function work on individual elements. My function is a slider. When I put one slider to my html, it works fine, without problems. But whenever I try to put a second slider, it doesn't work properly. The first slider controls both of them, then the second slider takes the charge if I click right arrow too much etc.
Here is my jQuery code:
$('.right-arrow').click(function () {
var currentSlide = $('.slide.active');
var nextSlide = currentSlide.next();
currentSlide.fadeOut(300).removeClass('active');
nextSlide.fadeIn(300).addClass('active');
if (nextSlide.length == 0) {
$('.slide').first().fadeIn(300).addClass('active');
}
});
$('.left-arrow').click(function() {
var currentSlide = $('.slide.active');
var prevSlide = currentSlide.prev();
currentSlide.fadeOut(300).removeClass('active');
prevSlide.fadeIn(300).addClass('active');
if (prevSlide.length == 0) {
$('.slide').last().fadeIn(300).addClass('active');
}
});
And this is where I use it:
<style>
.slide {
display:none;
}
.slide.active {
display:block;
}
</style>
<div class="slider-container">
<div id="slider1">
<div class="slide active">#1</div>
<div class="slide">#2</div>
<div class="slide">#3</div>
</div>
<p class="left-arrow"><</p>
<p class="right-arrow">></p>
</div>
<div class="slider-container">
<div id="slider2">
<div class="slide active">#a</div>
<div class="slide">#b</div>
<div class="slide">#c</div>
</div>
<p class="left-arrow"><</p>
<p class="right-arrow">></p>
</div>
Like I said previously, when I click the first slider's right arrow, first slider's #2 and second slider's #b shows up.
You are getting this behavior because of the line
var currentSlide = $('.slide.active');
which selects all elements with the classes slide and active. try replacing that line with something like this:
var currentSlide = $(this).parent().find('.slide.active');
What this is doing is selecting the element the event was fired on $(this). Then getting the parent of that element, then finding the active slide within that element.
EDIT
Here is an example of your first if statement. Once again, you are getting the parent of the element that caused the event, then searching inside that dom element for all of the elements with a class of 'slide'.
As a side note you might want to make $(this) a variable something like var $this = $(this). Then use $this instead of $(this). It's a performance issue that you may or may not be concerned with.
if (nextSlide.length == 0) {
$(this).parent().find('.slide').first().fadeIn(300).addClass('active');
}
As other answers and comments mentioned, you are searching the .slide elements on the whole document. Instead you need to limit the search inside the related .slider-container element. For this purpose, you can use JQuery.closest(). Also, it will be nice to wait the fadeOut animation to finish using the complete callback function before showing the new .slide element. You can take next example as reference of implementation:
$('.right-arrow').click(function()
{
var container = $(this).closest(".slider-container");
var currSlide = container.find('.slide.active');
var nextSlide = currSlide.next(".slide");
if (nextSlide.length === 0)
nextSlide = container.find('.slide:first-child');
currSlide.fadeOut(300, function()
{
$(this).removeClass('active');
nextSlide.fadeIn(300).addClass('active');
});
});
$('.left-arrow').click(function()
{
var container = $(this).closest(".slider-container");
var currSlide = container.find('.slide.active');
var prevSlide = currSlide.prev(".slide");
if (prevSlide.length === 0)
prevSlide = container.find('.slide:last-child');
currSlide.fadeOut(300, function()
{
$(this).removeClass('active');
prevSlide.fadeIn(300).addClass('active');
});
});
.slide {
display:none;
}
.slide.active {
display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slider-container">
<div id="slider1">
<div class="slide active">#1</div>
<div class="slide">#2</div>
<div class="slide">#3</div>
</div>
<p class="left-arrow"><</p>
<p class="right-arrow">></p>
</div>
<div class="slider-container">
<div id="slider2">
<div class="slide active">#a</div>
<div class="slide">#b</div>
<div class="slide">#c</div>
</div>
<p class="left-arrow"><</p>
<p class="right-arrow">></p>
</div>

Changing multiple divs based on arrows

I have created an input section for users to write their own work. I have multiple divs to the side of this and I'd like to change the divs from a left and right arrow that can be clicked.
$(document).ready(function() {
$('.menubody:nth-child(1)').show('slow');
$('.menubody:nth-child(1)').hide('slow');
$('.fa-caret-right').on({
click: function() {
var i = $('.menubody:visible').index();
var len = $('.menubody').length;
var next;
if (i >= 0) {
if (i == len - 1) {
next = $('.menubody:eq(0)');
} else {
next = $('.menubody:eq(' + (i + 1) + ')');
}
$('.menubody:visible').hide();
$(next).show();
}
}
});
});
EDIT:
I have a working example (see fiddle) that changes and changes the content when 'right' is pressed.
How do I make it so the 'left' div moves the content to previous? And add more than one content area to change?
For an example layout of the usage (not jQuery working), please see here.
Use jQuery's .prev() and .next(). If they return a collection of zero length, use .last() and .first() instead to cycle through your content (not sure that you needed this).
$(function() {
$('.tabs-container div').not(':first-child').hide();
$('#tabs li a').click(function() {
var $clickedLink = $(this),
$visible = $('.tabs-container div:visible');
$visible.each(function(){
var $this = $(this),
$parentContainer = $this.parents('.tabs-container').eq(0),
$toShow;
if( $clickedLink.is('.prev') ){
$toShow = $this.prev('div').length ? $this.prev('div') : $('div', $parentContainer).last();
} else {
$toShow = $this.next('div').length ? $this.next('div') : $('div', $parentContainer).first();
}
$this.hide();
$toShow.show();
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<ul id="tabs">
<li>Left Arrrow
</li>
<li>Right Arrow
</li>
</ul>
<div class="tabs-container">
<div id="content1">Content for link 1. Should display only when Link 1 is clicked.</div>
<div id="content2">Content for link 2. Should display only when Link 2 is clicked.</div>
<div id="content3">Content for link 3. Should display only when Link 3 is clicked.</div>
<div id="content4">Content for link 4. Should display only when Link 4 is clicked.</div>
</div>
<p>Unrelated text is here. Text in this area is static and should display at all times.</p>
<div class="tabs-container">
<div id="content1-2">Additional content for link 1. Should display only when Link 1 is clicked.</div>
<div id="content2-2">Additional content for link 2. Should display only when Link 2 is clicked.</div>
</div>
<p>More unrelated text</p>
<div class="tabs-container">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
</div>
I think you should use the nth-child() jQuery selector here. Simply increment the value of n every time the button right is clicked and decrease the value of n every time the left arrow is clicked.
$('#left-arrow').on('click', function(){
var i++;
$('main-div:nth-child(i-1)').hide();
$('main-div:nth-child(i)').show();
})
Here's a link to read more : W3 Schools :nth-child() selector

How can I separate these divs in the javascript?

I have this div scrolling script:
$(document).ready(function () {
$('.tab-box').each(function () {
var top = 0;
var $tabbox = $(this);
var height = $tabbox.height();
$(this).find('.tab').each(function () {
var shift = top;
$(this).click(function () {
$tabbox.find('.items').animate({
marginTop: shift + 'px'
});
$tabbox.find('.tab').removeClass('active');
$(this).addClass('active');
});
top -= height;
});
$(this).find('.tab:eq(0)').addClass('active');
});
});
If I understand it correctly it gets every divs working only within the div "tab-box".
http://jsfiddle.net/9SfEH/5/
What I want to change is that I separate the "tabs" from the main tab-box div, but make them still controll the "items".
http://jsfiddle.net/w65Dn/1/
I was trying for a simple solution buuut couldn't come up with one by myself.
Thanks everyone in advance :)
The problem was that in the original code, it was looking for the tab clickables using $(this).find(".tab"), but the .tabs were no longer inside of the .tab-box. So, if you just search globally, with $(".tab"), it works.
Note that you can no longer have more than one tab box, because it is searching globally for the .tabs. You could use something like javaCity's solution (i.e. wrapping everything in another div) to fix this.
You were looking for .tabs inside the tab-box which does not exist. So how about creating a div outside of .tabs which also encloses tab-box?
http://jsfiddle.net/3D8we/
HTML:
<div class="enclosingDiv">
<div class="tabs">
<div class="tab">1</div>
<div class="tab">2</div>
<div class="tab">3</div>
</div>
<div class="tab-box">
<div class="items">
<div class="item" style="background: #cbe86b;"></div>
<div class="item" style="background: #f2e9e1;"></div>
<div class="item" style="background: #1c140d;"> </div>
</div>
</div>
</div>
JS:
$(document).ready(function () {
$('.tab-box').each(function () {
var top = 0;
var $tabbox = $(this);
var height = $tabbox.height();
$('.enclosingDiv').find('.tab').each(function () {
var shift = top;
$(this).click(function () {
$tabbox.find('.items').animate({
marginTop: shift + 'px'
});
$tabbox.find('.tab').removeClass('active');
$(this).addClass('active');
});
top -= height;
});
$(this).find('.tab:eq(0)').addClass('active');
});
});
On line 7, change the selector from this to .tabs
$(this).find('.tab') becomes $(.tabs).find('.tab')
as seen here: jsfiddle example

Select next element carousel

I have a list of DIVs, and I want every X second using setTimeout to take the next div and set the display to block, and for the other ones to none, how can I do that? Can someone please give me an example?
How can I make it to be infinite, when reaches the last one to start from the first one again.
I know this is a kind of carousel, but I want too see how it's done.
There are many ways to do this, but here's one way: http://jsfiddle.net/jfriend00/Yr3NV/
HTML:
<div id="container">
<div class="item active">1111</div>
<div class="item">2222</div>
<div class="item">3333</div>
<div class="item">4444</div>
<div class="item">5555</div>
<div class="item">6666</div>
<div class="item">7777</div>
</div>
Code:
setInterval(function() {
var next = $("#container .active").removeClass("active").next();
if (next.length == 0) {
next = $("#container .item:first");
}
next.addClass("active");
}, 1000);
CSS:
.item {display: none;}
.item.active {display: block;}
Using the method of adding/removing a class gives you a little more style control via CSS rather than coding the style into your javascript and avoids the use of any global or closure variables to keep the state.
var divs = $('#container').find('div'),
index = 0;
setInterval(function() {
if (!divs[index]) index = 0;
divs.hide();
divs[index++].style.display = 'block';
}, 1000); // fires every 1 second
All the usual disclaimers about global scope being a bad idea, but this should give you what you want.
$("#list div").hide();
var current = $("#list div").first().show();
setInterval(function() {
current.hide();
current = current.next().length > 0 ? current.next() : $("#list div").first();
current.show();
},2000);
<div id="list">
<div>1</div>
<div>22</div>
<div>333</div>
<div>4444</div>
</div>
Can be seen working here:
http://jsfiddle.net/KenwV/
Here's an implementation with setTimeout: http://jsfiddle.net/imsky/EBpTw/
Given a UL with id of "list" and LIs inside:
$(function() {
$("#list li:gt(0)").hide();
function showNextBlock() {
var currentBlock = $("#list li:visible");
if (currentBlock.index() == $("#list li").length - 1) {
currentBlock.hide().parent().find("li:first").show()
}
else {
currentBlock.hide().next("li").show();
}
setTimeout(showNextBlock,1000);
}
setTimeout(showNextBlock,1000);
});
DIV LOOP DEMO
var i=0, len=$('#parent div').length;
(function loop(){
$('#parent div').eq(i++%len).fadeTo(700,1).siblings().fadeTo(700,0,loop);
})();
HTML example:
<div id="parent">
<div class="children ch1">I'm DIV 1</div>
<div class="children ch2">I'm DIV 2</div>
<div class="children ch3">I'm DIV 3</div>
<div class="children ch4">I'm DIV 4</div>
</div>
CSS basic setup:
.children{
position:absolute;
}
And here is one with a mouseover pause :
DEMO with mouseover pause
function cycleDivs(base)
{
var next = ($(base).next('div').css('display') == 'none')? $(base).next('div') : $('div:first');
$(base).hide();
$(next).show();
window.setTimeout(function(){cycleDivs(next);}, 1000)
}
window.setTimeout(function(){cycleDivs($('div:first'));}, 1000);
Here's a working example: http://jsfiddle.net/8hfBd/

on .bind('click') it is not deleting the first div

When I click on a particular div, that div should fade out, simple, but when I click on one of the divs it deletes the div on top of the stack, i.e. when I click #sel6 it removes sel5
HTML code
<div id="selc_d" class="selc" style="position:absolute; left:15px; top:200px; width:260px;">
<div id="sel5" class="sel">something</div>
<div id="sel6" class="sel">something</div>
<div id="sel7" class="sel">something</div>
</div>
jQuery code
sel_id, sel_1 are variables
$('.selc_d').bind('click',function(){
var sel_id = $('.sel').attr('id');
alert(sel_id);
$('#'+sel_id).fadeOut('slow');
$('#'+sel_id).remove();
$('.search_box').append(sel_1);
});
$('.sel').bind('click',function(){
var sel_id = this.id; // replace this line using this.id or $(this).attr('id');
alert(sel_id);
$('#'+sel_id).fadeOut('slow');
$('#'+sel_id).remove();
$('.search_box').append(sel_1);
});
Note the use of this... this will contain the element that is clicked.
What you were doing was
var sel_id = $('.sel').attr('id');
Which will always select the first div with class sel in this case the div with id sel5
##WHAT YOU WANT##
<div id="selc_d" class="selc" style="position:absolute; left:15px; top:200px; width:260px;">
<div id="sel5" class="sel">something</div>
<div id="sel6" class="sel">something</div>
<div id="sel7" class="sel">something</div>
</div>
$('.sel').bind('click',function(){
var sel_id = $(this).attr('id');
alert(sel_id);
$('#'+sel_id).fadeOut('slow');
$('#'+sel_id).remove();
$('.search_box').append(sel_1);
});
it looks like, you are trying something like this
$('.sel').bind('click', function(){
$this = $(this);
$this.fadeOut('slow', function(){$this.remove();});
$('.search_box').append(this.id);
});
That's because you are saying $('.sel')
You need to grab the one that is clicked, not any one that has that class. To make that work as you want, do this
$('.sel').click( function() {
var sel_id = $(this).attr('id');
$(this).fadeOut('slow');
// Wait for it to fade out before you remove it
setTimeout( function() {
$('#' + sel_id).remove();
}, 1000 );
$('.search_box:first').append(sel_id);
});

Categories