OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Bubble implementation. | 6 * @fileoverview Bubble implementation. |
7 */ | 7 */ |
8 | 8 |
9 // TODO(xiyuan): Move this into shared. | 9 // TODO(xiyuan): Move this into shared. |
10 cr.define('cr.ui', function() { | 10 cr.define('cr.ui', function() { |
11 /** | 11 /** |
12 * Creates a bubble div. | 12 * Creates a bubble div. |
13 * @constructor | 13 * @constructor |
14 * @extends {HTMLDivElement} | 14 * @extends {HTMLDivElement} |
15 */ | 15 */ |
16 var Bubble = cr.ui.define('div'); | 16 var Bubble = cr.ui.define('div'); |
17 | 17 |
| 18 /** |
| 19 * Bubble attachment side. |
| 20 * @enum {string} |
| 21 */ |
| 22 Bubble.Attachment = { |
| 23 RIGHT: 'bubble-right', |
| 24 LEFT: 'bubble-left', |
| 25 TOP: 'bubble-top', |
| 26 BOTTOM: 'bubble-bottom' |
| 27 }; |
| 28 |
18 Bubble.prototype = { | 29 Bubble.prototype = { |
19 __proto__: HTMLDivElement.prototype, | 30 __proto__: HTMLDivElement.prototype, |
20 | 31 |
21 // Anchor element | 32 // Anchor element |
22 anchor_: undefined, | 33 anchor_: undefined, |
23 | 34 |
24 /** @inheritDoc */ | 35 /** @inheritDoc */ |
25 decorate: function() { | 36 decorate: function() { |
26 this.ownerDocument.addEventListener('click', | 37 this.ownerDocument.addEventListener('click', |
27 this.handleDocClick_.bind(this)); | 38 this.handleDocClick_.bind(this)); |
28 this.ownerDocument.addEventListener('keydown', | 39 this.ownerDocument.addEventListener('keydown', |
29 this.handleDocKeyDown_.bind(this)); | 40 this.handleDocKeyDown_.bind(this)); |
30 this.addEventListener('webkitTransitionEnd', | 41 this.addEventListener('webkitTransitionEnd', |
31 this.handleTransitionEnd_.bind(this)); | 42 this.handleTransitionEnd_.bind(this)); |
32 }, | 43 }, |
33 | 44 |
34 /** | 45 /** |
| 46 * Sets the attachment of the bubble. |
| 47 * @param {!Attachment} attachment Bubble attachment. |
| 48 */ |
| 49 setAttachment_: function (attachment) { |
| 50 for (var k in Bubble.Attachment) { |
| 51 var v = Bubble.Attachment[k]; |
| 52 this.classList[v == attachment ? 'add' : 'remove'](v); |
| 53 } |
| 54 }, |
| 55 |
| 56 /** |
35 * Shows the bubble for given anchor element. | 57 * Shows the bubble for given anchor element. |
36 * @param {number} x X position of bubble's reference point. | 58 * @param {!Object} pos Bubble position (left, top, right, bottom in px). |
37 * @param {number} y Y position of bubble's reference point. | |
38 * @param {HTMLElement} content Content to show in bubble. | 59 * @param {HTMLElement} content Content to show in bubble. |
39 * @public | 60 * @param {!Attachment} attachment Bubble attachment (on which side of the |
| 61 * specified position it should be displayed). |
| 62 * @private |
40 */ | 63 */ |
41 showContentAt: function(x, y, content) { | 64 showContentAt_: function(pos, content, attachment) { |
42 const ARROW_OFFSET = 14; | 65 for (var k in pos) { |
43 | 66 if (typeof pos[k] == 'number') |
44 var anchorX = x - ARROW_OFFSET; | 67 this.style[k] = pos[k] + 'px'; |
45 var anchorY = y; | 68 } |
46 | |
47 this.style.left = anchorX + 'px'; | |
48 this.style.top = anchorY + 'px'; | |
49 | |
50 this.innerHTML = ''; | 69 this.innerHTML = ''; |
51 this.appendChild(content); | 70 this.appendChild(content); |
| 71 this.setAttachment_(attachment); |
52 this.hidden = false; | 72 this.hidden = false; |
53 this.classList.remove('faded'); | 73 this.classList.remove('faded'); |
54 }, | 74 }, |
55 | 75 |
56 /** | 76 /** |
57 * Shows the bubble for given anchor element. | 77 * Shows the bubble for given anchor element. |
58 * @param {!HTMLElement} el Anchor element of the bubble. | 78 * @param {!HTMLElement} el Anchor element of the bubble. |
59 * @param {HTMLElement} content Content to show in bubble. | 79 * @param {HTMLElement} content Content to show in bubble. |
| 80 * @param {!Attachment} attachment Bubble attachment (on which side of the |
| 81 * element it should be displayed). |
| 82 * @param {number=} opt_offset Offset of the bubble attachment point from |
| 83 * left (for vertical attachment) or top (for horizontal attachment) |
| 84 * side of the element. If not specified, the bubble is positioned to |
| 85 * be aligned with the left/top side of the element but not farther than |
| 86 * half of it's weight/height. |
| 87 * @param {number=} opt_padding Optional padding of the bubble. |
60 * @public | 88 * @public |
61 */ | 89 */ |
62 showContentForElement: function(el, content) { | 90 showContentForElement: function(el, content, attachment, |
63 const HORIZONTAL_PADDING = 10; | 91 opt_offset, opt_padding) { |
64 const VERTICAL_PADDING = 5; | 92 const ARROW_OFFSET = 25; |
| 93 const DEFAULT_PADDING = 18; |
65 | 94 |
66 var elementOrigin = cr.ui.login.DisplayManager.getOffset(el); | 95 if (typeof opt_padding == 'undefined') |
67 var anchorX = elementOrigin.left + HORIZONTAL_PADDING; | 96 opt_padding = DEFAULT_PADDING; |
68 var anchorY = elementOrigin.top + el.offsetHeight + VERTICAL_PADDING; | 97 |
| 98 var origin = cr.ui.login.DisplayManager.getPosition(el); |
| 99 var offset = typeof opt_offset == 'undefined' ? |
| 100 [ Math.min(ARROW_OFFSET, el.offsetWidth/2), |
| 101 Math.min(ARROW_OFFSET, el.offsetHeight/2) ] : |
| 102 [ opt_offset, opt_offset ]; |
| 103 |
| 104 var pos = {}; |
| 105 if (isRTL()) { |
| 106 switch (attachment) { |
| 107 case Bubble.Attachment.TOP: |
| 108 pos.right = origin.right + offset[0] - ARROW_OFFSET; |
| 109 pos.bottom = origin.bottom + el.offsetHeight + opt_padding; |
| 110 break; |
| 111 case Bubble.Attachment.RIGHT: |
| 112 pos.top = origin.top + offset[1] - ARROW_OFFSET; |
| 113 pos.right = origin.right + el.offsetWidth + opt_padding; |
| 114 break; |
| 115 case Bubble.Attachment.BOTTOM: |
| 116 pos.right = origin.right + offset[0] - ARROW_OFFSET; |
| 117 pos.top = origin.top + el.offsetHeight + opt_padding; |
| 118 break; |
| 119 case Bubble.Attachment.LEFT: |
| 120 pos.top = origin.top + offset[1] - ARROW_OFFSET; |
| 121 pos.left = origin.left + el.offsetWidth + opt_padding; |
| 122 break; |
| 123 } |
| 124 } else { |
| 125 switch (attachment) { |
| 126 case Bubble.Attachment.TOP: |
| 127 pos.left = origin.left + offset[0] - ARROW_OFFSET; |
| 128 pos.bottom = origin.bottom + el.offsetHeight + opt_padding; |
| 129 break; |
| 130 case Bubble.Attachment.RIGHT: |
| 131 pos.top = origin.top + offset[1] - ARROW_OFFSET; |
| 132 pos.left = origin.left + el.offsetWidth + opt_padding; |
| 133 break; |
| 134 case Bubble.Attachment.BOTTOM: |
| 135 pos.left = origin.left + offset[0] - ARROW_OFFSET; |
| 136 pos.top = origin.top + el.offsetHeight + opt_padding; |
| 137 break; |
| 138 case Bubble.Attachment.LEFT: |
| 139 pos.top = origin.top + offset[1] - ARROW_OFFSET; |
| 140 pos.right = origin.right + el.offsetWidth + opt_padding; |
| 141 break; |
| 142 } |
| 143 } |
69 | 144 |
70 this.anchor_ = el; | 145 this.anchor_ = el; |
71 this.showContentAt(anchorX, anchorY, content); | 146 this.showContentAt_(pos, content, attachment); |
72 }, | 147 }, |
73 | 148 |
74 /** | 149 /** |
75 * Shows the bubble for given anchor element. | 150 * Shows the bubble for given anchor element. |
76 * @param {!HTMLElement} el Anchor element of the bubble. | 151 * @param {!HTMLElement} el Anchor element of the bubble. |
77 * @param {string} text Text content to show in bubble. | 152 * @param {string} text Text content to show in bubble. |
| 153 * @param {!Attachment} attachment Bubble attachment (on which side of the |
| 154 * element it should be displayed). |
| 155 * @param {number=} opt_offset Offset of the bubble attachment point from |
| 156 * left (for vertical attachment) or top (for horizontal attachment) |
| 157 * side of the element. If not specified, the bubble is positioned to |
| 158 * be aligned with the left/top side of the element but not farther than |
| 159 * half of it's weight/height. |
| 160 * @param {number=} opt_padding Optional padding of the bubble. |
78 * @public | 161 * @public |
79 */ | 162 */ |
80 showTextForElement: function(el, text) { | 163 showTextForElement: function(el, text, attachment, |
| 164 opt_offset, opt_padding) { |
81 var span = this.ownerDocument.createElement('span'); | 165 var span = this.ownerDocument.createElement('span'); |
82 span.textContent = text; | 166 span.textContent = text; |
83 this.showContentForElement(el, span); | 167 this.showContentForElement(el, span, attachment, opt_offset, opt_padding); |
84 }, | 168 }, |
85 | 169 |
86 /** | 170 /** |
87 * Hides the bubble. | 171 * Hides the bubble. |
88 */ | 172 */ |
89 hide: function() { | 173 hide: function() { |
90 if (!this.classList.contains('faded')) | 174 if (!this.classList.contains('faded')) |
91 this.classList.add('faded'); | 175 this.classList.add('faded'); |
92 }, | 176 }, |
93 | 177 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 handleDocKeyDown_: function(e) { | 213 handleDocKeyDown_: function(e) { |
130 if (!this.hidden) | 214 if (!this.hidden) |
131 this.hide(); | 215 this.hide(); |
132 } | 216 } |
133 }; | 217 }; |
134 | 218 |
135 return { | 219 return { |
136 Bubble: Bubble | 220 Bubble: Bubble |
137 }; | 221 }; |
138 }); | 222 }); |
OLD | NEW |