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
3 // found in the LICENSE file.
5 cr
.define('options', function() {
6 /** @const */ var Page
= cr
.ui
.pageManager
.Page
;
7 /** @const */ var PageManager
= cr
.ui
.pageManager
.PageManager
;
8 /** @const */ var ArrayDataModel
= cr
.ui
.ArrayDataModel
;
11 * AutofillEditAddressOverlay class
12 * Encapsulated handling of the 'Add Page' overlay page.
14 * @extends {cr.ui.pageManager.Page}
16 function AutofillEditAddressOverlay() {
17 Page
.call(this, 'autofillEditAddress',
18 loadTimeData
.getString('autofillEditAddressTitle'),
19 'autofill-edit-address-overlay');
22 cr
.addSingletonGetter(AutofillEditAddressOverlay
);
24 AutofillEditAddressOverlay
.prototype = {
25 __proto__
: Page
.prototype,
28 * The GUID of the loaded address.
34 * The BCP 47 language code for the layout of input fields.
40 * The saved field values for the address. For example, if the user changes
41 * from United States to Switzerland, then the State field will be hidden
42 * and its value will be stored here. If the user changes back to United
43 * States, then the State field will be restored to its previous value, as
44 * stored in this object.
47 savedFieldValues_
: {},
50 initializePage: function() {
51 Page
.prototype.initializePage
.call(this);
54 $('autofill-edit-address-cancel-button').onclick = function(event
) {
55 self
.dismissOverlay_();
58 // TODO(jhawkins): Investigate other possible solutions.
59 $('autofill-edit-address-apply-button').onclick = function(event
) {
60 // Blur active element to ensure that pending changes are committed.
61 if (document
.activeElement
)
62 document
.activeElement
.blur();
64 self
.dismissOverlay_();
68 this.populateCountryList_();
69 this.rebuildInputFields_(
70 loadTimeData
.getValue('autofillDefaultCountryComponents'));
72 loadTimeData
.getString('autofillDefaultCountryLanguageCode');
73 this.connectInputEvents_();
74 this.setInputFields_({});
75 this.getCountrySwitcher_().onchange = function(event
) {
76 self
.countryChanged_();
81 * Specifically catch the situations in which the overlay is cancelled
82 * externally (e.g. by pressing <Esc>), so that the input fields and
83 * GUID can be properly cleared.
86 handleCancel: function() {
87 this.dismissOverlay_();
91 * Clears any uncommitted input, resets the stored GUID and dismisses the
95 dismissOverlay_: function() {
96 this.setInputFields_({});
97 this.inputFieldChanged_();
99 this.languageCode_
= '';
100 this.savedInputFields_
= {};
101 PageManager
.closeOverlay();
105 * @return {Element} The element used to switch countries.
108 getCountrySwitcher_: function() {
109 return this.pageDiv
.querySelector('[field=country]');
113 * Returns all text input elements.
114 * @return {!NodeList} The text input elements.
117 getTextFields_: function() {
118 return this.pageDiv
.querySelectorAll('textarea[field], input[field]');
122 * Creates a map from type => value for all text fields.
123 * @return {Object} The mapping from field names to values.
126 getInputFields_: function() {
127 var address
= {country
: this.getCountrySwitcher_().value
};
129 var fields
= this.getTextFields_();
130 for (var i
= 0; i
< fields
.length
; i
++) {
131 address
[fields
[i
].getAttribute('field')] = fields
[i
].value
;
138 * Sets the value of each input field according to |address|.
139 * @param {Object} address The object with values to use.
142 setInputFields_: function(address
) {
143 this.getCountrySwitcher_().value
= address
.country
|| '';
145 var fields
= this.getTextFields_();
146 for (var i
= 0; i
< fields
.length
; i
++) {
147 fields
[i
].value
= address
[fields
[i
].getAttribute('field')] || '';
152 * Aggregates the values in the input fields into an array and sends the
153 * array to the Autofill handler.
156 saveAddress_: function() {
157 var inputFields
= this.getInputFields_();
160 inputFields
['fullName'] || [],
161 inputFields
['companyName'] || '',
162 inputFields
['addrLines'] || '',
163 inputFields
['dependentLocality'] || '',
164 inputFields
['city'] || '',
165 inputFields
['state'] || '',
166 inputFields
['postalCode'] || '',
167 inputFields
['sortingCode'] || '',
168 inputFields
['country'] || loadTimeData
.getString('defaultCountryCode'),
169 inputFields
['phone'] || [],
170 inputFields
['email'] || [],
173 chrome
.send('setAddress', address
);
175 // If the GUID is empty, this form is being used to add a new address,
176 // rather than edit an existing one.
177 if (!this.guid_
.length
) {
178 chrome
.send('coreOptionsUserMetricsAction',
179 ['Options_AutofillAddressAdded']);
184 * Connects each input field to the inputFieldChanged_() method that enables
185 * or disables the 'Ok' button based on whether all the fields are empty or
189 connectInputEvents_: function() {
190 var fields
= this.getTextFields_();
191 for (var i
= 0; i
< fields
.length
; i
++) {
192 fields
[i
].oninput
= this.inputFieldChanged_
.bind(this);
197 * Disables the 'Ok' button if all of the fields are empty.
200 inputFieldChanged_: function() {
201 var disabled
= !this.getCountrySwitcher_().value
;
203 var fields
= this.getTextFields_();
204 for (var i
= 0; i
< fields
.length
; i
++) {
205 if (fields
[i
].value
) {
212 $('autofill-edit-address-apply-button').disabled
= disabled
;
216 * Updates the address fields appropriately for the selected country.
219 countryChanged_: function() {
220 var countryCode
= this.getCountrySwitcher_().value
;
222 chrome
.send('loadAddressEditorComponents', [countryCode
]);
224 this.inputFieldChanged_();
228 * Populates the country <select> list.
231 populateCountryList_: function() {
232 var countryList
= loadTimeData
.getValue('autofillCountrySelectList');
234 // Add the countries to the country <select>.
235 var countrySelect
= this.getCountrySwitcher_();
236 // Add an empty option.
237 countrySelect
.appendChild(new Option('', ''));
238 for (var i
= 0; i
< countryList
.length
; i
++) {
239 var option
= new Option(countryList
[i
].name
,
240 countryList
[i
].value
);
241 option
.disabled
= countryList
[i
].value
== 'separator';
242 countrySelect
.appendChild(option
);
247 * Called to prepare the overlay when a new address is being added.
250 prepForNewAddress_: function() {
251 // Focus the first element.
252 this.pageDiv
.querySelector('input').focus();
256 * Loads the address data from |address|, sets the input fields based on
257 * this data, and stores the GUID and language code of the address.
258 * @param {!Object} address Lots of info about an address from the browser.
261 loadAddress_: function(address
) {
262 this.rebuildInputFields_(address
.components
);
263 this.setInputFields_(address
);
264 this.inputFieldChanged_();
265 this.connectInputEvents_();
266 this.guid_
= address
.guid
;
267 this.languageCode_
= address
.languageCode
;
271 * Takes a snapshot of the input values, clears the input values, loads the
272 * address input layout from |input.components|, restores the input values
273 * from snapshot, and stores the |input.languageCode| for the address.
274 * @param {{languageCode: string, components: Array<Array<Object>>}} input
275 * Info about how to layout inputs fields in this dialog.
278 loadAddressComponents_: function(input
) {
279 var inputFields
= this.getInputFields_();
280 for (var fieldName
in inputFields
) {
281 if (inputFields
.hasOwnProperty(fieldName
))
282 this.savedFieldValues_
[fieldName
] = inputFields
[fieldName
];
284 this.rebuildInputFields_(input
.components
);
285 this.setInputFields_(this.savedFieldValues_
);
286 this.inputFieldChanged_();
287 this.connectInputEvents_();
288 this.languageCode_
= input
.languageCode
;
292 * Clears address inputs and rebuilds the input fields according to
294 * @param {Array<Array<Object>>} components A list of information about
298 rebuildInputFields_: function(components
) {
299 var content
= $('autofill-edit-address-fields');
300 content
.innerHTML
= '';
302 var customInputElements
= {addrLines
: 'textarea'};
304 for (var i
in components
) {
305 var row
= document
.createElement('div');
306 row
.classList
.add('input-group', 'settings-row');
307 content
.appendChild(row
);
309 for (var j
in components
[i
]) {
310 if (components
[i
][j
].field
== 'country')
313 var fieldContainer
= document
.createElement('label');
314 row
.appendChild(fieldContainer
);
316 var fieldName
= document
.createElement('div');
317 fieldName
.textContent
= components
[i
][j
].name
;
318 fieldContainer
.appendChild(fieldName
);
320 var input
= document
.createElement(
321 customInputElements
[components
[i
][j
].field
] || 'input');
322 input
.setAttribute('field', components
[i
][j
].field
);
323 input
.classList
.add(components
[i
][j
].length
);
324 fieldContainer
.appendChild(input
);
330 AutofillEditAddressOverlay
.prepForNewAddress = function() {
331 AutofillEditAddressOverlay
.getInstance().prepForNewAddress_();
334 AutofillEditAddressOverlay
.loadAddress = function(address
) {
335 AutofillEditAddressOverlay
.getInstance().loadAddress_(address
);
338 AutofillEditAddressOverlay
.loadAddressComponents = function(input
) {
339 AutofillEditAddressOverlay
.getInstance().loadAddressComponents_(input
);
342 AutofillEditAddressOverlay
.setTitle = function(title
) {
343 $('autofill-address-title').textContent
= title
;
348 AutofillEditAddressOverlay
: AutofillEditAddressOverlay