1 /* |
1 /* |
2 * |
2 * |
3 * Copyright 2010 Institut de recherche et d'innovation |
3 * Copyright 2010 Institut de recherche et d'innovation |
4 * contributor(s) : Samuel Huron |
4 * contributor(s) : Samuel Huron |
5 * |
5 * |
6 * contact@iri.centrepompidou.fr |
6 * contact@iri.centrepompidou.fr |
7 * http://www.iri.centrepompidou.fr |
7 * http://www.iri.centrepompidou.fr |
8 * |
8 * |
9 * This software is a computer program whose purpose is to show and add annotations on a video . |
9 * This software is a computer program whose purpose is to show and add annotations on a video . |
10 * This software is governed by the CeCILL-C license under French law and |
10 * This software is governed by the CeCILL-C license under French law and |
11 * abiding by the rules of distribution of free software. You can use, |
11 * abiding by the rules of distribution of free software. You can use, |
12 * modify and/ or redistribute the software under the terms of the CeCILL-C |
12 * modify and/ or redistribute the software under the terms of the CeCILL-C |
13 * license as circulated by CEA, CNRS and INRIA at the following URL |
13 * license as circulated by CEA, CNRS and INRIA at the following URL |
14 * "http://www.cecill.info". |
14 * "http://www.cecill.info". |
15 * |
15 * |
16 * The fact that you are presently reading this means that you have had |
16 * The fact that you are presently reading this means that you have had |
17 * knowledge of the CeCILL-C license and that you accept its terms. |
17 * knowledge of the CeCILL-C license and that you accept its terms. |
18 */ |
18 */ |
19 // CHART TIMELINE / VERSION PROTOTYPE :: |
19 // CHART TIMELINE / VERSION PROTOTYPE :: |
20 |
20 |
21 IriSP.PolemicWidget = function(Popcorn, config, Serializer) { |
21 IriSP.PolemicWidget = function(Popcorn, config, Serializer) { |
22 IriSP.Widget.call(this, Popcorn, config, Serializer); |
22 IriSP.Widget.call(this, Popcorn, config, Serializer); |
23 |
23 |
24 this.userPol = new Array(); |
24 this.userPol = new Array(); |
25 this.userNoPol = new Array(); |
25 this.userNoPol = new Array(); |
26 this.userst = new Array(); |
26 this.userst = new Array(); |
27 this.numberOfTweet = 0; |
27 this.numberOfTweet = 0; |
28 this.Users; |
28 this.Users; |
29 this.TweetPolemic; |
29 this.TweetPolemic; |
30 this.yMax = this.height; |
30 this.yMax = this.height; |
31 this.PaperSlider; |
31 this.PaperSlider; |
32 this.heightOfChart; |
32 this.heightOfChart; |
33 this.tweets = new Array(); |
33 this.tweets = new Array(); |
34 this.svgElements = new Array(); |
34 this.svgElements = new Array(); |
35 |
35 |
36 // Make and define the Raphael area |
36 // Make and define the Raphael area |
37 this.paper = Raphael(document.getElementById(this._id), config.width, config.height); |
37 this.paper = Raphael(document.getElementById(this._id), config.width, config.height); |
38 |
38 |
39 }; |
39 }; |
40 |
40 |
41 IriSP.PolemicWidget.prototype = new IriSP.Widget(); |
41 IriSP.PolemicWidget.prototype = new IriSP.Widget(); |
42 |
42 |
43 IriSP.PolemicWidget.prototype.draw = function() { |
43 IriSP.PolemicWidget.prototype.draw = function() { |
44 |
44 |
45 // variable |
45 // variable |
46 // yMax |
46 // yMax |
47 |
47 |
48 var self = this; |
48 var self = this; |
49 var yCoef = 2; // coef for height of 1 tweet |
49 var yCoef = 2; // coef for height of 1 tweet |
50 var frameSize = 5; // frame size |
50 var frameSize = 5; // frame size |
51 var margin = 1; // marge between frame |
51 var margin = 1; // marge between frame |
52 var lineSize = this.width; // timeline pixel width |
52 var lineSize = this.width; // timeline pixel width |
53 var nbrframes = lineSize/frameSize; // frame numbers |
53 var nbrframes = lineSize/frameSize; // frame numbers |
54 var numberOfTweet = 0; // number of tweet overide later |
54 var numberOfTweet = 0; // number of tweet overide later |
55 var duration = +this._serializer.currentMedia().meta["dc:duration"]; // timescale width |
55 var duration = +this._serializer.currentMedia().meta["dc:duration"]; // timescale width |
56 var frameLength = lineSize / frameSize; // frame timescale |
56 var frameLength = lineSize / frameSize; // frame timescale |
57 var timeline; |
57 var timeline; |
58 var colors = new Array("","#1D973D","#C5A62D","#CE0A15","#036AAE","#585858"); |
58 var colors = new Array("","#1D973D","#C5A62D","#CE0A15","#036AAE","#585858"); |
59 |
59 |
60 // array |
60 // array |
61 //var tweets = new Array(); |
61 //var tweets = new Array(); |
62 var element = new Array(); |
62 var element = new Array(); |
63 var cluster = new Array(); |
63 var cluster = new Array(); |
64 var frames = new Array(frameLength); |
64 var frames = new Array(frameLength); |
65 var slices = new Array(); |
65 var slices = new Array(); |
66 |
66 |
67 |
67 |
68 // Classes ======================================================================= |
68 // Classes ======================================================================= |
69 var Frames = function(){ |
69 var Frames = function(){ |
70 |
70 |
71 var Myclusters; |
71 var Myclusters; |
72 var x; |
72 var x; |
73 var y; |
73 var y; |
74 var width; |
74 var width; |
75 var height; |
75 var height; |
76 }; |
76 }; |
77 Frames = function(json){ |
77 Frames = function(json){ |
78 // make my clusters |
78 // make my clusters |
79 // ou Frame vide |
79 // ou Frame vide |
80 }; |
80 }; |
81 Frames.prototype.draw = function(){ |
81 Frames.prototype.draw = function(){ |
82 }; |
82 }; |
83 Frames.prototype.zoom = function(){ |
83 Frames.prototype.zoom = function(){ |
84 }; |
84 }; |
85 Frames.prototype.inside = function(){ |
85 Frames.prototype.inside = function(){ |
86 }; |
86 }; |
87 var Clusters = function(){ |
87 var Clusters = function(){ |
88 var Object; |
88 var Object; |
89 var yDist; |
89 var yDist; |
90 var x; |
90 var x; |
91 var y; |
91 var y; |
92 var width; |
92 var width; |
93 var height; |
93 var height; |
94 }; |
94 }; |
95 Clusters = function(json){ |
95 Clusters = function(json){ |
96 // make my object |
96 // make my object |
97 }; |
97 }; |
98 var Tweet = function(){ |
98 var Tweet = function(){ |
99 }; |
99 }; |
100 // Classes ======================================================================= |
100 // Classes ======================================================================= |
101 |
101 |
102 // Refactoring (parametere) ************************************************************ |
102 // Refactoring (parametere) ************************************************************ |
103 // color translastion |
103 // color translastion |
104 var qTweet_0 =0; |
104 var qTweet_0 =0; |
105 var qTweet_Q =0; |
105 var qTweet_Q =0; |
106 var qTweet_REF=0; |
106 var qTweet_REF=0; |
107 var qTweet_OK =0; |
107 var qTweet_OK =0; |
108 var qTweet_KO =0; |
108 var qTweet_KO =0; |
109 function colorTranslation(value){ |
109 function colorTranslation(value){ |
110 if(value == "Q"){ |
110 if(value == "Q"){ |
111 qTweet_Q+=1; |
111 qTweet_Q+=1; |
112 return 2; |
112 return 2; |
113 }else if(value =="REF"){ |
113 }else if(value =="REF"){ |
114 qTweet_REF+=1; |
114 qTweet_REF+=1; |
115 return 4; |
115 return 4; |
116 }else if(value =="OK"){ |
116 }else if(value =="OK"){ |
117 qTweet_OK+=1; |
117 qTweet_OK+=1; |
118 return 1; |
118 return 1; |
119 }else if(value =="KO"){ |
119 }else if(value =="KO"){ |
120 qTweet_KO+=1; |
120 qTweet_KO+=1; |
121 return 3; |
121 return 3; |
122 }else if(value ==""){ |
122 }else if(value ==""){ |
123 qTweet_0+=1; |
123 qTweet_0+=1; |
124 return 5; |
124 return 5; |
125 } |
125 } |
126 } |
126 } |
127 |
127 |
128 |
128 |
129 this._serializer.sync(function(data) { loaded_callback.call(self, data) }); |
129 this._serializer.sync(function(data) { loaded_callback.call(self, data) }); |
130 |
130 |
131 function loaded_callback (json) { |
131 function loaded_callback (json) { |
132 |
132 |
133 // get current view (the first ???) |
133 // get current view (the first ???) |
134 view = json.views[0]; |
134 view = json.views[0]; |
135 |
135 |
136 // the tweets are by definition of the second annotation type FIXME ? |
136 // the tweets are by definition of the second annotation type FIXME ? |
137 tweet_annot_type = null; |
137 tweet_annot_type = null; |
138 if(typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) { |
138 if(typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) { |
139 tweet_annot_type = view.annotation_types[1]; |
139 tweet_annot_type = view.annotation_types[1]; |
140 } |
140 } |
141 |
141 |
142 for(var i = 0; i < json.annotations.length; i++) { |
142 for(var i = 0; i < json.annotations.length; i++) { |
143 var item = json.annotations[i]; |
143 var item = json.annotations[i]; |
144 var MyTime = Math.floor(item.begin/duration*lineSize); |
144 var MyTime = Math.floor(item.begin/duration*lineSize); |
145 var Myframe = Math.floor(MyTime/lineSize*frameLength); |
145 var Myframe = Math.floor(MyTime/lineSize*frameLength); |
146 |
146 |
147 if (typeof(item.meta) !== "undefined" |
147 if (typeof(item.meta) !== "undefined" |
148 && typeof(item.meta["id-ref"]) !== "undefined" |
148 && typeof(item.meta["id-ref"]) !== "undefined" |
149 && item.meta["id-ref"] === tweet_annot_type) { |
149 && item.meta["id-ref"] === tweet_annot_type) { |
150 |
150 |
151 var MyTJson = JSON.parse(item.meta['dc:source']['content']); |
151 var MyTJson = JSON.parse(item.meta['dc:source']['content']); |
152 |
152 |
153 if (item.content['polemics'] != undefined |
153 if (item.content['polemics'] != undefined |
154 && item.content['polemics'][0] != null) { |
154 && item.content['polemics'][0] != null) { |
155 |
155 |
156 |
156 |
157 for(var j=0; j<item.content['polemics'].length; j++){ |
157 for(var j=0; j<item.content['polemics'].length; j++){ |
158 |
158 |
159 this.tweets[numberOfTweet] = { |
159 this.tweets[numberOfTweet] = { |
160 id:i, |
160 id:i, |
161 qualification:colorTranslation(item.content['polemics'][j]), |
161 qualification:colorTranslation(item.content['polemics'][j]), |
162 yIndicator:MyTime, |
162 yIndicator:MyTime, |
163 yframe:Myframe, |
163 yframe:Myframe, |
164 title:item.content['title'], |
164 title:item.content['title'], |
165 timeframe:item.begin, |
165 timeframe:item.begin, |
166 userId: MyTJson.id, |
166 userId: MyTJson.id, |
167 userScreenName: MyTJson.screen_name, |
167 userScreenName: MyTJson.screen_name, |
168 tsource:MyTJson |
168 tsource:MyTJson |
169 }; |
169 }; |
170 numberOfTweet+=1; |
170 numberOfTweet+=1; |
171 |
171 |
172 } |
172 } |
173 } |
173 } |
174 else { |
174 else { |
175 this.tweets[numberOfTweet] = { |
175 this.tweets[numberOfTweet] = { |
176 id:i, |
176 id:i, |
177 qualification:colorTranslation(""), |
177 qualification:colorTranslation(""), |
178 yIndicator:MyTime, |
178 yIndicator:MyTime, |
179 yframe:Myframe, |
179 yframe:Myframe, |
180 title:item.content['title'], |
180 title:item.content['title'], |
181 timeframe:item.begin, |
181 timeframe:item.begin, |
182 userId: MyTJson.id, |
182 userId: MyTJson.id, |
183 userScreenName: MyTJson.screen_name, |
183 userScreenName: MyTJson.screen_name, |
184 tsource:MyTJson |
184 tsource:MyTJson |
185 |
185 |
186 }; |
186 }; |
187 numberOfTweet+=1; |
187 numberOfTweet+=1; |
188 } |
188 } |
189 |
189 |
190 } |
190 } |
191 }; |
191 }; |
192 |
192 |
193 DrawTweets.call (this); // FIXME: ugly. |
193 DrawTweets.call (this); // FIXME: ugly. |
194 |
194 |
195 }; |
195 }; |
196 |
196 |
197 // tweet Drawing (in raphael) |
197 // tweet Drawing (in raphael) |
198 function DrawTweets (){ |
198 function DrawTweets (){ |
199 // GROUPES TWEET ============================================ |
199 // GROUPES TWEET ============================================ |
200 // Count nbr of cluster and tweet in a frame an save int in "frames" |
200 // Count nbr of cluster and tweet in a frame an save int in "frames" |
201 numberOfTweet = this.tweets.length; |
201 numberOfTweet = this.tweets.length; |
202 for(var i=0; i<nbrframes; i++) { |
202 for(var i=0; i<nbrframes; i++) { |
203 for(var j=0; j<numberOfTweet; j++) { |
203 for(var j=0; j<numberOfTweet; j++) { |
204 |
204 |
205 if (i==this.tweets[j].yframe){ |
205 if (i==this.tweets[j].yframe){ |
206 |
206 |
207 var k = this.tweets[j].qualification; |
207 var k = this.tweets[j].qualification; |
208 |
208 |
209 // make array for frame cluster |
209 // make array for frame cluster |
210 if(frames[i]==undefined){ |
210 if(frames[i]==undefined){ |
211 frames[i] = {id:i, |
211 frames[i] = {id:i, |
212 qualifVol:new Array(), |
212 qualifVol:new Array(), |
213 mytweetsID:new Array() |
213 mytweetsID:new Array() |
214 }; |
214 }; |
215 } |
215 } |
216 // add my tweet to frame |
216 // add my tweet to frame |
217 frames[i].mytweetsID.push(this.tweets[j]); |
217 frames[i].mytweetsID.push(this.tweets[j]); |
218 |
218 |
219 // count opinion by frame |
219 // count opinion by frame |
220 if( frames[i].qualifVol[k] == undefined){ |
220 if( frames[i].qualifVol[k] == undefined){ |
221 frames[i].qualifVol[k] = 1; |
221 frames[i].qualifVol[k] = 1; |
222 }else{ |
222 }else{ |
223 frames[i].qualifVol[k] += 1; |
223 frames[i].qualifVol[k] += 1; |
224 } |
224 } |
225 |
225 |
226 } |
226 } |
227 } |
227 } |
228 } |
228 } |
229 |
229 |
230 // GROUPES TWEET ============================================ |
230 // GROUPES TWEET ============================================ |
231 // max of tweet by Frame |
231 // max of tweet by Frame |
232 var max = 0; |
232 var max = 0; |
233 for(var i = 0; i < nbrframes; i++) { |
233 for(var i = 0; i < nbrframes; i++) { |
234 var moy = 0; |
234 var moy = 0; |
235 for (var j = 0; j < 6; j++) { |
235 for (var j = 0; j < 6; j++) { |
236 if (frames[i] != undefined) { |
236 if (frames[i] != undefined) { |
237 if (frames[i].qualifVol[j] != undefined) { |
237 if (frames[i].qualifVol[j] != undefined) { |
238 moy += frames[i].qualifVol[j]; |
238 moy += frames[i].qualifVol[j]; |
239 } |
239 } |
240 } |
240 } |
241 } |
241 } |
242 |
242 |
243 if (moy > max) { |
243 if (moy > max) { |
244 max = moy; |
244 max = moy; |
245 } |
245 } |
246 } |
246 } |
247 |
247 |
248 var tweetDrawed = new Array(); |
248 var tweetDrawed = new Array(); |
249 var TweetHeight = 5; |
249 var TweetHeight = 5; |
250 |
250 |
251 // DRAW TWEETS ============================================ |
251 // DRAW TWEETS ============================================ |
252 for(var i = 0; i < nbrframes; i++) { |
252 for(var i = 0; i < nbrframes; i++) { |
253 var addEheight = 5; |
253 var addEheight = 5; |
254 if (frames[i] != undefined){ |
254 if (frames[i] != undefined){ |
255 // by type |
255 // by type |
256 |
256 |
257 for (var j = 6; j > -1; j--) { |
257 for (var j = 6; j > -1; j--) { |
258 if (frames[i].qualifVol[j] != undefined) { |
258 if (frames[i].qualifVol[j] != undefined) { |
259 // show tweet by type |
259 // show tweet by type |
260 for (var k = 0; k < frames[i].mytweetsID.length; k++) { |
260 for (var k = 0; k < frames[i].mytweetsID.length; k++) { |
261 |
261 |
262 if (frames[i].mytweetsID[k].qualification == j) { |
262 if (frames[i].mytweetsID[k].qualification == j) { |
263 var x = i * frameSize; |
263 var x = i * frameSize; |
264 var y = this.heightmax - addEheight; |
264 var y = this.heightmax - addEheight; |
265 |
265 |
266 if (this.yMax > y) { |
266 if (this.yMax > y) { |
267 this.yMax = y; |
267 this.yMax = y; |
268 } |
268 } |
269 |
269 |
270 var e = this.paper.rect(x, y, frameSize - margin, TweetHeight /* height */).attr({stroke:"#00","stroke-width":0.1, fill: colors[j]}); |
270 var e = this.paper.rect(x, y, frameSize - margin, TweetHeight /* height */).attr({stroke:"#00","stroke-width":0.1, fill: colors[j]}); |
271 this.svgElements.push(e); |
271 this.svgElements.push(e); |
272 |
272 |
273 addEheight += TweetHeight; |
273 addEheight += TweetHeight; |
274 |
274 |
275 e.time= frames[i].mytweetsID[k].timeframe; |
275 e.time= frames[i].mytweetsID[k].timeframe; |
276 e.title= frames[i].mytweetsID[k].title; |
276 e.title= frames[i].mytweetsID[k].title; |
277 |
277 |
278 e.mouseover(function(element) { return function (event) { |
278 e.mouseover(function(element) { return function (event) { |
279 |
279 |
280 // event.clientX and event.clientY are to raphael what event.pageX and pageY are to jquery. |
280 // event.clientX and event.clientY are to raphael what event.pageX and pageY are to jquery. |
281 self.TooltipWidget.show.call(self.TooltipWidget, element.title, element.attr("fill"), event.clientX - 106, event.clientY - 160); |
281 self.TooltipWidget.show.call(self.TooltipWidget, element.title, element.attr("fill"), event.clientX - 106, event.clientY - 160); |
282 element.displayed = true; |
282 element.displayed = true; |
283 }}(e)).mouseout(function(element) { return function () { |
283 }}(e)).mouseout(function(element) { return function () { |
284 self.TooltipWidget.hide.call(self.TooltipWidget); |
284 self.TooltipWidget.hide.call(self.TooltipWidget); |
285 }}(e)).mousedown(function () { |
285 }}(e)).mousedown(function () { |
286 self._Popcorn.currentTime(this.time/1000); |
286 self._Popcorn.currentTime(this.time/1000); |
287 }); |
287 }); |
288 |
288 |
289 IriSP.jQuery(e.node).attr('id', 't' + k + ''); |
289 IriSP.jQuery(e.node).attr('id', 't' + k + ''); |
290 IriSP.jQuery(e.node).attr('title', frames[i].mytweetsID[k].title); |
290 IriSP.jQuery(e.node).attr('title', frames[i].mytweetsID[k].title); |
291 IriSP.jQuery(e.node).attr('begin', frames[i].mytweetsID[k].timeframe); |
291 IriSP.jQuery(e.node).attr('begin', frames[i].mytweetsID[k].timeframe); |
292 } |
292 } |
293 } |
293 } |
294 } |
294 } |
295 } |
295 } |
296 } |
296 } |
297 |
297 |
298 } |
298 } |
299 // DRAW UI :: resize border and bgd |
299 // DRAW UI :: resize border and bgd |
300 this.paperBackground = this.paper.rect(0, 0, this.width, this.heightmax).attr({fill:"#F8F8F8","stroke-width":0.1,opacity: 1}); |
300 this.paperBackground = this.paper.rect(0, 0, this.width, this.heightmax).attr({fill:"#F8F8F8","stroke-width":0.1,opacity: 1}); |
301 // var PaperBorder = this.paper.rect(0, this.yMax,this.width,1).attr({fill:"#fff",stroke: "none",opacity: 1}); |
301 // var PaperBorder = this.paper.rect(0, this.yMax,this.width,1).attr({fill:"#fff",stroke: "none",opacity: 1}); |
302 |
302 |
303 this.paperSlider = this.paper.rect(0, 0, 0, this.heightmax).attr({fill:"#D4D5D5", stroke: "none", opacity: 1}); |
303 this.paperSlider = this.paper.rect(0, 0, 0, this.heightmax).attr({fill:"#D4D5D5", stroke: "none", opacity: 1}); |
304 |
304 |
305 // the small white line displayed over the slider. |
305 // the small white line displayed over the slider. |
306 this.sliderTip = this.paper.rect(0, 0, 1, this.heightmax).attr({fill:"#fc00ff", stroke: "none", opacity: 1}); |
306 this.sliderTip = this.paper.rect(0, 0, 1, this.heightmax).attr({fill:"#fc00ff", stroke: "none", opacity: 1}); |
307 |
307 |
308 // decalage |
308 // decalage |
309 // tweetSelection = this.paper.rect(-100,-100,5,5).attr({fill:"#fff",stroke: "none",opacity: 1}); |
309 // tweetSelection = this.paper.rect(-100,-100,5,5).attr({fill:"#fff",stroke: "none",opacity: 1}); |
310 |
310 |
311 |
311 |
312 this.paperSlider.toBack(); |
312 this.paperSlider.toBack(); |
313 this.paperBackground.toBack(); |
313 this.paperBackground.toBack(); |
314 this.sliderTip.toFront(); |
314 this.sliderTip.toFront(); |
315 } |
315 } |
316 |
316 |
317 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater)); |
317 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater)); |
318 } |
318 } |
319 |
319 |
320 IriSP.PolemicWidget.prototype.sliderUpdater = function() { |
320 IriSP.PolemicWidget.prototype.sliderUpdater = function() { |