added 'Copy Link' and 'Copy Deezer Link' options to context menu

This commit is contained in:
Roberto Tonino 2020-08-03 22:12:53 +02:00
parent e3a016e778
commit 1c6141ca5a
2 changed files with 116 additions and 45 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,12 @@
<template> <template>
<div class="context-menu" v-show="contextMenuOpen" ref="contextMenu"> <div class="context-menu" v-show="menuOpen" ref="contextMenu" :style="{ top: yPos, left: xPos }">
<button class="menu-option" v-for="option of options" :key="option.label" @click.prevent="option.action"> <button
class="menu-option"
v-for="option of options"
:key="option.label"
v-show="option.show"
@click.prevent="option.action"
>
<span class="menu-option__text">{{ option.label }}</span> <span class="menu-option__text">{{ option.label }}</span>
</button> </button>
</div> </div>
@ -9,16 +15,14 @@
<script> <script>
export default { export default {
data: () => ({ data: () => ({
contextMenuOpen: false menuOpen: false,
}), xPos: 0,
// Using computed properties because this data is not meant to be reactive yPos: 0,
// In this way it's cached currentHref: '',
// https://vuejs.org/v2/guide/computed.html options: [
computed: {
options() {
return [
{ {
label: 'Cut', label: 'Cut',
show: true,
// Use arrow functions to keep the Vue instance in 'this' // Use arrow functions to keep the Vue instance in 'this'
// Use normal functions to keep the object instance in 'this' // Use normal functions to keep the object instance in 'this'
action: () => { action: () => {
@ -27,12 +31,24 @@ export default {
}, },
{ {
label: 'Copy', label: 'Copy',
show: true,
action: () => { action: () => {
document.execCommand('Copy') document.execCommand('Copy')
} }
}, },
{
label: 'Copy Link',
show: false,
action: null
},
{
label: 'Copy Deezer Link',
show: false,
action: null
},
{ {
label: 'Paste', label: 'Paste',
show: true,
action: () => { action: () => {
navigator.clipboard.readText().then(text => { navigator.clipboard.readText().then(text => {
document.execCommand('insertText', undefined, text) document.execCommand('insertText', undefined, text)
@ -40,23 +56,76 @@ export default {
} }
} }
] ]
} }),
},
mounted() { mounted() {
document.body.addEventListener('contextmenu', contextMenuEvent => { document.body.addEventListener('contextmenu', this.showMenu)
contextMenuEvent.preventDefault()
let { pageX, pageY } = contextMenuEvent
this.$refs.contextMenu.style.top = `${pageY}px`
this.$refs.contextMenu.style.left = `${pageX}px`
this.contextMenuOpen = true
})
document.body.addEventListener('click', () => { document.body.addEventListener('click', () => {
// Finish all operations before closing (may be not necessary)
this.$nextTick().then(() => { this.$nextTick().then(() => {
this.contextMenuOpen = false this.menuOpen = false
this.options[2].show = false
this.options[3].show = false
}) })
}) })
},
methods: {
showMenu(contextMenuEvent) {
contextMenuEvent.preventDefault()
const {
pageX,
pageY,
path,
path: [elementClicked]
} = contextMenuEvent
this.positionMenu(pageX, pageY)
// Show 'Copy Link' option
if (elementClicked.matches('a')) {
this.showCopyLink(elementClicked.href)
}
let link = null
for (let i = 0; i < path.length; i++) {
if (path[i] == document) break
if (path[i].matches('[data-link]')) {
link = path[i].dataset.link
break
}
}
// Show 'Copy Deezer Link' option
if (link) {
this.showCopyDeezerLink(link)
}
this.menuOpen = true
},
positionMenu(newX, newY) {
this.xPos = `${newX}px`
this.yPos = `${newY}px`
},
showCopyLink(href) {
this.options[2].show = true
this.options[2].action = () => {
navigator.clipboard.writeText(href).catch(err => {
console.error('Link copying failed', err)
})
}
},
showCopyDeezerLink(link) {
this.options[3].show = true
this.options[3].action = () => {
navigator.clipboard.writeText(link).catch(err => {
console.error('Download link copying failed', err)
})
}
}
} }
} }
</script> </script>
@ -77,8 +146,9 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
width: 100%; width: 100%;
height: 50px; height: 40px;
padding-left: 10px; padding-left: 10px;
padding-right: 10px;
color: var(--foreground); color: var(--foreground);
cursor: pointer; cursor: pointer;
@ -96,6 +166,7 @@ export default {
} }
} }
// Resetting buttons only for this component (because the style is scoped)
button { button {
color: var(--accent-text); color: var(--accent-text);
color: unset; color: unset;