1 /*
  2  *  Copyright © 2009 Apple Inc. All rights reserved.
  3  */
  4 
  5 TKLyricsController.inherits = TKController;
  6 TKLyricsController.synthetizes = ['currentSong', 'previousSongButton', 'nextSongButton'];
  7 
  8 /**
  9  *  @class
 10  *
 11  *  <p>A lyrics controller is designed to make it easy to flip through a collection of lyrics. This controller type automatically wires the left and
 12  *  right keys to navigate between songs, and the author should leverage the {@link TKController#scrollableElement} property to identify the container
 13  *  for the scrolling lyrics region. Loading of new song content should be done using the {@link #songDidChange} method.</p>
 14  *
 15  *  @extends TKController
 16  *  @since TuneKit 1.0
 17  *
 18  *  @param {Object} data A hash of properties to use as this object is initialized.
 19  */
 20 function TKLyricsController (data) {
 21   /**
 22    *  The number of songs that the controller will be flipping through.
 23    *  @type int
 24    */
 25   this.numberOfSongs = 0;
 26   this.defaultToFirstSong = false;
 27   this._currentSong = null;
 28   this._previousSongButton = null;
 29   this._nextSongButton = null;
 30   //
 31   this.callSuper(data);
 32 };
 33 
 34 /* ==================== View Processing ==================== */
 35 
 36 TKLyricsController.prototype.processView = function () {
 37   this.callSuper();
 38   // restore properties that have not been set yet since construction
 39   this.restoreProperty('previousSongButton');
 40   this.restoreProperty('nextSongButton');
 41   this.restoreProperty('currentSong');
 42   // default to first song
 43   if (this.defaultToFirstSong && this._currentSong === null) {
 44     this.currentSong = 0;
 45   }
 46 };
 47 
 48 /* ==================== Keyboard Navigation ==================== */
 49 
 50 TKLyricsController.prototype.wantsToHandleKey = function (key) {
 51   return (key == KEYBOARD_LEFT || key == KEYBOARD_RIGHT) ? true : this.callSuper(key);
 52 };
 53 
 54 TKLyricsController.prototype.keyWasPressed = function (key) {
 55   // default action is move, so wire that up
 56   TKSpatialNavigationManager.soundToPlay = SOUND_MOVED;
 57   // left should go to the previous song
 58   if (key == KEYBOARD_LEFT) {
 59     this.goToPreviousSong();
 60   }
 61   // right should go to the next song
 62   else if (key == KEYBOARD_RIGHT) {
 63     this.goToNextSong();
 64   }
 65   // let the default behavior happen too
 66   this.callSuper(key);
 67 };
 68 
 69 /* ==================== Previous / Next Buttons ==================== */
 70 
 71 /**
 72  *  @name TKLyricsController.prototype
 73  *  @property {String} previousSongButton The CSS selector for the element acting as the trigger to navigate to the previous song.
 74  */
 75 TKLyricsController.prototype.setPreviousSongButton = function (previousSongButton) {
 76   if (previousSongButton === null || IS_APPLE_TV) {
 77     return;
 78   }
 79   // forget old button
 80   if (this._previousSongButton) {
 81     this.removeNavigableElement(this._previousSongButton);
 82   }
 83   // process new one
 84   if (previousSongButton !== null) {
 85     this._previousSongButton = this.view.querySelector(previousSongButton);
 86     if (this._previousSongButton !== null) {
 87       this.addNavigableElement(this._previousSongButton);
 88     }
 89   }
 90 };
 91 
 92 /**
 93  *  @name TKLyricsController.prototype
 94  *  @property {String} nextSongButton The CSS selector for the element acting as the trigger to navigate to the next song.
 95  */
 96 TKLyricsController.prototype.setNextSongButton = function (nextSongButton) {
 97   if (nextSongButton === null || IS_APPLE_TV) {
 98     return;
 99   }
100   // forget old button
101   if (this._nextSongButton) {
102     this.removeNavigableElement(this._nextSongButton);
103   }
104   // process new one
105   if (nextSongButton !== null) {
106     this._nextSongButton = this.view.querySelector(nextSongButton);
107     if (this._nextSongButton !== null) {
108       this.addNavigableElement(this._nextSongButton);
109     }
110   }
111 };
112 
113 TKLyricsController.prototype.elementWasActivated = function (element) {
114   // previous page button pressed
115   if (element === this._previousSongButton) {
116     this.goToPreviousSong();
117   }
118   // next page button pressed
119   else if (element === this._nextSongButton) {
120     this.goToNextSong();
121   }
122   // fall back to default behavior
123   else {
124     this.callSuper(element);
125   }
126 };
127 
128 /* ==================== Page Navigation ==================== */
129 
130 /**
131  *  Shows the previous song.
132  */
133 TKLyricsController.prototype.goToPreviousSong = function () {
134   this.currentSong = ((this._currentSong + this.numberOfSongs) - 1) % this.numberOfSongs;
135 };
136 
137 /**
138  *  Shows the next song.
139  */
140 TKLyricsController.prototype.goToNextSong = function () {
141   this.currentSong = (this._currentSong + 1) % this.numberOfSongs;
142 };
143 
144 /**
145  *  @name TKLyricsController.prototype
146  *  @property {int} currentSong The index of the current song. Whenever this value changes, the {@link #songDidChange} method is called.
147  */
148 TKLyricsController.prototype.setCurrentSong = function (song) {
149   if (song === null || song < 0 || song >= this.numberOfSongs) {
150     return;
151   }
152   // track what song we're on
153   this._currentSong = song;
154   // let our instance know that we've moved to a new song
155   this.songDidChange(song);
156 };
157 
158 /**
159  *  Triggered when a new song is displayed by the controller.
160  */
161 TKLyricsController.prototype.songDidChange = function (song) {};
162 
163 /* ==================== Archival ==================== */
164 
165 TKLyricsController.prototype.archive = function () {
166   var archive = this.callSuper();
167   archive.currentSong = this.currentSong;
168   return archive;
169 };
170 
171 TKClass(TKLyricsController);
172