have this for list:
<li
class="projects-item"
v-for="project in filteredProjects"
:key="project.id"
v-on:mouseover="displayHoverInfo($event, project)"
v-on:mouseleave="hover = false"
>
<router-link v-bind:to="'/project/' + project.slug">
and js:
displayHoverInfo(event, project) {
this.hover = true;
this.hoveredProject = project;
console.log(event);
}
on desktop works all fine, on mobile (on tap) only the v-on:mouseover/v-on:mouseleave events are being triggered.
I stole the answer here: https://forum.vuejs.org/t/how-to-disable-mouseover-on-mobile/37335
You can disable the mouseover and mouseleave on mobile. Going further you can detect if it's actually a mobile/tablet using the user agent.
<li
class="projects-item"
v-for="project in filteredProjects"
:key="project.id"
v-on:mouseover="isMobile ? null : displayHoverInfo($event, project)"
v-on:mouseleave="isMobile ? null : hover = false"
>
new Vue({
el: "#app",
data: {
isMobile: false,
hover: false
},
methods: {
mq() {
this.isMobile = window.matchMedia('(max-width: 400px)').matches;
},
displayHoverInfo($event, project) {
// your method
}
},
created () {
// get initial val
this.mq()
// listen to resize
window.addEventListener('resize', this.mq)
},
beforeDestroy() {
window.removeEventListener('resize', this.mq)
}
})
Related
I'm developing login page with connect with SSHFS drive.
And some of the functions are working but, I'm confusing with my codes. I analyze my code but I don't know why it's working, and why this is working.
My application looks like this.
It's just simple login web app with Electron. So When I click login and if the ID & and password is right, it will mount SSHFS drive and goes to system tray icon to hide. After that it should open the explorer that mounted folder.
So I thought When I click login button, and two #click with $emit functions should work like this.
<div class="form-item">
<button class="login" v-show="showConnectButton" :class="{ 'success': isConnected, 'connecting-disconnecting': isConnectingOrDisconnecting }" :disabled="isConnectingOrDisconnecting" #click="[$emit(isConnected ? 'disconnect' : 'connect', conn), $emit('open', conn.mountPoint)]">{{isConnected ? 'disconnect' : 'login'}}</button>
</div>
I use this code but it seems the code tries mount the drive early then $emit(isConnected) function so It shows the error that Cannot find 'E' Drive that I set in another code.
It's an error that 'System cannot find 'E' drive in my computer'
I tried to put mount function to another function but it doesn't work. Only the 'Hide to tray' and 'Mount Drive function' works well. So I think it should fix only a few code and it will work but I don't know where should I fix the code.
And I already searched in stackoverflow questions but it seems doesn't fit in my question.
Here's my part of my full code. Please check the code and give me some advise. Thanks.
My ConnectionItem.vue full Code
<template>
<div class="item">
<div class="form-item">
<button class="login" v-show="showConnectButton" :class="{ 'success': isConnected, 'connecting-disconnecting': isConnectingOrDisconnecting }" :disabled="isConnectingOrDisconnecting" #click="[$emit(isConnected ? 'disconnect' : 'connect', conn)]">{{isConnected ? 'disconnect' : 'login'}}</button>
</div>
</div>
</template>
<script>
import { remote } from 'electron'
import Icon from '#/components/Icon'
const window = remote.getCurrentWindow()
export default {
name: 'connection-item',
components: {
Icon
},
props: {
conn: {
type: Object,
required: true
},
mode: {
type: String,
required: false,
default: 'none'
}
},
computed: {
isConnected (conn) {
// this.isActive = !this.enable
this.$emit('open', conn.mountPoint)
window.hide()
return this.conn.status === 'connected'
},
isConnectingOrDisconnecting () {
return this.conn.status === 'connecting' || this.conn.status === 'disconnecting'
},
showConnectButton () {
// window.hide()
// openLocal(path);
// this.$emit('open', conn.mountPoint)
return this.mode === 'none' || this.isConnected || this.isConnectingOrDisconnecting
},
isEditing () {
return this.mode === 'edit' && !this.isConnected && !this.isConnectingOrDisconnecting
},
showDeleteButton () {
return this.mode === 'delete' && !this.isConnected && !this.isConnectingOrDisconnecting
},
showRunningInBackgroundNotification () {
if (!this.runningInBackgroundNotificationShowed) {
if (this.$store.state.Settings.settings.displayTrayMessageOnClose) {
this.notify('program runs in background (network connected)') // 1
this.notify('Click Quit button when you disconnect drive') // 2
this.runningInBackgroundNotificationShowed = true
}
}
}
}
}
</script>
I have this problem, that lightgallery can be opened only once. Each next click on button is unresponsive. I'm using lightgallery as component.
In my parent component I have two buttons, for opening image or video gallery
ParentComponent.vue
<template>
<div>
<button class="btn-secondary" #click="showGallery('IMAGE')">
{{ $t('showImages') }}
</button>
<button class="btn-secondary" #click="showGallery('VIDEO')">
{{ $t('playVideo') }}
</button>
<LightGallery
v-if="galleryVisible" :gallery-items="galleryItems"
:gallery-type="galleryType" :user-subscription="userSubscription">
</LightGallery>
</div>
<template>
<script>
import LightGallery from "./subComponents/LightGallery.vue";
export default {
name: "Location",
components: {
LightGallery: LightGallery,
},
data() {
return {
// image / video slide show data
locationImages: [],
locationVideo: [],
galleryItems: {},
galleryVisible: false,
galleryType: 'IMAGE',
};
},
methods: {
showGallery(type) {
this.galleryItems = {};
this.galleryVisible = true;
this.galleryType = type;
if (type === 'IMAGE') {
this.galleryItems = this.locationImages;
} else if (type === 'VIDEO') {
this.galleryItems = this.locationVideo
}
},
hideGallery() {
this.galleryItems = {};
this.galleryVisible = false;
},
};
</script>
And this is my child (lightgallery) component
<template>
<div id="lightgallery">
</div>
</template>
<script>
// Light gallery
import 'lightgallery.js'
import 'lightgallery.js/dist/css/lightgallery.css'
import 'lg-zoom.js'
import 'lg-autoplay.js'
import 'lg-fullscreen.js'
import 'lg-hash.js'
import 'lg-pager.js'
import 'lg-share.js'
import 'lg-thumbnail.js'
import 'lg-video.js'
// Light gallery
export default {
name: "LightGallery",
props: {
galleryItems: {
type: Array,
required: true
},
galleryType: {
type: String,
required: true
},
userSubscription: {
type: Object,
required: false,
default: {
active: false
}
}
},
methods: {
openGallery() {
// prepare images / video to display them in lightGallery
let dynamicElements = [];
if (this.galleryType === 'IMAGE') {
this.galleryItems.forEach(function (value) {
dynamicElements.push({
src: '/' + value.hd_path,
thumb: '/' + value.thumb_path,
});
});
}
if (this.galleryType === 'VIDEO') {
this.galleryItems.forEach(function (value) {
dynamicElements.push({
src: 'https://vimeo.com/' + value.vimeo_id,
});
});
}
let lg = document.getElementById('lightgallery');
window.lightGallery(lg, {
mode: 'lg-slide',
download: false,
thumbnail: true,
dynamic: true,
dynamicEl: dynamicElements,
autoplayFirstVideo: true,
loadVimeoThumbnail: false,
});
lg.addEventListener('onCloseAfter', function (event, index, fromTouch, fromThumb) {
lg.data('lightGallery').destroy(true);
}, false);
window.lightGallery(lg);
},
},
mounted() {
this.openGallery();
}
};
</script>
The problem!
On first "refresh" page reload if I click on button Show image or show video, gallery opens and it works well. When I close gallery I see error in developer tools (maybe complletly unrelated, with my problem)
Each next click on buttons Show image or show video does nothing. So how can I properly destroy Lightgallery so I will be able to reopen it? If you need any additional informations, please let me know and I will provide. Thank you!
Try adding this line to your showGallery method.
showGallery(type) {
this.galleryVisible = false // <<--- this line
this.galleryItems = {};
this.galleryVisible = true;
this.galleryType = type;
if (type === 'IMAGE') {
this.galleryItems = this.locationImages;
} else if (type === 'VIDEO') {
this.galleryItems = this.locationVideo
}
},
Light Gallery only seems to work once. But the above line of code will re-create the Light Gallery Component and you'll have a fresh instance of Light Gallery component (exactly what you have on a page load) each time you click on one of the buttons that would initiate the Light Gallery.
The code below actually plays sounds on each button click with vue.js.
How is it possible to detect keyboard press and play sound when DOM is ready and not when the buttons are clicked?
for example on enter play sound v-on:keyup.13="playSound('path/to/mp3')"
Vue documentation mostly explains html attributes, perhaps this is something that needs to be done in JS, i guess. I am new to Vue.js
Vue.js documentation on Event Modifiers
See the codepen.
new Vue({
el: '#app',
data: {
text: ''
},
methods: {
playSound (sound) {
if(sound) {
var audio = new Audio(sound);
audio.play();
}
}
}
});
When you press a key, the keyboard event will be fired from the active element and bubble upwards. So if you want to handle all key presses regardless of what element has focus, then you will need to register the listener manually in code on, e.g., document.
new Vue({
el: '#app',
created() {
this.onKeyDown = this.onKeyDown.bind(this);
document.addEventListener('keydown', this.onKeyDown);
},
destroyed() {
document.removeEventListener('keydown', this.onKeyDown);
},
methods: {
playSound (sound) {
if(sound) {
var audio = new Audio(sound);
audio.play();
}
},
onKeyDown(e) {
switch (e.keyCode) {
case 65: this.playSound(sound1); break; // 'a' key
case 66: this.playSound(sound2); break; // 'b' key
}
},
}
});
Codepen
I am trying to implement common chat app on Vue.js.
window.onload = function () {
new Vue({
el: '#vue-chat',
data: {
body: ''
},
methods: {
fooMethod: function () {
alert('foo');
},
barMethod: function () {
alert('bar');
}
}
})
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.3/vue.js"></script>
<div id="vue-chat">
<ul class="comments">
<li></li>
</ul>
<input type="text" v-model="body" #keyup.enter="fooMethod">
</div>
and i want to call barMethod when users press enter key and shift key at the same time.
I read docs however I could not find the way.
Thank you for reading!
With the shift key and other modifier keys you can see if they were pressed through the event object.
I'd use a single method with #keyup.enter and then decide to which method to call based on the event's shiftKey value.
new Vue({
el: '#app',
data: {
message: 'Hi',
},
methods: {
action(event) {
if (event.shiftKey) {
this.shiftKeyPressed()
} else {
this.shiftKeyNotPressed()
}
},
shiftKeyPressed() {
console.log('Shift key was pressed.')
},
shiftKeyNotPressed() {
console.log('Shift key was NOT pressed.')
},
}
})
Here's a quick demo: https://jsfiddle.net/bj75cyd3/
There is no trivial way to do what you want.
You can't reach your goal through modifiers; you have to drop the .enter modifier and deal with the keyup event, as well as the keydown event.
<input type="text" v-model="body" #keyup="keyUp" #keydown="keyDown">
There are a short answer and a long answer suggesting how to track multiple keys pressed at once in JavaScript.
Based on the answers linked above, we can build the basis of our Vue solution:
data: {
shiftPressed: false
},
methods: {
keyDown: function (event) {
if (event.keyCode === 16) {
this.shiftPressed = true
}
},
keyUp: function(event) {
if (event.keyCode === 16) {
this.shiftPressed = false
}
if (this.shiftPressed && (event.keyCode === 13)) {
this.shiftPressed = false // avoid double trigger
this.fooMethod()
}
}
}
How to create a Vue.js logic to handle all tag elements with the same class selector?
I have this simple code: http://jsfiddle.net/x2spo1qu/
var dropdown = new Vue({
el: '.dropdown',
data: {
is_open : false
},
methods: {
onClick: function (event) {
// # toggle the dropdown open/closed state
// ---
this.is_open = ! this.is_open;
},
mouseLeave: function (event) {
// # set show of dropdown to false
// ----
this.is_open = false;
}
}
});
But it only works for the first dropdown in the HTML and does not work for the second.
Please explain me how to do this.
From vuejs.org :
Vue.js uses DOM-based templating. Each Vue instance is associated with a corresponding DOM element. When a Vue instance is created, it recursively walks all child nodes of its root element while setting up the necessary data bindings. After the View is compiled, it becomes reactive to data changes.
you can achieve this using Vue component system
follow this example :
var bs3_dropdown = Vue.extend
({
props: ['name'],
replace: true,
template: '<li class="dropdown" v-class="open : is_open" v-on="mouseleave : mouseLeave"> {{ name }} <span class="caret"></span> <ul class="dropdown-menu" role="menu"> <content></content> </ul> </li>',
data: function () {
return {
is_open: false,
}
},
methods : {
onClick : function(event) {
// # toggle the dropdown open/closed state
// ---
this.is_open = ! this.is_open;
},
mouseLeave : function(event) {
// # set show of dropdown to false
// ----
this.is_open = false;
}
},
created: function () {
console.log('An instance of MyComponent has been created!')
}
});
Vue.component('bs3-dropdown', bs3_dropdown);
full : http://jsfiddle.net/msa965j5/
there is some bug beacuse of initial HTML