| Index: chrome/browser/resources/options/language_list.js
|
| ===================================================================
|
| --- chrome/browser/resources/options/language_list.js (revision 84868)
|
| +++ chrome/browser/resources/options/language_list.js (working copy)
|
| @@ -1,483 +0,0 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -cr.define('options', function() {
|
| - const ArrayDataModel = cr.ui.ArrayDataModel;
|
| - const DeletableItem = options.DeletableItem;
|
| - const DeletableItemList = options.DeletableItemList;
|
| - const List = cr.ui.List;
|
| - const ListItem = cr.ui.ListItem;
|
| - const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
|
| -
|
| - /**
|
| - * Creates a new Language list item.
|
| - * @param {String} languageCode the languageCode.
|
| - * @constructor
|
| - * @extends {DeletableItem.ListItem}
|
| - */
|
| - function LanguageListItem(languageCode) {
|
| - var el = cr.doc.createElement('li');
|
| - el.__proto__ = LanguageListItem.prototype;
|
| - el.languageCode_ = languageCode;
|
| - el.decorate();
|
| - return el;
|
| - };
|
| -
|
| - LanguageListItem.prototype = {
|
| - __proto__: DeletableItem.prototype,
|
| -
|
| - /**
|
| - * The language code of this language.
|
| - * @type {String}
|
| - * @private
|
| - */
|
| - languageCode_: null,
|
| -
|
| - /** @inheritDoc */
|
| - decorate: function() {
|
| - DeletableItem.prototype.decorate.call(this);
|
| -
|
| - var languageCode = this.languageCode_;
|
| - var languageOptions = options.LanguageOptions.getInstance();
|
| - this.deletable = languageOptions.languageIsDeletable(languageCode);
|
| - this.languageCode = languageCode;
|
| - this.contentElement.textContent =
|
| - LanguageList.getDisplayNameFromLanguageCode(languageCode);
|
| - this.title =
|
| - LanguageList.getNativeDisplayNameFromLanguageCode(languageCode);
|
| - this.draggable = true;
|
| - },
|
| - };
|
| -
|
| - /**
|
| - * Creates a new language list.
|
| - * @param {Object=} opt_propertyBag Optional properties.
|
| - * @constructor
|
| - * @extends {cr.ui.List}
|
| - */
|
| - var LanguageList = cr.ui.define('list');
|
| -
|
| - /**
|
| - * Gets display name from the given language code.
|
| - * @param {string} languageCode Language code (ex. "fr").
|
| - */
|
| - LanguageList.getDisplayNameFromLanguageCode = function(languageCode) {
|
| - // Build the language code to display name dictionary at first time.
|
| - if (!this.languageCodeToDisplayName_) {
|
| - this.languageCodeToDisplayName_ = {};
|
| - var languageList = templateData.languageList;
|
| - for (var i = 0; i < languageList.length; i++) {
|
| - var language = languageList[i];
|
| - this.languageCodeToDisplayName_[language.code] = language.displayName;
|
| - }
|
| - }
|
| -
|
| - return this.languageCodeToDisplayName_[languageCode];
|
| - }
|
| -
|
| - /**
|
| - * Gets native display name from the given language code.
|
| - * @param {string} languageCode Language code (ex. "fr").
|
| - */
|
| - LanguageList.getNativeDisplayNameFromLanguageCode = function(languageCode) {
|
| - // Build the language code to display name dictionary at first time.
|
| - if (!this.languageCodeToNativeDisplayName_) {
|
| - this.languageCodeToNativeDisplayName_ = {};
|
| - var languageList = templateData.languageList;
|
| - for (var i = 0; i < languageList.length; i++) {
|
| - var language = languageList[i];
|
| - this.languageCodeToNativeDisplayName_[language.code] =
|
| - language.nativeDisplayName;
|
| - }
|
| - }
|
| -
|
| - return this.languageCodeToNativeDisplayName_[languageCode];
|
| - }
|
| -
|
| - /**
|
| - * Returns true if the given language code is valid.
|
| - * @param {string} languageCode Language code (ex. "fr").
|
| - */
|
| - LanguageList.isValidLanguageCode = function(languageCode) {
|
| - // Having the display name for the language code means that the
|
| - // language code is valid.
|
| - if (LanguageList.getDisplayNameFromLanguageCode(languageCode)) {
|
| - return true;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - LanguageList.prototype = {
|
| - __proto__: DeletableItemList.prototype,
|
| -
|
| - // The list item being dragged.
|
| - draggedItem: null,
|
| - // The drop position information: "below" or "above".
|
| - dropPos: null,
|
| - // The preference is a CSV string that describes preferred languages
|
| - // in Chrome OS. The language list is used for showing the language
|
| - // list in "Language and Input" options page.
|
| - preferredLanguagesPref: 'settings.language.preferred_languages',
|
| - // The preference is a CSV string that describes accept languages used
|
| - // for content negotiation. To be more precise, the list will be used
|
| - // in "Accept-Language" header in HTTP requests.
|
| - acceptLanguagesPref: 'intl.accept_languages',
|
| -
|
| - /** @inheritDoc */
|
| - decorate: function() {
|
| - DeletableItemList.prototype.decorate.call(this);
|
| - this.selectionModel = new ListSingleSelectionModel;
|
| -
|
| - // HACK(arv): http://crbug.com/40902
|
| - window.addEventListener('resize', this.redraw.bind(this));
|
| -
|
| - // Listen to pref change.
|
| - if (cr.isChromeOS) {
|
| - Preferences.getInstance().addEventListener(this.preferredLanguagesPref,
|
| - this.handlePreferredLanguagesPrefChange_.bind(this));
|
| - } else {
|
| - Preferences.getInstance().addEventListener(this.acceptLanguagesPref,
|
| - this.handleAcceptLanguagesPrefChange_.bind(this));
|
| - }
|
| -
|
| - // Listen to drag and drop events.
|
| - this.addEventListener('dragstart', this.handleDragStart_.bind(this));
|
| - this.addEventListener('dragenter', this.handleDragEnter_.bind(this));
|
| - this.addEventListener('dragover', this.handleDragOver_.bind(this));
|
| - this.addEventListener('drop', this.handleDrop_.bind(this));
|
| - this.addEventListener('dragleave', this.handleDragLeave_.bind(this));
|
| - },
|
| -
|
| - createItem: function(languageCode) {
|
| - return new LanguageListItem(languageCode);
|
| - },
|
| -
|
| - /*
|
| - * For each item, determines whether it's deletable.
|
| - */
|
| - updateDeletable: function() {
|
| - for (var i = 0; i < this.items.length; ++i) {
|
| - var item = this.getListItemByIndex(i);
|
| - var languageCode = item.languageCode;
|
| - var languageOptions = options.LanguageOptions.getInstance();
|
| - item.deletable = languageOptions.languageIsDeletable(languageCode);
|
| - }
|
| - },
|
| -
|
| - /*
|
| - * Adds a language to the language list.
|
| - * @param {string} languageCode language code (ex. "fr").
|
| - */
|
| - addLanguage: function(languageCode) {
|
| - // It shouldn't happen but ignore the language code if it's
|
| - // null/undefined, or already present.
|
| - if (!languageCode || this.dataModel.indexOf(languageCode) >= 0) {
|
| - return;
|
| - }
|
| - this.dataModel.push(languageCode);
|
| - // Select the last item, which is the language added.
|
| - this.selectionModel.selectedIndex = this.dataModel.length - 1;
|
| -
|
| - this.savePreference_();
|
| - },
|
| -
|
| - /*
|
| - * Gets the language codes of the currently listed languages.
|
| - */
|
| - getLanguageCodes: function() {
|
| - return this.dataModel.slice();
|
| - },
|
| -
|
| - /*
|
| - * Gets the language code of the selected language.
|
| - */
|
| - getSelectedLanguageCode: function() {
|
| - return this.selectedItem;
|
| - },
|
| -
|
| - /*
|
| - * Selects the language by the given language code.
|
| - * @returns {boolean} True if the operation is successful.
|
| - */
|
| - selectLanguageByCode: function(languageCode) {
|
| - var index = this.dataModel.indexOf(languageCode);
|
| - if (index >= 0) {
|
| - this.selectionModel.selectedIndex = index;
|
| - return true;
|
| - }
|
| - return false;
|
| - },
|
| -
|
| - /** @inheritDoc */
|
| - deleteItemAtIndex: function(index) {
|
| - if (index >= 0) {
|
| - this.dataModel.splice(index, 1);
|
| - // Once the selected item is removed, there will be no selected item.
|
| - // Select the item pointed by the lead index.
|
| - index = this.selectionModel.leadIndex;
|
| - this.savePreference_();
|
| - }
|
| - return index;
|
| - },
|
| -
|
| - /*
|
| - * Computes the target item of drop event.
|
| - * @param {Event} e The drop or dragover event.
|
| - * @private
|
| - */
|
| - getTargetFromDropEvent_ : function(e) {
|
| - var target = e.target;
|
| - // e.target may be an inner element of the list item
|
| - while (target != null && !(target instanceof ListItem)) {
|
| - target = target.parentNode;
|
| - }
|
| - return target;
|
| - },
|
| -
|
| - /*
|
| - * Handles the dragstart event.
|
| - * @param {Event} e The dragstart event.
|
| - * @private
|
| - */
|
| - handleDragStart_: function(e) {
|
| - var target = e.target;
|
| - // ListItem should be the only draggable element type in the page,
|
| - // but just in case.
|
| - if (target instanceof ListItem) {
|
| - this.draggedItem = target;
|
| - e.dataTransfer.effectAllowed = 'move';
|
| - // We need to put some kind of data in the drag or it will be
|
| - // ignored. Use the display name in case the user drags to a text
|
| - // field or the desktop.
|
| - e.dataTransfer.setData('text/plain', target.title);
|
| - }
|
| - },
|
| -
|
| - /*
|
| - * Handles the dragenter event.
|
| - * @param {Event} e The dragenter event.
|
| - * @private
|
| - */
|
| - handleDragEnter_: function(e) {
|
| - e.preventDefault();
|
| - },
|
| -
|
| - /*
|
| - * Handles the dragover event.
|
| - * @param {Event} e The dragover event.
|
| - * @private
|
| - */
|
| - handleDragOver_: function(e) {
|
| - var dropTarget = this.getTargetFromDropEvent_(e);
|
| - // Determines whether the drop target is to accept the drop.
|
| - // The drop is only successful on another ListItem.
|
| - if (!(dropTarget instanceof ListItem) ||
|
| - dropTarget == this.draggedItem) {
|
| - this.hideDropMarker_();
|
| - return;
|
| - }
|
| - // Compute the drop postion. Should we move the dragged item to
|
| - // below or above the drop target?
|
| - var rect = dropTarget.getBoundingClientRect();
|
| - var dy = e.clientY - rect.top;
|
| - var yRatio = dy / rect.height;
|
| - var dropPos = yRatio <= .5 ? 'above' : 'below';
|
| - this.dropPos = dropPos;
|
| - this.showDropMarker_(dropTarget, dropPos);
|
| - e.preventDefault();
|
| - },
|
| -
|
| - /*
|
| - * Handles the drop event.
|
| - * @param {Event} e The drop event.
|
| - * @private
|
| - */
|
| - handleDrop_: function(e) {
|
| - var dropTarget = this.getTargetFromDropEvent_(e);
|
| - this.hideDropMarker_();
|
| -
|
| - // Delete the language from the original position.
|
| - var languageCode = this.draggedItem.languageCode;
|
| - var originalIndex = this.dataModel.indexOf(languageCode);
|
| - this.dataModel.splice(originalIndex, 1);
|
| - // Insert the language to the new position.
|
| - var newIndex = this.dataModel.indexOf(dropTarget.languageCode);
|
| - if (this.dropPos == 'below')
|
| - newIndex += 1;
|
| - this.dataModel.splice(newIndex, 0, languageCode);
|
| - // The cursor should move to the moved item.
|
| - this.selectionModel.selectedIndex = newIndex;
|
| - // Save the preference.
|
| - this.savePreference_();
|
| - },
|
| -
|
| - /*
|
| - * Handles the dragleave event.
|
| - * @param {Event} e The dragleave event
|
| - * @private
|
| - */
|
| - handleDragLeave_ : function(e) {
|
| - this.hideDropMarker_();
|
| - },
|
| -
|
| - /*
|
| - * Shows and positions the marker to indicate the drop target.
|
| - * @param {HTMLElement} target The current target list item of drop
|
| - * @param {string} pos 'below' or 'above'
|
| - * @private
|
| - */
|
| - showDropMarker_ : function(target, pos) {
|
| - window.clearTimeout(this.hideDropMarkerTimer_);
|
| - var marker = $('language-options-list-dropmarker');
|
| - var rect = target.getBoundingClientRect();
|
| - var markerHeight = 8;
|
| - if (pos == 'above') {
|
| - marker.style.top = (rect.top - markerHeight/2) + 'px';
|
| - } else {
|
| - marker.style.top = (rect.bottom - markerHeight/2) + 'px';
|
| - }
|
| - marker.style.width = rect.width + 'px';
|
| - marker.style.left = rect.left + 'px';
|
| - marker.style.display = 'block';
|
| - },
|
| -
|
| - /*
|
| - * Hides the drop marker.
|
| - * @private
|
| - */
|
| - hideDropMarker_ : function() {
|
| - // Hide the marker in a timeout to reduce flickering as we move between
|
| - // valid drop targets.
|
| - window.clearTimeout(this.hideDropMarkerTimer_);
|
| - this.hideDropMarkerTimer_ = window.setTimeout(function() {
|
| - $('language-options-list-dropmarker').style.display = '';
|
| - }, 100);
|
| - },
|
| -
|
| - /**
|
| - * Handles preferred languages pref change.
|
| - * @param {Event} e The change event object.
|
| - * @private
|
| - */
|
| - handlePreferredLanguagesPrefChange_: function(e) {
|
| - var languageCodesInCsv = e.value.value;
|
| - var languageCodes = languageCodesInCsv.split(',');
|
| -
|
| - // Add the UI language to the initial list of languages. This is to avoid
|
| - // a bug where the UI language would be removed from the preferred
|
| - // language list by sync on first login.
|
| - // See: crosbug.com/14283
|
| - languageCodes.push(navigator.language);
|
| - languageCodes = this.filterBadLanguageCodes_(languageCodes);
|
| - this.load_(languageCodes);
|
| - },
|
| -
|
| - /**
|
| - * Handles accept languages pref change.
|
| - * @param {Event} e The change event object.
|
| - * @private
|
| - */
|
| - handleAcceptLanguagesPrefChange_: function(e) {
|
| - var languageCodesInCsv = e.value.value;
|
| - var languageCodes = this.filterBadLanguageCodes_(
|
| - languageCodesInCsv.split(','));
|
| - this.load_(languageCodes);
|
| - },
|
| -
|
| - /**
|
| - * Loads given language list.
|
| - * @param {Array} languageCodes List of language codes.
|
| - * @private
|
| - */
|
| - load_: function(languageCodes) {
|
| - // Preserve the original selected index. See comments below.
|
| - var originalSelectedIndex = (this.selectionModel ?
|
| - this.selectionModel.selectedIndex : -1);
|
| - this.dataModel = new ArrayDataModel(languageCodes);
|
| - if (originalSelectedIndex >= 0 &&
|
| - originalSelectedIndex < this.dataModel.length) {
|
| - // Restore the original selected index if the selected index is
|
| - // valid after the data model is loaded. This is neeeded to keep
|
| - // the selected language after the languge is added or removed.
|
| - this.selectionModel.selectedIndex = originalSelectedIndex;
|
| - // The lead index should be updated too.
|
| - this.selectionModel.leadIndex = originalSelectedIndex;
|
| - } else if (this.dataModel.length > 0){
|
| - // Otherwise, select the first item if it's not empty.
|
| - // Note that ListSingleSelectionModel won't select an item
|
| - // automatically, hence we manually select the first item here.
|
| - this.selectionModel.selectedIndex = 0;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * Saves the preference.
|
| - */
|
| - savePreference_: function() {
|
| - // Encode the language codes into a CSV string.
|
| - if (cr.isChromeOS)
|
| - Preferences.setStringPref(this.preferredLanguagesPref,
|
| - this.dataModel.slice().join(','));
|
| - // Save the same language list as accept languages preference as
|
| - // well, but we need to expand the language list, to make it more
|
| - // acceptable. For instance, some web sites don't understand 'en-US'
|
| - // but 'en'. See crosbug.com/9884.
|
| - var acceptLanguages = this.expandLanguageCodes(this.dataModel.slice());
|
| - Preferences.setStringPref(this.acceptLanguagesPref,
|
| - acceptLanguages.join(','));
|
| - cr.dispatchSimpleEvent(this, 'save');
|
| - },
|
| -
|
| - /**
|
| - * Expands language codes to make these more suitable for Accept-Language.
|
| - * Example: ['en-US', 'ja', 'en-CA'] => ['en-US', 'en', 'ja', 'en-CA'].
|
| - * 'en' won't appear twice as this function eliminates duplicates.
|
| - * @param {Array} languageCodes List of language codes.
|
| - * @private
|
| - */
|
| - expandLanguageCodes: function(languageCodes) {
|
| - var expandedLanguageCodes = [];
|
| - var seen = {}; // Used to eliminiate duplicates.
|
| - for (var i = 0; i < languageCodes.length; i++) {
|
| - var languageCode = languageCodes[i];
|
| - if (!(languageCode in seen)) {
|
| - expandedLanguageCodes.push(languageCode);
|
| - seen[languageCode] = true;
|
| - }
|
| - var parts = languageCode.split('-');
|
| - if (!(parts[0] in seen)) {
|
| - expandedLanguageCodes.push(parts[0]);
|
| - seen[parts[0]] = true;
|
| - }
|
| - }
|
| - return expandedLanguageCodes;
|
| - },
|
| -
|
| - /**
|
| - * Filters bad language codes in case bad language codes are
|
| - * stored in the preference. Removes duplicates as well.
|
| - * @param {Array} languageCodes List of language codes.
|
| - * @private
|
| - */
|
| - filterBadLanguageCodes_: function(languageCodes) {
|
| - var filteredLanguageCodes = [];
|
| - var seen = {};
|
| - for (var i = 0; i < languageCodes.length; i++) {
|
| - // Check if the the language code is valid, and not
|
| - // duplicate. Otherwise, skip it.
|
| - if (LanguageList.isValidLanguageCode(languageCodes[i]) &&
|
| - !(languageCodes[i] in seen)) {
|
| - filteredLanguageCodes.push(languageCodes[i]);
|
| - seen[languageCodes[i]] = true;
|
| - }
|
| - }
|
| - return filteredLanguageCodes;
|
| - },
|
| - };
|
| -
|
| - return {
|
| - LanguageList: LanguageList,
|
| - LanguageListItem: LanguageListItem
|
| - };
|
| -});
|
|
|