| | |
| | (function($) { |
| |
|
| | $.fn.annotateImage = function(options) { |
| | |
| | |
| | |
| | |
| | var opts = $.extend({}, $.fn.annotateImage.defaults, options); |
| | var image = this; |
| |
|
| | this.image = this; |
| | this.mode = 'view'; |
| |
|
| | |
| | this.getUrl = opts.getUrl; |
| | this.saveUrl = opts.saveUrl; |
| | this.deleteUrl = opts.deleteUrl; |
| | this.editable = opts.editable; |
| | this.useAjax = opts.useAjax; |
| | this.notes = opts.notes; |
| |
|
| | |
| | this.canvas = $('<div class="image-annotate-canvas"><div class="image-annotate-view"></div><div class="image-annotate-edit"><div class="image-annotate-edit-area"></div></div></div>'); |
| | this.canvas.children('.image-annotate-edit').hide(); |
| | this.canvas.children('.image-annotate-view').hide(); |
| | this.image.after(this.canvas); |
| |
|
| | |
| | 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()); |
| |
|
| | |
| | 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(); |
| | }); |
| |
|
| | |
| | if (this.useAjax) { |
| | $.fn.annotateImage.ajaxLoad(this); |
| | } else { |
| | $.fn.annotateImage.load(this); |
| | } |
| |
|
| | |
| | if (this.editable) { |
| | this.button = $('<a class="image-annotate-add" id="image-annotate-add" href="#">Add Note</a>'); |
| | this.button.click(function() { |
| | $.fn.annotateImage.add(image); |
| | }); |
| | this.canvas.after(this.button); |
| | } |
| |
|
| | |
| | this.hide(); |
| |
|
| | return this; |
| | }; |
| |
|
| | |
| | |
| | |
| | $.fn.annotateImage.defaults = { |
| | getUrl: 'your-get.rails', |
| | saveUrl: 'your-save.rails', |
| | deleteUrl: 'your-delete.rails', |
| | editable: true, |
| | useAjax: true, |
| | notes: new Array() |
| | }; |
| |
|
| | $.fn.annotateImage.clear = function(image) { |
| | |
| | |
| | |
| | for (var i = 0; i < image.notes.length; i++) { |
| | image.notes[image.notes[i]].destroy(); |
| | } |
| | image.notes = new Array(); |
| | }; |
| |
|
| | $.fn.annotateImage.ajaxLoad = function(image) { |
| | |
| | |
| | |
| | |
| | $.getJSON(image.getUrl + '?ticks=' + $.fn.annotateImage.getTicks(), function(data) { |
| | image.notes = data; |
| | $.fn.annotateImage.load(image); |
| | }); |
| | }; |
| |
|
| | $.fn.annotateImage.load = function(image) { |
| | |
| | |
| | |
| | |
| | for (var i = 0; i < image.notes.length; i++) { |
| | image.notes[image.notes[i]] = new $.fn.annotateView(image, image.notes[i]); |
| | } |
| | }; |
| |
|
| | $.fn.annotateImage.getTicks = function() { |
| | |
| | |
| | |
| | |
| | var now = new Date(); |
| | return now.getTime(); |
| | }; |
| |
|
| | $.fn.annotateImage.add = function(image) { |
| | |
| | |
| | |
| | if (image.mode == 'view') { |
| | image.mode = 'edit'; |
| |
|
| | |
| | var editable = new $.fn.annotateEdit(image); |
| |
|
| | $.fn.annotateImage.createSaveButton(editable, image); |
| | $.fn.annotateImage.createCancelButton(editable, image); |
| | } |
| | }; |
| |
|
| | $.fn.annotateImage.createSaveButton = function(editable, image, note) { |
| | |
| | |
| | |
| | var ok = $('<a class="image-annotate-edit-ok">OK</a>'); |
| |
|
| | ok.click(function() { |
| | var form = $('#image-annotate-edit-form form'); |
| | var text = $('#image-annotate-text').val(); |
| | $.fn.annotateImage.appendPosition(form, editable) |
| | image.mode = 'view'; |
| |
|
| | |
| | if (image.useAjax) { |
| | $.ajax({ |
| | url: image.saveUrl, |
| | data: form.serialize(), |
| | error: function(e) { alert("An error occured saving that note.") }, |
| | success: function(data) { |
| | if (data.annotation_id != undefined) { |
| | editable.note.id = data.annotation_id; |
| | } |
| | }, |
| | dataType: "json" |
| | }); |
| | } |
| |
|
| | |
| | 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); |
| | }; |
| |
|
| | $.fn.annotateImage.createCancelButton = function(editable, image) { |
| | |
| | |
| | |
| | var cancel = $('<a class="image-annotate-edit-close">Cancel</a>'); |
| | 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 + '" /><br />'; |
| | }; |
| |
|
| | $.fn.annotateEdit = function(image, note) { |
| | |
| | |
| | |
| | this.image = image; |
| |
|
| | if (note) { |
| | this.note = note; |
| | } else { |
| | var newNote = new Object(); |
| | newNote.id = "new"; |
| | newNote.top = 30; |
| | newNote.left = 30; |
| | newNote.width = 30; |
| | newNote.height = 30; |
| | newNote.text = ""; |
| | this.note = newNote; |
| | } |
| |
|
| | |
| | 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'); |
| |
|
| | |
| | image.canvas.children('.image-annotate-view').hide(); |
| | image.canvas.children('.image-annotate-edit').show(); |
| |
|
| | |
| | var form = $('<div id="image-annotate-edit-form"><form><textarea id="image-annotate-text" name="text" rows="3" cols="30">' + this.note.text + '</textarea></form></div>'); |
| | 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'); |
| |
|
| | |
| | |
| | area.resizable({ |
| | handles: 'all', |
| |
|
| | 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; |
| | }; |
| |
|
| | $.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(); |
| | } |
| |
|
| | $.fn.annotateView = function(image, note) { |
| | |
| | |
| | |
| | this.image = image; |
| |
|
| | this.note = note; |
| |
|
| | this.editable = (note.editable && image.editable); |
| |
|
| | |
| | this.area = $('<div class="image-annotate-area' + (this.editable ? ' image-annotate-area-editable' : '') + '"><div></div></div>'); |
| | image.canvas.children('.image-annotate-view').prepend(this.area); |
| |
|
| | |
| | this.form = $('<div class="image-annotate-note">' + note.text + '</div>'); |
| | this.form.hide(); |
| | image.canvas.children('.image-annotate-view').append(this.form); |
| | this.form.children('span.actions').hide(); |
| |
|
| | |
| | this.setPosition(); |
| |
|
| | |
| | var annotation = this; |
| | this.area.hover(function() { |
| | annotation.show(); |
| | }, function() { |
| | annotation.hide(); |
| | }); |
| |
|
| | |
| | if (this.editable) { |
| | var form = this; |
| | this.area.click(function() { |
| | form.edit(); |
| | }); |
| | } |
| | }; |
| |
|
| | $.fn.annotateView.prototype.setPosition = function() { |
| | |
| | |
| | |
| | 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() { |
| | |
| | |
| | |
| | this.form.fadeIn(250); |
| | if (!this.editable) { |
| | this.area.addClass('image-annotate-area-hover'); |
| | } else { |
| | this.area.addClass('image-annotate-area-editable-hover'); |
| | } |
| | }; |
| |
|
| | $.fn.annotateView.prototype.hide = function() { |
| | |
| | |
| | |
| | this.form.fadeOut(250); |
| | this.area.removeClass('image-annotate-area-hover'); |
| | this.area.removeClass('image-annotate-area-editable-hover'); |
| | }; |
| |
|
| | $.fn.annotateView.prototype.destroy = function() { |
| | |
| | |
| | |
| | this.area.remove(); |
| | this.form.remove(); |
| | } |
| |
|
| | $.fn.annotateView.prototype.edit = function() { |
| | |
| | |
| | |
| | if (this.image.mode == 'view') { |
| | this.image.mode = 'edit'; |
| | var annotation = this; |
| |
|
| | |
| | var editable = new $.fn.annotateEdit(this.image, this.note); |
| |
|
| | $.fn.annotateImage.createSaveButton(editable, this.image, annotation); |
| |
|
| | |
| | var del = $('<a class="image-annotate-edit-delete">Delete</a>'); |
| | del.click(function() { |
| | var form = $('#image-annotate-edit-form form'); |
| |
|
| | $.fn.annotateImage.appendPosition(form, editable) |
| |
|
| | if (annotation.image.useAjax) { |
| | $.ajax({ |
| | url: annotation.image.deleteUrl, |
| | data: form.serialize(), |
| | error: function(e) { alert("An error occured deleting that note.") } |
| | }); |
| | } |
| |
|
| | annotation.image.mode = 'view'; |
| | editable.destroy(); |
| | annotation.destroy(); |
| | }); |
| | editable.form.append(del); |
| |
|
| | $.fn.annotateImage.createCancelButton(editable, this.image); |
| | } |
| | }; |
| |
|
| | $.fn.annotateImage.appendPosition = function(form, editable) { |
| | |
| | |
| | |
| | var areaFields = $('<input type="hidden" value="' + editable.area.height() + '" name="height"/>' + |
| | '<input type="hidden" value="' + editable.area.width() + '" name="width"/>' + |
| | '<input type="hidden" value="' + editable.area.position().top + '" name="top"/>' + |
| | '<input type="hidden" value="' + editable.area.position().left + '" name="left"/>' + |
| | '<input type="hidden" value="' + editable.note.id + '" name="id"/>'); |
| | form.append(areaFields); |
| | } |
| |
|
| | $.fn.annotateView.prototype.resetPosition = function(editable, text) { |
| | |
| | |
| | |
| | this.form.html(text); |
| | this.form.hide(); |
| |
|
| | |
| | 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'); |
| |
|
| | |
| | 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); |