src/js/widgets/stackGraphWidget.js
branchnew-model
changeset 882 61c384dda19e
parent 881 f11b234497f7
child 883 d35ad8111c5e
equal deleted inserted replaced
881:f11b234497f7 882:61c384dda19e
     1 IriSP.StackGraphWidget = function(Popcorn, config, Serializer) {
       
     2   IriSP.Widget.call(this, Popcorn, config, Serializer);
       
     3 }
       
     4 
       
     5 IriSP.StackGraphWidget.prototype = new IriSP.Widget();
       
     6 
       
     7 IriSP.StackGraphWidget.prototype.draw = function() {
       
     8     var _ = IriSP._;
       
     9     this.height =  this._config.height || 50;
       
    10     this.width = this.selector.width();
       
    11     this.slices = this._config.slices || ~~(this.width/(this.streamgraph ? 20 : 5));
       
    12     _(this.tags).each(function(_a) {
       
    13         _a.regexp = new RegExp(_(_a.keywords).map(function(_k) {
       
    14             return _k.replace(/([\W])/gm,'\\$1');
       
    15         }).join("|"),"im")
       
    16     });
       
    17     this.paper = new Raphael(this.selector[0], this.width, this.height);
       
    18     this.groups = [];
       
    19     this.duration = this.getDuration();
       
    20     
       
    21     var _annotationType = this._serializer.getTweets(),
       
    22         _sliceDuration = ~~ ( this.duration / this.slices),
       
    23         _annotations = this._serializer._data.annotations,
       
    24         _groupedAnnotations = _(_.range(this.slices)).map(function(_i) {
       
    25             return _(_annotations).filter(function(_a){
       
    26                 return (_a.begin <= (1 + _i) * _sliceDuration) && (_a.end >= _i * _sliceDuration)
       
    27             });
       
    28         }),
       
    29         _max = IriSP._(_groupedAnnotations).max(function(_g) {
       
    30             return _g.length
       
    31         }).length,
       
    32         _scale = this.height / _max,
       
    33         _width = this.width / this.slices,
       
    34         _showTitle = !this._config.excludeTitle,
       
    35         _showDescription = !this._config.excludeDescription;
       
    36     
       
    37     
       
    38     var _paths = _(this.tags).map(function() {
       
    39         return [];
       
    40     });
       
    41     _paths.push([]);
       
    42     
       
    43     for (var i = 0; i < this.slices; i++) {
       
    44         var _group = _groupedAnnotations[i];
       
    45         if (_group) {
       
    46             var _vol = _(this.tags).map(function() {
       
    47                 return 0;
       
    48             });
       
    49             for (var j = 0; j < _group.length; j++){
       
    50            var _txt = (_showTitle ? _group[j].content.title : '') + ' ' + (_showDescription ? _group[j].content.description : '')
       
    51                 var _tags = _(this.tags).map(function(_tag) {
       
    52                         return (_txt.search(_tag.regexp) == -1 ? 0 : 1)
       
    53                     }),
       
    54                     _nbtags = _(_tags).reduce(function(_a,_b) {
       
    55                         return _a + _b;
       
    56                     }, 0);
       
    57                 if (_nbtags) {
       
    58                     IriSP._(_tags).each(function(_v, _k) {
       
    59                         _vol[_k] += (_v / _nbtags);
       
    60                     });
       
    61                 }
       
    62             }
       
    63             var _nbtags = _(_vol).reduce(function(_a,_b) {
       
    64                     return _a + _b;
       
    65                 }, 0),
       
    66                 _nbneutre = _group.length - _nbtags,
       
    67                 _h = _nbneutre * _scale,
       
    68                 _base = this.height - _h;
       
    69             if (!this.streamgraph) {
       
    70                 this.paper.rect(i * _width, _base, _width - 1, _h ).attr({
       
    71                     "stroke" : "none",
       
    72                     "fill" : this.defaultcolor
       
    73                 });
       
    74             }
       
    75            _paths[0].push(_base);
       
    76             for (var j = 0; j < this.tags.length; j++) {
       
    77                 _h = _vol[j] * _scale;
       
    78                 _base = _base - _h;
       
    79                 if (!this.streamgraph) {
       
    80                     this.paper.rect(i * _width, _base, _width - 1, _h ).attr({
       
    81                         "stroke" : "none",
       
    82                         "fill" : this.tags[j].color
       
    83                     });
       
    84                 }
       
    85                 _paths[j+1].push(_base);
       
    86             }
       
    87             this.groups.push(_(_vol).map(function(_v) {
       
    88                 return _v / _group.length;
       
    89             }))
       
    90         } else {
       
    91             for (var j = 0; j < _paths.length; j++) {
       
    92                 _paths[j].push(this.height);
       
    93             }
       
    94             this.groups.push(_(this.tags).map(function() {
       
    95                 return 0;
       
    96             }));
       
    97         }
       
    98     }
       
    99     
       
   100     if (this.streamgraph) {
       
   101         for (var j = _paths.length - 1; j >= 0; j--) {
       
   102             var _d = _(_paths[j]).reduce(function(_memo, _v, _k) {
       
   103                return _memo + ( _k
       
   104                    ? 'C' + (_k * _width) + ' ' + _paths[j][_k - 1] + ' ' + (_k * _width) + ' ' + _v + ' ' + ((_k + .5) * _width) + ' ' + _v
       
   105                    : 'M0 ' + _v + 'L' + (.5*_width) + ' ' + _v )
       
   106             },'') + 'L' + this.width + ' ' + _paths[j][_paths[j].length - 1] + 'L' + this.width + ' ' + this.height + 'L0 ' + this.height;
       
   107             this.paper.path(_d).attr({
       
   108                 "stroke" : "none",
       
   109                 "fill" : (j ? this.tags[j-1].color : this.defaultcolor)
       
   110             });
       
   111         }
       
   112     }
       
   113     this.rectangleFocus = this.paper.rect(0,0,_width,this.height)
       
   114         .attr({
       
   115             "stroke" : "none",
       
   116             "fill" : "#ff00ff",
       
   117             "opacity" : 0
       
   118         })
       
   119     this.rectangleProgress = this.paper.rect(0,0,0,this.height)
       
   120         .attr({
       
   121             "stroke" : "none",
       
   122             "fill" : "#808080",
       
   123             "opacity" : .3
       
   124         });
       
   125     this.ligneProgress = this.paper.path("M0 0L0 "+this.height).attr({"stroke":"#ff00ff", "line-width" : 2})
       
   126     
       
   127     this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeUpdateHandler));
       
   128     var _this = this;
       
   129     this.selector
       
   130         .click(IriSP.wrap(this, this.clickHandler))
       
   131         .mousemove(function(_e) {
       
   132             _this.updateTooltip(_e);
       
   133             // Trace
       
   134             var relX = _e.pageX - _this.selector.offset().left;
       
   135             var _duration = _this.getDuration();
       
   136             var _time = parseInt((relX / _this.width) * _duration);
       
   137             _this._Popcorn.trigger("IriSP.TraceWidget.MouseEvents", {
       
   138                 "widget" : "StackGraphWidget",
       
   139                 "type": "mousemove",
       
   140                 "x": _e.pageX,
       
   141                 "y": _e.pageY,
       
   142                 "time": _time
       
   143             });
       
   144 
       
   145         })
       
   146         .mouseout(function() {
       
   147             _this.TooltipWidget.hide();
       
   148             _this.rectangleFocus.attr({
       
   149                 "opacity" : 0
       
   150             })
       
   151         })
       
   152 }
       
   153 
       
   154 IriSP.StackGraphWidget.prototype.timeUpdateHandler = function() {
       
   155     var _currentTime = this._Popcorn.currentTime(),
       
   156         _x = (1000 * _currentTime / this.duration) * this.width;
       
   157     this.rectangleProgress.attr({
       
   158         "width" : _x
       
   159     });
       
   160     this.ligneProgress.attr({
       
   161         "path" : "M" + _x + " 0L" + _x + " " + this.height
       
   162     })
       
   163 }
       
   164 
       
   165 IriSP.StackGraphWidget.prototype.clickHandler = function(event) {
       
   166   /* Ctrl-C Ctrl-V'ed from another widget
       
   167   */
       
   168 
       
   169   var relX = event.pageX - this.selector.offset().left;
       
   170   var newTime = ((relX / this.width) * this.duration/1000).toFixed(2);
       
   171   this._Popcorn.trigger("IriSP.StackGraphWidget.clicked", newTime);
       
   172   this._Popcorn.currentTime(newTime);                                 
       
   173 };
       
   174 
       
   175 IriSP.StackGraphWidget.prototype.updateTooltip = function(event) {
       
   176     var _segment = Math.max(0,Math.min(this.groups.length - 1, Math.floor(this.slices * (event.pageX - this.selector.offset().left)/this.width))),
       
   177         _valeurs = this.groups[_segment],
       
   178         _width = this.width / this.slices,
       
   179         _html = '<ul style="list-style: none; margin: 0; padding: 0;">' + IriSP._(this.tags).map(function(_tag, _i) {
       
   180             return '<li style="clear: both;"><span style="float: left; width: 10px; height: 10px; margin: 2px; background: '
       
   181                 + _tag.color
       
   182                 + ';"></span>'
       
   183                 + ~~(100 * _valeurs[_i])
       
   184                 + '% de '
       
   185                 + _tag.description
       
   186                 + '</li>';
       
   187         }).join('') + '</ul>';
       
   188     this.TooltipWidget._shown = false; // Vraiment, on ne peut pas ouvrir le widget s'il n'est pas encore ouvert ?
       
   189     this.TooltipWidget.show('','',(_segment + .5)* this.width / this.slices, 0);
       
   190     this.TooltipWidget.selector.find(".tip").html(_html);
       
   191     this.rectangleFocus.attr({
       
   192         "x" : _segment * _width,
       
   193         "opacity" : .4
       
   194     })
       
   195 }
       
   196