diff --git a/public_html/css/core.css b/public_html/css/core.css index dfea8d91..cc58fbf1 100644 --- a/public_html/css/core.css +++ b/public_html/css/core.css @@ -99,3 +99,16 @@ blockquote { blockquote :last-child { margin-bottom: 0; } + +.draggable { + cursor: move; +} +.resizer { + position: absolute; + cursor: nwse-resize; + border: 0.25em solid rgba(0, 0, 0, 0.3); + border-top: 0.25em solid transparent; + border-left: 0.25em solid transparent; + right: 0; + bottom: 0; +} diff --git a/public_html/css/post.css b/public_html/css/post.css index 11993247..dde83597 100644 --- a/public_html/css/post.css +++ b/public_html/css/post.css @@ -195,7 +195,7 @@ .post-note-edit { pointer-events: auto; display: none; - position: fixed; + position: absolute; z-index: 3; background: white; border: 1px solid black; @@ -206,8 +206,13 @@ .post-note-edit textarea { width: 20em; height: 5em; + display: block; } .post-note-edit .actions { + pointer-events: none; +} +.post-note-edit button { + pointer-events: auto; margin-top: 0.5em; } .post-note-edit .actions button:not(:last-child) { @@ -247,19 +252,3 @@ .post-note .text p:last-of-type { margin-bottom: 0; } - -.post-note .dragger { - position: absolute; - width: 100%; - height: 100%; - cursor: move; -} -.post-note .resizer { - position: absolute; - cursor: nwse-resize; - border: 0.25em solid rgba(0, 0, 0, 0.3); - border-top: 0.25em solid transparent; - border-left: 0.25em solid transparent; - right: 0; - bottom: 0; -} diff --git a/public_html/index.html b/public_html/index.html index 17bc7fd2..4104bf5a 100644 --- a/public_html/index.html +++ b/public_html/index.html @@ -100,7 +100,9 @@ - + + + diff --git a/public_html/js/Presenters/PostNotesPresenter.js b/public_html/js/Presenters/PostNotesPresenter.js index 546b6012..545be550 100644 --- a/public_html/js/Presenters/PostNotesPresenter.js +++ b/public_html/js/Presenters/PostNotesPresenter.js @@ -6,7 +6,9 @@ App.Presenters.PostNotesPresenter = function( util, promise, api, - auth) { + auth, + draggable, + resizable) { var post; var notes; @@ -59,8 +61,8 @@ App.Presenters.PostNotesPresenter = function( $postNote.data('postNote', postNote); $postNote.find('.text-wrapper').click(postNoteClicked); postNote.$element = $postNote; - makeDraggable($postNote); - makeResizable($postNote); + draggable.makeDraggable($postNote, draggable.relativeDragStrategy); + resizable.makeResizable($postNote); }); $form.find('button').click(formSubmitted); @@ -144,85 +146,13 @@ App.Presenters.PostNotesPresenter = function( $form.data('postNote', postNote); $form.find('textarea').val(postNote.text); $form.show(); + draggable.makeDraggable($form, draggable.absoluteDragStrategy); } function hideForm() { $form.hide(); } - function makeDraggable($element) { - var $dragger = jQuery('
'); - $element.prepend($dragger); - - $dragger.mousedown(function(e) { - e.preventDefault(); - $element.addClass('dragging'); - - var $parent = $element.parent(); - var deltaX = $element.offset().left - e.clientX; - var deltaY = $element.offset().top - e.clientY; - - var update = function(e) { - var x = e.clientX + deltaX - $parent.offset().left; - var y = e.clientY + deltaY - $parent.offset().top; - x = Math.min(Math.max(x, 0), $parent.outerWidth() - $element.outerWidth()); - y = Math.min(Math.max(y, 0), $parent.outerHeight() - $element.outerHeight()); - x *= 100.0 / $parent.outerWidth(); - y *= 100.0 / $parent.outerHeight(); - $element.css({ - left: x + '%', - top: y + '%'}); - }; - - jQuery(window).bind('mousemove.elemmove', function(e) { - update(e); - }).bind('mouseup.elemmove', function(e) { - e.preventDefault(); - update(e); - $element.removeClass('dragging'); - jQuery(window).unbind('mousemove.elemmove'); - jQuery(window).unbind('mouseup.elemmove'); - }); - }); - } - - function makeResizable($element) { - var $resizer = jQuery('
'); - $element.append($resizer); - - $resizer.mousedown(function(e) { - e.preventDefault(); - e.stopPropagation(); - $element.addClass('resizing'); - - var $parent = $element.parent(); - var deltaX = $element.width() - e.clientX; - var deltaY = $element.height() - e.clientY; - - var update = function(e) { - var w = e.clientX + deltaX; - var h = e.clientY + deltaY; - w = Math.min(Math.max(w, 20), $parent.outerWidth() + $parent.offset().left - $element.offset().left); - h = Math.min(Math.max(h, 20), $parent.outerHeight() + $parent.offset().top - $element.offset().top); - w *= 100.0 / $parent.outerWidth(); - h *= 100.0 / $parent.outerHeight(); - $element.css({ - width: w + '%', - height: h + '%'}); - }; - - jQuery(window).bind('mousemove.elemsize', function(e) { - update(e); - }).bind('mouseup.elemsize', function(e) { - e.preventDefault(); - update(e); - $element.removeClass('resizing'); - jQuery(window).unbind('mousemove.elemsize'); - jQuery(window).unbind('mouseup.elemsize'); - }); - }); - } - return { init: init, render: render, @@ -236,5 +166,7 @@ App.DI.register('postNotesPresenter', [ 'util', 'promise', 'api', - 'auth'], + 'auth', + 'draggable', + 'resizable'], App.Presenters.PostNotesPresenter); diff --git a/public_html/js/Util/Draggable.js b/public_html/js/Util/Draggable.js new file mode 100644 index 00000000..955e5ee4 --- /dev/null +++ b/public_html/js/Util/Draggable.js @@ -0,0 +1,84 @@ +var App = App || {}; +App.Util = App.Util || {}; + +App.Util.Draggable = function(jQuery) { + function relativeDragStrategy($element) { + var $parent = $element.parent(); + var delta; + + return { + click: function(e) { + delta = { + x: $element.offset().left - e.clientX, + y: $element.offset().top - e.clientY, + }; + }, + + update: function(e) { + var x = e.clientX + delta.x - $parent.offset().left; + var y = e.clientY + delta.y - $parent.offset().top; + x = Math.min(Math.max(x, 0), $parent.outerWidth() - $element.outerWidth()); + y = Math.min(Math.max(y, 0), $parent.outerHeight() - $element.outerHeight()); + x *= 100.0 / $parent.outerWidth(); + y *= 100.0 / $parent.outerHeight(); + $element.css({ + left: x + '%', + top: y + '%'}); + }, + }; + } + + function absoluteDragStrategy($element) { + var delta; + + return { + click: function(e) { + delta = { + x: $element.position().left - e.clientX, + y: $element.position().top - e.clientY, + }; + }, + + update: function(e) { + var x = e.clientX + delta.x; + var y = e.clientY + delta.y; + $element.css({ + left: x + 'px', + top: y + 'px'}); + }, + }; + } + + function makeDraggable($element, dragStrategy) { + var strategy = dragStrategy($element); + + $element.addClass('draggable'); + $element.mousedown(function(e) { + if (e.target !== $element.get(0)) { + return; + } + e.preventDefault(); + $element.addClass('dragging'); + + strategy.click(e); + jQuery(window).bind('mousemove.elemmove', function(e) { + strategy.update(e); + }).bind('mouseup.elemmove', function(e) { + e.preventDefault(); + strategy.update(e); + $element.removeClass('dragging'); + jQuery(window).unbind('mousemove.elemmove'); + jQuery(window).unbind('mouseup.elemmove'); + }); + }); + } + + return { + makeDraggable: makeDraggable, + absoluteDragStrategy: absoluteDragStrategy, + relativeDragStrategy: relativeDragStrategy, + }; + +}; + +App.DI.registerSingleton('draggable', ['jQuery'], App.Util.Draggable); diff --git a/public_html/js/Util.js b/public_html/js/Util/Misc.js similarity index 98% rename from public_html/js/Util.js rename to public_html/js/Util/Misc.js index daa9b422..a4374036 100644 --- a/public_html/js/Util.js +++ b/public_html/js/Util/Misc.js @@ -1,6 +1,7 @@ var App = App || {}; +App.Util = App.Util || {}; -App.Util = function(_, jQuery, marked, promise) { +App.Util.Misc = function(_, jQuery, marked, promise) { var exitConfirmationEnabled = false; @@ -244,4 +245,4 @@ App.Util = function(_, jQuery, marked, promise) { }; -App.DI.registerSingleton('util', ['_', 'jQuery', 'marked', 'promise'], App.Util); +App.DI.registerSingleton('util', ['_', 'jQuery', 'marked', 'promise'], App.Util.Misc); diff --git a/public_html/js/Util/Resizable.js b/public_html/js/Util/Resizable.js new file mode 100644 index 00000000..1d4240de --- /dev/null +++ b/public_html/js/Util/Resizable.js @@ -0,0 +1,48 @@ +var App = App || {}; +App.Util = App.Util || {}; + +App.Util.Resizable = function(jQuery) { + function makeResizable($element) { + var $resizer = jQuery('
'); + $element.append($resizer); + + $resizer.mousedown(function(e) { + e.preventDefault(); + e.stopPropagation(); + $element.addClass('resizing'); + + var $parent = $element.parent(); + var deltaX = $element.width() - e.clientX; + var deltaY = $element.height() - e.clientY; + + var update = function(e) { + var w = e.clientX + deltaX; + var h = e.clientY + deltaY; + w = Math.min(Math.max(w, 20), $parent.outerWidth() + $parent.offset().left - $element.offset().left); + h = Math.min(Math.max(h, 20), $parent.outerHeight() + $parent.offset().top - $element.offset().top); + w *= 100.0 / $parent.outerWidth(); + h *= 100.0 / $parent.outerHeight(); + $element.css({ + width: w + '%', + height: h + '%'}); + }; + + jQuery(window).bind('mousemove.elemsize', function(e) { + update(e); + }).bind('mouseup.elemsize', function(e) { + e.preventDefault(); + update(e); + $element.removeClass('resizing'); + jQuery(window).unbind('mousemove.elemsize'); + jQuery(window).unbind('mouseup.elemsize'); + }); + }); + } + + return { + makeResizable: makeResizable, + }; + +}; + +App.DI.registerSingleton('resizable', ['jQuery'], App.Util.Resizable);