-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use default behavior for platform wide anchors (part I) #4834
Changes from 19 commits
929245f
da43160
5a3522d
0a87b52
fd7f288
08c7f61
da730cf
a41d0c0
1476245
06bcaa0
39e7193
782ef75
afe1d6b
bbd10e8
00142c2
bf0b22a
db414ca
4fb7bf3
2bec70b
6109c8c
7980433
d57b40b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { useRouter } from 'vue-router' | ||
|
||
export function useNavigationHelper () { | ||
const _router = useRouter() | ||
|
||
const openInANewTab = (href) => { | ||
return new Promise(resolve => { | ||
window.open(href, '_blank') | ||
resolve() | ||
}) | ||
} | ||
|
||
const _isExternalLink = (href) => { | ||
try { | ||
const link = new URL(href, window.location.origin) | ||
|
||
return link.origin !== window.location.origin | ||
} catch { | ||
return false | ||
} | ||
} | ||
|
||
const navigateTo = (to, $event = null) => { | ||
const internalHref = _router.resolve(to).href | ||
const isMiddleButtonClick = $event?.button === 1 | ||
const newTabKeyCombination = $event && ($event?.ctrlKey || $event.metaKey || isMiddleButtonClick) | ||
const isExternalLink = _isExternalLink(to) | ||
|
||
switch (true) { | ||
case isExternalLink && newTabKeyCombination: | ||
return openInANewTab(to) | ||
|
||
case isExternalLink: | ||
return navigateToExternal(to) | ||
|
||
case newTabKeyCombination: | ||
return openInANewTab(internalHref) | ||
|
||
default: | ||
return _router.push(to) | ||
} | ||
} | ||
|
||
const navigateToExternal = (href) => { | ||
return new Promise(resolve => { | ||
window.location.href = href | ||
resolve() | ||
}) | ||
} | ||
|
||
return { | ||
openInANewTab, | ||
navigateTo, | ||
navigateToExternal | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,14 @@ | ||
<template> | ||
<div :data-type="`${isImmersiveEditor ? 'immersive' : 'standard'}-editor`" @click.stop="openEditor()"> | ||
<div :data-type="`${isImmersiveEditor ? 'immersive' : 'standard'}-editor`" @mouseup.stop.prevent="openEditor"> | ||
<slot name="default"> | ||
<ff-button | ||
v-ff-tooltip:left="(editorDisabled || disabled) ? disabledReason : undefined" | ||
type="anchor" | ||
:to="editorURL" | ||
kind="secondary" | ||
data-action="open-editor" | ||
:disabled="buttonDisabled" | ||
class="whitespace-nowrap" | ||
@click.stop="openEditor" | ||
:emit-instead-of-navigate="true" | ||
@select="openEditor" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. another way of preventing click events from bubbling up/down. This is specific to the editor link button, having to open different urls based on the type of click/combination acted upon. Emitting an event instead of propagating the click event when clicked gets rid of a lot of headaches and changes when dealing with event propagation in parent components. I have to admit, 'select' is not the best choice of name for the event being emitted when clicked |
||
> | ||
<template v-if="showText" #icon-left> | ||
<ProjectIcon /> | ||
|
@@ -32,6 +31,7 @@ import SemVer from 'semver' | |
import { mapState } from 'vuex' | ||
|
||
import ProjectIcon from '../../../components/icons/Projects.js' | ||
import { useNavigationHelper } from '../../../composables/NavigationHelper.js' | ||
|
||
export default { | ||
name: 'InstanceEditorLink', | ||
|
@@ -59,6 +59,13 @@ export default { | |
type: Boolean | ||
} | ||
}, | ||
setup () { | ||
const { openInANewTab } = useNavigationHelper() | ||
|
||
return { | ||
openInANewTab | ||
} | ||
}, | ||
computed: { | ||
...mapState('account', ['team', 'teamMembership']), | ||
isImmersiveEditor () { | ||
|
@@ -85,20 +92,21 @@ export default { | |
}, | ||
methods: { | ||
openEditor (evt) { | ||
evt.preventDefault() | ||
if (this.disabled) { | ||
return false | ||
} | ||
let href = this.url | ||
let target = !this.isImmersiveEditor ? '_blank' : '_self' | ||
// On Mac Keyboard, ⌘ + click opens in new tab (⌘ is `metaKey`) | ||
// Otherwise Ctrl + click opens in new tab (Ctrl is `ctrlKey`) | ||
if (evt.ctrlKey || evt.metaKey) { | ||
target = '_blank' | ||
href = this.editorURL | ||
|
||
switch (true) { | ||
case !this.isImmersiveEditor: | ||
return this.openInANewTab(this.editorURL) | ||
case evt.ctrlKey || evt.metaKey || evt.button === 1: | ||
// On Mac Keyboard, ⌘ + click opens in new tab (⌘ is `metaKey`) | ||
// Otherwise Ctrl + click opens in new tab (Ctrl is `ctrlKey`) | ||
// Middle mouse button click opens in a new tab (button === 1) | ||
return this.openInANewTab(this.url) | ||
default: | ||
return this.$router.push(this.url) | ||
} | ||
window.open(href, target) | ||
return false | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are these required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to prevent the click event from bubbling up/down. In the case of the dashboard link being nested inside another anchor/link/button, this prevents opening both parent anchor and dashboard link when clicking (or any other click + keyboard combination) directly on the dashboard link element