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.
5 cr.define('print_preview', function() {
9 * Encapsulated handling of a search bubble.
11 * @extends {HTMLDivElement}
13 function SearchBubble(text) {
14 var el = cr.doc.createElement('div');
15 SearchBubble.decorate(el);
20 SearchBubble.decorate = function(el) {
21 el.__proto__ = SearchBubble.prototype;
25 SearchBubble.prototype = {
26 __proto__: HTMLDivElement.prototype,
28 decorate: function() {
29 this.className = 'search-bubble';
31 this.innards_ = cr.doc.createElement('div');
32 this.innards_.className = 'search-bubble-innards';
33 this.appendChild(this.innards_);
35 // We create a timer to periodically update the position of the bubbles.
36 // While this isn't all that desirable, it's the only sure-fire way of
37 // making sure the bubbles stay in the correct location as sections
38 // may dynamically change size at any time.
39 this.intervalId = setInterval(this.updatePosition.bind(this), 250);
43 * Sets the text message in the bubble.
44 * @param {string} text The text the bubble will show.
47 this.innards_.textContent = text;
50 /** Attach the bubble to the element. */
51 attachTo: function(element) {
52 var parent = element.parentElement;
55 if (parent.tagName == 'TD') {
56 // To make absolute positioning work inside a table cell we need
57 // to wrap the bubble div into another div with position:relative.
58 // This only works properly if the element is the first child of the
59 // table cell which is true for all options pages (the only place
60 // it is used on tables).
61 this.wrapper = cr.doc.createElement('div');
62 this.wrapper.className = 'search-bubble-wrapper';
63 this.wrapper.appendChild(this);
64 parent.insertBefore(this.wrapper, element);
66 parent.insertBefore(this, element);
68 this.updatePosition();
71 /** Clear the interval timer and remove the element from the page. */
73 clearInterval(this.intervalId);
75 var child = this.wrapper || this;
76 var parent = child.parentNode;
78 parent.removeChild(child);
82 * Update the position of the bubble. Called at creation time and then
83 * periodically while the bubble remains visible.
85 updatePosition: function() {
86 // This bubble is 'owned' by the next sibling.
87 var owner = (this.wrapper || this).nextSibling;
89 // If there isn't an offset parent, we have nothing to do.
90 if (!owner.offsetParent)
93 // Position the bubble below the location of the owner.
94 var left = owner.offsetLeft + owner.offsetWidth / 2 -
96 var top = owner.offsetTop + owner.offsetHeight;
98 // Update the position in the CSS. Cache the last values for
100 if (left != this.lastLeft) {
101 this.style.left = left + 'px';
102 this.lastLeft = left;
104 if (top != this.lastTop) {
105 this.style.top = top + 'px';
113 SearchBubble: SearchBubble