Having value loop from 100 to 0 - Vuejs - javascript

I'm trying to have my power value go from 100 to 0 and back from 0 to 100. This will be for a power meter where the user will hit a button to stop it at a random value.
Just need help getting the loop working properly
export default {
data() {
return {
power: 100,
};
},
}
watch:{
power: {
handler(value) {
if (value == 100 || value > 0) {
setTimeout(() => {
this.power--;
}, 100);
} if (value == 0) {
setTimeout(() => {
this.power++;
}, 100);
}
},
immediate: true
},
}

Maybe you could find other solutions also, but this is what comes in my mind:
<template>
<section v-if="!showPart">
<!-- This part is shown when program is cycling looping numbers -->
<div v-if="power1">
{{power}}
</div>
<div v-else>
{{powerReverse}}
</div>
</section>
<div v-else>
<!-- This part is shown when user clicks to select a number -->
{{showValue}}
</div>
<button #click="stopFunc">{{textBtn}}</button>
</template>
<script>
export default {
name: "powerCompo",
data() {
return {
speed: 100, // speed of loop
power: 99, // start point of loop
power1: true, // for change view in increase and decrease states
powerReverse: 0, // for increasing loop after reach to "0"
showValue: "nothing selected", // showing the selected value
decrease: null, // for clearing "timeout" in decrease mode
increase: null, // for clearing "timeout" in increase mode
showPart: false, // for changing view between "loop" or "stop" modes
textBtn: "click for stop" // defines the text of btn
};
},
watch:{
power: {
handler(value) {
this.decrease = setTimeout(() => {
this.power--;
}, this.speed);
if (this.power === 0) {
clearTimeout(this.decrease);
console.log("decrease");
this.power1 = false;
this.powerReverse = 0;
this.powerReverse++;
}
},
immediate: true
},
powerReverse(newValue) {
this.increase = setTimeout(() => {
this.powerReverse++;
}, this.speed);
if (this.powerReverse === 100) {
clearTimeout(this.increase);
console.log("increase");
this.power1 = true;
this.power = 100;
this.power--;
}
}
},
methods: {
stopFunc: function ($event) {
/* This function is called each time the user clicks on button. Then if the text of button is "click for cycling again", it calls "resetFunc()" method and if not, it stops looping and shows the selected value. */
if ($event.target.innerText === "click for cycling again") {
this.resetFunc();
} else {
if (this.power1) {
this.showValue = this.power;
if (this.showValue === 100) {
this.showValue = 99;
this.power = 99;
}
} else {
this.showValue = this.powerReverse;
}
this.showPart = true;
clearTimeout(this.increase);
clearTimeout(this.decrease);
this.textBtn = "click for cycling again"
}
},
resetFunc: function () {
clearTimeout(this.increase);
clearTimeout(this.decrease);
this.textBtn = "click for stop"
this.showPart = false;
this.power= 100;
this.power1= true;
}
}
}
</script>
With the above component you can loop between [1, 99] inclusive.

Related

is it possible to auto refresh alert without closing?

I want to refresh v-alert automatically after 1 sec without closing it so that value store in locaStorage can be reflected on v-alert after every 1 sec.
<v-alert
style="position: fixed;left: 35%;top: 7%;"
border="left"
close-text="Close Alert"
color="deep-purple accent-4"
dark
dismissible
text-align ='center'
v-model="alert"
>
Yesterday's Leads: {{this.totalAndYetToCallCounts.previousLeads}} and Today's Leads: {{this.totalAndYetToCallCounts.TodaysLeads}}.
</v-alert>
export default {
data () {
return {
totalAndYetToCallCounts: '',
alert: true
}
},
watch: {
alert (newVal) {
if (!newVal) {
setTimeout(() => {
this.alert = true
this.totalAndYetToCallCounts = JSON.parse(localStorage.getItem('getTotalAndYetToCallCount'))
}, 1000)
}
}
},
}
after writing it in created hook
async created () {
try {
setInterval(() => {
this.alert = true
this.totalAndYetToCallCounts = JSON.parse(localStorage.getItem('getTotalAndYetToCallCount'))
}, 1000)
},

clear interval on another function vue js

I'm confused how to add a set Interval variable in my vue file myTimer = setInterval(function, time).
The goal of my program is to change the number variable every 3 seconds, to access the object that I created to let it display different background images but I also have 2 buttons that can navigate through the background as well.
This is my template code
<div class="background" :style="{backgroundImage: `url(${Images[`${number}`].picture})`}">
<div class="content_container">
<div v-on:click="prev" class="prevButton"><p><</p></div>
<div class="title_container">
<div class="theTitle"><p>{{Images[`${number}`].Title}}</p></div>
</div>
<div v-on:click="next" class="nextButton"><p>></p></div>
</div>
</div>
This is my set Interval code
export default {
data: () => ({
number: 0,
myTimer
}),
mounted:function() {
this.$nextTick(() => {
this.timer();
});
},
methods:{
timer: function() {
var myTimer = setInterval(this.counter, 3000);
},
counter:function(){
if(this.number >= (this.Images.length -1)){
this.number = 0;
}
else{
this.number +=1;
}
},
next()
{
clearInterval(this.myTimer)
if(this.number >= (this.Images.length -1)){
this.number = 0;
}
else{
this.number +=1;
}
},
I want to clearInterval at the next() function how can I access the variable from another function.
your myTimer need be in this context.
export default {
data: () => ({
number: 0,
myTimer: 0, // init myTimer
}),
mounted: function () {
this.$nextTick(() => {
this.timer();
});
},
methods: {
timer: function () {
this.myTimer = setInterval(this.counter, 3000); // in this.myTimer
},
counter: function () {
if (this.number >= this.Images.length - 1) {
this.number = 0;
} else {
this.number += 1;
}
},
next() {
clearInterval(this.myTimer); // clear
if (this.number >= this.Images.length - 1) {
this.number = 0;
} else {
this.number += 1;
}
this.timer(); // start next
},
},
};

mutate vuex store state outside mutation handlers

I created a custom timer component, but I got errors about vuex store.
This component starts a timer when it's created and put into the store, then each minute it increments the time. If the person leaves the page like the timer is in the store, the time is saved and when the person comes back to the page, the timer resume by itself.
This is my component
<template>
<div>
<v-icon v-if="timer.visibility" :color="timeColor" #click="changeTimer">
{{ $icons.clock }}
</v-icon>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
required: true
},
id: {
type: Number,
default: null
},
type: {
type: String,
default: null
}
},
data() {
return {
timer: {
actif: false,
visibility: false,
timeOut: null,
dateDebut: null,
id: 0
}
}
},
computed: {
listeTimer() {
return this.$store.state.listeTimerPointage
},
timeColor() {
return this.timer.actif ? 'green' : 'red'
},
count: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
},
beforeDestroy() {
this.stopTimer()
},
created() {
let precedentTimer = null
if (this.id > 0) {
if (this.listeTimer.length > 0) {
precedentTimer = this.listeTimer.filter((f) => f.id === this.id)
}
} else {
this.timer.id = 0
}
this.startTimer(precedentTimer)
},
methods: {
// Start le timer
startTimer(precedentTimer) {
if (precedentTimer !== null) {
this.timer = precedentTimer
this.count = precedentTimer.count
} else {
this.count = 1
this.timer.dateDebut = new Date()
if (this.timer.timeOut === null) {
this.timer.actif = true
this.timer.visibility = true
this.timer.timeOut = setTimeout(() => {
this.timerBoucle()
}, 60000)
}
}
// this.listeTimer.push(this.timer)
this.$store.commit('addListeTimerPointage', this.timer)
},
// Arrete le timer
stopTimer() {
this.timer.actif = false
clearTimeout(this.timer.timeOut)
},
// Met en place la boucle toute les 1 minutes
timerBoucle() {
const now = new Date()
const diff = now - this.timer.dateDebut
this.count += Math.round(diff / 60000)
this.timer.dateDebut = new Date()
this.timer.timeOut = setTimeout(() => {
this.timerBoucle()
}, 60000)
},
// Modifie l'état du timer
changeTimer() {
this.timer.actif = !this.timer.actif
if (!this.timer.actif) {
clearTimeout(this.timer.timeOut)
} else {
this.timer.dateDebut = new Date()
this.timer.timeOut = setTimeout(() => {
this.timerBoucle()
}, 60000)
}
}
}
}
</script>
I indeed mutate a state, but I don't think I change the state directly
And this is the store:
addListeTimerPointage(state, data) {
state.listeTimerPointage.push(data)
},
deleteTimer(state, data) {
const newArray = state.listeTimerPointage.filter(
(item) => item.id !== data
)
state.listeTimerPointage = newArray
}
Thanks for your help

Stop typing text when element is focused

I have a component with typing text, this effect add/remove word and write new word:
<template>
<span
id="textCode"
contenteditable="true"
spellcheck="false"
style="width: 800px"
v-text="displayText.join('')"
/>
</template>
<script>
export default {
props: {
speed: {
type: Number,
default: 100
},
deleteSpeed: {
type: Number,
default: 30
},
nextWordInterval: {
type: Number,
default: 1200
},
words: {
type: Array,
default: null
}
},
data () {
return {
displayText: [],
currentWord: '',
wordIdx: 0,
timeoutSpeed: null,
isWaitingNextWord: false
}
},
mounted () {
this.start()
},
methods: {
start () {
if (this.words && this.words.length > 0 && !document.querySelector('#textCode').contains(document.activeElement)) {
this.currentWord = this.words[this.wordIdx].split('')
this.timeoutSpeed = this.speed
this.animate = setTimeout(this.type, this.timeoutSpeed)
}
},
type () {
if (this.currentWord.length > 0) {
this.displayText.push(this.currentWord.shift())
// if done typing, wait for a while
} else if (!this.isWaitingNextWord && this.currentWord.length === 0 && this.displayText.length === this.words[this.wordIdx].length) {
this.timeoutSpeed = this.nextWordInterval
this.isWaitingNextWord = true
// if done typing, then delete
} else if (this.currentWord.length === 0 && this.displayText.length > 0) {
this.timeoutSpeed = this.deleteSpeed
this.displayText.pop()
// if done typing & deleting
} else if (this.currentWord.length === 0 && this.displayText.length === 0) {
// change words
if (this.wordIdx < (this.words.length - 1)) {
this.wordIdx++
} else {
// reset
this.wordIdx = 0
}
this.timeoutSpeed = this.speed
this.isWaitingNextWord = false
this.currentWord = this.words[this.wordIdx].split('')
this.displayText.push(this.currentWord.shift())
}
setTimeout(this.type, this.timeoutSpeed)
}
}
}
</script>
I need stop typing text, when element span is focused. How I can do it? I try do in method start:
!document.querySelector('#textCode').contains(document.activeElement)
But is not work.. I checked. Maybe is there another method to solve this problem? Please help me resolve this issue. Thanks.

Noticeable lag between loading of video elements in a stack

I am working on a small scale app that displays videos in multiple ways using a video-player component.
Currently I am implementing a stack-list, which is a container that holds video-stack components, and each stack contains one or more video-player components.
While the correct videos are loaded from the DOM, there is a noticeable multi-second lag (in terms of keyboard response) which seems to be related to the ending of the currently played video and the fetching of the next video in the stack.
How can I get rid of this lag? Videos are able to be toggled/selected via mouse hovers or WASD keyboard commands (A: previous, D: next), and the lag can cause a delay in keyboard inputs being registered.
video-stack.hbs
{{video-player highlightedStyle=(string-append stackStyle borderStyle)
looping=(is-single-video videos) videoPos=selectedVidPos
isMuted=(if (video-selected key selectedStackIndex) isMuted true)
url=(if curVideo.teaser.isUrl curVideo.teaser.fileIdentifier
(make-local-url modelIdentifier curVideo.teaser.fileIdentifier))
onClickCallback=(action 'stackClicked')
onHoverCallback=(action 'stackHovered')
onEndedCallback=(action 'getNextVid')}}
video-stack.js
import Ember from 'ember';
export default Ember.Component.extend({
selectedVidPos: 0,
selectedStackIndex: 0,
stackStyle: '',
playerSize: '',
isMuted: true,
init() {
this._super(...arguments);
switch(this.get('videos').length){
case 1:
break;
case 2:
this.set('stackStyle', 'vid-shadows--2');
break;
case 3:
this.set('stackStyle', 'vid-shadows--3');
break;
case 4:
this.set('stackStyle', 'vid-shadows--4');
break;
default:
this.set('stackStyle', 'vid-shadows--4');
break;
}
},
curVideo: Ember.computed('videos', 'selectedVidPos', function () {
return this.get('videos')[this.get('selectedVidPos')];
}),
actions: {
stackClicked() {
this.get('onClickCallback') (this.get('videos'), this.get('selectedVidPos'));
},
getNextVid() {
let arrayLength = this.get('videos').length;
//check if there is only 1 video in the stack
if (arrayLength === 1) {
return;
}
let curArrayPos = parseInt(this.get('selectedVidPos'));
this.set('selectedVidPos', (curArrayPos + 1) % arrayLength);
},
stackHovered() {
this.get('onHoverCallback') (this.get('videos'), this.get('selectedStackIndex'));
}
}
});
video-player.hbs
<video oncanplay={{action 'play'}} looping=true
onended={{action 'ended'}} src={{url}}
class="video-player__video {{highlightedStyle}} {{if playing '' 'video-
player__darken'}}" muted={{muted}} />
video-player.js
import Ember from 'ember';
export default Ember.Component.extend({
url: null,
looping: false,
playing: true,
muted: true,
highlightedStyle: '',
click(event) {
this.get('onClickCallback') (this.get('videoPos'));
event.stopPropagation();
},
mouseEnter() {
this.get('onHoverCallback') (this.get('videoPos'));
},
willClearRender() {
this.set('playingObserver', null);
this.set('urlObserver', null);
},
playingObserver: Ember.observer('playing', function() {
if (this) {
var p = this.get("playing");
var videoElement = this.$().find("video").get(0);
if (videoElement) {
if (p) {
videoElement.play();
}
else {
videoElement.pause();
}
}
else {
console.log("No video element found!");
}
}
}),
urlObserver: Ember.observer('url', function() {
if (this) {
var videoElement = this.$().find("video").get(0);
if (videoElement) {
videoElement.load();
}
else {
console.log("No video element found");
}
}
}),
actions: {
ended() {
if (this.get('looping')) {
this.$().find("video").get(0).play();
console.log("video-player ended");
}
else {
console.log(this.get('videoPos'));
this.get('onEndedCallback') (this.get('videoPos'));
}
},
play() {
if (this.get('playing')) {
this.$().find("video").get(0).play();
}
}
}
});
I can post more code if it would help shed light on the culprit, thanks!
I found the culprit of the lag. The issue was in the parent container, content-area.js, which had a resetTimeout action that was being called incorrectly, which caused the focus to cycle needlessly, resulting in the lag.
Also implemented a switch off in terms of rendering videos to ensure smooth loading from one video to the next in video-stack.js, there are now 2 video objects, A & B, which are fetched and preloaded from the blob object, showing one while the other is hidden. Once the displayed video ends, they swap out, and the next video in the stack is loaded.
video-stack.js
export default Ember.Component.extend({
selectedVidAPos: 0,
selectedVidBPos: 0,
selectedStackIndex: 0,
stackStyle: '',
playerSize: '',
isMuted: true,
showVidA: true,
init() {
...
}
},
videoA: Ember.computed('videos', 'selectedVidAPos', function () {
return this.get('videos')[this.get('selectedVidAPos')];
}),
videoB: Ember.computed('videos', 'selectedVidBPos', function () {
return this.get('videos')[this.get('selectedVidBPos')];
}),
actions: {
stackClicked() {
this.get('onClickCallback') (this.get('videos'), (this.get('showVidA') ? this.get('selectedVidAPos') : this.get('selectedVidBPos')));
},
getNextVideoA() {
let arrayLength = this.get('videos').length;
if (arrayLength === 1) {
return;
}
let curArrayPos = parseInt(this.get('selectedVidAPos'));
this.set('selectedVidAPos', (curArrayPos + 2) % arrayLength);
this.set('showVidA', false);
},
getNextVideoB(){
let arrayLength = this.get('videos').length;
if (arrayLength === 1) {
return;
}
let curArrayPos = parseInt(this.get('selectedVidBPos'));
this.set('selectedVidBPos', (curArrayPos + 2) % arrayLength);
this.set('showVidA', true);
},
stackHovered() {
this.get('onHoverCallback') (this.get('videos'), this.get('selectedStackIndex'));
}
}
});
content-area.js
import Ember from 'ember';
import KeyboardControls from '../mixins/keyboard-controls';
export default Ember.Component.extend(KeyboardControls, {
displayVideoSelect: false,
displayVideoSelectTimeout: null,
displayVideo: false,
video: null,
videoPlaying: false,
keyboard: null,
backgroundVideoPos: 0,
backgroundVideoUrl: null,
backgroundVideoKeys: null,
selectionVideos: [],
stackListData: null,
showVideoSelect: function() {
this.set('displayVideoSelect', true);
this.send('resetTimeout');
},
hideVideoSelect: function() {
this.set('displayVideoSelect', false);
clearTimeout(this.get('displayVideoSelectTimeout'));
},
pauseVideo: function() {
this.set('videoPlaying', !this.get('videoPlaying'));
this.set('displayVideoSelect', !this.get('videoPlaying'));
this.set('focus', this.get('videoPlaying'));
},
select: function() {
this.set('videoPlaying', false);
this.set('focus', false);
this.showVideoSelect();
this.send('resetTimeout');
},
cancel: function() {
this.pauseVideo();
this.send('resetTimeout');
},
goNext: function() {
this.pauseVideo();
this.send('resetTimeout');
},
goPrevious: function() {
this.pauseVideo();
this.send('resetTimeout');
},
updateFocus: function(param) {
if (param) {
this.$().attr('tabindex', 2);
this.$().focus();
}//if
else {
this.$().attr('tabindex', -2);
this.$().blur();
}//else
},
init() {
...
},
click() {
this.set('focus', false);
this.showVideoSelect();
},
actions: {
videoSelected(sender, videoData) {
...
},
videoEnded() {
this.set('focus', false);
this.showVideoSelect();
this.set('displayVideo', false);
},
cycleBackground() {
...
},
cancelPressed() {
this.cancel();
},
resetTimeout() {
let component = this;
clearTimeout(this.get('displayVideoSelectTimeout'));
let timeout = setTimeout(() => {
component.hideVideoSelect();
//This set command was responsible for the lag
component.set('focus', true);
}, this.get('data.config.ui.idle') * 1000);
this.set('displayVideoSelectTimeout', timeout);
}
}
});

Categories