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