OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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('cr.ui.dialogs', function() { | |
6 | |
7 function BaseDialog(parentNode) { | |
8 this.parentNode_ = parentNode; | |
9 this.document_ = parentNode.ownerDocument; | |
10 | |
11 // The DOM element from the dialog which should receive focus when the | |
12 // dialog is first displayed. | |
13 this.initialFocusElement_ = null; | |
14 | |
15 // The DOM element from the parent which had focus before we were displayed, | |
16 // so we can restore it when we're hidden. | |
17 this.previousActiveElement_ = null; | |
18 | |
19 this.initDom_(); | |
20 } | |
21 | |
22 /** | |
23 * Default text for Ok and Cancel buttons. | |
24 * | |
25 * Clients should override these with localized labels. | |
26 */ | |
27 BaseDialog.OK_LABEL = 'Ok'; | |
28 BaseDialog.CANCEL_LABEL = 'Cancel'; | |
29 | |
30 /** | |
31 * Number of miliseconds animation is expected to take, plus some margin for | |
32 * error. | |
33 */ | |
34 BaseDialog.ANIMATE_STABLE_DURATION = 500; | |
35 | |
36 BaseDialog.prototype.initDom_ = function() { | |
37 var doc = this.document_; | |
38 this.container_ = doc.createElement('div'); | |
39 this.container_.className = 'cr-dialog-container'; | |
40 this.container_.addEventListener('keydown', | |
41 this.onContainerKeyDown_.bind(this)); | |
42 | |
43 this.frame_ = doc.createElement('div'); | |
44 this.frame_.className = 'cr-dialog-frame'; | |
45 this.container_.appendChild(this.frame_); | |
46 | |
47 this.text_ = doc.createElement('div'); | |
48 this.text_.className = 'cr-dialog-text'; | |
49 this.frame_.appendChild(this.text_); | |
50 | |
51 var buttons = doc.createElement('div'); | |
52 buttons.className = 'cr-dialog-buttons'; | |
53 this.frame_.appendChild(buttons); | |
54 | |
55 this.cancelButton_ = doc.createElement('button'); | |
56 this.cancelButton_.className = 'cr-dialog-cancel'; | |
57 this.cancelButton_.textContent = BaseDialog.CANCEL_LABEL; | |
58 this.cancelButton_.addEventListener('click', | |
59 this.onCancelClick_.bind(this)); | |
60 buttons.appendChild(this.cancelButton_); | |
61 | |
62 this.okButton_ = doc.createElement('button'); | |
63 this.okButton_.className = 'cr-dialog-ok'; | |
64 this.okButton_.textContent = BaseDialog.OK_LABEL; | |
65 this.okButton_.addEventListener('click', this.onOkClick_.bind(this)); | |
66 buttons.appendChild(this.okButton_); | |
67 | |
68 this.initialFocusElement_ = this.okButton_; | |
69 }; | |
70 | |
71 BaseDialog.prototype.onOk_ = null; | |
72 BaseDialog.prototype.onCancel_ = null; | |
73 | |
74 BaseDialog.prototype.onContainerKeyDown_ = function(event) { | |
75 switch (event.keyCode) { | |
76 case 13: // Enter | |
77 if (!this.okButton_.disabled) { | |
78 this.onOkClick_(event); | |
79 event.preventDefault(); | |
80 } | |
81 return; | |
82 | |
83 case 27: // Escape | |
84 if (!this.cancelButton_.disabled) { | |
85 this.onCancelClick_(event); | |
86 event.preventDefault(); | |
87 } | |
88 return; | |
89 } | |
90 }; | |
91 | |
92 BaseDialog.prototype.onOkClick_ = function(event) { | |
93 this.hide(); | |
94 if (this.onOk_) | |
95 this.onOk_(); | |
96 }; | |
97 | |
98 BaseDialog.prototype.onCancelClick_ = function(event) { | |
99 this.hide(); | |
100 if (this.onCancel_) | |
101 this.onCancel_(); | |
102 }; | |
103 | |
104 BaseDialog.prototype.setOkLabel = function(label) { | |
105 this.okButton_.textContent = label; | |
106 }; | |
107 | |
108 BaseDialog.prototype.setCancelLabel = function(label) { | |
109 this.cancelButton_.textContent = label; | |
110 }; | |
111 | |
112 BaseDialog.prototype.show = function(message, onOk, onCancel, onShow) { | |
113 this.previousActiveElement_ = this.document_.activeElement; | |
114 this.parentNode_.appendChild(this.container_); | |
115 | |
116 this.onOk_ = onOk; | |
117 this.onCancel_ = onCancel; | |
118 | |
119 this.text_.textContent = message; | |
120 | |
121 var top = (this.document_.body.clientHeight - | |
122 this.frame_.clientHeight) / 2; | |
123 var left = (this.document_.body.clientWidth - | |
124 this.frame_.clientWidth) / 2; | |
125 | |
126 // Disable transitions so that we can set the initial position of the | |
127 // dialog right away. | |
128 this.frame_.style.webkitTransitionProperty = ''; | |
129 this.frame_.style.top = (top - 50) + 'px'; | |
130 this.frame_.style.left = (left + 10) + 'px'; | |
131 | |
132 var self = this; | |
133 setTimeout(function () { | |
134 // Note that we control the opacity of the *container*, but the top/left | |
135 // of the *frame*. | |
136 self.container_.style.opacity = '1'; | |
137 self.frame_.style.top = top + 'px'; | |
138 self.frame_.style.left = left + 'px'; | |
139 self.frame_.style.webkitTransitionProperty = 'left, top'; | |
140 self.initialFocusElement_.focus(); | |
141 setTimeout(function() { | |
142 if (onShow) | |
143 onShow(); | |
144 }, BaseDialog.ANIMATE_STABLE_DURATION); | |
145 }, 0); | |
146 }; | |
147 | |
148 BaseDialog.prototype.hide = function(onHide) { | |
149 // Note that we control the opacity of the *container*, but the top/left | |
150 // of the *frame*. | |
151 this.container_.style.opacity = '0'; | |
152 this.frame_.style.top = (parseInt(this.frame_.style.top) + 50) + 'px'; | |
153 this.frame_.style.left = (parseInt(this.frame_.style.left) - 10) + 'px'; | |
154 | |
155 if (this.previousActiveElement_) { | |
156 this.previousActiveElement_.focus(); | |
157 } else { | |
158 this.document_.body.focus(); | |
159 } | |
160 | |
161 var self = this; | |
162 setTimeout(function() { | |
163 // Wait until the transition is done before removing the dialog. | |
164 self.parentNode_.removeChild(self.container_); | |
165 if (onHide) | |
166 onHide(); | |
167 }, BaseDialog.ANIMATE_STABLE_DURATION); | |
168 }; | |
169 | |
170 /** | |
171 * AlertDialog contains just a message and an ok button. | |
172 */ | |
173 function AlertDialog(parentNode) { | |
174 BaseDialog.apply(this, [parentNode]); | |
175 this.cancelButton_.style.display = 'none'; | |
176 } | |
177 | |
178 AlertDialog.prototype = {__proto__: BaseDialog.prototype}; | |
179 | |
180 AlertDialog.prototype.show = function(message, onOk, onShow) { | |
181 return BaseDialog.prototype.show.apply(this, [message, onOk, onOk, onShow]); | |
182 }; | |
183 | |
184 /** | |
185 * ConfirmDialog contains a message, an ok button, and a cancel button. | |
186 */ | |
187 function ConfirmDialog(parentNode) { | |
188 BaseDialog.apply(this, [parentNode]); | |
189 } | |
190 | |
191 ConfirmDialog.prototype = {__proto__: BaseDialog.prototype}; | |
192 | |
193 /** | |
194 * PromptDialog contains a message, a text input, an ok button, and a | |
195 * cancel button. | |
196 */ | |
197 function PromptDialog(parentNode) { | |
198 BaseDialog.apply(this, [parentNode]); | |
199 this.input_ = this.document_.createElement('input'); | |
200 this.input_.setAttribute('type', 'text'); | |
201 this.input_.addEventListener('focus', this.onInputFocus.bind(this)); | |
202 this.initialFocusElement_ = this.input_; | |
203 this.frame_.insertBefore(this.input_, this.text_.nextSibling); | |
204 } | |
205 | |
206 PromptDialog.prototype = {__proto__: BaseDialog.prototype}; | |
207 | |
208 PromptDialog.prototype.onInputFocus = function(event) { | |
209 this.input_.select(); | |
210 }; | |
211 | |
212 PromptDialog.prototype.show = function(message, defaultValue, onOk, onCancel, | |
213 onShow) { | |
214 this.input_.value = defaultValue || ''; | |
215 return BaseDialog.prototype.show.apply(this, [message, onOk, onCancel, | |
216 onShow]); | |
217 }; | |
218 | |
219 PromptDialog.prototype.getValue = function() { | |
220 return this.input_.value; | |
221 }; | |
222 | |
223 PromptDialog.prototype.onOkClick_ = function(event) { | |
224 this.hide(); | |
225 if (this.onOk_) | |
226 this.onOk_(this.getValue()); | |
227 }; | |
228 | |
229 return { | |
230 BaseDialog: BaseDialog, | |
231 AlertDialog: AlertDialog, | |
232 ConfirmDialog: ConfirmDialog, | |
233 PromptDialog: PromptDialog | |
234 }; | |
235 }); | |
OLD | NEW |