///
(function($) {
var _posCount = 1;
var _page;
/**
* Creates annotations on the given image.
* Images are loaded from the "getUrl" propety
* passed into the options.
**/
$.fn.annotateImage = function(options) {
var opts = $.extend({}, $.fn.annotateImage.defaults, options);
var image = this;
this.image = this;
this.mode = 'view';
// Assign defaults
this.getUrl = opts.getUrl;
this.saveUrl = opts.saveUrl;
this.deleteUrl = opts.deleteUrl;
this.editable = opts.editable;
this.useAjax = opts.useAjax;
this.notes = opts.notes;
_page = opts.page;
//With paged document images, the width and height are not being read, hence the addition of these if statements.
if(this.width() == 0 && opts.width !== undefined)
this.width(opts.width);
if(this.height() == 0 && opts.width !== undefined)
this.height(opts.height);
//get the last ID number and set _posCount to be the next number.
if(this.notes !== null && this.notes !== undefined){
if(this.notes.length > 0){
var lastId = this.notes[this.notes.length-1].id;
if(lastId != null && lastId !== undefined)
_posCount = lastId + 1;
}
}
// Add the canvas
this.canvas = $('
');
this.canvas.children('.image-annotate-edit').hide();
this.canvas.children('.image-annotate-view').hide();
this.image.after(this.canvas);
// Give the canvas and the container their size and background
this.canvas.height(this.height());
this.canvas.width(this.width());
this.canvas.css('background-image', 'url("' + this.attr('src') + '")');
this.canvas.children('.image-annotate-view, .image-annotate-edit').height(this.height());
this.canvas.children('.image-annotate-view, .image-annotate-edit').width(this.width());
// Add the behavior: hide/show the notes when hovering the picture
this.canvas.hover(function() {
if ($(this).children('.image-annotate-edit').css('display') == 'none') {
$(this).children('.image-annotate-view').show();
}
}, function() {
$(this).children('.image-annotate-view').hide();
});
this.canvas.children('.image-annotate-view').hover(function() {
$(this).show();
}, function() {
$(this).hide();
});
// load the notes
if (this.useAjax) {
$.fn.annotateImage.ajaxLoad(this);
} else {
$.fn.annotateImage.load(this);
}
// Add the "Add a note" button
if (this.editable) {
this.button = $('');
this.button.click(function() {
$.fn.annotateImage.add(image);
});
//this.canvas.after(this.button);
this.br = $(' ');
this.canvas.before(this.button);
this.canvas.before(this.br);
}
// Hide the original image
this.hide();
return this;
};
/**
* Plugin Defaults
**/
$.fn.annotateImage.defaults = {
getUrl: 'cgi-bin/metadata-server.pl?a=get-metadata&site=' + gs.xsltParams.site_name + '&c=' + gs.cgiParams.c + '&d=' + gs.cgiParams.d + '&metaname=gsimg.Annotation',
saveUrl: 'cgi-bin/metadata-server.pl?a=insert-metadata&site=' + gs.xsltParams.site_name + '&c=' + gs.cgiParams.c + '&d=' + gs.cgiParams.d + '&metaname=gsimg.Annotation&metamode=accumulate&metavalue=',
deleteUrl: 'cgi-bin/metadata-server.pl?a=remove-metadata&site=' + gs.xsltParams.site_name + '&c=' + gs.cgiParams.c + '&d=' + gs.cgiParams.d + '&metaname=gsimg.Annotation&metamode=override&metavalue=' + 'testing',
editable: true,
useAjax: true,
notes: new Array(),
page: 0 //TODO: use this to annotate correct image when dealing with GSDL paged documents//
};
/**
* Clears all existing annotations from the image.
**/
$.fn.annotateImage.clear = function(image) {
for (var i = 0; i < image.notes.length; i++) {
image.notes[image.notes[i]].destroy();
}
image.notes = new Array();
};
/**
* Loads the annotations from the "getUrl" property passed in on the options object.
**/
$.fn.annotateImage.ajaxLoad = function(image) {
$.fn.annotateImage.load(image);
};
/**
* Loads the annotations from the notes property
* passed in on the options object (this method is
* only used if "useAjax" is set to false.
**/
$.fn.annotateImage.load = function(image) {
if(image.notes === undefined || image.notes === null){
console.log("No annotations to load in.");
image.notes = new Array();
}else{
if(image.notes.length > 0){
for (var i = 0; i < image.notes.length; i++) {
image.notes[image.notes[i]] = new $.fn.annotateView(image, image.notes[i]);
}
}else{
console.log("No annotations to load in.");
}
}
};
/**
* Gets a count of the ticks for the current date.
* This is used to ensure that URLs are always
* unique and not cached by the browser.
**/
$.fn.annotateImage.getTicks = function() {
var now = new Date();
return now.getTime();
};
/**
* Adds a note to the image.
**/
$.fn.annotateImage.add = function(image) {
console.log("image mode = " + image.mode);
if (image.mode == 'view') {
image.mode = 'edit';
gs.userInformation.currentAction = "editingNote";
// Create/prepare the editable note elements
var editable = new $.fn.annotateEdit(image);
$.fn.annotateImage.createSaveButton(editable, image);
$.fn.annotateImage.createCancelButton(editable, image);
}
};
/**
*Creates an OK button on the editable note.
**/
$.fn.annotateImage.createSaveButton = function(editable, image, note, prev) {
var ok = $('OK');
ok.click(function() {
gs.userInformation.currentAction = "savingNote";
var form = $('#image-annotate-edit-form form');
var text = $('#image-annotate-text').val();
$.fn.annotateImage.appendPosition(form, editable)
image.mode = 'view';
// Save via AJAX
if (image.useAjax) {
var left_pos = editable.area.position().left;
var top_pos = editable.area.position().top;
var width = editable.area.width();
var height = editable.area.height();
var id = editable.note.id;
//var page = editable.note.page;
console.log(editable.note);
//var json = '{ "top": ' + top_pos + ', "left": ' + left_pos + ', "width": ' + width + ', "height": ' + height + ', "text": "' + text + '", "id": ' + id + ', "editable": true }';
var json = '{ "top": ' + top_pos + ', "left": ' + left_pos + ', "width": ' + width + ', "height": ' + height + ', "text": "' + text + '", "id": ' + id + ', "editable": true, "page": ' + _page + ' }';
var metaname = "gsimg.Annotation";
var metadata_server_url = "cgi-bin/metadata-server.pl?";
var saveIndexUrl = metadata_server_url + "a=set-metadata&site=" + gs.xsltParams.site_name + "&c=" + gs.cgiParams.c + "&d=" + gs.cgiParams.d + "&metaname=" + metaname + "&metavalue=" + json;
var saveArchivesUrl = metadata_server_url + "a=set-archives-metadata&site=" + gs.xsltParams.site_name + "&c=" + gs.cgiParams.c + "&d=" + gs.cgiParams.d + "&metaname=" + metaname + "&metavalue=" + json;
var saveImportUrl = metadata_server_url + "a=set-import-metadata&site=" + gs.xsltParams.site_name + "&c=" + gs.cgiParams.c + "&d=" + gs.cgiParams.d + "&metaname=" + metaname + "&metavalue=" + json;
if(prev !== undefined && prev !== null)
{
var prevJson = '{ "top": ' + prev.top + ', "left": ' + prev.left + ', "width": ' + prev.width + ', "height": ' + height + ', "text": "' + prev.text + '", "id": ' + prev.id + ', "editable": true, "page": ' + _page + ' }';
saveIndexUrl += "&prevmetavalue=" + prevJson + "&metamode=override";
saveArchivesUrl += "&prevmetavalue=" + prevJson + "&metamode=override";
saveImportUrl += "&prevmetavalue=" + prevJson + "&metamode=override";
}
var saveIndexCallBack = {
success: function(response)
{
YAHOO.util.Connect.asyncRequest("GET", gs.xsltParams.library_name + "?a=s&sa=c&c=" + gs.cgiParams.c, null);
console.log("Save index metata successful! Note id: " + id);
},
failed: function(response){ console.log("Failed to save index metadata of note with id: " + id);}
};
var saveImportCallBack =
{
sucess: function(response){ console.log("Save import metdata successful! Note id: " + id);},
failed: function(response){console.log("Failed in save import metadata of note with id: " + id);}
};
var saveArchivesCallBack = {
success: function(response){
//apparently should rebuild collection here.
console.log("Save archives metadata successful! Note id: " + id);
},
failed: function(response){
console.log("Failed to save archives metadata of note with id: " + id);
}
};
YAHOO.util.Connect.asyncRequest("GET",saveIndexUrl,saveIndexCallBack);
YAHOO.util.Connect.asyncRequest("GET",saveArchivesUrl,saveArchivesUrl);
YAHOO.util.Connect.asyncRequest("GET",saveImportUrl,saveImportCallBack);
}
// Add to canvas
if (note) {
note.resetPosition(editable, text);
} else {
editable.note.editable = true;
note = new $.fn.annotateView(image, editable.note);
note.resetPosition(editable, text);
image.notes.push(editable.note);
}
editable.destroy();
});
editable.form.append(ok);
};
/**
* Creates a cancel button on the editable note.
**/
$.fn.annotateImage.createCancelButton = function(editable, image) {
var cancel = $('Cancel');
cancel.click(function() {
editable.destroy();
image.mode = 'view';
});
editable.form.append(cancel);
};
$.fn.annotateImage.saveAsHtml = function(image, target) {
var element = $(target);
var html = "";
for (var i = 0; i < image.notes.length; i++) {
html += $.fn.annotateImage.createHiddenField("text_" + i, image.notes[i].text);
html += $.fn.annotateImage.createHiddenField("top_" + i, image.notes[i].top);
html += $.fn.annotateImage.createHiddenField("left_" + i, image.notes[i].left);
html += $.fn.annotateImage.createHiddenField("height_" + i, image.notes[i].height);
html += $.fn.annotateImage.createHiddenField("width_" + i, image.notes[i].width);
}
element.html(html);
};
$.fn.annotateImage.createHiddenField = function(name, value) {
return '<input type="hidden" name="' + name + '" value="' + value + '" /> ';
};
/**
* Defines an editable annotation area.
**/
$.fn.annotateEdit = function(image, note) {
this.image = image;
if (note) {
this.note = note;
} else {
var newNote = new Object();
newNote.id = _posCount;
_posCount++;
newNote.top = 30;
newNote.left = 30;
newNote.width = 30;
newNote.height = 30;
newNote.text = "";
newNote.page = _page;
this.note = newNote;
}
// Set area
var area = image.canvas.children('.image-annotate-edit').children('.image-annotate-edit-area');
this.area = area;
this.area.css('height', this.note.height + 'px');
this.area.css('width', this.note.width + 'px');
this.area.css('left', this.note.left + 'px');
this.area.css('top', this.note.top + 'px');
// Show the edition canvas and hide the view canvas
image.canvas.children('.image-annotate-view').hide();
image.canvas.children('.image-annotate-edit').show();
// Add the note (which we'll load with the form afterwards)
var form = $('');
this.form = form;
$('body').append(this.form);
this.form.css('left', this.area.offset().left + 'px');
this.form.css('top', (parseInt(this.area.offset().top) + parseInt(this.area.height()) + 7) + 'px');
// Set the area as a draggable/resizable element contained in the image canvas.
// Would be better to use the containment option for resizable but buggy
area.resizable({
handles: 'all',
resize: function(e, ui) {
form.css('left', area.offset().left + 'px');
form.css('top', (parseInt(area.offset().top) + parseInt(area.height()) + 2) + 'px');
},
stop: function(e, ui) {
form.css('left', area.offset().left + 'px');
form.css('top', (parseInt(area.offset().top) + parseInt(area.height()) + 2) + 'px');
}
})
.draggable({
containment: image.canvas,
drag: function(e, ui) {
form.css('left', area.offset().left + 'px');
form.css('top', (parseInt(area.offset().top) + parseInt(area.height()) + 2) + 'px');
},
stop: function(e, ui) {
form.css('left', area.offset().left + 'px');
form.css('top', (parseInt(area.offset().top) + parseInt(area.height()) + 2) + 'px');
}
});
return this;
};
/**
* Destroys an editable annotation area.
**/
$.fn.annotateEdit.prototype.destroy = function() {
this.image.canvas.children('.image-annotate-edit').hide();
this.area.resizable('destroy');
this.area.draggable('destroy');
this.area.css('height', '');
this.area.css('width', '');
this.area.css('left', '');
this.area.css('top', '');
this.form.remove();
}
/**
* Defines an annotation area.
**/
$.fn.annotateView = function(image, note) {
this.image = image;
this.note = note;
this.editable = (note.editable && image.editable);
// Add the area
this.area = $('
');
image.canvas.children('.image-annotate-view').prepend(this.area);
// Add the note
this.form = $('
' + note.text + '
');
this.form.hide();
image.canvas.children('.image-annotate-view').append(this.form);
this.form.children('span.actions').hide();
// Set the position and size of the note
this.setPosition();
// Add the behavior: hide/display the note when hovering the area
var annotation = this;
this.area.hover(function() {
annotation.show();
}, function() {
annotation.hide();
});
// Edit a note feature
if (this.editable) {
var form = this;
this.area.click(function() {
form.edit();
});
}
};
$.fn.annotateView.prototype.setPosition = function() {
///
/// Sets the position of an annotation.
///
this.area.children('div').height((parseInt(this.note.height) - 2) + 'px');
this.area.children('div').width((parseInt(this.note.width) - 2) + 'px');
this.area.css('left', (this.note.left) + 'px');
this.area.css('top', (this.note.top) + 'px');
this.form.css('left', (this.note.left) + 'px');
this.form.css('top', (parseInt(this.note.top) + parseInt(this.note.height) + 7) + 'px');
};
$.fn.annotateView.prototype.show = function() {
///
/// Highlights the annotation
///
this.form.fadeIn(250);
if (!this.editable) {
this.area.addClass('image-annotate-area-hover');
} else {
this.area.addClass('image-annotate-area-editable-hover');
}
};
/**
* Removes the highlight from the annotation.
**/
$.fn.annotateView.prototype.hide = function() {
this.form.fadeOut(250);
this.area.removeClass('image-annotate-area-hover');
this.area.removeClass('image-annotate-area-editable-hover');
};
/**
* Destroys the annotation.
**/
$.fn.annotateView.prototype.destroy = function() {
this.area.remove();
this.form.remove();
}
/**
* Edits the annotation.
**/
$.fn.annotateView.prototype.edit = function() {
if (this.image.mode == 'view') {
this.image.mode = 'edit';
var annotation = this;
//Save the previous note (before the edit was made).
var storePrevNotes = this.image.notes;
console.log("this note's id: " + this.note.id);
var prev = null;
for(var i = 0; i < storePrevNotes.length; i++){
var curr = storePrevNotes[i];
if(curr.id == this.note.id){
prev = curr;
}
}
// Create/prepare the editable note elements
var editable = new $.fn.annotateEdit(this.image, this.note);
$.fn.annotateImage.createSaveButton(editable, this.image, annotation,prev);
// Add the delete button
var del = $('Delete');
del.click(function() {
var form = $('#image-annotate-edit-form form');
$.fn.annotateImage.appendPosition(form, editable)
if (annotation.image.useAjax) {
var left_pos = annotation.note.left;
var top_pos = annotation.note.top;
var width = annotation.note.width;
var height = annotation.note.height;
var id = annotation.note.id;
var text = annotation.note.text;
//var page = annotation.note.page;
var json = '{ "top": ' + top_pos + ', "left": ' + left_pos + ', "width": ' + width + ', "height": ' + height + ', "text": "' + text + '", "id": ' + id + ', "editable": true ' + ', "page": ' + _page + ' }';
var metaposVal = id-1;
//make below variables global...
var metaname = "gsimg.Annotation";
var metadata_server_url = "cgi-bin/metadata-server.pl?";
var removeFromIndexUrl = metadata_server_url + "a=remove-metadata&site=" + gs.xsltParams.site_name + "&c=" + gs.cgiParams.c + "&d=" + gs.cgiParams.d + "&metaname=" + metaname + "&metavalue=" + json + "&metapos=" + metaposVal;
var removeFromArchivesUrl = metadata_server_url + "a=remove-archives-metadata&site=" + gs.xsltParams.site_name + "&c=" + gs.cgiParams.c + "&d=" + gs.cgiParams.d + "&metaname=" + metaname + "&metavalue=" + json + "&metapos=" + metaposVal;
var removeFromImportUrl = metadata_server_url + "a=remove-import-metadata&site=" + gs.xsltParams.site_name + "&c=" + gs.cgiParams.c + "&d=" + gs.cgiParams.d + "&metaname=" + metaname + "&metavalue=" + json;
var indexCallBack = {
success: function(response){
//need to renumber ids so that the correct note is deleted next time
for(var i = 0; i < annotation.image.notes.length; i++)
{
var currNote = annotation.image.notes[i];
if(currNote.id > id)
currNote.id--;
}
//_posCount--;
console.log("Index metadata successfully removed. Note id: " + id);
},
failed: function(){
console.log("Failed to delete index metadata of note with id: " + id);
}
};
var archiveCallBack = {
success: function(response){
//need to rebuild collection here.
console.log("Metadata successfully removed from archives. Note id: " + id);
},
failed: function(){
console.log("Failed to remove metadata from archives. Note id: " + id);
}
};
var importCallBack = {
success: function(){},
failed: function(){ alert("Failed to delete import metadata of note with id: " + id);}
};
YAHOO.util.Connect.asyncRequest("GET",removeFromIndexUrl,indexCallBack);
YAHOO.util.Connect.asyncRequest("GET",removeFromArchivesUrl,archiveCallBack);
YAHOO.util.Connect.asyncRequest("GET",removeFromImportUrl,importCallBack);
}
annotation.image.mode = 'view';
editable.destroy();
annotation.destroy();
});
editable.form.append(del);
$.fn.annotateImage.createCancelButton(editable, this.image);
}
};
/**
* Appends the annotations coordinates to the given form that is posted to the server.
**/
$.fn.annotateImage.appendPosition = function(form, editable) {
var areaFields = $('' +
'' +
'' +
'' +
'');
form.append(areaFields);
}
/**
* Sets the position of an annotation.
**/
$.fn.annotateView.prototype.resetPosition = function(editable, text) {
this.form.html(text);
this.form.hide();
// Resize
this.area.children('div').height(editable.area.height() + 'px');
this.area.children('div').width((editable.area.width() - 2) + 'px');
this.area.css('left', (editable.area.position().left) + 'px');
this.area.css('top', (editable.area.position().top) + 'px');
this.form.css('left', (editable.area.position().left) + 'px');
this.form.css('top', (parseInt(editable.area.position().top) + parseInt(editable.area.height()) + 7) + 'px');
// Save new position to note
this.note.top = editable.area.position().top;
this.note.left = editable.area.position().left;
this.note.height = editable.area.height();
this.note.width = editable.area.width();
this.note.text = text;
this.note.id = editable.note.id;
this.editable = true;
};
})(jQuery);