Commit e4e4b32c by lduarte1991

Image Annotation Tool: Add linkback functionality to image thumbnails

Changes requested in PR
parent 0318c955
......@@ -147,3 +147,4 @@ David Bodor <david.gabor.bodor@gmail.com>
Sébastien Hinderer <Sebastien.Hinderer@inria.fr>
Kristin Stephens <ksteph@cs.berkeley.edu>
Ben Patterson <bpatterson@edx.org>
Luis Duarte <lduarte1991@gmail.com>
......@@ -754,3 +754,5 @@ LMS: Option to email students when enroll/un-enroll them.
Blades: Added WAI-ARIA markup to the video player controls. These are now fully
accessible by screen readers.
Common: Added advanced_module for annotating images to go with the ones for text and videos.
......@@ -50,6 +50,6 @@ class MLStripper(HTMLParser):
def html_to_text(html):
"strips the html tags off of the text to return plaintext"
htmlStripper = MLStripper()
htmlStripper.feed(html)
return htmlStripper.get_data()
htmlstripper = MLStripper()
htmlstripper.feed(html)
return htmlstripper.get_data()
......@@ -23,8 +23,8 @@ def retrieve_token(userid, secret):
dtnow = datetime.datetime.now()
dtutcnow = datetime.datetime.utcnow()
delta = dtnow - dtutcnow
newhour, newmin = divmod((delta.days * 24 * 60 * 60 + delta.seconds + 30) // 60, 60) # pylint: disable=E1103
newtime = "%s%+02d:%02d" % (dtnow.isoformat(), newhour, newmin) # pylint: disable=E1103
newhour, newmin = divmod((delta.days * 24 * 60 * 60 + delta.seconds + 30) // 60, 60)
newtime = "%s%+02d:%02d" % (dtnow.isoformat(), newhour, newmin)
# uses the issued time (UTC plus timezone), the consumer key and the user's email to maintain a
# federated system in the annotation backend server
custom_data = {"issuedAt": newtime, "consumerKey": secret, "userId": userid, "ttl": 86400}
......
# pylint: disable=W0223
"""
Module for Image annotations using annotator.
"""
......@@ -48,8 +47,18 @@ class AnnotatableFields(object):
scope=Scope.settings,
default='professor:green,teachingAssistant:blue',
)
annotation_storage_url = String(help="Location of Annotation backend", scope=Scope.settings, default="http://your_annotation_storage.com", display_name="Url for Annotation Storage")
annotation_token_secret = String(help="Secret string for annotation storage", scope=Scope.settings, default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", display_name="Secret Token String for Annotation")
annotation_storage_url = String(
help="Location of Annotation backend",
scope=Scope.settings,
default="http://your_annotation_storage.com",
display_name="Url for Annotation Storage"
)
annotation_token_secret = String(
help="Secret string for annotation storage",
scope=Scope.settings,
default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
display_name="Secret Token String for Annotation"
)
class ImageAnnotationModule(AnnotatableFields, XModule):
......@@ -96,7 +105,7 @@ class ImageAnnotationModule(AnnotatableFields, XModule):
return self.system.render_template('imageannotation.html', context)
class ImageAnnotationDescriptor(AnnotatableFields, RawDescriptor):
class ImageAnnotationDescriptor(AnnotatableFields, RawDescriptor): # pylint: disable=abstract-method
''' Image annotation descriptor '''
module_class = ImageAnnotationModule
mako_template = "widgets/raw-edit.html"
......
......@@ -23,17 +23,18 @@ class HelperFunctionTest(unittest.TestCase):
def test_get_instructions(self):
"""
Function takes in an input of a specific xml string with surrounding instructions tags and returns a valid html string.
Function takes in an input of a specific xml string with surrounding instructions
tags and returns a valid html string.
"""
xmltree = etree.fromstring(self.sample_xml)
expected_xml = u"<div><p>Helper Test Instructions.</p></div>"
actual_xml = get_instructions(xmltree) # pylint: disable=W0212
actual_xml = get_instructions(xmltree)
self.assertIsNotNone(actual_xml)
self.assertEqual(expected_xml.strip(), actual_xml.strip())
xmltree = etree.fromstring('<annotatable>foo</annotatable>')
actual = get_instructions(xmltree) # pylint: disable=W0212
actual = get_instructions(xmltree)
self.assertIsNone(actual)
def test_get_extension(self):
......@@ -42,8 +43,8 @@ class HelperFunctionTest(unittest.TestCase):
"""
expectedyoutube = 'video/youtube'
expectednotyoutube = 'video/mp4'
result1 = get_extension(self.sample_sourceurl) # pylint: disable=W0212
result2 = get_extension(self.sample_youtubeurl) # pylint: disable=W0212
result1 = get_extension(self.sample_sourceurl)
result2 = get_extension(self.sample_youtubeurl)
self.assertEqual(expectedyoutube, result2)
self.assertEqual(expectednotyoutube, result1)
......
......@@ -12,9 +12,12 @@ class TokenRetriever(unittest.TestCase):
"""
def test_token(self):
"""
Test for the token generator. Give an a random username and secret token, it should create the properly encoded string of text.
Test for the token generator. Give an a random username and secret token,
it should create the properly encoded string of text.
"""
expected = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3N1ZWRBdCI6ICIyMDE0LTAyLTI3VDE3OjAwOjQyLjQwNjQ0MSswOjAwIiwgImNvbnN1bWVyS2V5IjogImZha2Vfc2VjcmV0IiwgInVzZXJJZCI6ICJ1c2VybmFtZSIsICJ0dGwiOiA4NjQwMH0.Dx1PoF-7mqBOOSGDMZ9R_s3oaaLRPnn6CJgGGF2A5CQ"
response = retrieve_token("username", "fake_secret")
# because the middle hashes are dependent on time, conly the header and footer are checked for secret key
self.assertEqual(expected.split('.')[0], response.split('.')[0])
self.assertNotEqual(expected.split('.')[2], response.split('.')[2])
# -*- coding: utf-8 -*-
"Test for Image Annotation Xmodule functional logic."
"""Test for Image Annotation Xmodule functional logic."""
import unittest
from mock import Mock
......@@ -61,12 +61,12 @@ class ImageAnnotationModuleTestCase(unittest.TestCase):
xmltree = etree.fromstring(self.sample_xml)
expected_xml = u"<div><p>Image Test Instructions.</p></div>"
actual_xml = self.mod._extract_instructions(xmltree) # pylint: disable=W0212
actual_xml = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNotNone(actual_xml)
self.assertEqual(expected_xml.strip(), actual_xml.strip())
xmltree = etree.fromstring('<annotatable>foo</annotatable>')
actual = self.mod._extract_instructions(xmltree) # pylint: disable=W0212
actual = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNone(actual)
def test_get_html(self):
......
......@@ -66,6 +66,6 @@ class VideoAnnotationModuleTestCase(unittest.TestCase):
"""
Tests to make sure variables passed in truly exist within the html once it is all rendered.
"""
context = self.mod.get_html() # pylint: disable=W0212
context = self.mod.get_html()
for key in ['display_name', 'instructions_html', 'sourceUrl', 'typeSource', 'poster', 'annotation_storage']:
self.assertIn(key, context)
......@@ -68,9 +68,9 @@ class VideoAnnotationModule(AnnotatableFields, XModule):
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
return get_instructions(xmltree)
def _get_extension(self, srcurl):
def _get_extension(self, src_url):
''' get the extension of a given url '''
return get_extension(srcurl)
return get_extension(src_url)
def get_html(self):
""" Renders parameters to template. """
......
......@@ -16,10 +16,6 @@
font-style: italic;
}
.annotator-wrapper .mce-container {
z-index: 3000000000!important; /*To fix full-screen problems*/
}
.mce-container-body {
min-width: 400px;
}
......@@ -29,6 +25,10 @@
min-width: 400px;
}
.mce-floatpanel {
z-index: 700000000!important;
}
div.mce-tinymce.mce-container.mce-panel {
min-width:400px;
}
......
......@@ -69,6 +69,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
this.options = options;
this.isAnnotating = false; //If the user is annotating
this.isDrawing = false; //if the user is drawing something
this.rectPosition = undefined;
//Init
this.init();
......@@ -84,9 +85,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
/* canvas Events */
//- Bind canvas functions
var onCanvasMouseDown = this.__bind(this._onCanvasMouseDown,this),
onCanvasMouseMove = this.__bind(this._onCanvasMouseMove,this),
onDocumentMouseUp = this.__bind(this._onDocumentMouseUp,this);
var onCanvasMouseDown = this.__bind(this._onCanvasMouseDown,this);
var onCanvasMouseMove = this.__bind(this._onCanvasMouseMove,this);
var onDocumentMouseUp = this.__bind(this._onDocumentMouseUp,this);
//- Add canvas events
$.addEvent(viewer.canvas, "mousedown", onCanvasMouseDown, true);
......@@ -162,13 +163,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
},
drawRect:function(an){
if (typeof an.rangePosition!='undefined'){
var span = document.createElement('span'),
rectPosition = an.rangePosition;
var span = document.createElement('span');
var rectPosition = an.rangePosition;
//Span
span.className = "annotator-hl";
span.style.border = '1px solid rgba(0,0,0,0.5)';
var onAnnotationMouseMove = this.__bind(this._onAnnotationMouseMove,this),
onAnnotationClick = this.__bind(this._onAnnotationClick,this);
var onAnnotationMouseMove = this.__bind(this._onAnnotationMouseMove,this);
var onAnnotationClick = this.__bind(this._onAnnotationClick,this);
$.addEvent(span, "mousemove", onAnnotationMouseMove, true);
$.addEvent(span, "click", onAnnotationClick, true);
......@@ -188,12 +189,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
},
//Change object(this.rectPosition)the rectangle Position using div element(this.rect)
setRectPosition:function(){
var left = parseInt(this.rect.style.left),
top = parseInt(this.rect.style.top),
width = parseInt(this.rect.style.left)+parseInt(this.rect.style.width),
height = parseInt(this.rect.style.top)+parseInt(this.rect.style.height),
startPoint = new $.Point(left,top),
endPoint = new $.Point(width,height);
var left = parseInt(this.rect.style.left);
var top = parseInt(this.rect.style.top);
var width = parseInt(this.rect.style.left)+parseInt(this.rect.style.width);
var height = parseInt(this.rect.style.top)+parseInt(this.rect.style.height);
var startPoint = new $.Point(left,top);
var endPoint = new $.Point(width,height);
this.rectPosition = {left:this._physicalToLogicalXY(startPoint).x,
top:this._physicalToLogicalXY(startPoint).y,
width:this._physicalToLogicalXY(endPoint).x-this._physicalToLogicalXY(startPoint).x,
......@@ -213,9 +214,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
this.isDrawing = true;
//Create rect element
var mouse = $.getMousePosition( event ),
elementPosition = $.getElementPosition(viewer.canvas),
position = mouse.minus( elementPosition );
var mouse = $.getMousePosition( event );
var elementPosition = $.getElementPosition(viewer.canvas);
var position = mouse.minus( elementPosition );
viewer.innerTracker.setTracking(false);
this.rect = document.createElement('div');
this.rect.style.background = 'rgba(0,0,0,0.25)';
......@@ -242,14 +243,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
var viewer = this.viewer;
//Calculate the new end position
var mouse = $.getMousePosition( event ),
elementPosition = $.getElementPosition(viewer.canvas),
endPosition = mouse.minus( elementPosition );
var mouse = $.getMousePosition( event );
var elementPosition = $.getElementPosition(viewer.canvas);
var endPosition = mouse.minus( elementPosition );
//retrieve start position
var startPosition = this.startPosition;
var newWidth= endPosition.x-startPosition.x,
newHeight =endPosition.y-startPosition.y;
var newWidth= endPosition.x-startPosition.x;
var newHeight =endPosition.y-startPosition.y;
//Set new position
this.rect.style.width = (newWidth<0) ? (-1*newWidth) +'px' : newWidth +'px';
......@@ -293,17 +294,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
annotator.viewer.hide();
//get the annotation over the mouse
var annotations = jQuery(event.target.parentNode).find('.annotator-hl').map(function() {
var self = jQuery(this),
offset = self.offset(),
l = offset.left,
t = offset.top,
h = self.height(),
w = self.width(),
x = $.getMousePosition(event).x,
y = $.getMousePosition(event).y;
var maxx = l + w,
maxy = t + h;
var self = jQuery(this);
var offset = self.offset();
var l = offset.left;
var t = offset.top;
var h = self.height();
var w = self.width();
var x = $.getMousePosition(event).x;
var y = $.getMousePosition(event).y;
var maxx = l + w;
var maxy = t + h;
this.style.background = (y <= maxy && y >= t) && (x <= maxx && x >= l)?
'rgba(12, 150, 0, 0.3)':'rgba(255, 255, 10, 0.3)';
return (y <= maxy && y >= t) && (x <= maxx && x >= l)? jQuery(this).data("annotation") : null;
......@@ -317,9 +318,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
}
},
_onAnnotationClick: function(event){
var an = jQuery.data(event.target, 'annotation'),
bounds = typeof an.bounds!='undefined'?an.bounds:{},
currentBounds = this.viewer.drawer.viewport.getBounds();
var an = jQuery.data(event.target, 'annotation');
var bounds = typeof an.bounds!='undefined'?an.bounds:{};
var currentBounds = this.viewer.drawer.viewport.getBounds();
if (typeof bounds.x!='undefined') currentBounds.x = bounds.x;
if (typeof bounds.y!='undefined') currentBounds.y = bounds.y;
if (typeof bounds.width!='undefined') currentBounds.width = bounds.width;
......@@ -350,10 +351,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
});
},
_createNewButton:function(){
var viewer = this.viewer,
onFocusHandler = $.delegate( this, onFocus ),
onBlurHandler = $.delegate( this, onBlur ),
onModeAnnotationHandler = $.delegate( this, this.modeAnnotation );
var viewer = this.viewer;
var onFocusHandler = $.delegate( this, onFocus );
var onBlurHandler = $.delegate( this, onBlur );
var onModeAnnotationHandler = $.delegate( this, this.modeAnnotation );
/* Buttons */
var viewer = this.viewer;
var self = this;
......@@ -403,8 +404,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
__bind: function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
// Remove all the elements with a given name inside "inElement"
_removeElemsByClass: function(className,inElement){
var className = className || '',
inElement = inElement || {};
var className = className || '';
var inElement = inElement || {};
divs = inElement.getElementsByClassName(className);
for(var i = 0; i < divs.length; i++) {
divs[i].remove();
......@@ -412,33 +413,33 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
},
//Detect if the annotation is an image annotation
_isOpenSeaDragon: function (an){
var annotator = this.annotator,
rp = an.rangePosition,
isOpenSeaDragon = (typeof annotator.osda != 'undefined'),
isContainer = (typeof an.target!='undefined' && an.target.container==this.viewer.id ),
isImage = (typeof an.media!='undefined' && an.media=='image'),
isRP = (typeof rp!='undefined'),
isSource = false;
var annotator = this.annotator;
var rp = an.rangePosition;
var isOpenSeaDragon = (typeof annotator.osda != 'undefined');
var isContainer = (typeof an.target!='undefined' && an.target.container==this.viewer.id );
var isImage = (typeof an.media!='undefined' && an.media=='image');
var isRP = (typeof rp!='undefined');
var isSource = false;
//Save source url
var source = this.viewer.source,
tilesUrl = typeof source.tilesUrl!='undefined'?source.tilesUrl:'';
functionUrl = typeof source.getTileUrl!='undefined'?source.getTileUrl:'',
compareUrl = tilesUrl!=''?tilesUrl:(''+functionUrl).replace(/\s+/g, ' ');
var source = this.viewer.source;
var tilesUrl = typeof source.tilesUrl!='undefined'?source.tilesUrl:'';
var functionUrl = typeof source.getTileUrl!='undefined'?source.getTileUrl:'';
var compareUrl = tilesUrl!=''?tilesUrl:(''+functionUrl).replace(/\s+/g, ' ');
if(isContainer) isSource = (an.target.src == compareUrl);
return (isOpenSeaDragon && isContainer && isImage && isRP && isSource);
},
/* Annotator Utilities */
_setOverShape: function(elem){
//Calculate Point absolute positions
var rectPosition = this.rectPosition || {},
startPoint = this._logicalToPhysicalXY(new $.Point(rectPosition.left,rectPosition.top)),
endPoint = this._logicalToPhysicalXY(new $.Point(rectPosition.left+rectPosition.width,rectPosition.top+rectPosition.height));
var rectPosition = this.rectPosition || {};
var startPoint = this._logicalToPhysicalXY(new $.Point(rectPosition.left,rectPosition.top));
var endPoint = this._logicalToPhysicalXY(new $.Point(rectPosition.left+rectPosition.width,rectPosition.top+rectPosition.height));
//Calculate Point absolute positions
var wrapper = jQuery('.annotator-wrapper')[0],
positionAnnotator = $.getElementPosition(wrapper),
positionCanvas = $.getElementPosition(this.viewer.canvas),
positionAdder = {};
var wrapper = jQuery('.annotator-wrapper')[0];
var positionAnnotator = $.getElementPosition(wrapper);
var positionCanvas = $.getElementPosition(this.viewer.canvas);
var positionAdder = {};
//Fix with positionCanvas
startPoint = startPoint.plus(positionCanvas);
......@@ -457,15 +458,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// return a point with the values in percentage related to the Image
// point is an object $.Point with the value of the canvas relative coordenates
_physicalToLogicalXY: function(point){
var point = typeof point!='undefined'?point:{},
boundX = this.viewer.viewport.getBounds(true).x,
boundY = this.viewer.viewport.getBounds(true).y,
boundWidth = this.viewer.viewport.getBounds(true).width,
boundHeight = this.viewer.viewport.getBounds(true).height,
containerSizeX = this.viewer.viewport.getContainerSize().x,
containerSizeY = this.viewer.viewport.getContainerSize().y,
x = typeof point.x!='undefined'?point.x:0,
y = typeof point.y!='undefined'?point.y:0;
var point = typeof point!='undefined'?point:{};
var boundX = this.viewer.viewport.getBounds(true).x;
var boundY = this.viewer.viewport.getBounds(true).y;
var boundWidth = this.viewer.viewport.getBounds(true).width;
var boundHeight = this.viewer.viewport.getBounds(true).height;
var containerSizeX = this.viewer.viewport.getContainerSize().x;
var containerSizeY = this.viewer.viewport.getContainerSize().y;
var x = typeof point.x!='undefined'?point.x:0;
var y = typeof point.y!='undefined'?point.y:0;
x = boundX + ((x / containerSizeX) * boundWidth);
y = boundY + ((y / containerSizeY) * boundHeight);
return new $.Point(x,y);
......@@ -473,15 +474,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// return a point with the values in pixels related to the canvas element
// point is an object $.Point with the value of the Image relative percentage
_logicalToPhysicalXY: function(point){
var point = typeof point!='undefined'?point:{},
boundX = this.viewer.viewport.getBounds(true).x,
boundY = this.viewer.viewport.getBounds(true).y,
boundWidth = this.viewer.viewport.getBounds(true).width,
boundHeight = this.viewer.viewport.getBounds(true).height,
containerSizeX = this.viewer.viewport.getContainerSize().x,
containerSizeY = this.viewer.viewport.getContainerSize().y,
x = typeof point.x!='undefined'?point.x:0,
y = typeof point.y!='undefined'?point.y:0;
var point = typeof point!='undefined'?point:{};
var boundX = this.viewer.viewport.getBounds(true).x;
var boundY = this.viewer.viewport.getBounds(true).y;
var boundWidth = this.viewer.viewport.getBounds(true).width;
var boundHeight = this.viewer.viewport.getBounds(true).height;
var containerSizeX = this.viewer.viewport.getContainerSize().x;
var containerSizeY = this.viewer.viewport.getContainerSize().y;
var x = typeof point.x!='undefined'?point.x:0;
var y = typeof point.y!='undefined'?point.y:0;
x = (x - boundX) * containerSizeX / boundWidth;
y = (y - boundY) * containerSizeY / boundHeight;
return new $.Point(x,y);
......@@ -533,7 +534,17 @@ Annotator.Plugin.OpenSeaDragon = (function(_super) {
function OpenSeaDragon() {
this.pluginSubmit = __bind(this.pluginSubmit, this);
_ref = OpenSeaDragon.__super__.constructor.apply(this, arguments);
this.__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }
this.__indexOf = [].indexOf;
if(!this.__indexOf){
this.__indexOf = function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (i in this && this[i] === item)
return i;
}
return -1;
}
}
return _ref;
}
......@@ -555,8 +566,8 @@ Annotator.Plugin.OpenSeaDragon = (function(_super) {
});
//Modify the element created with annotator to be an invisible span
var select = '<li><span id="osd-input-rangePosition-annotations"></span></li>',
newfield = Annotator.$(select);
var select = '<li><span id="osd-input-rangePosition-annotations"></span></li>';
var newfield = Annotator.$(select);
Annotator.$(this.field).replaceWith(newfield);
this.field=newfield[0];
......@@ -572,20 +583,27 @@ Annotator.Plugin.OpenSeaDragon = (function(_super) {
OpenSeaDragon.prototype.pluginSubmit = function(field, annotation) {
//Select the new JSON for the Object to save
if (this.EditOpenSeaDragonAn()){
var annotator = this.annotator,
osda = annotator.osda,
position = osda.rectPosition,
isNew = typeof annotation.media=='undefined';
var annotator = this.annotator;
var osda = annotator.osda;
var position = osda.rectPosition;
var isNew = typeof annotation.media=='undefined';
if (typeof annotation.media == 'undefined') annotation.media = "image"; // - media
annotation.target = annotation.target || {}; // - target
annotation.target.container = osda.viewer.id || ""; // - target.container
//Save source url
var source = osda.viewer.source,
tilesUrl = typeof source.tilesUrl!='undefined'?source.tilesUrl:'',
functionUrl = typeof source.getTileUrl!='undefined'?source.getTileUrl:'';
var source = osda.viewer.source;
var tilesUrl = typeof source.tilesUrl!='undefined'?source.tilesUrl:'';
var functionUrl = typeof source.getTileUrl!='undefined'?source.getTileUrl:'';
annotation.target.src = tilesUrl!=''?tilesUrl:(''+functionUrl).replace(/\s+/g, ' '); // - target.src (media source)
annotation.target.ext = source.fileFormat || ""; // - target.ext (extension)
annotation.bounds = osda.viewer.drawer.viewport.getBounds() || {}; // - bounds
var finalimagelink = source["@id"].replace("/info.json", "");
var highlightX = Math.round(position.left * source["width"]);
var highlightY = Math.round(position.top * source["width"]);
var highlightWidth = Math.round(position.width * source["width"]);
var highlightHeight = Math.round(position.height * source["width"]);
annotation.target.thumb = finalimagelink + "/" + highlightX + "," + highlightY + "," + highlightWidth + "," + highlightHeight + "/full/0/native." + source["formats"][0];
if(isNew) annotation.rangePosition = position || {}; // - rangePosition
annotation.updated = new Date().toISOString(); // - updated
if (typeof annotation.created == 'undefined')
......@@ -614,19 +632,19 @@ Annotator.Plugin.OpenSeaDragon = (function(_super) {
//Detect if the annotation is an OpenSeaDragon annotation
OpenSeaDragon.prototype.isOpenSeaDragon = function (an){
var wrapper = $('.annotator-wrapper').parent()[0],
annotator = window.annotator = $.data(wrapper, 'annotator'),
rp = an.rangePosition,
isOpenSeaDragon = (typeof annotator.osda != 'undefined'),
isContainer = (typeof an.target!='undefined' && an.target.container==annotator.osda.viewer.id ),
isImage = (typeof an.media!='undefined' && an.media=='image'),
isRP = (typeof rp!='undefined'),
isSource = false;
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = window.annotator = $.data(wrapper, 'annotator');
var rp = an.rangePosition;
var isOpenSeaDragon = (typeof annotator.osda != 'undefined');
var isContainer = (typeof an.target!='undefined' && an.target.container==annotator.osda.viewer.id );
var isImage = (typeof an.media!='undefined' && an.media=='image');
var isRP = (typeof rp!='undefined');
var isSource = false;
//Save source url
var source = annotator.osda.viewer.source,
tilesUrl = typeof source.tilesUrl!='undefined'?source.tilesUrl:'';
functionUrl = typeof source.getTileUrl!='undefined'?source.getTileUrl:'',
compareUrl = tilesUrl!=''?tilesUrl:(''+functionUrl).replace(/\s+/g, ' ');
var source = annotator.osda.viewer.source;
var tilesUrl = typeof source.tilesUrl!='undefined'?source.tilesUrl:'';
var functionUrl = typeof source.getTileUrl!='undefined'?source.getTileUrl:'';
var compareUrl = tilesUrl!=''?tilesUrl:(''+functionUrl).replace(/\s+/g, ' ');
if(isContainer) isSource = (an.target.src == compareUrl);
return (isOpenSeaDragon && isContainer && isImage && isRP && isSource);
};
......@@ -644,11 +662,11 @@ Annotator.Plugin.OpenSeaDragon = (function(_super) {
//--Listeners
OpenSeaDragon.prototype.initListeners = function (){
var wrapper = $('.annotator-wrapper').parent()[0],
annotator = $.data(wrapper, 'annotator');
var EditOpenSeaDragonAn = this.EditOpenSeaDragonAn,
isOpenSeaDragon = this.isOpenSeaDragon,
self = this;
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = $.data(wrapper, 'annotator');
var EditOpenSeaDragonAn = this.EditOpenSeaDragonAn;
var isOpenSeaDragon = this.isOpenSeaDragon;
var self = this;
//local functions
//-- Editor
......@@ -714,8 +732,8 @@ OpenSeadragonAnnotation = ("OpenSeadragonAnnotation" in window) ? OpenSeadragonA
OpenSeadragonAnnotation = function (element, options) {
//local variables
var $ = jQuery,
options = options || {};
var $ = jQuery;
var options = options || {};
options.optionsOpenSeadragon = options.optionsOpenSeadragon || {};
options.optionsOSDA = options.optionsOSDA || {};
options.optionsAnnotator = options.optionsAnnotator || {};
......
......@@ -225,7 +225,14 @@
margin-top: 15px;
}
#mainCatch .playMediaButton {
#mainCatch .zoomToImageBounds {
width: 20em;
text-align:center;
margin-top: 15px;
margin-bottom: 5px;
}
#mainCatch .playMediaButton, #mainCatch .zoomToImageBounds {
border-top: 2px solid #d3bd89;
border-bottom: 2px solid #b3ad69;
border-right: 2px solid #b3ad69;
......@@ -242,7 +249,7 @@
border-radius: 24px;
color: #000000;
}
#mainCatch .playMediaButton:hover {
#mainCatch .playMediaButton:hover, #mainCatch .zoomToImageBounds:hover {
border-top: 2px solid #d3bd89;
border-bottom: 2px solid #b3ad69;
border-right: 2px solid #b3ad69;
......@@ -250,7 +257,7 @@
background: #f5c105;
color: #080708;
}
#mainCatch .playMediaButton:active {
#mainCatch .playMediaButton:active, #mainCatch .zoomToImageBounds:active {
border-top: 2px solid #d3bd89;
border-bottom: 2px solid #b3ad69;
border-right: 2px solid #b3ad69;
......
......@@ -222,7 +222,11 @@ annotationDetail:
'</div>'+
'{{/if}}'+
'{{#if mediatypeforgrid.image}}'+
'<img src="http://www.paraemigrantes.com/wp-content/themes/daily/images/default-thumb.gif">'+
'<div class="zoomToImageBounds">'+
'<img src="{{{ thumbnailLink }}}">'+
'<span class="idAnnotation" style="display:none">{{{ id }}}</span>'+
'<span class="uri" style="display:none">{{{uri}}}</span>'+
'</div>'+
'{{/if}}'+
'<div class="body">'+
'{{{ text }}}'+
......@@ -254,10 +258,6 @@ annotationDetail:
'{{/if}}'+
'<div class="controlPanel">'+
//'<img class="privacy_button" src="'+root+'privacy_icon.png" width="36" height="36" alt="Privacy Settings" title="Privacy Settings">'+
// '<img class="groups_button" src="'+root+'groups_icon.png" width="36" height="36" alt="Groups Access" title="Groups Access">'+
// '<img class="reply_button" src="'+root+'groups_icon.png" width="36" height="36" alt="Reply" title="Reply" idAnnotation="{{{ id }}}">'+
//'<img class="share_button" src="'+root+'share_icon.png" width="36" height="36" alt="Share Annotation" title="Share Annotation"/>'+
'</div>'+
'</div>',
};
......@@ -412,18 +412,19 @@ CatchAnnotation.prototype = {
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),
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),
onDeleteReplyButtonClick = this.__bind(this._onDeleteReplyButtonClick,this);
onDeleteReplyButtonClick = this.__bind(this._onDeleteReplyButtonClick, this),
onZoomToImageBoundsButtonClick = this.__bind(this._onZoomToImageBoundsButtonClick, this);
//Open Button
el.on("click", ".annotationItem .annotationRow", openAnnotationItem);
......@@ -444,6 +445,12 @@ CatchAnnotation.prototype = {
el.on("click",".annotationItem .annotationDetail .quote", onQuoteMediaButton);
}
//IMAGE
if (this.options.media=='image') {
//PlaySelection button
el.on("click",".annotationItem .annotationDetail .zoomToImageBounds", onZoomToImageBoundsButtonClick);
}
//controlReplies
el.on("click",".annotationItem .controlReplies", onControlRepliesClick);
......@@ -651,6 +658,10 @@ CatchAnnotation.prototype = {
item.mediatypeforgrid = {};
item.mediatypeforgrid[item.media] = true;
if (item.mediatypeforgrid.image) {
item.thumbnailLink = item.target.thumb;
};
//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){
......@@ -751,6 +762,26 @@ 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 allannotations = this.annotator.plugins['Store'].annotations,
osda = this.annotator.osda;
for(var item in allannotations){
var an = allannotations[item];
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);
osda.viewer.viewport.fitBounds(bounds, false);
console.log(an.target.container);
$('html,body').animate({scrollTop: $("#"+an.target.container).offset().top},
'slow');
}
}
},
_onQuoteMediaButton: function(evt){
var quote = $(evt.target).hasClass('quote')?$(evt.target):$(evt.target).parents('.quote:first'),
id = quote.find('.idAnnotation').html(),
......
......@@ -78,7 +78,6 @@ Annotator.Plugin.RichText = (function(_super) {
annotator.subscribe("annotationEditorShown", function(){
$(annotator.editor.element).find('.mce-tinymce')[0].style.display='block';
$(annotator.editor.element).find('.mce-container').css('z-index',3000000000);
annotator.editor.checkOrientation();
});
annotator.subscribe("annotationEditorHidden", function(){
......@@ -91,9 +90,6 @@ Annotator.Plugin.RichText = (function(_super) {
//set the modification in the textarea of annotator
$(editor.element).find('textarea')[0].value = tinymce.activeEditor.getContent();
});
ed.on('Init', function(ed){
$('.mce-container').css('z-index','3090000000000000000');
});
//New button to add Rubrics of the url https://gteavirtual.org/rubric
ed.addButton('rubric', {
icon: 'rubric',
......
......@@ -35,6 +35,7 @@
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js', raw=True)}" />
</div>
<div id="catchDIV">
## Translators: Notes below refer to annotations. They wil later be put under a "Notes" section.
<div class="annotationListContainer">${_('You do not have any notes.')}</div>
</div>
</div>
......
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