jQuery - Transition between images instead of sudden change - javascript

I am showing and hiding images depending on a button click by changing the src like this...
var images = ["https://dummyimage.com/300x300/000/fff&text=Image+1", "https://dummyimage.com/300x300/000/fff&text=Image+2", "https://dummyimage.com/300x300/000/fff&text=Image+3"];
$('.btn').click(function(){
$('.btn').removeClass('active').addClass('inactive');
$(this).removeClass('inactive').addClass('active');
if ( $('.btn1').hasClass('active') ) {
$("#output").attr("src",images[0]);
} else if ( $('.btn2').hasClass('active') ) {
$("#output").attr("src",images[1]);
} else if ( $('.btn3').hasClass('active') ) {
$("#output").attr("src",images[2]);
}
});
.active{background:green;}
.inactive{background:grey;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btn btn1 active">
Button 1
</button>
<button class="btn btn2 inactive">
Button 2
</button>
<button class="btn btn3 inactive">
Button 3
</button>
<br>
<br>
<img id="output" src="https://dummyimage.com/300x300/000/fff&text=Image+1">
This is working but I would like the images to transition into each other instead of just suddenly change
I know I can fade out and then in but is there a way to fade one into another instead?

You can achieve this by using fadeIn(), fadeOut() function:
$("#output").fadeOut("slow");
if ( $('.btn1').hasClass('active') ) {
$("#output").attr("src",images[0]);
} else if ( $('.btn2').hasClass('active') ) {
$("#output").attr("src",images[1]);
} else if ( $('.btn3').hasClass('active') ) {
$("#output").attr("src",images[2]);
}
$("#output").fadeOut("slow");

Depending on your needs, you can load use fade out and switch elements, or likewise use a background image. I've opted for a double image, using a spacer and assumed that since all your images are the same dimensions, then they will always been the same size.
The code below looks for the index in the array using a data attribute from the clicked element, then loads the image into the temp img, fades out the original, sets the url of the original and then shows it.
var images = ["https://dummyimage.com/300x300/000/fff&text=Image+1", "https://dummyimage.com/300x300/000/fff&text=Image+2", "https://dummyimage.com/300x300/000/fff&text=Image+3"];
var spacer = 'https://dummyimage.com/300x300/4a314a/fff&text=Spacer';
$('.btn').click(function(){
var $t = $(this);
var tgt = parseFloat($t.attr('data-target'));
$('.btn').removeClass('active');
$t.addClass('active');
$("#temp").attr("src",images[tgt]);
$("#output").fadeOut('300', function() {
$("#output").attr("src",images[tgt]).show();
$("#temp").attr("src",spacer);
});
});
.btn {background:grey;}
.btn.active{background:green;}
#imgswap {position:relative;}
#imgswap>img {position:absolute;top:0;left:0;}
#output {z-index:2;}
#temp {z-index:1;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btn btn1 active" data-target="0">
Button 1
</button>
<button class="btn btn2 inactive" data-target="1">
Button 2
</button>
<button class="btn btn3 inactive" data-target="2">
Button 3
</button>
<br>
<br>
<div id="imgswap">
<img id="output" src="https://dummyimage.com/300x300/000/fff&text=Image+1">
<img id="temp" src="https://dummyimage.com/300x300/4a314a/fff&text=Spacer">
</div>
I think the above should do you well enough and should work if you're using fixed-size images.

Use .fadeOut() and .fadeIn() to acheive a similar illusion to what you are looking for. Remeber that all animation functions in jQuery can accept a callback function.
In my solution below, I am calling .fadeOut() immediately after the button is pressed, but also pass a call back function to be executed once the .fadeOut() animation is finished. In that callback, I am chaning the source of the image and immediately queuing another animation:= .fadeIn()
var images = ["https://dummyimage.com/300x300/000/fff&text=Image+1", "https://dummyimage.com/300x300/000/fff&text=Image+2", "https://dummyimage.com/300x300/000/fff&text=Image+3"];
$('.btn').click(function(){
$('.btn').removeClass('active').addClass('inactive');
$(this).removeClass('inactive').addClass('active');
var new_src;
if ( $('.btn1').hasClass('active') ) { new_src = images[0]; }
else if ( $('.btn2').hasClass('active') ) { new_src = images[1]; }
else if ( $('.btn3').hasClass('active') ) { new_src = images[2]; }
$('#output').fadeOut('slow',function(){
$("#output").attr("src",new_src);
$('#output').fadeIn();
});
});
.active{background:green;}
.inactive{background:grey;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btn btn1 active">
Button 1
</button>
<button class="btn btn2 inactive">
Button 2
</button>
<button class="btn btn3 inactive">
Button 3
</button>
<br>
<br>
<img id="output" src="https://dummyimage.com/300x300/000/fff&text=Image+1">

Related

Change the outcome of a variable based on a button push to match a different button

I have a button with an id that sets a global variable like this:
<div class="mybuttons"
<button id="mapOne" data-toggle="modal" data-target="#map-1-scene-1">Scene</button>
<button class="no-click-span" id="mapOneCurrent" data-toggle="modal" data-target="#map-1-scene-1"><i class="fas fa-charging-station fa2x"></i> Current</button>
</div>
Then in JS:
var mapNumber;
const mybuttons = document.querySelectorAll('.mybuttons button');
mybuttons.forEach(mybutton => {
mybutton.addEventListener('click', processClick);
});
function processClick() {
window.mapNumber = this.id; // the id of the clicked button
}
The second button in the div with the id #mapOneCurrent just reopens the modal without refreshing the data.
What I would like to happen, is if the second button is pushed (eg #mapOneCurrent) that the variable mapNumber just remains as mapOne (without the word "Current" at the end of it). So it would almost be as if the other button had been pushed.
Is this possible to do in this type of scenario?
This should do what you want:
var mapNumber;
const mybuttons = [...document.querySelectorAll('.mybuttons button')];
mybuttons.forEach(mybutton=>{
mybutton.addEventListener('click',function() {
window.mapNumber = this.id.replace("Current",""); // the id of the clicked button
console.log(mapNumber);
});
})
<div class="mybuttons">
<button id="mapOne" data-toggle="modal" data-target="#map-1-scene-1">Scene</button>
<button class="no-click-span" id="mapOneCurrent" data-toggle="modal" data-target="#map-1-scene-1"><i class="fas fa-charging-station fa2x"></i>Current</button>
</div>
However, you could simplify it by using "delegated event listening" to:
var mapNumber;
document.querySelector('.mybuttons').addEventListener('click',function(ev){
if (ev.target.tagName==="BUTTON") {
window.mapNumber = ev.target.id.replace("Current","");
console.log(mapNumber);
}
})
<div class="mybuttons">
<button id="mapOne" data-toggle="modal" data-target="#map-1-scene-1">Scene</button>
<button class="no-click-span" id="mapOneCurrent" data-toggle="modal" data-target="#map-1-scene-1"><i class="fas fa-charging-station fa2x"></i>Current</button>
</div>
In this snippet the event is listening to clicks on the wrapper container .mybuttobs but will trigger actions only if an inside BUTTON was clicked.

How to fadeOut two children elements simultaneously using $(this)

I have a div in which there are 3 buttons. What I am expecting is that when I click the 3rd button, the 2nd and the 3rd buttons should fadeOut ... but in reality, only the 3rd button is fading out ... why so?
Here's, my code
<div id="bttns">
<button class="btn btn-danger"> Delete </button> //1st Button
<button class="btn btn-warning"> Modify </button> //2nd Button
<button class="btn btn-success"> Complete </button> //3rd Button
</div>
And here is the jQuery
$(".btn-success").on("click", function(){
$( $(this) , $(this).parent().children(".btn-warning") ).fadeOut(500)
})
I couldn't find a question similar to mine ... and also I am new to all of this so if you do find that such a question exists, please redirect me to it.
This happens becuse:
$( $(this) , $(this).parent().children(".btn-warning") )
this is not a valid selector here. To chain multiple jQuery objects you can use .add() method and then call .fadeOut(500) on the collection like:
$(".btn-success").on("click", function() {
var $btn3 = $(this);
var $btn2 = $(this).parent().children(".btn-warning");
$btn2.add($btn3).fadeOut(500)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="bttns">
<button class="btn btn-danger"> Delete </button>
<button class="btn btn-warning"> Modify </button>
<button class="btn btn-success"> Complete </button>
</div>
As you have assigned classes. You can go like this :-
$(".btn-success").on("click", function () {
$('.btn-warning, .btn-success').fadeOut(500);
})
you are fading out only the button with the btn-warning class. instead use two selectors.
$(".btn-success").on("click", function(){
$(this).parent().children(".btn-warning, .btn-success").fadeOut(500)
})

How to capture two same id but different class in addEventListener

first of all, thank you for your time to read this question, and two things, I'm using ES5 and I don't use jQuery.
Right now I'm struggling a lot to figure what's the correct solution for the addEventListener, because for some reason it does not trigger for the second button which is only for the mobile screen dimensions, the problem is that the second button have the same id but different class, for example this:
<div class="product-bg-container product-general-info variation-info">
<input type="hidden" name="sku" value="Something-15892290" id="selected-option">
{/* Desktop screen button */}
<button id="buy-now" class="btn btn-lg hidden-sm-down btn-primary">
Add to Cart
</button>
{/* Mobile screen button */}
<button id="buy-now" class="btn btn-lg hidden-md-up btn-primary">
Add to Cart
</button>
</div>
Where I am trying to trigger the second button but it does not where I don't understand why it does, if the id is the same, should not matter, so I'm trying to figure how to trigger from the first button if it's clicked and also with the second if it's clicked, but I'm out of ideas...
var button = document.getElementById('buy-now');
if (!button) {
return;
}
button.addEventListener('click', function trackAddToCart() {
// more code for the event
}
I thought an idea to capture the attribute of the button, but it works in the first button but not for the second one:
var button = document.getElementById('buy-now');
var att = button.getAttribute('class');
button.addEventListener('click', function() {
console.log('class ' + att); //shows: class: btn btn-lg hidden-sm-down btn-primary
console.log('button class? '+ button); //shows: button element: [object HTMLButtonElement]
});
But when I click the second button... does not trigger or happening nothing, not sure why... and I can't change the id value (which it should be easy but I can't "company standard")
Can anyone help me to have an idea how to capture and trigger the event for the second button ??
The attribute id must be unique in a document. You can use attributeStartsWith selector or class with querySelectorAll(). Then loop through all the button to attach the event (click) individually:
//var button = document.querySelectorAll('.btn.btn-primary');
var button = document.querySelectorAll('[id^=buy-now]');
button.forEach(function(btn){
btn.addEventListener('click', function() {
console.log('class ' + this.classList);
console.log('button class? '+ this.id);
});
});
<div class="product-bg-container product-general-info variation-info">
<input type="hidden" name="sku" value="Something-15892290" id="selected-option">
<button id="buy-now" class="btn btn-lg hidden-sm-down btn-primary">
Add to Cart
</button>
<button id="buy-now2" class="btn btn-lg hidden-md-up btn-primary">
Add to Cart
</button>
</div>
nextElementSibling seems working in this case.
var btn1 = document.getElementById("btn");
var btn2 = btn1.nextElementSibling;
btn1.addEventListener("click",function(e){
console.log("btn1");
});
btn2.addEventListener("click",function(e){
console.log("btn2");
});
<div>
<button id="btn" class="btn1">butotn 1</button>
<button id="btn" class="btn2">butotn 2</button>
</div>

How can I get a substring of an ID name?

I have a number of buttons within a section, each with an id of the form #balls-left-n, where n ranges from 1 to 15.
When one of these buttons is clicked, I want to grab the number from the id that was clicked and hide all of the buttons with ids that have names including numbers that are greater than the one clicked on.
So, if #balls-left-13 is clicked, I want to hide #balls-left-14 and #balls-left-15. But if #balls-left-3 is clicked I want to hide all the buttons from #balls-left-4 through #balls-left-15.
I'm a novice at web-dev so if I've made other mistakes or taken a poor approach don't hesitate to point that out.
I have a handler for each of the buttons (which if I knew more could probably be one function) that look like this:
$("#balls-left-14").click(function() {
var num_balls = $(this).attr('id').match(/[\d]/);
j_end_balls_on_table = 14;
$("#balls-left button:gt(num_balls-2)").hide;
...
other stuff
...
});
This didn't work and I get an error that num_balls is undefined, which I don't understand.
#balls-left is the section all of the buttons are inside of.
relevant HTML as requested
<section id="balls-left">
<h2>How Many Balls are Left on the Table?</h2>
<button type="button" id="balls-left-2" class="x-balls-left">2</button>
<button type="button" id="balls-left-3" class="x-balls-left">3</button>
<button type="button" id="balls-left-4" class="x-balls-left">4</button>
<button type="button" id="balls-left-5" class="x-balls-left">5</button>
<button type="button" id="balls-left-6" class="x-balls-left">6</button>
<button type="button" id="balls-left-7" class="x-balls-left">7</button>
<button type="button" id="balls-left-8" class="x-balls-left">8</button>
<button type="button" id="balls-left-9" class="x-balls-left">9</button>
<button type="button" id="balls-left-10" class="x-balls-left">10</button>
<button type="button" id="balls-left-11" class="x-balls-left">11</button>
<button type="button" id="balls-left-12" class="x-balls-left">12</button>
<button type="button" id="balls-left-13" class="x-balls-left">13</button>
<button type="button" id="balls-left-14" class="x-balls-left">14</button>
<button type="button" id="balls-left-15" class="x-balls-left">15</button>
</section>
Hope this helps.
var exploded = id.split("-");
alert(exploded.pop());
Now, to use that concept on your HTML structure, you can do something like this:
$(document).ready(function() {
$(".x-balls-left").click(function(e) {
e.preventDefault();
var exploded = this.id.split("-");
alert(exploded.pop());
});
});
And here's a Fiddle you can play around with.
You might don't even need all of these if your elements to hide share the same parent. Just set class on click .selected and hide the rest using CSS .selected.x-balls-left ~ .x-balls-left {display: none;}
$('.x-balls-left').click(function() {
$(this).toggleClass('selected');
})
.selected.x-balls-left ~ .x-balls-left {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section id="balls-left">
<h2>How Many Balls are Left on the Table?</h2>
<button type="button" id="balls-left-2" class="x-balls-left">2</button>
<button type="button" id="balls-left-3" class="x-balls-left">3</button>
<button type="button" id="balls-left-4" class="x-balls-left">4</button>
<button type="button" id="balls-left-5" class="x-balls-left">5</button>
<button type="button" id="balls-left-6" class="x-balls-left">6</button>
<button type="button" id="balls-left-7" class="x-balls-left">7</button>
<button type="button" id="balls-left-8" class="x-balls-left">8</button>
<button type="button" id="balls-left-9" class="x-balls-left">9</button>
<button type="button" id="balls-left-10" class="x-balls-left">10</button>
<button type="button" id="balls-left-11" class="x-balls-left">11</button>
<button type="button" id="balls-left-12" class="x-balls-left">12</button>
<button type="button" id="balls-left-13" class="x-balls-left">13</button>
<button type="button" id="balls-left-14" class="x-balls-left">14</button>
<button type="button" id="balls-left-15" class="x-balls-left">15</button>
</section>
$(document).on('click', '.balls-left', function() {
var num = getNum(this);
$('.balls-left').each(function() {
var that = $(this);
var bnum = getNum(that);
if (bnum > num) {
that.show();
} else {
that.hide();
}
});
});
var getNum = function(elem) {
if (elem) {
return $(elem).attr('id').replace('balls-left-', '');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="balls-left-1" class="balls-left">Ball 1</div>
<div id="balls-left-2" class="balls-left">Ball 2</div>
<div id="balls-left-3" class="balls-left">Ball 3</div>
<div id="balls-left-4" class="balls-left">Ball 4</div>
<div id="balls-left-5" class="balls-left">Ball 5</div>
$("#balls-left button:gt(num_balls-2)").hide;
This is an invalid CSS selector, and only gets the hide method, without calling it. You want something like:
$("#balls-left button:gt("+(num_balls-2)+")").hide();
First you should put a class on each object so you can reference them all at once, and the simplest way to understand is to just put the ball number right in the tag as a custom attribute if you can:
<input type="button" id="balls-left-1" class="left-ball" num="1"/>
<input type="button" id="balls-left-2" class="left-ball" num="2"/>
etc...
Then you can write the javascript as follows:
$('.left-ball').click(function () {
var BallNum = $(this).attr('num');
$('.left-ball').each(function () {
if ($(this).attr('num') > BallNum) {
$(this).hide();
}
});
});
You can use RegEx match like this. This might resolve your undefined num_balls error message.
$("#balls-left-14").click(function() {
var ret = $(this).attr('id').match("[0-9]+");
var num_balls = ret[0];
j_end_balls_on_table = 14;
$("#balls-left button:gt(num_balls-2)").hide;
...
other stuff
...
});
Another way of doing it using your original HTML:
$('.x-balls-left').click(function () {
var BallNum = $(this)[0].innerHTML;
$('.x-balls-left').each(function () {
if ($(this)[0].innerHTML > BallNum) {
$(this).hide();
}
});
});
I just did it like this:
$('button[id^=balls-left-]').click(function(){
var num_balls = $(this).attr('id').match(/[\d]/);
$('#balls-left button:gt(' + num_balls + ')').hide();
});
Keep in mind that :gt select by index, it means that $('#balls-left button:gt(2)') will not select the button with id balls-left-2 but the one with id balls-left-4 (according to the html you posted).

hide many button with next and preview button

I have ten buttons with a button for next and previous,
when I click the next button, it should show the next two buttons (hiding the rest).
The reverse should happen when the previous button is clicked (Show the previous two buttons (hide the rest)).
thanks.
my html code is :
<div>
<button class="menu">M1</button>
<button class="menu">M2</button>
<button class="menu">M3</button>
<button class="menu">M4</button>
<button class="menu">M5</button>
<button class="menu">M6</button>
<button class="menu">M7</button>
<button class="menu">M8</button>
<button class="menu">M9</button>
<button class="menu">M10</button>
</div>
<div>
<button class="action" id="btnNext">Next</button>
<button class="action" id="btnPreview">Previous</button>
</div>
Initially make every button hidden except first two.
$("#btnNext").on('click', function(){
var vBtn = $(".menu:visible:last");
$(".menu").hide();
vBtn.next().show();
vBtn.next().next().show();
});
$("#btnPreview").on('click', function(){
var vBtn = $(".menu:visible:first");
$(".menu").hide();
vBtn.prev().show();
vBtn.prev().prev().show();
});
I manually coded not tested please check
$("button.menu").not(':eq(0),:eq(1)').hide();
var count = 1;
$("#btnNext").click(function() {
$("button.menu").hide();
count = count + 2;
$("button.menu").eq(count-1).show();
$("button.menu").eq(count).show();
});
$("#btnPreview").click(function() {
$("button.menu").hide();
count = count - 2;
$("button.menu").eq(count-1).show();
$("button.menu").eq(count).show();
});

Categories