Last active
August 29, 2015 14:14
-
-
Save ixtli/4baed07ab212dcb573f0 to your computer and use it in GitHub Desktop.
ember mixin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
var $ = Ember.$; | |
// These are defined in reorder-handle.scss | |
var DRAGGING_CLASS = 'is-dragging'; | |
var DRAG_OVER_CLASS = 'drag-over'; | |
var DROP_TARGET_CLASS = 'drop-target'; | |
/** | |
* Handles dragover from other syblings | |
*/ | |
function _siblingDragOver(event) | |
{ | |
$(this).addClass(DRAG_OVER_CLASS); | |
// If you dont do this, the drop event doesnt get called. | |
event.preventDefault(); | |
return false; | |
} | |
/** | |
* Mark the recieving row as the drop target | |
*/ | |
function _siblingDrop(event) | |
{ | |
$(this).addClass(DROP_TARGET_CLASS); | |
event.preventDefault(); | |
return false; | |
} | |
/** | |
* Handles the dragleave from other syblings | |
*/ | |
function _siblingDragLeave(event) | |
{ | |
$(this).removeClass(DRAG_OVER_CLASS); | |
} | |
/** | |
* This swaps two elements in a HasMany collection. The normal way you'd do it | |
* with an ember mutable array doesnt work because ember data poorly documents | |
* its additions to the class it extends to implement hasMany. | |
*/ | |
function _swapCollectionElements(collection, first, second) | |
{ | |
var firstObject = collection.objectAt(first); | |
var secondObject = collection.objectAt(second); | |
collection.removeObject(firstObject); | |
collection.removeObject(secondObject); | |
if (first < second) | |
{ | |
collection.insertAt(first, secondObject); | |
collection.insertAt(second, firstObject); | |
} else { | |
collection.insertAt(second, firstObject); | |
collection.insertAt(first, secondObject); | |
} | |
} | |
export default Ember.Mixin.create({ | |
// The collection of objects that the container value belongs to. | |
// Records are reorderd within the container when something is dropped | |
reorderCollection: null, | |
dragStart: function(event) | |
{ | |
var self = $(event.target); | |
// This implementation assumes that the element being reordered is the | |
// PARENT of the UI element that initiates the dragging. I find this to | |
// be a more consistent user experience otherwise the user may accidentally | |
// initiate row dragging by clicking somewhere else. | |
var parent = self.parent(); | |
parent.addClass(DRAGGING_CLASS); | |
// Assume here that all other elements at the same level as the parent | |
// are sortable elements. This tells them to respond to dragover. | |
var siblings = parent.siblings(); | |
siblings.on('dragover.clg', _siblingDragOver); | |
siblings.on('dragleave.clg', _siblingDragLeave); | |
siblings.on('drop.clg', _siblingDrop); | |
}, | |
dragEnd: function(event) | |
{ | |
var self = $(event.target); | |
// Clean up the dragged element | |
var parent = self.parent(); | |
parent.removeClass(DRAGGING_CLASS); | |
// The row container | |
var container = parent.parent(); | |
var over = container.children('.' + DROP_TARGET_CLASS); | |
// Clear the drag-over handler and state | |
var siblings = parent.siblings(); | |
siblings.removeClass(DRAG_OVER_CLASS); | |
siblings.off('dragover.clg'); | |
siblings.off('dragleave.clg'); | |
siblings.off('drop.clg'); | |
if (!over.length) | |
{ | |
return; | |
} | |
// Check to make sure the embedder has defined a collection | |
var collection = this.get('reorderCollection'); | |
if (!collection) | |
{ | |
console.warn('No reorder collection defined.'); | |
return; | |
} | |
// Swap elements | |
_swapCollectionElements(collection, parent.index(), over.index()); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment