How to call function after javascript .scroll() - javascript

Description
I want to call a function after the javascript .scroll() function has finished.
Code
The interesting part is the javascript:
const vertScroll = document.getElementById('boxSlider');
$("#btnLeft").on("click", () => {
vertScroll.scroll({
left: vertScroll.scrollLeft - 120,
behavior: "smooth"
});
//This should print out the new value of
//vertScroll but instead always prints the value
//before scroll()
console.log(vertScroll.scrollLeft);
});
$("#btnRight").on("click", () => {
vertScroll.scroll({
left: vertScroll.scrollLeft + 120,
behavior: "smooth"
});
//same as above
console.log(vertScroll.scrollLeft);
});
.boxSlider {
width: 100%;
overflow-x: auto;
white-space: nowrap;
display: inline-block;
}
.box {
display: inline-block;
background-color: cyan;
width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="boxSlider" class="boxSlider">
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
<div class="box">Box 4</div>
<div class="box">Box 5</div>
<div class="box">Box 6</div>
<div class="box">Box 7</div>
<div class="box">Box 8</div>
<div class="box">Box 9</div>
<div class="box">Box 10</div>
</div>
<input id="btnLeft" type="Button" value="Scroll left"/>
<input id="btnRight" type="Button" value="Scroll right" />
Expected Behaviour
console.log(...) should output the scroll value after the scroll() function has completed.
Not the answer
Don't just do console.log(scrollLeft - 120) (or +120) since I want to implement more complex code there and the console.log() is just for better understanding.
What I've tried
I've looked at the scroll() docs (mozilla scroll()) and it doesn't seem to have a callback function.
Question
How can I achieve the expected behaviour?
TIA

Related

JavaScript Sortable do function on list changes?

How can I make a function fire when a sortable list changes?
I have looked for some examples but they are making the lists different to how I am and I cant see how to do it with how my sortable lists are generated. Perhaps I am using a different Sortable version or something?
This is how I make my lists...
<script>
Sortable.create(plansList, {
animation: 100,
group: 'list-1',
draggable: '.recipe',
handle: '.handle',
sort: true,
filter: '.sortable-disabled',
chosenClass: 'active'
});
Sortable.create(suggestionsList, {
animation: 100,
group: 'list-1',
draggable: '.recipe',
handle: '.handle',
sort: true,
filter: '.sortable-disabled',
chosenClass: 'active'
});
</script>
As you can see I have 2 lists. I want both to fire the same function when they change, but if both lists change (because an item was moved from one list to the other) I don't want the function to fire twice.
Can anyone help?
Thanks,
Chris
Event onEnd will only fire once, as requested. But it will fire if also no change has been made. So you might need to compare old index to new index.
var example2Left = document.querySelector("#example2-left");
var example2Right = document.querySelector("#example2-right");
new Sortable(example2Left, {
group: 'shared', // set both lists to same group
animation: 150,
onEnd: foo
});
new Sortable(example2Right, {
group: 'shared',
animation: 150,
onEnd: foo
});
function foo(ev) {
var to = ev.to;
var from = ev.from;
var oldIndex = ev.oldIndex;
var newIndex = ev.newIndex;
if (to != from || oldIndex != newIndex) {
singleOnChange(ev)
}
}
function singleOnChange(ev) {
console.log("list(s) changed")
}
.col {
width: 50%;
float: left;
}
.list-group-item {
padding: 10px;
margin: 2px;
background: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js" integrity="sha512-Eezs+g9Lq4TCCq0wae01s9PuNWzHYoCMkE97e2qdkYthpI0pzC3UGB03lgEHn2XM85hDOUF6qgqqszs+iXU4UA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="example2-left" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 6</div>
</div>
<div id="example2-right" class="list-group col">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 6</div>
</div>

Javascript Toggle opening all divs [duplicate]

This question already has answers here:
jQuery toggle children of div
(4 answers)
Closed 4 years ago.
I'm trying to make an accordion and I'm using the same classes for each row. Like this.
$(document).ready(function() {
$(".faq-article").click(function() {
$(".faq-details").toggle();
})
});
.faq-details {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="faq">
<div class="faq-article">
<div class="title-faq">Question 1</div>
<div class="faq-details">answer</div>
</div>
<div class="faq-article">
<div class="title-faq">Question 2</div>
<div class="faq-details">answer 2</div>
</div>
</div>
I can't remember how to prevent showing all the faq-details when clicking on the first question title.
You need to use this as context of your search for the .faq-details element.
$(document).ready(function() {
$(".faq-article").click(function() {
$(".faq-details", this).toggle();
})
});
.faq-details {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="faq">
<div class="faq-article">
<div class="title-faq">Question 1</div>
<div class="faq-details">answer</div>
</div>
<div class="faq-article">
<div class="title-faq">Question 2</div>
<div class="faq-details">answer 2</div>
</div>
</div>
As there are multiple elements with class faq-article, when implementing toggle() on that class all elements are affected. To get the currently clicked element you have to target the current context of the click event by specifying this.
Change
$(".faq-details").toggle();
To
$(this).find(".faq-details").toggle(); OR $(".faq-details", this).toggle();
$(document).ready(function() {
$(".faq-article").click(function() {
$(this).find(".faq-details").toggle();
})
});
.faq-details {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="faq">
<div class="faq-article">
<div class="title-faq">Question 1</div>
<div class="faq-details">answer</div>
</div>
<div class="faq-article">
<div class="title-faq">Question 2</div>
<div class="faq-details">answer 2</div>
</div>
</div>

Onclick scroll to next div with a specific ID

$('.mark').click(function(){
var id = $(this).attr('id');
var next = (Number(id) + 1);
window.scrollTo($('#'+next));
})
.mark {
height: 500px;
color: white;
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='marker'>
<div class='mark' id='1'>Mark 1</div>
<div class='mark' id='2'>Mark 2</div>
<div class='mark' id='3'>Mark 3</div>
<div class='mark' id='4'>Mark 4</div>
<div class='mark' id='5'>Mark 5</div>
</div>
Right here, I'm trying to make my window scroll to the next div with an id numbered with current id + 1.
I've tried window.scrollTo($('#'+next));.
But didn't work, then tried window.scrollTo($('#'+next), 500);.
But always returns to first div + 500px.
What is the proper way to handle that?
window.scrollTo(xpos, ypos) takes two parameters. The first one is coordinate along x-axis and second is along y-axis. So you can use 0 for first parameter and $('#'+next).offset().top for second parameter
$('.mark').click(function(){
var id = $(this).attr('id');
var next = (Number(id) + 1);
//window.scrollTo(0, $('#'+next).offset().top);
$('html, body').animate({scrollTop : $('#'+next).offset().top}, 2000);
})
.mark {
height: 500px;
color: white;
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='marker'>
<div class='mark' id='1'>Mark 1</div>
<div class='mark' id='2'>Mark 2</div>
<div class='mark' id='3'>Mark 3</div>
<div class='mark' id='4'>Mark 4</div>
<div class='mark' id='5'>Mark 5</div>
</div>
I have done something like this which maybe helpfull for you check out.
HTML
<div class='marker'>
<div class='mark' id='1'>Mark 1</div>
<div class='mark' id='2'>Mark 2</div>
<div class='mark' id='3'>Mark 3</div>
<div class='mark' id='4'>Mark 4</div>
<div class='mark' id='5'>Mark 5</div>
</div>
CSS
.mark {
height: 500px;
color: white;
background: black;
}
JS
$(document).ready(function(){
$('.mark').click(function(){;
var y = $(this).outerHeight();
var z =$(window).scrollTop();
$('body').animate({scrollTop:z+y},800);
});
});
You can check the demo here
$('.mark').click(function(){
var id = $(this).attr('id');
var next = (Number(id) + 1);
location.href="#"+next;
});
.mark {
height: 500px;
color: white;
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='marker'>
<div class='mark' id='1'>Mark 1</div>
<div class='mark' id='2'>Mark 2</div>
<div class='mark' id='3'>Mark 3</div>
<div class='mark' id='4'>Mark 4</div>
<div class='mark' id='5'>Mark 5</div>
</div>
This is the solution when you use data-number.
Actually, it's not perfect solution.
But I hope it help you.
$('.mark').click(function(){
var id = $(this).attr('data-number');
var next = (Number(id) + 1);
window.scrollTo(0, $(`.mark[data-number=${next}]`).offset().top);
});
.mark {
height: 500px;
color: white;
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='marker'>
<div class='mark' data-number='1'>Mark 1</div>
<div class='mark' data-number='2'>Mark 2</div>
<div class='mark' data-number='3'>Mark 3</div>
<div class='mark' data-number='4'>Mark 4</div>
<div class='mark' data-number='5'>Mark 5</div>
</div>

Jquery optimisation [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I made an animation with jquery and I find myself with 15400 line of code.
I have 26 div (images) with IDs: .article1, article2, .article3, .article4, ... article26.
When I click on one of them lot of translation will be applied on the others.
I want to decrease the number of code lines, i tried a For loop:
for (var i = 1 ; i<=26 ; i++)
{
$('.article' + i]).click(function(){
-- animations --
}
}
But it seems don't work because the value of i will take the last value of the loop (26) so the click function will work only on the div with id .article26.
Thank you.
this could be a way to manage an animation over many different named elements...
function AnimationCtrl($) {
var els = $('[class^="article"]');
els.click(function(event) {
$(this).toggleClass('is-active');
});
}
jQuery(document).ready(AnimationCtrl);
[class^="article"] {
padding: .5em 1em;
background: cyan;
border: 1px solid lightseagreen;
display: inline-block;
margin: .2em .5em;
cursor: pointer;
transition: 500ms all linear;
}
.is-active[class^="article"] {
background: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="article-1">elemnt number 1</div>
<div class="article-2">elemnt number 2</div>
<div class="article-3">elemnt number 3</div>
<div class="article-4">elemnt number 4</div>
<div class="article-5">elemnt number 5</div>
<div class="article-6">elemnt number 6</div>
<div class="article-7">elemnt number 7</div>
<div class="article-8">elemnt number 8</div>
<div class="article-9">elemnt number 9</div>
<div class="article-10">elemnt number 10</div>
<div class="article-11">elemnt number 11</div>
<div class="article-12">elemnt number 12</div>
<div class="article-13">elemnt number 13</div>
<div class="article-14">elemnt number 14</div>
<div class="article-15">elemnt number 15</div>
<div class="article-16">elemnt number 16</div>
<div class="article-17">elemnt number 17</div>
<div class="article-18">elemnt number 18</div>
<div class="article-19">elemnt number 19</div>
<div class="article-20">elemnt number 20</div>
<div class="article-21">elemnt number 21</div>
<div class="article-22">elemnt number 22</div>
<div class="article-23">elemnt number 23</div>
<div class="article-24">elemnt number 24</div>
<div class="article-25">elemnt number 25</div>
<div class="article-26">elemnt number 26</div>

Edit css of "item" when clicking on corresponding "btn"

So I have this
<div class="btns">
<div class="btn1"></div>
<div class="btn2"></div>
<div class="btn3"></div>
<div class="btn4"></div>
</div>
<div class="prevs">
<div class="pre1"></div>
<div class="pre2"></div>
<div class="pre3"></div>
<div class="pre4"></div>
</div>
http://jsfiddle.net/uzpxjukv/
You have btn1, btn2, btn3 and btn4. I'm trying to make it so that when you press btn1, the div with the class pre1 should then get "display: block;" or something to make it visible. Then when btn2 is clicked, pre1 turns invisible again and pre2 turns visible.
Maybe something like this? If there will be more buttons, it should be more optimalized.
$('.btns').find('div').click(function(){
$('.prevs').find('div').eq($(this).index()).toggle();
});
$('.btns').find('div').click(function(){
$('.prevs').find('div').eq($(this).index()).toggle();
});
.prevs div:not(.pre1) {
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btns">
<div class="btn1">Button 1</div>
<div class="btn2">Button 2</div>
<div class="btn3">Button 3</div>
<div class="btn4">Button 4</div>
</div>
<div class="prevs">
<div class="pre1">Previews 1</div>
<div class="pre2">Previews 2</div>
<div class="pre3">Previews 3</div>
<div class="pre4">Previews 4</div>
</div>
JSFIDDLE DEMO -> http://jsfiddle.net/uzpxjukv/5/
$('.btns div').click(function() {
var classNumber = this.className.slice(-1);
$('.prevs div').hide();
$('.pre' + classNumber).show();
});
On click of the button div, first hide all the pre divs and then show only the relevant div.
Try it
$('.btns > div').on('click', function() {
var numberOfDiv = $(this).attr('class').slice('-1'),
prevs = $('.prevs');
prevs.find('> div').hide();
prevs.find('.pre' + numberOfDiv).show();
});
This example is with your html code, if is possible to change it, you can get a better code.
See the fiddle
I have changed your HTML a little bit..Changed the class attribute of the prevs divsti ids.
HTML
<div class="btns">
<div class="btn1" id="1" onClick="reply_click(this.id)"></div>
<div class="btn2" id="2" onClick="reply_click(this.id)"></div>
<div class="btn3" id="3" onClick="reply_click(this.id)"></div>
<div class="btn4" id="4" onClick="reply_click(this.id)"></div>
</div>
<div class="prevs">
<div id="pre1"></div>
<div id="pre2"></div>
<div id="pre3"></div>
<div id="pre4"></div>
</div>
JS
function reply_click(id) {
document.getElementById("pre" + id).style.display = "block";
}
Provided that you know what naming system the divs use, you could use something along these lines. (To see properly working, view using developer tool)
$('.btns div').on('click', function() {
var currClass = $(this).attr('class').slice(-1); //get end of number of div clicked
$('.prevs div').css('display', 'none'); //reset all divs to being hidden
$('.pre' + currClass).css('display', 'inline-block'); //show desired div
});
.btns div {
background-color: gray;
}
.btns div, .prevs div {
width: 2em;
height: 2em;
display: inline-block;
padding-right: 0.2em;
}
.prevs div {
background-color: red;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btns">
<div class="btn1"></div>
<div class="btn2"></div>
<div class="btn3"></div>
<div class="btn4"></div>
</div>
<div class="prevs">
<div class="pre1"></div>
<div class="pre2"></div>
<div class="pre3"></div>
<div class="pre4"></div>
</div>

Categories

Resources