blob: 634be4696a8c76c7dcd67f6d8b7046818c6c47fc [file] [log] [blame]
<!--
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<!--
The `core-tooltip` element creates a hover tooltip centered for the content
it contains. It can be positioned on the top|bottom|left|right of content using
the `position` attribute.
To include HTML in the tooltip, include the `tip` attribute on the relevant
content.
<b>Example</b>:
<core-tooltip label="I'm a tooltip">
<span>Hover over me.</span>
</core-tooltip>
<b>Example</b> - positioning the tooltip to the right:
<core-tooltip label="I'm a tooltip to the right" position="right">
<core-icon-button icon="drawer"></core-icon-button>
</core-tooltip>
<b>Example</b> - no arrow and showing by default:
<core-tooltip label="Tooltip with no arrow and always on" noarrow show>
<img src="image.jpg">
</core-tooltip>
<b>Example</b> - disable the tooltip.
<core-tooltip label="Disabled label never shows" disabled>
...
</core-tooltip>
<b>Example</b> - rich tooltip using the `tip` attribute:
<core-tooltip>
<div>Example of a rich information tooltip</div>
<div tip>
<img src="profile.jpg">Foo <b>Bar</b> - <a href="#">@baz</a>
</div>
</core-tooltip>
By default, the `tip` attribute specifies the HTML content for a rich tooltip.
You can customize this attribute with the `tipAttribute` attribute:
<core-tooltip tipAttribute="htmltooltip">
<div>Example of a rich information tooltip</div>
<div htmltooltip>
...
</div>
</core-tooltip>
@group Polymer Core Elements
@element core-tooltip
@mixins Polymer.CoreFocusable https://github.com/polymer/core-focusable
@mixins Polymer.CoreResizable https://github.com/polymer/core-resizable
@homepage http://www.polymer-project.org/components/core-tooltip/index.html
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../core-focusable/core-focusable.html">
<link rel="import" href="../core-resizable/core-resizable.html">
<!-- TODO: would be nice to inherit from label to get .htmlFor, and .control,
but the latter is readonly. -->
<!-- TODO: support off center arrows. -->
<!-- TODO: detect mobile and apply the .large class, instead of manual
control. -->
<!-- TODO: possibly reuse core-overlay. -->
<polymer-element name="core-tooltip" attributes="noarrow position label show tipAttribute" role="tooltip" tabindex="0">
<template>
<link rel="stylesheet" href="core-tooltip.css">
<div id="tooltip" hidden?="{{!hasTooltipContent}}"
class="core-tooltip {{position}} {{ {noarrow: noarrow, show: show && !disabled} | tokenList}}">
<content id="c" select="[{{tipAttribute}}]">{{label}}</content>
</div>
<content></content>
</template>
<script>
(function() {
var proto = {
/**
* A simple string label for the tooltip to display. To display a rich
* HTML tooltip instead, omit `label` and include the `tip` attribute
* on a child node of `core-tooltip`.
*
* @attribute label
* @type string
* @default null
*/
label: null,
eventDelegates: {
'core-resize': 'positionChanged'
},
computed: {
// Indicates whether the tooltip has a set label propety or
// an element with the `tip` attribute.
hasTooltipContent: 'label || !!tipElement'
},
publish: {
/**
* Forces the tooltip to display. If `disabled` is set, this property is ignored.
*
* @attribute show
* @type boolean
* @default false
*/
show: {value: false, reflect: true},
/**
* Positions the tooltip to the top, right, bottom, left of its content.
*
* @attribute position
* @type string
* @default 'bottom'
*/
position: {value: 'bottom', reflect: true},
/**
* If true, the tooltip an arrow pointing towards the content.
*
* @attribute noarrow
* @type boolean
* @default false
*/
noarrow: {value: false, reflect: true}
},
/**
* Customizes the attribute used to specify which content
* is the rich HTML tooltip.
*
* @attribute tipAttribute
* @type string
* @default 'tip'
*/
tipAttribute: 'tip',
attached: function() {
this.updatedChildren();
this.resizableAttachedHandler();
},
detached: function() {
this.resizableDetachedHandler();
},
updatedChildren: function () {
this.tipElement = null;
for (var i = 0, el; el = this.$.c.getDistributedNodes()[i]; ++i) {
if (el.hasAttribute && el.hasAttribute(this.tipAttribute)) {
this.tipElement = el;
break;
}
}
// Job ensures we're not double calling setPosition() on DOM attach.
this.job('positionJob', this.setPosition);
// Monitor children to re-position tooltip when light dom changes.
this.onMutation(this, this.updatedChildren);
},
labelChanged: function(oldVal, newVal) {
this.job('positionJob', this.setPosition);
},
positionChanged: function(oldVal, newVal) {
this.job('positionJob', this.setPosition);
},
setPosition: function() {
var controlWidth = this.clientWidth;
var controlHeight = this.clientHeight;
var toolTipWidth = this.$.tooltip.clientWidth;
var toolTipHeight = this.$.tooltip.clientHeight;
switch (this.position) {
case 'top':
case 'bottom':
this.$.tooltip.style.left = (controlWidth - toolTipWidth) / 2 + 'px';
this.$.tooltip.style.top = null;
break;
case 'left':
case 'right':
this.$.tooltip.style.left = null;
this.$.tooltip.style.top = (controlHeight - toolTipHeight) / 2 + 'px';
break;
}
}
};
Polymer.mixin2(proto, Polymer.CoreFocusable);
Polymer.mixin(proto, Polymer.CoreResizable);
Polymer(proto);
})();
</script>
</polymer-element>