How to add Prev and next buttons to change on outer divs - javascript

I have this sample navigation that I'm trying to create. What I want to achieve is when you clicked on prev or next class. The active class will be added to map-inr and the scale_text will also be added to the global_map_location class. I believe that only the eq() function will be used in this part.
Here's my js Code:
// Open Popup
$(".map-inr").on("click", function () {
let myIndex = $(this).closest(".global-map").index() - 1;
$('.map-inr').removeClass('active');
$(this).addClass('active');
$('.global_map_location').removeClass('scale_text');
$(this).closest(".global-map").find('.global_map_location').addClass('scale_text');
if ($(".map-item.is--show").length) {
$(".map-item").removeClass("is--show");
setTimeout(function () {
$(".map-item").eq(myIndex).addClass("is--show");
}, 600);
} else {
$(".map-item").eq(myIndex).addClass("is--show");
}
});
//Next function
$('.next').click(function(){
if ($('.is--show').next('.map-item').length) {
$('.is--show').removeClass('is--show')
.next('.map-item')
.addClass('is--show');
}
});
//Prev function
$('.prev').click(function(){
if ($('.is--show').prev('.map-item').length) {
$('.is--show').removeClass('is--show')
.prev('.map-item')
.addClass('is--show');
}
});
.global-map {
display: inline-block;
vertical-align: top;
margin-right: 20px;
margin-bottom: 20px;
}
.map-inr {
background: red;
width: 150px;
height: 150px;
cursor: pointer;
}
.map-inr.active {
background: yellow;
}
.global_map_location.scale_text {
font-weight: 600;
}
.contain {
width: 100%;
max-width: 1000px;
margin: 50px auto 0;
padding: 0;
}
.map-item {
display: inline-block;
vertical-align: top;
padding: 20px;
border-radius: 20px;
text-align: center;
}
.map-item.is--show {
background: yellow;
}
.slider-arrow-wrapper {
margin-bottom: 20px;
}
.slider-arrow-wrapper .prev,
.slider-arrow-wrapper .next {
display: inline-block;
vertical-align: top;
text-decoration: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="global-map">
<div class="map-inr active"></div>
<p class="global_map_location scale_text">map1</p>
</div>
<div class="global-map">
<div class="map-inr"></div>
<p class="global_map_location">map2</p>
</div>
<div class="global-map">
<div class="map-inr"></div>
<p class="global_map_location">map3</p>
</div>
<div class="contain">
<div class="map-item is--show">
<div class="slider-arrow-wrapper">
prev
next
</div>
1
</div>
<div class="map-item">
<div class="slider-arrow-wrapper">
prev
next
</div>
2</div>
<div class="map-item">
<div class="slider-arrow-wrapper">
prev
next
</div>
3</div>
</div>
I have tried this on next button:
//Next function
$('.next').click(function(){
let nextIndex = $(this).closest(".map-item").index() + 1;
console.log("This next is " + nextIndex);
$(".global-map").eq(nextIndex).find('.map-inr').addClass("active");
$(".global-map").eq(nextIndex).find('.global_map_location').addClass("scale_text");
if ($('.is--show').next('.map-item').length) {
$('.is--show').removeClass('is--show')
.next('.map-item')
.addClass('is--show');
}
});
But it just keeps adding classes to next div. How to remove the classes from prev sections/divs? Is there any proper way to do it?

When user click on Prev and Next anchor tag which have Yellow background then only it should work. It is not feasible solution to make all the prev and next anchor tag click work. Only yellow background prev and next click should work.
Below is the code which match up the scenario which is explained above and also it will give you the user friendly standard view:
$(".next").on('click', function(e) {
e.preventDefault();
if($(this).closest(".map-item.is--show").next().length > 0)
{
$(".contain .is--show").removeClass('is--show').next().addClass("is--show");
$(".map-inr.active").removeClass('active').parent().next().children(".map-inr").addClass("active");
}
});
$(".prev").on('click', function(e) {
e.preventDefault();
if($(this).closest(".map-item.is--show").prev().length > 0)
{
$(".contain .is--show").removeClass('is--show').prev().addClass("is--show");
$(".map-inr.active").removeClass('active').parent().prev().children(".map-inr").addClass("active");
}
Please replace it with your prev and next click jQuery.
Let me know if you have any issues or modification request.

Related

is there any better way to do this js code?

I am making these panels to be resized to fit screen height as I click 'this' element. I feel like I hard coded those javascript, and I believe there must be better way. But couldn't really sort it out.
when one panel is clicked, its size is going to get bigger, and rest of pannels gonna get smaller
I would very much appreciate any suggestion of it.
I've tried making this function reusable, but then couldn't really come up with better solution as I am a begginer.
const panels = document.querySelectorAll('.panel');
const panelsArr = Array.from(panels);
panelsArr.forEach(panel => panel.addEventListener('click',getCurrentName))
function getCurrentName(element) {
const panel1 = document.querySelector('.panel1');
const panel2 = document.querySelector('.panel2');
const panel3 = document.querySelector('.panel3');
const panel4 = document.querySelector('.panel4');
console.log(this);
if(this) {
this.classList.toggle('active');
if(this === panel1) {
panel2.classList.toggle('inactive');
panel3.classList.toggle('inactive');
panel4.classList.toggle('inactive');
} else if (this === panel2) {
panel1.classList.toggle('inactive');
panel3.classList.toggle('inactive');
panel4.classList.toggle('inactive');
} else if (this === panel3) {
panel1.classList.toggle('inactive');
panel2.classList.toggle('inactive');
panel4.classList.toggle('inactive');
} else if (this === panel4) {
panel1.classList.toggle('inactive');
panel2.classList.toggle('inactive');
panel3.classList.toggle('inactive');
}
}
}
.panel {
background-color: #002712;
box-shadow: inset 0 0 0 .5rem rgba(255,255,255,0.1);
min-height: 22.5vh;
color: #fff;
text-align: center;
font-size: 2rem;
background-size: cover;
background-position: center;
line-height: 8rem;
transition:
min-height .5s linear,
font-size .2s linear .5s,
line-height .2s linear .5s;
}
.panel1 { background-image: url("../images/steake.png"); }
.panel2 { background-image: url("../images/sundayRoast.png"); }
.panel3 { background-image: url("../images/image1(1).png"); }
.panel4 { background-image: url("../images/cannonbury.png"); }
.active {
min-height: 37vh;
line-height: 15rem;
font-size: 2.3rem;
}
.inactive {
min-height: 15vh;
font-size: 1.2rem;
}
<main>
<section class="intro">
<div class="intro-panels">
<section class="panel panel1">
<p>most original,</p>
</section>
<section class="panel panel2">
<p>best beer,</p>
</section>
<section class="panel panel3">
<p>grilled food</p>
</section>
<section class="panel panel4">
<p>Islington</p>
</section>
</div>
</section>
</main>
I expect simplified javascript code to achieve the same goal.
Here's how I've sorted it out by your answer. Thank you for your help guys.
const panels = document.querySelectorAll('.panel');
const panelsArr = Array.from(panels);
panelsArr.forEach(panel => panel.addEventListener('click', getCurrentName))
function getCurrentName(element) {
if(this) {
panelsArr.forEach(panel => panel.classList.toggle('inactive'));
this.classList.toggle('inactive');
this.classList.toggle('active');
}
}
You could mark them all as inactive and re-mark the current one as active.
Array.from(document.querySelectorAll('.panel')).forEach(element => {
element.classList.remove('active');
element.classList.add('inactive')
});
this.classList.remove('inactive');
this.classList.add('active');
You could also filter out this from the array, but it wouldn't change the outcome.
You can toggle inactive class on all class elements but undo it again on the target element:
const panels = document.querySelectorAll('.panel');
const panelsArr = Array.from(panels);
panelsArr.forEach(panel => panel.addEventListener('click',getCurrentName))
function getCurrentName(element) {
console.log(this);
if(this) {
// Toggle inactive on all elements
for (i = 0; i < panels.length; ++i) {
panels[i].classList.toggle('inactive');
}
//But undo for selected element again
this.classList.toggle('inactive');
this.classList.toggle('active');
}
}
Try something like this. Event delegation
document.addEventListener('click', (e) => {
if(e.target.matches('.sizable')) {
document.querySelectorAll('.sizable').forEach(div => {
div.classList.remove('active');
div.classList.add('inactive');
});
e.target.classList.add('active');
}
});
.sizable {
display: inline-block;
border: 1px solid black;
margin: 5px;
}
.inactive {
width: 50px;
height: 50px;
}
.active {
width: 150px;
height: 150px;
}
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>

Sliding animation when hiding/showing a div

I have two divs, top and bottom. Both divs have dynamic height, the top div will show or hide depending on a variable.
I would like to add in a sliding animation to the top div when showing or hiding, but the bottom div should stick with the top div and slide with it too.
var hide = true;
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if (hide) {
topdiv.classList.add('hide');
} else {
topdiv.classList.remove('hide');
}
hide = !hide;
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
background: #999;
}
.body {
background: #555;
}
.hide {
display: none !important;
}
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>
I tried adding transform animations, but the effect is only applied to the top div while the bottom div remains unanimated.
#keyframes topDivAnimate {
from {
transform: translateY(-100%);
}
to {
transform:translateY(0%);
}
}
Help is much appreciated.
I would use CSS transition rather than animation. I've found it easiest to do by animating the lower div rather than the upper one, and changing its position so that it covers the top one (or, of course, not). See demonstration below, I've made as minimal changes as I could to the CSS and JS:
var cover = true;
var trigger = document.getElementById("trigger");
var bottomdiv = document.getElementsByClassName("body")[0];
trigger.addEventListener('click', function() {
if (cover) {
bottomdiv.classList.add('cover');
} else {
bottomdiv.classList.remove('cover');
}
cover = !cover;
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
background: #999;
}
.body {
background: #555;
transform: translateY(0%);
transition: transform 0.5s;
}
.cover {
transform: translateY(-100%);
}
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>
Are you looking something like this? Then please try this:
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if ($('#topdiv').css('display') == 'none') {
$(topdiv).slideDown();
} else {
$(topdiv).slideUp();
}
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
display: none;
background: #999;
}
.body {
background: #555;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>
Try this code and see if that's the effect you wanted. It uses the Animate.css library so you'll need to link that in your <head></head>
function animateCSS(element, animationName, callback) {
const node = document.querySelector(element)
node.classList.add('animated', animationName)
function handleAnimationEnd() {
node.classList.remove('animated', animationName)
node.removeEventListener('animationend', handleAnimationEnd)
if (typeof callback === 'function') callback()
}
node.addEventListener('animationend', handleAnimationEnd)
}
var hide = false;
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if (!hide) {
topdiv.classList.remove('hide');
animateCSS('.body', 'slideInDown');
animateCSS('#topdiv', 'slideInDown');
} else {
animateCSS('#topdiv', 'slideOutUp', function() {
topdiv.classList.add('hide');
})
animateCSS('.body', 'slideOutUp');
}
hide = !hide;
});
Working Codepen demo of my solution
Here's some more explanation on how to use the Animate.css library.

Stop tabbed element closing on second click

I have snippet of code that opens tabs, however I would like 1 tab to always remain open.
How can I disable the second click on the tab button already open stopping the tab from closing?
So referring to the fiddle, if you click 'Button 1' once, it will show the corresponding tab, but if you click 'Button 1' again it shouldn't close the corresponding tab. Only clicking 'Button 2' will close it also opening it's own tab.
Fiddle
JS
$(document).ready(function() {
$(".tone").click(function(e) {
e.preventDefault();
var tab = $(this).attr("id");
$(".tone__pack").not(tab).css("display", "none");
$(tab).toggle();
});
});
HTML
<div class="tone" id="#tone1">
Button 1
</div>
<div class="tone__pack" id="tone1">
</div>
<div class="tone" id="#tone2">
Button 2
</div>
<div class="tone__pack" id="tone2">
</div>
CSS
.tone {
display: block;
background: blue;
width: 100px;
text-align: center;
color: #fff;
}
.tone__pack {
display: none;
width: 100px;
height: 100px;
background: red;
}
You can use .show() instead of toggle.
fiddle
$(document).ready(function() {
$(".tone").click(function(e) {
e.preventDefault();
var tab = $(this).attr("id");
$(".tone__pack").not(tab).css("display", "none");
$(tab).show();
});
});
.tone {
display: block;
background: blue;
width: 100px;
text-align: center;
color: #fff;
}
.tone__pack {
display: none;
width: 100px;
height: 100px;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tone" id="#tone1">
Button 1
</div>
<div class="tone__pack" id="tone1">
</div>
<div class="tone" id="#tone2">
Button 2
</div>
<div class="tone__pack" id="tone2">
</div>
Toggle it only when its pack is hidden, like so:
$(document).ready(function() {
$(".tone").click(function(e) {
e.preventDefault();
var tab = $(this).attr("id");
if($(".tone__pack"+tab).is(":hidden")) {
$(".tone__pack").not(tab).css("display", "none");
$(tab).toggle();
}
});
});
.tone {
display: block;
background: blue;
width: 100px;
text-align: center;
color: #fff;
}
.tone__pack {
display: none;
width: 100px;
height: 100px;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tone" id="#tone1">
Button 1
</div>
<div class="tone__pack" id="tone1">
</div>
<div class="tone" id="#tone2">
Button 2
</div>
<div class="tone__pack" id="tone2">
</div>
I modified your code like this,
When the tab is opened, I will add one class to identify that it is already opened.
when again a click event is detected, if it already contains the class, the will not do anything,else I will do as required.
$(document).ready(function() {
$(".tone").click(function(e) {
e.preventDefault();
var tab = $(this).attr("id");
$(".tone__pack").not(tab).css("display", "none");
// removing class, if it is present in any other tab
$(".tone__pack").not(tab).removeClass("active");
//if it is already opened, then return
if($(tab).hasClass("active")){
return;
}
//add identifier for next iterations
$(tab).addClass("active");
$(tab).toggle();
});
});

Button click Triggers Text Below

I want to set up a functionality for a button that causes text to appear underneath it on click.
For example, when you click a button that says "Sign up now", text would appear underneath the button that says "Are you a member, yes or no?".
"Yes" and "No" would be links that bring you to a different page depending on how you answer.
My button code so far (just html and styling done):
<a href="/ticket-link" target="_blank" class="ticket-button">Sign Up
Now</a>
I'm new with this kind of functionality so any help would be greatly appreciated!
Thanks!
Adjust the href attribute as you want.
$('#btn').click(function() {
$('#modal').fadeIn();
});
a {
display: block;
text-decoration: none;
color: white;
background-color: #333;
width: 100px;
padding: 20px;
border-radius: 5px;
margin: 0 auto;
}
#modal {
width: 300px;
height: 120px;
background-color: #ccc;
border-radius: 5px;
margin: 0 auto;
display: none;
}
#modal h3 {
text-align: center;
padding: 10px;
}
#modal a {
width: 50px;
display: inline-block;
text-align: center;
margin: 0 auto;
height: 10px;
vertical-align: middle;
line-height: 10px;
}
.btns {
width: 200px;
margin: auto;
}
a:hover {
background-color: #666;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="/ticket-link" target="_blank" class="ticket-button" id='btn'>Sign Up Now</a>
<div id='modal'>
<h3>Are you a member?</h3>
<div class='btns'>
Yes
No
</div>
</div>
You could use the onClick function to unhide text, or elements, below it.
Sign Up Now
<span style="display:none;" id="text">This is some text :D</span>
simple way:
Sign Up Now
<script>
function confirmSignup(){
if(confirm("Are you sure?"))
{
window.location.href="http://somelocation.com/sign-up";
}
}
</script>
Like #Pety Howell said, you can use the onClick function to unhide the text. Here's a pretty straightforward way to do it with jQuery.
$(function() {
$('.link').on('click', function() {
$('.span').addClass('open');
});
});
.span {
display: none;
}
.open {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Click me
<span class="span">I'm hidden!</span>
Working fiddle: https://jsfiddle.net/3gr03yzn/4/
You could use jQuery toggle() function.
HTML :
<button id="member">
Are you Member ?
</button>
<div class="answer">
Yes<br />
No
</div>
JS :
$("#member").click(function() {
$(".answer").toggle();
});
CSS :
.answer {
display:none;
}
The working example on jsFiddle.
Hope this helps
Try this code.
please vote if this code helpful to you
function execute(){
var x = document.getElementById('link_list');
var y =document.getElementById('btn');
if(x.style.visibility==="hidden"){
y.style.visibility="hidden";
x.style.visibility="visible";
}
}
<button onclick="execute()" id="btn">sign up</button>
<div id="link_list" style="visibility:hidden">
Are you a member, <button onclick="window.open('http://sparrolite.blogspot.in')">Yes</button> or <button onclick="window.open('google.com')">no</button>
</div>
Most answers mentioned here either uses
jQuery or,
onclick attribute which is obtrusive javascript.
Here's how to achieve the desired behavior using vanilla, unobtrusive JavaScript.
window.onload = function() {
var button = document.querySelector('.ticket-button');
var info = document.querySelector('.info');
info.style.display = 'none';
var dispalyInfo = false;
button.onclick = function(e) {
e.preventDefault(); /* prevent page from navigating to a new page onclick */
if (dispalyInfo) {
info.style.display = 'none';
dispalyInfo = false;
} else {
info.style.display = 'initial';
dispalyInfo = true;
}
}
}
.ticket-button {
display: block;
}
Sign Up Now
<span class="info">Are you a member, yes or no?</span>
References:
Document.querySelector()
HTMLElement.style

jQuery custom slider creation with loop

Please, help me to configure my slider.
If you click on numbers in any row, you can see, that jquery give them classes and spin slider to index()
I want to add arrows to my slider, and do infinite loop. Eg if number 2 selected right arrow moves all 3 rows to number 3. And vice versa.
Here is my code.
$('.item').click(function() {
$this = $(this);
$(".item").removeClass("active");
$('.item').each(function() {
if (+$(this).index() == +$this.index()) {
$(this).addClass('active');
var box = $(this).closest('.scroll');
var x = ($(this).position().left - (box.width() / 2)) + box.scrollLeft();
box.animate({
scrollLeft: x
});
}
});
});
* {
margin: 0;
padding: 0;
}
.first-line,
.second-line,
.line3 {
margin-top: 20px;
}
.second-line,
.line3 {
margin-left: 20px;
}
.second-line {
width: 200px;
overflow: auto;
}
.line3 {
width: 200px;
overflow: hidden;
}
.wrap {
width: 500px;
}
.number,
.anotherclass,
.onemoreclass {
display: inline-block;
width: 40px;
height: 40px;
line-height: 40px;
font-size: 15px;
border: 1px solid blue;
text-align: center;
margin: 0 10px;
}
.right-arrow,
.left-arrow {
display: inline-block;
cursor: pointer;
margin: 0 20px;
}
.number.active,
.anotherclass.active,
.onemoreclass.active {
background: blue;
color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="left-arrow"> << </div>
<div class="right-arrow"> >> </div>
<div class="first-line scroll">
<div class="anywrap">
<div class="number active item">1</div>
<div class="number item">2</div>
<div class="number item">3</div>
<div class="number item">4</div>
<div class="number item">5</div>
</div>
</div>
<div class="second-line scroll">
<div class="wrap">
<div class="anotherclass item active">1</div>
<div class="anotherclass item">2</div>
<div class="anotherclass item">3</div>
<div class="anotherclass item">4</div>
<div class="anotherclass item">5</div>
</div>
</div>
<div class="line3 scroll">
<div class="wrap">
<div class="onemoreclass item active">1</div>
<div class="onemoreclass item">2</div>
<div class="onemoreclass item">3</div>
<div class="onemoreclass item">4</div>
<div class="onemoreclass item">5</div>
</div>
</div>
Added to your function to support all of what you want. Let me know if this helps! Added comments to areas I changed to explain what I am doing. I also made $this a local variable instead of a global as well by defining it with var.
Fiddle: http://jsfiddle.net/AtheistP3ace/3ewguuyL/
JS:
// Attach click to all clickable elements
$('.item, .left-arrow, .right-arrow').click(function () {
var $this = $(this);
// check if we clicked an item or arrow
if (!$this.hasClass('item')) {
// if left arrow, get previous item of first active we find
if ($this.hasClass('left-arrow')) {
$this = $('.item.active:first').prev();
}
// if right arrow, get next item of first active we find
else if ($this.hasClass('right-arrow')) {
$this = $('.item.active:first').next();
}
// Handle being at the start or end of items
if ($this.length == 0) {
return;
}
}
// Let your previous code run
$(".item").removeClass("active");
$('.item').each(function () {
if (+$(this).index() == +$this.index()) {
$(this).addClass('active');
var box = $(this).closest('.scroll');
var x = ($(this).position().left - (box.width() / 2)) + box.scrollLeft();
box.animate({
scrollLeft: x
});
}
});
});
Have a look at https://jsfiddle.net/0m0raekm/
For the arrow support I just added this part:
$('.arrow-control').click(function(){
var direction = $(this).hasClass('left-arrow') ? -1 : 1;
var currentItemIndex = $('.anywrap .active').index();
var itemCount = $('.anywrap .item').length;
var nextItemIndex = (currentItemIndex + direction)%itemCount;
var nextItem = $('.anywrap .item').get( nextItemIndex );
$(nextItem).trigger( "click" );
});
It is quite generic: it determines the currently active item, chooses the next one depending on the arrow direction and the number of items (infinite loops) and triggers a click event on the item that is supposed to be next. So after determining the next item, it uses your original code to do the actual effect.

Categories

Resources