From 8914cb015363ec6ed281f941bb84a0f42bf39f79 Mon Sep 17 00:00:00 2001 From: Andrew Bonventre Date: Fri, 13 May 2016 17:30:05 -0400 Subject: [PATCH] Add gr-tooltip-behavior and gr-tooltip element What it looks like: http://imgur.com/U37fSkk Will only trigger if the element has a title value and also has its hasTooltip property set. Add titles to the label buttons and turn tooltips on for those. Bug: Issue 3901 Change-Id: Id02f79bcf218419ab92d8100477ced093623f4d2 --- .../gr-tooltip-behavior.html | 18 +++ .../gr-tooltip-behavior.js | 110 ++++++++++++++++++ .../gr-reply-dialog/gr-reply-dialog.html | 3 +- .../change/gr-reply-dialog/gr-reply-dialog.js | 4 + .../elements/shared/gr-button/gr-button.html | 1 + .../elements/shared/gr-button/gr-button.js | 1 + .../shared/gr-tooltip/gr-tooltip.html | 49 ++++++++ .../elements/shared/gr-tooltip/gr-tooltip.js | 24 ++++ 8 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.html create mode 100644 polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js create mode 100644 polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.html create mode 100644 polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js diff --git a/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.html b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.html new file mode 100644 index 0000000000..6b35328f8f --- /dev/null +++ b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.html @@ -0,0 +1,18 @@ + + + + diff --git a/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js new file mode 100644 index 0000000000..2da68469b8 --- /dev/null +++ b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js @@ -0,0 +1,110 @@ +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +(function(window) { + 'use strict'; + + var BOTTOM_OFFSET = 10; + + var TooltipBehavior = { + + properties: { + hasTooltip: Boolean, + + _tooltip: Element, + _titleText: String, + }, + + attached: function() { + if (!this.hasTooltip) { return; } + + this.addEventListener('mouseover', this._handleShowTooltip.bind(this)); + this.addEventListener('mouseout', this._handleHideTooltip.bind(this)); + this.addEventListener('focusin', this._handleShowTooltip.bind(this)); + this.addEventListener('focusout', this._handleHideTooltip.bind(this)); + this.listen(window, 'scroll', '_handleWindowScroll'); + }, + + detached: function() { + this.unlisten(window, 'scroll', '_handleWindowScroll'); + }, + + _handleShowTooltip: function(e) { + if (!this.hasAttribute('title') || this._tooltip) { return; } + + // Store the title attribute text then set it to an empty string to + // prevent it from showing natively. + this._titleText = this.getAttribute('title'); + this.setAttribute('title', ''); + + var tooltip = document.createElement('gr-tooltip'); + tooltip.text = this._titleText; + + // Set visibility to hidden before appending to the DOM so that + // calculations can be made based on the element’s size. + tooltip.style.visibility = 'hidden'; + Polymer.dom(document.body).appendChild(tooltip); + this._positionTooltip(tooltip); + tooltip.style.visibility = null; + + this._tooltip = tooltip; + }, + + _handleHideTooltip: function(e) { + if (!this.hasAttribute('title') || + !this._titleText || + this === document.activeElement) { return; } + + this.setAttribute('title', this._titleText); + if (this._tooltip && this._tooltip.parentNode) { + this._tooltip.parentNode.removeChild(this._tooltip); + } + this._tooltip = null; + }, + + _handleWindowScroll: function(e) { + if (!this._tooltip) { return; } + + this._positionTooltip(this._tooltip); + }, + + _positionTooltip: function(tooltip) { + var offset = this._getOffset(this); + var top = offset.top; + var left = offset.left; + + top -= this.offsetHeight + BOTTOM_OFFSET; + left -= (tooltip.offsetWidth / 2) - (this.offsetWidth / 2); + left = Math.max(0, left); + top = Math.max(0, top); + + tooltip.style.left = left + 'px'; + tooltip.style.top = top + 'px'; + }, + + _getOffset: function(el) { + var top = 0; + var left = 0; + for (var node = el; node; node = node.offsetParent) { + if (node.offsetTop) { top += node.offsetTop; } + if (node.offsetLeft) { left += node.offsetLeft; } + } + top += window.scrollY; + left += window.scrollX; + return {top: top, left: left}; + }, + }; + + window.Gerrit = window.Gerrit || {}; + window.Gerrit.TooltipBehavior = TooltipBehavior; +})(window); diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html index 0859b41ec4..7fb998b65b 100644 --- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html +++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html @@ -125,7 +125,8 @@ limitations under the License. diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js index 375bd82b65..14119b9e67 100644 --- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js +++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js @@ -89,6 +89,10 @@ if (total > 1) { return total + ' Drafts'; } }, + _computeLabelValueTitle: function(labels, label, value) { + return labels[label].values[value]; + }, + _computeLabelArray: function(labelsObj) { return Object.keys(labelsObj).sort(); }, diff --git a/polygerrit-ui/app/elements/shared/gr-button/gr-button.html b/polygerrit-ui/app/elements/shared/gr-button/gr-button.html index 1df98fdf9e..c815ffd9a1 100644 --- a/polygerrit-ui/app/elements/shared/gr-button/gr-button.html +++ b/polygerrit-ui/app/elements/shared/gr-button/gr-button.html @@ -15,6 +15,7 @@ limitations under the License. --> + diff --git a/polygerrit-ui/app/elements/shared/gr-button/gr-button.js b/polygerrit-ui/app/elements/shared/gr-button/gr-button.js index 772fccc858..e10989645c 100644 --- a/polygerrit-ui/app/elements/shared/gr-button/gr-button.js +++ b/polygerrit-ui/app/elements/shared/gr-button/gr-button.js @@ -31,6 +31,7 @@ behaviors: [ Gerrit.KeyboardShortcutBehavior, + Gerrit.TooltipBehavior, ], hostAttributes: { diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.html b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.html new file mode 100644 index 0000000000..64ef9b29e5 --- /dev/null +++ b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.html @@ -0,0 +1,49 @@ + + + + + + + + + diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js new file mode 100644 index 0000000000..76372ba42f --- /dev/null +++ b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js @@ -0,0 +1,24 @@ +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +(function() { + 'use strict'; + + Polymer({ + is: 'gr-tooltip', + + properties: { + text: String, + }, + }); +})();