Christian has uploaded a new change for review.
https://gerrit.wikimedia.org/r/69279
Change subject: RelocatableNode for Inline and Block Images
......................................................................
RelocatableNode for Inline and Block Images
HTML5's drag and drop has a ton of benefits an a couple
limitations. To achieve a native drag marker, an image tag helper
is used to indicate the size of the relocatable node. Chrome
shades the marker gray natively, Firefox is styled to match.
Change-Id: I755b698a3d968cc7e6ff125109d68ac83fd8a8a2
---
M modules/ve/ce/nodes/ve.ce.MWBlockImageNode.js
M modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
M modules/ve/ce/styles/ve.ce.Node.css
M modules/ve/ce/ve.ce.RelocatableNode.js
M modules/ve/ce/ve.ce.ResizableNode.js
M modules/ve/ce/ve.ce.Surface.js
6 files changed, 95 insertions(+), 23 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/79/69279/1
diff --git a/modules/ve/ce/nodes/ve.ce.MWBlockImageNode.js
b/modules/ve/ce/nodes/ve.ce.MWBlockImageNode.js
index 8ea8f73..c618052 100644
--- a/modules/ve/ce/nodes/ve.ce.MWBlockImageNode.js
+++ b/modules/ve/ce/nodes/ve.ce.MWBlockImageNode.js
@@ -26,6 +26,7 @@
ve.ce.ProtectedNode.call( this );
ve.ce.FocusableNode.call( this );
ve.ce.ResizableNode.call( this );
+ ve.ce.RelocatableNode.call( this );
if ( this.model.getAttribute( 'align' ) === 'center' ) {
this.$.addClass( 'center' );
@@ -83,6 +84,8 @@
ve.mixinClass( ve.ce.MWBlockImageNode, ve.ce.ResizableNode );
+ve.mixinClass( ve.ce.MWBlockImageNode, ve.ce.RelocatableNode );
+
/* Static Properties */
ve.ce.MWBlockImageNode.static.name = 'mwBlockImage';
diff --git a/modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
b/modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
index eb9e9f2..f373163 100644
--- a/modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
+++ b/modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
@@ -35,6 +35,7 @@
// Mixin constructors
ve.ce.ProtectedNode.call( this );
ve.ce.FocusableNode.call( this );
+ ve.ce.RelocatableNode.call( this );
this.$image
.attr( 'src', this.model.getAttribute( 'src' ) )
@@ -62,6 +63,8 @@
ve.mixinClass( ve.ce.MWInlineImageNode, ve.ce.FocusableNode );
+ve.mixinClass( ve.ce.MWInlineImageNode, ve.ce.RelocatableNode );
+
/* Static Properties */
ve.ce.MWInlineImageNode.static.name = 'mwInlineImage';
diff --git a/modules/ve/ce/styles/ve.ce.Node.css
b/modules/ve/ce/styles/ve.ce.Node.css
index e51f48b..6d61749 100644
--- a/modules/ve/ce/styles/ve.ce.Node.css
+++ b/modules/ve/ce/styles/ve.ce.Node.css
@@ -70,24 +70,17 @@
/* ve.ce.ResizableNode */
-.ve-ce-resizableNode-transitioning {
- -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out;
- -moz-transition: width 100ms ease-in-out, height 100ms ease-in-out;
- -ms-transition: width 100ms ease-in-out, height 100ms ease-in-out;
- -o-transition: width 100ms ease-in-out, height 100ms ease-in-out;
- transition: width 100ms ease-in-out, height 100ms ease-in-out;
-}
-
-.ve-ce-resizableNode-handles-resizing {
- z-index: 10000;
-}
-
.ve-ce-resizableNode-handles {
position: absolute;
box-shadow: inset 0 0 0 1px rgba(0,0,0,.25);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
+ z-index: 1; /* Position above RelocatableNode's relocatableMarker */
+}
+
+.ve-ce-resizableNode-handles.resizing {
+ z-index: 10000;
}
.ve-ce-resizableNode-handles div {
@@ -127,6 +120,17 @@
right: -0.33em;
}
+/* ve.ce.RelocatableNode */
+
+.ve-ce-relocatableMarker {
+ cursor: move;
+ position: absolute;
+}
+
+.ve-ce-relocatableMarker.relocating {
+ background: rgba(0,0,0,1);
+}
+
/* ve.ce.ImageNode */
.ve-ce-imageNode {
diff --git a/modules/ve/ce/ve.ce.RelocatableNode.js
b/modules/ve/ce/ve.ce.RelocatableNode.js
index b87950a..2e026c4 100644
--- a/modules/ve/ce/ve.ce.RelocatableNode.js
+++ b/modules/ve/ce/ve.ce.RelocatableNode.js
@@ -8,31 +8,71 @@
/**
* ContentEditable relocatable node.
*
+ * Requires that the node also is Focusable
+ *
* @class
* @abstract
*
* @constructor
- * @param {jQuery} [$draggable=this.$] Draggable DOM element
*/
-ve.ce.RelocatableNode = function VeCeRelocatableNode( $draggable ) {
+ve.ce.RelocatableNode = function VeCeRelocatableNode() {
// Properties
- this.$draggable = $draggable || this.$;
this.relocatingSurface = null;
+ this.$relocatableMarker = $('<img>');
// Events
- this.$draggable.on( {
- 'dragstart': ve.bind( this.onRelocatableDragStart, this ),
- 'dragend': ve.bind( this.onRelocatableDragEnd, this )
+ this.connect( this, {
+ 'focus': 'onRelocatableFocus',
+ 'blur': 'onRelocatableBlur',
+ 'resize': 'onRelocatableResize'
} );
+
+ // Initialization
+ this.$relocatableMarker
+ .addClass( 've-ce-relocatableMarker' )
+ .attr('src',
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==')
+ .on( {
+ 'dragstart': ve.bind( this.onRelocatableDragStart, this
),
+ 'dragend': ve.bind( this.onRelocatableDragEnd, this )
+ } );
};
+/* Static Properties */
+
/* Methods */
+
+/**
+ * Handle node focus.
+ *
+ * @method
+ */
+ve.ce.RelocatableNode.prototype.onRelocatableFocus = function () {
+ this.setRelocatableMarkerSizeAndPosition();
+ this.$relocatableMarker.appendTo(
this.root.getSurface().getSurface().$localOverlay );
+};
+
+/**
+ * Handle node blur.
+ *
+ * @method
+ */
+ve.ce.RelocatableNode.prototype.onRelocatableBlur = function () {
+ this.$relocatableMarker.detach();
+};
+
+/**
+ * Handle node resize.
+ *
+ * @method
+ */
+ve.ce.RelocatableNode.prototype.onRelocatableResize = function () {
+ this.setRelocatableMarkerSizeAndPosition();
+};
/**
* Handle element drag start.
*
* @method
- * @param {jQuery.Event} e Drag start event
*/
ve.ce.RelocatableNode.prototype.onRelocatableDragStart = function () {
// Store a copy of the surface, when dragend occurs the node will be
detached
@@ -42,17 +82,36 @@
// Allow dragging this node in the surface
this.relocatingSurface.startRelocation( this );
}
+ this.$relocatableMarker.addClass('relocating');
+
+ setTimeout( ve.bind( function () {
+ this.$relocatableMarker.css( { 'top': -10000, 'left': -10000 }
);
+ }, this ), 0 );
};
/**
* Handle element drag end.
*
* @method
- * @param {jQuery.Event} e Drag end event
*/
ve.ce.RelocatableNode.prototype.onRelocatableDragEnd = function () {
if ( this.relocatingSurface ) {
this.relocatingSurface.endRelocation();
this.relocatingSurface = null;
}
+ this.$relocatableMarker.removeClass('relocating');
+};
+
+/**
+ * Set the correct size and position of the relocatable marker.
+ *
+ * @method
+ */
+ve.ce.RelocatableNode.prototype.setRelocatableMarkerSizeAndPosition = function
() {
+ this.$relocatableMarker.css({
+ 'height': this.$.height(),
+ 'width': this.$.width(),
+ 'top': this.$.offset().top,
+ 'left': this.$.offset().left
+ });
};
diff --git a/modules/ve/ce/ve.ce.ResizableNode.js
b/modules/ve/ce/ve.ce.ResizableNode.js
index 36bb9a5..c2a8b69 100644
--- a/modules/ve/ce/ve.ce.ResizableNode.js
+++ b/modules/ve/ce/ve.ce.ResizableNode.js
@@ -125,7 +125,7 @@
// Set bounding box width and undo the handle margins
this.$resizeHandles
- .addClass( 've-ce-resizableNode-handles-resizing' )
+ .addClass( 'resizing' )
.css( {
'width': this.$resizable.width(),
'height': this.$resizable.height()
@@ -248,7 +248,7 @@
selection = surfaceModel.getSelection(),
attrChanges = {};
- this.$resizeHandles.removeClass( 've-ce-resizableNode-handles-resizing'
);
+ this.$resizeHandles.removeClass( 'resizing' );
$( this.getElementDocument() ).off( '.ve-ce-resizableNode' );
this.resizing = false;
diff --git a/modules/ve/ce/ve.ce.Surface.js b/modules/ve/ce/ve.ce.Surface.js
index 1fbea19..f0bc192 100644
--- a/modules/ve/ce/ve.ce.Surface.js
+++ b/modules/ve/ce/ve.ce.Surface.js
@@ -378,7 +378,10 @@
nodeRange = node.getModel().getOuterRange();
// Get a fragment from the drop point
- dropPoint = rangy.positionFromPoint(
e.originalEvent.pageX, e.originalEvent.pageY );
+ dropPoint = rangy.positionFromPoint(
+ e.originalEvent.pageX -
this.$document.scrollLeft(),
+ e.originalEvent.pageY -
this.$document.scrollTop()
+ );
if ( !dropPoint ) {
// Getting position from point supported
return false;
--
To view, visit https://gerrit.wikimedia.org/r/69279
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I755b698a3d968cc7e6ff125109d68ac83fd8a8a2
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Christian <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits