Skip to content

Commit

Permalink
plugin API revamp (#1595)
Browse files Browse the repository at this point in the history
  • Loading branch information
owen-m1 authored Aug 30, 2019
1 parent 211b030 commit c3d1ea7
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 64 deletions.
14 changes: 7 additions & 7 deletions plugins/AutoScroll/AutoScroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ let autoScrolls = [],
function AutoScrollPlugin() {

function AutoScroll() {
this.options = {
this.defaults = {
scroll: true,
scrollSensitivity: 30,
scrollSpeed: 10,
Expand All @@ -47,7 +47,7 @@ function AutoScrollPlugin() {
if (this.sortable.nativeDraggable) {
on(document, 'dragover', this._handleAutoScroll);
} else {
if (this.sortable.options.supportPointer) {
if (this.options.supportPointer) {
on(document, 'pointermove', this._handleFallbackAutoScroll);
} else if (originalEvent.touches) {
on(document, 'touchmove', this._handleFallbackAutoScroll);
Expand All @@ -59,7 +59,7 @@ function AutoScrollPlugin() {

dragOverCompleted({ originalEvent }) {
// For when bubbling is canceled and using fallback (fallback 'touchmove' always reached)
if (!this.sortable.options.dragOverBubble && !originalEvent.rootEl) {
if (!this.options.dragOverBubble && !originalEvent.rootEl) {
this._handleAutoScroll(originalEvent);
}
},
Expand Down Expand Up @@ -107,7 +107,7 @@ function AutoScrollPlugin() {
// MACOS Safari does not have autoscroll,
// Firefox and Chrome are good
if (fallback || Edge || IE11OrLess || Safari) {
autoScroll(evt, this.sortable.options, elem, fallback);
autoScroll(evt, this.options, elem, fallback);

// Listener for pointer element change
let ogElemScroller = getParentAutoScrollElement(elem, true);
Expand All @@ -127,18 +127,18 @@ function AutoScrollPlugin() {
ogElemScroller = newElem;
clearAutoScrolls();
}
autoScroll(evt, this.sortable.options, newElem, fallback);
autoScroll(evt, this.options, newElem, fallback);
}, 10);
lastAutoScrollX = x;
lastAutoScrollY = y;
}
} else {
// if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll
if (!this.sortable.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) {
if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) {
clearAutoScrolls();
return;
}
autoScroll(evt, this.sortable.options, getParentAutoScrollElement(elem, false), false);
autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false);
}
}
};
Expand Down
61 changes: 31 additions & 30 deletions plugins/MultiDrag/MultiDrag.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function MultiDragPlugin() {
on(document, 'keydown', this._checkKeyDown);
on(document, 'keyup', this._checkKeyUp);

this.options = {
this.defaults = {
selectedClass: 'sortable-selected',
multiDragKey: null,
setData(dataTransfer, dragEl) {
Expand Down Expand Up @@ -75,7 +75,7 @@ function MultiDragPlugin() {
this.isMultiDrag = ~multiDragElements.indexOf(dragEl);
},

setupClone({ sortable }) {
setupClone({ sortable, cancel }) {
if (!this.isMultiDrag) return;
for (let i = 0; i < multiDragElements.length; i++) {
multiDragClones.push(clone(multiDragElements[i]));
Expand All @@ -85,27 +85,27 @@ function MultiDragPlugin() {
multiDragClones[i].draggable = false;
multiDragClones[i].style['will-change'] = '';

toggleClass(multiDragClones[i], sortable.options.selectedClass, false);
multiDragElements[i] === dragEl && toggleClass(multiDragClones[i], sortable.options.chosenClass, false);
toggleClass(multiDragClones[i], this.options.selectedClass, false);
multiDragElements[i] === dragEl && toggleClass(multiDragClones[i], this.options.chosenClass, false);
}

sortable._hideClone();
return true;
cancel();
},

clone({ sortable, rootEl, dispatchSortableEvent }) {
clone({ sortable, rootEl, dispatchSortableEvent, cancel }) {
if (!this.isMultiDrag) return;
if (!sortable.options.removeCloneOnHide) {
if (!this.options.removeCloneOnHide) {
if (multiDragElements.length && multiDragSortable === sortable) {
insertMultiDragClones(true, rootEl);
dispatchSortableEvent('clone');

return true;
cancel();
}
}
},

showClone({ cloneNowShown, rootEl }) {
showClone({ cloneNowShown, rootEl, cancel }) {
if (!this.isMultiDrag) return;
insertMultiDragClones(false, rootEl);
multiDragClones.forEach(clone => {
Expand All @@ -114,21 +114,21 @@ function MultiDragPlugin() {

cloneNowShown();
clonesHidden = false;
return true;
cancel();
},

hideClone({ sortable, cloneNowHidden }) {
hideClone({ sortable, cloneNowHidden, cancel }) {
if (!this.isMultiDrag) return;
multiDragClones.forEach(clone => {
css(clone, 'display', 'none');
if (sortable.options.removeCloneOnHide && clone.parentNode) {
if (this.options.removeCloneOnHide && clone.parentNode) {
clone.parentNode.removeChild(clone);
}
});

cloneNowHidden();
clonesHidden = true;
return true;
cancel();
},

dragStartGlobal({ sortable }) {
Expand All @@ -149,7 +149,7 @@ function MultiDragPlugin() {

dragStarted({ sortable }) {
if (!this.isMultiDrag) return;
if (sortable.options.sort) {
if (this.options.sort) {
// Capture rects,
// hide multi drag elements (by positioning them absolute),
// set multi drag elements rects to dragRect,
Expand All @@ -159,7 +159,7 @@ function MultiDragPlugin() {

sortable.captureAnimationState();

if (sortable.options.animation) {
if (this.options.animation) {
multiDragElements.forEach(multiDragElement => {
if (multiDragElement === dragEl) return;
css(multiDragElement, 'position', 'absolute');
Expand All @@ -177,26 +177,27 @@ function MultiDragPlugin() {
}
}

sortable.animateAll(function() {
sortable.animateAll(() => {
folding = false;
initialFolding = false;

if (sortable.options.animation) {
if (this.options.animation) {
multiDragElements.forEach(multiDragElement => {
unsetRect(multiDragElement);
});
}

// Remove all auxiliary multidrag items from el, if sorting enabled
if (sortable.options.sort) {
if (this.options.sort) {
removeMultiDragElements();
}
});
},

dragOver({ target, completed }) {
dragOver({ target, completed, cancel }) {
if (folding && ~multiDragElements.indexOf(target)) {
return completed(false);
completed(false);
cancel();
}
},

Expand All @@ -216,12 +217,12 @@ function MultiDragPlugin() {
fromSortable.removeAnimationState(multiDragElement);
});
folding = false;
insertMultiDragElements(!sortable.options.removeCloneOnHide, rootEl);
insertMultiDragElements(!this.options.removeCloneOnHide, rootEl);
}
},

dragOverCompleted({ sortable, isOwner, insertion, activeSortable, parentEl, putSortable }) {
let options = sortable.options;
let options = this.options;
if (insertion) {
// Clones must be hidden before folding animation to capture dragRectAbsolute properly
if (isOwner) {
Expand Down Expand Up @@ -301,7 +302,7 @@ function MultiDragPlugin() {

if (!evt) return;

let options = sortable.options,
let options = this.options,
children = parentEl.children;

// Multi-drag selection
Expand Down Expand Up @@ -344,7 +345,7 @@ function MultiDragPlugin() {
multiDragElements.push(children[i]);

dispatchEvent({
sortable: sortable,
sortable,
rootEl,
name: 'select',
targetEl: children[i],
Expand Down Expand Up @@ -375,7 +376,7 @@ function MultiDragPlugin() {
// Do not "unfold" after around dragEl if reverted
if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {
let dragRect = getRect(dragEl),
multiDragIndex = index(dragEl, ':not(.' + sortable.options.selectedClass + ')');
multiDragIndex = index(dragEl, ':not(.' + this.options.selectedClass + ')');

if (!initialFolding && options.animation) dragEl.thisAnimationDuration = null;

Expand Down Expand Up @@ -472,14 +473,14 @@ function MultiDragPlugin() {
if (multiDragSortable !== this.sortable) return;

// Only deselect if target is not item in this sortable
if (evt && closest(evt.target, this.sortable.options.draggable, this.sortable.el, false)) return;
if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return;

// Only deselect if left click
if (evt && evt.button !== 0) return;

while (multiDragElements.length) {
let el = multiDragElements[0];
toggleClass(el, this.sortable.options.selectedClass, false);
toggleClass(el, this.options.selectedClass, false);
multiDragElements.shift();
dispatchEvent({
sortable: this.sortable,
Expand All @@ -492,13 +493,13 @@ function MultiDragPlugin() {
},

_checkKeyDown(evt) {
if (evt.key === this.sortable.options.multiDragKey) {
if (evt.key === this.options.multiDragKey) {
this.multiDragKeyDown = true;
}
},

_checkKeyUp(evt) {
if (evt.key === this.sortable.options.multiDragKey) {
if (evt.key === this.options.multiDragKey) {
this.multiDragKeyDown = false;
}
}
Expand Down Expand Up @@ -534,7 +535,7 @@ function MultiDragPlugin() {
multiDragElements.splice(index, 1);
}
},
eventOptions() {
eventProperties() {
const oldIndicies = [],
newIndicies = [];

Expand Down
2 changes: 1 addition & 1 deletion plugins/OnSpill/OnSpill.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Revert.prototype = {
if (putSortable) {
putSortable.captureAnimationState();
}
let nextSibling = getChild(this.sortable.el, this.startIndex, this.sortable.options);
let nextSibling = getChild(this.sortable.el, this.startIndex, this.options);

if (nextSibling) {
this.sortable.el.insertBefore(dragEl, nextSibling);
Expand Down
14 changes: 8 additions & 6 deletions plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Sortable plugins are plugins that can be directly mounted to the Sortable class.

`el: HTMLElement` — The element that the sortable is being initialized on

`options: Object` — The options object that the user has passed into Sortable (not merged with defaults yet)


## Static Properties
The constructor function passed to `Sortable.mount` may contain several static properties and methods. The following static properties may be defined:
Expand All @@ -16,10 +18,10 @@ The constructor function passed to `Sortable.mount` may contain several static p
The name of the option that the user will use in their sortable's options to enable the plugin. Should start with a lower case and be camel-cased. For example: `'multiDrag'`. This is also the property name that the plugin's instance will be under in a sortable instance (ex. `sortableInstance.multiDrag`).

`utils: Object`
Object containing functions that will be added to the `Sortable.utils` default object on the Sortable class.
Object containing functions that will be added to the `Sortable.utils` static object on the Sortable class.

`eventOptions(eventName: String): Function`
A function that is called whenever Sortable fires an event. This function should return an object to be combined with the event object that Sortable will emit. The function will be called in the context of the Sortable that is firing the event (ie. the `this` keyword will be the Sortable calling the event).
A function that is called whenever Sortable fires an event. This function should return an object to be combined with the event object that Sortable will emit. The function will be called in the context of the instance of the plugin on the Sortable that is firing the event (ie. the `this` keyword will be the plugin instance).

`initializeByDefault: Boolean`
Determines whether or not the plugin will always be initialized on every new Sortable instance. If this option is enabled, it does not mean that by default the plugin will be enabled on the Sortable - this must still be done in the options via the plugin's `pluginName`, or it can be enabled by default if your plugin specifies it's pluginName as a default option that is truthy. Since the plugin will already be initialized on every Sortable instance, it can also be enabled dynamically via `sortableInstance.option('pluginName', true)`.
Expand Down Expand Up @@ -51,11 +53,11 @@ Plugin.optionModifiers = {
```

## Plugin Options
Plugins may have custom options or override the defaults of certain options. In order to do this, there must be an `options` object on the initialized plugin. This can be set in the plugin's prototype, or during the initialization of the plugin (when the `el` is available). For example:
Plugins may have custom default options or may override the defaults of other options. In order to do this, there must be a `defaults` object on the initialized plugin. This can be set in the plugin's prototype, or during the initialization of the plugin (when the `el` is available). For example:

```js
function myPlugin(el) {
this.options = {
function myPlugin(sortable, el, options) {
this.defaults = {
color: el.style.backgroundColor
};
}
Expand All @@ -67,7 +69,7 @@ Sortable.mount(myPlugin);
## Plugin Events

### Context
The events will be fired in the context of their own parent object (ie. context is not changed), however the plugin instance's Sortable instance is available under `this.sortable`.
The events will be fired in the context of their own parent object (ie. context is not changed), however the plugin instance's Sortable instance is available under `this.sortable`. Likewise, the options are available under `this.options`.

### Event List
The following table contains details on the events that a plugin may handle in the prototype of the plugin's constructor function.
Expand Down
13 changes: 7 additions & 6 deletions plugins/Swap/Swap.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ let lastSwapEl;

function SwapPlugin() {
function Swap() {
this.options = {
this.defaults = {
swapClass: 'sortable-swap-highlight'
};
}
Expand All @@ -17,10 +17,10 @@ function SwapPlugin() {
dragStart({ dragEl }) {
lastSwapEl = dragEl;
},
dragOverValid({ completed, target, onMove, activeSortable, changed }) {
dragOverValid({ completed, target, onMove, activeSortable, changed, cancel }) {
if (!activeSortable.options.swap) return;
let el = this.sortable.el,
options = this.sortable.options;
options = this.options;
if (target && target !== el) {
let prevSwapEl = lastSwapEl;
if (onMove(target) !== false) {
Expand All @@ -36,11 +36,12 @@ function SwapPlugin() {
}
changed();

return completed(true);
completed(true);
cancel();
},
drop({ activeSortable, putSortable, dragEl }) {
let toSortable = (putSortable || this.sortable);
let options = this.sortable.options;
let options = this.options;
lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);
if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {
if (dragEl !== lastSwapEl) {
Expand All @@ -60,7 +61,7 @@ function SwapPlugin() {

return Object.assign(Swap, {
pluginName: 'swap',
eventOptions() {
eventProperties() {
return {
swapItem: lastSwapEl
};
Expand Down
8 changes: 4 additions & 4 deletions src/EventDispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default function dispatchEvent(
targetEl, cloneEl, toEl, fromEl,
oldIndex, newIndex,
oldDraggableIndex, newDraggableIndex,
originalEvent, putSortable, eventOptions
originalEvent, putSortable, extraEventProperties
}
) {
sortable = (sortable || (rootEl && rootEl[expando]));
Expand Down Expand Up @@ -42,9 +42,9 @@ export default function dispatchEvent(
evt.originalEvent = originalEvent;
evt.pullMode = putSortable ? putSortable.lastPutMode : undefined;

let allEventOptions = { ...eventOptions, ...PluginManager.getEventOptions(name, sortable) };
for (let option in allEventOptions) {
evt[option] = allEventOptions[option];
let allEventProperties = { ...extraEventProperties, ...PluginManager.getEventProperties(name, sortable) };
for (let option in allEventProperties) {
evt[option] = allEventProperties[option];
}

if (rootEl) {
Expand Down
Loading

0 comments on commit c3d1ea7

Please sign in to comment.