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

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

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

Powered by Google App Engine
This is Rietveld 408576698