| // Copyright (c) 2013 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. |
| |
| // Redefine '$' here rather than including 'cr.js', since this is |
| // the only function needed. This allows this file to be loaded |
| // in a browser directly for layout and some testing purposes. |
| var $ = function(id) { return document.getElementById(id); }; |
| |
| /** |
| * A generic WebUI for configuring preference values used by Chrome's gesture |
| * recognition systems. |
| * @param {string} title The user-visible title to display for the configuration |
| * section. |
| * @param {string} prefix The prefix for the configuration fields. |
| * @param {!Object} fields An array of fields that contain the name of the pref |
| * and user-visible labels. |
| */ |
| function GeneralConfig(title, prefix, fields) { |
| this.title = title; |
| this.prefix = prefix; |
| this.fields = fields; |
| } |
| |
| GeneralConfig.prototype = { |
| /** |
| * Sets up the form for configuring all the preference values. |
| */ |
| buildAll: function() { |
| this.buildForm(); |
| this.loadForm(); |
| this.initForm(); |
| }, |
| |
| /** |
| * Dynamically builds web-form based on the list of preferences. |
| */ |
| buildForm: function() { |
| var buf = []; |
| |
| var section = $('section-template').cloneNode(true); |
| section.removeAttribute('id'); |
| var title = section.querySelector('.section-title'); |
| title.textContent = this.title; |
| |
| for (var i = 0; i < this.fields.length; i++) { |
| var field = this.fields[i]; |
| |
| var row = $('section-row-template').cloneNode(true); |
| row.removeAttribute('id'); |
| |
| var label = row.querySelector('.row-label'); |
| var input = row.querySelector('.input'); |
| var units = row.querySelector('.row-units'); |
| var reset = row.querySelector('.row-reset'); |
| |
| label.setAttribute('for', field.key); |
| label.innerHTML = field.label; |
| input.id = field.key; |
| input.min = field.min || 0; |
| |
| if (field.max) |
| input.max = field.max; |
| |
| input.step = field.step || 'any'; |
| |
| if (field.units) |
| units.innerHTML = field.units; |
| |
| reset.id = field.key + '-reset'; |
| gesture_config.updateResetButton(reset, true); |
| |
| section.querySelector('.section-properties').appendChild(row); |
| } |
| $('gesture-form').appendChild(section); |
| }, |
| |
| /** |
| * Initializes the form by adding appropriate event listeners to elements. |
| */ |
| initForm: function() { |
| for (var i = 0; i < this.fields.length; i++) { |
| var field = this.fields[i]; |
| var config = this; |
| $(field.key).onchange = (function(key) { |
| config.setPreferenceValue(key, $(key).value); |
| gesture_config.updateResetButton($(key + '-reset'), false); |
| gesture_config.updateResetAllButton(false); |
| }).bind(null, field.key); |
| $(field.key + '-reset').onclick = (function(key) { |
| config.resetPreferenceValue(key); |
| }).bind(null, field.key); |
| } |
| }, |
| |
| /** |
| * Requests preference values for all the relevant fields. |
| */ |
| loadForm: function() { |
| for (var i = 0; i < this.fields.length; i++) |
| this.updatePreferenceValue(this.fields[i].key); |
| }, |
| |
| /** |
| * Handles processing of "Reset All" button. |
| * Causes all form values to be updated based on current preference values. |
| * @return {boolean} Returns false. |
| */ |
| onReset: function() { |
| for (var i = 0; i < this.fields.length; i++) { |
| var field = this.fields[i]; |
| this.resetPreferenceValue(field.key); |
| } |
| return false; |
| }, |
| |
| /** |
| * Requests a preference setting's value. |
| * This method is asynchronous; the result is provided by a call to |
| * updatePreferenceValueResult. |
| * @param {string} prefName The name of the preference value being requested. |
| */ |
| updatePreferenceValue: function(prefName) { |
| chrome.send('updatePreferenceValue', [this.prefix + prefName]); |
| }, |
| |
| /** |
| * Sets a preference setting's value. |
| * @param {string} prefName The name of the preference value being set. |
| * @param {value} value The value to be associated with prefName. |
| */ |
| setPreferenceValue: function(prefName, value) { |
| chrome.send('setPreferenceValue', |
| [this.prefix + prefName, parseFloat(value)]); |
| }, |
| |
| /** |
| * Resets a preference to its default value and get that callback |
| * to updatePreferenceValueResult with the new value of the preference. |
| * @param {string} prefName The name of the requested preference. |
| */ |
| resetPreferenceValue: function(prefName) { |
| chrome.send('resetPreferenceValue', [this.prefix + prefName]); |
| } |
| }; |
| |
| /** |
| * Returns a GeneralConfig for configuring gestures.* preferences. |
| * @return {object} A GeneralConfig object. |
| */ |
| function GestureConfig() { |
| /** The title of the section for the gesture preferences. **/ |
| /** @const */ var GESTURE_TITLE = 'Gesture Configuration'; |
| |
| /** Common prefix of gesture preferences. **/ |
| /** @const */ var GESTURE_PREFIX = 'gesture.'; |
| |
| /** List of fields used to dynamically build form. **/ |
| var GESTURE_FIELDS = [ |
| { |
| key: 'fling_max_cancel_to_down_time_in_ms', |
| label: 'Maximum Cancel to Down Time for Tap Suppression', |
| units: 'milliseconds', |
| }, |
| { |
| key: 'fling_max_tap_gap_time_in_ms', |
| label: 'Maximum Tap Gap Time for Tap Suppression', |
| units: 'milliseconds', |
| }, |
| { |
| key: 'long_press_time_in_seconds', |
| label: 'Long Press Time', |
| units: 'seconds' |
| }, |
| { |
| key: 'semi_long_press_time_in_seconds', |
| label: 'Semi Long Press Time', |
| units: 'seconds', |
| step: 0.1 |
| }, |
| { |
| key: 'show_press_delay_in_ms', |
| label: 'Delay before show press event is fired', |
| units: 'milliseconds', |
| }, |
| { |
| key: 'max_seconds_between_double_click', |
| label: 'Maximum Double Click Interval', |
| units: 'seconds', |
| step: 0.1 |
| }, |
| { |
| key: 'max_separation_for_gesture_touches_in_pixels', |
| label: 'Maximum Separation for Gesture Touches', |
| units: 'pixels' |
| }, |
| { |
| key: 'max_swipe_deviation_ratio', |
| label: 'Maximum Swipe Deviation', |
| units: '' |
| }, |
| { |
| key: 'max_touch_down_duration_in_seconds_for_click', |
| label: 'Maximum Touch-Down Duration for Click', |
| units: 'seconds', |
| step: 0.1 |
| }, |
| { |
| key: 'max_touch_move_in_pixels_for_click', |
| label: 'Maximum Touch-Move for Click', |
| units: 'pixels' |
| }, |
| { |
| key: 'max_distance_between_taps_for_double_tap', |
| label: 'Maximum Distance between two taps for Double Tap', |
| units: 'pixels' |
| }, |
| { |
| key: 'min_distance_for_pinch_scroll_in_pixels', |
| label: 'Minimum Distance for Pinch Scroll', |
| units: 'pixels' |
| }, |
| { |
| key: 'min_flick_speed_squared', |
| label: 'Minimum Flick Speed Squared', |
| units: '(pixels/sec.)<sup>2</sup>' |
| }, |
| { |
| key: 'min_pinch_update_distance_in_pixels', |
| label: 'Minimum Pinch Update Distance', |
| units: 'pixels' |
| }, |
| { |
| key: 'min_rail_break_velocity', |
| label: 'Minimum Rail-Break Velocity', |
| units: 'pixels/sec.' |
| }, |
| { |
| key: 'min_scroll_delta_squared', |
| label: 'Minimum Scroll Delta Squared', |
| units: '' |
| }, |
| { |
| key: 'min_scroll_successive_velocity_events', |
| label: 'Minimum Scroll Successive Velocity Events', |
| units: '' |
| }, |
| { |
| key: 'scroll_prediction_seconds', |
| label: 'Scroll prediction interval<br>' + |
| '(Enable scroll prediction in ' + |
| '<a href="chrome://flags">chrome://flags</a>)', |
| units: 'seconds', |
| step: 0.01 |
| }, |
| { |
| key: 'min_swipe_speed', |
| label: 'Minimum Swipe Speed', |
| units: 'pixels/sec.' |
| }, |
| { |
| key: 'min_touch_down_duration_in_seconds_for_click', |
| label: 'Minimum Touch-Down Duration for Click', |
| units: 'seconds', |
| step: 0.01 |
| }, |
| { |
| key: 'points_buffered_for_velocity', |
| label: 'Points Buffered for Velocity', |
| units: '', |
| step: 1 |
| }, |
| { |
| key: 'rail_break_proportion', |
| label: 'Rail-Break Proportion', |
| units: '%' |
| }, |
| { |
| key: 'rail_start_proportion', |
| label: 'Rail-Start Proportion', |
| units: '%' |
| }, |
| { |
| key: 'fling_acceleration_curve_coefficient_0', |
| label: 'Touchscreen Fling Acceleration', |
| units: 'x<sup>3</sup>', |
| min: '-1' |
| }, |
| { |
| key: 'fling_acceleration_curve_coefficient_1', |
| label: '+', |
| units: 'x<sup>2</sup>', |
| min: '-1' |
| }, |
| { |
| key: 'fling_acceleration_curve_coefficient_2', |
| label: '+', |
| units: 'x<sup>1</sup>', |
| min: '-1' |
| }, |
| { |
| key: 'fling_acceleration_curve_coefficient_3', |
| label: '+', |
| units: 'x<sup>0</sup>', |
| min: '-1' |
| }, |
| { |
| key: 'fling_velocity_cap', |
| label: 'Touchscreen Fling Velocity Cap', |
| units: 'pixels / second' |
| }, |
| { |
| key: 'tab_scrub_activation_delay_in_ms', |
| label: 'Tab scrub auto activation delay, (-1 for never)', |
| units: 'milliseconds' |
| } |
| ]; |
| |
| return new GeneralConfig(GESTURE_TITLE, GESTURE_PREFIX, GESTURE_FIELDS); |
| } |
| |
| /** |
| * Returns a GeneralConfig for configuring overscroll.* preferences. |
| * @return {object} A GeneralConfig object. |
| */ |
| function OverscrollConfig() { |
| /** @const */ var OVERSCROLL_TITLE = 'Overscroll Configuration'; |
| |
| /** @const */ var OVERSCROLL_PREFIX = 'overscroll.'; |
| |
| var OVERSCROLL_FIELDS = [ |
| { |
| key: 'horizontal_threshold_complete', |
| label: 'Complete when overscrolled (horizontal)', |
| units: '%' |
| }, |
| { |
| key: 'vertical_threshold_complete', |
| label: 'Complete when overscrolled (vertical)', |
| units: '%' |
| }, |
| { |
| key: 'minimum_threshold_start_touchpad', |
| label: 'Start overscroll gesture (horizontal; touchpad)', |
| units: 'pixels' |
| }, |
| { |
| key: 'minimum_threshold_start', |
| label: 'Start overscroll gesture (horizontal; touchscreen)', |
| units: 'pixels' |
| }, |
| { |
| key: 'vertical_threshold_start', |
| label: 'Start overscroll gesture (vertical)', |
| units: 'pixels' |
| }, |
| { |
| key: 'horizontal_resist_threshold', |
| label: 'Start resisting overscroll after (horizontal)', |
| units: 'pixels' |
| }, |
| { |
| key: 'vertical_resist_threshold', |
| label: 'Start resisting overscroll after (vertical)', |
| units: 'pixels' |
| }, |
| ]; |
| |
| return new GeneralConfig(OVERSCROLL_TITLE, |
| OVERSCROLL_PREFIX, |
| OVERSCROLL_FIELDS); |
| } |
| |
| /** |
| * Returns a GeneralConfig for configuring flingcurve.* preferences. |
| * @return {object} A GeneralConfig object. |
| */ |
| function FlingConfig() { |
| /** @const */ var FLING_TITLE = 'Fling Configuration'; |
| |
| /** @const */ var FLING_PREFIX = 'flingcurve.'; |
| |
| var FLING_FIELDS = [ |
| { |
| key: 'touchscreen_alpha', |
| label: 'Touchscreen fling deacceleration coefficients', |
| units: 'alpha', |
| min: '-inf' |
| }, |
| { |
| key: 'touchscreen_beta', |
| label: '', |
| units: 'beta', |
| min: '-inf' |
| }, |
| { |
| key: 'touchscreen_gamma', |
| label: '', |
| units: 'gamma', |
| min: '-inf' |
| }, |
| { |
| key: 'touchpad_alpha', |
| label: 'Touchpad fling deacceleration coefficients', |
| units: 'alpha', |
| min: '-inf' |
| }, |
| { |
| key: 'touchpad_beta', |
| label: '', |
| units: 'beta', |
| min: '-inf' |
| }, |
| { |
| key: 'touchpad_gamma', |
| label: '', |
| units: 'gamma', |
| min: '-inf' |
| }, |
| ]; |
| |
| return new GeneralConfig(FLING_TITLE, FLING_PREFIX, FLING_FIELDS); |
| } |
| |
| /** |
| * WebUI instance for configuring preference values related to gesture input. |
| */ |
| window.gesture_config = { |
| /** |
| * Build and initialize the gesture configuration form. |
| */ |
| initialize: function() { |
| var g = GestureConfig(); |
| g.buildAll(); |
| |
| var o = OverscrollConfig(); |
| o.buildAll(); |
| |
| var f = FlingConfig(); |
| f.buildAll(); |
| |
| $('reset-all-button').onclick = function() { |
| g.onReset(); |
| o.onReset(); |
| f.onReset(); |
| }; |
| }, |
| |
| /** |
| * Checks if all gesture preferences are set to default by checking the status |
| * of the reset button associated with each preference. |
| * @return {boolean} True if all gesture preferences are set to default. |
| */ |
| areAllPrefsSetToDefault: function() { |
| var resets = $('gesture-form').querySelectorAll('.row-reset'); |
| for (var i = 0; i < resets.length; i++) { |
| if (!resets[i].disabled) |
| return false; |
| } |
| return true; |
| }, |
| |
| /** |
| * Updates the status and label of a preference reset button. |
| * @param {HTMLInputElement} resetButton Reset button for the preference. |
| * @param {boolean} isDefault Whether the preference is set to the default |
| * value. |
| */ |
| updateResetButton: function(resetButton, isDefault) { |
| /** @const */ var TITLE_DEFAULT = 'Default'; |
| |
| /** @const */ var TITLE_NOT_DEFAULT = 'Reset'; |
| |
| resetButton.innerHTML = isDefault ? TITLE_DEFAULT : TITLE_NOT_DEFAULT; |
| resetButton.disabled = isDefault; |
| }, |
| |
| /** |
| * Updates the status and label of "Reset All" button. |
| * @param {boolean} isDefault Whether all preference are set to their default |
| * values. |
| */ |
| updateResetAllButton: function(isDefault) { |
| /** @const */ var TITLE_DEFAULT = 'Everything is set to default'; |
| |
| /** @const */ var TITLE_NOT_DEFAULT = 'Reset All To Default'; |
| |
| var button = $('reset-all-button'); |
| button.innerHTML = isDefault ? TITLE_DEFAULT : TITLE_NOT_DEFAULT; |
| button.disabled = isDefault; |
| }, |
| |
| /** |
| * Handle callback from call to updatePreferenceValue. |
| * @param {string} prefName The name of the requested preference value. |
| * @param {value} value The current value associated with prefName. |
| * @param {boolean} isDefault Whether the value is the default value. |
| */ |
| updatePreferenceValueResult: function(prefName, value, isDefault) { |
| prefName = prefName.substring(prefName.indexOf('.') + 1); |
| $(prefName).value = value; |
| this.updateResetButton($(prefName + '-reset'), isDefault); |
| this.updateResetAllButton(this.areAllPrefsSetToDefault()); |
| }, |
| }; |
| |
| document.addEventListener('DOMContentLoaded', gesture_config.initialize); |