How to stop the video if the slide has changed? - vue.js

I need to stop the video when the slide is changed. The current code reacts to changing the variable, but does not stop the video. I use Clappr ^0.3.3, Vue-cli ^3.5.0 and Swiper ^4.5.0.
I change the boolean value to use it for the trigger in the player:
data: () => ({
slider_is_move: false,
}),
After request:
.then(() => {
// init slider
new Swiper('.content__slider', {
// Note: I removed extra options
on: {
slideChange: function () {
this.slider_is_move = true; // if slide is change
setTimeout(() => {
this.slider_is_move = false; // set the previous value
}, 1500);
}
}
});
// init clappr (video player)
if ( document.querySelector('.content-video') ) {
for (let i = 0; i < this.project_videos.length; i++) {
new Clappr.Player({
source: '/storage/' + this.project_videos[i],
parentId: '#container_' + (this.project_images.length + i),
mute: true,
width: document.querySelector('.content-item').offsetWidth,
height: document.querySelector('.content-item').offsetHeight,
events: {
onPlay: () => {
setInterval(() => {
if (this.slider_is_move === true) {
this.pause();
}
}, 1000);
}
}
});
}
}
});
If I add a console.log(), the code will work as it should, but it will not stop the video.
onPlay: () => {
setInterval(() => {
if (this.slider_is_move === true) {
this.pause();
}
}, 1000);
}

To make the video stop when you change the slide, you need to add a few lines in the code:
add name to object
let player_video = new Clappr.Player...
and pause it
player_video.pause();

You should watch the data attribute slider_is_move, and react to any changes in the state.
watch: {
slider_is_move: {
handler(nowMoving) {
if (nowMoving) {
this.pause();
}
},
}
}

Related

I would like to change page when the user scrolls down

methods: {
handleScroll () {
window.onscroll = () => {
if (window.scrollY > 0) {
alert('toto');
}
}
}
},
created () {
window.addEventListener('scroll', this.handleScroll);
},
destroyed () {
window.removeEventListener('scroll', this.handleScroll);
},
This code does not work.
It is also triggered when the page loads.
Besides, I would like this code to be active only on the homepage.
Thanks for your help.
methods: {
handleScroll () {
window.onscroll = () => {
if (window.scrollY > 5 && this.$route.name ==="Accueil" ) {
this.$router.push({name:'Offres'})
}
}
}
},
With this code, it's ok

Update image src on the fly with VueJS

I'm a new VueJS user, currently struggling with updating image src on the fly. This is what I've got:
Template:
<div v-for="place in places">
<img
v-bind:src="isPlacePrivate(place.data.place_is_private)"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
>
</div>
<script>
export default {
data: function () {
return {
places: null,
}
},
mounted () {
this.username = this.$route.params.username;
axios.get('/api/' + this.username + '/places')
.then(response => {
this.places = response.data.data;
})
.catch(error => {
// show error
});
},
methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
var src = '/icons/padlock-color.png'
} else {
var src = '/icons/padlock.png'
}
return src;
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
let newValue = response.data.data.private;
this.isPlacePrivate(newValue);
})
.catch(error => {
// show error
});
},
},
}
</script>
On a page load -> if a particular place is private it will show colored padlock icon or uncolored padlock if a place is public!
A user will be able to press on the padlock icon and change the value from public->private or private->public.
Everything is working fine but the padlock image is not updating on the fly when a user is clicking on it, I need to refresh a page to see changes! How to make it work?
I would suggest using a computed property so that it is reactive
Also according to your updates you are looping through an array of places so when you get your response from your axios call instead of just updating the icon I would try replacing the object in the array so I created the method called updatePlace() and I pass in the response object.
And change your places in the v-for to a computed property as well so that it is also reactive
Template:
<div v-for="place in placesArray" :key="index" v-if="places">
<img
v-bind:src="imgSrc"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
v-if="imgSrc"
>
</div>
Script:
<script>
export default {
data() {
return {
src: '',
places: null
}
},
computed: {
imgSrc() {
return this.src
},
placesArray() {
return this.places
}
},
Methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
this.src = '/icons/padlock-color.png'
} else {
this.src = '/icons/padlock.png'
}
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
console.log(response);
let newValue = response.data.data;
this.updatePlace(newValue);
})
.catch(error => {
console.log(error);
});
},
},
updatePlace(newPlace) {
const index = this.places.findIndex(place => place.id === newPlace.id)
this.places.splice(index, 1, place)
},
created() {
this.username = this.$route.params.username;
axios.get('/api/' + this.username + '/places')
.then(response => {
this.places = response.data.data;
})
.catch(error => {
// show error
});
}
}
</script>
Also make sure to move your mounted method to a created() method so that it is called before anything else is trying to render.
Apparently the problem is that you are calling the function and printing its return on the <img v-bind:src>, the isPlacePrivate function returns a value, so when you use this function within the setPlaceAsPrivate it returns the value only in scope of setPlaceAsPrivate.
The isPlacePrivate function does not modify any data value of the component, so the image always remains the same. You just need to set a data and manipulate its value in the isPlacePrivate function.
Template
<img
v-bind:src="bindSrc"
v-on:click="setPlaceAsPrivate(place.data.place_is_private, place.data.place_id)"
>
Script
<script>
export default {
data() {
return {
bindSrc: '/icons/padlock-color.png', // default img src value
... // your other values
}
},
Methods: {
isPlacePrivate: function (value) {
// If Place is private
if (value == 1) {
this.bindSrc = '/icons/padlock-color.png'
} else {
this.bindSrc = '/icons/padlock.png'
}
},
setPlaceAsPrivate: function (value, placeId) {
let data = {
isPrivate: value
};
axios.put('/api/' + this.username + '/places/' + placeId + '/edit', data)
.then(response => {
console.log(response);
let newValue = response.data.data.private;
this.isPlacePrivate(newValue);
})
.catch(error => {
console.log(error);
});
},
}
}
</script>

Vue.js updating text in a modal

I have a modal and I am trying to dynamically update the text.
in my data
return {
count: {
value: 5
},
}
then I have a method
bulkUserImport: function() {
this.isLoading = true;
let _this = this;
axios.post('bulkUpdate', {'csv': this.importData})
.then((r) => console.log(r))
.then(() => this.isLoading = false)
.then(function() {
_this.$modal.show('dialog', {
title: 'Adding your new Clients',
text: `Jobscan is now provisioning your accounts, page will refresh in ${_this.count.value} seconds.`,
buttons: [
{
default: true,
handler: () => _this.$emit('close'),
}
]
});
_this.test()
})
.then(() => this.reloadClients());
},
Then the test method
test: function(){
if(this.count.value > 0){
this.count.value = this.count.value - 1;
console.log(this.count.value);
let temp = this;
setTimeout(function(count){
temp.test();
}, 1000);
}
},
In the text in the modal I have a variable _this.count.value that prints out 5. Then I have a call to _this.test() to update the variable.
In test(). I console.log the results and the number does go down
However, it is not updating the _this.count.value in the text. What am I doing wrong?
Here is the modal

How to use vuex with Konva for onDragEnd option

I am using konva with vuex together.
This is a code at '~.vue' for defining image.
There are two options onDragEnd and onTransform in "const yo".
'this.msg' and 'this.msg2' for the two options is defined in methods.
Thus, I can use the two options on realtime.
/gallery.vue
.
.
created() {
const image = new window.Image();
image.src = this.imageUpload.url;
image.onload = () => {
const yo = {
image: image,
name: "yoyo",
draggable: true,
scaleX: this.imageUpload.positions.scaleX,
scaleY: this.imageUpload.positions.scaleY,
x: this.imageUpload.positions._lastPosX,
y: this.imageUpload.positions._lastPosY,
onDragEnd: this.msg,
onTransform: this.msg2
};
this.images.push(yo);
};
},
methods: {
msg(e) {
this.savePositions(e.target.attrs);
},
msg2(e) {
this.savePositions(e.currentTarget.attrs);
},
But I want to move the code inside of 'created()' into 'vuex store' to control by one file.
Therefore, I make that in vuex store again like below.
And when I call this actions into 'gallery.vue', everything works well except the two options function as 'this.msg' and 'this.msg2'.
I guessed the problem would happen from 'e' argument. And I edited with various methods.
But that functions doesn;t work saying this.msg and this.msg2 is not function.
How can I call this function correctly?
Thank you so much for your reading.
/store.js
.
.
const actions = {
bringImage({ commit }) {
axios
.get(`http://localhost:4000/work`)
.then(payload => {
commit('pushWorks', payload);
})
.then(() => {
const image = new window.Image();
image.src = state.url;
image.onload = () => {
// set image only when it is loaded
const yo = {
image: image,
name: state.title,
draggable: true,
scaleX: state.positions.scaleX,
scaleY: state.positions.scaleY,
x: state.positions._lastPosX,
y: state.positions._lastPosY,
onDragEnd: this.msg,
onTransform: this.msg2
};
state.images.push(yo);
};
});
},
msg({ commit }, e) {
commit('savePositions', e.target.attrs);
},
msg2({ commit }, e) {
commit('savePositions', e.currentTarget.attrs);
}
}
You don't have this in your actions. So try to dispatch your actions with e argument as a payload.
bringImage({
commit,
dispatch
}) {
axios
.get(`http://localhost:4000/work`)
.then(payload => {
commit('pushWorks', payload)
})
.then(() => {
const image = new window.Image()
image.src = state.url
image.onload = () => {
// set image only when it is loaded
const yo = {
image: image,
name: state.title,
draggable: true,
scaleX: state.positions.scaleX,
scaleY: state.positions.scaleY,
x: state.positions._lastPosX,
y: state.positions._lastPosY,
onDragEnd: e => dispatch('msg', e),
onTransform: e => dispatch('msg2', e),
}
state.images.push(yo)
}
})
}

Relay Moder - Pagination

I am already working on Pagination.
I used PaginationContainer for that. It work’s but no way what I am looking for.
I got button next which call props.relay.loadMore(2) function. So when I click on this button it will call query and add me 2 more items to list. It works like load more. But I would like instead of add these two new items to list, replace the old item with new.
I try to use this getFragmentVariables for modifying variables for reading from the store but it’s not working.
Have somebody Idea or implemented something similar before?
class QueuesBookingsList extends Component {
props: Props;
handleLoadMore = () => {
const { hasMore, isLoading, loadMore } = this.props.relay;
console.log('hasMore', hasMore());
if (!hasMore() || isLoading()) {
return;
}
this.setState({ isLoading });
loadMore(1, () => {
this.setState({ isLoading: false });
});
};
getItems = () => {
const edges = idx(this.props, _ => _.data.queuesBookings.edges) || [];
return edges.map(edge => edge && edge.node);
};
getItemUrl = ({ bid }: { bid: number }) => getDetailUrlWithId(BOOKING, bid);
render() {
return (
<div>
<button onClick={this.handleLoadMore}>TEST</button>
<GenericList
displayValue={'bid'}
items={this.getItems()}
itemUrl={this.getItemUrl}
emptyText="No matching booking found"
/>
</div>
);
}
}
export default createPaginationContainer(
QueuesBookingsList,
{
data: graphql`
fragment QueuesBookingsList_data on RootQuery {
queuesBookings(first: $count, after: $after, queueId: $queueId)
#connection(
key: "QueuesBookingsList_queuesBookings"
filters: ["queueId"]
) {
edges {
cursor
node {
id
bid
url
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
`,
},
{
direction: 'forward',
query: graphql`
query QueuesBookingsListQuery(
$count: Int!
$after: String
$queueId: ID
) {
...QueuesBookingsList_data
}
`,
getConnectionFromProps(props) {
return props.data && props.data.queuesBookings;
},
getFragmentVariables(prevVars, totalCount) {
console.log({ prevVars });
return {
...prevVars,
count: totalCount,
};
},
getVariables(props, variables, fragmentVariables) {
return {
count: variables.count,
after: variables.cursor,
queueId: fragmentVariables.queueId,
};
},
},
);
As I figure out, there are two solutions, use refechConnection method for Pagination Container or use Refech Container.