--- a/src/js/widgets/polemicWidget.js Thu Apr 19 19:20:41 2012 +0200
+++ b/src/js/widgets/polemicWidget.js Fri Apr 20 19:13:11 2012 +0200
@@ -1,448 +1,178 @@
-/*
- *
- * Copyright 2010 Institut de recherche et d'innovation
- * contributor(s) : Samuel Huron
- *
- * contact@iri.centrepompidou.fr
- * http://www.iri.centrepompidou.fr
- *
- * This software is a computer program whose purpose is to show and add annotations on a video .
- * This software is governed by the CeCILL-C license under French law and
- * abiding by the rules of distribution of free software. You can use,
- * modify and/ or redistribute the software under the terms of the CeCILL-C
- * license as circulated by CEA, CNRS and INRIA at the following URL
- * "http://www.cecill.info".
- *
- * The fact that you are presently reading this means that you have had
- * knowledge of the CeCILL-C license and that you accept its terms.
-*/
-// CHART TIMELINE / VERSION PROTOTYPE ::
-
-/** the polemic widget */
-IriSP.PolemicWidget = function(Popcorn, config, Serializer) {
- IriSP.Widget.call(this, Popcorn, config, Serializer);
-
- this.userPol = new Array();
- this.userNoPol = new Array();
- this.userst = new Array();
- this.numberOfTweet = 0;
- this.Users;
- this.TweetPolemic;
- this.yMax = this.height;
- this.PaperSlider;
- this.heightOfChart;
- this.tweets = new Array();
- this.svgElements = {};
-
- this.oldSearchMatches = [];
+IriSP.PolemicWidget = function(player, config) {
+ IriSP.Widget.call(this, player, config);
+ this.bindPopcorn("IriSP.search", "searchHandler");
+ this.bindPopcorn("IriSP.search.closed", "searchHandler");
+ this.bindPopcorn("IriSP.search.cleared", "searchHandler");
+ this.bindPopcorn("timeupdate", "onTimeupdate");
+ this.sliceCount = Math.floor( this.width / this.element_width );
+ this.$zone = IriSP.jQuery('<div>');
+ this.$.append(this.$zone);
};
IriSP.PolemicWidget.prototype = new IriSP.Widget();
-
-IriSP.PolemicWidget.prototype.draw = function() {
-
- // variable
- // yMax
-
- var self = this;
- var yCoef = 2; // coef for height of 1 tweet
- var frameSize = 5; // frame size
- var margin = 1; // marge between frame
- var lineSize = this.width; // timeline pixel width
- var nbrframes = lineSize/frameSize; // frame numbers
- var numberOfTweet = 0; // number of tweet overide later
- var duration = this.getDuration(); // timescale width
- var frameLength = lineSize / frameSize; // frame timescale
- var timeline;
- var colors = new Array("","#1D973D","#036AAE","#CE0A15","#C5A62D","#585858");
-
- // array
- //var tweets = new Array();
- var element = new Array();
- var cluster = new Array();
- var frames = new Array(frameLength);
- var slices = new Array();
-
-
- // Classes =======================================================================
- var Frames = function(){
-
- var Myclusters;
- var x;
- var y;
- var width;
- var height;
- };
- Frames = function(json){
- // make my clusters
- // ou Frame vide
- };
- Frames.prototype.draw = function(){
- };
- Frames.prototype.zoom = function(){
- };
- Frames.prototype.inside = function(){
- };
- var Clusters = function(){
- var Object;
- var yDist;
- var x;
- var y;
- var width;
- var height;
- };
- Clusters = function(json){
- // make my object
- };
- var Tweet = function(){
- };
- // Classes =======================================================================
- // Refactoring (parametere) ************************************************************
- // color translastion
- var qTweet_0 =0;
- var qTweet_Q =0;
- var qTweet_REF=0;
- var qTweet_OK =0;
- var qTweet_KO =0;
- function colorTranslation(value){
- if(value == "Q"){
- qTweet_Q+=1;
- return 2;
- }else if(value =="REF"){
- qTweet_REF+=1;
- return 4;
- }else if(value =="OK"){
- qTweet_OK+=1;
- return 1;
- }else if(value =="KO"){
- qTweet_KO+=1;
- return 3;
- }else if(value ==""){
- qTweet_0+=1;
- return 5;
- }
+IriSP.PolemicWidget.prototype.searchHandler = function(searchString) {
+ this.searchString = typeof searchString !== "undefined" ? searchString : '';
+ var _found = 0,
+ _re = IriSP.Model.regexpFromTextOrArray(searchString)
+ _this = this;
+ this.$tweets.each(function() {
+ var _el = IriSP.jQuery(this);
+ if (_this.searchString) {
+ if (_re.test(_el.attr("tweet-title"))) {
+ _el.css({
+ "background" : _this.foundcolor,
+ "opacity" : 1
+ });
+ _found++;
+ } else {
+ _el.css({
+ "background" : _el.attr("polemic-color"),
+ "opacity" : .5
+ });
+ }
+ } else {
+ _el.css({
+ "background" : _el.attr("polemic-color"),
+ "opacity" : 1
+ });
+ }
+ });
+ if (this.searchString) {
+ if (_found) {
+ this.player.popcorn.trigger("IriSP.search.matchFound");
+ } else {
+ this.player.popcorn.trigger("IriSP.search.noMatchFound");
+ }
}
-
-
- this._serializer.sync(function(data) { loaded_callback.call(self, data); return; });
-
- function loaded_callback (json) {
- var view_type = this._serializer.getTweets();
+}
-
- if (typeof(view_type) === "undefined") {
- var view_type = this._serializer.getTweetIds()[0];
- if (typeof(view_type) === "undefined") {
- // default to guessing if nothing else works.
- var view = json.views[0];
-
- if(typeof(view.annotation_types) !== "undefined") {
- /* we need to be backward compatible with the old files which used to
- feature only two lines : Chapitrage and Tweets. We've added a
- "Contributions" line so we need to discriminate against that */
- if (view.annotation_types.length === 2 && typeof(this._serializer.getContributions()) === "undefined") {
- var view_type = view.annotation_types[1];
- } else {
- console.log("PolemicWidget: invalid file - minimizing");
- return;
- }
- }
- }
- }
-
- // Make and define the Raphael area
- this.paper = Raphael(document.getElementById(this._id), this._config.width, this._config.height);
-
- // event handlers
- this._Popcorn.listen("IriSP.search", IriSP.wrap(this, function(searchString) { this.searchHandler(searchString); }));
- this._Popcorn.listen("IriSP.search.closed", IriSP.wrap(this, this.searchFieldClosedHandler));
- this._Popcorn.listen("IriSP.search.cleared", IriSP.wrap(this, this.searchFieldClearedHandler));
- this.selector.mouseleave(IriSP.wrap(this, function() { self.TooltipWidget.hide.call(self.TooltipWidget); }));
- this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater));
- this._Popcorn.listen("IriSP.Mediafragment.showAnnotation", IriSP.wrap(this, this.showAnnotation));
-
- for(var i = 0; i < json.annotations.length; i++) {
- var item = json.annotations[i];
- var MyTime = Math.floor(item.begin/duration*lineSize);
- var Myframe = Math.floor(MyTime/lineSize*frameLength);
-
- if (typeof(item.meta) !== "undefined"
- && typeof(item.meta["id-ref"]) !== "undefined"
- && item.meta["id-ref"] === view_type) {
-
- var MyTJson = {},
- _source = IriSP.get_aliased(item.meta, ['dc:source', 'source']);
- if (_source !== null) {
- var MyTJson = JSON.parse(_source['content']);
+IriSP.PolemicWidget.prototype.draw = function() {
+ var _slices = [],
+ _duration = this.source.getDuration(),
+ _max = 0,
+ _list = this.annotation_type ? this.source.getAnnotationsByTypeTitle(this.annotation_type) : this.source.getAnnotations();
+
+ for (var _i = 0; _i < this.sliceCount; _i++) {
+ var _begin = new IriSP.Model.Time(_i*_duration/this.sliceCount),
+ _end = new IriSP.Model.Time((_i+1)*_duration/this.sliceCount),
+ _count = 0,
+ _res = {
+ annotations : _list.filter(function(_annotation) {
+ return _annotation.begin >= _begin && _annotation.end < _end;
+ }),
+ polemicStacks : []
}
- if (item.content['polemics'] != undefined
- && item.content['polemics'][0] != null) {
-
- // a tweet can have many polemics at the same time.
- for(var j=0; j<item.content['polemics'].length; j++){
-
- this.tweets[numberOfTweet] = {
- id:i,
- qualification:colorTranslation(item.content['polemics'][j]),
- yIndicator:MyTime,
- yframe:Myframe,
- title:item.content['title'],
- timeframe:item.begin,
- userId: MyTJson.id,
- userScreenName: MyTJson.screen_name,
- tsource:MyTJson,
- cinecast_id: item.id
- };
- numberOfTweet+=1;
-
- }
- }
- else {
- this.tweets[numberOfTweet] = {
- id:i,
- qualification:colorTranslation(""),
- yIndicator:MyTime,
- yframe:Myframe,
- title:item.content['title'],
- timeframe:item.begin,
- userId: MyTJson.id,
- userScreenName: MyTJson.screen_name,
- tsource:MyTJson,
- cinecast_id: item.id
- };
- numberOfTweet+=1;
- }
-
- }
- };
-
- DrawTweets.call (this); // FIXME: ugly.
-
- };
-
- // tweet Drawing (in raphael)
- function DrawTweets (){
- // GROUPES TWEET ============================================
- // Count nbr of cluster and tweet in a frame an save int in "frames"
- numberOfTweet = this.tweets.length;
- for(var i=0; i<nbrframes; i++) {
- for(var j=0; j<numberOfTweet; j++) {
-
- if (i==this.tweets[j].yframe){
-
- var k = this.tweets[j].qualification;
-
- // make array for frame cluster
- if(frames[i]==undefined){
- frames[i] = {id:i,
- qualifVol:new Array(),
- mytweetsID:new Array()
- };
- }
- // add my tweet to frame
- frames[i].mytweetsID.push(this.tweets[j]);
-
- // count opinion by frame
- if( frames[i].qualifVol[k] == undefined){
- frames[i].qualifVol[k] = 1;
- }else{
- frames[i].qualifVol[k] += 1;
- }
-
- }
+ for (var _j = 0; _j < this.tags.length; _j++) {
+ var _polemic = _res.annotations.searchByDescription(this.tags[_j].keywords);
+ _count += _polemic.length;
+ _res.polemicStacks.push(_polemic);
+ }
+ for (var _j = 0; _j < this.tags.length; _j++) {
+ _res.annotations.removeElements(_res.polemicStacks[_j]);
}
- }
-
- // GROUPES TWEET ============================================
- // max of tweet by Frame
- var max = 0;
- for(var i = 0; i < nbrframes; i++) {
- var moy = 0;
- for (var j = 0; j < 6; j++) {
- if (frames[i] != undefined) {
- if (frames[i].qualifVol[j] != undefined) {
- moy += frames[i].qualifVol[j];
- }
- }
- }
-
- if (moy > max) {
- max = moy;
- }
- }
+ _count += _res.annotations.length;
+ _max = Math.max(_max, _count);
+ _slices.push(_res);
+ }
+ this.height = (_max ? (_max + 2) * this.element_height : 0);
+ this.$zone.css({
+ width: this.width + "px",
+ height: this.height + "px",
+ position: "relative"
+ });
- var tweetDrawed = new Array();
- var TweetHeight = 5;
- var newHeight = TweetHeight * max + 10;
-
-
- if (newHeight > this.height) {
- this.paper.setSize(this.width, newHeight);
- this.height = newHeight;
- console.log("resizeing");
- }
-
-
- // DRAW TWEETS ============================================
- for(var i = 0; i < nbrframes; i++) {
- var addEheight = 5;
- if (frames[i] != undefined){
- // by type
-
- for (var j = 6; j > -1; j--) {
- if (frames[i].qualifVol[j] != undefined) {
- // show tweet by type
- for (var k = 0; k < frames[i].mytweetsID.length; k++) {
-
- if (frames[i].mytweetsID[k].qualification == j) {
- var x = i * frameSize;
- var y = this.height - addEheight;
-
- if (this.yMax > y) {
- this.yMax = y;
- }
-
- /* some tweets seem to be duplicated - so we make a check before
- creating a new rect */
- if (this.svgElements.hasOwnProperty(frames[i].mytweetsID[k].cinecast_id))
- continue;
-
- var e = this.paper.rect(x, y, frameSize - margin, TweetHeight /* height */)
- .attr({stroke:"#00","stroke-width":0.1, fill: colors[j]});
-
- addEheight += TweetHeight;
-
- /* stick a lot of things into e because that's the easiest way
- to do it */
- e.color = colors[j];
- e.time = frames[i].mytweetsID[k].timeframe;
- e.title = frames[i].mytweetsID[k].title;
- e.id = frames[i].mytweetsID[k].cinecast_id;
- this.svgElements[e.id] = e;
-
- IriSP.jQuery(e.node).mouseenter(function(element) { return function (_e) {
- self.TooltipWidget.show.call(self.TooltipWidget, element.title, element.attr("fill"), element.attrs.x + element.attrs.width / 2, element.attrs.y - 2);
- element.displayed = true;
- self._Popcorn.trigger("IriSP.TraceWidget.MouseEvents", {
- "widget" : "StackGraphWidget",
- "type": "mousemove",
- "x": _e.pageX,
- "y": _e.pageY,
- "annotation_id": element.id
- });
- }}(e)).mousedown(function(element) { return function () {
- self._Popcorn.currentTime(element.time/1000);
- self._Popcorn.trigger("IriSP.PolemicTweet.click", element.id);
- }
- }(e));
-
- IriSP.jQuery(e.node).attr('id', 't' + k + '');
- IriSP.jQuery(e.node).attr('title', frames[i].mytweetsID[k].title);
- IriSP.jQuery(e.node).attr('begin', frames[i].mytweetsID[k].timeframe);
- }
- }
- }
- }
- }
-
- }
- // DRAW UI :: resize border and bgd
- this.paperBackground = this.paper.rect(0, 0, this.width, this.height).attr({fill:"#F8F8F8","stroke-width":0.1,opacity: 1});
-
- // outer borders
- this.outerBorders = [];
- this.outerBorders.push(this.paper.rect(0, this.height - 1, this.width, 1).attr({fill:"#ababab",stroke: "none",opacity: 1}));
- this.outerBorders.push(this.paper.rect(0, 0, this.width, 1).attr({fill:"#ababab",stroke: "none",opacity: 1}));
-
- // inner borders
- this.innerBorders = [];
- this.innerBorders.push(this.paper.rect(1, this.height - 2, this.width, 1).attr({fill:"#efefef",stroke: "none",opacity: 1}));
- this.innerBorders.push(this.paper.rect(1, 1, this.width, 1).attr({fill:"#efefef",stroke: "none",opacity: 1}));
- this.innerBorders.push(this.paper.rect(1, 1, 1, this.height - 2).attr({fill:"#d0d1d1",stroke: "none",opacity: 0.8}));
- this.innerBorders.push(this.paper.rect(this.width - 2, 1, 1, this.height - 2).attr({fill:"#efefef",stroke: "none",opacity: 1}));
-
-
-
- this.paperSlider = this.paper.rect(0, 0, 0, this.height).attr({fill:"#D4D5D5", stroke: "none", opacity: 1});
-
- // the small white line displayed over the slider.
- this.sliderTip = this.paper.rect(0, 0, 1, this.height).attr({fill:"#fc00ff", stroke: "none", opacity: 1});
- // decalage
- // tweetSelection = this.paper.rect(-100,-100,5,5).attr({fill:"#fff",stroke: "none",opacity: 1});
-
-
- this.paperSlider.toBack();
- this.paperBackground.toBack();
- this.sliderTip.toFront();
+ this.$elapsed = IriSP.jQuery('<div>')
+ .css({
+ background: '#cccccc',
+ position: "absolute",
+ top: 0,
+ left: 0,
+ width: 0,
+ height: "100%"
+ });
+
+ this.$zone.append(this.$elapsed);
+
+ var _x = 0,
+ _this = this;
+
+ function displayElement(_x, _y, _color, _id, _title) {
+ var _el = IriSP.jQuery('<div>')
+ .attr({
+ "tweet-title" : _title,
+ "pos-x" : Math.floor(_x + (_this.element_width - 1) / 2),
+ "pos-y" : _y,
+ "polemic-color" : _color,
+ "annotation-id" : _id
+ })
+ .css({
+ position: "absolute",
+ width: (_this.element_width-1) + "px",
+ height: _this.element_height + "px",
+ left: _x + "px",
+ top: _y + "px",
+ background: _color
+ })
+ .addClass("Ldt-Polemic-TweetDiv");
+ _this.$zone.append(_el);
+ return _el;
}
-
+ IriSP._(_slices).forEach(function(_slice) {
+ var _y = _this.height;
+ _slice.annotations.forEach(function(_annotation) {
+ _y -= _this.element_height;
+ displayElement(_x, _y, _this.defaultcolor, _annotation.namespacedId.name, _annotation.title);
+ });
+ IriSP._(_slice.polemicStacks).forEach(function(_annotations, _j) {
+ var _color = _this.tags[_j].color;
+ _annotations.forEach(function(_annotation) {
+ _y -= _this.element_height;
+ displayElement(_x, _y, _color, _annotation.namespacedId.name, _annotation.title);
+ });
+ });
+ _x += _this.element_width;
+ });
+
+ this.$tweets = this.$.find(".Ldt-Polemic-TweetDiv");
+
+ this.$position = IriSP.jQuery('<div>')
+ .css({
+ background: '#fc00ff',
+ position: "absolute",
+ top: 0,
+ left: "-1px",
+ width: "2px",
+ height: "100%"
+ });
+
+ this.$zone.append(this.$position);
+
+ this.$tweets
+ .mouseover(function() {
+ var _el = IriSP.jQuery(this);
+ _this.TooltipWidget.show(_el.attr("pos-x"), _el.attr("pos-y"), _el.attr("tweet-title"), _el.attr("polemic-color"));
+ })
+ .mouseout(function() {
+ _this.TooltipWidget.hide();
+ });
+
+ //TODO: Display Tweet in Tweet Widget on click
+
+ this.$zone.click(function(_e) {
+ var _x = _e.pageX - _this.$zone.offset().left;
+ _this.player.popcorn.currentTime(_this.source.getDuration().getSeconds() * _x / _this.width);
+ });
}
-/** update the positionMarker as time passes */
-IriSP.PolemicWidget.prototype.sliderUpdater = function() {
-
- var time = +this._Popcorn.currentTime();
- var duration = this.getDuration();
-
- this.paperSlider.attr("width", time * (this.width / (duration / 1000)));
-
- this.sliderTip.attr("x", time * (this.width / (duration / 1000)));
-};
-
-/** reacts to IriSP.search events */
-IriSP.PolemicWidget.prototype.searchHandler = function(searchString) {
- if (searchString == "")
- return;
-
- var matches = this._serializer.searchTweetsOccurences(searchString);
-
- if (IriSP.countProperties(matches) > 0) {
- this._Popcorn.trigger("IriSP.search.matchFound");
- } else {
- this._Popcorn.trigger("IriSP.search.noMatchFound");
- }
-
-
- // decrease the opacity of the other elements.
- for (var id in this.svgElements) {
- var e = this.svgElements[id];
- e.attr({fill: e.color, opacity: 0.4});
- }
-
-
- for (var id in matches) {
- if (this.svgElements.hasOwnProperty(id)) {
- var e = this.svgElements[id];
- this.svgElements[id].attr({fill: "#fc00ff", opacity: 1});
- }
- }
-
- this.oldSearchMatches = matches;
-};
-
-/** reacts to IriSP.search.cleared messages */
-IriSP.PolemicWidget.prototype.searchFieldClearedHandler = function() {
- for (var id in this.svgElements) {
- var e = this.svgElements[id];
- e.attr({fill: e.color, opacity: 1});
- }
-};
-
-/** reacts to IriSP.search.closed messages by clearing the highlighted elements */
-IriSP.PolemicWidget.prototype.searchFieldClosedHandler = function() {
- for (var id in this.svgElements) {
- var e = this.svgElements[id];
- e.attr({fill: e.color, opacity: 1});
- }
-
-};
-
-IriSP.PolemicWidget.prototype.showAnnotation = function(id) {
- if (this.svgElements.hasOwnProperty(id)) {
- var e = this.svgElements[id];
- this.TooltipWidget.show(e.title, e.attr("fill"), e.x - 103, e.y - 160);
- }
-};
+IriSP.PolemicWidget.prototype.onTimeupdate = function() {
+ var _x = Math.floor( this.width * this.player.popcorn.currentTime() / this.source.getDuration().getSeconds());
+ this.$elapsed.css({
+ width: _x + "px"
+ });
+ this.$position.css({
+ left: (_x - 1) + "px"
+ })
+}