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