Files
gerrit/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js
Becky Siegel c9e4a34e77 Introduce gr-tooltip-content element and add for draft comment
This change introduces an element that can wrap a tooltip around
arbitrary contents. Previously, we could only attach a tooltip to a
Polymer element, and want more granularity than that for the purposes
of positioning.

The new tooltip element takes the following arguments:
- title (the contents of the tooltip, required)
- showIcon (optional, to show an info icon)
- maxWidth (optional, to pass a max-width to the tooltip itself).

The tooltip itself will be attached to the content inside of the
<gr-tooltip-content> wrapper.

One tooltip has been added using this new element for the 'DRAFT' text
in the gr-diff-comment'.

Bug: Issue 4539
Change-Id: Iff05c785052c643ef1f1cc01d101b21c48c6299f
2017-03-14 13:17:30 -07:00

124 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 = 7.2; // Height of the arrow in tooltip.
/** @polymerBehavior Gerrit.TooltipBehavior */
var TooltipBehavior = {
properties: {
hasTooltip: Boolean,
_isTouchDevice: {
type: Boolean,
value: function() {
return 'ontouchstart' in document.documentElement;
},
},
_tooltip: Element,
_titleText: String,
},
attached: function() {
if (!this.hasTooltip) { return; }
this.addEventListener('mouseenter', this._handleShowTooltip.bind(this));
this.addEventListener('mouseleave', this._handleHideTooltip.bind(this));
this.addEventListener('tap', this._handleHideTooltip.bind(this));
this.listen(window, 'scroll', '_handleWindowScroll');
},
detached: function() {
this._handleHideTooltip();
this.unlisten(window, 'scroll', '_handleWindowScroll');
},
_handleShowTooltip: function(e) {
if (this._isTouchDevice) { return; }
if (!this.hasAttribute('title') ||
this.getAttribute('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;
tooltip.maxWidth = this.getAttribute('max-width');
// Set visibility to hidden before appending to the DOM so that
// calculations can be made based on the elements 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._isTouchDevice) { return; }
if (!this.hasAttribute('title') ||
this._titleText == null) {
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 rect = this.getBoundingClientRect();
var boxRect = tooltip.getBoundingClientRect();
var parentRect = tooltip.parentElement.getBoundingClientRect();
var top = rect.top - parentRect.top;
var left = rect.left - parentRect.left + (rect.width - boxRect.width) / 2;
var right = parentRect.width - left - boxRect.width;
if (left < 0) {
tooltip.updateStyles({
'--gr-tooltip-arrow-center-offset': left + 'px',
});
} else if (right < 0) {
tooltip.updateStyles({
'--gr-tooltip-arrow-center-offset': (-0.5 * right) + 'px',
});
}
tooltip.style.left = Math.max(0, left) + 'px';
tooltip.style.top = Math.max(0, top) + 'px';
tooltip.style.transform = 'translateY(calc(-100% - ' + BOTTOM_OFFSET +
'px))';
},
};
window.Gerrit = window.Gerrit || {};
window.Gerrit.TooltipBehavior = TooltipBehavior;
})(window);