Commit 0217ef80 by Sarina Canelake

Merge pull request #4351 from lduarte1991/lduarte-harvardx-pr8

Annotation Tool: Bug Fix Filtered Personal Annotations on Page Load
parents 20d3eaa4 6a281dd8
......@@ -28,7 +28,7 @@ window.CatchSources = ("CatchSources" in window) ? CatchSources : {};
CatchSources.HTMLTEMPLATES = function(root){
var root = root || '';
return {
//Main
// Main
annotationList:
'<div class="annotationListButtons">'+
'{{{ PublicPrivate }}}'+
......@@ -76,7 +76,7 @@ annotationList:
'<div class="moreButtonCatch">'+gettext('More')+'</div>'+
'</div>',
//Main->PublicPrivateInstructor
// Main->PublicPrivateInstructor
annotationPublicPrivateInstructor:
'<div class="selectors"><div class="PublicPrivate myNotes active">'+gettext('My Notes')+'<span class="action">myNotes</span></div>'+
'<div class="PublicPrivate instructor"> '+gettext('Instructor')+'<span class="action">instructor</span></div>'+
......@@ -87,7 +87,7 @@ annotationPublicPrivateInstructor:
'<option>'+gettext('Annotation Text')+'</option>'+
'</select><input type="text" name="search"/><div class="search-icon" alt="Run search."></div><div class="clear-search-icon" alt="Clear search.">'+gettext('Clear')+'</div></div>',
//Main->PublicPrivate
// Main->PublicPrivate
annotationPublicPrivate:
'<div class="selectors"><div class="PublicPrivate myNotes active">'+gettext('My Notes')+'<span class="action">myNotes</span></div>'+
'<div class="PublicPrivate public"> '+gettext('Public')+'<span class="action">public</span></div></div>'+
......@@ -97,7 +97,7 @@ annotationPublicPrivate:
'<option>'+gettext('Annotation Text')+'</option>'+
'</select><input type="text" name="search"/><div class="search-icon" alt="Run search."></div><div class="clear-search-icon" alt="Clear search.">'+gettext('Clear')+'</div></div>',
//Main->MediaSelector
// Main->MediaSelector
annotationMediaSelector:
'<ul class="ui-tabs-nav">'+
'<li class="ui-state-default" media="text">'+
......@@ -111,16 +111,15 @@ annotationMediaSelector:
'</li>'+
'</ul>',
//Main->ContainerRow
// Main->ContainerRow
annotationItem:
'<div class="annotationItem {{ evenOrOdd }} {{ openOrClosed }}" annotationId="{{ id }}">'+
'{{{ annotationRow }}}'+
'{{{ annotationDetail }}}'+
'</div>',
//Main->ContainerRow->Reply
// Main->ContainerRow->Reply
annotationReply:
//<blockquote style="font-size:90%"><p><em>On Sep 14, 2013 4:35 PM <a href="#">jharvard</a>, wrote from [<a href="#">show map location</a>]:</em></p><p>{{{ an.text }}}</p></blockquote>
'{{#if annotations}}'+
'{{#each annotations}}'+
'<blockquote class="replyItem" annotationId="{{this.id}}" style="font-size:90%">'+
......@@ -150,7 +149,7 @@ annotationReply:
'{{/each}}'+
'{{/if}}',
//Main->ContainerRow->Row
// Main->ContainerRow->Row
annotationRow:
'<div class="annotationRow item">'+
'<div class="expandableIcon field">'+
......@@ -187,7 +186,7 @@ annotationRow:
'</div>'+
'</div>',
//Main->ContainerRow->DetailRow
// Main->ContainerRow->DetailRow
annotationDetail:
'{{#if mediatypeforgrid.text}}'+
'<div class="annotationDetail">'+
......@@ -277,32 +276,32 @@ annotationDetail:
CatchAnnotation = function (element, options) {
//local variables
// local variables
var $ = jQuery,
options = options || {};
//Options
// Options
var defaultOptions = {
media: 'text',
userId: '', //this is an integer and its value is the userId to see user annotations
userId: '', // this is an integer and its value is the userId to see user annotations
externalLink: false,//This is true if you want to open the link in a new URL. However, it is false if you want to open the url in the same page
showMediaSelector: true, //whether show the selector of Media Annotations or not
showPublicPrivate: true, //Whether show Public or Private Annotation Selector
pagination: 50, //Number of Annotations per load in the pagination
flags:false //This checks to see if user is staff and has access to see flags
showMediaSelector: true, // whether show the selector of Media Annotations or not
showPublicPrivate: true, // Whether show Public or Private Annotation Selector
pagination: 50, // Number of Annotations per load in the pagination
flags:false // This checks to see if user is staff and has access to see flags
};
this.options = $.extend( true, defaultOptions, options );
//element
// element
this.element = element;
//clean boolean
// clean boolean
this.clean = false;
//Reset element an create a new element div
// Reset element an create a new element div
element.html('<div id="mainCatch" class="annotationListContainer"></div>');
this.current_tab = this.options.default_tab;
//INIT
// INIT
var self = this;
$( document ).ready(function() {
self.init();
......@@ -316,46 +315,46 @@ CatchAnnotation = function (element, options) {
CatchAnnotation.prototype = {
init: function(){
//Set variables
//Initial Templates
// Set variables
// Initial Templates
this.TEMPLATENAMES = [
"annotationList", //Main
"annotationPublicPrivate", //Main->PublicPrivate
"annotationPublicPrivateInstructor", //Main->PublicPrivateInstructor
"annotationMediaSelector", //Main->MediaSelector
"annotationItem", //Main->ContainerRow
"annotationReply",//Main->ContainerRow->Reply
"annotationRow", //Main->ContainerRow->Row
"annotationDetail",//Main->ContainerRow->DetailRow
"annotationList", // Main
"annotationPublicPrivate", // Main->PublicPrivate
"annotationPublicPrivateInstructor", // Main->PublicPrivateInstructor
"annotationMediaSelector", // Main->MediaSelector
"annotationItem", // Main->ContainerRow
"annotationReply", // Main->ContainerRow->Reply
"annotationRow", // Main->ContainerRow->Row
"annotationDetail", // Main->ContainerRow->DetailRow
];
//annotator
// annotator
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = $.data(wrapper, 'annotator');
this.annotator = annotator;
//Subscribe to annotator
// Subscribe to annotator
this._subscribeAnnotator();
//
// Handlebars Register Library
//
//
Handlebars.registerHelper('deparagraph', function(txt) {
var dpg = txt.replace("<p>", "").replace("</p>", "");
return dpg;
});
//Compile templates
// Compile templates
this.HTMLTEMPLATES = CatchSources.HTMLTEMPLATES(this.options.imageUrlRoot);
this.TEMPLATES = {};
this._compileTemplates();
// the default annotations are the user's personal ones instead of instructor
// the default annotations are the user's personal ones instead of instructor.
// if the default tab is instructor, we must refresh the catch to pull the ones
// under the instructor's email. passing empty strings as arguments will default
// to pulling the annotations for the email within this.options.userId.
// under the instructor's email. Calling changeUserId will update this.options.userId
// and most importantly refresh not only the highlights (from Annotator)
// but also the table below from the annotations database server (called Catch).
if(this.options.default_tab.toLowerCase() == 'instructor'){
this.options.userId = this.options.instructor_email;
this._refresh('','');
this.changeUserId(this.options.instructor_email);
}
},
//
......@@ -365,26 +364,26 @@ CatchAnnotation.prototype = {
return this.TEMPLATES[templateName]() || '';
},
refreshCatch: function(newInstance) {
var mediaType = this.options.media || 'text',
annotationItems = [],
index = 0,
annotations = this.annotator.plugins['Store'].annotations || [],
el = $("#mainCatch.annotationListContainer"),
self = this,
newInstance = newInstance || false;
var mediaType = this.options.media || 'text';
var annotationItems = [];
var index = 0;
var annotations = this.annotator.plugins['Store'].annotations || [];
var el = $("#mainCatch.annotationListContainer");
var self = this;
var newInstance = newInstance || false;
annotations.forEach(function(annotation) {
var isMedia = annotation.media==self.options.media,
isUser = (typeof self.options.userId!='undefined' && self.options.userId!='' && self.options.userId!=null)?
self.options.userId == annotation.user.id:true,
isInList = newInstance?false:self._isInList(annotation);
var isMedia = annotation.media==self.options.media;
var isUser = (typeof self.options.userId!='undefined' && self.options.userId!='' && self.options.userId!=null)?
self.options.userId == annotation.user.id:true;
var isInList = newInstance?false:self._isInList(annotation);
if (isMedia && isUser && !isInList){
var item = jQuery.extend(true, {}, annotation);
self._formatCatch(item);
//Authorized
var permissions = self.annotator.plugins.Permissions,
authorized = permissions.options.userAuthorize('delete', annotation,permissions.user),
updateAuthorized = permissions.options.userAuthorize('update', annotation,permissions.user);
// Authorized
var permissions = self.annotator.plugins.Permissions;
var authorized = permissions.options.userAuthorize('delete', annotation,permissions.user);
var updateAuthorized = permissions.options.userAuthorize('update', annotation,permissions.user);
item.authToDeleteButton = authorized;
item.authToEditButton = updateAuthorized;
......@@ -423,14 +422,14 @@ CatchAnnotation.prototype = {
});
}
//Set SelButtons to media
var SelButtons = el.find('.annotationList li').removeClass('active'); //reset
// Set SelButtons to media
var SelButtons = el.find('.annotationList li').removeClass('active'); // reset
for (var index=0;index<SelButtons.length;index++) {
var span = $(SelButtons[index]);
if (span.attr("media")==this.options.media) $(SelButtons[index]).addClass('active');
}
//Set PublicPrivate
var PublicPrivateButtons = el.find('.annotationListButtons .PublicPrivate').removeClass('active'); //reset
// Set PublicPrivate
var PublicPrivateButtons = el.find('.annotationListButtons .PublicPrivate').removeClass('active'); // reset
for (var index=0;index<PublicPrivateButtons.length;index++) {
var span = $(PublicPrivateButtons[index]).find('span');
if (span.html().toLowerCase()==self.current_tab.toLowerCase()) {
......@@ -449,67 +448,67 @@ CatchAnnotation.prototype = {
}
}
//reset all old events
// reset all old events
el.off();
//Bind functions
var openAnnotationItem = this.__bind(this._openAnnotationItem, this),
closeAnnotationItem = this.__bind(this._closeAnnotationItem, this),
onGeolocationClick = this.__bind(this._onGeolocationClick, this),
onPlaySelectionClick = this.__bind(this._onPlaySelectionClick, this),
onShareControlsClick = this.__bind(this._onShareControlsClick, this),
onSelectionButtonClick = this.__bind(this._onSelectionButtonClick, this),
onPublicPrivateButtonClick = this.__bind(this._onPublicPrivateButtonClick, this),
onQuoteMediaButton = this.__bind(this._onQuoteMediaButton, this),
onControlRepliesClick = this.__bind(this._onControlRepliesClick, this),
onMoreButtonClick = this.__bind(this._onMoreButtonClick, this),
onSearchButtonClick = this.__bind(this._onSearchButtonClick, this),
onClearSearchButtonClick = this.__bind(this._onClearSearchButtonClick, this),
onDeleteReplyButtonClick = this.__bind(this._onDeleteReplyButtonClick, this),
onZoomToImageBoundsButtonClick = this.__bind(this._onZoomToImageBoundsButtonClick, this);
// Bind functions
var openAnnotationItem = this.__bind(this._openAnnotationItem, this);
var closeAnnotationItem = this.__bind(this._closeAnnotationItem, this);
var onGeolocationClick = this.__bind(this._onGeolocationClick, this);
var onPlaySelectionClick = this.__bind(this._onPlaySelectionClick, this);
var onShareControlsClick = this.__bind(this._onShareControlsClick, this);
var onSelectionButtonClick = this.__bind(this._onSelectionButtonClick, this);
var onPublicPrivateButtonClick = this.__bind(this._onPublicPrivateButtonClick, this);
var onQuoteMediaButton = this.__bind(this._onQuoteMediaButton, this);
var onControlRepliesClick = this.__bind(this._onControlRepliesClick, this);
var onMoreButtonClick = this.__bind(this._onMoreButtonClick, this);
var onSearchButtonClick = this.__bind(this._onSearchButtonClick, this);
var onClearSearchButtonClick = this.__bind(this._onClearSearchButtonClick, this);
var onDeleteReplyButtonClick = this.__bind(this._onDeleteReplyButtonClick, this);
var onZoomToImageBoundsButtonClick = this.__bind(this._onZoomToImageBoundsButtonClick, this);
//Open Button
// Open Button
el.on("click", ".annotationItem .annotationRow", openAnnotationItem);
//Close Button
// Close Button
el.on("click", ".annotationItem .detailHeader", closeAnnotationItem);
//Geolocation button
// Geolocation button
el.on("click",".annotationItem .detailHeader .geolocationIcon img", onGeolocationClick);
//controlPanel buttons
// controlPanel buttons
el.on("click",".annotationItem .annotationDetail .controlPanel", onShareControlsClick);
//VIDEO
// VIDEO
if (this.options.media=='video') {
//PlaySelection button
// PlaySelection button
el.on("click",".annotationItem .annotationDetail .playMediaButton", onPlaySelectionClick);
}
//TEXT
// TEXT
if (this.options.media=='text') {
//PlaySelection button
// PlaySelection button
el.on("click",".annotationItem .annotationDetail .quote", onQuoteMediaButton);
}
//IMAGE
// IMAGE
if (this.options.media=='image') {
//PlaySelection button
// PlaySelection button
el.on("click",".annotationItem .annotationDetail .zoomToImageBounds", onZoomToImageBoundsButtonClick);
}
//controlReplies
// controlReplies
el.on("click",".annotationItem .controlReplies", onControlRepliesClick);
//Selection Buttons
// Selection Buttons
el.on("click",".annotationList li", onSelectionButtonClick);
//PublicPrivate Buttons
// PublicPrivate Buttons
el.on("click",".annotationListButtons .PublicPrivate", onPublicPrivateButtonClick);
//More Button
// More Button
el.on("click",".annotationListButtons .moreButtonCatch", onMoreButtonClick);
//Search Button
// Search Button
el.on("click",".searchbox .search-icon", onSearchButtonClick);
//Clear Search Button
// Clear Search Button
el.on("click",".searchbox .clear-search-icon", onClearSearchButtonClick);
//Delete Reply Button
// Delete Reply Button
el.on("click", ".replies .replyItem .deleteReply", onDeleteReplyButtonClick);
},
......@@ -527,10 +526,35 @@ CatchAnnotation.prototype = {
this.refreshCatch(true);
this.checkTotAnnotations();
},
/**
* This function makes sure that the annotations loaded are only the ones that we are
* currently looking for. Annotator has a habit of loading the user's annotations
* immediately without checking to see if we are doing some filtering or otherwise.
* Since it's a vendor file, this is the workaround for that bug.
*/
cleanUpAnnotations: function(){
var annotator = this.annotator;
var store = annotator.plugins.Store;
var annotations = store.annotations;
var self = this;
// goes through all the annotations currently loaded
$.each(annotations, function(key, value){
// if the options.userID (i.e. the value we are searching for) is empty signifying
// public or is equal to the person with update access, then we leave it alone,
// otherwise we need to clean them up (i.e. disable them).
if(self.options.userId !== '' && self.options.userId !== value.permissions.update[0]){
$.each(value.highlights, function(key1, value1){
$(value1).removeClass('annotator-hl');
});
}
});
},
loadAnnotations: function() {
var annotator = this.annotator,
loadFromSearch = annotator.plugins.Store.options.loadFromSearch,
loadedAn = this.element.find('.annotationList .annotationItem').length;
var annotator = this.annotator;
var loadFromSearch = annotator.plugins.Store.options.loadFromSearch;
var loadedAn = this.element.find('.annotationList .annotationItem').length;
loadedAn = typeof loadedAn!='undefined' ?loadedAn:0;
loadFromSearch.limit = this.options.pagination;
......@@ -540,42 +564,42 @@ CatchAnnotation.prototype = {
// Dani had this for some reason. we can't remember. but if something
// breaks, uncomment next line.
//annotator.plugins['Store'].loadAnnotationsFromSearch(loadFromSearch);
// annotator.plugins['Store'].loadAnnotationsFromSearch(loadFromSearch);
//Make sure to be openned all annotations for this pagination
loadFromSearch.limit = this.options.pagination+loadedAn;
loadFromSearch.offset = 0;
annotator.plugins['Store'].loadAnnotationsFromSearch(loadFromSearch);
// Make sure to be openned all annotations for this pagination
loadFromSearch.limit = this.options.pagination+loadedAn;
loadFromSearch.offset = 0;
annotator.plugins['Store'].loadAnnotationsFromSearch(loadFromSearch);
//text loading annotations
// text loading annotations
var moreBut = this.element.find('.annotationListButtons .moreButtonCatch');
moreBut.html('Please wait, loading...');
},
//check whether is necessary more button or not
// check whether is necessary to have a more button or not
checkTotAnnotations: function(){
var annotator = this.annotator,
loadFromSearch = annotator.plugins.Store.options.loadFromSearch,
oldLimit = loadFromSearch.limit,
oldOffset = loadFromSearch.offset,
self = this;
var annotator = this.annotator;
var loadFromSearch = annotator.plugins.Store.options.loadFromSearch;
var oldLimit = loadFromSearch.limit;
var oldOffset = loadFromSearch.offset;
var self = this;
loadFromSearch.limit = 0;
loadFromSearch.offset = 0;
loadFromSearch.media = this.options.media;
loadFromSearch.userid = this.options.userId;
var onSuccess = function(response){
var totAn = self.element.find('.annotationList .annotationItem').length,
maxAn = response.total,
moreBut = self.element.find('.annotationListButtons .moreButtonCatch');
var totAn = self.element.find('.annotationList .annotationItem').length;
var maxAn = response.total;
var moreBut = self.element.find('.annotationListButtons .moreButtonCatch');
if (totAn<maxAn && totAn > 0)
moreBut.show();
else
moreBut.hide();
}
var obj = loadFromSearch,
action = 'search';
var obj = loadFromSearch;
var action = 'search';
var id, options, url;
id = obj && obj.id;
......@@ -583,11 +607,11 @@ CatchAnnotation.prototype = {
options = annotator.plugins['Store']._apiRequestOptions(action, obj, onSuccess);
$.ajax(url, options);
//reset values
// reset values
loadFromSearch.limit = oldLimit;
loadFromSearch.offset = oldOffset;
//set More button text
// set More button text
var moreBut = this.element.find('.annotationListButtons .moreButtonCatch');
moreBut.html('More');
......@@ -597,12 +621,13 @@ CatchAnnotation.prototype = {
// LOCAL UTILITIES
//
_subscribeAnnotator: function(){
var self = this,
annotator = this.annotator;
//Subscribe to Annotator changes
var self = this;
var annotator = this.annotator;
// Subscribe to Annotator changes
annotator.subscribe("annotationsLoaded", function (annotations){
self.cleanUpAnnotations();
self.refreshCatch(self.clean);
//hide or show more button
// hide or show more button
self.checkTotAnnotations();
});
annotator.subscribe("annotationUpdated", function (annotation){
......@@ -610,14 +635,14 @@ CatchAnnotation.prototype = {
self.checkTotAnnotations();
});
annotator.subscribe("annotationDeleted", function (annotation){
var annotations = annotator.plugins['Store'].annotations,
tot = typeof annotations !='undefined'?annotations.length:0,
attempts = 0; // max 100
var annotations = annotator.plugins['Store'].annotations;
var tot = typeof annotations !='undefined'?annotations.length:0;
var attempts = 0; // max 100
if(annotation.media == "image"){
self.refreshCatch(true);
self.checkTotAnnotations();
} else {
//This is to watch the annotations object, to see when is deleted the annotation
// This is to watch the annotations object, to see when is deleted the annotation
var ischanged = function(){
var new_tot = annotator.plugins['Store'].annotations.length;
if (attempts<100)
......@@ -629,34 +654,34 @@ CatchAnnotation.prototype = {
attempts++;
ischanged();
}
},100); //wait for the change in the annotations
},100); // wait for the change in the annotations
};
ischanged();
}
});
annotator.subscribe("annotationCreated", function (annotation){
var attempts = 0; // max 100
//There is a delay between calls to the backend--especially reading after
//writing. This function listens to when a function is created and waits
//until the server provides it with an annotation id before doing anything
//with it.
// There is a delay between calls to the backend--especially reading after
// writing. This function listens to when a function is created and waits
// until the server provides it with an annotation id before doing anything
// with it.
var ischanged = function(){
if (attempts<100)
setTimeout(function(){
if (typeof annotation.id!='undefined'){
//once it gets the annotation id, the table refreshes to show
//the edits
// once it gets the annotation id, the table refreshes to show
// the edits
self.refreshCatch();
if (typeof annotation.parent != 'undefined' && annotation.parent != '0'){
//if annotation made was actually a replay to an annotation
//i.e. the only difference is that annotations that are
//not replies have no "parent"
// if annotation made was actually a replay to an annotation
// i.e. the only difference is that annotations that are
// not replies have no "parent"
var replies = $("[annotationid="+annotation.parent+"]").find(".controlReplies .hideReplies");
//forces "Show replies" section to show and then refreshes
//via two clicks
// forces "Show replies" section to show and then refreshes
// via two clicks
replies.show();
replies.click();
replies.click();
......@@ -665,7 +690,7 @@ CatchAnnotation.prototype = {
attempts++;
ischanged();
}
},100); //wait for annotation id
},100); // wait for annotation id
};
ischanged();
});
......@@ -673,23 +698,23 @@ CatchAnnotation.prototype = {
__bind: function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
_compileTemplates: function() {
var self = this;
//Change the html tags to functions
// Change the html tags to functions
this.TEMPLATENAMES.forEach(function(templateName) {
self.TEMPLATES[templateName] = Handlebars.compile(self.HTMLTEMPLATES[templateName]);
});
},
_isVideoJS: function (an){
var annotator = this.annotator,
rt = an.rangeTime,
isOpenVideojs = (typeof annotator.mplayer != 'undefined'),
isVideo = (typeof an.media!='undefined' && an.media=='video'),
isNumber = (typeof rt!='undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end));
var annotator = this.annotator;
var rt = an.rangeTime;
var isOpenVideojs = (typeof annotator.mplayer != 'undefined');
var isVideo = (typeof an.media!='undefined' && an.media=='video');
var isNumber = (typeof rt!='undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end));
return (isOpenVideojs && isVideo && isNumber);
},
_isInList: function (an){
var annotator = this.annotator,
isInList = false,
list = $('#mainCatch .annotationList .annotationRow.item');
var annotator = this.annotator;
var isInList = false;
var list = $('#mainCatch .annotationList .annotationRow.item');
for (_i = 0, _len = list.length; _i < _len; _i++) {
if ($(list[_i]).parent().attr('annotationid') == an.id)
isInList = true;
......@@ -700,23 +725,23 @@ CatchAnnotation.prototype = {
var item = item || {};
if(this._isVideoJS(item)){
//format time
// format time
item.rangeTime.start= typeof vjs!='undefined'?vjs.formatTime(item.rangeTime.start):item.rangeTime.start;
item.rangeTime.end= typeof vjs!='undefined'?vjs.formatTime(item.rangeTime.end):item.rangeTime.end;
}
//format date
// format date
if(typeof item.updated!='undefined' && typeof createDateFromISO8601!='undefined')
item.updated = createDateFromISO8601(item.updated);
//format geolocation
// format geolocation
if(typeof item.geolocation!='undefined' && (typeof item.geolocation.latitude=='undefined'||item.geolocation.latitude==''))
delete item.geolocation;
/* NEW VARIABLES */
//set plainText for Catch
// set plainText for Catch
item.plainText = item.text.replace(/&(lt|gt);/g, function (strMatch, p1){
return (p1 == "lt")? "<" : ">";
});//Change to < and > tags
item.plainText = item.plainText.replace(/<\/?[^>]+(>|$)/g, "").replace('&nbsp;',''); //remove all the html tags
item.plainText = item.plainText.replace(/<\/?[^>]+(>|$)/g, "").replace('&nbsp;',''); // remove all the html tags
item.mediatypeforgrid = {};
item.mediatypeforgrid[item.media] = true;
......@@ -725,7 +750,7 @@ CatchAnnotation.prototype = {
item.thumbnailLink = item.target.thumb;
};
//Flags
// Flags
if(!this.options.flags && typeof item.tags != 'undefined' && item.tags.length > 0){
for(var len=item.tags.length, index = len-1; index >= 0; --index){
var currTag = item.tags[index];
......@@ -744,15 +769,15 @@ CatchAnnotation.prototype = {
var isClosed = $(evt.currentTarget).closest(".annotationItem").hasClass("closed");
if (isClosed) {
$(evt.currentTarget).closest(".annotationItem").removeClass("closed").addClass("open");
//Add Share button
// Add Share button
var shareControl = $(evt.currentTarget).closest(".annotationItem").find('.annotationDetail .controlPanel:first'),
annotator = this.annotator,
idAnnotation = shareControl.parent().find('.idAnnotation').html(),
uri = shareControl.parent().find('.uri').html();
//remove the last share container
// remove the last share container
shareControl.find('.share-container-annotator').remove();
shareControl.append(annotator.plugins.Share.buildHTMLShareButton("",idAnnotation));
//Set actions button
// Set actions button
annotator.plugins.Share.buttonsActions(shareControl[0],1,uri);
} else {
$(evt.currentTarget).closest(".annotationItem").removeClass("open").addClass("closed");
......@@ -765,15 +790,15 @@ CatchAnnotation.prototype = {
}
},
_onGeolocationClick: function(evt) {
var latitude = $(evt.target).parent().find('.latitude').html(),
longitude = $(evt.target).parent().find('.longitude').html();
var latitude = $(evt.target).parent().find('.latitude').html();
var longitude = $(evt.target).parent().find('.longitude').html();
var imgSrc = '<img src="http://maps.googleapis.com/maps/api/staticmap?center='+latitude+','+longitude+'&zoom=14&size=500x500&sensor=false&markers=color:green%7Clabel:G%7C'+latitude+','+longitude+'">';
$(evt.target).parents('.detailHeader:first').find('#myLocationMap .map').html(imgSrc);
},
_onPlaySelectionClick: function(evt) {
var id = $(evt.target).find('.idAnnotation').html(),
uri = $(evt.target).find('.uri').html();
container = $(evt.target).find('.container').html();
var id = $(evt.target).find('.idAnnotation').html();
var uri = $(evt.target).find('.uri').html();
var container = $(evt.target).find('.container').html();
if(this.options.externalLink){
uri += (uri.indexOf('?') >= 0)?'&ovaId='+id:'?ovaId='+id;
location.href = uri;
......@@ -793,7 +818,7 @@ CatchAnnotation.prototype = {
var anFound = an;
var playFunction = function(){
//Fix problem with youtube videos in the first play. The plugin don't have this trigger
// Fix problem with youtube videos in the first play. The plugin don't have this trigger
if (player.techName == 'Youtube'){
var startAPI = function(){
ovaInstance.showAnnotation(anFound);
......@@ -826,12 +851,12 @@ CatchAnnotation.prototype = {
}
},
_onZoomToImageBoundsButtonClick: function(evt){
var zoomToBounds = $(evt.target).hasClass('zoomToImageBounds')?$(evt.target):$(evt.target).parents('.zoomToImageBounds:first'),
osdaId = zoomToBounds.find('.idAnnotation').html(),
uri = zoomToBounds.find('.uri').html();
var zoomToBounds = $(evt.target).hasClass('zoomToImageBounds')?$(evt.target):$(evt.target).parents('.zoomToImageBounds:first');
var osdaId = zoomToBounds.find('.idAnnotation').html();
var uri = zoomToBounds.find('.uri').html();
var allannotations = this.annotator.plugins['Store'].annotations,
osda = this.annotator.osda;
var allannotations = this.annotator.plugins['Store'].annotations;
var osda = this.annotator.osda;
if(this.options.externalLink){
uri += (uri.indexOf('?') >= 0)?'&osdaId='+osdaId:'?osdaId='+osdaId;
......@@ -839,8 +864,8 @@ CatchAnnotation.prototype = {
}
for(var item in allannotations){
var an = allannotations[item];
//Makes sure that all images are set to transparent in case one was
//previously selected.
// Makes sure that all images are set to transparent in case one was
// previously selected.
an.highlights[0].style.background = "rgba(0,0,0,0)";
if (typeof an.id!='undefined' && an.id == osdaId){//this is the annotation
var bounds = new OpenSeadragon.Rect(an.bounds.x, an.bounds.y, an.bounds.width, an.bounds.height);
......@@ -848,28 +873,28 @@ CatchAnnotation.prototype = {
$('html,body').animate({scrollTop: $("#"+an.target.container).offset().top},
'slow');
//signifies a selected annotation once OSD has zoomed in on the
//appropriate area, it turns the background a bit yellow
// signifies a selected annotation once OSD has zoomed in on the
// appropriate area, it turns the background a bit yellow
an.highlights[0].style.background = "rgba(255,255,10,0.2)";
}
}
},
_onQuoteMediaButton: function(evt){
var quote = $(evt.target).hasClass('quote')?$(evt.target):$(evt.target).parents('.quote:first'),
id = quote.find('.idAnnotation').html(),
uri = quote.find('.uri').html();
var quote = $(evt.target).hasClass('quote')?$(evt.target):$(evt.target).parents('.quote:first');
var id = quote.find('.idAnnotation').html();
var uri = quote.find('.uri').html();
if (typeof id=='undefined' || id==''){
this.refreshCatch();
this.checkTotAnnotations();
id = quote.find('.idAnnotation').html();
//clickPlaySelection(evt);
// clickPlaySelection(evt);
}
if(this.options.externalLink){
uri += (uri.indexOf('?') >= 0)?'&ovaId='+id:'?ovaId='+id;
location.href = uri;
}else{
var allannotations = this.annotator.plugins['Store'].annotations,
ovaId = id;
var allannotations = this.annotator.plugins['Store'].annotations;
var ovaId = id;
for (var item in allannotations) {
var an = allannotations[item];
if (typeof an.id!='undefined' && an.id == ovaId){//this is the annotation
......@@ -882,9 +907,9 @@ CatchAnnotation.prototype = {
if(typeof startOffset!='undefined' && typeof endOffset!='undefined'){
$(an.highlights).parent().find('.annotator-hl').removeClass('api');
//change the color
// change the color
$(an.highlights).addClass('api');
//animate to the annotation
// animate to the annotation
$('html,body').animate({
scrollTop: $(an.highlights[0]).offset().top},
'slow');
......@@ -895,90 +920,90 @@ CatchAnnotation.prototype = {
}
},
_refreshReplies: function(evt){
var item = $(evt.target).parents('.annotationItem:first'),
anId = item.attr('annotationId');
var item = $(evt.target).parents('.annotationItem:first');
var anId = item.attr('annotationId');
var replyElem = $(evt.target).parents('.annotationItem:first').find('.replies');
var annotator = this.annotator,
loadFromSearchURI = annotator.plugins.Store.options.loadFromSearch.uri,
self = this,
action='search',
loadFromSearch={
limit:-1,
parentid:anId,
uri:loadFromSearchURI,
},
onSuccess=function(data){
if (data == null) data = {};
annotations = data.rows || [];
var _i,_len;
for (_i = 0, _len = annotations.length; _i < _len; _i++) {
self._formatCatch(annotations[_i]);
}
replyElem.html(self.TEMPLATES.annotationReply({
annotations: annotations
}));
var replyItems = $('.replies .replyItem');
if(typeof replyItems != 'undefined' && replyItems.length > 0){
annotations.forEach(function(ann){
replyItems.each(function(item){
var id = $(replyItems[item]).attr('annotationid');
if(id == ann.id){
var perm = self.annotator.plugins.Permissions;
if(!perm.options.userAuthorize('delete',ann,perm.user)){
$(replyItems[item]).find('.deleteReply').remove();
}else{
$(replyItems[item]).data('annotation',ann);
}
}
});
});
}
};
var id, options, request, url,
store = this.annotator.plugins.Store;
id = loadFromSearch && loadFromSearch.id;
url = store._urlFor(action, id);
options = store._apiRequestOptions(action, loadFromSearch, onSuccess);
request = $.ajax(url, options);
request._id = id;
request._action = action;
var replyElem = $(evt.target).parents('.annotationItem:first').find('.replies');
var annotator = this.annotator;
var loadFromSearchURI = annotator.plugins.Store.options.loadFromSearch.uri;
var self = this;
var action='search';
var loadFromSearch={
limit:-1,
parentid:anId,
uri:loadFromSearchURI,
};
var onSuccess=function(data){
if (data == null) data = {};
annotations = data.rows || [];
var _i,_len;
for (_i = 0, _len = annotations.length; _i < _len; _i++) {
self._formatCatch(annotations[_i]);
}
replyElem.html(self.TEMPLATES.annotationReply({
annotations: annotations
}));
var replyItems = $('.replies .replyItem');
if(typeof replyItems != 'undefined' && replyItems.length > 0){
annotations.forEach(function(ann){
replyItems.each(function(item){
var id = $(replyItems[item]).attr('annotationid');
if(id == ann.id){
var perm = self.annotator.plugins.Permissions;
if(!perm.options.userAuthorize('delete',ann,perm.user)){
$(replyItems[item]).find('.deleteReply').remove();
}else{
$(replyItems[item]).data('annotation',ann);
}
}
});
});
}
};
var id, options, request, url;
var store = this.annotator.plugins.Store;
id = loadFromSearch && loadFromSearch.id;
url = store._urlFor(action, id);
options = store._apiRequestOptions(action, loadFromSearch, onSuccess);
request = $.ajax(url, options);
request._id = id;
request._action = action;
},
_onControlRepliesClick: function(evt){
var action = $(evt.target)[0].className;
if(action=='newReply'){
var item = $(evt.target).parents('.annotationItem:first'),
id = item.attr('annotationId');
//Pre-show Adder
var item = $(evt.target).parents('.annotationItem:first');
var id = item.attr('annotationId');
// Pre-show Adder
this.annotator.adder.show();
//Get elements
var replyElem = $(evt.target).parents('.annotationItem:first').find('.annotationDetail'),
adder =this.annotator.adder,
wrapper = $('.annotator-wrapper');
// Get elements
var replyElem = $(evt.target).parents('.annotationItem:first').find('.annotationDetail');
var adder =this.annotator.adder;
var wrapper = $('.annotator-wrapper');
//Calculate Editor position
var positionLeft = videojs.findPosition($(evt.target).parent().find('.newReply')[0]),
positionAnnotator = videojs.findPosition(wrapper[0]),
positionAdder = {};
// Calculate Editor position
var positionLeft = videojs.findPosition($(evt.target).parent().find('.newReply')[0]);
var positionAnnotator = videojs.findPosition(wrapper[0]);
var positionAdder = {};
positionAdder.left = positionLeft.left - positionAnnotator.left;
positionAdder.top = positionLeft.top + 20 - positionAnnotator.top;
adder.css(positionAdder);
//Open a new annotator dialog
// Open a new annotator dialog
this.annotator.onAdderClick();
//Set vertical editor
// Set vertical editor
this.annotator.editor.resetOrientation();
this.annotator.editor.invertY();
this.annotator.editor.element.find('.annotator-widget').css('min-width',replyElem.css('width'));
//set parent
// set parent
var parentValue = $(this.annotator.editor.element).find(".reply-item span.parent-annotation");
parentValue.html(id);
var self = this;
......@@ -995,16 +1020,16 @@ CatchAnnotation.prototype = {
return false;
}
//search
// search
this._refreshReplies(evt);
}else if(action=='deleteAnnotation'){
if(confirm("Would you like to delete the annotation?")){
var annotator = this.annotator,
item = $(evt.target).parents('.annotationItem:first'),
id = item.attr('annotationId'),
store = annotator.plugins.Store,
annotations = store.annotations,
permissions = annotator.plugins.Permissions;
var annotator = this.annotator;
var item = $(evt.target).parents('.annotationItem:first');
var id = item.attr('annotationId');
var store = annotator.plugins.Store;
var annotations = store.annotations;
var permissions = annotator.plugins.Permissions;
var annotation;
annotations.forEach(function(ann){
if(ann.id == id)
......@@ -1016,12 +1041,12 @@ CatchAnnotation.prototype = {
}
}else if(action=='editAnnotation'){
var annotator = this.annotator,
item = $(evt.target).parents('.annotationItem:first'),
id = item.attr('annotationId'),
store = annotator.plugins.Store,
annotations = store.annotations,
permissions = annotator.plugins.Permissions;
var annotator = this.annotator;
var item = $(evt.target).parents('.annotationItem:first');
var id = item.attr('annotationId');
var store = annotator.plugins.Store;
var annotations = store.annotations;
var permissions = annotator.plugins.Permissions;
var annotation;
annotations.forEach(function(ann){
if(ann.id == id)
......@@ -1029,17 +1054,17 @@ CatchAnnotation.prototype = {
});
var authorized = permissions.options.userAuthorize('update', annotation,permissions.user);
if(authorized){
//Get elements
// Get elements
var wrapper = $('.annotator-wrapper');
//Calculate Editor position
var positionLeft = videojs.findPosition($(evt.target).parent().find('.editAnnotation')[0]),
positionAnnotator = videojs.findPosition(wrapper[0]),
positionAdder = {};
// Calculate Editor position
var positionLeft = videojs.findPosition($(evt.target).parent().find('.editAnnotation')[0]);
var positionAnnotator = videojs.findPosition(wrapper[0]);
var positionAdder = {};
positionAdder.left = positionLeft.left - positionAnnotator.left;
positionAdder.top = positionLeft.top + 20 - positionAnnotator.top;
var cleanup, offset, update,
_this = this.annotator;
var cleanup, offset, update;
var _this = this.annotator;
offset = positionAdder;
update = function() {
cleanup();
......@@ -1058,31 +1083,27 @@ CatchAnnotation.prototype = {
},
_onShareControlsClick: function(evt) {
var action = $(evt.target)[0].className;
//TODO- Decide whether privacy or group button
if(action=='privacy_button'){
//location.href = "index.php?r=video/privacy&id="+videoId;
}else if(action=='groups_button'){
alert("Coming soon...");
}else if(action=='reply_button'){
var item = $(evt.target).parents('.annotationItem:first'),
id = item.attr('annotationId');
//New annotation
// New annotation
var an = this.annotator.setupAnnotation(this.annotator.createAnnotation());
an.text="010";
an.parent = id;
//Store the annotation
//this.annotator.plugins.Store.annotationCreated(an);
}else if(action=='share_button'){
}
},
_onPublicPrivateButtonClick: function(evt) {
var action = $(evt.target).find('span'),
userId = '';
var action = $(evt.target).find('span');
var userId = '';
//Get userI
// Get userI
switch (action.html()){
case 'public':
userId = '';
......@@ -1095,36 +1116,36 @@ CatchAnnotation.prototype = {
break;
}
this.current_tab = action.html();
//Change userid and refresh
// Change userid and refresh
this.changeUserId(userId);
},
_onSelectionButtonClick: function(evt){
var but = $(evt.target),
action = but.attr('media');
var but = $(evt.target);
var action = but.attr('media');
//Get action
if (action.length<=0) action="text"; //By default
// Get action
if (action.length<=0) action="text"; // By default
//Change media and refresh
// Change media and refresh
this.changeMedia(action);
},
_onMoreButtonClick: function(evt){
this.clean = false;
var moreBut = this.element.find('.annotationListButtons .moreButtonCatch'),
isLoading = moreBut.html()=='More'?false:true;
var moreBut = this.element.find('.annotationListButtons .moreButtonCatch');
var isLoading = moreBut.html()=='More'?false:true;
if(!isLoading)
this.loadAnnotations();
},
_refresh:function(searchtype,searchInput){
var searchtype = searchtype || "",
searchInput = searchInput || "";
this.clean = true;
var searchtype = searchtype || "";
var searchInput = searchInput || "";
this.clean = true;
this._clearAnnotator();
var annotator = this.annotator,
loadFromSearch = annotator.plugins.Store.options.loadFromSearch;
var annotator = this.annotator;
var loadFromSearch = annotator.plugins.Store.options.loadFromSearch;
loadFromSearch.limit = this.options.pagination;
loadFromSearch.offset = 0;
......@@ -1155,38 +1176,37 @@ CatchAnnotation.prototype = {
this._refresh('','');
},
_clearAnnotator: function(){
var annotator = this.annotator,
store = annotator.plugins.Store,
annotations = store.annotations.slice();
var annotator = this.annotator;
var store = annotator.plugins.Store;
var annotations = store.annotations.slice();
annotations.forEach(function(ann){
var child, h, _i, _len, _ref;
if (ann.highlights != null) {
_ref = ann.highlights;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
h = _ref[_i];
if (!(h.parentNode != null)) {
continue;
_ref = ann.highlights;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
h = _ref[_i];
if (!(h.parentNode != null)) {
continue;
}
child = h.childNodes[0];
$(h).replaceWith(h.childNodes);
}
child = h.childNodes[0];
$(h).replaceWith(h.childNodes);
}
}
store.unregisterAnnotation(ann);
});
},
_onDeleteReplyButtonClick : function(evt){
var annotator = this.annotator,
item = $(evt.target).parents('.replyItem:first'),
id = item.attr('annotationid'),
permissions = annotator.plugins.Permissions,
annotation = item.data('annotation');
var annotator = this.annotator;
var item = $(evt.target).parents('.replyItem:first');
var id = item.attr('annotationid');
var permissions = annotator.plugins.Permissions;
var annotation = item.data('annotation');
var authorized = permissions.options.userAuthorize('delete', annotation,permissions.user);
if(authorized){
if(confirm('Would you like to delete this reply?')){
annotator.plugins['Store']._apiRequest('destroy', annotation, function(){});
item.remove();
annotator.plugins['Store']._apiRequest('destroy', annotation, function(){});
item.remove();
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment