OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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() { | 5 (function() { |
6 'use strict'; | 6 'use strict'; |
7 | 7 |
8 /** | 8 /** |
9 * @constructor | 9 * @constructor |
10 * @extends {PolymerElement} | 10 * @extends {PolymerElement} |
11 */ | 11 */ |
12 var TrackListElement = function() {}; | 12 var TrackListElement = function() {}; |
13 | 13 |
14 TrackListElement.prototype = { | 14 TrackListElement.prototype = { |
| 15 is: 'track-list', |
| 16 |
| 17 properties: { |
| 18 /** |
| 19 * List of tracks. |
| 20 * @type {Array<AudioPlayer.TrackInfo>} |
| 21 */ |
| 22 tracks: { |
| 23 type: Array, |
| 24 value: [], |
| 25 observer: 'tracksChanged' |
| 26 }, |
| 27 |
| 28 /** |
| 29 * Track index of the current track. |
| 30 * If the tracks property is empty, it should be -1. Otherwise, be a valid |
| 31 * track number. |
| 32 */ |
| 33 currentTrackIndex: { |
| 34 type: Number, |
| 35 value: -1, |
| 36 observer: 'currentTrackIndexChanged', |
| 37 notify: true |
| 38 }, |
| 39 |
| 40 /** |
| 41 * Whether shuffling play order is enabled or not. |
| 42 */ |
| 43 shuffle: { |
| 44 type: Boolean, |
| 45 observer: 'shuffleChanged' |
| 46 } |
| 47 }, |
| 48 |
15 /** | 49 /** |
16 * Initializes an element. This method is called automatically when the | 50 * Initializes an element. This method is called automatically when the |
17 * element is ready. | 51 * element is ready. |
18 */ | 52 */ |
19 ready: function() { | 53 ready: function() { |
20 this.observeTrackList(); | 54 this.observeTrackList(); |
21 | 55 |
22 window.addEventListener('resize', this.onWindowResize_.bind(this)); | 56 window.addEventListener('resize', this.onWindowResize_.bind(this)); |
23 }, | 57 }, |
24 | 58 |
25 observeTrackList: function() { | 59 observeTrackList: function() { |
26 // Unobserve the previous track list. | 60 // Unobserve the previous track list. |
27 if (this.unobserveTrackList_) | 61 if (this.unobserveTrackList_) |
28 this.unobserveTrackList_(); | 62 this.unobserveTrackList_(); |
29 | 63 |
30 // Observe the new track list. | 64 // Observe the new track list. |
31 var observer = this.tracksValueChanged_.bind(this); | 65 var observer = this.tracksValueChanged_.bind(this); |
32 Array.observe(this.tracks, observer); | 66 Array.observe(this.tracks, observer); |
33 | 67 |
34 // Set the function to unobserve it. | 68 // Set the function to unobserve it. |
35 this.unobserveTrackList_ = function(tracks, observer) { | 69 this.unobserveTrackList_ = function(tracks, observer) { |
36 Array.unobserve(tracks, observer); | 70 Array.unobserve(tracks, observer); |
37 }.bind(null, this.tracks, observer); | 71 }.bind(null, this.tracks, observer); |
38 }, | 72 }, |
39 | 73 |
40 /** | 74 /** |
41 * Registers handlers for changing of external variables | |
42 */ | |
43 observe: { | |
44 'model.shuffle': 'onShuffleChanged', | |
45 }, | |
46 | |
47 /** | |
48 * Model object of the Audio Player. | |
49 * @type {AudioPlayerModel} | |
50 */ | |
51 model: null, | |
52 | |
53 /** | |
54 * List of tracks. | |
55 * @type {Array<AudioPlayer.TrackInfo>} | |
56 */ | |
57 tracks: [], | |
58 | |
59 /** | |
60 * Play order of the tracks. Each value is the index of 'this.tracks'. | 75 * Play order of the tracks. Each value is the index of 'this.tracks'. |
61 * @type {Array<number>} | 76 * @type {Array<number>} |
62 */ | 77 */ |
63 playOrder: [], | 78 playOrder: [], |
64 | 79 |
65 /** | 80 /** |
66 * Track index of the current track. | 81 * Invoked when 'shuffle' property is changed. |
67 * If the tracks property is empty, it should be -1. Otherwise, be a valid | 82 * @param {boolean} newValue New value. |
68 * track number. | 83 * @param {boolean} oldValue Old value. |
69 * | |
70 * @type {number} | |
71 */ | 84 */ |
72 currentTrackIndex: -1, | 85 shuffleChanged: function(newValue, oldValue) { |
73 | |
74 /** | |
75 * Invoked when 'shuffle' property is changed. | |
76 * @param {boolean} oldValue Old value. | |
77 * @param {boolean} newValue New value. | |
78 */ | |
79 onShuffleChanged: function(oldValue, newValue) { | |
80 this.generatePlayOrder(true /* keep the current track */); | 86 this.generatePlayOrder(true /* keep the current track */); |
81 }, | 87 }, |
82 | 88 |
83 /** | 89 /** |
84 * Invoked when the current track index is changed. | 90 * Invoked when the current track index is changed. |
| 91 * @param {number} newValue new value. |
85 * @param {number} oldValue old value. | 92 * @param {number} oldValue old value. |
86 * @param {number} newValue new value. | |
87 */ | 93 */ |
88 currentTrackIndexChanged: function(oldValue, newValue) { | 94 currentTrackIndexChanged: function(newValue, oldValue) { |
89 if (oldValue === newValue) | 95 if (oldValue === newValue) |
90 return; | 96 return; |
91 | 97 |
92 if (!isNaN(oldValue) && 0 <= oldValue && oldValue < this.tracks.length) | 98 if (!isNaN(oldValue) && 0 <= oldValue && oldValue < this.tracks.length) |
93 this.tracks[oldValue].active = false; | 99 this.set('tracks.' + oldValue + '.active', false); |
94 | 100 |
95 if (0 <= newValue && newValue < this.tracks.length) { | 101 if (0 <= newValue && newValue < this.tracks.length) { |
96 var currentPlayOrder = this.playOrder.indexOf(newValue); | 102 var currentPlayOrder = this.playOrder.indexOf(newValue); |
97 if (currentPlayOrder !== -1) { | 103 if (currentPlayOrder !== -1) { |
98 // Success | 104 // Success |
99 this.tracks[newValue].active = true; | 105 this.set('tracks.' + newValue + '.active', true); |
100 | 106 |
101 this.ensureTrackInViewport_(newValue /* trackIndex */); | 107 this.ensureTrackInViewport_(newValue /* trackIndex */); |
102 return; | 108 return; |
103 } | 109 } |
104 } | 110 } |
105 | 111 |
106 // Invalid index | 112 // Invalid index |
107 if (this.tracks.length === 0) | 113 if (this.tracks.length === 0) |
108 this.currentTrackIndex = -1; | 114 this.currentTrackIndex = -1; |
109 else | 115 else |
110 this.generatePlayOrder(false /* no need to keep the current track */); | 116 this.generatePlayOrder(false /* no need to keep the current track */); |
111 }, | 117 }, |
112 | 118 |
113 /** | 119 /** |
114 * Invoked when 'tracks' property is changed. | 120 * Invoked when 'tracks' property is changed. |
| 121 * @param {Array<AudioPlayer.TrackInfo>} newValue New value. |
115 * @param {Array<AudioPlayer.TrackInfo>} oldValue Old value. | 122 * @param {Array<AudioPlayer.TrackInfo>} oldValue Old value. |
116 * @param {Array<AudioPlayer.TrackInfo>} newValue New value. | |
117 */ | 123 */ |
118 tracksChanged: function(oldValue, newValue) { | 124 tracksChanged: function(newValue, oldValue) { |
119 // Note: Sometimes both oldValue and newValue are null though the actual | 125 // Note: Sometimes both oldValue and newValue are null though the actual |
120 // values are not null. Maybe it's a bug of Polymer. | 126 // values are not null. Maybe it's a bug of Polymer. |
121 | 127 |
122 // Re-register the observer of 'this.tracks'. | 128 // Re-register the observer of 'this.tracks'. |
123 this.observeTrackList(); | 129 this.observeTrackList(); |
124 | 130 |
125 if (this.tracks.length !== 0) { | 131 if (this.tracks.length !== 0) { |
126 // Restore the active track. | 132 // Restore the active track. |
127 if (this.currentTrackIndex !== -1 && | 133 if (this.currentTrackIndex !== -1 && |
128 this.currentTrackIndex < this.tracks.length) { | 134 this.currentTrackIndex < this.tracks.length) { |
129 this.tracks[this.currentTrackIndex].active = true; | 135 this.set('tracks.' + this.currentTrackIndex + '.active', true); |
130 } | 136 } |
131 | 137 |
132 // Reset play order and current index. | 138 // Reset play order and current index. |
133 this.generatePlayOrder(false /* no need to keep the current track */); | 139 this.generatePlayOrder(false /* no need to keep the current track */); |
134 } else { | 140 } else { |
135 this.playOrder = []; | 141 this.playOrder = []; |
136 this.currentTrackIndex = -1; | 142 this.currentTrackIndex = -1; |
137 } | 143 } |
138 }, | 144 }, |
139 | 145 |
140 /** | 146 /** |
141 * Invoked when the value in the 'tracks' is changed. | 147 * Invoked when the value in the 'tracks' is changed. |
142 * @param {Array<Object>} changes The detail of the change. | 148 * @param {Array<Object>} changes The detail of the change. |
143 */ | 149 */ |
144 tracksValueChanged_: function(changes) { | 150 tracksValueChanged_: function(changes) { |
145 if (this.tracks.length === 0) | 151 if (this.tracks.length === 0) |
146 this.currentTrackIndex = -1; | 152 this.currentTrackIndex = -1; |
147 else | 153 else |
148 this.tracks[this.currentTrackIndex].active = true; | 154 this.set('tracks.' + this.currentTrackIndex + '.active', true); |
149 }, | 155 }, |
150 | 156 |
151 /** | 157 /** |
152 * Invoked when the track element is clicked. | 158 * Invoked when the track element is clicked. |
153 * @param {Event} event Click event. | 159 * @param {Event} event Click event. |
154 */ | 160 */ |
155 trackClicked: function(event) { | 161 trackClicked: function(event) { |
156 var index = ~~event.currentTarget.getAttribute('index'); | 162 var index = ~~event.currentTarget.getAttribute('index'); |
157 var track = this.tracks[index]; | 163 var track = this.tracks[index]; |
158 if (track) | 164 if (track) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 if (this.tracks.length === 0) { | 211 if (this.tracks.length === 0) { |
206 this.playOrder = []; | 212 this.playOrder = []; |
207 return; | 213 return; |
208 } | 214 } |
209 | 215 |
210 // Creates sequenced array. | 216 // Creates sequenced array. |
211 this.playOrder = | 217 this.playOrder = |
212 this.tracks. | 218 this.tracks. |
213 map(function(unused, index) { return index; }); | 219 map(function(unused, index) { return index; }); |
214 | 220 |
215 if (this.model && this.model.shuffle) { | 221 if (this.shuffle) { |
216 // Randomizes the play order array (Schwarzian-transform algorithm). | 222 // Randomizes the play order array (Schwarzian-transform algorithm). |
217 this.playOrder = this.playOrder | 223 this.playOrder = this.playOrder |
218 .map(function(a) { | 224 .map(function(a) { |
219 return {weight: Math.random(), index: a}; | 225 return {weight: Math.random(), index: a}; |
220 }) | 226 }) |
221 .sort(function(a, b) { return a.weight - b.weight }) | 227 .sort(function(a, b) { return a.weight - b.weight }) |
222 .map(function(a) { return a.index }); | 228 .map(function(a) { return a.index }); |
223 | 229 |
224 if (keepCurrentTrack) { | 230 if (keepCurrentTrack) { |
225 // Puts the current track at the beginning of the play order. | 231 // Puts the current track at the beginning of the play order. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 | 311 |
306 var newTrackIndex = this.playOrder[newPlayOrder]; | 312 var newTrackIndex = this.playOrder[newPlayOrder]; |
307 console.assert( | 313 console.assert( |
308 (0 <= newTrackIndex && newTrackIndex < this.tracks.length), | 314 (0 <= newTrackIndex && newTrackIndex < this.tracks.length), |
309 'Insufficient TrackList.playOrder. New Play Order: ' + newPlayOrder); | 315 'Insufficient TrackList.playOrder. New Play Order: ' + newPlayOrder); |
310 | 316 |
311 return newTrackIndex; | 317 return newTrackIndex; |
312 }, | 318 }, |
313 }; // TrackListElement.prototype for 'track-list' | 319 }; // TrackListElement.prototype for 'track-list' |
314 | 320 |
315 Polymer('track-list', TrackListElement.prototype); | 321 Polymer(TrackListElement.prototype); |
316 })(); // Anonymous closure | 322 })(); // Anonymous closure |
OLD | NEW |