Vue how to trigger click on links based on interval - javascript

In my vue-app I have a list of links, which I want to be triggered automatically one by one by a default interval, lets say after 3 seconds, the first link gets triggered, then after another 3 seconds, link 2 gets triggered... so its kind of a carousel/autoplay with links I want to achieve, but I don't really know how to solve that.
here is my code:
<li v-for="(slide, index) in slides" :key="index" :class="slideIndex === index ? 'active' : ''" #click="slideIndex = index" ref="slide">
{{ slide.title }}
</li>
and then I thought somethinbg like this:
mounted() {
Object.keys(this.$refs.slide).forEach((el) => {
setInterval(() => {
this.$refs.slide[el].click();
}, 3000);
});
},
but this triggers all links and does not seem to be right at all, but its just a slight idea...
Can someone help me out?

I would not recommend doing this by simulating a click on the link.
How about setting the element you want to be active in your code?
I assume slideIndex is the current selected slide?
You could try something like this:
setInterval(() => {
this.slideIndex = this.slideIndex < this.slides.length - 1 ? (this.slideIndex += 1) : 0;
}, 3000);
So you add +1 every time the interval is triggered and cycle through the slides. If it's at the end slideIndex gets reset and starts at 00

Related

Click event doesn't produce any result

total noob here.
I'm writing a countdown timer that starts clicking on a "Start" button. No matter what I do, the timer always starts at the load of the page. And I mean that, when using live server on VS Code, every time I give the page a save, the timer starts.
No error appears in the console.
Probably I'm missing something really basilar, but I would love some help!
const btnStart = document.querySelector('.start');
const startTimer = function() {
let time = 10;
const timer = setInterval(function() {
const min = String(Math.trunc(time/60));
const sec = String(time%60);
time --;
input.value = `${min.length <= 9 ? min.padStart(2, 0) : min}:${sec.length <= 9 ?sec.padStart (2, 0) : sec}`;
if(time == 0){
setTimeout(function(){clearInterval(timer);
startTimer();}, 1000)
}
}, 1000)
}
btnStart.addEventListener('click', startTimer);
Html elements part:
<div class="main-container">
<input type="text" class="input" placeholder="MM:SS">
<div class="buttons-container">
Start
<button class="start">START</button>
Stop
Reset
</div>
</div>
You new edit to the question answered the question.
You're using VSCode LiveShare. When you save, it doesn't actually reload the page, it just loads the changes.
Since you're recursively calling startTimer(); (it's calling itself inside a setTimeout), it will never stop since it's not a full reload.
The easiest way to fix this is to reload your page manually (Ctrl+r or Command+r)
The harder way you could solve this is to store timer as a global variable, and on load, if timer exists, run clearInterval(timer)

Current slide number of total in Vue Slick Carousel

I am trying to make current number and total number of slides using vue-slick-carousel.
This is what I tried so far.
<VueSlickCarousel ref="carousel">
<div>1 <button tabindex="-1">11</button></div>
<div>2 <button tabindex="-1">22</button></div>
<div>3 <button tabindex="-1">33</button></div>
<div>4<button tabindex="-1">44</button></div>
</VueSlickCarousel>
methods: {
customPaging: function (slider, i) {
var slideNumber = i + 1,
totalSlides = slider.slideCount;
return (
'<a class="custom-dot" role="button" title="' + slideNumber + ' of ' + totalSlides + '"><span class="string">' + slideNumber + '</span></a>'
);
},
},
But this is not working.
And this is vue-slick-carousel API url below.
https://github.com/gs-shop/vue-slick-carousel/blob/master/docs/API.md#methods
What do i need to fixed the code to show a current slide number and total slide.
ex) "3/10"
I had the same problem recently.
This probably comes late, but to whom it may still concern:
If you want to display current page numbers instead of the default dots, there is an example at the bottom of this VueSlickCarousel documentation page and you should be good.
If you want to display the current page number only once anywhere on your page, I found a solution that worked for me:
this.$refs solution did not work for me, but this was likely due to v-if that I was using to render the <VueSlickCarousel>.
v-if and this.$refs don't like each other very much - see also Vue.js refs are undefined, even though this.$refs shows they're there.
Eventually I tried looking at the events that the children emitted in Vue Devtools and I found this afterChange event.
The afterChange event is fired each time you move your carousel to the next page (regardless of whether you drag-slide or click the arrow) and contains a very useful param - the current page index. In my case, this param starts at 0 and for each change it is incremented or decremented by 3 - that is because my carrousel settings are set to slidesToScroll : 3.
So my solution was to:
Add event listener like this:
<VueSlickCarousel #afterChange="afterPageChange">
Create the sliderPageIndex in your data with the initial value 0.
data() {
return {
sliderPageIndex: 0;
}
}
Create the afterPageChange in methods: {}.
methods: {
afterPageChange(page) {
this.sliderPageIndex = page;
}
}
Create the currentPage in computed: {} with some additional logic to compensate for the abovementioned slidesToScroll setting and for the sliderPageIndex starting at 0, like this:
computed: {
currentPage() {
// always display 1 if page index is 0
if (this.sliderPageIndex == 0) {
return 1;
} else {
// compensate for slidesToScroll settings and compensate the shift by 1
return this.sliderPageIndex / this.carouselSettings.slidesToScroll + 1;
}
},
}
Now you should have access to the currentPage computed property and can use it anywhere in your <template>.
When it comes to the totalPages, I compute it from the length of the picture array that I send to the carousel instead of taking it from the carousel directly. Here, I also compensate for carouselSettings - if this requires further explanation, let me know.
You can read more about the VueSlickCarousel events here.
Hope this will be of use to someone! :)
Cheers and have a nice day.

VueJS how to double doubleclick

I have a table with columns of different widths. I use sticky headers for which I have to calculate the column widths.
Now I wrote a function to increase the column width by double clicking the header. This works for the first double click. But if I click on it 4 or 6 times nothing happens after the first double click.
How can I reset the event so that after 2 more clicks the event is triggered again?
When I move the mouse I can do several double clicks one after the other. But that is not the goal.
Here is the code snippet:
<th
v-for="c in data.columns"
v-if="visiblecolumns.includes(c)"
v-on:dblclick="COLUMN_DEFINITION[c]+=50"
:style="{ 'min-width': COLUMN_DEFINITION[c] + 'px', 'max-width': COLUMN_DEFINITION[c] + 'px' }">
{{ c }}
</th>
<th
v-for="c in data.columns"
v-if="visiblecolumns.includes(c)"
#click="changeColumnDefinition"
:style="{ 'min-width': COLUMN_DEFINITION[c] + 'px', 'max-width': COLUMN_DEFINITION[c] + 'px' }">
{{ c }}
</th>
From: vue.js: how to handle click and dblclick events on same element, and as suggested by #JBDouble05
new Vue({
el: '#app',
data: {
counter: 0, // count the clicks
timer: null // Needs to be specified here so it can be accessed on both clicks
},
methods: {
changeColumnDefinition: function(event){
var self = this
this.counter++
if(this.counter == 1) {
this.timer = setTimeout(function() {
// DO NOTHING BUT RESET IN CASE THERES JUST ONE CLICK
self.counter = 0
}, 500); // increase delay as you like
}else{
clearTimeout(this.timer);
// COLUMN_DEFINITION[c]+=50
self.counter = 0;
}
}
}
});
NOTE This goes beyond the question, but:
I would personally wrap this up in a component, since you probably will have more than one header. If you need to call an outside function just use:
this.$emit('someEvent', someValue);
To emit an event and then access it in your component as
<my-awesome-component #someEvent="someFunction"></my-awesome-component>
What you should do is make a modulo variable, and attach an incrementational statement to your v-on:dblclick attribute, that adds one to (increments) the value of a variable, and then, add an event listener in your JavaScript file, and when this happens, perform a modulus operation upon that variable: if it's divisible by two (counter % 2 == 0), then the user has double-clicked twice. If it's not divisible by two (counter % 2 != 0) then they've clicked on it an odd number of times, and you can re-engage the event that occurred when they first double-clicked on it. That was a mouthful, but hopefully you got it, and just ask if you need simplification or further explanation.

Angular ng-repeat, reordering animation slides

I have a carousel slider in angular, I have ng-repeat with orderBy:'id' and when i click next slide button, id change it.
Look at my JSFiddle here
I have div with ng-repeat:
<div class="slide" ng-repeat="slide in slides | orderBy:'id*1'">
<p>
{{ slide.value.name }}
</p>
</div>
And I have function to sort new item list:
$scope.nextSlide = () => {
let items = $scope.slides
let countItems = items.length
for (let i = 0; i < countItems; i++) {
let z = items[i].id % countItems;
items[i].id = z + (countItems - 1);
}
}
And my problem:
First occurs animate, then scope new ordering item and blink to new slide. Any ideas? How can I animated reordering in ng-repeat?
Why don't you reorder first, so that the first slides are in the 'normal' order and when you click next, the 'reordered' slides show up...
I just don\t understand why you would reorder on "next()"
I think you are tackling the problem the wrong way, about your animation.
Let's say you have 2 items always visible.
1 | 2 | 3 | 4
When you click next, it should:
- slide on the left (animation)
- THEN, once animation is done, you do:
- reorder items (2 first at the back) AND - at the same time - recenter the list.
I think in your small demo, you just forget to recenter the list.
I guess it all depends on the way you are doing your animation as well.

Custom slider with automatic timed animation and also controls

I am trying to create a news slider that consists of a big slide area (picture and heading) and a second area to the left which contains a simple list of all the slides.
I've managed to get the slider to work so that you can click on one of the list items and this then changes the slide.
However, I'd also like the slider to animate by default through all the slides. I'd like clicking on a list item to override the animation and make the animation loop go to the point in the loop at which the current slide is at. So if the user clicks slide 2, the next slide to be animated to will be slide 3. I'd also like hovering over a slide to pause the animation.
Any ideas how I can achieve the animation/hover part? I am new to jQuery so pretty confused.
This is what I've come up with so far:
var $newsitem = jQuery('.featured-news');
var $newsitem1 = jQuery('.featured-news.item-1');
var $newsitem2 = jQuery('.featured-news.item-2');
var $newsitem3 = jQuery('.featured-news.item-3');
var $newslistitem1 = jQuery( '.newslist.item-1' );
var $newslistitem2 = jQuery( '.newslist.item-2' );
var $newslistitem3 = jQuery( '.newslist.item-3' );
// click actions
$newslistitem1.click(function () {
$newsitem.hide();
$newsitem1.fadeIn();
});
$newslistitem2.click(function () {
$newsitem.hide();
$newsitem2.fadeIn();
});
$newslistitem3.click(function () {
$newsitem.hide();
$newsitem3.fadeIn();
});
// timed actions
animate();
function animate() {
$newsitem1.delay(4000).hide();
$newsitem2.delay(4000).fadeIn();
$newsitem2.delay(4000).hide();
$newsitem3.delay(4000).fadeIn();
}
HTML:
<ul>
<li class="newslist item-1">
News item 1
</li>
<li class="newslist item-2">
News item 2
</li>
<li class="newslist item-3">
News item 3
</li>
</ul>
<ul>
<li class="featured-news item-1">
<img src="http://placehold.it/350x150">
<br>News Story 1
</li>
<li class="featured-news item-2" style="display: none">
<img src="http://placehold.it/350x150">
<br>News Story 2
</li>
<li class="featured-news item-3" style="display: none">
<img src="http://placehold.it/350x150">
<br>News Story 3
</li>
</ul>
And here's a fiddle:
http://jsfiddle.net/HdDG6/
here is how I modified your code :
First, setup global variables :
var $newsitem = $('.featured-news');
// global variable of the current slide
var current = 0;
// global variable interval, which will call "nextSlide" func every 3s
var interval = setInterval(nextSlide, 3000);
I updated your slide list click function so it become general. You won't need to setup every slide click event now :
// attach event to every list item
$('.newslist').click(function () {
// clear the interval
clearInterval(interval);
// set it back to reset the timer
interval = setInterval(nextSlide,3000);
// set current slide var to .newslist item index (0, 1, 2,...)
current = $(this).index();
// hide every shown item
$newsitem.hide();
// show item which index = current slide index
$newsitem.eq(current).fadeIn();
});
Then I created the nextSlide function which will increment current before hiding every slides and showing the current one as $('.newslist').click function
function nextSlide () {
// if current slide is the last one, go back to the first, else increment
if (current == $newsitem.length - 1) {
current = 0;
} else {
current++;
}
// hide every slides and show the good one
$newsitem.hide();
$newsitem.eq(current).fadeIn();
}
Then I finally set the hover event, which simply clear the timer when mouse enter .featured-news and set it back on mouse leave :
$('.featured-news').hover(function(ev){
clearInterval(interval);
}, function(ev){
interval = setInterval(nextSlide,3000);
});
Here is a working fiddle : DEMO
This way you can add as many slides as you want without changing the code. You can also bind nextSlide function to any button or control (like arrow keys or a "next slide" button).
Hope I helped you :)

Categories

Resources