Skip to content

Commit

Permalink
Merge pull request #3480 from lduarte1991/lduarte-harvardx2
Browse files Browse the repository at this point in the history
Annotation Tool Clean up and Plugins
  • Loading branch information
sarina committed Jun 2, 2014
2 parents f33eb60 + b83e27f commit 31274a5
Show file tree
Hide file tree
Showing 16 changed files with 349 additions and 35 deletions.
21 changes: 19 additions & 2 deletions common/lib/xmodule/xmodule/textannotation_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,24 @@ class AnnotatableFields(object):
scope=Scope.settings,
default='None',
)
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"),
)
diacritics = String(
display_name=_("Diacritic Marks"),
help=_("Add diacritic marks to be added to a text using the comma-separated form, i.e. markname;urltomark;baseline,markname2;urltomark2;baseline2"),
scope=Scope.settings,
default='',
)


class TextAnnotationModule(AnnotatableFields, XModule):
Expand Down Expand Up @@ -84,6 +100,7 @@ def student_view(self, context):
'content_html': self.content,
'annotation_storage': self.annotation_storage_url,
'token': retrieve_token(self.user_email, self.annotation_token_secret),
'diacritic_marks': self.diacritics,
}
fragment = Fragment(self.system.render_template('textannotation.html', context))
fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
Expand Down
27 changes: 23 additions & 4 deletions common/lib/xmodule/xmodule/videoannotation_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,29 @@ class AnnotatableFields(object):
scope=Scope.settings,
default=_('Video Annotation'),
)
sourceurl = String(help=_("The external source URL for the video."), display_name=_("Source URL"), scope=Scope.settings, default="http://video-js.zencoder.com/oceans-clip.mp4")
poster_url = String(help=_("Poster Image URL"), display_name=_("Poster URL"), scope=Scope.settings, default="")
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"))
sourceurl = String(
help=_("The external source URL for the video."),
display_name=_("Source URL"),
scope=Scope.settings, default="http://video-js.zencoder.com/oceans-clip.mp4"
)
poster_url = String(
help=_("Poster Image URL"),
display_name=_("Poster URL"),
scope=Scope.settings,
default=""
)
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 VideoAnnotationModule(AnnotatableFields, XModule):
'''Video Annotation Module'''
Expand Down
8 changes: 8 additions & 0 deletions common/static/css/vendor/ova/diacritic-annotator.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.mark{
width: 10px;
height: 10px;
position: absolute;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 0%;
}
4 changes: 4 additions & 0 deletions common/static/css/vendor/ova/edx-annotator.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/*This is written to fix some design problems with edX*/
.annotatable-wrapper .annotatable-header .annotatable-title{
padding-top: 20px !important;
}

.annotator-wrapper .annotator-adder button {
opacity:0;
}
Expand Down
14 changes: 9 additions & 5 deletions common/static/css/vendor/ova/richText-annotator.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
font-style: italic;
}

.mce-floatpanel {
z-index: 700000000!important;
}

.annotator-wrapper .mce-container {
z-index: 3000000000!important; /*To fix full-screen problems*/
}

.mce-container-body {
min-width: 400px;
}
Expand All @@ -25,10 +33,6 @@
min-width: 400px;
}

.mce-floatpanel {
z-index: 700000000!important;
}

div.mce-tinymce.mce-container.mce-panel {
min-width:400px;
}
Expand All @@ -42,4 +46,4 @@ div.mce-tinymce.mce-container.mce-panel {
.mce-ico.mce-i-rubric{
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QkBBB07nraNoQAAAhZJREFUKM+NkstrE1EUxr+5c08ykztpJtVoazHBF8FgQQzonyBKEZS6FrQKLl0EXBRT0ZULJSs3oii4TyHgu90IlTaL6qouWlv7Ck1N0BSnmZk714WbPHz07M4534+Pw3eAHdTY8A9+Nd9/bshU1DpnO4HXjh2ZY2J9/OSTxHTrnP8PvJYf+BDQ6qEDaQBB43jrTusUFy4oPjsYWYzF+VS91nxLYfdhKgONaQT3W/KMxr1XY5e+qj86f8zsKYYsZ6AvjWFzA8ORHkAnwN8So7evzL/8pzMAXL/Hq8mMv1up371T7Z+/c3n9cKeuDS6Xy6dN07zLuZ56Onk2Ed2/ANJsnE/PQMpgyffle+kYzwazB1+3waVS6X48Hr9BRPB9H57nYXplFKeSt8D1Hriug9XKF0x+Lmw+ys8m2m42DOOn4zhQSsGyLOi6jqONm9isbmFVFlDbaGKx8QaB1rvdlbNhGLAsC0IIGIYBIQSy2ROQ0oOp7wOPraHXEugRvDtnzjmi0SiICEIIEBGklAB9B6cmbG0AUnrY5m73h+m6DsYYTNMEYwxEBMY0hGNVhHkcZigBO9qHlDHS7cwYg23bAIBQKAQigud7IH0XwtxDoHwEIQ9SLKx0wa7rPiaivYyxESklXNeFBg0mjyNQTQSuATMSm6ipuYt//eVcLhdeXl5+UKlUlur1upqamVAv3j3/VCyOD3VqfwF6uLp3q+vMcgAAAABJRU5ErkJggg==');
background-repeat: no-repeat;
}
}
2 changes: 1 addition & 1 deletion common/static/css/vendor/ova/tags-annotator.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ li.token-input-input-token {

div.token-input-dropdown {
position: absolute;
width: 120px;
width: 400px;
background-color: #fff;
overflow: hidden;
border-left: 1px solid #ccc;
Expand Down
270 changes: 270 additions & 0 deletions common/static/js/vendor/ova/diacritic-annotator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
/*
Diacritic Annotator Plugin v1.0 (https://github.com/lduarte1991/diacritic-annotator)
Copyright (C) 2014 Luis F Duarte
License: https://github.com/lduarte1991/diacritic-annotator/blob/master/LICENSE.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

var _ref;
var __bind = function(fn, me){
return function(){
return fn.apply(me, arguments);
};
};
var __hasProp = {}.hasOwnProperty;
var __extends = function(child, parent) {
for (var key in parent) {
if (__hasProp.call(parent, key))
child[key] = parent[key];
}
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
};

Annotator.Plugin.Diacritics = (function(_super) {
__extends(Diacritics, _super);

//Options will include diacritic name, picture used, baseline
Diacritics.prototype.options = null;
Diacritics.prototype.diacriticmarks = null;

/**
* Declares all the functions and variables that the plugin will need.
* @constructor
*/
function Diacritics(element,options) {
this.pluginSubmit = __bind(this.pluginSubmit, this);
this.updateDiacritics = __bind(this.updateDiacritics, this);
this.updateViewer = __bind(this.updateViewer, this);
this.getDiacritics = __bind(this.getDiacritics, this);
this.getPos = __bind(this.getPos, this);
this.putMarkAtLocation = __bind(this.putMarkAtLocation, this);
this.updateEditorForDiacritics =
__bind(this.updateEditorForDiacritics, this);

this.options = options;
this.diacriticmarks = this.getDiacritics();
_ref = Diacritics.__super__.constructor.apply(this, arguments);
return _ref;
}

//example variables to be used to receive input in the annotator view
Diacritics.prototype.field = null;
Diacritics.prototype.input = null;

/**
* Initalizes the Plug-in for diacritic marks. It adds in the field for the mark
* and sets up listeners from the Annotator.js file to make changes as needed
*/
Diacritics.prototype.pluginInit = function() {
//Check that annotator is working
if (!Annotator.supported()) {
return;
}
var di = this.diacriticmarks;

//-- Editor
var self = this;
if(di != 'undefined'){
$.each(di,function(item){
self.field = self.annotator.editor.addField({
//options (textarea,input,select,checkbox)
type: 'checkbox',
label: Annotator._t(item),
submit: self.pluginSubmit,
});
});

//-- Viewer
this.annotator.viewer.addField({
load: this.updateViewer,
});

this.annotator.subscribe('annotationsLoaded', this.updateDiacritics);
this.annotator.subscribe('annotationUploaded', this.updateDiacritics);
this.annotator.subscribe('annotationDeleted', this.updateDiacritics);
this.annotator.subscribe('annotationUpdated', this.updateDiacritics);
this.annotator.subscribe('annotationEditorShown', this.updateEditorForDiacritics, this.field);

$(window).resize(this.updateDiacritics.bind(this));
}

return this.input = $(this.field).find(':input');
};

/**
* Adds or removes tag from checked/unchecked boxes of diacritics available
* @param field {Object} - element which holds editor
* @param annotation {Object} - object that contains annotation information from database
*/
Diacritics.prototype.pluginSubmit = function(field, annotation) {
var checkedItems = $(this.field).find(':input');
var self = this;
$.each(checkedItems, function(item){
if(typeof annotation.tags != 'undefined'){
var index = $.inArray(checkedItems[item].placeholder, annotation.tags);
if(index != -1){
annotation.tags.splice(index, 1);
var annotatorWrapper = $('.annotator-wrapper').first();
var element = annotatorWrapper.find('div.' + annotation.id);

if(!element.length){
element = annotatorWrapper.find('div.undefined');
}

element.remove();
}

if(checkedItems[item].checked === true){
annotation.tags.unshift(checkedItems[item].placeholder);
self.putMarkAtLocation(annotation, checkedItems[item].placeholder);
}
} else {
if(checkedItems[item].checked === true){
annotation.tags = [checkedItems[item].placeholder];
self.putMarkAtLocation(annotation, checkedItems[item].placeholder);
}
}
});

};

/**
* Draws the mark above a specific annotation
* @param annotation {Object} - location where mark should go
* @param mark {string}- type of mark that should go above annotation
*/
Diacritics.prototype.putMarkAtLocation = function (annotation, mark){
var loc = this.getPos(annotation.highlights[0]);
var alignment = this.diacriticmarks[mark][1];
var imgurl = this.diacriticmarks[mark][0];

var top;
switch(alignment){
case 'top':
top = (loc.y-5);
break;
case 'bottom':
top = (loc.y + loc.height-5);
break;
default:
top = loc.y;
}
$('<div></div>').addClass('mark ' + annotation.id).css({
'top': top,
'left': loc.x + (0.5 * loc.width) - 5,
'background-image': 'url(' + imgurl +')',
}).appendTo('.annotator-wrapper');
};

/**
* Gets the Diacritics from the instantiation in studio
* @returns An object with the diacritics instantiated
*/
Diacritics.prototype.getDiacritics = function(){
var diacritics = {};
var diacriticsList;
if(typeof this.options.diacritics != 'undefined'){
diacriticsList = this.options.diacritics.split(",");
$.each(diacriticsList, function(key, item){
var temp = item.split(";");
if (temp.length > 2) {
diacritics[temp[0]] = [temp[1], temp[2]];
}
});
}
return diacritics;
};

/**
* Gets the position of a specific element given the wrapper
* @param el {Object} - element you are trying to get the position of
*/
Diacritics.prototype.getPos = function(el) {
var element = $(el),
elementOffset = element.offset(),
annotatorOffset = $('.annotator-wrapper').offset();

return {
x: elementOffset.left - annotatorOffset.left,
y: elementOffset.top - annotatorOffset.top,
width: element.width(),
height: element.height()
};
};

/**
* Redraws the marks above annotations by cycling through tags
*/
Diacritics.prototype.updateDiacritics = function(){
$('.mark').remove();
var annotations = this.annotator.plugins.Store.annotations;
var self = this;
$.each(annotations, function(key, annotation){
$.each(self.diacriticmarks, function(tag){
if($.inArray(tag, annotation.tags) != -1){
self.putMarkAtLocation(annotation, tag);
}
});
});
};

/**
* Removes unnecessary field that Annotator automatically adds to popup
* @param {Object} field - the html element that represents the popup
* @param {Object} annotation - the annotation element that holds metadata
*/
Diacritics.prototype.updateViewer = function(field, annotation){
$(field).remove();
};

/**
* Function for adding Diacritic choices to the annotator popup
* @param {Object} field - the html element that represents the popup
* @param {Object} annotation - the annotation element that holds metadata
*/
Diacritics.prototype.updateEditorForDiacritics =
function(field, annotation){

// if no tags are present, no need to go through this
if (typeof annotation.tags == 'undefined'){
return;
}

var inputItems = $(this.field).find(':input');
var dictOfItems = {};
var self = this;

// add each diacritic mark to a dictionary and default to off
$.each(inputItems, function(key,item){
item.checked = false;
dictOfItems[item.placeholder] = item;
});

// match tags to diacritics and check off the ones that are true
$.each(annotation.tags, function(key,tag){
if(self.diacriticmarks[tag]){
dictOfItems[tag].checked = true;
}
});
};

return Diacritics;

})(Annotator.Plugin);
Loading

0 comments on commit 31274a5

Please sign in to comment.