Changing multiple divs based on arrows - javascript

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

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>

jQuery carousel dots on click always going to first item

I'm building a carousel with basic jquery - I'm using the .css() rule to simply toggle opacity between each slide.
The way I want to do this is on click of each dot I want to check if the specific class exists and if it does hide all other items and show that one. So far I have:
$('.dot').click(function() {
$('.review-module--reviews').children().css('opacity', 0);
if ($('.dot').hasClass('dot1')) {
$('.review-one').css('opacity', 1);
$('.dot1').addClass('dot-active');
} else if ($('.dot').hasClass('dot2')) {
$('.review-two').css('opacity', 1);
$('.dot2').addClass('dot-active');
} else {
$('.review-three').css('opacity', 1);
$('.dot3').addClass('dot-active');
}
});
HTML:
<div class="review-module">
<div class="review-module--reviews">
<div class="review-one">
</div>
<div class="review-two">
</div>
<div class="review-three">
</div>
</div>
<span class="slider-dots">
<div class="dot dot1"></div>
<div class="dot dot2"></div>
<div class="dot dot3"></div>
</span>
</div>
However when I click on dots 2 and 3, it always targets the dot1 slide in the DOM. The 'dot-active' class gets added successfully to dot1 but on click of 2 and 3, that class does not get added.
I also tried explicity checking for a true value in the if statement like so:
if ($('.dot').hasClass('dot1') === true)
Is this the best way to do this? Or should I consider a different thought process?
The error is in this code:
if ($('.dot').hasClass('dotX'))
What you're actually doing here is fetching the list of all .dot elements and checking if the first one has the dotX class. As you can imagine, this will always pick up the first .dot element, which has the dot1 class.
What you probably mean to do is to check if the element that was clicked on has the dotX class, for which you need to check only that element.
Either do so by using the current scope of the click handler:
if ($(this).hasClass('dotX'))
or by checking the target of the click event:
$('.dot').click(function(e) {
$('.review-module--reviews').children().css('opacity', 0);
if ($(e.target).hasClass('dot1')) {
Try this may be it can help you -
JAVASCRIPT CODE-
$('.dot').click(function() {
$('.review-module--reviews').children().css('opacity', 0);
$('.dot').removeClass('dot-active');
if ($(this).hasClass('dot1')) {
$('.review-one').css('opacity', 1);
$(this).addClass('dot-active');
} else if ($(this).hasClass('dot2')) {
$('.review-two').css('opacity', 1);
$(this).addClass('dot-active');
} else {
$('.review-three').css('opacity', 1);
$(this).addClass('dot-active');
}
});
I suggest to use data-* attributes instead so give every .dot a data-review that refer to the related review div :
$('.review-module--reviews div').hide(); //Hide all the slides
$('.dot').click(function() {
var review = $(this).data('review');
$('.review-module--reviews div').hide(); //Hide all slides
$('.slider-dots .dot').removeClass('dot-active'); //Remove 'dot-active' class from all the dots
$(this).addClass('dot-active'); //Active the clicked dot
$('.review-'+review).show(); //Show the related slide
});
Then on click just get the review using jQuery method .data() and show the div with related class.
Hope this helps.
$('.review-module--reviews div').hide();
$('.dot').click(function() {
var review = $(this).data('review');
$('.review-module--reviews div').hide();
$('.slider-dots .dot').removeClass('dot-active');
$(this).addClass('dot-active');
$('.review-'+review).show();
});
.dot-active{
color: green;
font-weight:bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="slider-dots">
<div class="dot dot1" data-review="one">dot1</div>
<div class="dot dot2" data-review="two">dot2</div>
<div class="dot dot3" data-review="three">dot3</div>
</span>
<br>
<div class="review-module">
<div class="review-module--reviews">
<div class="review-one">
Review-one
</div>
<div class="review-two">
Review-two
</div>
<div class="review-three">
Review-three
</div>
</div>
</div>

show pagination in a javascript tabs

I have this javascript code that allows me to show and hide tabs but my problem is when the user clicks on a link in the last tab it shows the first one. In another way the result of my clicks are hiden by the other tab.
Here is my javascript
$(document).ready(function() {
$("#content div").hide(); // Initially hide all content
$("#tabs li:first").attr("id","current"); // Activate first tab
$("#content div:first").fadeIn(); // Show first tab content
$('#tabs a').click(function(e) {
e.preventDefault();
if ($(this).closest("li").attr("id") == "current"){ //detection for current tab
return
}
else{
$("#content div").hide(); //Hide all content
$("#tabs li").attr("id",""); //Reset id's
$(this).parent().attr("id","current"); // Activate this
$('#' + $(this).attr('name')).fadeIn(); // Show content for current tab
}
});
});
This $('#' + $(this).attr('name')).fadeIn(); is where I think your problem is. That is some very messed up code. Without seeing your markup, I'm not even sure what you were trying to do, but that isn't it. Anyway, you ended up trying to do that because your solution is messy to begin with. See my example below. I only do what is necessary...no need to add ids and attributes to everything to hide/show the appropriate things.
Here is a light and simple way to accomplish what you're looking for. Live demo (click here).
sample markup:
<ul class="tabs">
<li>
<a>Tab1</a>
</li>
<li>
<a>Tab2</a>
</li>
<li>
<a>Tab3</a>
</li>
</ul>
<div class="content">
<div>Tab1 Content</div>
<div>Tab2 Content</div>
<div>Tab3 Content</div>
</div>
javascript:
$(document).ready(function() {
$(".content div").not(':first').hide();
var $content = $('.content');
$('.tabs a').click(function() {
var index = $(this).parent().index();
var $selected = $('div:eq('+index+')', $content);
$('div', $content).not($selected).hide();
$selected.show();
});
});

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/

Best approach to slideup and tabs with jQuery

I'm creating a page with an image at the top, and a menu below. When the user clicks on on of the 3 menu buttons, the image slideUp and the page scrolls down so the menu is at the top of the page, then the right .content div fades in. The slideUp should only happen the first time the user clicks on of the buttons.
What the absolute best way to do this with jQuery? (no plugins)
I also need to know how I can't prevent it to fade in the page that is already visible if i click the same button twice?
I'm using rel instead of href, since the href made the page jump, even with return false.
This is what I have so far:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
imgVisible = true;
$('#mainmenu a').click(function(){
var $activeTab = $(this).attr('rel');
if(!imgVisible){
$('html:not(:animated),body:not(:animated)').animate({scrollTop:$('#mainmenu').offset().top-20},500);
$('.content').hide();
$($activeTab).fadeIn();
} else{
$('#imgholder').slideUp(500,function(){
imgVisible = false;
$('#mainmenu a[rel="'+$activeTab+'"]').click();
});
}
return false;
});
});
</script>
<div id="imgholder"><img src="image.jpg" /></div>
<div id="mainmenu">
<ul>
<li><a rel="#tab1"></a></li>
<li><a rel="#tab2"></a></li>
<li><a rel="#tab3"></a></li>
</ul>
</div>
<div id="container">
<div class="content" id="tab1">
content
</div>
<div class="content" id="tab2">
content
</div>
<div class="content" id="tab3">
content
</div>
</div>
The following code accomplishes what you need:
$('#mainmenu a').click(function(){
var myrel=$(this).attr('rel');
$('.content:not([id='+myrel+'])').hide();
$('#imgholder').slideUp(500,function(){
$('#'+myrel).fadeIn();
});
});
....
<li><a href='#' rel='tab0'></a></li>
I have removed the '#' sign from your rel='' piece ;-)
I am not sure why you would want to scroll the page. When a user clicks on the menu, he/she already has it focused (so it is visible inside the current viewport). But do you have a very large top image? If that is the case, let me know and I will modify the snippet. (Still, it depends on the amount of content below the menu visible when the page first loads.)
Also, for SEO reasons you might want to use the href instead of the rel attribute and create separate content holding pages. The following snippet would remove the navigation action.
$('#mainmenu a').each(function(){
var myhref = $(this).attr('href');
$(this).attr('href','#').attr('rel',myhref);
}).click(function(){
var myrel=$(this).attr('rel');
$('.content:not([id='+myrel+'])').hide();
//....etc
I think this is a great example of what your looking for: Organic Tabs
var imgVisible = true;
var $activeTab, $lastTab;
var $mainmenu = $('#mainmenu');
var offset = $mainmenu.offset().top - 20;
$mainmenu.find('a').click(function() {
$activeTab = $($(this).attr('rel'));
if (!imgVisible) {
// dont fire any events if already open
if ($lastTab.attr('id') == $activeTab.attr('id')) return false;
$lastTab.fadeOut('normal', function() {
$activeTab.fadeIn(500, function() {
$lastTab = $activeTab;
});
});
} else {
$('#imgholder').slideUp(500, function() {
imgVisible = false;
window.scrollTo(0, offset);
$activeTab.fadeIn(500, function() {
$lastTab = $activeTab;
});
});
}
return false;
});
I highly suggest adding <a href="#"> as this will not make the page jump when done properly and will ensure validation on your anchor links. Someone let me know if I missed something, it can be resolved quickly (or you can do it for me if you have an optimization or improvement).

Categories