--- a/integration/css/common.css Tue Nov 06 18:49:13 2012 +0100
+++ b/integration/css/common.css Thu Nov 08 18:24:47 2012 +0100
@@ -380,17 +380,17 @@
/* content */
.left-content,
.right-content{
- padding-top: 8px;
float: left;
}
.left-content h2,
.right-content h2{
padding: 6px 0;
- margin-bottom: 14px;
+ margin: 8px 0 14px;
border-bottom: 1px solid #333333;
color: #30036d;
font-size: 18px;
font-weight: 600;
+ clear: both;
}
/* left-content */
.left-content{
@@ -499,6 +499,7 @@
background: #CCCCCC;
}
.frise-segment{
+ cursor: pointer;
height: 22px;
position: absolute;
background-image: url(../img/border-right-segment.png);
--- a/integration/css/edition.css Tue Nov 06 18:49:13 2012 +0100
+++ b/integration/css/edition.css Thu Nov 08 18:24:47 2012 +0100
@@ -46,27 +46,12 @@
.update-title .form-left{
float: left;
}
-.update-title textarea{
- width: 200px;
- height: 66px;
- max-width: 530px;
-}
.update-title .form-left{
margin-right: 12px;
}
.update-title .pointer{
left: 110px;
}
-.update-title label{
- display: block;
- margin-bottom: 4px;
-}
-.update-title input[type=text]{
- width: 200px;
-}
-.update-title p.titre-wrap{
- margin-bottom: 6px;
-}
/* col */
.col-middle,
.col-left,
@@ -140,7 +125,7 @@
font-size: 14px;
font-weight: 600;
color:#de2500;
- margin: 5px 0 10px;
+ margin: 5px 0 2px;
}
.time-tangle {
@@ -173,31 +158,34 @@
float: left;
}
.segmentation .form-segment-left{
- width: 228px;
+ width: 230px;
}
-.segmentation form p{
- margin-bottom: 8px;
-}
-.segmentation label{
+
+.segmentation label, .update-title label {
display: block;
font-size: 12px;
font-weight: 600;
- margin-bottom: 4px;
+ margin: 8px 0 4px;
}
-.segmentation textarea{
+.segmentation textarea, .update-title textarea {
width: 200px;
- height: 66px;
+ height: 69px;
max-width: 200px;
font-size: 12px;
}
-.segmentation input[type=text]{
+
+.segmentation textarea {
+ margin-bottom: 32px;
+}
+
+.segmentation input[type=text], .update-title input[type=text]{
font-size: 12px;
width: 200px;
height: 20px;
}
.add-segment {
- float: right; margin: 4px 0;
+ position: absolute; right: 10px; bottom: 10px;
}
.media-segments h2{
color: #30036d;
@@ -536,3 +524,21 @@
left: 0; position: absolute; width: 100%;
background: url(../img/tooltip.png) bottom no-repeat;
}
+
+.tagit {
+ border: 1px solid #867A97;
+ padding: 0 4px; width: 200px;
+ font-size: 12px; font-family: OpenSans;
+}
+
+ul.tagit li.tagit-choice {
+ padding: 3px 18px 3px 3px;
+}
+
+ul.tagit li.tagit-new {
+ padding: 0;
+}
+
+ul.tagit input[type="text"] {
+ width: 100px;
+}
--- a/integration/css/hashcut.css Tue Nov 06 18:49:13 2012 +0100
+++ b/integration/css/hashcut.css Thu Nov 08 18:24:47 2012 +0100
@@ -35,10 +35,11 @@
color: #7628df;
}
.cloner{
- float: right;
+ float: right; margin-bottom: 8px;
}
.list-video{
- height: 450px;
+ height: auto;
+ margin-left: -10px;
}
.item-video:hover,
.item-video.active{
--- a/integration/data/moon.json Tue Nov 06 18:49:13 2012 +0100
+++ b/integration/data/moon.json Thu Nov 08 18:24:47 2012 +0100
@@ -1,20 +1,20 @@
[
{
- "id": "melies",
+ "id": "f72aa2f4-29bb-11e2-a193-08002791f1b7",
"video": "http://www.iri.centrepompidou.fr/dev/~veltr/mashup/moon/melies.mp4",
"title": "Le voyage à la lune",
"author": "Georges Méliès",
"thumbnail": "http://www.iri.centrepompidou.fr/dev/~veltr/mashup/moon/melies.jpg",
"duration": 674000
}, {
- "id": "apollo",
+ "id": "7e96d10c-29be-11e2-a481-08002791f1b7",
"video": "http://www.iri.centrepompidou.fr/dev/~veltr/mashup/moon/apollo.mp4",
"title": "Apollo 11 Overview",
"author": "NASA",
"thumbnail": "http://www.iri.centrepompidou.fr/dev/~veltr/mashup/moon/apollo.jpg",
"duration": 137000
}, {
- "id": "juno",
+ "id": "7c3f5e0e-29c0-11e2-8017-08002791f1b7",
"video": "http://www.iri.centrepompidou.fr/dev/~veltr/mashup/moon/juno.mp4",
"title": "Launch of Juno!",
"author": "NASA",
--- a/integration/edition.html Tue Nov 06 18:49:13 2012 +0100
+++ b/integration/edition.html Thu Nov 08 18:24:47 2012 +0100
@@ -8,6 +8,7 @@
<meta name="author" content="Anthony Ly, Raphaël Velt" />
<title>Hashcut > Edition</title>
<link rel="stylesheet" href="lib/jquery-ui.css" />
+ <link rel="stylesheet" href="lib/jquery.tagit.css" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/common.css" />
<link rel="stylesheet" href="css/edition.css" />
@@ -24,19 +25,15 @@
<div class="popin-content">
<form class="clearfix" action="#" method="">
<div class="form-left">
- <p class="titre-wrap">
- <label for="hashcut-title">Titre :</label>
- <input type="text" id="hashcut-title" name="" value="Hashcut sans titre" />
- </p>
- <p>
- <label for="hashcut-tags">Tags :</label>
- <input type="text" id="hashcut-tags" name="" value="" />
- </p>
+ <label for="hashcut-title">Titre :</label>
+ <input type="text" id="hashcut-title" name="" value="Hashcut sans titre" />
+ <label for="hashcut-tags">Tags :</label>
+ <ul id="hashcut-tags"></ul>
</div>
- <p class="form-right">
+ <div class="form-right">
<label for="hashcut-description">Description :</label>
<textarea name="" id="hashcut-description"></textarea>
- </p>
+ </div>
</form>
</div>
</div><!-- popin update-title -->
@@ -212,7 +209,7 @@
</p>
<p>
<label for="segment-tags">Tags :</label>
- <input type="text" id="segment-tags" />
+ <ul id="segment-tags"></ul>
</p>
</div>
<div class="form-segment-right">
@@ -237,7 +234,7 @@
<div class="bloc-pvw">
- <div class="frise">
+ <div class="frise mashup-frise">
<div class="frise-overflow">
<div class="frise-segments">
</div>
@@ -270,7 +267,7 @@
</tr>
<tr>
<th>Tags :</th>
- <td><span class="annotation-tags">(fonctionnalité à venir)</span></td>
+ <td><span class="annotation-tags"></span></td>
</tr>
</tbody>
</table>
@@ -286,7 +283,7 @@
<div class="validate-tooltip"></div>
</div>
<h2>Liste des segments</h2>
- <div class="frise">
+ <div class="frise mashup-frise">
<p class="aucun-segment">Aucun segment</p>
<div class="frise-overflow">
<div class="frise-segments">
@@ -320,16 +317,18 @@
<!-- JavaScript -->
<script type="text/javascript" src="lib/jquery.min.js"></script>
<script type="text/javascript" src="lib/jquery-ui.min.js"></script>
+ <script type="text/javascript" src="lib/tag-it.js"></script>
<script type="text/javascript" src="lib/underscore-min.js"></script>
<script type="text/javascript" src="lib/popcorn-complete.min.js"></script>
<script type="text/javascript" src="js/init.js"></script>
<script type="text/javascript" src="js/medialist-serializer.js"></script>
<script type="text/javascript" src="js/model.js"></script>
+ <script type="text/javascript" src="js/mashupcore.js"></script>
<script type="text/javascript" src="js/editor.js"></script>
<script type="text/javascript" src="js/common.js"></script>
<script type="text/javascript">
$(function() {
- var hashcut = new IriSP.Hashcut({url: "data/bpidata.json"});
+ var hashcut = IriSP.editor({url: "data/moon.json"});
});
</script>
</body>
--- a/integration/hashcut.html Tue Nov 06 18:49:13 2012 +0100
+++ b/integration/hashcut.html Thu Nov 08 18:24:47 2012 +0100
@@ -158,13 +158,11 @@
</div>
</div>
- <div class="frise">
+ <div class="frise mashup-frise">
<div class="frise-overflow">
<div class="frise-segments">
- <div style="background-color:#9467bd; left:0%; width:41.02564102564102%;" class="frise-segment"></div><div style="background-color:#d62728; left:41.02564102564102%; width:58.97435897435897%;" class="frise-segment"></div>
</div>
<div class="frise-indications">
- <span style="left:12.82051282051282%;" class="frise-indication">15:00</span><span style="left:25.64102564102564%;" class="frise-indication">30:00</span><span style="left:38.46153846153846%;" class="frise-indication">45:00</span><span style="left:51.28205128205128%;" class="frise-indication">1:00:00</span><span style="left:64.1025641025641%;" class="frise-indication">1:15:00</span><span style="left:76.92307692307692%;" class="frise-indication">1:30:00</span><span style="left:89.74358974358974%;" class="frise-indication">1:45:00</span>
</div>
</div>
<div class="frise-position"></div>
@@ -197,7 +195,7 @@
<div class="right-content">
<h2>Plus d’informations</h2>
- <div class="more-info-wrap clearfix">
+ <div class="more-info-wrap">
<table class="more-info ">
<tbody>
<tr class="info-title">
@@ -206,20 +204,20 @@
</tr>
<tr class="info-duration">
<th>Durée :</th>
- <td>17:03</td>
+ <td></td>
</tr>
<tr class="info-author">
<th>Auteur : </th>
- <td><a href="#">Hashcutter75</a></td>
+ <td><a href="#"></a></td>
</tr>
<tr class="info-description">
<th>Description : </th>
- <td> An Atlas V rocket lofted the Juno spacecraft toward Jupiter from Space Launch Complex-41. The 4-ton Juno spacecraft will take five years to reach Jupiter on a mission to study its structure and decipher its history.</td>
+ <td></td>
</tr>
- <tr class="info-tags">
+<!-- <tr class="info-tags">
<th>Tags : </th>
<td>Mashup, Création, Art</td>
- </tr>
+ </tr> -->
</tbody>
</table>
<a href="#" class="button cloner">Cloner le Hashcut</a>
@@ -280,6 +278,18 @@
<script type="text/javascript" src="lib/jquery-ui.min.js"></script>
<script type="text/javascript" src="lib/underscore-min.js"></script>
<script type="text/javascript" src="lib/popcorn-complete.min.js"></script>
+ <script type="text/javascript" src="js/init.js"></script>
+ <script type="text/javascript" src="js/ldt-serializer.js"></script>
+ <script type="text/javascript" src="js/model.js"></script>
+ <script type="text/javascript" src="js/mashupcore.js"></script>
+ <script type="text/javascript" src="js/mashupplayer.js"></script>
<script type="text/javascript" src="js/common.js"></script>
+ <script type="text/javascript">
+ $(function() {
+ IriSP.player({
+ url: "data/moon-mashup.json"
+ })
+ })
+ </script>
</body>
</html>
Binary file integration/img/tooltip.png has changed
--- a/integration/js/editor.js Tue Nov 06 18:49:13 2012 +0100
+++ b/integration/js/editor.js Thu Nov 08 18:24:47 2012 +0100
@@ -13,8 +13,7 @@
mashup_title_placeholder: "Hashcut sans titre"
}
-IriSP.Hashcut = function(options) {
-
+IriSP.editor = function(options) {
/* Load Media List */
@@ -24,48 +23,60 @@
serializer: IriSP.serializers.medialist
}),
mashup = new IriSP.Model.Mashup(false, project),
- mediatemplate = _.template('<li class="item-video" data-media-id="<%= id %>"><img src="<%= thumbnail %>" alt="<%= title %>" />'
+ mediatemplate = _.template('<li class="item-video media" data-media-id="<%= id %>"><img src="<%= thumbnail %>" alt="<%= title %>" />'
+ '<span class="video-info"><span class="title-video"><%= title %></span><span class="author"><%= description %></span>'
+ '<span class="time-length"><%= IriSP.hc_messages.Duration_ %> <span><%= duration.toString() %></span></span></span></li>'),
- segmenttemplate = _.template('<li class="item-video" data-segment-id="<%= annotation.id %>" data-media-id="<%= annotation.getMedia().id %>">'
+ segmenttemplate = _.template('<li class="item-video annotation" data-segment-id="<%= annotation.id %>" data-media-id="<%= annotation.getMedia().id %>">'
+ '<img src="<%= annotation.getMedia().thumbnail %>" alt="<%= annotation.getMedia().title %>" />'
+ '<div class="validate <%= annotation.status %>"><div class="validate-tooltip"><ul><li><%= annotation.status_messages.join("</li><li>") %></li></ul></div></div><span class="video-info"><span class="title-video"><%= annotation.getMedia().title %></span>'
+ '<span class="subtitle"><%= annotation.title %></span><span class="duration"><%= annotation.begin.toString() %> - <%= annotation.end.toString() %> (<%= annotation.getDuration().toString() %>)</span>'
+ '<ul class="tools"><li><a class="edit" href="#" title="<%= IriSP.hc_messages.edit_segment %>"></a></li><li><a class="bottom" href="#" title="<%= IriSP.hc_messages.segment_down %>"></a></li>'
+ '<li><a class="top" href="#" title="<%= IriSP.hc_messages.segment_up %>"></a></li><li><a class="delete" href="#" title="<%= IriSP.hc_messages.delete_segment %>"></a></li></ul></span></li>'),
- viztemplate = _.template('<div class="frise-segment" data-segment-id="<%= segmentid %>" style="background-color:<%= color %>; left:<%= left %>%; width:<%= width %>%;"></div>'),
- intervaltemplate = _.template('<span class="frise-indication" style="left:<%= left %>%;"><%= time.toString() %></span>'),
mediasegmenttemplate = _.template('<div class="media-segments-list"><div class="media-segment">'
- + '<div class="media-section media-segment-section" style="left:<%= left %>px; width:<%= width %>px; background:<%= annotation.getMedia().color %>"></div>'
+ + '<div class="media-section media-segment-section" style="left:<%= left %>px; width:<%= width %>px; background:<%= annotation.color %>"></div>'
+ '<div class="media-section media-current-section" style="left:<%= currentleft %>px; width:<%= currentwidth %>px;"><div class="media-current-section-inner"></div></div>'
+ '<div class="popin media-segment-popin" style="left:<%= popleft %>px"><img style="left:<%= pointerpos %>px;" class="pointer" src="img/popin-triangle.png" alt="" /><div class="popin-content">'
+ '<h3><%= annotation.title %></h3><a href="#" class="button reprendre-segment" data-segment-id="<%= annotation.id %>"><%= IriSP.hc_messages.clone_segment %></a>'
+ '<p><%= IriSP.hc_messages.From_ %> <span><%= annotation.begin.toString() %></span> <%= IriSP.hc_messages.to_ %> <span><%= annotation.end.toString() %></span> (<%= IriSP.hc_messages.duration_ %> <span><%= annotation.getDuration().toString() %></span>)</p>'
- + '</div></div></div></div>');
+ + '</div></div></div></div>'),
+ addMode, currentMedia, currentSegment;
+
+ IriSP.mashupcore(project, mashup);
/* Validation of segments and mashup */
var segmentcritical = [
{
validate: function(_s) {
- var _d = _s.getDuration();
- return (_d > 1000 && _d < 180000);
+ return (_s.getDuration() >= 1000);
},
- message: "La durée du segment doit être comprise entre 1 seconde et trois minutes"
+ message: "Le segment doit durer au moins une seconde"
+ },
+ {
+ validate: function(_s) {
+ return (_s.getDuration() < 180000);
+ },
+ message: "Le segment doit durer moins de trois minutes"
},
{
validate: function(_s) {
return (!!_s.title && _s.title !== IriSP.hc_messages.segment_title_placeholder);
},
- message: "Un titre doit être donné au segment"
+ message: "Le segment doit avoir un titre"
}
];
var segmentwarning = [
{
validate: function(_s) {
- return (_s.description);
+ return (!!_s.description);
},
message: "Il est recommandé de donner une description au segment"
+ },
+ {
+ validate: function(_s) {
+ return (!!_s.keywords.length);
+ },
+ message: "Il est recommandé de tagguer le segment"
}
];
@@ -129,30 +140,14 @@
});
/* Fill right column when mashup is updated */
-
- function setPointerToCurrentAnnotation() {
- if (mashupCurrentAnnotation) {
- var p = (mashupCurrentAnnotation.begin + mashupCurrentAnnotation.end) / (2 * mashup.duration);
- $(".mashup-description .pointer").css("left", (100 * p) + "%");
- }
- }
function updateMashupUI() {
- var listhtml = '', vizhtml = '', t = 0, k = mashup.duration ? (100 / mashup.duration) : 0;
- var critical = false, warning = false, messages = [];
+ var listhtml = '', critical = false, warning = false, messages = [];
mashup.segments.forEach(function(_s) {
listhtml += segmenttemplate(_s);
- var vizdata = {
- left: k * t,
- width: k * _s.duration,
- color: _s.getMedia().color,
- segmentid: _s.annotation.id
- }
- vizhtml += viztemplate(vizdata);
if (_s.annotation.status === "critical") {
critical = true;
}
- t += _s.duration.milliseconds;
});
if (critical) {
messages.push("Certains segments ne sont pas valides");
@@ -179,217 +174,22 @@
$(".liste-segment .validate").removeClass("critical warning valid").addClass(mashup.status);
$(".liste-segment .validate-tooltip").html("<ul><li>" + messages.join("</li><li>")+"</li></ul>");
- var intervals = [ 1000, 2000, 5000, 10000, 30000, 60000, 120000, 300000, 600000, 900000, 1800000, 3600000, 7200000 ];
-
- function createIntervals(maxn) {
- for (var i = 0; i < intervals.length; i++) {
- if (mashup.duration / intervals[i] <= maxn) {
- var html = '';
- for (var j = intervals[i]; j < mashup.duration; j += intervals[i]) {
- html += intervaltemplate({ left: k * j, time: new IriSP.Model.Time(j) });
- }
- return html;
- }
- }
- return "";
- }
+ $(".col-right .list-video").html(listhtml).find(".item-video:last-child .bottom, .item-video:first-child .top").addClass("disable");
- $(".col-right .list-video").html(listhtml).find(".item-video:last-child .bottom, .item-video:first-child .top").addClass("disable");
- $(".mashup-total-duration").text(mashup.duration.toString());
- $(".frise-segments").html(vizhtml);
- $(".col-right .frise-indications").html(createIntervals(4));
- $(".bloc-pvw .frise-indications").html(createIntervals(8));
- highlightCurrentSegment();
- if (currentMedia === mashup) {
- $(".Ldt-Ctrl-Time-Total").text(currentMedia.duration.toString());
- if (mashupTimecode > mashup.duration) {
- mashup.setCurrentTime(mashup.duration);
- }
- changeCurrentAnnotation();
- setPointerToCurrentAnnotation();
- }
- }
-
- mashup.on("change",updateMashupUI);
-
- /* Slider */
-
- var timeSlider = $(".Ldt-Slider"),
- timeSliderContainer = $(".Ldt-Slider-Container"),
- slidersRange = 920;
- timeSlider.slider({
- range: "min",
- value: 0,
- min: 0,
- max: slidersRange,
- slide: function(event, ui) {
- if (currentMedia) {
- var t = currentMedia.duration * ui.value / slidersRange;
- currentMedia.setCurrentTime(t);
- }
- }
- });
-
- var timeSliderHandle = timeSlider.find('.ui-slider-handle'),
- timeSliderMaximized = false,
- timeSliderTimeoutId = false,
- timeSliderMinimizedHeight = 4,
- timeSliderMaximizedHeight = 10,
- timeSliderTimeoutDuration = 1500,
- timeTooltip = $(".Ldt-Slider-Time");
-
- timeSliderContainer.css(calculateSliderCss(timeSliderMinimizedHeight));
- timeSliderHandle.css(calculateHandleCss(timeSliderMinimizedHeight));
-
- function timeSliderMouseOver() {
- if (timeSliderTimeoutId) {
- window.clearTimeout(timeSliderTimeoutId);
- timeSliderTimeoutId = false;
- }
- if (!timeSliderMaximized) {
- timeSliderAnimateToHeight(timeSliderMaximizedHeight);
- timeSliderMaximized = true;
- }
- }
-
- function timeSliderMouseOut() {
- timeTooltip.hide();
- if (timeSliderTimeoutId) {
- clearTimeout(timeSliderTimeoutId);
- timeSliderTimeoutId = false;
- }
- timeSliderTimeoutId = setTimeout(function() {
- if (timeSliderMaximized) {
- timeSliderAnimateToHeight(timeSliderMinimizedHeight);
- timeSliderMaximized = false;
- }
- timeSliderTimeoutId = false;
- }, timeSliderTimeoutDuration);
+ project.trigger("mouseout-annotation");
}
- timeSliderContainer
- .mouseover(function() {
- timeTooltip.show();
- timeSliderMouseOver();
- })
- .mouseout(timeSliderMouseOut);
- timeSlider.mousemove(function(_e) {
- var _x = _e.pageX - timeSlider.offset().left,
- _t = new IriSP.Model.Time(
- );
- timeTooltip.text(_t.toString()).css("left",_x);
- });
-
- $(".Ldt-Ctrl").mouseover(timeSliderMouseOver).mouseout(timeSliderMouseOut);
-
- function timeSliderAnimateToHeight(_height) {
- timeSliderContainer.stop().animate(
- calculateSliderCss(_height),
- 500,
- function() {
- IriSP.jQuery(this).css("overflow","visible");
- });
- timeSliderHandle.stop().animate(
- calculateHandleCss(_height),
- 500,
- function() {
- IriSP.jQuery(this).css("overflow","visible");
- });
- }
-
- function calculateSliderCss(_size) {
- return {
- height: _size + "px",
- "margin-top": (timeSliderMinimizedHeight - _size) + "px"
- };
- }
-
- function calculateHandleCss(_size) {
- return {
- height: (2 + _size) + "px",
- width: (2 + _size) + "px",
- "margin-left": -Math.ceil(2 + _size / 2) + "px"
- }
- }
-
- /* Controller Widget */
-
- var volBlock = $(".Ldt-Ctrl-Volume-Control");
-
- $('.Ldt-Ctrl-Sound')
- .click(function() {
- if (currentMedia) {
- currentMedia.setMuted(!currentMedia.getMuted());
- }
- })
- .mouseover(function() {
- volBlock.show();
- })
- .mouseout(function() {
- volBlock.hide();
- });
- volBlock.mouseover(function() {
- volBlock.show();
- }).mouseout(function() {
- volBlock.hide();
+ mashup.on("setcurrent", function() {
+ currentMedia = mashup;
});
- var volBar = $(".Ldt-Ctrl-Volume-Bar");
-
- function ctrlVolumeUpdater() {
- if (currentMedia) {
- var _muted = currentMedia.getMuted(),
- _vol = currentMedia.getVolume();
- if (_vol === false) {
- _vol = .5;
- }
- var _soundCtl = $(".Ldt-Ctrl-Sound");
- _soundCtl.removeClass("Ldt-Ctrl-Sound-Mute Ldt-Ctrl-Sound-Half Ldt-Ctrl-Sound-Full");
- if (_muted) {
- _soundCtl.attr("title", "Activer le son")
- .addClass("Ldt-Ctrl-Sound-Mute");
- } else {
- _soundCtl.attr("title", "Couper le son")
- .addClass(_vol < .5 ? "Ldt-Ctrl-Sound-Half" : "Ldt-Ctrl-Sound-Full" )
- }
- volBar.slider("value", _muted ? 0 : 100 * _vol);
- volBar.attr("title",'Volume : ' + Math.floor(100 * _vol) + '%');
- }
- }
-
- volBar.slider({
- slide: function(event, ui) {
- if (currentMedia) {
- currentMedia.setVolume(ui.value / 100);
- }
- }
- });
-
- $(".Ldt-Ctrl-Play").click(function() {
- if (currentMedia) {
- if (currentMedia.getPaused()) {
- currentMedia.play();
- } else {
- currentMedia.pause();
- }
- }
- });
-
- $(".Ldt-Ctrl-SetIn").click(function() {
- if (currentMedia && currentSegment) {
- currentSegment.setBegin(currentMedia.getCurrentTime());
- }
- });
- $(".Ldt-Ctrl-SetOut").click(function() {
- if (currentMedia && currentSegment) {
- currentSegment.setEnd(currentMedia.getCurrentTime());
- }
- });
+ mashup.on("change",updateMashupUI);
/* Slice Widget */
var sliceSlider = $(".Ldt-Slice"),
- sliceStartTime;
+ sliceStartTime,
+ slidersRange = 920;
sliceSlider.slider({
range: true,
@@ -430,93 +230,8 @@
}
});
- /* UI Events */
-
- function onCurrentMediaPlay() {
- $(".Ldt-Ctrl-Play")
- .attr("title", "Pause")
- .removeClass("Ldt-Ctrl-Play-PlayState")
- .addClass("Ldt-Ctrl-Play-PauseState")
- }
- function onCurrentMediaPause() {
- $(".Ldt-Ctrl-Play")
- .attr("title", "Lecture")
- .removeClass("Ldt-Ctrl-Play-PauseState")
- .addClass("Ldt-Ctrl-Play-PlayState")
- }
-
- function onCurrentMediaTimeupdate(_time) {
- $(".Ldt-Ctrl-Time-Elapsed").text(_time.toString());
- timeSlider.slider("value",slidersRange * _time / currentMedia.duration);
- }
-
- /* Mashup Player */
-
- var mashupCurrentMedia = null,
- mashupCurrentAnnotation = null,
- mashupSegmentBegin,
- mashupSegmentEnd,
- mashupTimecode = 0,
- mashupSeeking = false,
- seekdiv = $(".video-wait"),
- mashupTimedelta;
-
- function showSeek() {
- if (mashupSeeking) {
- seekdiv.show();
- }
- }
-
- function changeCurrentAnnotation() {
- if (mashupTimecode >= mashup.duration) {
- if (!mashup.paused) {
- mashup.paused = true;
- mashup.trigger("pause");
- }
- mashupTimecode = 0;
- }
- var _annotation = mashup.getAnnotationAtTime( mashupTimecode );
- if (typeof _annotation === "undefined") {
- if (mashupCurrentMedia) {
- mashupCurrentMedia.pause();
- if (!mashup.paused) {
- mashup.paused = true;
- mashup.trigger("pause");
- }
- }
- return;
- }
- mashupCurrentAnnotation = _annotation;
- mashupSegmentBegin = mashupCurrentAnnotation.annotation.begin.milliseconds;
- mashupSegmentEnd = mashupCurrentAnnotation.annotation.end.milliseconds;
- mashupTimedelta = mashupSegmentBegin - mashupCurrentAnnotation.begin.milliseconds;
- mashupCurrentMedia = mashupCurrentAnnotation.getMedia();
-
- project.getMedias().forEach(function(_media) {
- if (_media !== mashupCurrentMedia) {
- _media.hide();
- _media.pause();
- } else {
- _media.show();
- }
- });
-
- mashupCurrentMedia.setCurrentTime( mashupTimecode + mashupTimedelta);
- mashupCurrentMedia.seeking = true;
-
- if (!mashup.paused) {
- mashupCurrentMedia.play();
- mashupSeeking = true;
- setTimeout(showSeek,200);
- }
- mashup.trigger("timeupdate", new IriSP.Model.Time(mashupTimecode));
-
- }
-
- /* Set current Media */
-
- var currentMedia, currentSegment;
+ /* Update Segment UI */
function updateSegmentUI() {
if (currentMedia && currentSegment) {
@@ -564,23 +279,14 @@
}
}
- var addMode;
-
function setMedia(media) {
if (currentMedia) {
currentMedia.pause();
}
currentMedia = media;
+ project.trigger("set-current", media);
if (currentMedia.elementType == "media") {
- $("video").hide();
showSegmentation();
- if (!currentMedia.loaded) {
- seekdiv.show();
- }
- var currentvideo = $('#video_' + currentMedia.id);
- if (!currentvideo.length) {
- addMediaPlayer(currentMedia);
- }
$(".tab-media-title").text(currentMedia.title);
addMode = !(currentSegment && mashup.hasAnnotation(currentSegment));
@@ -591,6 +297,8 @@
currentSegment.setBegin(0);
currentSegment.setEnd(currentMedia.duration);
currentSegment.title = IriSP.hc_messages.segment_title_placeholder;
+ currentSegment.color = currentMedia.color;
+ currentSegment.keywords = [];
currentSegment.description = "";
currentSegment.on("change-begin", function() {
if (currentMedia && currentSegment === this) {
@@ -604,28 +312,25 @@
updateSegmentUI();
}
});
- currentSegment.on("enter", function() {
- if (currentMedia === mashup) {
- $(".annotation-title").text(this.title);
- $(".annotation-begin").text(this.begin.toString());
- $(".annotation-end").text(this.end.toString());
- $(".annotation-media-title").text(this.getMedia().title);
- $(".annotation-description").text(this.description);
- setPointerToCurrentAnnotation();
- highlightCurrentSegment();
- }
- });
}
if (currentMedia.loaded) {
currentMedia.setCurrentTime(currentSegment.begin);
}
$(".add-segment").val(addMode ? "Ajouter au Hashcut" : "Sauvegarder");
$(".create-or-edit").text(addMode ? "Créer un nouveau segment" : "Modifier le segment");
- updateSegmentUI();
media.show();
$("#segment-title").val(currentSegment.title);
$("#segment-description").val(currentSegment.description);
- $("#segment-tags").val("");
+ var segment_tags = $("#segment-tags");
+ segment_tags.tagit("option","onTagRemoved",function(){});
+ segment_tags.tagit("option","onTagAdded",function(){});
+ segment_tags.tagit("removeAll");
+ _(currentSegment.keywords).each(function(tag) {
+ segment_tags.tagit("createTag",tag);
+ });
+ segment_tags.tagit("option","onTagRemoved",updateSegmentTags);
+ segment_tags.tagit("option","onTagAdded",updateSegmentTags);
+ updateSegmentUI();
var relatedSegments = mashup.segments.filter(function(_s) {
return _s.getMedia() === currentMedia && _s.annotation !== currentSegment;
});
@@ -652,254 +357,15 @@
} else {
$(".self-media-segments").hide();
}
+
+ //TODO: Show Related Segments from http://capsicum/pf/ldtplatform/api/ldt/1.0/segments/bytimecode/f72aa2f4-29bb-11e2-a193-08002791f1b7/0/674000?format=json
+
}
$(".self-media-segments .media-segments-list").html(html);
if (currentMedia.elementType === "mashup") {
showPreview();
- mashup.checkLoaded();
}
- $(".Ldt-Ctrl-Time-Total").text(currentMedia.duration.toString());
- // TODO: Do something with the tags !
- onCurrentMediaTimeupdate(currentMedia.getCurrentTime());
- onCurrentMediaPause();
- highlightCurrentSegment();
}
-
- function addMediaPlayer(media) {
- var videoid = "video_" + media.id,
- videoEl = $('<video>'),
- width = $(".video").width(),
- height = $(".video").height(),
- mp4_file = media.video.replace(/\.webm$/i,'.mp4'),
- webm_file = media.video.replace(/\.mp4$/i,'.webm'),
- mp4_src = $('<source>'),
- webm_src = $('<source>');
- mp4_src.attr({
- src: mp4_file,
- type: "video/mp4"
- });
- webm_src.attr({
- src: webm_file,
- type: "video/webm"
- });
- videoEl.attr({
- id : videoid,
- width : width,
- height : height
- }).css({
- position : "absolute",
- left: 0,
- top: 0,
- width : width,
- height : height
- });
- videoEl.append(mp4_src).append(webm_src);
- $(".video").append(videoEl);
-
- media.show = function() {
- videoEl.show();
- }
- media.hide = function() {
- videoEl.hide();
- }
-
- var popcorn = Popcorn("#" + videoid);
-
- // Binding functions to Popcorn
-
- media.on("setcurrenttime", function(_milliseconds) {
- if (media.loaded) {
- popcorn.currentTime(_milliseconds / 1000);
- }
- });
-
- media.on("setvolume", function(_vol) {
- media.volume = _vol;
- if (media.loaded) {
- popcorn.volume(_vol);
- }
- });
-
- media.on("setmuted", function(_muted) {
- media.muted = _muted;
- if (media.loaded) {
- popcorn.muted(_muted);
- }
- });
-
- media.on("setplay", function() {
- if (media.loaded) {
- popcorn.play();
- }
- });
-
- media.on("setpause", function() {
- if (media.loaded) {
- popcorn.pause();
- }
- });
-
- // Binding Popcorn events to media
-
- function getVolume() {
- media.muted = popcorn.muted();
- media.volume = popcorn.volume();
- }
-
- popcorn.on("loadedmetadata", function() {
- getVolume();
- media.loaded = true;
- media.trigger("loadedmetadata");
- media.trigger("volumechange");
- })
-
- popcorn.on("timeupdate", function() {
- media.trigger("timeupdate", new IriSP.Model.Time(1000*popcorn.currentTime()));
- });
-
- popcorn.on("volumechange", function() {
- getVolume();
- media.trigger("volumechange");
- })
-
- popcorn.on("play", function() {
- media.trigger("play");
- });
-
- popcorn.on("pause", function() {
- media.trigger("pause");
- });
-
- popcorn.on("seeked", function() {
- media.trigger("seeked");
- });
-
- // Binding UI Events and Mashup Playing to Media
-
- media.on("loadedmetadata", function() {
- if (media === currentMedia) {
- seekdiv.hide();
- }
- mashup.checkLoaded();
- });
-
- media.on("play", function() {
- if (media === currentMedia) {
- onCurrentMediaPlay();
- }
- if (mashup === currentMedia && media === mashupCurrentMedia) {
- mashup.trigger("play");
- }
- });
-
- media.on("pause", function() {
- if (media === currentMedia) {
- onCurrentMediaPause();
- }
- if (mashup === currentMedia && media === mashupCurrentMedia) {
- mashup.trigger("pause");
- }
- });
-
- media.on("timeupdate", function(_time) {
- if (media === currentMedia) {
- onCurrentMediaTimeupdate(_time);
- }
- if (mashup === currentMedia && !mashup.paused && media === mashupCurrentMedia && !media.seeking) {
- if ( _time < mashupSegmentEnd ) {
- if ( _time >= mashupSegmentBegin ) {
- mashupTimecode = _time - mashupTimedelta;
- } else {
- mashupTimecode = mashupSegmentBegin - mashupTimedelta;
- media.setCurrentTime(mashupSegmentBegin);
- }
- } else {
- mashupTimecode = mashupSegmentEnd - mashupTimedelta;
- media.pause();
- changeCurrentAnnotation();
- }
- mashup.trigger("timeupdate", new IriSP.Model.Time(mashupTimecode));
- }
- });
-
- media.on("seeked", function() {
- media.seeking = false;
- if (mashup === currentMedia && media === mashupCurrentMedia && mashupSeeking) {
- mashupSeeking = false;
- seekdiv.hide();
- }
- });
-
- media.on("volumechange", function() {
- if (media === currentMedia) {
- ctrlVolumeUpdater();
- }
- mashup.muted = media.muted;
- mashup.volume = media.volume;
- mashup.trigger("volumechange");
- })
-
- }
-
- // Mashup Events
-
- mashup.on("setcurrenttime", function(_milliseconds) {
- mashupTimecode = _milliseconds;
- changeCurrentAnnotation();
- });
-
- mashup.on("setvolume", function(_vol) {
- mashup.getMedias().forEach(function(_media) {
- _media.setVolume(_vol);
- });
- mashup.volume = _vol;
- });
-
- mashup.on("setmuted", function(_muted) {
- mashup.getMedias().forEach(function(_media) {
- _media.setMuted(_muted);
- });
- mashup.muted = _muted;
- });
-
- mashup.on("setplay", function() {
- mashup.paused = false;
- changeCurrentAnnotation();
- });
-
- mashup.on("setpause", function() {
- mashup.paused = true;
- if (mashupCurrentMedia) {
- mashupCurrentMedia.pause();
- }
- });
-
- mashup.on("loadedmetadata", function() {
- if (mashup === currentMedia) {
- changeCurrentAnnotation();
- }
- });
-
- /* Mashup Events to UI */
-
- mashup.on("play", function() {
- if (mashup === currentMedia) {
- onCurrentMediaPlay();
- }
- });
-
- mashup.on("pause", function() {
- if (mashup === currentMedia) {
- onCurrentMediaPause();
- }
- });
-
- mashup.on("timeupdate", function(_time) {
- if (mashup === currentMedia) {
- $(".frise-position").css("left",(100*_time/mashup.duration)+"%");
- onCurrentMediaTimeupdate(_time);
- }
- });
/* Segment Form interaction */
@@ -907,29 +373,43 @@
if (currentMedia && currentSegment) {
currentSegment.title = $(this).val();
updateSegmentUI();
- updateMashupUI();
+ mashup.trigger("change");
}
});
$("#segment-description").on("keyup change input paste", function() {
if (currentMedia && currentSegment) {
currentSegment.description = $(this).val();
- updateSegmentUI();
+ mashup.trigger("change");
}
});
$("#segment-form").submit(function() {
if (addMode) {
mashup.addAnnotation(currentSegment);
} else {
- updateMashupUI();
+ mashup.trigger("change");
}
var segment = mashup.getAnnotation(currentSegment);
currentSegment = undefined;
setMedia(mashup);
if (segment) {
mashup.setCurrentTime(segment.begin);
+ mashup.trigger("enter-annotation",segment);
}
return false;
- })
+ });
+
+ $("#segment-tags").tagit();
+
+
+ /* We have to defer this function because the tagit events
+ * are triggered before the data are updated */
+ function updateSegmentTags() {
+ window.setTimeout(function() {
+ if (currentMedia && currentSegment) {
+ currentSegment.keywords = $("#segment-tags").tagit("assignedTags");
+ }
+ }, 0);
+ }
/* Click on media items */
@@ -967,50 +447,40 @@
mashup.setAnnotationsById(ids);
}
- function highlightCurrentSegment() {
- $(".organize-segments .item-video, .col-left .item-video, .frise-segment").removeClass("active");
- var segmentid = undefined;
- if (currentMedia && currentSegment) {
- segmentid = currentSegment.id;
- }
- if (currentMedia === mashup && mashupCurrentAnnotation) {
- segmentid = mashupCurrentAnnotation.annotation.id;
- }
- $(".item-video[data-segment-id='" + segmentid + "']").addClass("active");
+ project.on("mouseover-annotation", function(annotation) {
+ var mediaid = annotation.getMedia().id;
+ $(".media").removeClass("active");
+ $(".media[data-media-id='" + mediaid + "']").addClass("active");
+ });
+
+ project.on("mouseout-annotation", function(annotation) {
+ $(".media").removeClass("active");
var mediaid = undefined;
- if (currentMedia) {
+ if (currentMedia && currentMedia.elementType === "media") {
mediaid = currentMedia.id;
+ if (currentSegment) {
+ $(".annotation").removeClass("active");
+ $(".annotation[data-segment-id='" + currentSegment.id + "']").addClass("active");
+ }
}
- if (currentMedia === mashup && mashupCurrentMedia) {
- mediaid = mashupCurrentMedia.id
+ if (currentMedia === mashup && mashup.currentMedia) {
+ mediaid = mashup.currentMedia.id
}
- $(".col-left .item-video[data-media-id='" + mediaid + "']").addClass("active");
- }
-
- function hoverSegment() {
- var segmentid = $(this).attr("data-segment-id");
- $(".organize-segments .item-video, .frise-segment").removeClass("active");
- $(".item-video[data-segment-id='" + segmentid + "'], .frise-segment[data-segment-id='" + segmentid + "']").addClass("active");
- }
-
- $(".frise")
- .on("mouseover", ".frise-segment", hoverSegment)
- .on("mouseout", ".frise-segment", highlightCurrentSegment)
+ $(".media[data-media-id='" + mediaid + "']").addClass("active");
+ });
$(".organize-segments")
.sortable({
stop : reorganizeMashup
})
- .on("mouseover", ".item-video", hoverSegment)
- .on("mouseout", ".item-video", highlightCurrentSegment)
- .on("click", ".item-video", function(e) {
- var el = $(this),
- segment = mashup.getAnnotationById(el.attr("data-segment-id"));
- setMedia(mashup);
- if (segment) {
- mashup.setCurrentTime(segment.begin);
- }
- return false;
+ .on("mouseover", ".item-video", function() {
+ project.trigger("mouseover-annotation", project.getElement($(this).attr("data-segment-id")));
+ })
+ .on("mouseout", ".item-video", function() {
+ project.trigger("mouseout-annotation");
+ })
+ .on("click", ".item-video", function() {
+ project.trigger("click-annotation", project.getElement($(this).attr("data-segment-id")));
})
.on("click", ".edit", function(e) {
var currentItem = $(this).parents(".item-video"),
@@ -1130,6 +600,11 @@
/* Changing Hashcut Title and description */
+ $("#hashcut-tags").tagit({
+ onTagRemoved: updateSegmentTags,
+ onTagAdded: updateSegmentTags
+ });
+
mashup.title = IriSP.hc_messages.mashup_title_placeholder;
$(".title-video-wrap a").text(mashup.title);
$("#hashcut-title").val(mashup.title);
@@ -1137,13 +612,19 @@
$("#hashcut-title").on("keyup change input paste", function() {
mashup.title = $(this).val();
$(".title-video-wrap a").text(mashup.title);
- updateMashupUI();
+ mashup.trigger("change");
});
$("#hashcut-description").on("keyup change input paste", function() {
mashup.description = $(this).val();
- updateMashupUI();
+ mashup.trigger("change");
});
- updateMashupUI();
+ function updateMashupTags() {
+ window.setTimeout(function() {
+ mashup.keywords = $("#segment-tags").tagit("assignedTags");
+ }, 0);
+ }
+
+ mashup.trigger("change");
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/integration/js/ldt-serializer.js Thu Nov 08 18:24:47 2012 +0100
@@ -0,0 +1,215 @@
+/* LDT Platform Serializer */
+
+if (typeof IriSP.serializers === "undefined") {
+ IriSP.serializers = {}
+}
+
+IriSP.serializers.ldt = {
+ types : {
+ media : {
+ serialized_name : "medias",
+ deserializer : function(_data, _source) {
+ var _res = new IriSP.Model.Media(_data.id, _source);
+ _res.video = (
+ typeof _data.url !== "undefined"
+ ? _data.url
+ : (
+ typeof _data.href !== "undefined"
+ ? _data.href
+ : null
+ )
+ );
+ if (typeof _data.meta.item !== "undefined" && _data.meta.item.name === "streamer") {
+ _res.streamer = _data.meta.item.value;
+ }
+ _res.title = _data.meta["dc:title"];
+ _res.description = _data.meta["dc:description"];
+ _res.setDuration(_data.meta["dc:duration"]);
+ _res.url = _data.meta.url;
+ if (typeof _data.meta.img !== "undefined" && _data.meta.img.src !== "undefined") {
+ _res.thumbnail = _data.meta.img.src;
+ }
+ return _res;
+ },
+ serializer : function(_data, _source) {
+ return {
+ id : _data.id,
+ url : _data.video,
+ meta : {
+ "dc:title" : _data.title,
+ "dc:description" : _data.description,
+ "dc:duration" : _data.duration.milliseconds
+ }
+ }
+ }
+ },
+ tag : {
+ serialized_name : "tags",
+ model_name : "tag",
+ deserializer : function(_data, _source) {
+ var _res = new IriSP.Model.Tag(_data.id, _source);
+ _res.title = _data.meta["dc:title"];
+ return _res;
+ },
+ serializer : function(_data, _source) {
+ return {
+ id : _data.id,
+ meta : {
+ "dc:title" : _data.title
+ }
+ }
+ }
+ },
+ annotationType : {
+ serialized_name : "annotation-types",
+ deserializer : function(_data, _source) {
+ var _res = new IriSP.Model.AnnotationType(_data.id, _source);
+ _res.title = _data["dc:title"];
+ _res.description = _data["dc:description"];
+ return _res;
+ },
+ serializer : function(_data, _source) {
+ return {
+ id : _data.id,
+ "dc:title" : _data.title,
+ "dc:description" : _data.description
+ }
+ }
+ },
+ annotation : {
+ serialized_name : "annotations",
+ deserializer : function(_data, _source) {
+ var _res = new IriSP.Model.Annotation(_data.id, _source);
+ _res.title = _data.content.title || "";
+ _res.description = _data.content.description || "";
+ if (typeof _data.content.img !== "undefined" && _data.content.img.src !== "undefined") {
+ _res.thumbnail = _data.content.img.src;
+ }
+ _res.created = IriSP.Model.isoToDate(_data.meta["dc:created"]);
+ if (typeof _data.color !== "undefined") {
+ var _c = parseInt(_data.color).toString(16);
+ while (_c.length < 6) {
+ _c = '0' + _c;
+ }
+ _res.color = '#' + _c;
+ }
+ _res.setMedia(_data.media);
+ _res.setAnnotationType(_data.meta["id-ref"]);
+ _res.setTags(IriSP._(_data.tags).pluck("id-ref"));
+ _res.keywords = _res.getTagTexts();
+ _res.setBegin(_data.begin);
+ _res.setEnd(_data.end);
+ _res.creator = _data.meta["dc:creator"] || "";
+ _res.project = _data.meta.project || "";
+ if (typeof _data.meta["dc:source"] !== "undefined" && typeof _data.meta["dc:source"].content !== "undefined") {
+ _res.source = JSON.parse(_data.meta["dc:source"].content);
+ }
+ if (typeof _data.content.audio !== "undefined" && _data.content.audio.href) {
+ _res.audio = _data.content.audio;
+ }
+ return _res;
+ },
+ serializer : function(_data, _source) {
+ return {
+ id : _data.id,
+ begin : _data.begin.milliseconds,
+ end : _data.end.milliseconds,
+ content : {
+ title : _data.title,
+ description : _data.description,
+ audio : _data.audio
+ },
+ media : _data.media.id,
+ meta : {
+ "id-ref" : _data.annotationType.id,
+ "dc:created" : IriSP.Model.dateToIso(_data.created),
+ "dc:creator" : _data.creator,
+ project : _source.projectId
+ },
+ tags : IriSP._(_data.tag.id).map(function(_id) {
+ return {
+ "id-ref" : _id
+ }
+ })
+ }
+ }
+ },
+ mashup : {
+ serialized_name : "lists",
+ deserializer : function(_data, _source) {
+ if (typeof _data.meta !== "object" || typeof _data.meta.listtype !== "string" || _data.meta.listtype !== "mashup") {
+ return undefined;
+ }
+ var _res = new IriSP.Model.Mashup(_data.id, _source);
+ _res.title = _data.meta["dc:title"];
+ _res.description = _data.meta["dc:description"];
+ _res.creator = _data.meta["dc:creator"];
+ _res.setAnnotationsById(_data.items);
+ return _res;
+ },
+ serializer : function(_data, _source) {
+ return {
+ meta : {
+ "dc:title": _data.title,
+ "dc:description": _data.description,
+ listtype: "mashup"
+ },
+ items: _data.segments.map(function(_annotation) {
+ return _id;
+ }),
+ id: _data.id
+ }
+ }
+ }
+ },
+ serialize : function(_source) {
+ var _res = {},
+ _this = this;
+ _source.forEach(function(_list, _typename) {
+ if (typeof _this.types[_typename] !== "undefined") {
+ _res[_this.types[_typename].serialized_name] = _list.map(function(_el) {
+ return _this.types[_typename].serializer(_el, _source);
+ });
+ }
+ });
+ return JSON.stringify(_res);
+ },
+ loadData : function(_url, _callback) {
+ IriSP.jQuery.getJSON(_url, _callback)
+ },
+ deSerialize : function(_data, _source) {
+ if (typeof _data !== "object" || _data === null) {
+ return;
+ }
+ IriSP._(this.types).forEach(function(_type, _typename) {
+ var _listdata = _data[_type.serialized_name],
+ _list = new IriSP.Model.List(_source.directory);
+ if (typeof _listdata !== "undefined" && _listdata !== null) {
+ if (_listdata.hasOwnProperty("length")) {
+ var _l = _listdata.length;
+ for (var _i = 0; _i < _l; _i++) {
+ var _element = _type.deserializer(_listdata[_i], _source);
+ if (typeof _element !== "undefined" && _element) {
+ _list.push(_element);
+ }
+ }
+ } else {
+ var _element = _type.deserializer(_listdata, _source);
+ if (typeof _element !== "undefined" && _element) {
+ _list.push(_element);
+ }
+ }
+ }
+ _source.addList(_typename, _list);
+ });
+
+ if (typeof _data.meta !== "undefined") {
+ _source.projectId = _data.meta.id;
+ }
+
+ if (typeof _data.meta !== "undefined" && typeof _data.meta.main_media !== "undefined" && typeof _data.meta.main_media["id-ref"] !== "undefined") {
+ _source.currentMedia = _source.getElement(_data.meta.main_media["id-ref"]);
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/integration/js/mashupcore.js Thu Nov 08 18:24:47 2012 +0100
@@ -0,0 +1,632 @@
+IriSP.mashupcore = function(project, mashup) {
+
+ var currentMedia,
+ intervaltemplate = _.template('<span class="frise-indication" style="left:<%= left %>%;"><%= time.toString() %></span>'),
+ viztemplate = _.template('<div class="frise-segment annotation" data-segment-id="<%= segmentid %>" style="background-color:<%= color %>; left:<%= left %>%; width:<%= width %>%;"></div>');
+
+ function updateMashupUI() {
+ var vizhtml = '', t = 0, k = mashup.duration ? (100 / mashup.duration) : 0;
+ mashup.segments.forEach(function(_s) {
+ var vizdata = {
+ left: k * t,
+ width: k * _s.duration,
+ color: _s.color,
+ segmentid: _s.annotation.id
+ }
+ vizhtml += viztemplate(vizdata);
+ t += _s.duration.milliseconds;
+ });
+
+ var intervals = [ 1000, 2000, 5000, 10000, 30000, 60000, 120000, 300000, 600000, 900000, 1800000, 3600000, 7200000 ];
+
+ function createIntervals(maxn) {
+ for (var i = 0; i < intervals.length; i++) {
+ if (mashup.duration / intervals[i] <= maxn) {
+ var html = '';
+ for (var j = intervals[i]; j < mashup.duration; j += intervals[i]) {
+ html += intervaltemplate({ left: k * j, time: new IriSP.Model.Time(j) });
+ }
+ return html;
+ }
+ }
+ return "";
+ }
+
+ $(".mashup-total-duration").text(mashup.duration.toString());
+ $(".mashup-frise .frise-segments").html(vizhtml);
+ $(".mashup-frise .frise-indications").html(createIntervals(6));
+
+ if (currentMedia === mashup) {
+ $(".Ldt-Ctrl-Time-Total").text(currentMedia.duration.toString());
+ if (mashupTimecode > mashup.duration) {
+ mashup.setCurrentTime(mashup.duration);
+ }
+ changeCurrentAnnotation();
+ mashup.trigger("enter-annotation",mashupCurrentAnnotation);
+ }
+
+ }
+
+ /* Slider */
+
+ var timeSlider = $(".Ldt-Slider"),
+ timeSliderContainer = $(".Ldt-Slider-Container"),
+ slidersRange = 920;
+ timeSlider.slider({
+ range: "min",
+ value: 0,
+ min: 0,
+ max: slidersRange,
+ slide: function(event, ui) {
+ if (currentMedia) {
+ var t = currentMedia.duration * ui.value / slidersRange;
+ currentMedia.setCurrentTime(t);
+ }
+ }
+ });
+
+ var timeSliderHandle = timeSlider.find('.ui-slider-handle'),
+ timeSliderMaximized = false,
+ timeSliderTimeoutId = false,
+ timeSliderMinimizedHeight = 4,
+ timeSliderMaximizedHeight = 10,
+ timeSliderTimeoutDuration = 1500,
+ timeTooltip = $(".Ldt-Slider-Time");
+
+ timeSliderContainer.css(calculateSliderCss(timeSliderMinimizedHeight));
+ timeSliderHandle.css(calculateHandleCss(timeSliderMinimizedHeight));
+
+ function timeSliderMouseOver() {
+ if (timeSliderTimeoutId) {
+ window.clearTimeout(timeSliderTimeoutId);
+ timeSliderTimeoutId = false;
+ }
+ if (!timeSliderMaximized) {
+ timeSliderAnimateToHeight(timeSliderMaximizedHeight);
+ timeSliderMaximized = true;
+ }
+ }
+
+ function timeSliderMouseOut() {
+ timeTooltip.hide();
+ if (timeSliderTimeoutId) {
+ clearTimeout(timeSliderTimeoutId);
+ timeSliderTimeoutId = false;
+ }
+ timeSliderTimeoutId = setTimeout(function() {
+ if (timeSliderMaximized) {
+ timeSliderAnimateToHeight(timeSliderMinimizedHeight);
+ timeSliderMaximized = false;
+ }
+ timeSliderTimeoutId = false;
+ }, timeSliderTimeoutDuration);
+ }
+
+ timeSliderContainer
+ .mouseover(function() {
+ timeTooltip.show();
+ timeSliderMouseOver();
+ })
+ .mouseout(timeSliderMouseOut);
+ timeSlider.mousemove(function(_e) {
+ var _x = _e.pageX - timeSlider.offset().left,
+ _t = new IriSP.Model.Time(
+ );
+ timeTooltip.text(_t.toString()).css("left",_x);
+ });
+
+ $(".Ldt-Ctrl").mouseover(timeSliderMouseOver).mouseout(timeSliderMouseOut);
+
+ function timeSliderAnimateToHeight(_height) {
+ timeSliderContainer.stop().animate(
+ calculateSliderCss(_height),
+ 500,
+ function() {
+ IriSP.jQuery(this).css("overflow","visible");
+ });
+ timeSliderHandle.stop().animate(
+ calculateHandleCss(_height),
+ 500,
+ function() {
+ IriSP.jQuery(this).css("overflow","visible");
+ });
+ }
+
+ function calculateSliderCss(_size) {
+ return {
+ height: _size + "px",
+ "margin-top": (timeSliderMinimizedHeight - _size) + "px"
+ };
+ }
+
+ function calculateHandleCss(_size) {
+ return {
+ height: (2 + _size) + "px",
+ width: (2 + _size) + "px",
+ "margin-left": -Math.ceil(2 + _size / 2) + "px"
+ }
+ }
+
+ /* Controller Widget */
+
+ var volBlock = $(".Ldt-Ctrl-Volume-Control");
+
+ $('.Ldt-Ctrl-Sound')
+ .click(function() {
+ if (currentMedia) {
+ currentMedia.setMuted(!currentMedia.getMuted());
+ }
+ })
+ .mouseover(function() {
+ volBlock.show();
+ })
+ .mouseout(function() {
+ volBlock.hide();
+ });
+ volBlock.mouseover(function() {
+ volBlock.show();
+ }).mouseout(function() {
+ volBlock.hide();
+ });
+
+ var volBar = $(".Ldt-Ctrl-Volume-Bar");
+
+ function ctrlVolumeUpdater() {
+ if (currentMedia) {
+ var _muted = currentMedia.getMuted(),
+ _vol = currentMedia.getVolume();
+ if (_vol === false) {
+ _vol = .5;
+ }
+ var _soundCtl = $(".Ldt-Ctrl-Sound");
+ _soundCtl.removeClass("Ldt-Ctrl-Sound-Mute Ldt-Ctrl-Sound-Half Ldt-Ctrl-Sound-Full");
+ if (_muted) {
+ _soundCtl.attr("title", "Activer le son")
+ .addClass("Ldt-Ctrl-Sound-Mute");
+ } else {
+ _soundCtl.attr("title", "Couper le son")
+ .addClass(_vol < .5 ? "Ldt-Ctrl-Sound-Half" : "Ldt-Ctrl-Sound-Full" )
+ }
+ volBar.slider("value", _muted ? 0 : 100 * _vol);
+ volBar.attr("title",'Volume : ' + Math.floor(100 * _vol) + '%');
+ }
+ }
+
+ volBar.slider({
+ slide: function(event, ui) {
+ if (currentMedia) {
+ currentMedia.setVolume(ui.value / 100);
+ }
+ }
+ });
+
+ $(".Ldt-Ctrl-Play").click(function() {
+ if (currentMedia) {
+ if (currentMedia.getPaused()) {
+ currentMedia.play();
+ } else {
+ currentMedia.pause();
+ }
+ }
+ });
+
+ $(".Ldt-Ctrl-SetIn").click(function() {
+ if (currentMedia && currentSegment) {
+ currentSegment.setBegin(currentMedia.getCurrentTime());
+ }
+ });
+ $(".Ldt-Ctrl-SetOut").click(function() {
+ if (currentMedia && currentSegment) {
+ currentSegment.setEnd(currentMedia.getCurrentTime());
+ }
+ });
+
+ /* UI Events */
+
+ function onCurrentMediaPlay() {
+ $(".Ldt-Ctrl-Play")
+ .attr("title", "Pause")
+ .removeClass("Ldt-Ctrl-Play-PlayState")
+ .addClass("Ldt-Ctrl-Play-PauseState")
+ }
+
+ function onCurrentMediaPause() {
+ $(".Ldt-Ctrl-Play")
+ .attr("title", "Lecture")
+ .removeClass("Ldt-Ctrl-Play-PauseState")
+ .addClass("Ldt-Ctrl-Play-PlayState")
+ }
+
+ function onCurrentMediaTimeupdate(_time) {
+ $(".Ldt-Ctrl-Time-Elapsed").text(_time.toString());
+ timeSlider.slider("value",slidersRange * _time / currentMedia.duration);
+ }
+
+ /* Mashup Player */
+
+ mashup.currentMedia = null;
+
+ var mashupCurrentAnnotation = null,
+ mashupSegmentBegin,
+ mashupSegmentEnd,
+ mashupTimecode = 0,
+ mashupSeeking = false,
+ seekdiv = $(".video-wait"),
+ mashupTimedelta;
+
+ function showSeek() {
+ if (mashupSeeking) {
+ seekdiv.show();
+ }
+ }
+
+ function changeCurrentAnnotation() {
+ if (mashupTimecode >= mashup.duration) {
+ if (!mashup.paused) {
+ mashup.paused = true;
+ mashup.trigger("pause");
+ }
+ mashupTimecode = 0;
+ }
+ var _annotation = mashup.getAnnotationAtTime( mashupTimecode );
+ if (typeof _annotation === "undefined") {
+ if (mashup.currentMedia) {
+ mashup.currentMedia.pause();
+ if (!mashup.paused) {
+ mashup.paused = true;
+ mashup.trigger("pause");
+ }
+ }
+ return;
+ }
+ mashupCurrentAnnotation = _annotation;
+ mashupSegmentBegin = mashupCurrentAnnotation.annotation.begin.milliseconds;
+ mashupSegmentEnd = mashupCurrentAnnotation.annotation.end.milliseconds;
+ mashupTimedelta = mashupSegmentBegin - mashupCurrentAnnotation.begin.milliseconds;
+ mashup.currentMedia = mashupCurrentAnnotation.getMedia();
+
+ project.getMedias().forEach(function(_media) {
+ if (_media !== mashup.currentMedia) {
+ _media.hide();
+ _media.pause();
+ } else {
+ _media.show();
+ }
+ });
+
+ mashup.currentMedia.setCurrentTime( mashupTimecode + mashupTimedelta);
+ mashup.currentMedia.seeking = true;
+
+ if (!mashup.paused) {
+ mashup.currentMedia.play();
+ mashupSeeking = true;
+ setTimeout(showSeek,200);
+ }
+ mashup.trigger("timeupdate", new IriSP.Model.Time(mashupTimecode));
+
+ }
+
+ function addMedia(media) {
+ if (media.has_player) {
+ return;
+ }
+ media.has_player = true;
+ var videoid = "video_" + media.id,
+ videoEl = $('<video>'),
+ width = $(".video").width(),
+ height = $(".video").height(),
+ mp4_file = media.video.replace(/\.webm$/i,'.mp4'),
+ webm_file = media.video.replace(/\.mp4$/i,'.webm'),
+ mp4_src = $('<source>'),
+ webm_src = $('<source>');
+ mp4_src.attr({
+ src: mp4_file,
+ type: "video/mp4"
+ });
+ webm_src.attr({
+ src: webm_file,
+ type: "video/webm"
+ });
+ videoEl.attr({
+ id : videoid,
+ width : width,
+ height : height
+ }).css({
+ position : "absolute",
+ left: 0,
+ top: 0,
+ width : width,
+ height : height
+ });
+ videoEl.append(mp4_src).append(webm_src);
+ $(".video").append(videoEl);
+
+ media.show = function() {
+ videoEl.show();
+ }
+ media.hide = function() {
+ videoEl.hide();
+ }
+
+ var popcorn = Popcorn("#" + videoid);
+
+ // Binding functions to Popcorn
+
+ media.on("setcurrenttime", function(_milliseconds) {
+ if (media.loaded) {
+ popcorn.currentTime(_milliseconds / 1000);
+ }
+ });
+
+ media.on("setvolume", function(_vol) {
+ media.volume = _vol;
+ if (media.loaded) {
+ popcorn.volume(_vol);
+ }
+ });
+
+ media.on("setmuted", function(_muted) {
+ media.muted = _muted;
+ if (media.loaded) {
+ popcorn.muted(_muted);
+ }
+ });
+
+ media.on("setplay", function() {
+ if (media.loaded) {
+ popcorn.play();
+ }
+ });
+
+ media.on("setpause", function() {
+ if (media.loaded) {
+ popcorn.pause();
+ }
+ });
+
+ // Binding Popcorn events to media
+
+ function getVolume() {
+ media.muted = popcorn.muted();
+ media.volume = popcorn.volume();
+ }
+
+ popcorn.on("loadedmetadata", function() {
+ getVolume();
+ media.loaded = true;
+ media.trigger("loadedmetadata");
+ media.trigger("volumechange");
+ })
+
+ popcorn.on("timeupdate", function() {
+ media.trigger("timeupdate", new IriSP.Model.Time(1000*popcorn.currentTime()));
+ });
+
+ popcorn.on("volumechange", function() {
+ getVolume();
+ media.trigger("volumechange");
+ })
+
+ popcorn.on("play", function() {
+ media.trigger("play");
+ });
+
+ popcorn.on("pause", function() {
+ media.trigger("pause");
+ });
+
+ popcorn.on("seeked", function() {
+ media.trigger("seeked");
+ });
+
+ // Binding UI Events and Mashup Playing to Media
+
+ media.on("loadedmetadata", function() {
+ if (media === currentMedia) {
+ seekdiv.hide();
+ }
+ mashup.checkLoaded();
+ });
+
+ media.on("play", function() {
+ if (media === currentMedia) {
+ onCurrentMediaPlay();
+ }
+ if (mashup === currentMedia && media === mashup.currentMedia) {
+ mashup.trigger("play");
+ }
+ });
+
+ media.on("pause", function() {
+ if (media === currentMedia) {
+ onCurrentMediaPause();
+ }
+ if (mashup === currentMedia && media === mashup.currentMedia) {
+ mashup.trigger("pause");
+ }
+ });
+
+ media.on("timeupdate", function(_time) {
+ if (media === currentMedia) {
+ onCurrentMediaTimeupdate(_time);
+ }
+ if (mashup === currentMedia && !mashup.paused && media === mashup.currentMedia && !media.seeking) {
+ if ( _time < mashupSegmentEnd ) {
+ if ( _time >= mashupSegmentBegin ) {
+ mashupTimecode = _time - mashupTimedelta;
+ } else {
+ mashupTimecode = mashupSegmentBegin - mashupTimedelta;
+ media.setCurrentTime(mashupSegmentBegin);
+ }
+ } else {
+ mashupTimecode = mashupSegmentEnd - mashupTimedelta;
+ media.pause();
+ changeCurrentAnnotation();
+ }
+ mashup.trigger("timeupdate", new IriSP.Model.Time(mashupTimecode));
+ }
+ });
+
+ media.on("seeked", function() {
+ media.seeking = false;
+ if (mashup === currentMedia && media === mashup.currentMedia && mashupSeeking) {
+ mashupSeeking = false;
+ seekdiv.hide();
+ }
+ });
+
+ media.on("volumechange", function() {
+ if (media === currentMedia) {
+ ctrlVolumeUpdater();
+ }
+ mashup.muted = media.muted;
+ mashup.volume = media.volume;
+ mashup.trigger("volumechange");
+ });
+
+ project.on("set-current", function(_m) {
+ if (_m !== media) {
+ media.hide();
+ }
+ });
+
+ }
+
+ // Mashup Events
+
+ mashup.on("setcurrenttime", function(_milliseconds) {
+ mashupTimecode = _milliseconds;
+ changeCurrentAnnotation();
+ });
+
+ mashup.on("setvolume", function(_vol) {
+ mashup.getMedias().forEach(function(_media) {
+ _media.setVolume(_vol);
+ });
+ mashup.volume = _vol;
+ });
+
+ mashup.on("setmuted", function(_muted) {
+ mashup.getMedias().forEach(function(_media) {
+ _media.setMuted(_muted);
+ });
+ mashup.muted = _muted;
+ });
+
+ mashup.on("setplay", function() {
+ mashup.paused = false;
+ changeCurrentAnnotation();
+ });
+
+ mashup.on("setpause", function() {
+ mashup.paused = true;
+ if (mashup.currentMedia) {
+ mashup.currentMedia.pause();
+ }
+ });
+
+ mashup.on("loadedmetadata", function() {
+ if (mashup === currentMedia) {
+ changeCurrentAnnotation();
+ }
+ });
+
+ /* Mashup Events to UI */
+
+ mashup.on("play", function() {
+ if (mashup === currentMedia) {
+ onCurrentMediaPlay();
+ }
+ });
+
+ mashup.on("pause", function() {
+ if (mashup === currentMedia) {
+ onCurrentMediaPause();
+ }
+ });
+
+ mashup.on("timeupdate", function(_time) {
+ if (mashup === currentMedia) {
+ $(".frise-position").css("left",(100*_time/mashup.duration)+"%");
+ onCurrentMediaTimeupdate(_time);
+ }
+ });
+
+ mashup.on("add", function() {
+ mashup.getMedias().forEach(addMedia);
+ })
+
+ mashup.on("change",updateMashupUI);
+
+ mashup.on("enter-annotation", function(segment) {
+ var a = segment.annotation;
+ $(".annotation-title").text(a.title);
+ $(".annotation-begin").text(a.begin.toString());
+ $(".annotation-end").text(a.end.toString());
+ $(".annotation-tags").text(a.keywords.join(", "));
+ $(".annotation-media-title").text(a.getMedia().title);
+ $(".annotation-description").text(a.description);
+ var p = (segment.begin + segment.end) / (2 * mashup.duration);
+ $(".mashup-description .pointer").css("left", (100 * p) + "%");
+ project.trigger("mouseout-annotation");
+ });
+
+ project.on("mouseover-annotation", function(annotation) {
+ $(".annotation").removeClass("active");
+ if (!annotation) {
+ return;
+ }
+ $(".annotation[data-segment-id='" + annotation.id + "']").addClass("active");
+ });
+
+ project.on("mouseout-annotation", function() {
+ if (currentMedia === mashup && mashupCurrentAnnotation) {
+ $(".annotation").removeClass("active");
+ $(".item-video.annotation[data-segment-id='" + mashupCurrentAnnotation.annotation.id + "']").addClass("active");
+ }
+ });
+
+ project.on("click-annotation", function(annotation) {
+ if (!annotation) {
+ return;
+ }
+ var segment = mashup.getAnnotation(annotation);
+ project.trigger("set-current", mashup);
+ if (segment) {
+ mashup.setCurrentTime(segment.begin);
+ }
+ })
+
+ project.on("set-current", function(media) {
+ currentMedia = media;
+ if (currentMedia.elementType === "media") {
+ if (!media.has_player) {
+ addMedia(media);
+ }
+ media.show();
+ if (!currentMedia.loaded) {
+ seekdiv.show();
+ }
+ }
+ if (currentMedia.elementType === "mashup") {
+ mashup.checkLoaded();
+ }
+ $(".Ldt-Ctrl-Time-Total").text(currentMedia.duration.toString());
+ currentMedia.trigger("timeupdate",currentMedia.getCurrentTime());
+ currentMedia.trigger("pause");
+ });
+
+ $(".frise")
+ .on("mouseover", ".frise-segment", function() {
+ project.trigger("mouseover-annotation", project.getElement($(this).attr("data-segment-id")));
+ })
+ .on("mouseout", ".frise-segment", function() {
+ project.trigger("mouseout-annotation");
+ })
+ .on("click", ".frise-segment", function() {
+ project.trigger("click-annotation", project.getElement($(this).attr("data-segment-id")));
+ });
+
+ mashup.trigger("add");
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/integration/js/mashupplayer.js Thu Nov 08 18:24:47 2012 +0100
@@ -0,0 +1,21 @@
+IriSP.player = function(options) {
+
+ var directory = new IriSP.Model.Directory(),
+ project = directory.remoteSource({
+ url: options.url,
+ serializer: IriSP.serializers.ldt
+ }),
+ mashup;
+
+ project.onLoad(function() {
+ mashup = project.getMashups()[0];
+ IriSP.mashupcore(project, mashup);
+ project.trigger("set-current",mashup);
+
+ $(".info-title a").text(mashup.title);
+ $(".info-duration td").text(mashup.duration.toString());
+ $(".info-author a").text(mashup.creator);
+ $(".info-description td").text(mashup.description);
+
+ });
+}
--- a/integration/js/model.js Tue Nov 06 18:49:13 2012 +0100
+++ b/integration/js/model.js Thu Nov 08 18:24:47 2012 +0100
@@ -2,32 +2,28 @@
/* model.js is where data is stored in a standard form, whatever the serializer */
IriSP.Model = (function (ns) {
+
+ function pad(n, x, b) {
+ b = b || 10;
+ var s = (x).toString(b);
+ while (s.length < n) {
+ s = "0" + s;
+ }
+ return s;
+ }
+
+ function rand16(n) {
+ return pad(n, Math.floor(Math.random()*Math.pow(16,n)), 16);
+ }
+
+ var uidbase = rand16(8) + "-" + rand16(4) + "-", uidincrement = Math.floor(Math.random()*0x10000);
var Model = {
_SOURCE_STATUS_EMPTY : 0,
_SOURCE_STATUS_WAITING : 1,
_SOURCE_STATUS_READY : 2,
- _ID_AUTO_INCREMENT : 0,
- _ID_BASE : (function(_d) {
- function pad(n){return n<10 ? '0'+n : n}
- function fillrand(n) {
- var _res = ''
- for (var i=0; i<n; i++) {
- _res += Math.floor(16*Math.random()).toString(16);
- }
- return _res;
- }
- return _d.getUTCFullYear() + '-'
- + pad(_d.getUTCMonth()+1) + '-'
- + pad(_d.getUTCDate()) + '-'
- + fillrand(16);
- })(new Date()),
getUID : function() {
- var _n = (++this._ID_AUTO_INCREMENT).toString();
- while (_n.length < 4) {
- _n = '0' + _n
- }
- return "autoid-" + this._ID_BASE + '-' + _n;
+ return uidbase + pad(4, (++uidincrement % 0x10000), 16) + "-" + rand16(4) + "-" + rand16(6) + rand16(6);
},
regexpFromTextOrArray : function(_textOrArray, _testOnly, _iexact) {
var _testOnly = _testOnly || false,
@@ -75,13 +71,12 @@
return _res;
},
dateToIso : function(d) {
- function pad(n){return n<10 ? '0'+n : n}
return d.getUTCFullYear()+'-'
- + pad(d.getUTCMonth()+1)+'-'
- + pad(d.getUTCDate())+'T'
- + pad(d.getUTCHours())+':'
- + pad(d.getUTCMinutes())+':'
- + pad(d.getUTCSeconds())+'Z'
+ + pad(2, d.getUTCMonth()+1)+'-'
+ + pad(2, d.getUTCDate())+'T'
+ + pad(2, d.getUTCHours())+':'
+ + pad(2, d.getUTCMinutes())+':'
+ + pad(2, d.getUTCSeconds())+'Z'
}
}
@@ -347,19 +342,12 @@
}
Model.Time.prototype.toString = function(showCs) {
- function pad(_n) {
- var _res = _n.toString();
- while (_res.length < 2) {
- _res = '0' + _res;
- }
- return _res;
- }
var _hms = this.getHMS(),
_res = '';
if (_hms.hours) {
_res += _hms.hours + ':'
}
- _res += pad(_hms.minutes) + ':' + pad(_hms.seconds);
+ _res += pad(2, _hms.minutes) + ':' + pad(2, _hms.seconds);
if (showCs) {
_res += "." + Math.round(_hms.milliseconds / 100)
}
@@ -409,6 +397,9 @@
Model.Element = function(_id, _source) {
this.elementType = 'element';
+ this.title = "";
+ this.description = "";
+ this.__events = {}
if (typeof _source === "undefined") {
return;
}
@@ -417,9 +408,6 @@
}
this.source = _source;
this.id = _id;
- this.title = "";
- this.description = "";
- this.__events = {}
this.source.directory.addElement(this);
}
@@ -489,6 +477,20 @@
});
this.on("timeupdate", function(_time) {
_this.currentTime = _time;
+ _this.getAnnotations().filter(function(_a) {
+ return (_a.end <= _time || _a.begin > _time) && _a.playing
+ }).forEach(function(_a) {
+ _a.playing = false;
+ _a.trigger("leave");
+ _this.trigger("leave-annotation",_a);
+ });
+ _this.getAnnotations().filter(function(_a) {
+ return _a.begin <= _time && _a.end > _time && !_a.playing
+ }).forEach(function(_a) {
+ _a.playing = true;
+ _a.trigger("enter");
+ _this.trigger("enter-annotation",_a);
+ });
});
}
@@ -541,22 +543,7 @@
this.elementType = 'media';
this.duration = new Model.Time();
this.video = '';
-
var _this = this;
- this.on("timeupdate", function(_time) {
- _this.getAnnotations().filter(function(_a) {
- return (_a.end <= _time || _a.begin > _time) && _a.playing
- }).forEach(function(_a) {
- _a.playing = false;
- _a.trigger("leave");
- });
- _this.getAnnotations().filter(function(_a) {
- return _a.begin <= _time && _a.end > _time && !_a.playing
- }).forEach(function(_a) {
- _a.playing = true;
- _a.trigger("enter");
- });
- });
}
Model.Media.prototype = new Model.Playable();
@@ -737,30 +724,7 @@
this.duration = new Model.Time();
this.segments = new Model.List(_source.directory);
this.loaded = false;
- var _currentMedia = null;
var _this = this;
- this.on("timeupdate", function(_time) {
- _this.getSegments().filter(function(_a) {
- return (_a.end <= _time || _a.begin > _time) && _a.playing
- }).forEach(function(_a) {
- _a.playing = false;
- _a.trigger("leave");
- });
- _this.getSegments().filter(function(_a) {
- return _a.begin <= _time && _a.end > _time && !_a.playing
- }).forEach(function(_a) {
- _a.playing = true;
- _a.trigger("enter");
- var _m = _a.getMedia();
- if (_m !== _currentMedia) {
- if (_currentMedia) {
- _currentMedia.trigger("leave");
- }
- _m.trigger("enter");
- _currentMedia = _m;
- }
- });
- });
this._updateTimes = function() {
_this.updateTimes();
_this.trigger("change");
@@ -880,7 +844,7 @@
});
}
-Model.Mashup.prototype.getSegments = function() {
+Model.Mashup.prototype.getAnnotations = function() {
return this.segments;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/integration/lib/jquery.tagit.css Thu Nov 08 18:24:47 2012 +0100
@@ -0,0 +1,54 @@
+ul.tagit {
+ padding: 1px 5px;
+ overflow: auto;
+ margin-left: inherit; /* usually we don't want the regular ul margins. */
+ margin-right: inherit;
+}
+ul.tagit li {
+ display: block;
+ float: left;
+ margin: 2px 5px 2px 0;
+}
+ul.tagit li.tagit-choice {
+ padding: .2em 18px .2em .5em;
+ position: relative;
+ line-height: inherit;
+}
+ul.tagit li.tagit-new {
+ padding: .25em 4px .25em 0;
+}
+
+ul.tagit li.tagit-choice a.tagit-label {
+ cursor: pointer;
+ text-decoration: none;
+}
+ul.tagit li.tagit-choice .tagit-close {
+ cursor: pointer;
+ position: absolute;
+ right: .1em;
+ top: 50%;
+ margin-top: -8px;
+}
+
+/* used for some custom themes that don't need image icons */
+ul.tagit li.tagit-choice .tagit-close .text-icon {
+ display: none;
+}
+
+ul.tagit li.tagit-choice input {
+ display: block;
+ float: left;
+ margin: 2px 5px 2px 0;
+}
+ul.tagit input[type="text"] {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+
+ border: none;
+ margin: 0;
+ padding: 0;
+ width: inherit;
+ background-color: inherit;
+ outline: none;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/integration/lib/tag-it.js Thu Nov 08 18:24:47 2012 +0100
@@ -0,0 +1,392 @@
+/*
+* jQuery UI Tag-it!
+*
+* @version v2.0 (06/2011)
+*
+* Copyright 2011, Levy Carneiro Jr.
+* Released under the MIT license.
+* http://aehlke.github.com/tag-it/LICENSE
+*
+* Homepage:
+* http://aehlke.github.com/tag-it/
+*
+* Authors:
+* Levy Carneiro Jr.
+* Martin Rehfeld
+* Tobias Schmidt
+* Skylar Challand
+* Alex Ehlke
+*
+* Maintainer:
+* Alex Ehlke - Twitter: @aehlke
+*
+* Dependencies:
+* jQuery v1.4+
+* jQuery UI v1.8+
+*/
+(function($) {
+
+ $.widget('ui.tagit', {
+ options: {
+ itemName : 'item',
+ fieldName : 'tags',
+ availableTags : [],
+ tagSource : null,
+ removeConfirmation: false,
+ caseSensitive : true,
+ placeholderText : null,
+
+ // When enabled, quotes are not neccesary
+ // for inputting multi-word tags.
+ allowSpaces: false,
+
+ // Whether to animate tag removals or not.
+ animate: true,
+
+ // The below options are for using a single field instead of several
+ // for our form values.
+ //
+ // When enabled, will use a single hidden field for the form,
+ // rather than one per tag. It will delimit tags in the field
+ // with singleFieldDelimiter.
+ //
+ // The easiest way to use singleField is to just instantiate tag-it
+ // on an INPUT element, in which case singleField is automatically
+ // set to true, and singleFieldNode is set to that element. This
+ // way, you don't need to fiddle with these options.
+ singleField: false,
+
+ singleFieldDelimiter: ',',
+
+ // Set this to an input DOM node to use an existing form field.
+ // Any text in it will be erased on init. But it will be
+ // populated with the text of tags as they are created,
+ // delimited by singleFieldDelimiter.
+ //
+ // If this is not set, we create an input node for it,
+ // with the name given in settings.fieldName,
+ // ignoring settings.itemName.
+ singleFieldNode: null,
+
+ // Optionally set a tabindex attribute on the input that gets
+ // created for tag-it.
+ tabIndex: null,
+
+
+ // Event callbacks.
+ onTagAdded : null,
+ onTagRemoved: null,
+ onTagClicked: null
+ },
+
+
+ _create: function() {
+ // for handling static scoping inside callbacks
+ var that = this;
+
+ // There are 2 kinds of DOM nodes this widget can be instantiated on:
+ // 1. UL, OL, or some element containing either of these.
+ // 2. INPUT, in which case 'singleField' is overridden to true,
+ // a UL is created and the INPUT is hidden.
+ if (this.element.is('input')) {
+ this.tagList = $('<ul></ul>').insertAfter(this.element);
+ this.options.singleField = true;
+ this.options.singleFieldNode = this.element;
+ this.element.css('display', 'none');
+ } else {
+ this.tagList = this.element.find('ul, ol').andSelf().last();
+ }
+
+ this._tagInput = $('<input type="text" />').addClass('ui-widget-content');
+ if (this.options.tabIndex) {
+ this._tagInput.attr('tabindex', this.options.tabIndex);
+ }
+ if (this.options.placeholderText) {
+ this._tagInput.attr('placeholder', this.options.placeholderText);
+ }
+
+ this.options.tagSource = this.options.tagSource || function(search, showChoices) {
+ var filter = search.term.toLowerCase();
+ var choices = $.grep(this.options.availableTags, function(element) {
+ // Only match autocomplete options that begin with the search term.
+ // (Case insensitive.)
+ return (element.toLowerCase().indexOf(filter) === 0);
+ });
+ showChoices(this._subtractArray(choices, this.assignedTags()));
+ };
+
+ // Bind tagSource callback functions to this context.
+ if ($.isFunction(this.options.tagSource)) {
+ this.options.tagSource = $.proxy(this.options.tagSource, this);
+ }
+
+ this.tagList
+ .addClass('tagit')
+ .addClass('ui-widget ui-widget-content ui-corner-all')
+ // Create the input field.
+ .append($('<li class="tagit-new"></li>').append(this._tagInput))
+ .click(function(e) {
+ var target = $(e.target);
+ if (target.hasClass('tagit-label')) {
+ that._trigger('onTagClicked', e, target.closest('.tagit-choice'));
+ } else {
+ // Sets the focus() to the input field, if the user
+ // clicks anywhere inside the UL. This is needed
+ // because the input field needs to be of a small size.
+ that._tagInput.focus();
+ }
+ });
+
+ // Add existing tags from the list, if any.
+ this.tagList.children('li').each(function() {
+ if (!$(this).hasClass('tagit-new')) {
+ that.createTag($(this).html(), $(this).attr('class'));
+ $(this).remove();
+ }
+ });
+
+ // Single field support.
+ if (this.options.singleField) {
+ if (this.options.singleFieldNode) {
+ // Add existing tags from the input field.
+ var node = $(this.options.singleFieldNode);
+ var tags = node.val().split(this.options.singleFieldDelimiter);
+ node.val('');
+ $.each(tags, function(index, tag) {
+ that.createTag(tag);
+ });
+ } else {
+ // Create our single field input after our list.
+ this.options.singleFieldNode = this.tagList.after('<input type="hidden" style="display:none;" value="" name="' + this.options.fieldName + '" />');
+ }
+ }
+
+ // Events.
+ this._tagInput
+ .keydown(function(event) {
+ // Backspace is not detected within a keypress, so it must use keydown.
+ if (event.which == $.ui.keyCode.BACKSPACE && that._tagInput.val() === '') {
+ var tag = that._lastTag();
+ if (!that.options.removeConfirmation || tag.hasClass('remove')) {
+ // When backspace is pressed, the last tag is deleted.
+ that.removeTag(tag);
+ } else if (that.options.removeConfirmation) {
+ tag.addClass('remove ui-state-highlight');
+ }
+ } else if (that.options.removeConfirmation) {
+ that._lastTag().removeClass('remove ui-state-highlight');
+ }
+
+ // Comma/Space/Enter are all valid delimiters for new tags,
+ // except when there is an open quote or if setting allowSpaces = true.
+ // Tab will also create a tag, unless the tag input is empty, in which case it isn't caught.
+ if (
+ event.which == $.ui.keyCode.COMMA ||
+ event.which == $.ui.keyCode.ENTER ||
+ (
+ event.which == $.ui.keyCode.TAB &&
+ that._tagInput.val() !== ''
+ ) ||
+ (
+ event.which == $.ui.keyCode.SPACE &&
+ that.options.allowSpaces !== true &&
+ (
+ $.trim(that._tagInput.val()).replace( /^s*/, '' ).charAt(0) != '"' ||
+ (
+ $.trim(that._tagInput.val()).charAt(0) == '"' &&
+ $.trim(that._tagInput.val()).charAt($.trim(that._tagInput.val()).length - 1) == '"' &&
+ $.trim(that._tagInput.val()).length - 1 !== 0
+ )
+ )
+ )
+ ) {
+ event.preventDefault();
+ that.createTag(that._cleanedInput());
+
+ // The autocomplete doesn't close automatically when TAB is pressed.
+ // So let's ensure that it closes.
+ that._tagInput.autocomplete('close');
+ }
+ }).blur(function(e){
+ // Create a tag when the element loses focus (unless it's empty).
+ that.createTag(that._cleanedInput());
+ });
+
+
+ // Autocomplete.
+ if (this.options.availableTags || this.options.tagSource) {
+ this._tagInput.autocomplete({
+ source: this.options.tagSource,
+ select: function(event, ui) {
+ // Delete the last tag if we autocomplete something despite the input being empty
+ // This happens because the input's blur event causes the tag to be created when
+ // the user clicks an autocomplete item.
+ // The only artifact of this is that while the user holds down the mouse button
+ // on the selected autocomplete item, a tag is shown with the pre-autocompleted text,
+ // and is changed to the autocompleted text upon mouseup.
+ if (that._tagInput.val() === '') {
+ that.removeTag(that._lastTag(), false);
+ }
+ that.createTag(ui.item.value);
+ // Preventing the tag input to be updated with the chosen value.
+ return false;
+ }
+ });
+ }
+ },
+
+ _cleanedInput: function() {
+ // Returns the contents of the tag input, cleaned and ready to be passed to createTag
+ return $.trim(this._tagInput.val().replace(/^"(.*)"$/, '$1'));
+ },
+
+ _lastTag: function() {
+ return this.tagList.children('.tagit-choice:last');
+ },
+
+ assignedTags: function() {
+ // Returns an array of tag string values
+ var that = this;
+ var tags = [];
+ if (this.options.singleField) {
+ tags = $(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter);
+ if (tags[0] === '') {
+ tags = [];
+ }
+ } else {
+ this.tagList.children('.tagit-choice').each(function() {
+ tags.push(that.tagLabel(this));
+ });
+ }
+ return tags;
+ },
+
+ _updateSingleTagsField: function(tags) {
+ // Takes a list of tag string values, updates this.options.singleFieldNode.val to the tags delimited by this.options.singleFieldDelimiter
+ $(this.options.singleFieldNode).val(tags.join(this.options.singleFieldDelimiter));
+ },
+
+ _subtractArray: function(a1, a2) {
+ var result = [];
+ for (var i = 0; i < a1.length; i++) {
+ if ($.inArray(a1[i], a2) == -1) {
+ result.push(a1[i]);
+ }
+ }
+ return result;
+ },
+
+ tagLabel: function(tag) {
+ // Returns the tag's string label.
+ if (this.options.singleField) {
+ return $(tag).children('.tagit-label').text();
+ } else {
+ return $(tag).children('input').val();
+ }
+ },
+
+ _isNew: function(value) {
+ var that = this;
+ var isNew = true;
+ this.tagList.children('.tagit-choice').each(function(i) {
+ if (that._formatStr(value) == that._formatStr(that.tagLabel(this))) {
+ isNew = false;
+ return false;
+ }
+ });
+ return isNew;
+ },
+
+ _formatStr: function(str) {
+ if (this.options.caseSensitive) {
+ return str;
+ }
+ return $.trim(str.toLowerCase());
+ },
+
+ createTag: function(value, additionalClass) {
+ var that = this;
+ // Automatically trims the value of leading and trailing whitespace.
+ value = $.trim(value);
+
+ if (!this._isNew(value) || value === '') {
+ return false;
+ }
+
+ var label = $(this.options.onTagClicked ? '<a class="tagit-label"></a>' : '<span class="tagit-label"></span>').text(value);
+
+ // Create tag.
+ var tag = $('<li></li>')
+ .addClass('tagit-choice ui-widget-content ui-state-default ui-corner-all')
+ .addClass(additionalClass)
+ .append(label);
+
+ // Button for removing the tag.
+ var removeTagIcon = $('<span></span>')
+ .addClass('ui-icon ui-icon-close');
+ var removeTag = $('<a><span class="text-icon">\xd7</span></a>') // \xd7 is an X
+ .addClass('tagit-close')
+ .append(removeTagIcon)
+ .click(function(e) {
+ // Removes a tag when the little 'x' is clicked.
+ that.removeTag(tag);
+ });
+ tag.append(removeTag);
+
+ // Unless options.singleField is set, each tag has a hidden input field inline.
+ if (this.options.singleField) {
+ var tags = this.assignedTags();
+ tags.push(value);
+ this._updateSingleTagsField(tags);
+ } else {
+ var escapedValue = label.html();
+ tag.append('<input type="hidden" style="display:none;" value="' + escapedValue + '" name="' + this.options.itemName + '[' + this.options.fieldName + '][]" />');
+ }
+
+ this._trigger('onTagAdded', null, tag);
+
+ // Cleaning the input.
+ this._tagInput.val('');
+
+ // insert tag
+ this._tagInput.parent().before(tag);
+ },
+
+ removeTag: function(tag, animate) {
+ animate = animate || this.options.animate;
+
+ tag = $(tag);
+
+ this._trigger('onTagRemoved', null, tag);
+
+ if (this.options.singleField) {
+ var tags = this.assignedTags();
+ var removedTagLabel = this.tagLabel(tag);
+ tags = $.grep(tags, function(el){
+ return el != removedTagLabel;
+ });
+ this._updateSingleTagsField(tags);
+ }
+ // Animate the removal.
+ if (animate) {
+ tag.fadeOut('fast').hide('blind', {direction: 'horizontal'}, 'fast', function(){
+ tag.remove();
+ }).dequeue();
+ } else {
+ tag.remove();
+ }
+ },
+
+ removeAll: function() {
+ // Removes all tags.
+ var that = this;
+ this.tagList.children('.tagit-choice').each(function(index, tag) {
+ that.removeTag(tag, false);
+ });
+ }
+
+ });
+
+})(jQuery);
+
+