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 |