/** * DraggableElement is a mixin class used to create elements that can be clicked * and dragged by a mouse to a new position within a group. This class must be used * in conjunction with OO.ui.DraggableGroupElement, which provides a container for * the draggable elements. * * @abstract * @class * * @constructor */ OO.ui.DraggableElement = function OoUiDraggableElement() { // Properties this.index = null; // Initialize and events this.$element .attr( 'draggable', true ) .addClass( 'oo-ui-draggableElement' ) .on( { dragstart: this.onDragStart.bind( this ), dragover: this.onDragOver.bind( this ), dragend: this.onDragEnd.bind( this ), drop: this.onDrop.bind( this ) } ); }; OO.initClass( OO.ui.DraggableElement ); /* Events */ /** * @event dragstart * * A dragstart event is emitted when the user clicks and begins dragging an item. * @param {OO.ui.DraggableElement} item The item the user has clicked and is dragging with the mouse. */ /** * @event dragend * A dragend event is emitted when the user drags an item and releases the mouse, * thus terminating the drag operation. */ /** * @event drop * A drop event is emitted when the user drags an item and then releases the mouse button * over a valid target. */ /* Static Properties */ /** * @inheritdoc OO.ui.ButtonElement */ OO.ui.DraggableElement.static.cancelButtonMouseDownEvents = false; /* Methods */ /** * Respond to dragstart event. * * @private * @param {jQuery.Event} event jQuery event * @fires dragstart */ OO.ui.DraggableElement.prototype.onDragStart = function ( e ) { var dataTransfer = e.originalEvent.dataTransfer; // Define drop effect dataTransfer.dropEffect = 'none'; dataTransfer.effectAllowed = 'move'; // We must set up a dataTransfer data property or Firefox seems to // ignore the fact the element is draggable. try { dataTransfer.setData( 'application-x/OOjs-UI-draggable', this.getIndex() ); } catch ( err ) { // The above is only for firefox. No need to set a catch clause // if it fails, move on. } // Add dragging class this.$element.addClass( 'oo-ui-draggableElement-dragging' ); // Emit event this.emit( 'dragstart', this ); return true; }; /** * Respond to dragend event. * * @private * @fires dragend */ OO.ui.DraggableElement.prototype.onDragEnd = function () { this.$element.removeClass( 'oo-ui-draggableElement-dragging' ); this.emit( 'dragend' ); }; /** * Handle drop event. * * @private * @param {jQuery.Event} event jQuery event * @fires drop */ OO.ui.DraggableElement.prototype.onDrop = function ( e ) { e.preventDefault(); this.emit( 'drop', e ); }; /** * In order for drag/drop to work, the dragover event must * return false and stop propogation. * * @private */ OO.ui.DraggableElement.prototype.onDragOver = function ( e ) { e.preventDefault(); }; /** * Set item index. * Store it in the DOM so we can access from the widget drag event * * @private * @param {number} Item index */ OO.ui.DraggableElement.prototype.setIndex = function ( index ) { if ( this.index !== index ) { this.index = index; this.$element.data( 'index', index ); } }; /** * Get item index * * @private * @return {number} Item index */ OO.ui.DraggableElement.prototype.getIndex = function () { return this.index; };