Replace jquery in ft-icon-button with vue functionality (#2617)

* Replace jquery in ft-icon-button with vue functionality

* Rename hide method to hideDropdown

* Fix typo in comment

Co-authored-by: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com>

* Fix menu reappearing too soon

* Fix share menu buttons not triggering

Co-authored-by: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com>
This commit is contained in:
absidue 2022-09-27 14:16:56 +02:00 committed by GitHub
parent 498ae77ade
commit c3f8a3561b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 60 deletions

View File

@ -1,5 +1,4 @@
import Vue from 'vue' import Vue from 'vue'
import $ from 'jquery'
export default Vue.extend({ export default Vue.extend({
name: 'FtIconButton', name: 'FtIconButton',
@ -56,64 +55,45 @@ export default Vue.extend({
data: function () { data: function () {
return { return {
dropdownShown: false, dropdownShown: false,
id: '' mouseDownOnIcon: false
} }
}, },
mounted: function () {
this.id = `iconButton${this._uid}`
},
methods: { methods: {
toggleDropdown: function () { // used by the share menu
const dropdownBox = $(`#${this.id}`) hideDropdown: function () {
if (this.dropdownShown) {
dropdownBox.get(0).style.display = 'none'
this.dropdownShown = false
} else {
dropdownBox.get(0).style.display = 'inline'
dropdownBox.get(0).focus()
this.dropdownShown = true
dropdownBox.focusout(() => {
const shareLinks = dropdownBox.find('.shareLinks')
if (shareLinks.length > 0) {
if (!shareLinks[0].parentNode.matches(':hover')) {
dropdownBox.get(0).style.display = 'none'
// When pressing the profile button
// It will make the menu reappear if we set `dropdownShown` immediately
setTimeout(() => {
this.dropdownShown = false
}, 100)
}
} else {
dropdownBox.get(0).style.display = 'none'
// When pressing the profile button
// It will make the menu reappear if we set `dropdownShown` immediately
setTimeout(() => {
this.dropdownShown = false
}, 100)
}
})
}
},
focusOut: function () {
const dropdownBox = $(`#${this.id}`)
dropdownBox.focusout()
dropdownBox.get(0).style.display = 'none'
this.dropdownShown = false this.dropdownShown = false
}, },
handleIconClick: function () { handleIconClick: function () {
if (this.forceDropdown || (this.dropdownOptions.length > 0)) { if (this.forceDropdown || (this.dropdownOptions.length > 0)) {
this.toggleDropdown() this.dropdownShown = !this.dropdownShown
if (this.dropdownShown) {
// wait until the dropdown is visible
// then focus it so we can hide it automatically when it loses focus
setTimeout(() => {
this.$refs.dropdown.focus()
}, 0)
}
} else { } else {
this.$emit('click') this.$emit('click')
} }
}, },
handleIconMouseDown: function () {
if (this.dropdownShown) {
this.mouseDownOnIcon = true
}
},
handleDropdownFocusOut: function () {
if (this.mouseDownOnIcon) {
this.mouseDownOnIcon = false
} else if (!this.$refs.dropdown.matches(':focus-within')) {
this.dropdownShown = false
}
},
handleDropdownClick: function ({ url, index }) { handleDropdownClick: function ({ url, index }) {
if (this.returnIndex) { if (this.returnIndex) {
this.$emit('click', index) this.$emit('click', index)
@ -121,7 +101,7 @@ export default Vue.extend({
this.$emit('click', url) this.$emit('click', url)
} }
this.focusOut() this.dropdownShown = false
} }
} }
}) })

View File

@ -56,7 +56,7 @@
color: var(--favorite-icon-color) color: var(--favorite-icon-color)
.iconDropdown .iconDropdown
display: none display: inline
position: absolute position: absolute
text-align: center text-align: center
list-style-type: none list-style-type: none
@ -68,9 +68,6 @@
color: var(--secondary-text-color) color: var(--secondary-text-color)
user-select: none user-select: none
&:focus
display: inline
&.left &.left
right: calc(50% - 10px) right: calc(50% - 10px)

View File

@ -13,9 +13,11 @@
fontSize: size + 'px' fontSize: size + 'px'
}" }"
@click="handleIconClick" @click="handleIconClick"
@mousedown="handleIconMouseDown"
/> />
<div <div
:id="id" v-show="dropdownShown"
ref="dropdown"
tabindex="-1" tabindex="-1"
class="iconDropdown" class="iconDropdown"
:class="{ :class="{
@ -25,6 +27,7 @@
bottom: dropdownPositionY === 'bottom', bottom: dropdownPositionY === 'bottom',
top: dropdownPositionY === 'top' top: dropdownPositionY === 'top'
}" }"
@focusout="handleDropdownFocusOut"
> >
<slot> <slot>
<ul <ul

View File

@ -79,42 +79,42 @@ export default Vue.extend({
openInvidious() { openInvidious() {
this.openExternalLink(this.getFinalUrl(this.invidiousURL)) this.openExternalLink(this.getFinalUrl(this.invidiousURL))
this.$refs.iconButton.focusOut() this.$refs.iconButton.hideDropdown()
}, },
copyInvidious() { copyInvidious() {
this.copyToClipboard({ content: this.getFinalUrl(this.invidiousURL), messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') }) this.copyToClipboard({ content: this.getFinalUrl(this.invidiousURL), messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') })
this.$refs.iconButton.focusOut() this.$refs.iconButton.hideDropdown()
}, },
openYoutube() { openYoutube() {
this.openExternalLink(this.getFinalUrl(this.youtubeURL)) this.openExternalLink(this.getFinalUrl(this.youtubeURL))
this.$refs.iconButton.focusOut() this.$refs.iconButton.hideDropdown()
}, },
copyYoutube() { copyYoutube() {
this.copyToClipboard({ content: this.getFinalUrl(this.youtubeShareURL), messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') }) this.copyToClipboard({ content: this.getFinalUrl(this.youtubeShareURL), messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') })
this.$refs.iconButton.focusOut() this.$refs.iconButton.hideDropdown()
}, },
openYoutubeEmbed() { openYoutubeEmbed() {
this.openExternalLink(this.getFinalUrl(this.youtubeEmbedURL)) this.openExternalLink(this.getFinalUrl(this.youtubeEmbedURL))
this.$refs.iconButton.focusOut() this.$refs.iconButton.hideDropdown()
}, },
copyYoutubeEmbed() { copyYoutubeEmbed() {
this.copyToClipboard({ content: this.getFinalUrl(this.youtubeEmbedURL), messageOnSuccess: this.$t('Share.YouTube Embed URL copied to clipboard') }) this.copyToClipboard({ content: this.getFinalUrl(this.youtubeEmbedURL), messageOnSuccess: this.$t('Share.YouTube Embed URL copied to clipboard') })
this.$refs.iconButton.focusOut() this.$refs.iconButton.hideDropdown()
}, },
openInvidiousEmbed() { openInvidiousEmbed() {
this.openExternalLink(this.getFinalUrl(this.invidiousEmbedURL)) this.openExternalLink(this.getFinalUrl(this.invidiousEmbedURL))
this.$refs.iconButton.focusOut() this.$refs.iconButton.hideDropdown()
}, },
copyInvidiousEmbed() { copyInvidiousEmbed() {
this.copyToClipboard({ content: this.getFinalUrl(this.invidiousEmbedURL), messageOnSuccess: this.$t('Share.Invidious Embed URL copied to clipboard') }) this.copyToClipboard({ content: this.getFinalUrl(this.invidiousEmbedURL), messageOnSuccess: this.$t('Share.Invidious Embed URL copied to clipboard') })
this.$refs.iconButton.focusOut() this.$refs.iconButton.hideDropdown()
}, },
updateIncludeTimestamp() { updateIncludeTimestamp() {