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

Side by Side Diff: chrome/common/extensions/docs/examples/api/fontSettings/options.js

Issue 23434003: UI refresh of Advanced Font Settings Extension (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review comments Created 7 years, 3 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // The scripts supported by the Font Settings Extension API. 5 'use strict';
6 var scripts = [ 6
7 { scriptCode: 'Zyyy', scriptName: 'Default'}, 7 /**
8 * @fileoverview The Advanced Font Settings Extension implementation.
9 */
10
11 function $(id) {
12 return document.getElementById(id);
13 }
14
15 /**
16 * @namespace
17 */
18 var advancedFonts = {};
19
20 /**
21 * The ICU script code for the Common, or global, script, which is used as the
22 * fallback when the script is undeclared.
23 * @const
24 */
25 advancedFonts.COMMON_SCRIPT = 'Zyyy';
26
27 /**
28 * The scripts supported by the Font Settings Extension API.
29 * @const
30 */
31 advancedFonts.scripts = [
32 { scriptCode: advancedFonts.COMMON_SCRIPT, scriptName: 'Default'},
8 { scriptCode: 'Afak', scriptName: 'Afaka'}, 33 { scriptCode: 'Afak', scriptName: 'Afaka'},
9 { scriptCode: 'Arab', scriptName: 'Arabic'}, 34 { scriptCode: 'Arab', scriptName: 'Arabic'},
10 { scriptCode: 'Armi', scriptName: 'Imperial Aramaic'}, 35 { scriptCode: 'Armi', scriptName: 'Imperial Aramaic'},
11 { scriptCode: 'Armn', scriptName: 'Armenian'}, 36 { scriptCode: 'Armn', scriptName: 'Armenian'},
12 { scriptCode: 'Avst', scriptName: 'Avestan'}, 37 { scriptCode: 'Avst', scriptName: 'Avestan'},
13 { scriptCode: 'Bali', scriptName: 'Balinese'}, 38 { scriptCode: 'Bali', scriptName: 'Balinese'},
14 { scriptCode: 'Bamu', scriptName: 'Bamum'}, 39 { scriptCode: 'Bamu', scriptName: 'Bamum'},
15 { scriptCode: 'Bass', scriptName: 'Bassa Vah'}, 40 { scriptCode: 'Bass', scriptName: 'Bassa Vah'},
16 { scriptCode: 'Batk', scriptName: 'Batak'}, 41 { scriptCode: 'Batk', scriptName: 'Batak'},
17 { scriptCode: 'Beng', scriptName: 'Bengali'}, 42 { scriptCode: 'Beng', scriptName: 'Bengali'},
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 { scriptCode: 'Visp', scriptName: 'Visible Speech'}, 176 { scriptCode: 'Visp', scriptName: 'Visible Speech'},
152 { scriptCode: 'Wara', scriptName: 'Varang Kshiti'}, 177 { scriptCode: 'Wara', scriptName: 'Varang Kshiti'},
153 { scriptCode: 'Wole', scriptName: 'Woleai'}, 178 { scriptCode: 'Wole', scriptName: 'Woleai'},
154 { scriptCode: 'Xpeo', scriptName: 'Old Persian'}, 179 { scriptCode: 'Xpeo', scriptName: 'Old Persian'},
155 { scriptCode: 'Xsux', scriptName: 'Sumero-Akkadian Cuneiform'}, 180 { scriptCode: 'Xsux', scriptName: 'Sumero-Akkadian Cuneiform'},
156 { scriptCode: 'Yiii', scriptName: 'Yi'}, 181 { scriptCode: 'Yiii', scriptName: 'Yi'},
157 { scriptCode: 'Zmth', scriptName: 'Mathematical Notation'}, 182 { scriptCode: 'Zmth', scriptName: 'Mathematical Notation'},
158 { scriptCode: 'Zsym', scriptName: 'Symbols'} 183 { scriptCode: 'Zsym', scriptName: 'Symbols'}
159 ]; 184 ];
160 185
161 // The generic font families supported by the Font Settings Extension API. 186 /**
162 var families = 187 * The generic font families supported by the Font Settings Extension API.
163 ["standard", "sansserif", "serif", "fixed", "cursive", "fantasy"]; 188 * @const
164 189 */
165 // Mapping between font list ids and the generic family setting they 190 advancedFonts.FAMILIES =
166 // represent. 191 ['standard', 'sansserif', 'serif', 'fixed', 'cursive', 'fantasy'];
167 var fontPickers = [ 192
168 { fontList: 'standardFontList', name: 'standard' }, 193 /**
169 { fontList: 'serifFontList', name: 'serif' }, 194 * Sample texts.
170 { fontList: 'sansSerifFontList', name: 'sansserif' }, 195 * @const
171 { fontList: 'fixedFontList', name: 'fixed' } 196 */
172 ]; 197 advancedFonts.SAMPLE_TEXTS = {
173
174 // Ids of elements to contain the sample text.
175 var sampleTextDivIds = [
176 'standardFontSample',
177 'serifFontSample',
178 'sansSerifFontSample',
179 'fixedFontSample',
180 'minFontSample'
181 ];
182
183 // Sample texts.
184 var defaultSampleText = 'The quick brown fox jumps over the lazy dog.';
185 var scriptSpecificSampleText = {
186 // "Cyrllic script". 198 // "Cyrllic script".
187 'Cyrl': 'Кириллица', 199 Cyrl: 'Кириллица',
188 'Hang': '정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날.', 200 Hang: '정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날.',
189 'Hans': '床前明月光,疑是地上霜。举头望明月,低头思故乡。', 201 Hans: '床前明月光,疑是地上霜。举头望明月,低头思故乡。',
190 'Hant': '床前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。', 202 Hant: '床前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。',
191 'Jpan': '吾輩は猫である。名前はまだ無い。', 203 Jpan: '吾輩は猫である。名前はまだ無い。',
192 // "Khmer language". 204 // "Khmer language".
193 'Khmr': '\u1797\u17B6\u179F\u17B6\u1781\u17D2\u1798\u17C2\u179A', 205 Khmr: '\u1797\u17B6\u179F\u17B6\u1781\u17D2\u1798\u17C2\u179A',
206 Zyyy: 'The quick brown fox jumps over the lazy dog.'
194 }; 207 };
195 208
196 // Definition for ScriptList. 209 /**
197 cr.define('fontSettings.ui', function() { 210 * Controller of pending changes.
198 const List = cr.ui.List; 211 * @const
199 const ListItem = cr.ui.ListItem; 212 */
200 const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel; 213 advancedFonts.pendingChanges = new PendingChanges();
201 214
202 function ScriptListItem(info) { 215 /**
203 var el = cr.doc.createElement('li'); 216 * Map from |genericFamily| to UI controls and data for its font setting.
204 el.__proto__ = ScriptListItem.prototype; 217 */
205 el.info_ = info; 218 advancedFonts.fontSettings = null;
206 el.decorate(); 219
207 return el; 220 /**
221 * Map from |fontSizeKey| to UI contols and data for its font size setting.
222 */
223 advancedFonts.fontSizeSettings = null;
224
225 /**
226 * @return {function} A function of form function(x) which calls
yoshiki 2013/08/29 10:02:46 function(string)
227 * callback(x, y, z) where |y| and |z| are fixed to |font| and |controllable|,
228 * respectively.
229 */
230 advancedFonts.getBoundCallback = function(callback, font, controllable) {
231 return function(effectiveFont) {
232 callback(effectiveFont, font, controllable)
208 }; 233 };
209 234 }
210 ScriptListItem.prototype = { 235
211 __proto__: ListItem.prototype, 236 /**
212 237 * Gets the font size used for |fontSizeKey|, including pending changes. Calls
213 decorate: function() { 238 * |callback| with the result.
214 this.textContent = this.info_.scriptName; 239 *
215 if (this.info_.scriptCode == 'Zyyy') { 240 * @param {string} fontSizeKey The font size setting key. See
216 this.style.marginBottom = '1em'; 241 * PendingChanges.getFontSize().
242 * @param {function(number, boolean)} callback The callback of form
243 * function(size, controllable). |size| is the effective setting,
244 * |controllable| is whether the setting can be set.
245 */
246 advancedFonts.getEffectiveFontSize = function(fontSizeKey, callback) {
247 advancedFonts.fontSizeSettings[fontSizeKey].getter({}, function(details) {
248 var controllable = advancedFonts.isControllableLevel(
249 details.levelOfControl);
250 var size = details.pixelSize;
251 var pendingFontSize = advancedFonts.pendingChanges.getFontSize(fontSizeKey);
252 // If the setting is not controllable, we can have no pending change.
253 if (!controllable) {
254 if (pendingFontSize != null) {
255 advancedFonts.pendingChanges.setFontSize(fontSizeKey, null);
256 advancedFonts.refresh();
257 pendingFontSize = null;
217 } 258 }
218 } 259 }
260
261 // If we have a pending change, it overrides the current setting.
262 if (pendingFontSize != null)
263 size = pendingFontSize;
264 callback(size, controllable);
265 });
266 }
267
268 /**
269 * Gets the font used for |script| and |genericFamily|, including pending
270 * changes. Calls |callback| with the result.
271 *
272 * @param {string} script The script code.
273 * @param {string} genericFamily The generic family.
274 * @param {function(string, string, boolean)} callback The callback of form
275 * function(effectiveFont, font, controllable). |effectiveFont| is the font
276 * used taking fallback into consideration, |font| is the actual setting
277 * (pending or not), |controllable| is whether the setting can be set.
278 */
279 advancedFonts.getEffectiveFont = function(script, genericFamily, callback) {
280 var pendingChanges = advancedFonts.pendingChanges;
281 var details = { script: script, genericFamily: genericFamily };
282 var pendingFont =
283 pendingChanges.getFont(details.script, details.genericFamily);
284 chrome.fontSettings.getFont(details, function(result) {
285 var setting = {};
286 setting.font = result.fontId;
287 setting.controllable =
288 advancedFonts.isControllableLevel(result.levelOfControl);
289 // If the setting is not controllable, we can have no pending change.
290 if (!setting.controllable) {
291 pendingFont = null;
292 if (pendingChanges.getFont[script])
293 pendingChanges.setFont([script][genericFamily], null);
294 refresh();
295 }
296
297 // If we have a pending change, it overrides the current setting.
298 if (pendingFont != null)
299 setting.font = pendingFont;
300
301 // If we have a font, we're done.
302 if (setting.font) {
303 callback(setting.font, setting.font, setting.controllable);
304 return;
305 }
306
307 // If we're still here, we have to fallback to common script, unless this
308 // already is common script.
309 if (script == advancedFonts.COMMON_SCRIPT) {
310 callback('', '', setting.controllable);
311 return;
312 }
313 advancedFonts.getEffectiveFont(
314 advancedFonts.COMMON_SCRIPT,
315 genericFamily,
316 advancedFonts.getBoundCallback(
yoshiki 2013/08/29 10:02:46 advancedFonts.getBoundCallback returns one-argumen
falken 2013/08/30 07:33:17 I've updated getBoundCallback to clarify. How does
317 callback, setting.font, setting.controllable));
318 });
319 }
320
321 /**
322 * Returns a function that refreshes the UI controls related to a font setting.
323 *
324 * @param {HTMLSelectElement} list The <select> containing the list of fonts.
325 * @param {array} samples An array of HTMLElement objects with sample text that
yoshiki 2013/08/29 10:02:46 s/array/Array.<HTMLElement>/
falken 2013/08/30 07:33:17 Done.
326 * are rendered using this font setting.
327 * @return {function(string, string, boolean)} A function of form
328 * function(effectiveFont, font, controllable) that refreshes the UI
329 * controls for this font setting. |effectiveFont| is the font used
330 * including fallback, |font| is the value of the font setting (including
331 * pending changes), |controllable| is whether the setting can be
332 * controlled.
333 */
334 advancedFonts.getRefreshFontFunction = function(list, samples) {
335 return function(effectiveFont, font, controllable) {
336 for (var i = 0; i < samples.length; ++i)
337 samples[i].style.fontFamily = effectiveFont;
338 advancedFonts.setSelectedFont(list, font);
339 list.disabled = !controllable;
340 }
341 }
342
343 /**
344 * Returns a function that refreshes the UI controls related to a font size
345 * setting.
346 *
347 * @param {string} fontSizeKey The font size setting key. See
348 * PendingChanges.getFontSize().
349 * @return {function(number, boolean)} A function of form
350 * function(size, controllable) that refreshes the UI controls for this
351 * font size setting. |size| is the value of the font size setting
352 * (including pending changes), |controllable| is whether the setting can be
353 * controlled.
354 */
355 advancedFonts.getRefreshFontSizeFunction = function(fontSizeKey) {
356 var fontSizeSetting = advancedFonts.fontSizeSettings[fontSizeKey];
357 return function(size, controllable) {
358 fontSizeSetting.label.innerText = 'Size: ' + size + 'px';
359 advancedFonts.setFontSizeSlider(fontSizeSetting.slider, size, controllable);
360 for (var i = 0; i < fontSizeSetting.samples.length; ++i)
361 fontSizeSetting.samples[i].style.fontSize = size + 'px';
219 }; 362 };
220 363 }
221 var ScriptList = cr.ui.define('list'); 364
222 ScriptList.prototype = { 365 /**
223 __proto__: List.prototype, 366 * Refreshes all UI controls to reflect the current settings, including pending
224 367 * changes.
225 decorate: function() { 368 */
226 List.prototype.decorate.call(this); 369 advancedFonts.refresh = function() {
227 var sm = new ListSingleSelectionModel(); 370 var script = advancedFonts.getSelectedScript();
228 this.selectionModel = sm; 371 var sample;
229 this.autoExpands = true; 372 if (advancedFonts.SAMPLE_TEXTS[script])
230 this.dataModel = new cr.ui.ArrayDataModel(scripts); 373 sample = advancedFonts.SAMPLE_TEXTS[script];
231 this.style.height = '75vh'; 374 else
232 }, 375 sample = advancedFonts.SAMPLE_TEXTS[advancedFonts.COMMON_SCRIPT];
233 376 var sampleTexts = document.querySelectorAll('.sample-text-span');
234 createItem: function(info) { 377 for (var i = 0; i < sampleTexts.length; i++)
235 return new ScriptListItem(info); 378 sampleTexts[i].textContent = sample;
236 } 379
237 }; 380 var callback;
238 381 for (var genericFamily in advancedFonts.fontSettings) {
239 return { 382 var setting = advancedFonts.fontSettings[genericFamily];
240 ScriptList: ScriptList, 383 callback = advancedFonts.getRefreshFontFunction(setting.fontList,
241 ScriptListItem: ScriptListItem 384 setting.samples);
242 }; 385 advancedFonts.getEffectiveFont(script, genericFamily, callback);
243 }); 386 }
244 387
245 function getSelectedScript() { 388 for (var fontSizeKey in advancedFonts.fontSizeSettings) {
246 var scriptList = document.getElementById('scriptList'); 389 callback = advancedFonts.getRefreshFontSizeFunction(fontSizeKey);
247 return scriptList.selectedItem.scriptCode; 390 advancedFonts.getEffectiveFontSize(fontSizeKey, callback);
248 } 391 }
249 392
250 function getSelectedFont(fontList) { 393 $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty();
394 }
395
396 /**
397 * @return {string} The currently selected script code.
398 */
399 advancedFonts.getSelectedScript = function() {
400 var scriptList = $('scriptList');
401 return scriptList.options[scriptList.selectedIndex].value;
402 }
403
404 /**
405 * @param {HTMLSelectElement} fontList The <select> containing a list of fonts.
406 * @return {string} The currently selected value of |fontList|.
407 */
408 advancedFonts.getSelectedFont = function(fontList) {
251 return fontList.options[fontList.selectedIndex].value; 409 return fontList.options[fontList.selectedIndex].value;
252 } 410 }
253 411
254 // Populates the font lists with the list of system fonts from |fonts|. 412 /**
255 function populateLists(fonts) { 413 * Populates the font lists.
256 for (var i = 0; i < fontPickers.length; i++) { 414 * @param {array} fonts The list of fonts on the system.
yoshiki 2013/08/29 10:02:46 "array" -> "Array.<{fontId: number, displayName: s
falken 2013/08/30 07:33:17 Done, although fontId is a string.
257 var list = document.getElementById(fontPickers[i].fontList); 415 */
258 416 advancedFonts.populateFontLists = function(fonts) {
259 // Add special item to indicate fallback to the non-per-script 417 for (var genericFamily in advancedFonts.fontSettings) {
418 var list = advancedFonts.fontSettings[genericFamily].fontList;
419
420 // Add a special item to indicate fallback to the non-per-script
260 // font setting. The Font Settings API uses the empty string to indicate 421 // font setting. The Font Settings API uses the empty string to indicate
261 // fallback. 422 // fallback.
262 var defaultItem = document.createElement('option'); 423 var defaultItem = document.createElement('option');
263 defaultItem.value = ''; 424 defaultItem.value = '';
264 defaultItem.text = '(Use default)'; 425 defaultItem.text = '(Use default)';
265 list.add(defaultItem); 426 list.add(defaultItem);
266 427
267 for (var j = 0; j < fonts.length; j++) { 428 for (var i = 0; i < fonts.length; ++i) {
268 var item = document.createElement('option'); 429 var item = document.createElement('option');
269 item.value = fonts[j].fontId; 430 item.value = fonts[i].fontId;
270 item.text = fonts[j].displayName; 431 item.text = fonts[i].displayName;
271 list.add(item); 432 list.add(item);
272 } 433 }
273 } 434 }
274 435 advancedFonts.refresh();
275 updateFontListsForScript();
276 } 436 }
277 437
278 // Returns a function that updates the font setting for |genericFamily| 438 /**
279 // to match the selected value in |fontList|. It can be used as an event 439 * @param {HTMLSelectElement} fontList The <select> containing a list of fonts.
280 // handler for selection changes in |fontList|. 440 * @param {string} genericFamily The generic family for the font setting.
281 function getFontChangeHandler(fontList, genericFamily) { 441 * @return {function} A function to be called when the user changes the selected
yoshiki 2013/08/29 10:02:46 s/function/function()/
442 * font in |fontList|. The function updates the pending font change.
443 */
444 advancedFonts.getFontChangeHandler = function(fontList, genericFamily) {
282 return function() { 445 return function() {
283 var script = getSelectedScript(); 446 var script = advancedFonts.getSelectedScript();
284 var font = getSelectedFont(fontList); 447 var font = advancedFonts.getSelectedFont(fontList);
285 448
286 var details = {}; 449 advancedFonts.pendingChanges.setFont(script, genericFamily, font);
287 details.genericFamily = genericFamily; 450 advancedFonts.refresh();
288 details.fontId = font;
289 details.script = script;
290
291 chrome.fontSettings.setFont(details);
292 }; 451 };
293 } 452 }
294 453
295 // Sets the selected value of |fontList| to |fontId|. 454 /**
296 function setSelectedFont(fontList, fontId) { 455 * Sets the selected value of |fontList| to |fontId|.
297 var script = getSelectedScript(); 456 * @param {HTMLSelectElement} fontList The <select> containing a list of fonts.
457 * @param {string} fontId The font to set |fontList|'s selection to.
458 */
459 advancedFonts.setSelectedFont = function(fontList, fontId) {
460 var script = advancedFonts.getSelectedScript();
298 var i; 461 var i;
299 for (i = 0; i < fontList.length; i++) { 462 for (i = 0; i < fontList.length; i++) {
300 if (fontId == fontList.options[i].value) { 463 if (fontId == fontList.options[i].value) {
301 fontList.selectedIndex = i; 464 fontList.selectedIndex = i;
302 break; 465 break;
303 } 466 }
304 } 467 }
305 if (i == fontList.length) { 468 if (i == fontList.length) {
306 console.warn("font '" + fontId + "' for " + fontList.id + ' for ' + 469 console.warn("font '" + fontId + "' for " + fontList.id + ' for ' +
307 script + ' is not on the system'); 470 script + ' is not on the system');
308 } 471 }
309 } 472 }
310 473
311 // Returns a callback function that sets the selected value of |list| to the 474 /**
312 // font returned from |chrome.fontSettings.getFont|. 475 * Return a function that handles changes to the font size slider.
313 function getFontHandler(list) { 476 * @param {string} fontSizeKey The key for font size setting whose slider the
314 return function(details) { 477 * function should handle changed for. See PendingChanges.getFont.
315 setSelectedFont(list, details.fontId); 478 * @return {function(number)} A function to be called when the user changes the
316 list.disabled = !isControllableLevel(details.levelOfControl); 479 * font size slider for |fontSizeKey|. The function sets the pending font
317 }; 480 * size change.
318 } 481 */
319 482 advancedFonts.getFontSizeChangedFunc = function(fontSizeKey) {
320 // Called when the script list selection changes. Sets the selected value of 483 return function(value) {
321 // each font list to the current font setting, and updates the samples' lang 484 var pixelSize = parseInt(value);
322 // so that they are shown in the current font setting.
323 function updateFontListsForScript() {
324 var script = getSelectedScript();
325
326 for (var i = 0; i < fontPickers.length; i++) {
327 var list = document.getElementById(fontPickers[i].fontList);
328 var family = fontPickers[i].name;
329
330 var details = {};
331 details.genericFamily = family;
332 details.script = script;
333 chrome.fontSettings.getFont(details, getFontHandler(list));
334 }
335
336 if (typeof(scriptSpecificSampleText[script]) != 'undefined')
337 sample = scriptSpecificSampleText[script];
338 else
339 sample = defaultSampleText;
340 for (var i = 0; i < sampleTextDivIds.length; i++) {
341 var sampleTextDiv = document.getElementById(sampleTextDivIds[i]);
342 // For font selection it's the script code that matters, not language, so
343 // just use en for lang.
344 sampleTextDiv.lang = 'en-' + script;
345 sampleTextDiv.innerText = sample;
346 }
347 }
348
349 // Returns a function to be called when the user changes the font size
350 // input element |elem|. The function calls the Font Settings Extension API
351 // function |setter| to commit the change.
352 function getFontSizeChangedFunc(elem, setter) {
353 return function() {
354 var pixelSize = parseInt(elem.value);
355 if (!isNaN(pixelSize)) { 485 if (!isNaN(pixelSize)) {
356 setter({ pixelSize: pixelSize }); 486 advancedFonts.pendingChanges.setFontSize(fontSizeKey, pixelSize);
487 advancedFonts.refresh();
357 } 488 }
358 } 489 }
359 } 490 }
360 491
361 function isControllableLevel(levelOfControl) { 492 /**
493 * @param {string} levelOfControl The level of control string for a setting,
494 * as returned by the Font Settings Extension API.
495 * @return {boolean} True if |levelOfControl| signifies that the extension can
496 * control the setting; otherwise, returns false.
497 */
498 advancedFonts.isControllableLevel = function(levelOfControl) {
362 return levelOfControl == 'controllable_by_this_extension' || 499 return levelOfControl == 'controllable_by_this_extension' ||
363 levelOfControl == 'controlled_by_this_extension'; 500 levelOfControl == 'controlled_by_this_extension';
364 } 501 }
365 502
366 // Returns a function to be used as a listener for font size setting changed 503 /**
367 // events from the Font Settings Extension API. The function updates the input 504 * Returns a function to be used as a listener for font size setting changed
368 // element |elem| and the elements in |sampleTexts| to reflect the change. 505 * events from the Font Settings Extension API.
369 function getFontSizeChangedOnBrowserFunc(elem, sampleTexts) { 506 * @param {Slider} slider The slider for the font size setting.
507 * @param {HTMLElement} label The element that displays the slider's value.
508 * @param {array} sampleTexts An array of elements containing sample text
yoshiki 2013/08/29 10:02:46 s/array/Array.{HTMLElement}/ cf. https://develope
falken 2013/08/30 07:33:17 Done. Thanks, I'd missed that.
509 * which is rendered using this font size setting.
510 * @return {function(object) A function that can listen for font size change
yoshiki 2013/08/29 10:02:46 "}" is missing after the type.
falken 2013/08/30 07:33:17 Done.
511 * events from the browser and update |slider|, |label|, and |sampleTexts|
512 * to reflect the change.
513 */
514 advancedFonts.getFontSizeChangedOnBrowserFunc =
515 function(slider, label, sampleTexts) {
370 return function(details) { 516 return function(details) {
371 var size = details.pixelSize.toString(); 517 var size = details.pixelSize.toString();
372 elem.value = size; 518 var controllable =
373 elem.disabled = !isControllableLevel(details.levelOfControl); 519 advancedFonts.isControllableLevel(details.levelOfControl);
520 advancedFonts.setFontSizeSlider(slider, size, controllable);
521 label.disabled = !controllable;
374 for (var i = 0; i < sampleTexts.length; i++) 522 for (var i = 0; i < sampleTexts.length; i++)
375 document.getElementById(sampleTexts[i]).style.fontSize = size + 'px'; 523 sampleTexts[i].style.fontSize = size + 'px';
524 label.innerText = 'Size: ' + size + 'px';
376 } 525 }
377 } 526 }
378 527
379 // Maps the HTML <input> element with |id| to the extension API accessor 528 /*
380 // functions |getter| and |setter| for a setting and onChange event |apiEvent| 529 * Updates the specified font size slider's value and enabled property.
381 // for the setting. Also, maps the element ids in |sampleTexts| to this setting. 530 * @param {Slider} slider The slider for a font size setting.
382 function initFontSizePref(id, sampleTexts, getter, setter, apiEvent) { 531 * @param {number} size The value to set the slider to.
383 var elem = document.getElementById(id); 532 * @param {boolean} enabled Whether to enable or disable the slider.
384 getter({}, function(details) { 533 */
385 var size = details.pixelSize.toString(); 534 advancedFonts.setFontSizeSlider = function(slider, size, enabled) {
386 elem.value = size; 535 if (slider.getValue() != size)
387 elem.disabled = !isControllableLevel(details.levelOfControl); 536 slider.setValue(size);
388 for (var i = 0; i < sampleTexts.length; i++) 537 var inputElement = slider.getInput();
389 document.getElementById(sampleTexts[i]).style.fontSize = size + 'px'; 538 if (enabled) {
390 }); 539 inputElement.parentNode.classList.remove('disabled');
391 elem.addEventListener('change', getFontSizeChangedFunc(elem, setter)); 540 inputElement.disabled = false;
392 apiEvent.addListener(getFontSizeChangedOnBrowserFunc(elem, sampleTexts)); 541 } else {
542 inputElement.parentNode.classList.add('disabled');
543 inputElement.disabled = true;
544 }
393 } 545 }
394 546
395 function clearSettingsForScript(script) { 547 /**
396 for (var i = 0; i < families.length; i++) { 548 * Initializes the UI control elements related to the font size setting
549 * |fontSizeKey| and registers listeners for the user adjusting its slider and
550 * the setting changing on the browser-side.
551 * @param {string} fontSizeKey The key for font size setting. See
552 * PendingChanges.getFont().
553 */
554 advancedFonts.initFontSizeSetting = function(fontSizeKey) {
555 var fontSizeSettings = advancedFonts.fontSizeSettings;
556 var setting = fontSizeSettings[fontSizeKey];
557 var label = setting.label;
558 var samples = setting.samples;
559
560 setting.slider = new Slider(
561 setting.sliderContainer,
562 0,
563 setting.minValue,
564 setting.maxValue,
565 advancedFonts.getFontSizeChangedFunc(fontSizeKey)
566 );
567
568 var slider = setting.slider;
569 setting.getter({}, function(details) {
570 var size = details.pixelSize.toString();
571 var controllable = advancedFonts.isControllableLevel(
572 details.levelOfControl);
573 advancedFonts.setFontSizeSlider(slider, size, controllable);
574 for (var i = 0; i < samples.length; i++)
575 samples[i].style.fontSize = size + 'px';
576 });
577 var apiEvent = fontSizeSettings[fontSizeKey].onChanged;
578 apiEvent.addListener(
579 advancedFonts.getFontSizeChangedOnBrowserFunc(slider, label, samples));
580 }
581
582 /**
583 * Clears the font settings for the specified script.
584 * @param {string} script The script code.
585 */
586 advancedFonts.clearSettingsForScript = function(script) {
587 advancedFonts.pendingChanges.clearOneScript(script);
588 for (var i = 0; i < advancedFonts.FAMILIES.length; i++) {
397 chrome.fontSettings.clearFont({ 589 chrome.fontSettings.clearFont({
398 script: script, 590 script: script,
399 genericFamily: families[i] 591 genericFamily: advancedFonts.FAMILIES[i]
400 }); 592 });
401 } 593 }
402 } 594 }
403 595
404 function clearAllSettings() { 596 /**
405 for (var i = 0; i < scripts.length; i++) 597 * Clears all font and font size settings.
406 clearSettingsForScript(scripts[i].scriptCode); 598 */
407 599 advancedFonts.clearAllSettings = function() {
600 advancedFonts.pendingChanges.clear();
601 for (var i = 0; i < advancedFonts.scripts.length; i++)
602 advancedFonts.clearSettingsForScript(advancedFonts.scripts[i].scriptCode);
408 chrome.fontSettings.clearDefaultFixedFontSize(); 603 chrome.fontSettings.clearDefaultFixedFontSize();
409 chrome.fontSettings.clearDefaultFontSize(); 604 chrome.fontSettings.clearDefaultFontSize();
410 chrome.fontSettings.clearMinimumFontSize(); 605 chrome.fontSettings.clearMinimumFontSize();
411 } 606 }
412 607
413 function closeOverlay() { 608 /**
609 * Closes the overlay.
610 */
611 advancedFonts.closeOverlay = function() {
414 $('overlay-container').hidden = true; 612 $('overlay-container').hidden = true;
415 } 613 }
416 614
417 function initResetButtons() { 615 /**
616 * Initializes apply and reset buttons.
617 */
618 advancedFonts.initApplyAndResetButtons = function() {
619 var applyButton = $('apply-settings');
620 applyButton.addEventListener('click', function() {
621 advancedFonts.pendingChanges.apply();
622 advancedFonts.refresh();
623 });
624
418 var overlay = $('overlay-container'); 625 var overlay = $('overlay-container');
419 cr.ui.overlay.globalInitialization(); 626 cr.ui.overlay.globalInitialization();
420 cr.ui.overlay.setupOverlay(overlay); 627 cr.ui.overlay.setupOverlay(overlay);
421 overlay.addEventListener('cancelOverlay', closeOverlay); 628 overlay.addEventListener('cancelOverlay', advancedFonts.closeOverlay);
422 629
423 $('reset-this-script-button').onclick = function(event) { 630 $('reset-this-script-button').onclick = function(event) {
424 var scriptName = $('scriptList').selectedItem.scriptName; 631 var scriptList = $('scriptList');
632 var scriptName = scriptList.options[scriptList.selectedIndex].text;
425 $('reset-this-script-overlay-dialog-content').innerText = 633 $('reset-this-script-overlay-dialog-content').innerText =
426 'Are you sure you want to reset settings for ' + scriptName + 634 'Are you sure you want to reset settings for ' + scriptName +
427 ' script?'; 635 ' script?';
428 636
429 $('overlay-container').hidden = false; 637 $('overlay-container').hidden = false;
430 $('reset-this-script-overlay-dialog').hidden = false; 638 $('reset-this-script-overlay-dialog').hidden = false;
431 $('reset-all-scripts-overlay-dialog').hidden = true; 639 $('reset-all-scripts-overlay-dialog').hidden = true;
432 } 640 };
433 $('reset-this-script-ok').onclick = function(event) { 641 $('reset-this-script-ok').onclick = function(event) {
434 clearSettingsForScript(getSelectedScript()); 642 advancedFonts.clearSettingsForScript(advancedFonts.getSelectedScript());
435 closeOverlay(); 643 advancedFonts.closeOverlay();
644 advancedFonts.refresh();
436 }; 645 };
437 $('reset-this-script-cancel').onclick = closeOverlay; 646 $('reset-this-script-cancel').onclick = advancedFonts.closeOverlay;
438 647
439 $('reset-all-button').onclick = function(event) { 648 $('reset-all-button').onclick = function(event) {
440 $('overlay-container').hidden = false; 649 $('overlay-container').hidden = false;
441 $('reset-all-scripts-overlay-dialog').hidden = false; 650 $('reset-all-scripts-overlay-dialog').hidden = false;
442 $('reset-this-script-overlay-dialog').hidden = true; 651 $('reset-this-script-overlay-dialog').hidden = true;
443 } 652 };
444 $('reset-all-ok').onclick = function(event) { 653 $('reset-all-ok').onclick = function(event) {
445 clearAllSettings(); 654 advancedFonts.clearAllSettings();
446 closeOverlay(); 655 advancedFonts.closeOverlay();
447 } 656 advancedFonts.refresh();
448 $('reset-all-cancel').onclick = closeOverlay; 657 };
658 $('reset-all-cancel').onclick = advancedFonts.closeOverlay;
449 } 659 }
450 660
451 function init() { 661 /**
452 var scriptList = document.getElementById('scriptList'); 662 * Best guess for system fonts, taken from the IDS_WEB_FONT_FAMILY strings in
453 fontSettings.ui.ScriptList.decorate(scriptList); 663 * Chrome.
454 scriptList.selectionModel.selectedIndex = 0; 664 * TODO: The font should be localized like Chrome does.
455 scriptList.selectionModel.addEventListener('change', 665 * @const
456 updateFontListsForScript); 666 */
457 667 advancedFonts.systemFonts = {
458 // Populate the font lists. 668 cros: 'Noto Sans UI, sans-serif',
459 chrome.fontSettings.getFontList(populateLists); 669 linux: 'Ubuntu, sans-serif',
460 670 mac: 'Lucida Grande, sans-serif',
461 // Add change handlers to the font lists. 671 win: 'Segoe UI, Tahoma, sans-serif',
462 for (var i = 0; i < fontPickers.length; i++) { 672 unknown: 'sans-serif'
463 var list = document.getElementById(fontPickers[i].fontList);
464 var handler = getFontChangeHandler(list, fontPickers[i].name);
465 list.addEventListener('change', handler);
466 }
467
468 chrome.fontSettings.onFontChanged.addListener(
469 updateFontListsForScript);
470
471 initFontSizePref(
472 'defaultFontSizeRocker',
473 ['standardFontSample', 'serifFontSample', 'sansSerifFontSample'],
474 chrome.fontSettings.getDefaultFontSize,
475 chrome.fontSettings.setDefaultFontSize,
476 chrome.fontSettings.onDefaultFontSizeChanged);
477 initFontSizePref(
478 'defaultFontSizeRange',
479 ['standardFontSample', 'serifFontSample', 'sansSerifFontSample'],
480 chrome.fontSettings.getDefaultFontSize,
481 chrome.fontSettings.setDefaultFontSize,
482 chrome.fontSettings.onDefaultFontSizeChanged);
483 initFontSizePref(
484 'defaultFixedFontSizeRocker',
485 ['fixedFontSample'],
486 chrome.fontSettings.getDefaultFixedFontSize,
487 chrome.fontSettings.setDefaultFixedFontSize,
488 chrome.fontSettings.onDefaultFixedFontSizeChanged);
489 initFontSizePref(
490 'defaultFixedFontSizeRange',
491 ['fixedFontSample'],
492 chrome.fontSettings.getDefaultFixedFontSize,
493 chrome.fontSettings.setDefaultFixedFontSize,
494 chrome.fontSettings.onDefaultFixedFontSizeChanged);
495 initFontSizePref(
496 'minFontSizeRocker',
497 ['minFontSample'],
498 chrome.fontSettings.getMinimumFontSize,
499 chrome.fontSettings.setMinimumFontSize,
500 chrome.fontSettings.onMinimumFontSizeChanged);
501 initFontSizePref(
502 'minFontSizeRange',
503 ['minFontSample'],
504 chrome.fontSettings.getMinimumFontSize,
505 chrome.fontSettings.setMinimumFontSize,
506 chrome.fontSettings.onMinimumFontSizeChanged);
507
508 initResetButtons();
509 } 673 }
510 674
511 document.addEventListener('DOMContentLoaded', init); 675 /**
676 * @return {string} The platform this extension is running on.
677 */
678 advancedFonts.getPlatform = function() {
679 var ua = window.navigator.appVersion;
680 if (ua.indexOf('Win') != -1) return 'win';
681 if (ua.indexOf('Mac') != -1) return 'mac';
682 if (ua.indexOf('Linux') != -1) return 'linux';
683 if (ua.indexOf('CrOS') != -1) return 'cros';
684 return 'unknown';
685 }
686
687 /**
688 * Chrome settings tries to use the system font. So does this extension.
689 */
690 advancedFonts.useSystemFont = function() {
691 document.body.style.fontFamily =
692 advancedFonts.systemFonts[advancedFonts.getPlatform()];
693 }
694
695 /**
696 * Sorts the list of script codes by scriptName. Someday this extension will
697 * have localized script names, so the order will depend on locale.
698 */
699 advancedFonts.sortScripts = function() {
700 var i;
701 var scripts = advancedFonts.scripts;
702 for (i = 0; i < scripts; ++i) {
703 if (scripts[i].scriptCode == advancedFonts.COMMON_SCRIPT)
704 break;
705 }
706 var defaultScript = scripts.splice(i, 1)[0];
707
708 scripts.sort(function(a, b) {
709 if (a.scriptName > b.scriptName)
710 return 1;
711 if (a.scriptName < b.scriptName)
712 return -1;
713 return 0;
714 });
715
716 scripts.unshift(defaultScript);
717 }
718
719 /**
720 * Initializes UI controls for font settings.
721 */
722 advancedFonts.initFontControls = function() {
723 advancedFonts.fontSettings = {
724 'standard': {
725 fontList: $('standardFontList'),
726 samples: [$('standardFontSample'), $('minFontSample')]
727 },
728 'serif': {
729 fontList: $('serifFontList'),
730 samples: [$('serifFontSample')]
731 },
732 'sansserif': {
733 fontList: $('sansSerifFontList'),
734 samples: [$('sansSerifFontSample')]
735 },
736 'fixed': {
737 fontList: $('fixedFontList'),
738 samples: [$('fixedFontSample')]
739 }
740 };
741
742 for (var genericFamily in advancedFonts.fontSettings) {
743 var list = advancedFonts.fontSettings[genericFamily].fontList;
744 list.addEventListener('change', advancedFonts.getFontChangeHandler(
745 list, genericFamily));
746 }
747 chrome.fontSettings.onFontChanged.addListener(advancedFonts.refresh);
748 chrome.fontSettings.getFontList(advancedFonts.populateFontLists);
749 }
750
751 /**
752 * Initializes UI controls for font size settings.
753 */
754 advancedFonts.initFontSizeControls = function() {
755 advancedFonts.fontSizeSettings = {
756 'defaultFontSize': {
757 sliderContainer: $('defaultFontSizeSliderContainer'),
758 minValue: 6,
759 maxValue: 50,
760 samples: [
761 $('standardFontSample'), $('serifFontSample'), $('sansSerifFontSample')
762 ],
763 label: $('defaultFontSizeLabel'),
764 getter: chrome.fontSettings.getDefaultFontSize,
765 onChanged: chrome.fontSettings.onDefaultFontSizeChanged
766 },
767 'defaultFixedFontSize': {
768 sliderContainer: $('defaultFixedFontSizeSliderContainer'),
769 minValue: 6,
770 maxValue: 50,
771 samples: [$('fixedFontSample')],
772 label: $('fixedFontSizeLabel'),
773 getter: chrome.fontSettings.getDefaultFixedFontSize,
774 onChanged: chrome.fontSettings.onDefaultFixedFontSizeChanged
775 },
776 'minFontSize': {
777 sliderContainer: $('minFontSizeSliderContainer'),
778 minValue: 6,
779 maxValue: 24,
780 samples: [$('minFontSample')],
781 label: $('minFontSizeLabel'),
782 getter: chrome.fontSettings.getMinimumFontSize,
783 onChanged: chrome.fontSettings.onMinimumFontSizeChanged
784 }
785 };
786
787 for (var fontSizeKey in advancedFonts.fontSizeSettings)
788 advancedFonts.initFontSizeSetting(fontSizeKey);
789 }
790
791 /**
792 * Initializes the list of scripts.
793 */
794 advancedFonts.initScriptList = function() {
795 var scriptList = $('scriptList');
796 advancedFonts.sortScripts();
797 var scripts = advancedFonts.scripts;
798 for (var i = 0; i < scripts.length; i++) {
799 var script = document.createElement('option');
800 script.value = scripts[i].scriptCode;
801 script.text = scripts[i].scriptName;
802 scriptList.add(script);
803 }
804 scriptList.selectedIndex = 0;
805 scriptList.addEventListener('change', advancedFonts.refresh);
806 }
807
808 /**
809 * Initializes the extension.
810 */
811 advancedFonts.init = function() {
812 advancedFonts.useSystemFont();
813
814 advancedFonts.initFontControls();
815 advancedFonts.initFontSizeControls();
816 advancedFonts.initScriptList();
817
818 advancedFonts.initApplyAndResetButtons();
819 }
820
821 document.addEventListener('DOMContentLoaded', advancedFonts.init);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698