Mooeypoo has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/172321

Change subject: [wip] Adding DragGroupElement and DragElement mixins
......................................................................

[wip] Adding DragGroupElement and DragElement mixins

Adding a GroupDragElement and DragElement to ooui for a drag/drop
usability.

Change-Id: I04c2cecc36e639e7f2583b5a86dfc4d160892899
---
M build/modules.json
A src/elements/DragElement.js
A src/elements/DragGroupElement.js
M src/styles/core.less
A src/styles/elements/DragElement.less
A src/styles/elements/DragGroupElement.less
6 files changed, 339 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/21/172321/1

diff --git a/build/modules.json b/build/modules.json
index 6422127..ccec4d6 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -21,6 +21,8 @@
 
                        "src/elements/ButtonElement.js",
                        "src/elements/GroupElement.js",
+                       "src/elements/DragElement.js",
+                       "src/elements/DragGroupElement.js",
                        "src/elements/IconElement.js",
                        "src/elements/IndicatorElement.js",
                        "src/elements/LabelElement.js",
diff --git a/src/elements/DragElement.js b/src/elements/DragElement.js
new file mode 100644
index 0000000..39dc0b1
--- /dev/null
+++ b/src/elements/DragElement.js
@@ -0,0 +1,104 @@
+/**
+ * A mixin for an element that can be dragged and dropped.
+ * Use in conjunction with DragGroupWidget
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.DragElement = function OoUiDragElement( config ) {
+       // Configuration
+       config = config || {};
+
+       // Properties
+       this.index = null;
+
+       // Initialize and events
+       this.$element
+               .attr( 'draggable', true )
+               .addClass( 'oo-ui-dragElement' )
+               // This is only here until I figure out the CSS issue
+               // TODO: Remove this display rule - it should be in the css 
file!!!!
+               .css( 'display', 'inline-block' )
+               .on( {
+                       dragstart: this.onDragStart.bind( this ),
+                       dragover: this.onDragOver.bind( this ),
+                       dragend: this.onDragEnd.bind( this ),
+                       drop: this.onDrop.bind( this )
+               } );
+};
+
+/**
+ * Respond to dragstart event.
+ * @param {jQuery.event} event jQuery event
+ * @return {boolean} True
+ * @fires dragstart
+ */
+OO.ui.DragElement.prototype.onDragStart = function ( event ) {
+       // Define drop effect
+       event.originalEvent.dataTransfer.dropEffect = 'move';
+       event.originalEvent.dataTransfer.effectAllowed = 'move';
+
+       // Add dragging class
+       this.$element.addClass( 'oo-ui-dragElement-dragging' );
+
+       // Emit event
+       this.emit( 'dragstart', this );
+       return true;
+};
+
+/**
+ * Respond to dragend event.
+ * @param {jQuery.event} event jQuery event
+ * @return {boolean} False
+ * @fires dragend
+ */
+OO.ui.DragElement.prototype.onDragEnd = function () {
+       this.$element.removeClass( 'oo-ui-dragElement-dragging' );
+
+       this.emit( 'dragend' );
+       // Return false and prevent propogation
+       return false;
+};
+
+/**
+ * Handle drop event.
+ * @param {jQuery.event} event jQuery event
+ * @fires drop
+ */
+OO.ui.DragElement.prototype.onDrop = function () {
+       this.emit( 'drop', this );
+};
+
+/**
+ * In order for drag/drop to work, the dragover event must
+ * return false and stop propogation.
+ * @return {boolean} False
+ * @fires dragover
+ */
+OO.ui.DragElement.prototype.onDragOver = function () {
+       this.emit( 'dragover', this.index );
+       return false;
+};
+
+/**
+ * Set item index.
+ * Store it in the dom so we can access from the widget drag event
+ * @param {number} Item index
+ */
+OO.ui.DragElement.prototype.setIndex = function ( index ) {
+       if ( this.index !== index ) {
+               this.index = index;
+               this.$element.data( 'index', index );
+       }
+};
+
+/**
+ * Get item index
+ * @return {number} Item index
+ */
+OO.ui.DragElement.prototype.getIndex = function () {
+       return this.index;
+};
diff --git a/src/elements/DragGroupElement.js b/src/elements/DragGroupElement.js
new file mode 100644
index 0000000..9a5581f
--- /dev/null
+++ b/src/elements/DragGroupElement.js
@@ -0,0 +1,213 @@
+/**
+ * Element containing a sequence of child elements that can be dragged
+ * and dropped.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$group] Container node, assigned to #$group, omit to use a 
generated `<div>`
+ */
+OO.ui.DragGroupElement = function OoUiDragGroupElement( config ) {
+       // Configuration intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.GroupElement.call( this, config );
+
+       // Properties
+       this.dragItem = null;
+       this.itemKeys = {};
+       this.sideInsertion = '';
+
+       // Aggregate drag drop events in items
+       this.aggregate( {
+               dragstart: 'itemDragStart',
+               dragend: 'itemDragEnd',
+               drop: 'itemDrop'
+       } );
+
+       // Item events
+       this.connect( this, {
+               itemDragStart: 'onItemDragStart',
+               itemDrop: 'onItemDrop',
+               itemDragEnd: 'onItemDragEnd'
+       } );
+
+       // Group events
+       this.$element.on( {
+               drag: $.proxy( this.onDrag, this ),
+               dragover: $.proxy( this.onDragOver, this )
+       } );
+
+       // Add items
+       if ( $.isArray( config.items ) ) {
+               this.addItems( config.items );
+       }
+
+       // Initialize
+       this.$placeholder = $( '<div>' )
+               .addClass( 'oo-ui-dragGroupElement-placeholder' );
+       this.$element
+               .addClass( 'oo-ui-dragGroupElement' )
+               .prepend( this.$placeholder );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.DragGroupElement, OO.ui.GroupElement );
+
+/* Methods */
+
+/**
+ * Respond to item drag start event
+ * @param {ReorderItemWidget} item Dragged item
+ */
+OO.ui.DragGroupElement.prototype.onItemDragStart = function ( item ) {
+       // Set the height of the indicator
+       this.$placeholder.css( 'height', this.items[0].$element.outerHeight() 
|| 20 );
+       this.setDragItem( item );
+};
+
+/**
+ * Respond to item drag end event
+ */
+OO.ui.DragGroupElement.prototype.onItemDragEnd = function () {
+       this.unsetDragItem();
+};
+
+/**
+ * Handle drop event and switch the order of the items accordingly
+ * @param {OO.ui.DragElement} item Dropped item
+ */
+OO.ui.DragGroupElement.prototype.onItemDrop = function ( item ) {
+       this.placeItemAtIndex( this.getDragItem(), item.getIndex() );
+};
+
+/**
+ * Switch the place of two items
+ * @param {OO.ui.DragElement} fromIndex [description]
+ * @param {number} toIndex [description]
+ */
+OO.ui.DragGroupElement.prototype.placeItemAtIndex = function ( item, toIndex ) 
{
+       // If the insertion point is 'after', the insertion index
+       // is shifted to the right
+       if ( this.sideInsertion === 'after' ) {
+               toIndex++;
+       }
+
+       // Change the item position
+       this.addItems( [ item ], toIndex );
+};
+
+/**
+ * Respond to mouse move event
+ * @param {jQuery.event} event Event details
+ */
+OO.ui.DragGroupElement.prototype.onDrag = function ( event ) {
+       var dragOverObj, $optionWidget, itemOffset, itemWidth, itemMidpoint,
+               dragPosition, itemIndex, sidePosition,
+               pageX = event.originalEvent.pageX,
+               pageY = event.originalEvent.pageY,
+               widgetOffset = this.$element.offset();
+
+       // Get the OptionWidget item we are dragging over
+       dragOverObj = this.getElementDocument().elementFromPoint( pageX, pageY 
);
+       $optionWidget = $( dragOverObj ).closest( '.oo-ui-dragElement' );
+       itemOffset = $optionWidget.offset();
+       itemIndex = $optionWidget.data( 'index' );
+
+       if (
+               itemOffset &&
+               this.isDragging() &&
+               itemIndex !== this.getDragItem().getIndex()
+       ) {
+               // Calculate where the mouse is relative to the item
+               itemWidth = $optionWidget.outerWidth();
+               itemMidpoint = itemOffset.left + itemWidth / 2;
+               dragPosition = pageX - widgetOffset.left;
+
+               // Which side of the item we hover over will dictate
+               // where the placeholder will appear, on the left or
+               // on the right
+               sidePosition = dragPosition < itemMidpoint ? itemOffset.left : 
itemOffset.left + itemWidth;
+               // Store whether we are before or after an item to rearrange
+               // Also account for RTL, as this is flipped
+               if ( this.$element.css( 'direction' ) === 'rtl' ) {
+                       this.sideInsertion = dragPosition < itemMidpoint ? 
'after' : 'before';
+               } else {
+                       this.sideInsertion = dragPosition < itemMidpoint ? 
'before' : 'after';
+               }
+
+               // Add drop indicator between objects
+               if ( this.sideInsertion  ) {
+                       this.$placeholder
+                               .css( {
+                                       left: sidePosition,
+                                       top: itemOffset.top
+                               } )
+                               .show();
+               } else {
+                       this.$placeholder
+                               .css( {
+                                       left: 0,
+                                       top: itemOffset.top
+                               } )
+                               .hide();
+               }
+       } else {
+               // This means the item was dragged outside the widget
+               this.$placeholder
+                       .css( 'left', 0 )
+                       .hide();
+       }
+
+};
+
+/**
+ * Set a dragged item
+ * @param {ReorderItemWidget} item Dragged item
+ */
+OO.ui.DragGroupElement.prototype.setDragItem = function ( item ) {
+       this.dragItem = item;
+};
+
+/**
+ * Unset the current dragged item
+ */
+OO.ui.DragGroupElement.prototype.unsetDragItem = function () {
+       this.dragItem = null;
+       this.$placeholder.hide();
+       this.sideInsertion = '';
+};
+
+/**
+ * Get the current dragged item
+ * @return {ReorderItemWidget|null} item Dragged item or null if no item is 
dragged
+ */
+OO.ui.DragGroupElement.prototype.getDragItem = function () {
+       return this.dragItem;
+};
+
+/**
+ * Check if there's an item being dragged.
+ * @return {Boolean} Item is being dragged
+ */
+OO.ui.DragGroupElement.prototype.isDragging = function () {
+       return this.getDragItem() !== null;
+};
+
+/**
+ * Expand the addItems method to store item indeces
+ */
+OO.ui.DragGroupElement.prototype.addItems = function ( items, index ) {
+       var i;
+       // Parent
+       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
+
+       // Map the index of each object
+       for ( i = 0; i < this.items.length; i++ ) {
+               this.items[i].setIndex( i );
+       }
+};
diff --git a/src/styles/core.less b/src/styles/core.less
index 139384c..77bc1c1 100644
--- a/src/styles/core.less
+++ b/src/styles/core.less
@@ -19,6 +19,8 @@
 @import 'elements/ButtonElement.less';
 @import 'elements/ClippableElement.less';
 @import 'elements/FlaggedElement.less';
+@import 'elements/DragElement.less';
+@import 'elements/DragGroupElement.less';
 @import 'elements/GroupElement.less';
 @import 'elements/IconElement.less';
 @import 'elements/IndicatorElement.less';
diff --git a/src/styles/elements/DragElement.less 
b/src/styles/elements/DragElement.less
new file mode 100644
index 0000000..c3fba82
--- /dev/null
+++ b/src/styles/elements/DragElement.less
@@ -0,0 +1,10 @@
+@import '../common';
+
+.oo-ui-dragElement {
+       display: inline-block;
+}
+
+.oo-ui-dragElement-dragging {
+       background: #666666;
+       opacity: 0.4;
+}
diff --git a/src/styles/elements/DragGroupElement.less 
b/src/styles/elements/DragGroupElement.less
new file mode 100644
index 0000000..e2a11b3
--- /dev/null
+++ b/src/styles/elements/DragGroupElement.less
@@ -0,0 +1,8 @@
+@import '../common';
+
+.oo-ui-dragGroupElement-placeholder {
+       position: absolute;
+       display: block;
+       width: 2px;
+       background-color: #2947C2;
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/172321
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I04c2cecc36e639e7f2583b5a86dfc4d160892899
Gerrit-PatchSet: 1
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Mooeypoo <mor...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to