| OLD | NEW |
| (Empty) |
| 1 Polymer({ | |
| 2 is: 'paper-tooltip', | |
| 3 | |
| 4 hostAttributes: { | |
| 5 role: 'tooltip', | |
| 6 tabindex: -1 | |
| 7 }, | |
| 8 | |
| 9 behaviors: [ | |
| 10 Polymer.NeonAnimationRunnerBehavior | |
| 11 ], | |
| 12 | |
| 13 properties: { | |
| 14 /** | |
| 15 * The id of the element that the tooltip is anchored to. This element | |
| 16 * must be a sibling of the tooltip. | |
| 17 */ | |
| 18 for: { | |
| 19 type: String, | |
| 20 observer: '_forChanged' | |
| 21 }, | |
| 22 | |
| 23 /** | |
| 24 * Set this to true if you want to manually control when the tooltip | |
| 25 * is shown or hidden. | |
| 26 */ | |
| 27 manualMode: { | |
| 28 type: Boolean, | |
| 29 value: false | |
| 30 }, | |
| 31 | |
| 32 /** | |
| 33 * Positions the tooltip to the top, right, bottom, left of its content. | |
| 34 */ | |
| 35 position: { | |
| 36 type: String, | |
| 37 value: 'bottom' | |
| 38 }, | |
| 39 | |
| 40 /** | |
| 41 * If true, no parts of the tooltip will ever be shown offscreen. | |
| 42 */ | |
| 43 fitToVisibleBounds: { | |
| 44 type: Boolean, | |
| 45 value: false | |
| 46 }, | |
| 47 | |
| 48 /** | |
| 49 * The spacing between the top of the tooltip and the element it is | |
| 50 * anchored to. | |
| 51 */ | |
| 52 offset: { | |
| 53 type: Number, | |
| 54 value: 14 | |
| 55 }, | |
| 56 | |
| 57 /** | |
| 58 * This property is deprecated, but left over so that it doesn't | |
| 59 * break exiting code. Please use `offset` instead. If both `offset` and | |
| 60 * `marginTop` are provided, `marginTop` will be ignored. | |
| 61 * @deprecated since version 1.0.3 | |
| 62 */ | |
| 63 marginTop: { | |
| 64 type: Number, | |
| 65 value: 14 | |
| 66 }, | |
| 67 | |
| 68 /** | |
| 69 * The delay that will be applied before the `entry` animation is | |
| 70 * played when showing the tooltip. | |
| 71 */ | |
| 72 animationDelay: { | |
| 73 type: Number, | |
| 74 value: 500 | |
| 75 }, | |
| 76 | |
| 77 /** | |
| 78 * The entry and exit animations that will be played when showing and | |
| 79 * hiding the tooltip. If you want to override this, you must ensure | |
| 80 * that your animationConfig has the exact format below. | |
| 81 */ | |
| 82 animationConfig: { | |
| 83 type: Object, | |
| 84 value: function() { | |
| 85 return { | |
| 86 'entry': [{ | |
| 87 name: 'fade-in-animation', | |
| 88 node: this, | |
| 89 timing: {delay: 0} | |
| 90 }], | |
| 91 'exit': [{ | |
| 92 name: 'fade-out-animation', | |
| 93 node: this | |
| 94 }] | |
| 95 } | |
| 96 } | |
| 97 }, | |
| 98 | |
| 99 _showing: { | |
| 100 type: Boolean, | |
| 101 value: false | |
| 102 } | |
| 103 }, | |
| 104 | |
| 105 listeners: { | |
| 106 'neon-animation-finish': '_onAnimationFinish', | |
| 107 'mouseenter': 'hide' | |
| 108 }, | |
| 109 | |
| 110 /** | |
| 111 * Returns the target element that this tooltip is anchored to. It is | |
| 112 * either the element given by the `for` attribute, or the immediate paren
t | |
| 113 * of the tooltip. | |
| 114 */ | |
| 115 get target () { | |
| 116 var parentNode = Polymer.dom(this).parentNode; | |
| 117 // If the parentNode is a document fragment, then we need to use the hos
t. | |
| 118 var ownerRoot = Polymer.dom(this).getOwnerRoot(); | |
| 119 | |
| 120 var target; | |
| 121 if (this.for) { | |
| 122 target = Polymer.dom(ownerRoot).querySelector('#' + this.for); | |
| 123 } else { | |
| 124 target = parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? | |
| 125 ownerRoot.host : parentNode; | |
| 126 } | |
| 127 | |
| 128 return target; | |
| 129 }, | |
| 130 | |
| 131 attached: function() { | |
| 132 this._target = this.target; | |
| 133 | |
| 134 if (this.manualMode) | |
| 135 return; | |
| 136 | |
| 137 this.listen(this._target, 'mouseenter', 'show'); | |
| 138 this.listen(this._target, 'focus', 'show'); | |
| 139 this.listen(this._target, 'mouseleave', 'hide'); | |
| 140 this.listen(this._target, 'blur', 'hide'); | |
| 141 this.listen(this._target, 'tap', 'hide'); | |
| 142 }, | |
| 143 | |
| 144 detached: function() { | |
| 145 if (this._target && !this.manualMode) { | |
| 146 this.unlisten(this._target, 'mouseenter', 'show'); | |
| 147 this.unlisten(this._target, 'focus', 'show'); | |
| 148 this.unlisten(this._target, 'mouseleave', 'hide'); | |
| 149 this.unlisten(this._target, 'blur', 'hide'); | |
| 150 this.unlisten(this._target, 'tap', 'hide'); | |
| 151 } | |
| 152 }, | |
| 153 | |
| 154 show: function() { | |
| 155 // If the tooltip is already showing, there's nothing to do. | |
| 156 if (this._showing) | |
| 157 return; | |
| 158 | |
| 159 if (Polymer.dom(this).textContent.trim() === '') | |
| 160 return; | |
| 161 | |
| 162 | |
| 163 this.cancelAnimation(); | |
| 164 this._showing = true; | |
| 165 this.toggleClass('hidden', false, this.$.tooltip); | |
| 166 this.updatePosition(); | |
| 167 | |
| 168 this.animationConfig.entry[0].timing.delay = this.animationDelay; | |
| 169 this._animationPlaying = true; | |
| 170 this.playAnimation('entry'); | |
| 171 }, | |
| 172 | |
| 173 hide: function() { | |
| 174 // If the tooltip is already hidden, there's nothing to do. | |
| 175 if (!this._showing) { | |
| 176 return; | |
| 177 } | |
| 178 | |
| 179 // If the entry animation is still playing, don't try to play the exit | |
| 180 // animation since this will reset the opacity to 1. Just end the animat
ion. | |
| 181 if (this._animationPlaying) { | |
| 182 this.cancelAnimation(); | |
| 183 this._showing = false; | |
| 184 this._onAnimationFinish(); | |
| 185 return; | |
| 186 } | |
| 187 | |
| 188 this._showing = false; | |
| 189 this._animationPlaying = true; | |
| 190 this.playAnimation('exit'); | |
| 191 }, | |
| 192 | |
| 193 _forChanged: function() { | |
| 194 this._target = this.target; | |
| 195 }, | |
| 196 | |
| 197 updatePosition: function() { | |
| 198 if (!this._target || !this.offsetParent) | |
| 199 return; | |
| 200 | |
| 201 var offset = this.offset; | |
| 202 // If a marginTop has been provided by the user (pre 1.0.3), use it. | |
| 203 if (this.marginTop != 14 && this.offset == 14) | |
| 204 offset = this.marginTop; | |
| 205 | |
| 206 var parentRect = this.offsetParent.getBoundingClientRect(); | |
| 207 var targetRect = this._target.getBoundingClientRect(); | |
| 208 var thisRect = this.getBoundingClientRect(); | |
| 209 | |
| 210 var horizontalCenterOffset = (targetRect.width - thisRect.width) / 2; | |
| 211 var verticalCenterOffset = (targetRect.height - thisRect.height) / 2; | |
| 212 | |
| 213 var targetLeft = targetRect.left - parentRect.left; | |
| 214 var targetTop = targetRect.top - parentRect.top; | |
| 215 | |
| 216 var tooltipLeft, tooltipTop; | |
| 217 | |
| 218 switch (this.position) { | |
| 219 case 'top': | |
| 220 tooltipLeft = targetLeft + horizontalCenterOffset; | |
| 221 tooltipTop = targetTop - thisRect.height - offset; | |
| 222 break; | |
| 223 case 'bottom': | |
| 224 tooltipLeft = targetLeft + horizontalCenterOffset; | |
| 225 tooltipTop = targetTop + targetRect.height + offset; | |
| 226 break; | |
| 227 case 'left': | |
| 228 tooltipLeft = targetLeft - thisRect.width - offset; | |
| 229 tooltipTop = targetTop + verticalCenterOffset; | |
| 230 break; | |
| 231 case 'right': | |
| 232 tooltipLeft = targetLeft + targetRect.width + offset; | |
| 233 tooltipTop = targetTop + verticalCenterOffset; | |
| 234 break; | |
| 235 } | |
| 236 | |
| 237 // TODO(noms): This should use IronFitBehavior if possible. | |
| 238 if (this.fitToVisibleBounds) { | |
| 239 // Clip the left/right side. | |
| 240 if (tooltipLeft + thisRect.width > window.innerWidth) { | |
| 241 this.style.right = '0px'; | |
| 242 this.style.left = 'auto'; | |
| 243 } else { | |
| 244 this.style.left = Math.max(0, tooltipLeft) + 'px'; | |
| 245 this.style.right = 'auto'; | |
| 246 } | |
| 247 | |
| 248 // Clip the top/bottom side. | |
| 249 if (tooltipTop + thisRect.height > window.innerHeight) { | |
| 250 this.style.bottom = '0px'; | |
| 251 this.style.top = 'auto'; | |
| 252 } else { | |
| 253 this.style.top = Math.max(0, tooltipTop) + 'px'; | |
| 254 this.style.bottom = 'auto'; | |
| 255 } | |
| 256 } else { | |
| 257 this.style.left = tooltipLeft + 'px'; | |
| 258 this.style.top = tooltipTop + 'px'; | |
| 259 } | |
| 260 | |
| 261 }, | |
| 262 | |
| 263 _onAnimationFinish: function() { | |
| 264 this._animationPlaying = false; | |
| 265 if (!this._showing) { | |
| 266 this.toggleClass('hidden', true, this.$.tooltip); | |
| 267 } | |
| 268 }, | |
| 269 }); | |
| OLD | NEW |