Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(545)

Side by Side Diff: chrome/browser/resources/options/language_options.js

Issue 7003007: Apply content-security-policy to the HTML options page. This is a (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 // TODO(kochi): Generalize the notification as a component and put it
6 // in js/cr/ui/notification.js .
7
8 cr.define('options', function() {
9 const OptionsPage = options.OptionsPage;
10 const LanguageList = options.LanguageList;
11
12 // Some input methods like Chinese Pinyin have config pages.
13 // This is the map of the input method names to their config page names.
14 const INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME = {
15 'hangul': 'languageHangul',
16 'mozc': 'languageMozc',
17 'mozc-chewing': 'languageChewing',
18 'mozc-dv': 'languageMozc',
19 'mozc-jp': 'languageMozc',
20 'pinyin': 'languagePinyin',
21 };
22
23 /////////////////////////////////////////////////////////////////////////////
24 // LanguageOptions class:
25
26 /**
27 * Encapsulated handling of ChromeOS language options page.
28 * @constructor
29 */
30 function LanguageOptions(model) {
31 OptionsPage.call(this, 'languages', templateData.languagePageTabTitle,
32 'languagePage');
33 }
34
35 cr.addSingletonGetter(LanguageOptions);
36
37 // Inherit LanguageOptions from OptionsPage.
38 LanguageOptions.prototype = {
39 __proto__: OptionsPage.prototype,
40
41 /**
42 * Initializes LanguageOptions page.
43 * Calls base class implementation to starts preference initialization.
44 */
45 initializePage: function() {
46 OptionsPage.prototype.initializePage.call(this);
47
48 var languageOptionsList = $('language-options-list');
49 LanguageList.decorate(languageOptionsList);
50
51 languageOptionsList.addEventListener('change',
52 this.handleLanguageOptionsListChange_.bind(this));
53 languageOptionsList.addEventListener('save',
54 this.handleLanguageOptionsListSave_.bind(this));
55
56 this.addEventListener('visibleChange',
57 this.handleVisibleChange_.bind(this));
58
59 if (cr.isChromeOS) {
60 this.initializeInputMethodList_();
61 this.initializeLanguageCodeToInputMethodIdsMap_();
62 }
63 Preferences.getInstance().addEventListener(this.spellCheckDictionaryPref,
64 this.handleSpellCheckDictionaryPrefChange_.bind(this));
65
66 // Set up add button.
67 $('language-options-add-button').onclick = function(e) {
68 // Add the language without showing the overlay if it's specified in
69 // the URL hash (ex. lang_add=ja). Used for automated testing.
70 var match = document.location.hash.match(/\blang_add=([\w-]+)/);
71 if (match) {
72 var addLanguageCode = match[1];
73 $('language-options-list').addLanguage(addLanguageCode);
74 } else {
75 OptionsPage.navigateToPage('addLanguage');
76 }
77 };
78
79 if (cr.isChromeOS) {
80 // Listen to user clicks on the add language list.
81 var addLanguageList = $('add-language-overlay-language-list');
82 addLanguageList.addEventListener('click',
83 this.handleAddLanguageListClick_.bind(this));
84 } else {
85 // Listen to add language dialog ok button.
86 var addLanguageOkButton = $('add-language-overlay-ok-button');
87 addLanguageOkButton.addEventListener('click',
88 this.handleAddLanguageOkButtonClick_.bind(this));
89
90 // Show experimental features if enabled.
91 if (templateData.experimentalSpellCheckFeatures == 'true') {
92 $('auto-spell-correction-option').classList.remove('hidden');
93 }
94 }
95 },
96
97 // The preference is a CSV string that describes preload engines
98 // (i.e. active input methods).
99 preloadEnginesPref: 'settings.language.preload_engines',
100 // The list of preload engines, like ['mozc', 'pinyin'].
101 preloadEngines_: [],
102 // The preference is a string that describes the spell check
103 // dictionary language, like "en-US".
104 spellCheckDictionaryPref: 'spellcheck.dictionary',
105 spellCheckDictionary_: "",
106 // The map of language code to input method IDs, like:
107 // {'ja': ['mozc', 'mozc-jp'], 'zh-CN': ['pinyin'], ...}
108 languageCodeToInputMethodIdsMap_: {},
109
110 /**
111 * Initializes the input method list.
112 */
113 initializeInputMethodList_: function() {
114 var inputMethodList = $('language-options-input-method-list');
115 var inputMethodListData = templateData.inputMethodList;
116
117 // Add all input methods, but make all of them invisible here. We'll
118 // change the visibility in handleLanguageOptionsListChange_() based
119 // on the selected language. Note that we only have less than 100
120 // input methods, so creating DOM nodes at once here should be ok.
121 for (var i = 0; i < inputMethodListData.length; i++) {
122 var inputMethod = inputMethodListData[i];
123 var input = document.createElement('input');
124 input.type = 'checkbox';
125 input.inputMethodId = inputMethod.id;
126 // Listen to user clicks.
127 input.addEventListener('click',
128 this.handleCheckboxClick_.bind(this));
129 var label = document.createElement('label');
130 label.appendChild(input);
131 // Adding a space between the checkbox and the text. This is a bit
132 // dirty, but we rely on a space character for all other checkboxes.
133 label.appendChild(document.createTextNode(
134 ' ' + inputMethod.displayName));
135 label.style.display = 'none';
136 label.languageCodeSet = inputMethod.languageCodeSet;
137 // Add the configure button if the config page is present for this
138 // input method.
139 if (inputMethod.id in INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME) {
140 var pageName = INPUT_METHOD_ID_TO_CONFIG_PAGE_NAME[inputMethod.id];
141 var button = this.createConfigureInputMethodButton_(inputMethod.id,
142 pageName);
143 label.appendChild(button);
144 }
145
146 inputMethodList.appendChild(label);
147 }
148 // Listen to pref change once the input method list is initialized.
149 Preferences.getInstance().addEventListener(this.preloadEnginesPref,
150 this.handlePreloadEnginesPrefChange_.bind(this));
151 },
152
153 /**
154 * Creates a configure button for the given input method ID.
155 * @param {string} inputMethodId Input method ID (ex. "pinyin").
156 * @param {string} pageName Name of the config page (ex. "languagePinyin").
157 * @private
158 */
159 createConfigureInputMethodButton_: function(inputMethodId, pageName) {
160 var button = document.createElement('button');
161 button.textContent = localStrings.getString('configure');
162 button.onclick = function(e) {
163 // Prevent the default action (i.e. changing the checked property
164 // of the checkbox). The button click here should not be handled
165 // as checkbox click.
166 e.preventDefault();
167 chrome.send('inputMethodOptionsOpen', [inputMethodId]);
168 OptionsPage.navigateToPage(pageName);
169 }
170 return button;
171 },
172
173 /**
174 * Handles OptionsPage's visible property change event.
175 * @param {Event} e Property change event.
176 * @private
177 */
178 handleVisibleChange_: function(e) {
179 if (this.visible) {
180 $('language-options-list').redraw();
181 chrome.send('languageOptionsOpen');
182 }
183 },
184
185 /**
186 * Handles languageOptionsList's change event.
187 * @param {Event} e Change event.
188 * @private
189 */
190 handleLanguageOptionsListChange_: function(e) {
191 var languageOptionsList = $('language-options-list');
192 var languageCode = languageOptionsList.getSelectedLanguageCode();
193 // Select the language if it's specified in the URL hash (ex. lang=ja).
194 // Used for automated testing.
195 var match = document.location.hash.match(/\blang=([\w-]+)/);
196 if (match) {
197 var specifiedLanguageCode = match[1];
198 if (languageOptionsList.selectLanguageByCode(specifiedLanguageCode)) {
199 languageCode = specifiedLanguageCode;
200 }
201 }
202 this.updateSelectedLanguageName_(languageCode);
203 if (cr.isWindows || cr.isChromeOS)
204 this.updateUiLanguageButton_(languageCode);
205 this.updateSpellCheckLanguageButton_(languageCode);
206 if (cr.isChromeOS)
207 this.updateInputMethodList_(languageCode);
208 this.updateLanguageListInAddLanguageOverlay_();
209 },
210
211 /**
212 * Handles languageOptionsList's save event.
213 * @param {Event} e Save event.
214 * @private
215 */
216 handleLanguageOptionsListSave_: function(e) {
217 if (cr.isChromeOS) {
218 // Sort the preload engines per the saved languages before save.
219 this.preloadEngines_ = this.sortPreloadEngines_(this.preloadEngines_);
220 this.savePreloadEnginesPref_();
221 }
222 },
223
224 /**
225 * Sorts preloadEngines_ by languageOptionsList's order.
226 * @param {Array} preloadEngines List of preload engines.
227 * @return {Array} Returns sorted preloadEngines.
228 * @private
229 */
230 sortPreloadEngines_: function(preloadEngines) {
231 // For instance, suppose we have two languages and associated input
232 // methods:
233 //
234 // - Korean: hangul
235 // - Chinese: pinyin
236 //
237 // The preloadEngines preference should look like "hangul,pinyin".
238 // If the user reverse the order, the preference should be reorderd
239 // to "pinyin,hangul".
240 var languageOptionsList = $('language-options-list');
241 var languageCodes = languageOptionsList.getLanguageCodes();
242
243 // Convert the list into a dictonary for simpler lookup.
244 var preloadEngineSet = {};
245 for (var i = 0; i < preloadEngines.length; i++) {
246 preloadEngineSet[preloadEngines[i]] = true;
247 }
248
249 // Create the new preload engine list per the language codes.
250 var newPreloadEngines = [];
251 for (var i = 0; i < languageCodes.length; i++) {
252 var languageCode = languageCodes[i];
253 var inputMethodIds = this.languageCodeToInputMethodIdsMap_[
254 languageCode];
255 // Check if we have active input methods associated with the language.
256 for (var j = 0; j < inputMethodIds.length; j++) {
257 var inputMethodId = inputMethodIds[j];
258 if (inputMethodId in preloadEngineSet) {
259 // If we have, add it to the new engine list.
260 newPreloadEngines.push(inputMethodId);
261 // And delete it from the set. This is necessary as one input
262 // method can be associated with more than one language thus
263 // we should avoid having duplicates in the new list.
264 delete preloadEngineSet[inputMethodId];
265 }
266 }
267 }
268
269 return newPreloadEngines;
270 },
271
272 /**
273 * Initializes the map of language code to input method IDs.
274 * @private
275 */
276 initializeLanguageCodeToInputMethodIdsMap_: function() {
277 var inputMethodList = templateData.inputMethodList;
278 for (var i = 0; i < inputMethodList.length; i++) {
279 var inputMethod = inputMethodList[i];
280 for (var languageCode in inputMethod.languageCodeSet) {
281 if (languageCode in this.languageCodeToInputMethodIdsMap_) {
282 this.languageCodeToInputMethodIdsMap_[languageCode].push(
283 inputMethod.id);
284 } else {
285 this.languageCodeToInputMethodIdsMap_[languageCode] =
286 [inputMethod.id];
287 }
288 }
289 }
290 },
291
292 /**
293 * Updates the currently selected language name.
294 * @param {string} languageCode Language code (ex. "fr").
295 * @private
296 */
297 updateSelectedLanguageName_: function(languageCode) {
298 var languageDisplayName = LanguageList.getDisplayNameFromLanguageCode(
299 languageCode);
300 var languageNativeDisplayName =
301 LanguageList.getNativeDisplayNameFromLanguageCode(languageCode);
302 // If the native name is different, add it.
303 if (languageDisplayName != languageNativeDisplayName) {
304 languageDisplayName += ' - ' + languageNativeDisplayName;
305 }
306 // Update the currently selected language name.
307 $('language-options-language-name').textContent = languageDisplayName;
308 },
309
310 /**
311 * Updates the UI language button.
312 * @param {string} languageCode Language code (ex. "fr").
313 * @private
314 */
315 updateUiLanguageButton_: function(languageCode) {
316 var uiLanguageButton = $('language-options-ui-language-button');
317 // Check if the language code matches the current UI language.
318 if (languageCode == templateData.currentUiLanguageCode) {
319 // If it matches, the button just says that the UI language is
320 // currently in use.
321 uiLanguageButton.textContent =
322 localStrings.getString('is_displayed_in_this_language');
323 // Make it look like a text label.
324 uiLanguageButton.className = 'text-button';
325 // Remove the event listner.
326 uiLanguageButton.onclick = undefined;
327 } else if (languageCode in templateData.uiLanguageCodeSet) {
328 // If the language is supported as UI language, users can click on
329 // the button to change the UI language.
330 if (cr.commandLine.options['--bwsi']) {
331 // In the guest mode for ChromeOS, changing UI language does not make
332 // sense because it does not take effect after browser restart.
333 uiLanguageButton.className = 'hidden';
334 } else {
335 uiLanguageButton.textContent =
336 localStrings.getString('display_in_this_language');
337 uiLanguageButton.className = '';
338 // Send the change request to Chrome.
339 uiLanguageButton.onclick = function(e) {
340 chrome.send('uiLanguageChange', [languageCode]);
341 }
342 }
343 if (cr.isChromeOS) {
344 $('language-options-ui-restart-button').onclick = function(e) {
345 chrome.send('uiLanguageRestart');
346 }
347 }
348 } else {
349 // If the language is not supported as UI language, the button
350 // just says that Chromium OS cannot be displayed in this language.
351 uiLanguageButton.textContent =
352 localStrings.getString('cannot_be_displayed_in_this_language');
353 uiLanguageButton.className = 'text-button';
354 uiLanguageButton.onclick = undefined;
355 }
356 uiLanguageButton.style.display = 'block';
357 $('language-options-ui-notification-bar').style.display = 'none';
358 },
359
360 /**
361 * Updates the spell check language button.
362 * @param {string} languageCode Language code (ex. "fr").
363 * @private
364 */
365 updateSpellCheckLanguageButton_: function(languageCode) {
366 var spellCheckLanguageButton = $(
367 'language-options-spell-check-language-button');
368 // Check if the language code matches the current spell check language.
369 if (languageCode == this.spellCheckDictionary_) {
370 // If it matches, the button just says that the spell check language is
371 // currently in use.
372 spellCheckLanguageButton.textContent =
373 localStrings.getString('is_used_for_spell_checking');
374 // Make it look like a text label.
375 spellCheckLanguageButton.className = 'text-button';
376 // Remove the event listner.
377 spellCheckLanguageButton.onclick = undefined;
378 } else if (languageCode in templateData.spellCheckLanguageCodeSet) {
379 // If the language is supported as spell check language, users can
380 // click on the button to change the spell check language.
381 spellCheckLanguageButton.textContent =
382 localStrings.getString('use_this_for_spell_checking');
383 spellCheckLanguageButton.className = '';
384 spellCheckLanguageButton.languageCode = languageCode;
385 // Add an event listner to the click event.
386 spellCheckLanguageButton.addEventListener('click',
387 this.handleSpellCheckLanguageButtonClick_.bind(this));
388 } else {
389 // If the language is not supported as spell check language, the
390 // button just says that this language cannot be used for spell
391 // checking.
392 spellCheckLanguageButton.textContent =
393 localStrings.getString('cannot_be_used_for_spell_checking');
394 spellCheckLanguageButton.className = 'text-button';
395 spellCheckLanguageButton.onclick = undefined;
396 }
397 spellCheckLanguageButton.style.display = 'block';
398 $('language-options-ui-notification-bar').style.display = 'none';
399 },
400
401 /**
402 * Updates the input method list.
403 * @param {string} languageCode Language code (ex. "fr").
404 * @private
405 */
406 updateInputMethodList_: function(languageCode) {
407 // Give one of the checkboxes or buttons focus, if it's specified in the
408 // URL hash (ex. focus=mozc). Used for automated testing.
409 var focusInputMethodId = -1;
410 var match = document.location.hash.match(/\bfocus=([\w:-]+)\b/);
411 if (match) {
412 focusInputMethodId = match[1];
413 }
414 // Change the visibility of the input method list. Input methods that
415 // matches |languageCode| will become visible.
416 var inputMethodList = $('language-options-input-method-list');
417 var labels = inputMethodList.querySelectorAll('label');
418 for (var i = 0; i < labels.length; i++) {
419 var label = labels[i];
420 if (languageCode in label.languageCodeSet) {
421 label.style.display = 'block';
422 var input = label.childNodes[0];
423 // Give it focus if the ID matches.
424 if (input.inputMethodId == focusInputMethodId) {
425 input.focus();
426 }
427 } else {
428 label.style.display = 'none';
429 }
430 }
431
432 if (focusInputMethodId == 'add') {
433 $('language-options-add-button').focus();
434 }
435 },
436
437 /**
438 * Updates the language list in the add language overlay.
439 * @param {string} languageCode Language code (ex. "fr").
440 * @private
441 */
442 updateLanguageListInAddLanguageOverlay_: function(languageCode) {
443 // Change the visibility of the language list in the add language
444 // overlay. Languages that are already active will become invisible,
445 // so that users don't add the same language twice.
446 var languageOptionsList = $('language-options-list');
447 var languageCodes = languageOptionsList.getLanguageCodes();
448 var languageCodeSet = {};
449 for (var i = 0; i < languageCodes.length; i++) {
450 languageCodeSet[languageCodes[i]] = true;
451 }
452 var addLanguageList = $('add-language-overlay-language-list');
453 var lis = addLanguageList.querySelectorAll('li');
454 for (var i = 0; i < lis.length; i++) {
455 // The first child button knows the language code.
456 var button = lis[i].childNodes[0];
457 if (button.languageCode in languageCodeSet) {
458 lis[i].style.display = 'none';
459 } else {
460 lis[i].style.display = 'block';
461 }
462 }
463 },
464
465 /**
466 * Handles preloadEnginesPref change.
467 * @param {Event} e Change event.
468 * @private
469 */
470 handlePreloadEnginesPrefChange_: function(e) {
471 var value = e.value.value;
472 this.preloadEngines_ = this.filterBadPreloadEngines_(value.split(','));
473 this.updateCheckboxesFromPreloadEngines_();
474 $('language-options-list').updateDeletable();
475 },
476
477 /**
478 * Handles input method checkbox's click event.
479 * @param {Event} e Click event.
480 * @private
481 */
482 handleCheckboxClick_ : function(e) {
483 var checkbox = e.target;
484 if (this.preloadEngines_.length == 1 && !checkbox.checked) {
485 // Don't allow disabling the last input method.
486 this.showNotification_(
487 localStrings.getString('please_add_another_input_method'),
488 localStrings.getString('ok_button'));
489 checkbox.checked = true;
490 return;
491 }
492 if (checkbox.checked) {
493 chrome.send('inputMethodEnable', [checkbox.inputMethodId]);
494 } else {
495 chrome.send('inputMethodDisable', [checkbox.inputMethodId]);
496 }
497 this.updatePreloadEnginesFromCheckboxes_();
498 this.preloadEngines_ = this.sortPreloadEngines_(this.preloadEngines_);
499 this.savePreloadEnginesPref_();
500 },
501
502 /**
503 * Handles add language list's click event.
504 * @param {Event} e Click event.
505 */
506 handleAddLanguageListClick_ : function(e) {
507 var languageOptionsList = $('language-options-list');
508 var languageCode = e.target.languageCode;
509 // languageCode can be undefined, if click was made on some random
510 // place in the overlay, rather than a button. Ignore it.
511 if (!languageCode) {
512 return;
513 }
514 languageOptionsList.addLanguage(languageCode);
515 var inputMethodIds = this.languageCodeToInputMethodIdsMap_[languageCode];
516 // Enable the first input method for the language added.
517 if (inputMethodIds && inputMethodIds[0] &&
518 // Don't add the input method it's already present. This can
519 // happen if the same input method is shared among multiple
520 // languages (ex. English US keyboard is used for English US and
521 // Filipino).
522 this.preloadEngines_.indexOf(inputMethodIds[0]) == -1) {
523 this.preloadEngines_.push(inputMethodIds[0]);
524 this.updateCheckboxesFromPreloadEngines_();
525 this.savePreloadEnginesPref_();
526 }
527 OptionsPage.closeOverlay();
528 },
529
530 /**
531 * Handles add language dialog ok button.
532 */
533 handleAddLanguageOkButtonClick_ : function() {
534 var languagesSelect = $('add-language-overlay-language-list');
535 var selectedIndex = languagesSelect.selectedIndex;
536 if (selectedIndex >= 0) {
537 var selection = languagesSelect.options[selectedIndex];
538 $('language-options-list').addLanguage(String(selection.value));
539 OptionsPage.closeOverlay();
540 }
541 },
542
543 /**
544 * Checks if languageCode is deletable or not.
545 * @param {String} languageCode the languageCode to check for deletability.
546 */
547 languageIsDeletable: function(languageCode) {
548 // Don't allow removing the language if it's as UI language.
549 if (languageCode == templateData.currentUiLanguageCode)
550 return false;
551 return (!cr.isChromeOS ||
552 this.canDeleteLanguage_(languageCode));
553 },
554
555 /**
556 * Handles spellCheckDictionaryPref change.
557 * @param {Event} e Change event.
558 * @private
559 */
560 handleSpellCheckDictionaryPrefChange_: function(e) {
561 var languageCode = e.value.value
562 this.spellCheckDictionary_ = languageCode;
563 var languageOptionsList = $('language-options-list');
564 var selectedLanguageCode = languageOptionsList.getSelectedLanguageCode();
565 this.updateSpellCheckLanguageButton_(selectedLanguageCode);
566 },
567
568 /**
569 * Handles spellCheckLanguageButton click.
570 * @param {Event} e Click event.
571 * @private
572 */
573 handleSpellCheckLanguageButtonClick_: function(e) {
574 var languageCode = e.target.languageCode;
575 // Save the preference.
576 Preferences.setStringPref(this.spellCheckDictionaryPref,
577 languageCode);
578 chrome.send('spellCheckLanguageChange', [languageCode]);
579 },
580
581 /**
582 * Checks whether it's possible to remove the language specified by
583 * languageCode and returns true if possible. This function returns false
584 * if the removal causes the number of preload engines to be zero.
585 *
586 * @param {string} languageCode Language code (ex. "fr").
587 * @return {boolean} Returns true on success.
588 * @private
589 */
590 canDeleteLanguage_: function(languageCode) {
591 // First create the set of engines to be removed from input methods
592 // associated with the language code.
593 var enginesToBeRemovedSet = {};
594 var inputMethodIds = this.languageCodeToInputMethodIdsMap_[languageCode];
595 for (var i = 0; i < inputMethodIds.length; i++) {
596 enginesToBeRemovedSet[inputMethodIds[i]] = true;
597 }
598
599 // Then eliminate engines that are also used for other active languages.
600 // For instance, if "xkb:us::eng" is used for both English and Filipino.
601 var languageCodes = $('language-options-list').getLanguageCodes();
602 for (var i = 0; i < languageCodes.length; i++) {
603 // Skip the target language code.
604 if (languageCodes[i] == languageCode) {
605 continue;
606 }
607 // Check if input methods used in this language are included in
608 // enginesToBeRemovedSet. If so, eliminate these from the set, so
609 // we don't remove this time.
610 var inputMethodIdsForAnotherLanguage =
611 this.languageCodeToInputMethodIdsMap_[languageCodes[i]];
612 for (var j = 0; j < inputMethodIdsForAnotherLanguage.length; j++) {
613 var inputMethodId = inputMethodIdsForAnotherLanguage[j];
614 if (inputMethodId in enginesToBeRemovedSet) {
615 delete enginesToBeRemovedSet[inputMethodId];
616 }
617 }
618 }
619
620 // Update the preload engine list with the to-be-removed set.
621 var newPreloadEngines = [];
622 for (var i = 0; i < this.preloadEngines_.length; i++) {
623 if (!(this.preloadEngines_[i] in enginesToBeRemovedSet)) {
624 newPreloadEngines.push(this.preloadEngines_[i]);
625 }
626 }
627 // Don't allow this operation if it causes the number of preload
628 // engines to be zero.
629 return (newPreloadEngines.length > 0);
630 },
631
632 /**
633 * Saves the preload engines preference.
634 * @private
635 */
636 savePreloadEnginesPref_: function() {
637 Preferences.setStringPref(this.preloadEnginesPref,
638 this.preloadEngines_.join(','));
639 },
640
641 /**
642 * Updates the checkboxes in the input method list from the preload
643 * engines preference.
644 * @private
645 */
646 updateCheckboxesFromPreloadEngines_: function() {
647 // Convert the list into a dictonary for simpler lookup.
648 var dictionary = {};
649 for (var i = 0; i < this.preloadEngines_.length; i++) {
650 dictionary[this.preloadEngines_[i]] = true;
651 }
652
653 var inputMethodList = $('language-options-input-method-list');
654 var checkboxes = inputMethodList.querySelectorAll('input');
655 for (var i = 0; i < checkboxes.length; i++) {
656 checkboxes[i].checked = (checkboxes[i].inputMethodId in dictionary);
657 }
658 },
659
660 /**
661 * Updates the preload engines preference from the checkboxes in the
662 * input method list.
663 * @private
664 */
665 updatePreloadEnginesFromCheckboxes_: function() {
666 this.preloadEngines_ = [];
667 var inputMethodList = $('language-options-input-method-list');
668 var checkboxes = inputMethodList.querySelectorAll('input');
669 for (var i = 0; i < checkboxes.length; i++) {
670 if (checkboxes[i].checked) {
671 this.preloadEngines_.push(checkboxes[i].inputMethodId);
672 }
673 }
674 var languageOptionsList = $('language-options-list');
675 languageOptionsList.updateDeletable();
676 },
677
678 /**
679 * Filters bad preload engines in case bad preload engines are
680 * stored in the preference. Removes duplicates as well.
681 * @param {Array} preloadEngines List of preload engines.
682 * @private
683 */
684 filterBadPreloadEngines_: function(preloadEngines) {
685 // Convert the list into a dictonary for simpler lookup.
686 var dictionary = {};
687 for (var i = 0; i < templateData.inputMethodList.length; i++) {
688 dictionary[templateData.inputMethodList[i].id] = true;
689 }
690
691 var filteredPreloadEngines = [];
692 var seen = {};
693 for (var i = 0; i < preloadEngines.length; i++) {
694 // Check if the preload engine is present in the
695 // dictionary, and not duplicate. Otherwise, skip it.
696 if (preloadEngines[i] in dictionary && !(preloadEngines[i] in seen)) {
697 filteredPreloadEngines.push(preloadEngines[i]);
698 seen[preloadEngines[i]] = true;
699 }
700 }
701 return filteredPreloadEngines;
702 },
703
704 // TODO(kochi): This is an adapted copy from new_new_tab.js.
705 // If this will go as final UI, refactor this to share the component with
706 // new new tab page.
707 /**
708 * Shows notification
709 * @private
710 */
711 notificationTimeout_: null,
712 showNotification_ : function(text, actionText, opt_delay) {
713 var notificationElement = $('notification');
714 var actionLink = notificationElement.querySelector('.link-color');
715 var delay = opt_delay || 10000;
716
717 function show() {
718 window.clearTimeout(this.notificationTimeout_);
719 notificationElement.classList.add('show');
720 document.body.classList.add('notification-shown');
721 }
722
723 function hide() {
724 window.clearTimeout(this.notificationTimeout_);
725 notificationElement.classList.remove('show');
726 document.body.classList.remove('notification-shown');
727 // Prevent tabbing to the hidden link.
728 actionLink.tabIndex = -1;
729 // Setting tabIndex to -1 only prevents future tabbing to it. If,
730 // however, the user switches window or a tab and then moves back to
731 // this tab the element may gain focus. We therefore make sure that we
732 // blur the element so that the element focus is not restored when
733 // coming back to this window.
734 actionLink.blur();
735 }
736
737 function delayedHide() {
738 this.notificationTimeout_ = window.setTimeout(hide, delay);
739 }
740
741 notificationElement.firstElementChild.textContent = text;
742 actionLink.textContent = actionText;
743
744 actionLink.onclick = hide;
745 actionLink.onkeydown = function(e) {
746 if (e.keyIdentifier == 'Enter') {
747 hide();
748 }
749 };
750 notificationElement.onmouseover = show;
751 notificationElement.onmouseout = delayedHide;
752 actionLink.onfocus = show;
753 actionLink.onblur = delayedHide;
754 // Enable tabbing to the link now that it is shown.
755 actionLink.tabIndex = 0;
756
757 show();
758 delayedHide();
759 }
760 };
761
762 /**
763 * Chrome callback for when the UI language preference is saved.
764 */
765 LanguageOptions.uiLanguageSaved = function() {
766 $('language-options-ui-language-button').style.display = 'none';
767 $('language-options-ui-notification-bar').style.display = 'block';
768 };
769
770 // Export
771 return {
772 LanguageOptions: LanguageOptions
773 };
774 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698