From b0ca8c74f5a2f5c26dec3aff0e50045cf7d9b24c Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Tue, 12 Jun 2018 12:45:13 +0200 Subject: [PATCH 1/6] Fix tooltip position and allow tooltip mouseover | Fixes #995 --- packages/clay-tooltip/src/ClayTooltip.js | 165 ++++++++++++++++------ packages/clay-tooltip/src/ClayTooltip.soy | 9 +- 2 files changed, 129 insertions(+), 45 deletions(-) diff --git a/packages/clay-tooltip/src/ClayTooltip.js b/packages/clay-tooltip/src/ClayTooltip.js index 9ed1138fe8..3f064119bb 100644 --- a/packages/clay-tooltip/src/ClayTooltip.js +++ b/packages/clay-tooltip/src/ClayTooltip.js @@ -58,6 +58,20 @@ class ClayTooltip extends Component { this._eventHandler = new EventHandler(); } + attached() { + this.addListener('transitionend', this._handleTransitionEnd, true); + } + + rendered() { + if (this._target) { + const alignedPosition = Align.align(this.element, this._target, this.position); + + if (this.alignedPosition !== alignedPosition) { + this.alignedPosition = alignedPosition; + } + } + } + /** * @inheritDoc */ @@ -73,62 +87,117 @@ class ClayTooltip extends Component { } /** - * Handles mouseenter events. + * Handles mouseenter event. * @memberof ClayTooltip - * @param {Object} event The event object. - * @protected + * @param {!Element} event + * @return {!String} + * @private */ - _handleMouseEnter(event) { - const target = event.delegateTarget; - - const titleAttribute = target.getAttribute('title'); + _getContent(element) { + const titleAttribute = element.getAttribute('title'); if (titleAttribute) { - target.setAttribute('data-title', titleAttribute); - target.setAttribute('data-restore-title', 'true'); - target.removeAttribute('title'); - } else if (target.tagName === 'svg') { - let titleTag = target.querySelector('title'); + element.setAttribute('data-title', titleAttribute); + element.setAttribute('data-restore-title', 'true'); + element.removeAttribute('title'); + } else if (element.tagName === 'svg') { + let titleTag = element.querySelector('title'); if (titleTag) { - target.setAttribute('data-title', titleTag.innerHTML); - target.setAttribute('data-restore-title', 'true'); + element.setAttribute('data-title', titleTag.innerHTML); + element.setAttribute('data-restore-title', 'true'); titleTag.remove(); } } - this._content = target.getAttribute('data-title'); + return element.getAttribute('data-title'); + } + + /** + * Handles click event. + * @memberof ClayTooltip + * @param {!Event} event + * @private + */ + _handleMouseClick(event) { + this._restoreTitle(event.delegateTarget); - this.alignedPosition = Align.align(this.element, target, this.position); - this._showTooltip = true; + this._isTransitioning = true; + this.visible = false; + } + + /** + * Handles mouseenter event. + * @memberof ClayTooltip + * @param {!Event} event + * @private + */ + _handleMouseEnter(event) { + const content = this._getContent(event.delegateTarget); + this._target = event.delegateTarget; + + this._content = content; + + this._isTransitioning = true; + this.visible = true; + } + + /** + * Handles tooltip element mouseenter event. + * @memberof ClayTooltip + * @param {!Event} event + * @private + */ + _handleMouseEnterTooltip(event) { + if (this._isTransitioning) { + this.visible = true; + } } /** * Handles mouseleave events. * @memberof ClayTooltip - * @param {Object} event The event object. - * @protected + * @param {!Event} event + * @private */ _handleMouseLeave(event) { - const target = event.delegateTarget; + this._restoreTitle(event.delegateTarget); - const title = target.getAttribute('data-title'); - const restoreTitle = target.getAttribute('data-restore-title'); + this._isTransitioning = true; + this.visible = false; + } + + /** + * Handles transionend event. + * @memberof ClayTooltip + * @private + */ + _handleTransitionEnd() { + this._isTransitioning = false; + } + + /** + * Restores the title attribute to an element + * @memberof ClayTooltip + * @param {Element} element + * @private + */ + _restoreTitle(element) { + const title = element.getAttribute('data-title'); + const restoreTitle = element.getAttribute('data-restore-title'); if (title && restoreTitle === 'true') { - if (target.tagName === 'svg') { + if (element.tagName === 'svg') { let titleTag = document.createElement('title'); titleTag.innerHTML = title; - target.appendChild(titleTag); + element.appendChild(titleTag); } else { - target.setAttribute('title', title); + element.setAttribute('title', title); } - target.removeAttribute('data-restore-title'); + element.removeAttribute('data-restore-title'); } - - this._showTooltip = false; } /** @@ -136,7 +205,7 @@ class ClayTooltip extends Component { * @memberof ClayTooltip * @param {Object} val * @return {!Object} - * @protected + * @private */ setterClassMapFn_(val) { return object.mixin(this.valueClassMapFn_(), val); @@ -147,7 +216,7 @@ class ClayTooltip extends Component { * @memberof ClayTooltip * @param {Array.} newValue The new value of `this.selectors`. * @param {Array.} prevValue The previous value of `this.selectors`. - * @protected + * @private */ syncSelectors(newValue, prevValue) { if (newValue) { @@ -170,6 +239,12 @@ class ClayTooltip extends Component { selector, this._handleMouseLeave.bind(this) ), + dom.delegate( + document, + 'click', + selector, + this._handleMouseClick.bind(this) + ), dom.delegate( document, 'focus', @@ -193,10 +268,17 @@ class ClayTooltip extends Component { } } + /** + * @inheritDoc + */ + syncVisible() { + //This is needed to make fade transition work + } + /** * Gets the default value for the `classMap` state. * @return {!Object} - * @protected + * @private */ valueClassMapFn_() { return { @@ -229,17 +311,6 @@ ClayTooltip.STATE = { .value('') .internal(), - /** - * A flag indicating if the tooltip should be shown. - * @default false - * @instance - * @memberof ClayTooltip - * @type {boolean} - */ - _showTooltip: Config.bool() - .value(false) - .internal(), - /** * The current position of the tooltip after being aligned via `Align.align`. * @default undefined @@ -293,6 +364,16 @@ ClayTooltip.STATE = { * @type {!Array.} */ selectors: Config.array().value(['[data-title]', '[title]']), + + /** + * Tooltip visible when show is called. + * @default false + * @instance + * @memberof ClayTooltip + * @private + * @type {?bool} + */ + visible: Config.bool().value(false), }; Soy.register(ClayTooltip, templates); diff --git a/packages/clay-tooltip/src/ClayTooltip.soy b/packages/clay-tooltip/src/ClayTooltip.soy index 607e3273bf..9d13913311 100644 --- a/packages/clay-tooltip/src/ClayTooltip.soy +++ b/packages/clay-tooltip/src/ClayTooltip.soy @@ -5,28 +5,31 @@ */ {template .render} {@param? _content: html|string} - {@param? _showTooltip: bool} {@param? alignedPosition: number} {@param? classMap: ?} {@param? elementClasses: string} {@param? position: number} + {@param? visible: bool} {let $classes: $classMap ? $classMap : ['clay-tooltip-top-left', 'clay-tooltip-top', 'clay-tooltip-top-right', 'clay-tooltip-bottom-left', 'clay-tooltip-bottom', 'clay-tooltip-bottom-right', 'clay-tooltip-right', 'clay-tooltip-left'] /} {let $currentPosition: $alignedPosition ?: $position /} {let $positionClass: isNonnull($currentPosition) ? $classes[$currentPosition] : 'clay-tooltip-bottom' /} {let $tooltipAttributes kind="attributes"} - class="tooltip + class="tooltip fade {sp}{$positionClass} {if $elementClasses} {sp}{$elementClasses} {/if} - {if $_showTooltip} + {if $visible} {sp}show {/if} " + + data-onmouseenter="_handleMouseEnterTooltip" + data-onmouseleave="_handleMouseLeave" role="tooltip" {/let} From 60ee3a418dcb44ea4c79a26fb385bf680dcf8afb Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Tue, 12 Jun 2018 12:48:00 +0200 Subject: [PATCH 2/6] Regen snapshots | Fixes #995 --- .../src/__tests__/__snapshots__/ClayTooltip.js.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/clay-tooltip/src/__tests__/__snapshots__/ClayTooltip.js.snap b/packages/clay-tooltip/src/__tests__/__snapshots__/ClayTooltip.js.snap index 771a1434b7..d78cbf101e 100644 --- a/packages/clay-tooltip/src/__tests__/__snapshots__/ClayTooltip.js.snap +++ b/packages/clay-tooltip/src/__tests__/__snapshots__/ClayTooltip.js.snap @@ -1,14 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ClayTooltip should allow setting selectors 1`] = ` -