8bb09344ab
Previously on iOS devices, tooltips in reply dialog did not always close when clicking outside of the button. The focusOut event was not triggered and thus _handleHideTooltip was not called. On other devices, the tooltip remained open when clicking on it. This change detects when a device triggers a touch event and sets a boolean variable that it is a touch device. If touch, we do not open and close tooltips. This was necessary because mouseenter and mouseleave events are still triggered on touch devices with a touch. Also, mouseover and mouseout events were replaced with mousenter and mouseleave events because it seemed better practice since they don't bubble to child elements & this is what is done in paper-tooltip. Bug: Issue 4649 Change-Id: Ib3a4681e8da77a5cd7c140e3a899ceb0cf8400a8
116 lines
3.6 KiB
JavaScript
116 lines
3.6 KiB
JavaScript
// 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.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;
|
||
|
||
// 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._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 - boxRect.height - BOTTOM_OFFSET;
|
||
var left =
|
||
rect.left - parentRect.left + (rect.width - boxRect.width) / 2;
|
||
if (left < 0) {
|
||
tooltip.updateStyles({
|
||
'--gr-tooltip-arrow-center-offset': left + 'px',
|
||
});
|
||
}
|
||
tooltip.style.left = Math.max(0, left) + 'px';
|
||
tooltip.style.top = Math.max(0, top) + 'px';
|
||
},
|
||
};
|
||
|
||
window.Gerrit = window.Gerrit || {};
|
||
window.Gerrit.TooltipBehavior = TooltipBehavior;
|
||
})(window);
|