src/js/widgets/sliderWidget.js
branchnew-model
changeset 874 38b65761a7d5
parent 842 4ae2247a59f4
equal deleted inserted replaced
872:d777d05a16e4 874:38b65761a7d5
     1 IriSP.SliderWidget = function(Popcorn, config, Serializer) {
     1 /*
     2   IriSP.Widget.call(this, Popcorn, config, Serializer);
     2  The Slider Widget fits right under the video
       
     3  */
       
     4 
       
     5 IriSP.SliderWidget = function(player, config) {
       
     6     IriSP.Widget.call(this, player, config);
       
     7     this.bindPopcorn("timeupdate","onTimeupdate");
       
     8     this.bindPopcorn("IriSP.PlayerWidget.MouseOver","onMouseover");
       
     9     this.bindPopcorn("IriSP.PlayerWidget.MouseOut","onMouseout");
     3 };
    10 };
     4 
    11 
     5 IriSP.SliderWidget.prototype = new IriSP.Widget();
    12 IriSP.SliderWidget.prototype = new IriSP.Widget();
     6 
    13 
     7 IriSP.SliderWidget.prototype.draw = function() {
    14 IriSP.SliderWidget.prototype.draw = function() {
     8   var self = this;
    15     
     9 
    16     this.$slider = IriSP.jQuery('<div>')
    10   this.selector.append(Mustache.to_html(IriSP.sliderWidget_template, {}));
    17         .addClass("Ldt-Slider")
    11   this.selector.addClass("Ldt-SliderMinimized");
    18         .css(this.calculateSliderCss(this.minimized_height));
    12 
    19     
    13   this.sliderBackground = this.selector.find(".Ldt-sliderBackground");
    20     this.$.append(this.$slider);
    14   this.sliderForeground = this.selector.find(".Ldt-sliderForeground");
    21     
    15   this.positionMarker = this.selector.find(".Ldt-sliderPositionMarker");
    22     var _this = this;
    16 
    23     
    17 
    24     this.$slider.slider({
    18   // a special variable to stop methods from tinkering
    25         range: "min",
    19   // with the positionMarker when the user is dragging it
    26         value: 0,
    20   this.draggingOngoing = false;
    27         min: 0,
    21 
    28         max: this.source.getDuration().getSeconds(),
    22   // another special variable used by the timeout handler to
    29         slide: function(event, ui) {
    23   // open or close the slider.
    30             _this.player.popcorn.currentTime(ui.value);
    24   this.sliderMaximized = false;
    31         }
    25   this.timeOutId = null;
    32     });
    26 
    33     
    27   
    34     this.$handle = this.$slider.find('.ui-slider-handle');
    28   this.positionMarker.draggable({axis: "x",
    35     
    29   start: IriSP.wrap(this, this.positionMarkerDraggingStartedHandler),
    36     this.$handle.css(this.calculateHandleCss(this.minimized_height));
    30   stop: IriSP.wrap(this, this.positionMarkerDraggedHandler),
    37     
    31   containment: "parent"
    38     this.$
    32   });
    39         .mouseover(this.functionWrapper("onMouseover"))
    33   this.positionMarker.css("position", "absolute");
    40         .mouseout(this.functionWrapper("onMouseout"));
    34   
    41     
    35   this.sliderBackground.click(function(event) { self.backgroundClickHandler.call(self, event); });
    42     this.maximized = false;
    36   this.sliderForeground.click(function(event) { self.foregroundClickHandler.call(self, event); });
    43     this.timeoutId = false;
    37 
       
    38   this.selector.hover(IriSP.wrap(this, this.mouseOverHandler), IriSP.wrap(this, this.mouseOutHandler));
       
    39 
       
    40   // update the positions
       
    41   this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater));
       
    42 
       
    43   // special messages :
       
    44   this._Popcorn.listen("IriSP.PlayerWidget.MouseOver", IriSP.wrap(this, this.mouseOverHandler));
       
    45   this._Popcorn.listen("IriSP.PlayerWidget.MouseOut", IriSP.wrap(this, this.mouseOutHandler));
       
    46 };
    44 };
    47 
    45 
    48 /* update the slider and the position marker as time passes */
    46 IriSP.SliderWidget.prototype.onTimeupdate = function() {
    49 IriSP.SliderWidget.prototype.sliderUpdater = function() {
    47     this.$slider.slider("value",this.player.popcorn.currentTime());
    50   if(this.draggingOngoing || this._disableUpdate)
    48 }
    51     return;
       
    52   
       
    53   var time = this._Popcorn.currentTime();
       
    54 
    49 
    55   var duration = this.getDuration() / 1000;
    50 IriSP.SliderWidget.prototype.onMouseover = function() {
    56   var percents = time / duration;
    51     if (this.timeoutId) {
    57   
    52         window.clearTimeout(this.timeoutId);
    58   /* we do these complicated calculations to center exactly
    53         this.timeoutId = false;
    59      the position Marker */
    54     }
       
    55     if (!this.maximized) {
       
    56        this.animateToHeight(this.maximized_height);
       
    57        this.maximized = true;
       
    58     }
       
    59 }
    60 
    60 
    61   var divWidth = this.selector.width();
    61 IriSP.SliderWidget.prototype.onMouseout = function() {
    62   var pixels = Math.floor(this.selector.width() * percents);
    62     if (this.timeoutId) {
    63   var positionMarker_width = this.positionMarker.width();
    63         window.clearTimeout(this.timeoutId);
    64   var correction = (positionMarker_width / 2);
    64         this.timeoutId = false;
       
    65     }
       
    66     var _this = this;
       
    67     this.timeoutId = window.setTimeout(function() {
       
    68         if (_this.maximized) {
       
    69             _this.animateToHeight(_this.minimized_height);
       
    70             _this.maximized = false;
       
    71         }
       
    72         _this.timeoutId = false;
       
    73     }, this.minimize_timeout);
       
    74     
       
    75 }
    65 
    76 
    66   /* check that we don't leave the left side */
    77 IriSP.SliderWidget.prototype.animateToHeight = function(_height) {
    67   var newPos = pixels - correction;
    78     this.$slider.stop().animate(
    68   if (newPos <= 0)
    79         this.calculateSliderCss(_height),
    69     newPos = 0;
    80         500,
    70   
    81         function() {
    71   /* check that we don't leave the right side */
    82             IriSP.jQuery(this).css("overflow","visible");
    72   var rightEdgePos = pixels + 1 * correction;
    83         });
       
    84     this.$handle.stop().animate(
       
    85         this.calculateHandleCss(_height),
       
    86         500,
       
    87         function() {
       
    88             IriSP.jQuery(this).css("overflow","visible");
       
    89         });
       
    90 }
    73 
    91 
    74   if (rightEdgePos >= divWidth)
    92 IriSP.SliderWidget.prototype.calculateSliderCss = function(_size) {
    75     newPos = divWidth - 1 * correction - 1;
    93     return {
    76   
    94         height: _size + "px",
    77   this.sliderForeground.css("width", pixels + "px");
    95         "margin-top": (this.minimized_height - _size) + "px"
    78   this.positionMarker.css("left", newPos + "px");
    96     };
       
    97 }
    79 
    98 
    80 };
    99 IriSP.SliderWidget.prototype.calculateHandleCss = function(_size) {
    81 
   100     return {
    82 IriSP.SliderWidget.prototype.backgroundClickHandler = function(event) {
   101         height: (2 + _size) + "px",
    83   /* this piece of code is a little bit convoluted - here's how it works :
   102         width: (2 + _size) + "px",
    84      we want to handle clicks on the progress bar and convert those to seeks in the media.
   103         "margin-left": -Math.ceil(2 + _size / 2) + "px" 
    85      However, jquery only gives us a global position, and we want a number of pixels relative
   104     }
    86      to our container div, so we get the parent position, and compute an offset to this position,
   105 }
    87      and finally compute the progress ratio in the media.
       
    88      Finally we multiply this ratio with the duration to get the correct time
       
    89   */
       
    90 
       
    91   var parentOffset = this.sliderBackground.parent().offset();
       
    92   var width = this.sliderBackground.width();
       
    93   var relX = event.pageX - parentOffset.left;
       
    94 
       
    95   var duration = this.getDuration() / 1000;
       
    96   var newTime = ((relX / width) * duration).toFixed(2);
       
    97 
       
    98   this._Popcorn.currentTime(newTime);
       
    99 };
       
   100 
       
   101 /* same function as the previous one, except that it handles clicks
       
   102    on the foreground element */
       
   103 IriSP.SliderWidget.prototype.foregroundClickHandler = function(event) {
       
   104   var parentOffset = this.sliderForeground.parent().offset();
       
   105   var width = this.sliderBackground.width();
       
   106   var relX = event.pageX - parentOffset.left;
       
   107 
       
   108   var duration = this.getDuration() / 1000;
       
   109   var newTime = ((relX / width) * duration).toFixed(2);
       
   110 
       
   111   this._Popcorn.currentTime(newTime);
       
   112 };
       
   113 
       
   114 /* handles mouse over the slider */
       
   115 IriSP.SliderWidget.prototype.mouseOverHandler = function(event) {
       
   116   
       
   117   if (this.timeOutId !== null) {
       
   118     window.clearTimeout(this.timeOutId);
       
   119   }
       
   120  
       
   121   this.sliderMaximized = true;
       
   122 
       
   123   this.sliderBackground.animate({"height": "9px"}, 100);
       
   124   this.sliderForeground.animate({"height": "9px"}, 100);
       
   125   this.positionMarker.animate({"height": "9px", "width": "9px"}, 100);
       
   126   //this.positionMarker.css("margin-top", "-4px");
       
   127   
       
   128 //  this.selector.removeClass("Ldt-SliderMinimized");
       
   129 //  this.selector.addClass("Ldt-SliderMaximized");
       
   130 };
       
   131 
       
   132 /* handles when the mouse leaves the slider */
       
   133 IriSP.SliderWidget.prototype.mouseOutHandler = function(event) {
       
   134 
       
   135   this.timeOutId = window.setTimeout(IriSP.wrap(this, this.minimizeOnTimeout),
       
   136                                      this.minimize_period);
       
   137 };
       
   138 
       
   139 IriSP.SliderWidget.prototype.minimizeOnTimeout = function(event) {
       
   140   this.sliderBackground.animate({"height": "5px"}, 100);
       
   141   this.sliderForeground.animate({"height": "5px"}, 100);
       
   142   this.positionMarker.animate({"height": "5px", "width": "5px"}, 100);
       
   143   this.positionMarker.css("margin-top", "0px");
       
   144   this.sliderMinimized = true;
       
   145   
       
   146 //  this.selector.removeClass("Ldt-SliderMaximized");
       
   147 //  this.selector.addClass("Ldt-SliderMinimized");
       
   148 
       
   149 };
       
   150 
       
   151 // called when the user starts dragging the position indicator
       
   152 IriSP.SliderWidget.prototype.positionMarkerDraggingStartedHandler = function(event, ui) {  
       
   153   this.draggingOngoing = true;
       
   154 };
       
   155 
       
   156 IriSP.SliderWidget.prototype.positionMarkerDraggedHandler = function(event, ui) {   
       
   157 
       
   158 /*  this._disableUpdate = true; // disable slider position updates while dragging is ongoing.
       
   159   window.setTimeout(IriSP.wrap(this, function() { this._disableUpdate = false; }), 500);
       
   160 */
       
   161   var parentOffset = this.sliderForeground.parent().offset();
       
   162   var width = this.sliderBackground.width();
       
   163   var relX = event.originalEvent.pageX - parentOffset.left;
       
   164 
       
   165   var duration = this.getDuration() / 1000;
       
   166   var newTime = ((relX / width) * duration).toFixed(2);
       
   167   this._Popcorn.currentTime(newTime);
       
   168   
       
   169   this.draggingOngoing = false;
       
   170 };
       
   171