OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 cr.define('print_preview', function() { |
| 6 'use strict'; |
| 7 |
| 8 /** |
| 9 * Encapsulated handling of a search bubble. |
| 10 * @constructor |
| 11 */ |
| 12 function SearchBubble(text) { |
| 13 var el = cr.doc.createElement('div'); |
| 14 SearchBubble.decorate(el); |
| 15 el.content = text; |
| 16 return el; |
| 17 } |
| 18 |
| 19 SearchBubble.decorate = function(el) { |
| 20 el.__proto__ = SearchBubble.prototype; |
| 21 el.decorate(); |
| 22 }; |
| 23 |
| 24 SearchBubble.prototype = { |
| 25 __proto__: HTMLDivElement.prototype, |
| 26 |
| 27 decorate: function() { |
| 28 this.className = 'search-bubble'; |
| 29 |
| 30 this.innards_ = cr.doc.createElement('div'); |
| 31 this.innards_.className = 'search-bubble-innards'; |
| 32 this.appendChild(this.innards_); |
| 33 |
| 34 // We create a timer to periodically update the position of the bubbles. |
| 35 // While this isn't all that desirable, it's the only sure-fire way of |
| 36 // making sure the bubbles stay in the correct location as sections |
| 37 // may dynamically change size at any time. |
| 38 this.intervalId = setInterval(this.updatePosition.bind(this), 250); |
| 39 }, |
| 40 |
| 41 /** |
| 42 * Sets the text message in the bubble. |
| 43 * @param {string} text The text the bubble will show. |
| 44 */ |
| 45 set content(text) { |
| 46 this.innards_.textContent = text; |
| 47 }, |
| 48 |
| 49 /** Attach the bubble to the element. */ |
| 50 attachTo: function(element) { |
| 51 var parent = element.parentElement; |
| 52 if (!parent) |
| 53 return; |
| 54 if (parent.tagName == 'TD') { |
| 55 // To make absolute positioning work inside a table cell we need |
| 56 // to wrap the bubble div into another div with position:relative. |
| 57 // This only works properly if the element is the first child of the |
| 58 // table cell which is true for all options pages (the only place |
| 59 // it is used on tables). |
| 60 this.wrapper = cr.doc.createElement('div'); |
| 61 this.wrapper.className = 'search-bubble-wrapper'; |
| 62 this.wrapper.appendChild(this); |
| 63 parent.insertBefore(this.wrapper, element); |
| 64 } else { |
| 65 parent.insertBefore(this, element); |
| 66 } |
| 67 this.updatePosition(); |
| 68 }, |
| 69 |
| 70 /** Clear the interval timer and remove the element from the page. */ |
| 71 dispose: function() { |
| 72 clearInterval(this.intervalId); |
| 73 |
| 74 var child = this.wrapper || this; |
| 75 var parent = child.parentNode; |
| 76 if (parent) |
| 77 parent.removeChild(child); |
| 78 }, |
| 79 |
| 80 /** |
| 81 * Update the position of the bubble. Called at creation time and then |
| 82 * periodically while the bubble remains visible. |
| 83 */ |
| 84 updatePosition: function() { |
| 85 // This bubble is 'owned' by the next sibling. |
| 86 var owner = (this.wrapper || this).nextSibling; |
| 87 |
| 88 // If there isn't an offset parent, we have nothing to do. |
| 89 if (!owner.offsetParent) |
| 90 return; |
| 91 |
| 92 // Position the bubble below the location of the owner. |
| 93 var left = owner.offsetLeft + owner.offsetWidth / 2 - |
| 94 this.offsetWidth / 2; |
| 95 var top = owner.offsetTop + owner.offsetHeight; |
| 96 |
| 97 // Update the position in the CSS. Cache the last values for |
| 98 // best performance. |
| 99 if (left != this.lastLeft) { |
| 100 this.style.left = left + 'px'; |
| 101 this.lastLeft = left; |
| 102 } |
| 103 if (top != this.lastTop) { |
| 104 this.style.top = top + 'px'; |
| 105 this.lastTop = top; |
| 106 } |
| 107 }, |
| 108 }; |
| 109 |
| 110 // Export |
| 111 return { |
| 112 SearchBubble: SearchBubble |
| 113 }; |
| 114 }); |
OLD | NEW |