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

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

Issue 6265010: DOMUI settings: move/rename the language options panel so that it can be use... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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) 2010 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 cr.define('options.language', function() {
6 const ArrayDataModel = cr.ui.ArrayDataModel;
7 const LanguageOptions = options.LanguageOptions;
8 const List = cr.ui.List;
9 const ListItem = cr.ui.ListItem;
10 const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
11
12 /**
13 * Creates a new language list.
14 * @param {Object=} opt_propertyBag Optional properties.
15 * @constructor
16 * @extends {cr.ui.List}
17 */
18 var LanguageList = cr.ui.define('list');
19
20 /**
21 * Gets display name from the given language code.
22 * @param {string} languageCode Language code (ex. "fr").
23 */
24 LanguageList.getDisplayNameFromLanguageCode = function(languageCode) {
25 // Build the language code to display name dictionary at first time.
26 if (!this.languageCodeToDisplayName_) {
27 this.languageCodeToDisplayName_ = {};
28 var languageList = templateData.languageList;
29 for (var i = 0; i < languageList.length; i++) {
30 var language = languageList[i];
31 this.languageCodeToDisplayName_[language.code] = language.displayName;
32 }
33 }
34
35 return this.languageCodeToDisplayName_[languageCode];
36 }
37
38 /**
39 * Gets native display name from the given language code.
40 * @param {string} languageCode Language code (ex. "fr").
41 */
42 LanguageList.getNativeDisplayNameFromLanguageCode = function(languageCode) {
43 // Build the language code to display name dictionary at first time.
44 if (!this.languageCodeToNativeDisplayName_) {
45 this.languageCodeToNativeDisplayName_ = {};
46 var languageList = templateData.languageList;
47 for (var i = 0; i < languageList.length; i++) {
48 var language = languageList[i];
49 this.languageCodeToNativeDisplayName_[language.code] =
50 language.nativeDisplayName;
51 }
52 }
53
54 return this.languageCodeToNativeDisplayName_[languageCode];
55 }
56
57 /**
58 * Returns true if the given language code is valid.
59 * @param {string} languageCode Language code (ex. "fr").
60 */
61 LanguageList.isValidLanguageCode = function(languageCode) {
62 // Having the display name for the language code means that the
63 // language code is valid.
64 if (LanguageList.getDisplayNameFromLanguageCode(languageCode)) {
65 return true;
66 }
67 return false;
68 }
69
70 LanguageList.prototype = {
71 __proto__: List.prototype,
72
73 // The list item being dragged.
74 draggedItem: null,
75 // The drop position information: "below" or "above".
76 dropPos: null,
77 // The preference is a CSV string that describes preferred languages
78 // in Chrome OS. The language list is used for showing the language
79 // list in "Language and Input" options page.
80 preferredLanguagesPref: 'settings.language.preferred_languages',
81 // The preference is a CSV string that describes accept languages used
82 // for content negotiation. To be more precise, the list will be used
83 // in "Accept-Language" header in HTTP requests.
84 acceptLanguagesPref: 'intl.accept_languages',
85
86 /** @inheritDoc */
87 decorate: function() {
88 List.prototype.decorate.call(this);
89 this.selectionModel = new ListSingleSelectionModel;
90
91 // HACK(arv): http://crbug.com/40902
92 window.addEventListener('resize', this.redraw.bind(this));
93
94 // Listen to pref change.
95 Preferences.getInstance().addEventListener(this.preferredLanguagesPref,
96 this.handlePreferredLanguagesPrefChange_.bind(this));
97
98 // Listen to drag and drop events.
99 this.addEventListener('dragstart', this.handleDragStart_.bind(this));
100 this.addEventListener('dragenter', this.handleDragEnter_.bind(this));
101 this.addEventListener('dragover', this.handleDragOver_.bind(this));
102 this.addEventListener('drop', this.handleDrop_.bind(this));
103 },
104
105 createItem: function(languageCode) {
106 var languageDisplayName =
107 LanguageList.getDisplayNameFromLanguageCode(languageCode);
108 var languageNativeDisplayName =
109 LanguageList.getNativeDisplayNameFromLanguageCode(languageCode);
110 return new ListItem({
111 label: languageDisplayName,
112 draggable: true,
113 languageCode: languageCode,
114 title: languageNativeDisplayName // Show native name as tooltip.
115 });
116 },
117
118 /*
119 * Adds a language to the language list.
120 * @param {string} languageCode language code (ex. "fr").
121 */
122 addLanguage: function(languageCode) {
123 // It shouldn't happen but ignore the language code if it's
124 // null/undefined, or already present.
125 if (!languageCode || this.dataModel.indexOf(languageCode) >= 0) {
126 return;
127 }
128 this.dataModel.push(languageCode);
129 // Select the last item, which is the language added.
130 this.selectionModel.selectedIndex = this.dataModel.length - 1;
131
132 this.savePreference_();
133 },
134
135 /*
136 * Gets the language codes of the currently listed languages.
137 */
138 getLanguageCodes: function() {
139 return this.dataModel.slice();
140 },
141
142 /*
143 * Gets the language code of the selected language.
144 */
145 getSelectedLanguageCode: function() {
146 return this.selectedItem;
147 },
148
149 /*
150 * Selects the language by the given language code.
151 * @returns {boolean} True if the operation is successful.
152 */
153 selectLanguageByCode: function(languageCode) {
154 var index = this.dataModel.indexOf(languageCode);
155 if (index >= 0) {
156 this.selectionModel.selectedIndex = index;
157 return true;
158 }
159 return false;
160 },
161
162 /*
163 * Removes the currently selected language.
164 */
165 removeSelectedLanguage: function() {
166 if (this.selectionModel.selectedIndex >= 0) {
167 this.dataModel.splice(this.selectionModel.selectedIndex, 1);
168 // Once the selected item is removed, there will be no selected item.
169 // Select the item pointed by the lead index.
170 this.selectionModel.selectedIndex = this.selectionModel.leadIndex;
171 this.savePreference_();
172 }
173 },
174
175 /*
176 * Handles the dragstart event.
177 * @param {Event} e The dragstart event.
178 * @private
179 */
180 handleDragStart_: function(e) {
181 var target = e.target;
182 // ListItem should be the only draggable element type in the page,
183 // but just in case.
184 if (target instanceof ListItem) {
185 this.draggedItem = target;
186 e.dataTransfer.effectAllowed = 'move';
187 }
188 },
189
190 /*
191 * Handles the dragenter event.
192 * @param {Event} e The dragenter event.
193 * @private
194 */
195 handleDragEnter_: function(e) {
196 e.preventDefault();
197 },
198
199 /*
200 * Handles the dragover event.
201 * @param {Event} e The dragover event.
202 * @private
203 */
204 handleDragOver_: function(e) {
205 var dropTarget = e.target;
206 // Determins whether the drop target is to accept the drop.
207 // The drop is only successful on another ListItem.
208 if (!(dropTarget instanceof ListItem) ||
209 dropTarget == this.draggedItem) {
210 return;
211 }
212 // Compute the drop postion. Should we move the dragged item to
213 // below or above the drop target?
214 var rect = dropTarget.getBoundingClientRect();
215 var dy = e.clientY - rect.top;
216 var yRatio = dy / rect.height;
217 var dropPos = yRatio <= .5 ? 'above' : 'below';
218 this.dropPos = dropPos;
219 e.preventDefault();
220 // TODO(satorux): Show the drop marker just like the bookmark manager.
221 },
222
223 /*
224 * Handles the drop event.
225 * @param {Event} e The drop event.
226 * @private
227 */
228 handleDrop_: function(e) {
229 var dropTarget = e.target;
230
231 // Delete the language from the original position.
232 var languageCode = this.draggedItem.languageCode;
233 var originalIndex = this.dataModel.indexOf(languageCode);
234 this.dataModel.splice(originalIndex, 1);
235 // Insert the language to the new position.
236 var newIndex = this.dataModel.indexOf(dropTarget.languageCode);
237 if (this.dropPos == 'below')
238 newIndex += 1;
239 this.dataModel.splice(newIndex, 0, languageCode);
240 // The cursor should move to the moved item.
241 this.selectionModel.selectedIndex = newIndex;
242 // Save the preference.
243 this.savePreference_();
244 },
245
246 /**
247 * Handles preferred languages pref change.
248 * @param {Event} e The change event object.
249 * @private
250 */
251 handlePreferredLanguagesPrefChange_: function(e) {
252 var languageCodesInCsv = e.value.value;
253 var languageCodes = this.filterBadLanguageCodes_(
254 languageCodesInCsv.split(','));
255 this.load_(languageCodes);
256 },
257
258 /**
259 * Loads given language list.
260 * @param {Array} languageCodes List of language codes.
261 * @private
262 */
263 load_: function(languageCodes) {
264 // Preserve the original selected index. See comments below.
265 var originalSelectedIndex = (this.selectionModel ?
266 this.selectionModel.selectedIndex : -1);
267 this.dataModel = new ArrayDataModel(languageCodes);
268 if (originalSelectedIndex >= 0 &&
269 originalSelectedIndex < this.dataModel.length) {
270 // Restore the original selected index if the selected index is
271 // valid after the data model is loaded. This is neeeded to keep
272 // the selected language after the languge is added or removed.
273 this.selectionModel.selectedIndex = originalSelectedIndex;
274 // The lead index should be updated too.
275 this.selectionModel.leadIndex = originalSelectedIndex;
276 } else if (this.dataModel.length > 0){
277 // Otherwise, select the first item if it's not empty.
278 // Note that ListSingleSelectionModel won't select an item
279 // automatically, hence we manually select the first item here.
280 this.selectionModel.selectedIndex = 0;
281 }
282 },
283
284 /**
285 * Saves the preference.
286 */
287 savePreference_: function() {
288 // Encode the language codes into a CSV string.
289 Preferences.setStringPref(this.preferredLanguagesPref,
290 this.dataModel.slice().join(','));
291 // Save the same language list as accept languages preference as
292 // well, but we need to expand the language list, to make it more
293 // acceptable. For instance, some web sites don't understand 'en-US'
294 // but 'en'. See crosbug.com/9884.
295 var acceptLanguages = this.expandLanguageCodes(this.dataModel.slice());
296 Preferences.setStringPref(this.acceptLanguagesPref,
297 acceptLanguages.join(','));
298 cr.dispatchSimpleEvent(this, 'save');
299 },
300
301 /**
302 * Expands language codes to make these more suitable for Accept-Language.
303 * Example: ['en-US', 'ja', 'en-CA'] => ['en-US', 'en', 'ja', 'en-CA'].
304 * 'en' won't appear twice as this function eliminates duplicates.
305 * @param {Array} languageCodes List of language codes.
306 * @private
307 */
308 expandLanguageCodes: function(languageCodes) {
309 var expandedLanguageCodes = [];
310 var seen = {}; // Used to eliminiate duplicates.
311 for (var i = 0; i < languageCodes.length; i++) {
312 var languageCode = languageCodes[i];
313 if (!(languageCode in seen)) {
314 expandedLanguageCodes.push(languageCode);
315 seen[languageCode] = true;
316 }
317 var parts = languageCode.split('-');
318 if (!(parts[0] in seen)) {
319 expandedLanguageCodes.push(parts[0]);
320 seen[parts[0]] = true;
321 }
322 }
323 return expandedLanguageCodes;
324 },
325
326 /**
327 * Filters bad language codes in case bad language codes are
328 * stored in the preference. Removes duplicates as well.
329 * @param {Array} languageCodes List of language codes.
330 * @private
331 */
332 filterBadLanguageCodes_: function(languageCodes) {
333 var filteredLanguageCodes = [];
334 var seen = {};
335 for (var i = 0; i < languageCodes.length; i++) {
336 // Check if the the language code is valid, and not
337 // duplicate. Otherwise, skip it.
338 if (LanguageList.isValidLanguageCode(languageCodes[i]) &&
339 !(languageCodes[i] in seen)) {
340 filteredLanguageCodes.push(languageCodes[i]);
341 seen[languageCodes[i]] = true;
342 }
343 }
344 return filteredLanguageCodes;
345 },
346 };
347
348 return {
349 LanguageList: LanguageList
350 };
351 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698