Commit a3c56343 authored by Simon Knox's avatar Simon Knox

Merge branch '321514-fix-clipboard-buttons' into 'master'

Fix copy to clipboard tooltip button

See merge request gitlab-org/gitlab!54472
parents 50a028b3 aba25421
import Clipboard from 'clipboard'; import Clipboard from 'clipboard';
import $ from 'jquery'; import $ from 'jquery';
import { sprintf, __ } from '~/locale'; import { sprintf, __ } from '~/locale';
import { fixTitle, show } from '~/tooltips'; import { fixTitle, add, show, once } from '~/tooltips';
function showTooltip(target, title) { function showTooltip(target, title) {
const { originalTitle } = target.dataset; const { title: originalTitle } = target.dataset;
const hideTooltip = () => {
target.removeEventListener('mouseout', hideTooltip); once('hidden', (tooltip) => {
setTimeout(() => { if (tooltip.target === target) {
target.setAttribute('title', originalTitle); target.setAttribute('title', originalTitle);
fixTitle(target); fixTitle(target);
}, 100); }
}; });
target.setAttribute('title', title); target.setAttribute('title', title);
fixTitle(target); fixTitle(target);
show(target); show(target);
setTimeout(() => target.blur(), 1000);
target.addEventListener('mouseout', hideTooltip);
} }
function genericSuccess(e) { function genericSuccess(e) {
// Clear the selection and blur the trigger so it loses its border // Clear the selection and blur the trigger so it loses its border
e.clearSelection(); e.clearSelection();
$(e.trigger).blur();
showTooltip(e.trigger, __('Copied')); showTooltip(e.trigger, __('Copied'));
} }
...@@ -88,24 +84,8 @@ export default function initCopyToClipboard() { ...@@ -88,24 +84,8 @@ export default function initCopyToClipboard() {
* @param {HTMLElement} btnElement * @param {HTMLElement} btnElement
*/ */
export function clickCopyToClipboardButton(btnElement) { export function clickCopyToClipboardButton(btnElement) {
const $btnElement = $(btnElement);
// Ensure the button has already been tooltip'd. // Ensure the button has already been tooltip'd.
// If the use hasn't yet interacted (i.e. hovered or clicked) add([btnElement], { show: true });
// with the button, Bootstrap hasn't yet initialized
// the tooltip, and its `data-original-title` will be `undefined`.
// This value is used in the functions above.
$btnElement.tooltip();
btnElement.dispatchEvent(new MouseEvent('mouseover'));
btnElement.click(); btnElement.click();
// Manually trigger the necessary events to hide the
// button's tooltip and allow the button to perform its
// tooltip cleanup (updating the title from "Copied" back
// to its original title, "Copy branch name").
setTimeout(() => {
btnElement.dispatchEvent(new MouseEvent('mouseout'));
$btnElement.tooltip('hide');
}, 2000);
} }
...@@ -82,9 +82,10 @@ export default { ...@@ -82,9 +82,10 @@ export default {
}, },
triggerEvent(target, event) { triggerEvent(target, event) {
const tooltip = this.findTooltipByTarget(target); const tooltip = this.findTooltipByTarget(target);
const tooltipRef = this.$refs[tooltip?.id];
if (tooltip) { if (tooltipRef) {
this.$refs[tooltip.id][0].$emit(event); tooltipRef[0].$emit(event);
} }
}, },
tooltipExists(element) { tooltipExists(element) {
...@@ -113,6 +114,7 @@ export default { ...@@ -113,6 +114,7 @@ export default {
:boundary="tooltip.boundary" :boundary="tooltip.boundary"
:disabled="tooltip.disabled" :disabled="tooltip.disabled"
:show="tooltip.show" :show="tooltip.show"
@hidden="$emit('hidden', tooltip)"
> >
<span v-if="tooltip.html" v-safe-html:[$options.safeHtmlConfig]="tooltip.title"></span> <span v-if="tooltip.html" v-safe-html:[$options.safeHtmlConfig]="tooltip.title"></span>
<span v-else>{{ tooltip.title }}</span> <span v-else>{{ tooltip.title }}</span>
......
...@@ -92,6 +92,7 @@ export const hide = createTooltipApiInvoker((element) => ...@@ -92,6 +92,7 @@ export const hide = createTooltipApiInvoker((element) =>
export const show = createTooltipApiInvoker((element) => export const show = createTooltipApiInvoker((element) =>
tooltipsApp().triggerEvent(element, 'open'), tooltipsApp().triggerEvent(element, 'open'),
); );
export const once = (event, cb) => tooltipsApp().$once(event, cb);
export const destroy = () => { export const destroy = () => {
tooltipsApp().$destroy(); tooltipsApp().$destroy();
app = null; app = null;
......
---
title: Fix copy to clipboard tooltip button
merge_request: 54472
author:
type: fixed
...@@ -217,4 +217,14 @@ describe('tooltips/components/tooltips.vue', () => { ...@@ -217,4 +217,14 @@ describe('tooltips/components/tooltips.vue', () => {
wrapper.destroy(); wrapper.destroy();
expect(observersCount()).toBe(0); expect(observersCount()).toBe(0);
}); });
it('exposes hidden event', async () => {
buildWrapper();
wrapper.vm.addTooltips([createTooltipTarget()]);
await wrapper.vm.$nextTick();
wrapper.findComponent(GlTooltip).vm.$emit('hidden');
expect(wrapper.emitted('hidden')).toHaveLength(1);
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment