Created
February 3, 2017 18:29
-
-
Save clintharris/b552f61120c593cccdd37063372dd77f to your computer and use it in GitHub Desktop.
Files related to https://github.com/StreakYC/react-draggable-list/issues/12
This file contains 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
class MyDraggableList extends DraggableList { | |
constructor(props) { | |
super(props); | |
// We need to override and intercept calls to the _handleMouseMove() function defined in the DraggableList class. | |
// However, this function is NOT an instance method; we cannot simply override it. `this._handleMouseMove` is | |
// actually just an instance variable pointing to a function, so the way we "override" it is by modifying that | |
// variable to point to our custom implementation (_newHandleMouseMove) while keeping a pointer to the original | |
// function so we can still call it. Many Bothans died to bring us this information. | |
this._oldHandleMouseMove = this._handleMouseMove; | |
this._handleMouseMove = this._newHandleMouseMove; | |
} | |
/** | |
* Override the default _handleStartDrag() method inherited from DraggableList. | |
* | |
* @param {string|number} itemKey some sort of value that uniquely identifies the item in the list | |
* @param {number} pressY y-coord of where touch (i.e., touch-screen device) started | |
* @param {number} pageY y-coord of where mouse click started | |
*/ | |
_handleStartDrag(itemKey, pressY, pageY) { | |
super._handleStartDrag(itemKey, pressY, pageY); | |
// Override the cursor style set in super._handleStartDrag() and use the "grabbing hand" cursor instead. Note that | |
// the browser-specific prefix MUST be used for 'grabbing' to work. | |
if (document.documentElement) { | |
document.documentElement.style.cursor = `${Browser.cssPrefix}grabbing`; | |
} | |
// Important: we assume that the list items are instances of our custom MyDraggableListItem class, which specifically | |
// keeps references to _rootEl and _dragHandleEl. | |
const { _rootEl: listItemEl, _dragHandleEl: listItemDragHandleEl } = this.getItemInstance(itemKey); | |
// Note: the coordinates returned by getBoundingClientRect() are relative to the viewport. | |
const { top: containerTopY, bottom: containerBottomY } = super._getContainer().getBoundingClientRect(); | |
const { top: listItemTopY, height: listItemHeight } = listItemEl.getBoundingClientRect(); | |
const { top: dragHandleTopY, height: dragHandleHeight } = listItemDragHandleEl.getBoundingClientRect(); | |
const topOfItemToMiddleOfHandle = dragHandleTopY - listItemTopY + (dragHandleHeight / 2); | |
// Calculate a upper and lower boundaries for the mouse. If the mouse goes above or these lines, then we'll | |
// start rejecting "mousemove" events to prevent list item from being dragged outside (i.e., above the top, or below | |
// the bottom of) the container. | |
this._lowerMouseBoundary = | |
containerBottomY - listItemHeight // Start by using the top of the list item as the lower mouse boundary... | |
+ topOfItemToMiddleOfHandle // ...now move boundary line down so it's in line with the v-middle of the drag handle | |
+ 5; // ...then move the boundary down slightly so item can be dragged beyond the bottom of container a wee bit. | |
this._upperMouseBoundary = | |
containerTopY // Start by using the top of the list container as the upper mouse boundary... | |
+ topOfItemToMiddleOfHandle // ...now move boundary line down so it's in line with the v-middle of the drag handle | |
- 5; // ...then move the boundary up slightly so item can be dragged beyond the top of container a wee bit. | |
} | |
/** | |
* Our custom "handle mouse move" interceptor that will reject drag events if the mouse goes outside of set bounds. | |
* | |
* @param {long} options.pageY y-coord of mouse relative to the document (not just the view port), regardless of | |
* the current scrolling position. For example, the whole page may be 10 million pixels | |
* tall, but the viewport is only 800px tall. This coord represents the absolute position | |
* of the mouse within the 10M pixel tall document. | |
* @param {long} options.clientY y-coord of mouse pointer relative to viewport (regardless of the scroll position). | |
*/ | |
_newHandleMouseMove({pageY, clientY}) { | |
if(clientY < this._upperMouseBoundary || clientY > this._lowerMouseBoundary) { | |
return; | |
} | |
this._oldHandleMouseMove({pageY, clientY}); | |
} | |
} |
This file contains 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
class MyDraggableListItem extends React.PureComponent { | |
render() { | |
const {item, itemSelected, anySelected, dragHandle } = this.props; | |
const draggableHandle = dragHandle( | |
<div ref={(c) => this._dragHandleEl = c }> | |
// some sort of icon here... | |
</div> | |
); | |
return ( | |
<div ref={(c) => this._rootEl = c}> | |
{ draggableHandle } | |
{ item } | |
</div> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment