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

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 uiLanguageButton.textContent =
331 localStrings.getString('display_in_this_language');
332 uiLanguageButton.className = '';
333 // Send the change request to Chrome.
334 uiLanguageButton.onclick = function(e) {
335 chrome.send('uiLanguageChange', [languageCode]);
336 }
337 if (cr.isChromeOS) {
338 $('language-options-ui-restart-button').onclick = function(e) {
339 chrome.send('uiLanguageRestart');
340 }
341 }
342 } else {
343 // If the language is not supported as UI language, the button
344 // just says that Chromium OS cannot be displayed in this language.
345 uiLanguageButton.textContent =
346 localStrings.getString('cannot_be_displayed_in_this_language');
347 uiLanguageButton.className = 'text-button';
348 uiLanguageButton.onclick = undefined;
349 }
350 uiLanguageButton.style.display = 'block';
351 $('language-options-ui-notification-bar').style.display = 'none';
352 },
353
354 /**
355 * Updates the spell check language button.
356 * @param {string} languageCode Language code (ex. "fr").
357 * @private
358 */
359 updateSpellCheckLanguageButton_: function(languageCode) {
360 var spellCheckLanguageButton = $(
361 'language-options-spell-check-language-button');
362 // Check if the language code matches the current spell check language.
363 if (languageCode == this.spellCheckDictionary_) {
364 // If it matches, the button just says that the spell check language is
365 // currently in use.
366 spellCheckLanguageButton.textContent =
367 localStrings.getString('is_used_for_spell_checking');
368 // Make it look like a text label.
369 spellCheckLanguageButton.className = 'text-button';
370 // Remove the event listner.
371 spellCheckLanguageButton.onclick = undefined;
372 } else if (languageCode in templateData.spellCheckLanguageCodeSet) {
373 // If the language is supported as spell check language, users can
374 // click on the button to change the spell check language.
375 spellCheckLanguageButton.textContent =
376 localStrings.getString('use_this_for_spell_checking');
377 spellCheckLanguageButton.className = '';
378 spellCheckLanguageButton.languageCode = languageCode;
379 // Add an event listner to the click event.
380 spellCheckLanguageButton.addEventListener('click',
381 this.handleSpellCheckLanguageButtonClick_.bind(this));
382 } else {
383 // If the language is not supported as spell check language, the
384 // button just says that this language cannot be used for spell
385 // checking.
386 spellCheckLanguageButton.textContent =
387 localStrings.getString('cannot_be_used_for_spell_checking');
388 spellCheckLanguageButton.className = 'text-button';
389 spellCheckLanguageButton.onclick = undefined;
390 }
391 spellCheckLanguageButton.style.display = 'block';
392 $('language-options-ui-notification-bar').style.display = 'none';
393 },
394
395 /**
396 * Updates the input method list.
397 * @param {string} languageCode Language code (ex. "fr").
398 * @private
399 */
400 updateInputMethodList_: function(languageCode) {
401 // Give one of the checkboxes or buttons focus, if it's specified in the
402 // URL hash (ex. focus=mozc). Used for automated testing.
403 var focusInputMethodId = -1;
404 var match = document.location.hash.match(/\bfocus=([\w:-]+)\b/);
405 if (match) {
406 focusInputMethodId = match[1];
407 }
408 // Change the visibility of the input method list. Input methods that
409 // matches |languageCode| will become visible.
410 var inputMethodList = $('language-options-input-method-list');
411 var labels = inputMethodList.querySelectorAll('label');
412 for (var i = 0; i < labels.length; i++) {
413 var label = labels[i];
414 if (languageCode in label.languageCodeSet) {
415 label.style.display = 'block';
416 var input = label.childNodes[0];
417 // Give it focus if the ID matches.
418 if (input.inputMethodId == focusInputMethodId) {
419 input.focus();
420 }
421 } else {
422 label.style.display = 'none';
423 }
424 }
425
426 if (focusInputMethodId == 'add') {
427 $('language-options-add-button').focus();
428 }
429 },
430
431 /**
432 * Updates the language list in the add language overlay.
433 * @param {string} languageCode Language code (ex. "fr").
434 * @private
435 */
436 updateLanguageListInAddLanguageOverlay_: function(languageCode) {
437 // Change the visibility of the language list in the add language
438 // overlay. Languages that are already active will become invisible,
439 // so that users don't add the same language twice.
440 var languageOptionsList = $('language-options-list');
441 var languageCodes = languageOptionsList.getLanguageCodes();
442 var languageCodeSet = {};
443 for (var i = 0; i < languageCodes.length; i++) {
444 languageCodeSet[languageCodes[i]] = true;
445 }
446 var addLanguageList = $('add-language-overlay-language-list');
447 var lis = addLanguageList.querySelectorAll('li');
448 for (var i = 0; i < lis.length; i++) {
449 // The first child button knows the language code.
450 var button = lis[i].childNodes[0];
451 if (button.languageCode in languageCodeSet) {
452 lis[i].style.display = 'none';
453 } else {
454 lis[i].style.display = 'block';
455 }
456 }
457 },
458
459 /**
460 * Handles preloadEnginesPref change.
461 * @param {Event} e Change event.
462 * @private
463 */
464 handlePreloadEnginesPrefChange_: function(e) {
465 var value = e.value.value;
466 this.preloadEngines_ = this.filterBadPreloadEngines_(value.split(','));
467 this.updateCheckboxesFromPreloadEngines_();
468 $('language-options-list').updateDeletable();
469 },
470
471 /**
472 * Handles input method checkbox's click event.
473 * @param {Event} e Click event.
474 * @private
475 */
476 handleCheckboxClick_ : function(e) {
477 var checkbox = e.target;
478 if (this.preloadEngines_.length == 1 && !checkbox.checked) {
479 // Don't allow disabling the last input method.
480 this.showNotification_(
481 localStrings.getString('please_add_another_input_method'),
482 localStrings.getString('ok_button'));
483 checkbox.checked = true;
484 return;
485 }
486 if (checkbox.checked) {
487 chrome.send('inputMethodEnable', [checkbox.inputMethodId]);
488 } else {
489 chrome.send('inputMethodDisable', [checkbox.inputMethodId]);
490 }
491 this.updatePreloadEnginesFromCheckboxes_();
492 this.preloadEngines_ = this.sortPreloadEngines_(this.preloadEngines_);
493 this.savePreloadEnginesPref_();
494 },
495
496 /**
497 * Handles add language list's click event.
498 * @param {Event} e Click event.
499 */
500 handleAddLanguageListClick_ : function(e) {
501 var languageOptionsList = $('language-options-list');
502 var languageCode = e.target.languageCode;
503 // languageCode can be undefined, if click was made on some random
504 // place in the overlay, rather than a button. Ignore it.
505 if (!languageCode) {
506 return;
507 }
508 languageOptionsList.addLanguage(languageCode);
509 var inputMethodIds = this.languageCodeToInputMethodIdsMap_[languageCode];
510 // Enable the first input method for the language added.
511 if (inputMethodIds && inputMethodIds[0] &&
512 // Don't add the input method it's already present. This can
513 // happen if the same input method is shared among multiple
514 // languages (ex. English US keyboard is used for English US and
515 // Filipino).
516 this.preloadEngines_.indexOf(inputMethodIds[0]) == -1) {
517 this.preloadEngines_.push(inputMethodIds[0]);
518 this.updateCheckboxesFromPreloadEngines_();
519 this.savePreloadEnginesPref_();
520 }
521 OptionsPage.closeOverlay();
522 },
523
524 /**
525 * Handles add language dialog ok button.
526 */
527 handleAddLanguageOkButtonClick_ : function() {
528 var languagesSelect = $('add-language-overlay-language-list');
529 var selectedIndex = languagesSelect.selectedIndex;
530 if (selectedIndex >= 0) {
531 var selection = languagesSelect.options[selectedIndex];
532 $('language-options-list').addLanguage(String(selection.value));
533 OptionsPage.closeOverlay();
534 }
535 },
536
537 /**
538 * Checks if languageCode is deletable or not.
539 * @param {String} languageCode the languageCode to check for deletability.
540 */
541 languageIsDeletable: function(languageCode) {
542 // Don't allow removing the language if it's as UI language.
543 if (languageCode == templateData.currentUiLanguageCode)
544 return false;
545 return (!cr.isChromeOS ||
546 this.canDeleteLanguage_(languageCode));
547 },
548
549 /**
550 * Handles spellCheckDictionaryPref change.
551 * @param {Event} e Change event.
552 * @private
553 */
554 handleSpellCheckDictionaryPrefChange_: function(e) {
555 var languageCode = e.value.value
556 this.spellCheckDictionary_ = languageCode;
557 var languageOptionsList = $('language-options-list');
558 var selectedLanguageCode = languageOptionsList.getSelectedLanguageCode();
559 this.updateSpellCheckLanguageButton_(selectedLanguageCode);
560 },
561
562 /**
563 * Handles spellCheckLanguageButton click.
564 * @param {Event} e Click event.
565 * @private
566 */
567 handleSpellCheckLanguageButtonClick_: function(e) {
568 var languageCode = e.target.languageCode;
569 // Save the preference.
570 Preferences.setStringPref(this.spellCheckDictionaryPref,
571 languageCode);
572 chrome.send('spellCheckLanguageChange', [languageCode]);
573 },
574
575 /**
576 * Checks whether it's possible to remove the language specified by
577 * languageCode and returns true if possible. This function returns false
578 * if the removal causes the number of preload engines to be zero.
579 *
580 * @param {string} languageCode Language code (ex. "fr").
581 * @return {boolean} Returns true on success.
582 * @private
583 */
584 canDeleteLanguage_: function(languageCode) {
585 // First create the set of engines to be removed from input methods
586 // associated with the language code.
587 var enginesToBeRemovedSet = {};
588 var inputMethodIds = this.languageCodeToInputMethodIdsMap_[languageCode];
589 for (var i = 0; i < inputMethodIds.length; i++) {
590 enginesToBeRemovedSet[inputMethodIds[i]] = true;
591 }
592
593 // Then eliminate engines that are also used for other active languages.
594 // For instance, if "xkb:us::eng" is used for both English and Filipino.
595 var languageCodes = $('language-options-list').getLanguageCodes();
596 for (var i = 0; i < languageCodes.length; i++) {
597 // Skip the target language code.
598 if (languageCodes[i] == languageCode) {
599 continue;
600 }
601 // Check if input methods used in this language are included in
602 // enginesToBeRemovedSet. If so, eliminate these from the set, so
603 // we don't remove this time.
604 var inputMethodIdsForAnotherLanguage =
605 this.languageCodeToInputMethodIdsMap_[languageCodes[i]];
606 for (var j = 0; j < inputMethodIdsForAnotherLanguage.length; j++) {
607 var inputMethodId = inputMethodIdsForAnotherLanguage[j];
608 if (inputMethodId in enginesToBeRemovedSet) {
609 delete enginesToBeRemovedSet[inputMethodId];
610 }
611 }
612 }
613
614 // Update the preload engine list with the to-be-removed set.
615 var newPreloadEngines = [];
616 for (var i = 0; i < this.preloadEngines_.length; i++) {
617 if (!(this.preloadEngines_[i] in enginesToBeRemovedSet)) {
618 newPreloadEngines.push(this.preloadEngines_[i]);
619 }
620 }
621 // Don't allow this operation if it causes the number of preload
622 // engines to be zero.
623 return (newPreloadEngines.length > 0);
624 },
625
626 /**
627 * Saves the preload engines preference.
628 * @private
629 */
630 savePreloadEnginesPref_: function() {
631 Preferences.setStringPref(this.preloadEnginesPref,
632 this.preloadEngines_.join(','));
633 },
634
635 /**
636 * Updates the checkboxes in the input method list from the preload
637 * engines preference.
638 * @private
639 */
640 updateCheckboxesFromPreloadEngines_: function() {
641 // Convert the list into a dictonary for simpler lookup.
642 var dictionary = {};
643 for (var i = 0; i < this.preloadEngines_.length; i++) {
644 dictionary[this.preloadEngines_[i]] = true;
645 }
646
647 var inputMethodList = $('language-options-input-method-list');
648 var checkboxes = inputMethodList.querySelectorAll('input');
649 for (var i = 0; i < checkboxes.length; i++) {
650 checkboxes[i].checked = (checkboxes[i].inputMethodId in dictionary);
651 }
652 },
653
654 /**
655 * Updates the preload engines preference from the checkboxes in the
656 * input method list.
657 * @private
658 */
659 updatePreloadEnginesFromCheckboxes_: function() {
660 this.preloadEngines_ = [];
661 var inputMethodList = $('language-options-input-method-list');
662 var checkboxes = inputMethodList.querySelectorAll('input');
663 for (var i = 0; i < checkboxes.length; i++) {
664 if (checkboxes[i].checked) {
665 this.preloadEngines_.push(checkboxes[i].inputMethodId);
666 }
667 }
668 var languageOptionsList = $('language-options-list');
669 languageOptionsList.updateDeletable();
670 },
671
672 /**
673 * Filters bad preload engines in case bad preload engines are
674 * stored in the preference. Removes duplicates as well.
675 * @param {Array} preloadEngines List of preload engines.
676 * @private
677 */
678 filterBadPreloadEngines_: function(preloadEngines) {
679 // Convert the list into a dictonary for simpler lookup.
680 var dictionary = {};
681 for (var i = 0; i < templateData.inputMethodList.length; i++) {
682 dictionary[templateData.inputMethodList[i].id] = true;
683 }
684
685 var filteredPreloadEngines = [];
686 var seen = {};
687 for (var i = 0; i < preloadEngines.length; i++) {
688 // Check if the preload engine is present in the
689 // dictionary, and not duplicate. Otherwise, skip it.
690 if (preloadEngines[i] in dictionary && !(preloadEngines[i] in seen)) {
691 filteredPreloadEngines.push(preloadEngines[i]);
692 seen[preloadEngines[i]] = true;
693 }
694 }
695 return filteredPreloadEngines;
696 },
697
698 // TODO(kochi): This is an adapted copy from new_new_tab.js.
699 // If this will go as final UI, refactor this to share the component with
700 // new new tab page.
701 /**
702 * Shows notification
703 * @private
704 */
705 notificationTimeout_: null,
706 showNotification_ : function(text, actionText, opt_delay) {
707 var notificationElement = $('notification');
708 var actionLink = notificationElement.querySelector('.link-color');
709 var delay = opt_delay || 10000;
710
711 function show() {
712 window.clearTimeout(this.notificationTimeout_);
713 notificationElement.classList.add('show');
714 document.body.classList.add('notification-shown');
715 }
716
717 function hide() {
718 window.clearTimeout(this.notificationTimeout_);
719 notificationElement.classList.remove('show');
720 document.body.classList.remove('notification-shown');
721 // Prevent tabbing to the hidden link.
722 actionLink.tabIndex = -1;
723 // Setting tabIndex to -1 only prevents future tabbing to it. If,
724 // however, the user switches window or a tab and then moves back to
725 // this tab the element may gain focus. We therefore make sure that we
726 // blur the element so that the element focus is not restored when
727 // coming back to this window.
728 actionLink.blur();
729 }
730
731 function delayedHide() {
732 this.notificationTimeout_ = window.setTimeout(hide, delay);
733 }
734
735 notificationElement.firstElementChild.textContent = text;
736 actionLink.textContent = actionText;
737
738 actionLink.onclick = hide;
739 actionLink.onkeydown = function(e) {
740 if (e.keyIdentifier == 'Enter') {
741 hide();
742 }
743 };
744 notificationElement.onmouseover = show;
745 notificationElement.onmouseout = delayedHide;
746 actionLink.onfocus = show;
747 actionLink.onblur = delayedHide;
748 // Enable tabbing to the link now that it is shown.
749 actionLink.tabIndex = 0;
750
751 show();
752 delayedHide();
753 }
754 };
755
756 /**
757 * Chrome callback for when the UI language preference is saved.
758 */
759 LanguageOptions.uiLanguageSaved = function() {
760 $('language-options-ui-language-button').style.display = 'none';
761 $('language-options-ui-notification-bar').style.display = 'block';
762 };
763
764 // Export
765 return {
766 LanguageOptions: LanguageOptions
767 };
768 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698