added 'Copy Link' and 'Copy Deezer Link' options to context menu
This commit is contained in:
parent
e3a016e778
commit
1c6141ca5a
File diff suppressed because one or more lines are too long
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user