| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 (function() { |
| 6 |
| 5 /** | 7 /** |
| 6 * @fileoverview | 8 * @fileoverview |
| 7 * night-light-slider is used to set the custom automatic schedule of the | 9 * night-light-slider is used to set the custom automatic schedule of the |
| 8 * Night Light feature, so that users can set their desired start and end | 10 * Night Light feature, so that users can set their desired start and end |
| 9 * times. | 11 * times. |
| 10 */ | 12 */ |
| 11 | 13 |
| 12 /** @const */ var HOURS_PER_DAY = 24; | 14 /** @const */ var HOURS_PER_DAY = 24; |
| 13 /** @const */ var MIN_KNOBS_DISTANCE_MINUTES = 30; | 15 /** @const */ var MIN_KNOBS_DISTANCE_MINUTES = 30; |
| 14 /** @const */ var OFFSET_MINUTES_6PM = 18 * 60; | 16 /** @const */ var OFFSET_MINUTES_6PM = 18 * 60; |
| 15 /** @const */ var TOTAL_MINUTES_PER_DAY = 24 * 60; | 17 /** @const */ var TOTAL_MINUTES_PER_DAY = 24 * 60; |
| 16 | 18 |
| 17 Polymer({ | 19 Polymer({ |
| 18 is: 'night-light-slider', | 20 is: 'night-light-slider', |
| 19 | 21 |
| 20 behaviors: [ | 22 behaviors: [ |
| 21 I18nBehavior, | |
| 22 PrefsBehavior, | 23 PrefsBehavior, |
| 23 Polymer.IronA11yKeysBehavior, | 24 Polymer.IronA11yKeysBehavior, |
| 25 Polymer.PaperInkyFocusBehavior, |
| 24 ], | 26 ], |
| 25 | 27 |
| 26 properties: { | 28 properties: { |
| 27 /** | 29 /** |
| 28 * The object currently being dragged. Either the start or end knobs. | |
| 29 * @type {?Object} | |
| 30 * @private | |
| 31 */ | |
| 32 dragObject_: { | |
| 33 type: Object, | |
| 34 value: null, | |
| 35 }, | |
| 36 | |
| 37 /** | |
| 38 * The start knob time as a string to be shown on the start label bubble. | 30 * The start knob time as a string to be shown on the start label bubble. |
| 39 * @private | 31 * @private |
| 40 */ | 32 */ |
| 41 startTime_: { | 33 startTime_: String, |
| 42 type: String, | |
| 43 }, | |
| 44 | 34 |
| 45 /** | 35 /** |
| 46 * The end knob time as a string to be shown on the end label bubble. | 36 * The end knob time as a string to be shown on the end label bubble. |
| 47 * @private | 37 * @private |
| 48 */ | 38 */ |
| 49 endTime_: { | 39 endTime_: String, |
| 50 type: String, | |
| 51 }, | |
| 52 }, | 40 }, |
| 53 | 41 |
| 54 observers: [ | 42 observers: [ |
| 55 'customTimesChanged_(prefs.ash.night_light.custom_start_time.*, ' + | 43 'customTimesChanged_(prefs.ash.night_light.custom_start_time.*, ' + |
| 56 'prefs.ash.night_light.custom_end_time.*)', | 44 'prefs.ash.night_light.custom_end_time.*)', |
| 57 ], | 45 ], |
| 58 | 46 |
| 59 keyBindings: { | 47 keyBindings: { |
| 60 'left': 'onLeftKey_', | 48 'left': 'onLeftKey_', |
| 61 'right': 'onRightKey_', | 49 'right': 'onRightKey_', |
| 62 }, | 50 }, |
| 63 | 51 |
| 52 /** |
| 53 * The object currently being dragged. Either the start or end knobs. |
| 54 * @type {?Object} |
| 55 * @private |
| 56 */ |
| 57 dragObject_: null, |
| 58 |
| 59 /** @override */ |
| 64 ready: function() { | 60 ready: function() { |
| 65 // Build the legend markers. | 61 // Build the legend markers. |
| 66 var markersContainer = this.$.markersContainer; | 62 var markersContainer = this.$.markersContainer; |
| 67 var width = markersContainer.offsetWidth; | 63 var width = markersContainer.offsetWidth; |
| 68 for (var i = 0; i <= HOURS_PER_DAY; ++i) { | 64 for (var i = 0; i <= HOURS_PER_DAY; ++i) { |
| 69 var marker = document.createElement('div'); | 65 var marker = document.createElement('div'); |
| 70 marker.className = 'markers'; | 66 marker.className = 'markers'; |
| 71 markersContainer.appendChild(marker); | 67 markersContainer.appendChild(marker); |
| 72 marker.style.left = (i * 100 / HOURS_PER_DAY) + '%'; | 68 marker.style.left = (i * 100 / HOURS_PER_DAY) + '%'; |
| 73 } | 69 } |
| 70 |
| 74 this.async(function() { | 71 this.async(function() { |
| 75 // Read the initial prefs values and refresh the slider. | 72 // Read the initial prefs values and refresh the slider. |
| 76 this.customTimesChanged_(); | 73 this.customTimesChanged_(); |
| 77 }); | 74 }); |
| 78 }, | 75 }, |
| 79 | 76 |
| 80 /** | 77 /** |
| 81 * Expands or un-expands the knob being dragged along with its corresponding | 78 * Expands or un-expands the knob being dragged along with its corresponding |
| 82 * label bubble. | 79 * label bubble. |
| 83 * @param {boolean} expand True to expand, and false to un-expand. | 80 * @param {boolean} expand True to expand, and false to un-expand. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 104 if (activeElement == this.$.startKnob || activeElement == this.$.endKnob) | 101 if (activeElement == this.$.startKnob || activeElement == this.$.endKnob) |
| 105 activeElement.blur(); | 102 activeElement.blur(); |
| 106 }, | 103 }, |
| 107 | 104 |
| 108 /** | 105 /** |
| 109 * Start dragging the target knob. | 106 * Start dragging the target knob. |
| 110 * @private | 107 * @private |
| 111 */ | 108 */ |
| 112 startDrag_: function(event) { | 109 startDrag_: function(event) { |
| 113 event.preventDefault(); | 110 event.preventDefault(); |
| 114 this.dragObject_ = event.target; | 111 |
| 112 // Only handle start or end knobs. Use the "knob-inner" divs just to display |
| 113 // the knobs. |
| 114 if (event.target == this.$.startKnob || |
| 115 event.target == this.$.startKnob.firstElementChild) { |
| 116 this.dragObject_ = this.$.startKnob; |
| 117 } else if (event.target == this.$.endKnob || |
| 118 event.target == this.$.endKnob.firstElementChild) { |
| 119 this.dragObject_ = this.$.endKnob; |
| 120 } else { |
| 121 return; |
| 122 } |
| 123 |
| 115 this.setExpanded_(true); | 124 this.setExpanded_(true); |
| 116 | 125 |
| 117 // Focus is only given to the knobs by means of keyboard tab navigations. | 126 // Focus is only given to the knobs by means of keyboard tab navigations. |
| 118 // When we start dragging, we don't want to see any focus halos around any | 127 // When we start dragging, we don't want to see any focus halos around any |
| 119 // knob. | 128 // knob. |
| 120 this.blurAnyFocusedKnob_(); | 129 this.blurAnyFocusedKnob_(); |
| 121 | 130 |
| 122 // However, our night-light-slider element must get the focus. | 131 // However, our night-light-slider element must get the focus. |
| 123 this.focus(); | 132 this.focus(); |
| 124 }, | 133 }, |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 * @private | 451 * @private |
| 443 */ | 452 */ |
| 444 onRightKey_: function(e) { | 453 onRightKey_: function(e) { |
| 445 e.preventDefault(); | 454 e.preventDefault(); |
| 446 var knobPref = this.getFocusedKnobPrefPathIfAny_(); | 455 var knobPref = this.getFocusedKnobPrefPathIfAny_(); |
| 447 if (!knobPref) | 456 if (!knobPref) |
| 448 return; | 457 return; |
| 449 | 458 |
| 450 this.incrementPref_(knobPref, 1); | 459 this.incrementPref_(knobPref, 1); |
| 451 }, | 460 }, |
| 452 }); | 461 |
| 462 /** |
| 463 * @return {boolean} Whether either of the two knobs is focused. |
| 464 * @private |
| 465 */ |
| 466 isEitherKnobFocused_: function() { |
| 467 var activeElement = this.shadowRoot.activeElement; |
| 468 return activeElement == this.$.startKnob || activeElement == this.$.endKnob; |
| 469 }, |
| 470 |
| 471 /** |
| 472 * Overrides _createRipple() from PaperInkyFocusBehavior to create the ripple |
| 473 * only on a knob if it's focused, or on a dummy hidden element so that it |
| 474 * doesn't show. |
| 475 * @private |
| 476 */ |
| 477 _createRipple: function() { |
| 478 if (this.isEitherKnobFocused_()) { |
| 479 this._rippleContainer = this.shadowRoot.activeElement; |
| 480 } else { |
| 481 // We can't just skip the ripple creation and return early with null here. |
| 482 // The code inherited from PaperInkyFocusBehavior expects that this |
| 483 // function returns a ripple element. So to avoid crashes, we'll setup the |
| 484 // ripple to be created under a hidden element. |
| 485 this._rippleContainer = this.$.dummyRippleContainer; |
| 486 } |
| 487 |
| 488 return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this); |
| 489 }, |
| 490 |
| 491 /** |
| 492 * Handles focus events on the start and end knobs. |
| 493 * @private |
| 494 */ |
| 495 onFocus_: function() { |
| 496 this.ensureRipple(); |
| 497 |
| 498 if (this.hasRipple()) { |
| 499 this._ripple.style.display = ''; |
| 500 this._ripple.holdDown = true; |
| 501 } |
| 502 }, |
| 503 |
| 504 /** |
| 505 * Handles blur events on the start and end knobs. |
| 506 * @private |
| 507 */ |
| 508 onBlur_: function() { |
| 509 if (this.hasRipple()) { |
| 510 this._ripple.remove(); |
| 511 this._ripple = null; |
| 512 } |
| 513 }, |
| 514 |
| 515 /** @private */ |
| 516 _focusedChanged: function(receivedFocusFromKeyboard) { |
| 517 // Overrides the _focusedChanged() from the PaperInkyFocusBehavior so that |
| 518 // it does nothing. This function is called only once for the entire |
| 519 // night-light-slider element even when focus is moved between the two |
| 520 // knobs. This doesn't allow us to decide on which knob the ripple will be |
| 521 // created. Hence we handle focus and blur explicitly above. |
| 522 } |
| 523 }); |
| 524 |
| 525 })(); |
| OLD | NEW |