/// (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);