32 } |
32 } |
33 } |
33 } |
34 ); |
34 ); |
35 |
35 |
36 |
36 |
37 IriSP.PlayerWidget = function(Popcorn, config, Serializer) { |
37 IriSP.PlayerWidget = function(player, config) { |
38 IriSP.Widget.call(this, Popcorn, config, Serializer); |
38 IriSP.Widget.call(this, player, config); |
39 |
39 |
40 this._searchBlockOpen = false; |
|
41 this._searchLastValue = ""; |
40 this._searchLastValue = ""; |
42 }; |
41 }; |
43 |
42 |
44 IriSP.PlayerWidget.prototype = new IriSP.Widget(); |
43 IriSP.PlayerWidget.prototype = new IriSP.Widget(); |
45 |
44 |
46 IriSP.PlayerWidget.prototype.draw = function() { |
45 IriSP.PlayerWidget.prototype.draw = function() { |
47 var self = this; |
46 var _this = this, |
48 var width = this.width; |
47 _html = IriSP.templToHTML(IriSP.player_template, this); |
49 var height = this.height; |
48 |
50 var heightS = this.height-20; |
49 this.$.append(_html); |
51 |
50 |
52 var playerTempl = IriSP.templToHTML(IriSP.player_template, this._config); |
51 // Define blocks |
53 this.selector.append(playerTempl); |
52 this.$playButton = this.$.find(".Ldt-CtrlPlay"); |
54 |
53 this.$searchBlock = this.$.find(".LdtSearch"); |
55 this.selector.children(".Ldt-controler").show(); |
54 this.$searchInput = this.$.find(".LdtSearchInput"); |
56 |
55 this.$volumeBar = this.$.find(".Ldt-Ctrl-Volume-Bar"); |
57 // handle clicks by the user on the video. |
56 |
58 this._Popcorn.listen("play", IriSP.wrap(this, this.playButtonUpdater)); |
57 // handle events |
59 this._Popcorn.listen("pause", IriSP.wrap(this, this.playButtonUpdater)); |
58 this.bindPopcorn("play","playButtonUpdater"); |
60 |
59 this.bindPopcorn("pause","playButtonUpdater"); |
61 this._Popcorn.listen("volumechange", IriSP.wrap(this, this.volumeUpdater)); |
60 this.bindPopcorn("volumechange","volumeUpdater"); |
62 |
61 this.bindPopcorn("timeupdate","timeDisplayUpdater"); |
63 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeDisplayUpdater)); |
62 this.bindPopcorn("loadedmetadata","timeDisplayUpdater"); |
64 // update the time display for the first time. |
63 this.bindPopcorn("IriSP.search.matchFound","searchMatch"); |
65 this._Popcorn.listen("loadedmetadata", IriSP.wrap(this, this.timeDisplayUpdater)); |
64 this.bindPopcorn("IriSP.search.noMatchFound","searchNoMatch"); |
66 |
65 this.bindPopcorn("IriSP.search.triggeredSearch","triggeredSearch"); |
67 this._Popcorn.listen("IriSP.search.matchFound", IriSP.wrap(this, this.searchMatch)); |
66 |
68 this._Popcorn.listen("IriSP.search.noMatchFound", IriSP.wrap(this, this.searchNoMatch)); |
67 // handle clicks |
69 this._Popcorn.listen("IriSP.search.triggeredSearch", IriSP.wrap(this, this.triggeredSearch)); |
68 this.$playButton.click(this.functionWrapper("playHandler")); |
70 |
69 |
71 |
70 this.$.find(".Ldt-CtrlAnnotate").click(function() { |
72 this.selector.find(".Ldt-CtrlPlay").click(function() { self.playHandler.call(self); }); |
71 _this.player.popcorn.trigger("IriSP.PlayerWidget.AnnotateButton.clicked"); |
73 this.selector.find(".Ldt-CtrlAnnotate").click(function() |
72 }); |
74 { self._Popcorn.trigger("IriSP.PlayerWidget.AnnotateButton.clicked"); }); |
73 this.$.find(".Ldt-CtrlSearch").click(this.functionWrapper("searchButtonHandler")); |
75 this.selector.find(".Ldt-CtrlSearch").click(function() { self.searchButtonHandler.call(self); }); |
74 |
76 |
75 this.$searchInput.keyup(this.functionWrapper("searchHandler") ); |
77 var _volctrl = this.selector.find(".Ldt-Ctrl-Volume-Control"); |
76 |
78 this.selector.find('.Ldt-CtrlSound') |
77 var _volctrl = this.$.find(".Ldt-Ctrl-Volume-Control"); |
79 .click(function() { self.muteHandler.call(self); } ) |
78 this.$.find('.Ldt-CtrlSound') |
|
79 .click(this.functionWrapper("muteHandler")) |
80 .mouseover(function() { |
80 .mouseover(function() { |
81 _volctrl.show(); |
81 _volctrl.show(); |
82 }) |
82 }) |
83 .mouseout(function() { |
83 .mouseout(function() { |
84 _volctrl.hide(); |
84 _volctrl.hide(); |
87 _volctrl.show(); |
87 _volctrl.show(); |
88 }).mouseout(function() { |
88 }).mouseout(function() { |
89 _volctrl.hide(); |
89 _volctrl.hide(); |
90 }); |
90 }); |
91 |
91 |
92 /* |
92 |
93 var searchButtonPos = this.selector.find(".Ldt-CtrlSearch").position(); |
93 // Allow Volume Cursor Dragging |
94 var searchBox = Mustache.to_html(IriSP.search_template, {margin_left : searchButtonPos.left + "px"}); |
94 this.$volumeBar.slider({ |
95 this.selector.find(".Ldt-CtrlSearch").after(searchBox); |
95 slide: function(event, ui) { |
96 */ |
96 _this.$volumeBar.attr("title",IriSP.i18n.getMessage('volume')+': ' + ui.value + '%'); |
97 |
97 _this.player.popcorn.volume(ui.value / 100); |
98 // trigger an IriSP.PlayerWidget.MouseOver to the widgets that are interested (i.e : sliderWidget) |
98 }, |
99 this.selector.hover(function() { self._Popcorn.trigger("IriSP.PlayerWidget.MouseOver"); }, |
99 stop: this.functionWrapper("volumeUpdater") |
100 function() { self._Popcorn.trigger("IriSP.PlayerWidget.MouseOut"); }); |
100 }); |
101 this.selector.find(".Ldt-Ctrl-Volume-Cursor").draggable({ |
101 |
102 axis: "x", |
102 // trigger an IriSP.PlayerWidget.MouseOver to the widgets that are interested (i.e : sliderWidget) |
103 drag: function(event, ui) { |
103 this.$.hover( |
104 var _vol = Math.max(0, Math.min( 1, ui.position.left / (ui.helper.parent().width() - ui.helper.outerWidth()))); |
104 function() { |
105 ui.helper.attr("title",IriSP.i18n.getMessage('volume')+': ' + Math.floor(100*_vol) + '%'); |
105 _this.player.popcorn.trigger("IriSP.PlayerWidget.MouseOver"); |
106 self._Popcorn.volume(_vol); |
106 }, |
107 }, |
107 function() { |
108 containment: "parent" |
108 _this.player.popcorn.trigger("IriSP.PlayerWidget.MouseOut"); |
109 }); |
109 }); |
110 |
110 setTimeout(this.functionWrapper("volumeUpdater"), 1000); |
111 setTimeout(function() { |
111 /* some players - including jwplayer - save the state of the mute button between sessions */ |
112 self.volumeUpdater(); |
|
113 }, 1000); /* some player - jwplayer notable - save the state of the mute button between sessions */ |
|
114 }; |
112 }; |
115 |
113 |
116 /* Update the elasped time div */ |
114 /* Update the elasped time div */ |
117 IriSP.PlayerWidget.prototype.timeDisplayUpdater = function() { |
115 IriSP.PlayerWidget.prototype.timeDisplayUpdater = function() { |
118 |
116 var _curTime = this.player.popcorn.roundTime(); |
119 if (this._previousSecond === undefined) { |
117 if (typeof this._previousSecond !== "undefined" && _curTime === this._previousSecond) { |
120 this._previousSecond = this._Popcorn.roundTime(); |
118 return; |
121 } |
119 } |
122 else { |
120 |
123 /* we're still in the same second, so it's not necessary to update time */ |
121 // we get it at each call because it may change. |
124 if (this._Popcorn.roundTime() == this._previousSecond) |
122 var _totalTime = this.source.getDuration(), |
125 return; |
123 _elapsedTime = new IriSP.Model.Time(); |
126 |
124 |
127 } |
125 _elapsedTime.setSeconds(_curTime); |
128 |
126 |
129 // we get it at each call because it may change. |
127 this.$.find(".Ldt-ElapsedTime").html(_elapsedTime.toString()); |
130 var duration = this.getDuration() / 1000; |
128 this.$.find(".Ldt-TotalTime").html(_totalTime.toString()); |
131 var totalTime = IriSP.secondsToTime(duration); |
129 this._previousSecond = _curTime; |
132 var elapsedTime = IriSP.secondsToTime(this._Popcorn.currentTime()); |
|
133 |
|
134 this.selector.find(".Ldt-ElapsedTime").html(elapsedTime.toString()); |
|
135 this.selector.find(".Ldt-TotalTime").html(totalTime.toString()); |
|
136 this._previousSecond = this._Popcorn.roundTime(); |
|
137 }; |
130 }; |
138 |
131 |
139 /* update the icon of the button - separate function from playHandler |
132 /* update the icon of the button - separate function from playHandler |
140 because in some cases (for instance, when the user directly clicks on |
133 because in some cases (for instance, when the user directly clicks on |
141 the jwplayer window) we have to change the icon without playing/pausing |
134 the jwplayer window) we have to change the icon without playing/pausing |
142 */ |
135 */ |
143 IriSP.PlayerWidget.prototype.playButtonUpdater = function() { |
136 IriSP.PlayerWidget.prototype.playButtonUpdater = function() { |
144 var status = this._Popcorn.media.paused; |
137 |
145 |
138 var status = this.player.popcorn.media.paused; |
146 if ( status == true ){ |
139 |
|
140 if (status) { |
147 /* the background sprite is changed by adding/removing the correct classes */ |
141 /* the background sprite is changed by adding/removing the correct classes */ |
148 this.selector.find(".Ldt-CtrlPlay").attr("title", IriSP.i18n.getMessage('play')); |
142 this.$playButton |
149 this.selector.find(".Ldt-CtrlPlay").removeClass("Ldt-CtrlPlay-PauseState").addClass("Ldt-CtrlPlay-PlayState"); |
143 .attr("title", IriSP.i18n.getMessage('play')) |
150 } else { |
144 .removeClass("Ldt-CtrlPlay-PauseState") |
151 this.selector.find(".Ldt-CtrlPlay").attr("title", IriSP.i18n.getMessage('pause')); |
145 .addClass("Ldt-CtrlPlay-PlayState"); |
152 this.selector.find(".Ldt-CtrlPlay").removeClass("Ldt-CtrlPlay-PlayState").addClass("Ldt-CtrlPlay-PauseState"); |
146 } else { |
153 } |
147 this.$playButton |
154 |
148 .attr("title", IriSP.i18n.getMessage('pause')) |
155 return; |
149 .removeClass("Ldt-CtrlPlay-PlayState") |
|
150 .addClass("Ldt-CtrlPlay-PauseState"); |
|
151 } |
156 }; |
152 }; |
157 |
153 |
158 |
154 |
159 IriSP.PlayerWidget.prototype.playHandler = function() { |
155 IriSP.PlayerWidget.prototype.playHandler = function() { |
160 var status = this._Popcorn.media.paused; |
156 |
161 |
157 var status = this.player.popcorn.media.paused; |
162 if ( status == true ){ |
158 |
163 this._Popcorn.play(); |
159 if (status) { |
164 } else { |
160 this.player.popcorn.play(); |
165 this._Popcorn.pause(); |
161 } else { |
166 } |
162 this.player.popcorn.pause(); |
|
163 } |
167 }; |
164 }; |
168 |
165 |
169 IriSP.PlayerWidget.prototype.muteHandler = function() { |
166 IriSP.PlayerWidget.prototype.muteHandler = function() { |
170 this._Popcorn.mute(!this._Popcorn.muted()); |
167 this.player.popcorn.mute(!this.player.popcorn.muted()); |
171 }; |
168 }; |
172 |
169 |
173 IriSP.PlayerWidget.prototype.volumeUpdater = function() { |
170 IriSP.PlayerWidget.prototype.volumeUpdater = function() { |
174 var _muted = this._Popcorn.muted(), |
171 var _muted = this.player.popcorn.muted(), |
175 _vol = this._Popcorn.volume(); |
172 _vol = this.player.popcorn.volume(); |
176 if (_vol === false) { |
173 if (_vol === false) { |
177 _vol = .5; |
174 _vol = .5; |
178 } |
175 } |
179 var _soundCtl = this.selector.find(".Ldt-CtrlSound"); |
176 var _soundCtl = this.$.find(".Ldt-CtrlSound"); |
180 _soundCtl.removeClass("Ldt-CtrlSound-Mute Ldt-CtrlSound-Half Ldt-CtrlSound-Full"); |
177 _soundCtl.removeClass("Ldt-CtrlSound-Mute Ldt-CtrlSound-Half Ldt-CtrlSound-Full"); |
181 if (_muted) { |
178 if (_muted) { |
182 _soundCtl.attr("title", IriSP.i18n.getMessage('unmute')) |
179 _soundCtl.attr("title", IriSP.i18n.getMessage('unmute')) |
183 .addClass("Ldt-CtrlSound-Mute"); |
180 .addClass("Ldt-CtrlSound-Mute"); |
184 } else { |
181 } else { |
185 _soundCtl.attr("title", IriSP.i18n.getMessage('mute')) |
182 _soundCtl.attr("title", IriSP.i18n.getMessage('mute')) |
186 .addClass(_vol < .5 ? "Ldt-CtrlSound-Half" : "Ldt-CtrlSound-Full" ) |
183 .addClass(_vol < .5 ? "Ldt-CtrlSound-Half" : "Ldt-CtrlSound-Full" ) |
187 } |
184 } |
188 var _cursor = this.selector.find(".Ldt-Ctrl-Volume-Cursor"); |
185 this.$volumeBar.slider("value", _muted ? 0 : 100 * _vol); |
189 _cursor.css({ |
|
190 "left": ( _muted ? 0 : Math.floor(_vol * (_cursor.parent().width() - _cursor.outerWidth())) ) + "px" |
|
191 }) |
|
192 }; |
186 }; |
193 |
187 |
194 IriSP.PlayerWidget.prototype.showSearchBlock = function() { |
188 IriSP.PlayerWidget.prototype.showSearchBlock = function() { |
195 var self = this; |
189 this.$searchBlock.show("blind", { direction: "horizontal"}, 100); |
196 |
190 this.$searchInput.css('background-color','#fff'); |
197 if (this._searchBlockOpen == false) { |
|
198 this.selector.find(".LdtSearch").show("blind", { direction: "horizontal"}, 100); |
|
199 this.selector.find(".LdtSearchInput").css('background-color','#fff'); |
|
200 |
191 |
201 this._searchBlockOpen = true; |
192 this.$searchInput.focus(); |
202 this.selector.find(".LdtSearchInput").bind('keyup', null, function() { self.searchHandler.call(self); } ); |
193 |
203 this.selector.find(".LdtSearchInput").focus(); |
194 // we need this variable because some widgets can find a match in |
204 |
195 // their data while at the same time others don't. As we want the |
205 // we need this variable because some widget can find a match in |
|
206 // their data while at the same time other's don't. As we want the |
|
207 // search field to become green when there's a match, we need a |
196 // search field to become green when there's a match, we need a |
208 // variable to remember that we had one. |
197 // variable to remember that we had one. |
209 this._positiveMatch = false; |
198 this._positiveMatch = false; |
210 |
199 |
211 // tell the world the field is open |
200 // tell the world the field is open |
212 this._Popcorn.trigger("IriSP.search.open"); |
201 this.player.popcorn.trigger("IriSP.search.open"); |
213 } |
|
214 }; |
202 }; |
215 |
203 |
216 IriSP.PlayerWidget.prototype.hideSearchBlock = function() { |
204 IriSP.PlayerWidget.prototype.hideSearchBlock = function() { |
217 if (this._searchBlockOpen == true) { |
205 this._searchLastValue = this.$searchInput.val(); |
218 this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value'); |
206 this.$searchInput.val(''); |
219 this.selector.find(".LdtSearchInput").attr('value',''); |
207 this.$searchBlock.hide("blind", { direction: "horizontal"}, 75); |
220 this.selector.find(".LdtSearch").hide("blind", { direction: "horizontal"}, 75); |
|
221 |
|
222 // unbind the watcher event. |
|
223 this.selector.find(".LdtSearchInput").unbind('keypress set'); |
|
224 this._searchBlockOpen = false; |
|
225 |
208 |
226 this._positiveMatch = false; |
209 this._positiveMatch = false; |
227 |
210 |
228 this._Popcorn.trigger("IriSP.search.closed"); |
211 this.player.popcorn.trigger("IriSP.search.closed"); |
229 } |
|
230 }; |
212 }; |
231 |
213 |
232 /** react to clicks on the search button */ |
214 /** react to clicks on the search button */ |
233 IriSP.PlayerWidget.prototype.searchButtonHandler = function() { |
215 IriSP.PlayerWidget.prototype.searchButtonHandler = function() { |
234 var self = this; |
216 |
235 |
217 if ( this.$searchBlock.is(":hidden") ) { |
236 /* show the search field if it is not shown */ |
218 this.showSearchBlock(); |
237 if ( this._searchBlockOpen == false ) { |
219 this.$searchInput.val(this._searchLastValue); |
238 this.showSearchBlock(); |
220 this.player.popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural. |
239 this.selector.find(".LdtSearchInput").attr('value', this._searchLastValue); |
|
240 this._Popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural. |
|
241 } else { |
221 } else { |
242 this.hideSearchBlock(); |
222 this.hideSearchBlock(); |
243 } |
223 } |
244 }; |
224 }; |
245 |
225 |
246 /** this handler is called whenever the content of the search |
226 /** this handler is called whenever the content of the search |
247 field changes */ |
227 field changes */ |
248 IriSP.PlayerWidget.prototype.searchHandler = function() { |
228 IriSP.PlayerWidget.prototype.searchHandler = function() { |
249 this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value'); |
229 this._searchLastValue = this.$searchInput.val(); |
250 this._positiveMatch = false; |
230 this._positiveMatch = false; |
251 |
231 |
252 // do nothing if the search field is empty, instead of highlighting everything. |
232 // do nothing if the search field is empty, instead of highlighting everything. |
253 if (this._searchLastValue == "") { |
233 if (this._searchLastValue == "") { |
254 this._Popcorn.trigger("IriSP.search.cleared"); |
234 this.player.popcorn.trigger("IriSP.search.cleared"); |
255 this.selector.find(".LdtSearchInput").css('background-color',''); |
235 this.$searchInput.css('background-color',''); |
256 } else { |
236 } else { |
257 this._Popcorn.trigger("IriSP.search", this._searchLastValue); |
237 this.player.popcorn.trigger("IriSP.search", this._searchLastValue); |
258 } |
238 } |
259 }; |
239 }; |
260 |
240 |
261 /** |
241 /** |
262 handler for the IriSP.search.found message, which is sent by some views when they |
242 handler for the IriSP.search.found message, which is sent by some views when they |
263 highlight a match. |
243 highlight a match. |
264 */ |
244 */ |
265 IriSP.PlayerWidget.prototype.searchMatch = function() { |
245 IriSP.PlayerWidget.prototype.searchMatch = function() { |
266 this._positiveMatch = true; |
246 this._positiveMatch = true; |
267 this.selector.find(".LdtSearchInput").css('background-color','#e1ffe1'); |
247 this.$searchInput.css('background-color','#e1ffe1'); |
268 }; |
248 }; |
269 |
249 |
270 /** the same, except that no value could be found */ |
250 /** the same, except that no value could be found */ |
271 IriSP.PlayerWidget.prototype.searchNoMatch = function() { |
251 IriSP.PlayerWidget.prototype.searchNoMatch = function() { |
272 if (this._positiveMatch !== true) |
252 if (this._positiveMatch !== true) { |
273 this.selector.find(".LdtSearchInput").css('background-color', "#d62e3a"); |
253 this.$searchInput.css('background-color', "#d62e3a"); |
|
254 } |
274 }; |
255 }; |
275 |
256 |
276 /** react to an IriSP.Player.triggeredSearch - that is, when |
257 /** react to an IriSP.Player.triggeredSearch - that is, when |
277 a widget ask the PlayerWidget to do a search on his behalf */ |
258 a widget ask the PlayerWidget to do a search on his behalf */ |
278 IriSP.PlayerWidget.prototype.triggeredSearch = function(searchString) { |
259 IriSP.PlayerWidget.prototype.triggeredSearch = function(searchString) { |
279 this.showSearchBlock(); |
260 this.showSearchBlock(); |
280 this.selector.find(".LdtSearchInput").attr('value', searchString); |
261 this.$searchInput.attr('value', searchString); |
281 this._Popcorn.trigger("IriSP.search", searchString); // trigger the search to make it more natural. |
262 this.player.popcorn.trigger("IriSP.search", searchString); // trigger the search to make it more natural. |
282 }; |
263 }; |
283 |
264 |
284 |
265 |