web/res/metadataplayer/Controller.js
changeset 694 e9400c80e1e4
parent 654 a5977736d2b0
child 719 d0d3a9369f84
equal deleted inserted replaced
690:ff11367d4955 694:e9400c80e1e4
     1 /* Displays Play and Pause buttons, Search Button and Form, Volume Control */
     1 /* Displays Play and Pause buttons, Search Button and Form, Volume Control */
     2 
     2 
     3 IriSP.Widgets.Controller = function(player, config) {
     3 IriSP.Widgets.Controller = function(player, config) {
     4   IriSP.Widgets.Widget.call(this, player, config);
     4     IriSP.Widgets.Widget.call(this, player, config);
     5   
     5     this.lastSearchValue = "";
     6   this._searchLastValue = "";
       
     7 };
     6 };
     8 
     7 
     9 IriSP.Widgets.Controller.prototype = new IriSP.Widgets.Widget();
     8 IriSP.Widgets.Controller.prototype = new IriSP.Widgets.Widget();
    10 
     9 
    11 IriSP.Widgets.Controller.prototype.defaults = {
    10 IriSP.Widgets.Controller.prototype.defaults = {
    12     disable_annotate_btn: false,
    11     disable_annotate_btn: false,
    13     disable_search_btn: false
    12     disable_search_btn: false,
       
    13     disable_ctrl_f: false
    14 }
    14 }
    15 
    15 
    16 IriSP.Widgets.Controller.prototype.template =
    16 IriSP.Widgets.Controller.prototype.template =
    17     '<div class="Ldt-Ctrl">'
    17     '<div class="Ldt-Ctrl">'
    18     + '<div class="Ldt-Ctrl-Left">'
    18     + '<div class="Ldt-Ctrl-Left">'
    85     this.$searchBlock = this.$.find(".Ldt-Ctrl-Search");
    85     this.$searchBlock = this.$.find(".Ldt-Ctrl-Search");
    86     this.$searchInput = this.$.find(".Ldt-Ctrl-SearchInput");
    86     this.$searchInput = this.$.find(".Ldt-Ctrl-SearchInput");
    87     this.$volumeBar = this.$.find(".Ldt-Ctrl-Volume-Bar");
    87     this.$volumeBar = this.$.find(".Ldt-Ctrl-Volume-Bar");
    88     
    88     
    89     // handle events
    89     // handle events
    90     this.bindPopcorn("play","playButtonUpdater");
    90     this.onMediaEvent("play","playButtonUpdater");
    91     this.bindPopcorn("pause","playButtonUpdater");
    91     this.onMediaEvent("pause","playButtonUpdater");
    92     this.bindPopcorn("volumechange","volumeUpdater");
    92     this.onMediaEvent("volumechange","volumeUpdater");
    93     this.bindPopcorn("timeupdate","timeDisplayUpdater");
    93     this.onMediaEvent("timeupdate","timeDisplayUpdater");
    94     this.bindPopcorn("loadedmetadata","timeDisplayUpdater");
    94     this.onMediaEvent("loadedmetadata","volumeUpdater");
    95     this.bindPopcorn("loadedmetadata","volumeUpdater");
    95     this.onMdpEvent("search.matchFound","searchMatch");
    96     this.bindPopcorn("IriSP.search.matchFound","searchMatch");
    96     this.onMdpEvent("search.noMatchFound","searchNoMatch");
    97     this.bindPopcorn("IriSP.search.noMatchFound","searchNoMatch");
    97     this.onMdpEvent("search.triggeredSearch","triggeredSearch");
    98     this.bindPopcorn("IriSP.search.triggeredSearch","triggeredSearch");
    98     this.onMdpEvent("search.cleared","hideSearchBlock");
    99     
    99     
   100     // handle clicks
   100     // handle clicks
   101     this.$playButton.click(this.functionWrapper("playHandler"));
   101     this.$playButton.click(this.functionWrapper("playHandler"));
   102     
   102     
   103     this.$.find(".Ldt-Ctrl-Annotate").click(function() {
   103     this.$.find(".Ldt-Ctrl-Annotate").click(function() {
   104         _this.player.popcorn.trigger("IriSP.CreateAnnotation.toggle");
   104         _this.player.trigger("CreateAnnotation.toggle");
   105     });
   105     });
   106     this.$.find(".Ldt-Ctrl-SearchBtn").click(this.functionWrapper("searchButtonHandler"));
   106     this.$.find(".Ldt-Ctrl-SearchBtn").click(this.functionWrapper("searchButtonHandler"));
   107     
   107     
   108     this.$searchInput.keyup(this.functionWrapper("searchHandler") );
   108     this.$searchInput.keyup(this.functionWrapper("searchHandler"));
   109   
   109   
   110 	var _volctrl = this.$.find(".Ldt-Ctrl-Volume-Control");
   110 	var _volctrl = this.$.find(".Ldt-Ctrl-Volume-Control");
   111     this.$.find('.Ldt-Ctrl-Sound')
   111     this.$.find('.Ldt-Ctrl-Sound')
   112         .click(this.functionWrapper("muteHandler"))
   112         .click(this.functionWrapper("muteHandler"))
   113         .mouseover(function() {
   113         .mouseover(function() {
   119     _volctrl.mouseover(function() {
   119     _volctrl.mouseover(function() {
   120         _volctrl.show();
   120         _volctrl.show();
   121     }).mouseout(function() {
   121     }).mouseout(function() {
   122         _volctrl.hide();
   122         _volctrl.hide();
   123     });
   123     });
   124   
   124     
       
   125     // Handle CTRL-F
       
   126     if (!this.disable_ctrl_f) {
       
   127         var _fKey = "F".charCodeAt(0),
       
   128             _lastCtrlFTime = 0;
       
   129         IriSP.jQuery(document).keydown(function(_event) {
       
   130             if (_event.keyCode === _fKey && (_event.ctrlKey || _event.metaKey)) {
       
   131                 var _time = IriSP.jQuery.now();
       
   132                 if (_time - _lastCtrlFTime > 2000) {
       
   133                     _this.searchButtonHandler();
       
   134                 }
       
   135                 _lastCtrlFTime = _time;
       
   136                 return false;
       
   137             }
       
   138         });
       
   139     }
   125     
   140     
   126     // Allow Volume Cursor Dragging
   141     // Allow Volume Cursor Dragging
   127     this.$volumeBar.slider({
   142     this.$volumeBar.slider({
   128         slide: function(event, ui) {
   143         slide: function(event, ui) {
   129             _this.$volumeBar.attr("title",_this.l10n.volume+': ' + ui.value + '%');
   144             _this.$volumeBar.attr("title",_this.l10n.volume+': ' + ui.value + '%');
   130             _this.player.popcorn.volume(ui.value / 100);
   145             _this.media.setVolume(ui.value / 100);
   131         },
   146         },
   132         stop: this.functionWrapper("volumeUpdater")
   147         stop: this.functionWrapper("volumeUpdater")
   133     });
   148     });
   134 
   149 
   135     // trigger an IriSP.Player.MouseOver to the widgets that are interested (i.e : sliderWidget)
   150     // trigger an IriSP.Player.MouseOver to the widgets that are interested (i.e : sliderWidget)
   136     this.$.hover(
   151     this.$.hover(
   137         function() {
   152         function() {
   138             _this.player.popcorn.trigger("IriSP.Player.MouseOver");
   153             _this.player.trigger("Player.MouseOver");
   139         }, 
   154         }, 
   140         function() {
   155         function() {
   141             _this.player.popcorn.trigger("IriSP.Player.MouseOut");
   156             _this.player.trigger("Player.MouseOut");
   142         });
   157         });
       
   158     
       
   159     this.timeDisplayUpdater(new IriSP.Model.Time(0));
   143     /* some players - including jwplayer - save the state of the mute button between sessions */
   160     /* some players - including jwplayer - save the state of the mute button between sessions */
   144 
   161    //TODO: MOVE TO THE PLAYER/
   145     window.setTimeout(this.functionWrapper("volumeUpdater"), 1000);
   162     window.setTimeout(this.functionWrapper("volumeUpdater"), 1000);
   146    
   163    
   147 };
   164 };
   148 
   165 
   149 /* Update the elasped time div */
   166 /* Update the elasped time div */
   150 IriSP.Widgets.Controller.prototype.timeDisplayUpdater = function() {
   167 IriSP.Widgets.Controller.prototype.timeDisplayUpdater = function(_time) {
   151     var _curTime = this.player.popcorn.roundTime();
       
   152     if (typeof this._previousSecond !== "undefined" && _curTime === this._previousSecond) {
       
   153         return;
       
   154     }
       
   155   
   168   
   156     // we get it at each call because it may change.
   169     // we get it at each call because it may change.
   157     var _totalTime = this.source.getDuration(),
   170     var _totalTime = this.media.duration;
   158         _elapsedTime = new IriSP.Model.Time();
   171     this.$.find(".Ldt-Ctrl-Time-Elapsed").html(_time.toString());
   159         
       
   160     _elapsedTime.setSeconds(_curTime);
       
   161   
       
   162     this.$.find(".Ldt-Ctrl-Time-Elapsed").html(_elapsedTime.toString());
       
   163     this.$.find(".Ldt-Ctrl-Time-Total").html(_totalTime.toString());
   172     this.$.find(".Ldt-Ctrl-Time-Total").html(_totalTime.toString());
   164     this._previousSecond = _curTime;
       
   165 };
   173 };
   166 
   174 
   167 /* update the icon of the button - separate function from playHandler
   175 /* update the icon of the button - separate function from playHandler
   168    because in some cases (for instance, when the user directly clicks on
   176    because in some cases (for instance, when the user directly clicks on
   169    the jwplayer window) we have to change the icon without playing/pausing
   177    the jwplayer window) we have to change the icon without playing/pausing
   170 */
   178 */
   171 IriSP.Widgets.Controller.prototype.playButtonUpdater = function() {
   179 IriSP.Widgets.Controller.prototype.playButtonUpdater = function() {
   172     
   180     if (this.media.getPaused()) {
   173     var status = this.player.popcorn.media.paused;
       
   174   
       
   175     if (status) {
       
   176     /* the background sprite is changed by adding/removing the correct classes */
   181     /* the background sprite is changed by adding/removing the correct classes */
   177         this.$playButton
   182         this.$playButton
   178             .attr("title", this.l10n.play)
   183             .attr("title", this.l10n.play)
   179             .removeClass("Ldt-Ctrl-Play-PauseState")
   184             .removeClass("Ldt-Ctrl-Play-PauseState")
   180             .addClass("Ldt-Ctrl-Play-PlayState");
   185             .addClass("Ldt-Ctrl-Play-PlayState");
   186     }
   191     }
   187 };
   192 };
   188 
   193 
   189 
   194 
   190 IriSP.Widgets.Controller.prototype.playHandler = function() {
   195 IriSP.Widgets.Controller.prototype.playHandler = function() {
   191     
   196     if (this.media.getPaused()) {        
   192     var status = this.player.popcorn.media.paused;
   197         this.media.play();
   193   
       
   194     if (status) {        
       
   195         this.player.popcorn.play();   
       
   196     } else {
   198     } else {
   197         this.player.popcorn.pause();
   199         this.media.pause();
   198     }  
   200     }  
   199 };
   201 };
   200 
   202 
   201 IriSP.Widgets.Controller.prototype.muteHandler = function() {
   203 IriSP.Widgets.Controller.prototype.muteHandler = function() {
   202     this.player.popcorn.muted(!this.player.popcorn.muted());
   204     if (this.media.getMuted()) {
       
   205         this.media.unmute();
       
   206     } else {
       
   207         this.media.mute();
       
   208     }
   203 };
   209 };
   204 
   210 
   205 IriSP.Widgets.Controller.prototype.volumeUpdater = function() {
   211 IriSP.Widgets.Controller.prototype.volumeUpdater = function() {
   206     var _muted = this.player.popcorn.muted(),
   212     var _muted = this.media.getMuted(),
   207         _vol = this.player.popcorn.volume();
   213         _vol = this.media.getVolume();
   208     if (_vol === false) {
   214     if (_vol === false) {
   209         _vol = .5;
   215         _vol = .5;
   210     }
   216     }
   211     var _soundCtl = this.$.find(".Ldt-Ctrl-Sound");
   217     var _soundCtl = this.$.find(".Ldt-Ctrl-Sound");
   212     _soundCtl.removeClass("Ldt-Ctrl-Sound-Mute Ldt-Ctrl-Sound-Half Ldt-Ctrl-Sound-Full");
   218     _soundCtl.removeClass("Ldt-Ctrl-Sound-Mute Ldt-Ctrl-Sound-Half Ldt-Ctrl-Sound-Full");
   219     }
   225     }
   220     this.$volumeBar.slider("value", _muted ? 0 : 100 * _vol);
   226     this.$volumeBar.slider("value", _muted ? 0 : 100 * _vol);
   221 };
   227 };
   222 
   228 
   223 IriSP.Widgets.Controller.prototype.showSearchBlock = function() {
   229 IriSP.Widgets.Controller.prototype.showSearchBlock = function() {
   224     this.$searchBlock.show("blind", { direction: "horizontal"}, 100);
   230     this.$searchBlock.animate({ width:"160px" }, 200);
   225     this.$searchInput.css('background-color','#fff');
   231     this.$searchInput.css('background-color','#fff');
   226    
   232    
   227     this.$searchInput.focus();
   233     this.$searchInput.focus();
   228     
   234     
   229     // we need this variable because some widgets can find a match in
   235     // we need this variable because some widgets can find a match in
   231     // search field to become green when there's a match, we need a 
   237     // search field to become green when there's a match, we need a 
   232     // variable to remember that we had one.
   238     // variable to remember that we had one.
   233     this._positiveMatch = false;
   239     this._positiveMatch = false;
   234 
   240 
   235     // tell the world the field is open
   241     // tell the world the field is open
   236     this.player.popcorn.trigger("IriSP.search.open");
   242     this.player.trigger("search.open");
   237 };
   243 };
   238 
   244 
   239 IriSP.Widgets.Controller.prototype.hideSearchBlock = function() {
   245 IriSP.Widgets.Controller.prototype.hideSearchBlock = function() {
   240     this._searchLastValue = this.$searchInput.val();
   246     this.$searchBlock.animate( { width: 0 }, 200);
   241     this.$searchInput.val('');
       
   242     this.$searchBlock.hide("blind", { direction: "horizontal"}, 75);
       
   243 
       
   244     this._positiveMatch = false;
   247     this._positiveMatch = false;
   245     
   248     this.player.trigger("search.closed");
   246     this.player.popcorn.trigger("IriSP.search.closed");
       
   247 };
   249 };
   248 
   250 
   249 /** react to clicks on the search button */
   251 /** react to clicks on the search button */
   250 IriSP.Widgets.Controller.prototype.searchButtonHandler = function() {
   252 IriSP.Widgets.Controller.prototype.searchButtonHandler = function() {
   251     if ( this.$searchBlock.is(":hidden") ) {
   253     if ( !this.$searchBlock.width() ) {
   252         this.showSearchBlock();
   254         this.showSearchBlock();
   253         this.$searchInput.val(this._searchLastValue);      
   255         var _val = this.$searchInput.val();
   254         this.player.popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural.
   256         if (_val) {
       
   257             this.player.trigger("search", _val); // trigger the search to make it more natural.
       
   258         }
   255 	} else {
   259 	} else {
   256         this.hideSearchBlock();
   260         this.hideSearchBlock();
   257     }
   261     }
   258 };
   262 };
   259 
   263 
   260 /** this handler is called whenever the content of the search
   264 /** this handler is called whenever the content of the search
   261    field changes */
   265    field changes */
   262 IriSP.Widgets.Controller.prototype.searchHandler = function() {
   266 IriSP.Widgets.Controller.prototype.searchHandler = function() {
   263     this._searchLastValue = this.$searchInput.val();
   267     if ( !this.$searchBlock.width() ) {
       
   268         this.$searchBlock.css({ width:"160px" });
       
   269         this.$searchInput.css('background-color','#fff');
       
   270     }
       
   271     var _val = this.$searchInput.val();
   264     this._positiveMatch = false;
   272     this._positiveMatch = false;
   265   
   273     
   266     // do nothing if the search field is empty, instead of highlighting everything.
   274     // do nothing if the search field is empty, instead of highlighting everything.
   267     if (this._searchLastValue == "") {
   275     if (_val !== this.lastSearchValue) {
   268         this.player.popcorn.trigger("IriSP.search.cleared");
   276         if (_val) {
   269         this.$searchInput.css('background-color','');
   277             this.player.trigger("search", _val);
   270     } else {
   278         } else {
   271         this.player.popcorn.trigger("IriSP.search", this._searchLastValue);
   279             this.player.trigger("search.cleared");
   272     }
   280             this.$searchInput.css('background-color','');
       
   281         }
       
   282     }
       
   283     this.lastSearchValue = _val;
   273 };
   284 };
   274 
   285 
   275 /**
   286 /**
   276   handler for the IriSP.search.found message, which is sent by some views when they
   287   handler for the IriSP.search.found message, which is sent by some views when they
   277   highlight a match.
   288   highlight a match.
   291 /** react to an IriSP.Player.triggeredSearch - that is, when
   302 /** react to an IriSP.Player.triggeredSearch - that is, when
   292     a widget ask the.Player to do a search on his behalf */
   303     a widget ask the.Player to do a search on his behalf */
   293 IriSP.Widgets.Controller.prototype.triggeredSearch = function(searchString) {
   304 IriSP.Widgets.Controller.prototype.triggeredSearch = function(searchString) {
   294     this.showSearchBlock();
   305     this.showSearchBlock();
   295     this.$searchInput.attr('value', searchString);      
   306     this.$searchInput.attr('value', searchString);      
   296     this.player.popcorn.trigger("IriSP.search", searchString); // trigger the search to make it more natural.
   307     this.player.trigger("search", searchString); // trigger the search to make it more natural.
   297 };
   308 };
   298 
   309 
   299 
   310