1 IriSP.SegmentsWidget = function(Popcorn, config, Serializer) { |
1 define(["IriSP", "widgets", "util", "tooltipWidget"], function() { |
|
2 IriSP.SegmentsWidget = function(Popcorn, config, Serializer) { |
2 |
3 |
3 var self = this; |
4 var self = this; |
4 IriSP.Widget.call(this, Popcorn, config, Serializer); |
5 IriSP.Widget.call(this, Popcorn, config, Serializer); |
5 this.oldSearchMatches = []; |
6 this.oldSearchMatches = []; |
6 |
7 |
7 // event handlers |
8 // event handlers |
8 this._Popcorn.listen("IriSP.search", function(searchString) { self.searchHandler.call(self, searchString); }); |
9 this._Popcorn.listen("IriSP.search", function(searchString) { self.searchHandler.call(self, searchString); }); |
9 this._Popcorn.listen("IriSP.search.closed", function() { self.searchFieldClosedHandler.call(self); }); |
10 this._Popcorn.listen("IriSP.search.closed", function() { self.searchFieldClosedHandler.call(self); }); |
10 this._Popcorn.listen("IriSP.search.cleared", function() { self.searchFieldClearedHandler.call(self); }); |
11 this._Popcorn.listen("IriSP.search.cleared", function() { self.searchFieldClearedHandler.call(self); }); |
11 }; |
12 }; |
12 |
13 |
13 IriSP.SegmentsWidget.prototype = new IriSP.Widget(); |
14 IriSP.SegmentsWidget.prototype = new IriSP.Widget(); |
14 |
15 |
15 IriSP.SegmentsWidget.prototype.draw = function() { |
16 IriSP.SegmentsWidget.prototype.draw = function() { |
16 |
17 |
17 var self = this; |
18 var self = this; |
18 var annotations = this._serializer._data.annotations; |
19 var annotations = this._serializer._data.annotations; |
19 |
20 |
20 this.selector.css("overflow", "auto"); // clear the floats - FIXME : to refactor ? |
21 this.selector.css("overflow", "auto"); // clear the floats - FIXME : to refactor ? |
21 this.selector.append(Mustache.to_html(IriSP.overlay_marker_template)); |
22 this.selector.append(Mustache.to_html(IriSP.overlay_marker_template)); |
22 |
23 |
23 this.positionMarker = this.selector.children(":first"); |
24 this.positionMarker = this.selector.children(":first"); |
24 |
25 |
25 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.positionUpdater)); |
26 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.positionUpdater)); |
26 |
27 |
27 this.selector.after("<div class='cleaner'></div>"); // we need to do this because the segments are floated |
28 this.selector.after("<div class='cleaner'></div>"); // we need to do this because the segments are floated |
28 |
29 |
29 var i = 0; |
30 var i = 0; |
30 var totalWidth = this.selector.width(); |
31 var totalWidth = this.selector.width(); |
31 var onePxPercent = 100 / totalWidth; /* the value of a pixel, in percents */ |
32 var onePxPercent = 100 / totalWidth; /* the value of a pixel, in percents */ |
32 |
33 |
33 for (i = 0; i < annotations.length; i++) { |
34 for (i = 0; i < annotations.length; i++) { |
34 var annotation = annotations[i]; |
35 var annotation = annotations[i]; |
35 |
36 |
|
37 var begin = Math.round((+ annotation.begin) / 1000); |
|
38 var end = Math.round((+ annotation.end) / 1000); |
|
39 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
40 var id = annotation.id; |
|
41 var startPourcent = IriSP.timeToPourcent(begin, duration); |
|
42 |
|
43 /* some sort of collapsing occurs, so we only have to substract one pixel to each box instead of |
|
44 two |
|
45 */ |
|
46 var endPourcent = IriSP.timeToPourcent(end, duration) - startPourcent - onePxPercent * 1; |
|
47 |
|
48 /* on the other hand, we have to substract one pixel from the first box because it's the only |
|
49 one to have to effective 1px margins */ |
|
50 if (i == 0) { |
|
51 |
|
52 endPourcent -= onePxPercent; |
|
53 } |
|
54 |
|
55 var divTitle = annotation.content.title.substr(0,55); |
|
56 var color = annotation.content.color |
|
57 |
|
58 |
|
59 var annotationTemplate = Mustache.to_html(IriSP.annotation_template, |
|
60 {"divTitle" : divTitle, "id" : id, "startPourcent" : startPourcent, |
|
61 "endPourcent" : endPourcent, "hexa_color" : IriSP.DEC_HEXA_COLOR(color), |
|
62 "seekPlace" : Math.round(begin/1000)}); |
|
63 |
|
64 |
|
65 var toolTipTemplate = Mustache.to_html(IriSP.tooltip_template, |
|
66 {"title" : divTitle, "begin" : begin, "end" : end, |
|
67 "description": annotation.content.description}); |
|
68 |
|
69 this.selector.append(annotationTemplate); |
|
70 |
|
71 IriSP.jQuery("#" + id).tooltip({ effect: 'slide'}); |
|
72 |
|
73 IriSP.jQuery("#" + id).fadeTo(0, 0.3); |
|
74 |
|
75 IriSP.jQuery("#" + id).mouseover(function() { |
|
76 IriSP.jQuery("#" + id).animate({opacity: 0.6}, 5); |
|
77 }).mouseout(function(){ |
|
78 IriSP.jQuery("#" + id).animate({opacity: 0.3}, 5); |
|
79 }); |
|
80 |
|
81 IriSP.jQuery("#" + id).click(function(_this, annotation) { |
|
82 return function() { _this.clickHandler(annotation)}; |
|
83 }(this, annotation)); |
|
84 } |
|
85 }; |
|
86 |
|
87 /* restores the view after a search */ |
|
88 IriSP.SegmentsWidget.prototype.clear = function() { |
|
89 // reinit the fields |
|
90 for (var id in this.oldSearchMatches) { |
|
91 |
|
92 IriSP.jQuery("#"+id).dequeue(); |
|
93 IriSP.jQuery("#"+id).animate({height:0}, 100); |
|
94 IriSP.jQuery("#"+id).css('border-color','lightgray'); |
|
95 IriSP.jQuery("#"+id).animate({opacity:0.3}, 100); |
|
96 } |
|
97 }; |
|
98 |
|
99 IriSP.SegmentsWidget.prototype.clickHandler = function(annotation) { |
36 var begin = Math.round((+ annotation.begin) / 1000); |
100 var begin = Math.round((+ annotation.begin) / 1000); |
37 var end = Math.round((+ annotation.end) / 1000); |
101 this._Popcorn.currentTime(begin); |
38 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
102 }; |
39 var id = annotation.id; |
|
40 var startPourcent = IriSP.timeToPourcent(begin, duration); |
|
41 |
|
42 /* some sort of collapsing occurs, so we only have to substract one pixel to each box instead of |
|
43 two |
|
44 */ |
|
45 var endPourcent = IriSP.timeToPourcent(end, duration) - startPourcent - onePxPercent * 1; |
|
46 |
|
47 /* on the other hand, we have to substract one pixel from the first box because it's the only |
|
48 one to have to effective 1px margins */ |
|
49 if (i == 0) { |
|
50 |
103 |
51 endPourcent -= onePxPercent; |
104 IriSP.SegmentsWidget.prototype.searchHandler = function(searchString) { |
|
105 |
|
106 if (searchString == "") |
|
107 return; |
|
108 |
|
109 var matches = this._serializer.searchOccurences(searchString); |
|
110 |
|
111 for (var id in matches) { |
|
112 var factor = matches[id] * 8; |
|
113 this.selector.find("#"+id).dequeue(); |
|
114 this.selector.find("#"+id).animate({height: factor}, 200); |
|
115 this.selector.find("#"+id).css('border-color','red'); |
|
116 this.selector.find("#"+id).animate({opacity:0.6}, 200); |
|
117 |
|
118 IriSP.jQuery("#LdtSearchInput").css('background-color','#e1ffe1'); |
|
119 } |
|
120 |
|
121 // clean up the blocks that were in the previous search |
|
122 // but who aren't in the current one. |
|
123 for (var id in this.oldSearchMatches) { |
|
124 if (!matches.hasOwnProperty(id)) { |
|
125 IriSP.jQuery("#"+id).dequeue(); |
|
126 IriSP.jQuery("#"+id).animate({height:0}, 250); |
|
127 IriSP.jQuery("#"+id).animate({opacity:0.3}, 200); |
|
128 this.selector.find("#"+id).css('border','solid 1px #aaaaaa'); |
|
129 } |
52 } |
130 } |
53 |
131 |
54 var divTitle = annotation.content.title.substr(0,55); |
132 this.oldSearchMatches = matches; |
55 var color = annotation.content.color |
133 }; |
56 |
134 |
|
135 IriSP.SegmentsWidget.prototype.searchFieldClearedHandler = function() { |
|
136 this.clear(); |
|
137 }; |
57 |
138 |
58 var annotationTemplate = Mustache.to_html(IriSP.annotation_template, |
139 IriSP.SegmentsWidget.prototype.searchFieldClosedHandler = function() { |
59 {"divTitle" : divTitle, "id" : id, "startPourcent" : startPourcent, |
140 this.clear(); |
60 "endPourcent" : endPourcent, "hexa_color" : IriSP.DEC_HEXA_COLOR(color), |
141 }; |
61 "seekPlace" : Math.round(begin/1000)}); |
|
62 |
142 |
|
143 IriSP.SegmentsWidget.prototype.positionUpdater = function() { |
|
144 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
145 var time = this._Popcorn.currentTime(); |
|
146 var position = ((time / duration) * 100).toFixed(2); |
63 |
147 |
64 var toolTipTemplate = Mustache.to_html(IriSP.tooltip_template, |
148 this.positionMarker.css("left", position + "%"); |
65 {"title" : divTitle, "begin" : begin, "end" : end, |
149 }; |
66 "description": annotation.content.description}); |
150 }); |
67 |
|
68 this.selector.append(annotationTemplate); |
|
69 |
|
70 IriSP.jQuery("#" + id).tooltip({ effect: 'slide'}); |
|
71 |
|
72 IriSP.jQuery("#" + id).fadeTo(0, 0.3); |
|
73 |
|
74 IriSP.jQuery("#" + id).mouseover(function() { |
|
75 IriSP.jQuery("#" + id).animate({opacity: 0.6}, 5); |
|
76 }).mouseout(function(){ |
|
77 IriSP.jQuery("#" + id).animate({opacity: 0.3}, 5); |
|
78 }); |
|
79 |
|
80 IriSP.jQuery("#" + id).click(function(_this, annotation) { |
|
81 return function() { _this.clickHandler(annotation)}; |
|
82 }(this, annotation)); |
|
83 } |
|
84 }; |
|
85 |
|
86 /* restores the view after a search */ |
|
87 IriSP.SegmentsWidget.prototype.clear = function() { |
|
88 // reinit the fields |
|
89 for (var id in this.oldSearchMatches) { |
|
90 |
|
91 IriSP.jQuery("#"+id).dequeue(); |
|
92 IriSP.jQuery("#"+id).animate({height:0}, 100); |
|
93 IriSP.jQuery("#"+id).css('border-color','lightgray'); |
|
94 IriSP.jQuery("#"+id).animate({opacity:0.3}, 100); |
|
95 } |
|
96 }; |
|
97 |
|
98 IriSP.SegmentsWidget.prototype.clickHandler = function(annotation) { |
|
99 var begin = Math.round((+ annotation.begin) / 1000); |
|
100 this._Popcorn.currentTime(begin); |
|
101 }; |
|
102 |
|
103 IriSP.SegmentsWidget.prototype.searchHandler = function(searchString) { |
|
104 |
|
105 if (searchString == "") |
|
106 return; |
|
107 |
|
108 var matches = this._serializer.searchOccurences(searchString); |
|
109 |
|
110 for (var id in matches) { |
|
111 var factor = matches[id] * 8; |
|
112 this.selector.find("#"+id).dequeue(); |
|
113 this.selector.find("#"+id).animate({height: factor}, 200); |
|
114 this.selector.find("#"+id).css('border-color','red'); |
|
115 this.selector.find("#"+id).animate({opacity:0.6}, 200); |
|
116 |
|
117 IriSP.jQuery("#LdtSearchInput").css('background-color','#e1ffe1'); |
|
118 } |
|
119 |
|
120 // clean up the blocks that were in the previous search |
|
121 // but who aren't in the current one. |
|
122 for (var id in this.oldSearchMatches) { |
|
123 if (!matches.hasOwnProperty(id)) { |
|
124 IriSP.jQuery("#"+id).dequeue(); |
|
125 IriSP.jQuery("#"+id).animate({height:0}, 250); |
|
126 IriSP.jQuery("#"+id).animate({opacity:0.3}, 200); |
|
127 this.selector.find("#"+id).css('border','solid 1px #aaaaaa'); |
|
128 } |
|
129 } |
|
130 |
|
131 this.oldSearchMatches = matches; |
|
132 }; |
|
133 |
|
134 IriSP.SegmentsWidget.prototype.searchFieldClearedHandler = function() { |
|
135 this.clear(); |
|
136 }; |
|
137 |
|
138 IriSP.SegmentsWidget.prototype.searchFieldClosedHandler = function() { |
|
139 this.clear(); |
|
140 }; |
|
141 |
|
142 IriSP.SegmentsWidget.prototype.positionUpdater = function() { |
|
143 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
144 var time = this._Popcorn.currentTime(); |
|
145 var position = ((time / duration) * 100).toFixed(2); |
|
146 |
|
147 this.positionMarker.css("left", position + "%"); |
|
148 }; |
|