1// Copyright (c) 2013 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// Redefine '$' here rather than including 'cr.js', since this is 6// the only function needed. This allows this file to be loaded 7// in a browser directly for layout and some testing purposes. 8var $ = function(id) { return document.getElementById(id); }; 9 10/** 11 * A generic WebUI for configuring preference values used by Chrome's gesture 12 * recognition systems. 13 * @param {string} title The user-visible title to display for the configuration 14 * section. 15 * @param {string} prefix The prefix for the configuration fields. 16 * @param {!Object} fields An array of fields that contain the name of the pref 17 * and user-visible labels. 18 */ 19function GeneralConfig(title, prefix, fields) { 20 this.title = title; 21 this.prefix = prefix; 22 this.fields = fields; 23} 24 25GeneralConfig.prototype = { 26 /** 27 * Sets up the form for configuring all the preference values. 28 */ 29 buildAll: function() { 30 this.buildForm(); 31 this.loadForm(); 32 this.initForm(); 33 }, 34 35 /** 36 * Dynamically builds web-form based on the list of preferences. 37 */ 38 buildForm: function() { 39 var buf = []; 40 41 var section = $('section-template').cloneNode(true); 42 section.removeAttribute('id'); 43 var title = section.querySelector('.section-title'); 44 title.textContent = this.title; 45 46 for (var i = 0; i < this.fields.length; i++) { 47 var field = this.fields[i]; 48 49 var row = $('section-row-template').cloneNode(true); 50 row.removeAttribute('id'); 51 52 var label = row.querySelector('.row-label'); 53 var input = row.querySelector('.input'); 54 var units = row.querySelector('.row-units'); 55 var reset = row.querySelector('.row-reset'); 56 57 label.setAttribute('for', field.key); 58 label.innerHTML = field.label; 59 input.id = field.key; 60 input.min = field.min || 0; 61 62 if (field.max) 63 input.max = field.max; 64 65 input.step = field.step || 'any'; 66 67 if (field.units) 68 units.innerHTML = field.units; 69 70 reset.id = field.key + '-reset'; 71 gesture_config.updateResetButton(reset, true); 72 73 section.querySelector('.section-properties').appendChild(row); 74 } 75 $('gesture-form').appendChild(section); 76 }, 77 78 /** 79 * Initializes the form by adding appropriate event listeners to elements. 80 */ 81 initForm: function() { 82 for (var i = 0; i < this.fields.length; i++) { 83 var field = this.fields[i]; 84 var config = this; 85 $(field.key).onchange = (function(key) { 86 config.setPreferenceValue(key, $(key).value); 87 gesture_config.updateResetButton($(key + '-reset'), false); 88 gesture_config.updateResetAllButton(false); 89 }).bind(null, field.key); 90 $(field.key + '-reset').onclick = (function(key) { 91 config.resetPreferenceValue(key); 92 }).bind(null, field.key); 93 } 94 }, 95 96 /** 97 * Requests preference values for all the relevant fields. 98 */ 99 loadForm: function() { 100 for (var i = 0; i < this.fields.length; i++) 101 this.updatePreferenceValue(this.fields[i].key); 102 }, 103 104 /** 105 * Handles processing of "Reset All" button. 106 * Causes all form values to be updated based on current preference values. 107 * @return {boolean} Returns false. 108 */ 109 onReset: function() { 110 for (var i = 0; i < this.fields.length; i++) { 111 var field = this.fields[i]; 112 this.resetPreferenceValue(field.key); 113 } 114 return false; 115 }, 116 117 /** 118 * Requests a preference setting's value. 119 * This method is asynchronous; the result is provided by a call to 120 * updatePreferenceValueResult. 121 * @param {string} prefName The name of the preference value being requested. 122 */ 123 updatePreferenceValue: function(prefName) { 124 chrome.send('updatePreferenceValue', [this.prefix + prefName]); 125 }, 126 127 /** 128 * Sets a preference setting's value. 129 * @param {string} prefName The name of the preference value being set. 130 * @param {value} value The value to be associated with prefName. 131 */ 132 setPreferenceValue: function(prefName, value) { 133 chrome.send('setPreferenceValue', 134 [this.prefix + prefName, parseFloat(value)]); 135 }, 136 137 /** 138 * Resets a preference to its default value and get that callback 139 * to updatePreferenceValueResult with the new value of the preference. 140 * @param {string} prefName The name of the requested preference. 141 */ 142 resetPreferenceValue: function(prefName) { 143 chrome.send('resetPreferenceValue', [this.prefix + prefName]); 144 } 145}; 146 147/** 148 * Returns a GeneralConfig for configuring gestures.* preferences. 149 * @return {object} A GeneralConfig object. 150 */ 151function GestureConfig() { 152 /** The title of the section for the gesture preferences. **/ 153 /** @const */ var GESTURE_TITLE = 'Gesture Configuration'; 154 155 /** Common prefix of gesture preferences. **/ 156 /** @const */ var GESTURE_PREFIX = 'gesture.'; 157 158 /** List of fields used to dynamically build form. **/ 159 var GESTURE_FIELDS = [ 160 { 161 key: 'fling_max_cancel_to_down_time_in_ms', 162 label: 'Maximum Cancel to Down Time for Tap Suppression', 163 units: 'milliseconds', 164 }, 165 { 166 key: 'fling_max_tap_gap_time_in_ms', 167 label: 'Maximum Tap Gap Time for Tap Suppression', 168 units: 'milliseconds', 169 }, 170 { 171 key: 'semi_long_press_time_in_seconds', 172 label: 'Semi Long Press Time', 173 units: 'seconds', 174 step: 0.1 175 }, 176 { 177 key: 'max_separation_for_gesture_touches_in_pixels', 178 label: 'Maximum Separation for Gesture Touches', 179 units: 'pixels' 180 }, 181 { 182 key: 'tab_scrub_activation_delay_in_ms', 183 label: 'Tab scrub auto activation delay, (-1 for never)', 184 units: 'milliseconds' 185 } 186 ]; 187 188 return new GeneralConfig(GESTURE_TITLE, GESTURE_PREFIX, GESTURE_FIELDS); 189} 190 191/** 192 * Returns a GeneralConfig for configuring overscroll.* preferences. 193 * @return {object} A GeneralConfig object. 194 */ 195function OverscrollConfig() { 196 /** @const */ var OVERSCROLL_TITLE = 'Overscroll Configuration'; 197 198 /** @const */ var OVERSCROLL_PREFIX = 'overscroll.'; 199 200 var OVERSCROLL_FIELDS = [ 201 { 202 key: 'horizontal_threshold_complete', 203 label: 'Complete when overscrolled (horizontal)', 204 units: '%' 205 }, 206 { 207 key: 'vertical_threshold_complete', 208 label: 'Complete when overscrolled (vertical)', 209 units: '%' 210 }, 211 { 212 key: 'minimum_threshold_start_touchpad', 213 label: 'Start overscroll gesture (horizontal; touchpad)', 214 units: 'pixels' 215 }, 216 { 217 key: 'minimum_threshold_start', 218 label: 'Start overscroll gesture (horizontal; touchscreen)', 219 units: 'pixels' 220 }, 221 { 222 key: 'vertical_threshold_start', 223 label: 'Start overscroll gesture (vertical)', 224 units: 'pixels' 225 }, 226 { 227 key: 'horizontal_resist_threshold', 228 label: 'Start resisting overscroll after (horizontal)', 229 units: 'pixels' 230 }, 231 { 232 key: 'vertical_resist_threshold', 233 label: 'Start resisting overscroll after (vertical)', 234 units: 'pixels' 235 }, 236 ]; 237 238 return new GeneralConfig(OVERSCROLL_TITLE, 239 OVERSCROLL_PREFIX, 240 OVERSCROLL_FIELDS); 241} 242 243/** 244 * WebUI instance for configuring preference values related to gesture input. 245 */ 246window.gesture_config = { 247 /** 248 * Build and initialize the gesture configuration form. 249 */ 250 initialize: function() { 251 var g = GestureConfig(); 252 g.buildAll(); 253 254 var o = OverscrollConfig(); 255 o.buildAll(); 256 257 $('reset-all-button').onclick = function() { 258 g.onReset(); 259 o.onReset(); 260 }; 261 }, 262 263 /** 264 * Checks if all gesture preferences are set to default by checking the status 265 * of the reset button associated with each preference. 266 * @return {boolean} True if all gesture preferences are set to default. 267 */ 268 areAllPrefsSetToDefault: function() { 269 var resets = $('gesture-form').querySelectorAll('.row-reset'); 270 for (var i = 0; i < resets.length; i++) { 271 if (!resets[i].disabled) 272 return false; 273 } 274 return true; 275 }, 276 277 /** 278 * Updates the status and label of a preference reset button. 279 * @param {HTMLInputElement} resetButton Reset button for the preference. 280 * @param {boolean} isDefault Whether the preference is set to the default 281 * value. 282 */ 283 updateResetButton: function(resetButton, isDefault) { 284 /** @const */ var TITLE_DEFAULT = 'Default'; 285 286 /** @const */ var TITLE_NOT_DEFAULT = 'Reset'; 287 288 resetButton.innerHTML = isDefault ? TITLE_DEFAULT : TITLE_NOT_DEFAULT; 289 resetButton.disabled = isDefault; 290 }, 291 292 /** 293 * Updates the status and label of "Reset All" button. 294 * @param {boolean} isDefault Whether all preference are set to their default 295 * values. 296 */ 297 updateResetAllButton: function(isDefault) { 298 /** @const */ var TITLE_DEFAULT = 'Everything is set to default'; 299 300 /** @const */ var TITLE_NOT_DEFAULT = 'Reset All To Default'; 301 302 var button = $('reset-all-button'); 303 button.innerHTML = isDefault ? TITLE_DEFAULT : TITLE_NOT_DEFAULT; 304 button.disabled = isDefault; 305 }, 306 307 /** 308 * Handle callback from call to updatePreferenceValue. 309 * @param {string} prefName The name of the requested preference value. 310 * @param {value} value The current value associated with prefName. 311 * @param {boolean} isDefault Whether the value is the default value. 312 */ 313 updatePreferenceValueResult: function(prefName, value, isDefault) { 314 prefName = prefName.substring(prefName.indexOf('.') + 1); 315 $(prefName).value = value; 316 this.updateResetButton($(prefName + '-reset'), isDefault); 317 this.updateResetAllButton(this.areAllPrefsSetToDefault()); 318 }, 319}; 320 321document.addEventListener('DOMContentLoaded', gesture_config.initialize); 322