src/js/widgets/polemicViewer.js
branchcap-demo
changeset 400 58ade3113a02
child 410 de8fdd68930f
equal deleted inserted replaced
399:8048252d7cc5 400:58ade3113a02
       
     1 /* 
       
     2  *   
       
     3  *  Copyright 2010 Institut de recherche et d'innovation 
       
     4  *  contributor(s) : Samuel Huron 
       
     5  *   
       
     6  *  contact@iri.centrepompidou.fr
       
     7  *  http://www.iri.centrepompidou.fr 
       
     8  *   
       
     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
       
    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
       
    13  *  license as circulated by CEA, CNRS and INRIA at the following URL
       
    14  *  "http://www.cecill.info". 
       
    15  *  
       
    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.
       
    18 */
       
    19 // CHART TIMELINE / VERSION PROTOTYPE  ::
       
    20 
       
    21 IriSP.PolemicViewer = function(Popcorn, config, Serializer) {
       
    22   IriSP.Widget.call(this, Popcorn, config, Serializer);
       
    23  
       
    24   this.userPol    = new Array();
       
    25   this.userNoPol  = new Array();
       
    26   this.userst      = new Array();
       
    27   this.numberOfTweet = 0;
       
    28   this.Users;
       
    29   this.TweetPolemic;
       
    30   this.yMax        = this.height; 
       
    31   this.PaperSlider;
       
    32   this.heightOfChart;
       
    33   this.tweets  = new Array();
       
    34   this.svgElements = {};
       
    35   
       
    36   // Make and define the Raphael area
       
    37   this.paper = Raphael(document.getElementById(this._id), config.width, config.height);
       
    38   
       
    39   this.oldSearchMatches = [];
       
    40 
       
    41   // event handlers
       
    42   this._Popcorn.listen("IriSP.search", IriSP.wrap(this, function(searchString) { this.searchHandler(searchString); }));
       
    43   this._Popcorn.listen("IriSP.search.closed", IriSP.wrap(this, this.searchFieldClosedHandler));
       
    44   this._Popcorn.listen("IriSP.search.cleared", IriSP.wrap(this, this.searchFieldClearedHandler));
       
    45 
       
    46 };
       
    47 
       
    48 IriSP.PolemicViewer.prototype = new IriSP.Widget();
       
    49   
       
    50 IriSP.PolemicViewer.prototype.draw = function() {
       
    51   
       
    52     // variable 
       
    53     // yMax
       
    54     
       
    55     var self = this;
       
    56     var yCoef        = 2;             // coef for height of 1 tweet 
       
    57     var frameSize     = 5;             // frame size 
       
    58     var margin         = 1;            // marge between frame
       
    59     var lineSize      = this.width;        // timeline pixel width 
       
    60     var nbrframes     = lineSize/frameSize;     // frame numbers
       
    61     var numberOfTweet   = 0;            // number of tweet overide later 
       
    62     var duration      = +this._serializer.currentMedia().meta["dc:duration"];      // timescale width 
       
    63     var frameLength   = lineSize / frameSize;    // frame timescale  
       
    64     var timeline;
       
    65     var colors  = new Array("","#1D973D","#C5A62D","#CE0A15","#036AAE","#585858");
       
    66     
       
    67     // array 
       
    68     //var tweets  = new Array();
       
    69     var element = new Array();
       
    70     var cluster = new Array();
       
    71     var frames  = new Array(frameLength);
       
    72     var slices  = new Array();
       
    73     
       
    74     
       
    75     // Classes =======================================================================
       
    76     var Frames = function(){
       
    77       
       
    78       var Myclusters;
       
    79       var x;
       
    80       var y;
       
    81       var width;
       
    82       var height;
       
    83     };
       
    84     Frames = function(json){
       
    85       // make my clusters
       
    86       // ou Frame vide 
       
    87     };
       
    88     Frames.prototype.draw = function(){
       
    89     };
       
    90     Frames.prototype.zoom = function(){
       
    91     };
       
    92     Frames.prototype.inside = function(){
       
    93     };
       
    94     var Clusters = function(){
       
    95       var Object;
       
    96       var yDist;
       
    97       var x;
       
    98       var y;
       
    99       var width;
       
   100       var height;
       
   101     };
       
   102     Clusters = function(json){
       
   103       // make my object
       
   104     };
       
   105     var Tweet = function(){
       
   106     };
       
   107     // Classes =======================================================================
       
   108 
       
   109     // Refactoring (parametere) ************************************************************
       
   110     // color translastion
       
   111     var qTweet_0  =0;
       
   112     var qTweet_Q  =0;
       
   113     var qTweet_REF=0;
       
   114     var qTweet_OK =0;
       
   115     var qTweet_KO =0;
       
   116     function colorTranslation(value){
       
   117       if(value.indexOf("??") !== -1){
       
   118         qTweet_Q+=1;
       
   119         return 2;
       
   120       }else if(value.indexOf("==") !== -1){
       
   121         qTweet_REF+=1;
       
   122         return 4;
       
   123       }else if(value.indexOf("++") !== -1){
       
   124         qTweet_OK+=1;
       
   125         return 1;
       
   126       }else if(value.indexOf("--") !== -1){
       
   127         qTweet_KO+=1;
       
   128         return 3;
       
   129       }else {
       
   130         qTweet_0+=1;
       
   131         return 5;
       
   132       }
       
   133     }
       
   134     
       
   135 
       
   136       this._serializer.sync(function(data) { loaded_callback.call(self, data) });
       
   137       
       
   138       function loaded_callback (json) {
       
   139 
       
   140         // get current view (the first ???)
       
   141         view = json.views[0];
       
   142         
       
   143         // the tweets are by definition of the second annotation type FIXME ?
       
   144         tweet_annot_type = null;
       
   145         if(typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) {
       
   146           tweet_annot_type = view.annotation_types[1];
       
   147         }
       
   148       
       
   149       for(var i = 0; i < json.annotations.length; i++) {
       
   150         var item = json.annotations[i];        
       
   151         var MyTime  = Math.floor(item.begin/duration*lineSize);
       
   152         var Myframe = Math.floor(MyTime/lineSize*frameLength);
       
   153         /*
       
   154         if (typeof(item.meta) !== "undefined" 
       
   155           && typeof(item.meta["id-ref"]) !== "undefined"
       
   156           && item.meta["id-ref"] === tweet_annot_type) {
       
   157             
       
   158           var MyTJson = JSON.parse(item.meta['dc:source']['content']);
       
   159           
       
   160             if (item.content['polemics'] != undefined 
       
   161             && item.content['polemics'][0] != null) {
       
   162             
       
   163               // a tweet can have many polemics at the same time.
       
   164               for(var j=0; j<item.content['polemics'].length; j++){
       
   165                   
       
   166                   this.tweets[numberOfTweet] = {
       
   167                         id:i,
       
   168                         qualification:colorTranslation(item.content['polemics'][j]),
       
   169                         yIndicator:MyTime,
       
   170                         yframe:Myframe,
       
   171                         title:item.content['title'],
       
   172                         timeframe:item.begin,
       
   173                         userId: MyTJson.id,
       
   174                         userScreenName: MyTJson.screen_name,
       
   175                         tsource:MyTJson,
       
   176                         cinecast_id: item.id
       
   177                         };
       
   178                   numberOfTweet+=1;
       
   179                   
       
   180               }
       
   181           }
       
   182           else {
       
   183           */
       
   184             this.tweets[numberOfTweet] = {
       
   185                   id:i,
       
   186                   qualification:colorTranslation(item.content['description']),
       
   187                   description:item.content['description'],
       
   188                   yIndicator:MyTime,
       
   189                   yframe:Myframe,
       
   190                   title:item.content['title'],
       
   191                   timeframe:item.begin,
       
   192                   userId: "nobody",
       
   193                   userScreenName: "nobody",
       
   194                   tsource: "iri ldt platform",
       
   195                   cinecast_id: item.id
       
   196             };
       
   197             numberOfTweet+=1;
       
   198           
       
   199           /* } 
       
   200           
       
   201         } */
       
   202       };  
       
   203       
       
   204        DrawTweets.call (this); // FIXME: ugly.
       
   205        
       
   206       };      
       
   207 
       
   208     // tweet Drawing (in raphael) 
       
   209     function DrawTweets (){
       
   210     // GROUPES TWEET ============================================
       
   211     // Count nbr of cluster and tweet in a frame an save int in "frames"
       
   212       numberOfTweet = this.tweets.length;
       
   213       for(var i=0; i<nbrframes; i++) {  
       
   214         for(var j=0; j<numberOfTweet; j++) {  
       
   215         
       
   216           if (i==this.tweets[j].yframe){
       
   217             
       
   218             var k = this.tweets[j].qualification;
       
   219             
       
   220             // make array for frame cluster
       
   221             if(frames[i]==undefined){
       
   222               frames[i] = {id:i,
       
   223                      qualifVol:new Array(),
       
   224                      mytweetsID:new Array()
       
   225                     };
       
   226             }
       
   227             // add my tweet to frame
       
   228             frames[i].mytweetsID.push(this.tweets[j]);
       
   229             
       
   230             // count opinion by frame
       
   231             if( frames[i].qualifVol[k] == undefined){
       
   232               frames[i].qualifVol[k] = 1;
       
   233             }else{
       
   234               frames[i].qualifVol[k] += 1;
       
   235             }
       
   236             
       
   237           }
       
   238         }
       
   239       }
       
   240     
       
   241     // GROUPES TWEET ============================================    
       
   242     // max of tweet by Frame 
       
   243       var max = 0; 
       
   244       for(var i = 0; i < nbrframes; i++) {
       
   245         var moy  = 0;
       
   246         for (var j = 0; j < 6; j++) {    
       
   247           if (frames[i] != undefined) {
       
   248             if (frames[i].qualifVol[j] != undefined) {
       
   249               moy += frames[i].qualifVol[j];
       
   250             }
       
   251           }
       
   252         }
       
   253         
       
   254         if (moy > max) {
       
   255           max = moy;
       
   256         }
       
   257       }
       
   258     
       
   259       var tweetDrawed = new Array();
       
   260       var TweetHeight = 5;
       
   261       
       
   262       // DRAW  TWEETS ============================================
       
   263       for(var i = 0; i < nbrframes; i++) {
       
   264         var addEheight = 5;
       
   265         if (frames[i] != undefined){                
       
   266           // by type 
       
   267           
       
   268           for (var j = 6; j > -1; j--) {
       
   269             if (frames[i].qualifVol[j] != undefined) {
       
   270               // show tweet by type 
       
   271               for (var k = 0; k < frames[i].mytweetsID.length; k++) {
       
   272               
       
   273                 if (frames[i].mytweetsID[k].qualification == j) {                
       
   274                   var x = i * frameSize;
       
   275                   var y = this.heightmax - addEheight;
       
   276                   
       
   277                   if (this.yMax > y) {
       
   278                     this.yMax = y;
       
   279                   }
       
   280                   
       
   281                   var e = this.paper.rect(x, y, frameSize - margin, TweetHeight /* height */)
       
   282                                     .attr({stroke:"#00","stroke-width":0.1,  fill: colors[j]});  
       
   283                   
       
   284                   addEheight += TweetHeight;
       
   285                   
       
   286                   e.color = colors[j];
       
   287                   e.time = frames[i].mytweetsID[k].timeframe;
       
   288                   e.title = frames[i].mytweetsID[k].title;
       
   289                   e.description = frames[i].mytweetsID[k].description;
       
   290                   e.id = frames[i].mytweetsID[k].cinecast_id;
       
   291 
       
   292                   this.svgElements[e.id] = e;
       
   293 
       
   294                   e.mouseover(function(element) { return function (event) {
       
   295                         // event.clientX and event.clientY are to raphael what event.pageX and pageY are to jquery.                        
       
   296                         self.TooltipWidget.show.call(self.TooltipWidget, element.description, element.attr("fill"), event.clientX - 106, event.clientY - 160);
       
   297                         element.displayed = true;
       
   298                   }}(e)).mouseout(function(element) { return function () {                          
       
   299                           self.TooltipWidget.hide.call(self.TooltipWidget);
       
   300                   }}(e)).mousedown(function () {
       
   301                     self._Popcorn.currentTime(this.time/1000);
       
   302                     self._Popcorn.trigger("IriSP.PolemicTweet.click", this.id); 
       
   303                   });
       
   304                   
       
   305                   IriSP.jQuery(e.node).attr('id', 't' + k + '');
       
   306                   IriSP.jQuery(e.node).attr('title', frames[i].mytweetsID[k].title);
       
   307                   IriSP.jQuery(e.node).attr('begin',  frames[i].mytweetsID[k].timeframe);                  
       
   308                 }
       
   309               }
       
   310             }
       
   311           }
       
   312         }
       
   313 
       
   314       }    
       
   315       // DRAW UI :: resize border and bgd      
       
   316       this.paperBackground = this.paper.rect(0, 0, this.width, this.heightmax).attr({fill:"#F8F8F8","stroke-width":0.1,opacity: 1});  
       
   317 
       
   318       // outer borders
       
   319       this.outerBorders   = [];
       
   320       this.outerBorders.push(this.paper.rect(0, this.height - 1, this.width, 1).attr({fill:"#ababab",stroke: "none",opacity: 1}));  
       
   321       this.outerBorders.push(this.paper.rect(0, 0, this.width, 1).attr({fill:"#ababab",stroke: "none",opacity: 1}));  
       
   322 
       
   323       // inner borders
       
   324       this.innerBorders   = [];
       
   325       this.innerBorders.push(this.paper.rect(1, this.height - 2, this.width, 1).attr({fill:"#efefef",stroke: "none",opacity: 1}));  
       
   326       this.innerBorders.push(this.paper.rect(1, 1, this.width, 1).attr({fill:"#efefef",stroke: "none",opacity: 1}));  
       
   327       this.innerBorders.push(this.paper.rect(1, 1, 1, this.height - 2).attr({fill:"#d0d1d1",stroke: "none",opacity: 0.8}));  
       
   328       this.innerBorders.push(this.paper.rect(this.width - 2, 1, 1, this.height - 2).attr({fill:"#efefef",stroke: "none",opacity: 1}));  
       
   329 
       
   330 
       
   331 
       
   332       this.paperSlider   = this.paper.rect(0, 0, 0, this.heightmax).attr({fill:"#D4D5D5", stroke: "none", opacity: 1});
       
   333       
       
   334       // the small white line displayed over the slider.
       
   335       this.sliderTip = this.paper.rect(0, 0, 1, this.heightmax).attr({fill:"#fc00ff", stroke: "none", opacity: 1});
       
   336       // decalage 
       
   337       // tweetSelection = this.paper.rect(-100,-100,5,5).attr({fill:"#fff",stroke: "none",opacity: 1});  
       
   338       
       
   339       
       
   340       this.paperSlider.toBack();
       
   341       this.paperBackground.toBack();
       
   342       this.sliderTip.toFront();
       
   343     }
       
   344     
       
   345     this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater));
       
   346 }
       
   347 
       
   348 IriSP.PolemicViewer.prototype.sliderUpdater = function() {
       
   349 
       
   350     var time = +this._Popcorn.currentTime();
       
   351     var duration = +this._serializer.currentMedia().meta["dc:duration"];
       
   352     
       
   353     this.paperSlider.attr("width", time * (this.width / (duration / 1000)));
       
   354         
       
   355     this.sliderTip.attr("x", time * (this.width / (duration / 1000)));
       
   356 };
       
   357     
       
   358 IriSP.PolemicViewer.prototype.searchHandler = function(searchString) {
       
   359 
       
   360   if (searchString == "")
       
   361     return;
       
   362 
       
   363   var matches = this._serializer.searchTweetsOccurences(searchString);
       
   364 
       
   365   if (IriSP.countProperties(matches) > 0) {
       
   366     this._Popcorn.trigger("IriSP.search.matchFound");
       
   367   } else {
       
   368     this._Popcorn.trigger("IriSP.search.noMatchFound");
       
   369   }
       
   370 
       
   371   for (var id in matches) {
       
   372     var factor = 0.5 + matches[id] * 0.2;
       
   373     if (this.svgElements.hasOwnProperty(id)) {
       
   374       this.svgElements[id].attr({fill: "#fc00ff"});
       
   375     }
       
   376   }
       
   377 
       
   378   // clean up the blocks that were in the previous search
       
   379   // but who aren't in the current one.
       
   380   for (var id in this.oldSearchMatches) {
       
   381     if (!matches.hasOwnProperty(id)) {
       
   382       var e = this.svgElements[id];
       
   383       e.attr({fill: e.color});
       
   384     }
       
   385   }
       
   386   
       
   387   this.oldSearchMatches = matches;
       
   388 };
       
   389 
       
   390 IriSP.PolemicViewer.prototype.searchFieldClearedHandler = function() {
       
   391   // clean up the blocks that were in the previous search
       
   392   // but who aren't in the current one.
       
   393   for (var id in this.oldSearchMatches) {
       
   394       var e = this.svgElements[id];
       
   395       e.attr({fill: e.color});
       
   396   }
       
   397  
       
   398 };
       
   399 
       
   400 IriSP.PolemicViewer.prototype.searchFieldClosedHandler = function() {
       
   401   // clean up the blocks that were in the previous search
       
   402   // but who aren't in the current one.
       
   403   for (var id in this.oldSearchMatches) {
       
   404       var e = this.svgElements[id];
       
   405       e.attr({fill: e.color});
       
   406   }
       
   407  
       
   408 };
       
   409