Skip to content

Commit

Permalink
Use disposables for cleaner contract, temporarily depend on rx-lite
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Apr 4, 2015
1 parent a87131c commit 725b01b
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 71 deletions.
90 changes: 32 additions & 58 deletions modules/backends/HTML5.js
@@ -1,4 +1,5 @@
import { DragSource } from 'dnd-core';
import { Disposable } from 'rx-lite';
import NativeTypes from '../NativeTypes';
import EnterLeaveCounter from '../utils/EnterLeaveCounter';
import invariant from 'react/lib/invariant';
Expand Down Expand Up @@ -63,10 +64,7 @@ export default class HTML5Backend {
this.monitor = monitor;
this.registry = registry;

this.sourceNodes = {};
this.sourcePreviewNodes = {};
this.targetNodes = {};

this.enterLeaveCounter = new EnterLeaveCounter();

this.handleTopDragStart = this.handleTopDragStart.bind(this);
Expand All @@ -82,9 +80,9 @@ export default class HTML5Backend {
this.handleTopDrop = this.handleTopDrop.bind(this);
this.handleTopDropCapture = this.handleTopDropCapture.bind(this);
this.endDragIfSourceWasRemovedFromDOM = this.endDragIfSourceWasRemovedFromDOM.bind(this);
this.setSourceNode = this.setSourceNode.bind(this);
this.setSourcePreviewNode = this.setSourcePreviewNode.bind(this);
this.setTargetNode = this.setTargetNode.bind(this);
this.connectSourceNode = this.connectSourceNode.bind(this);
this.connectSourcePreviewNode = this.connectSourcePreviewNode.bind(this);
this.connectTargetNode = this.connectTargetNode.bind(this);
}

setup() {
Expand Down Expand Up @@ -391,69 +389,45 @@ export default class HTML5Backend {

getConnector() {
return {
dragSource: this.setSourceNode,
dragSourcePreview: this.setSourcePreviewNode,
dropTarget: this.setTargetNode
dragSource: this.connectSourceNode,
dragSourcePreview: this.connectSourcePreviewNode,
dropTarget: this.connectTargetNode
};
}

setSourcePreviewNode(sourceId, dragPreview) {
if (dragPreview) {
this.sourcePreviewNodes[sourceId] = dragPreview;
} else {
connectSourcePreviewNode(sourceId, node) {
this.sourcePreviewNodes[sourceId] = node;

return new Disposable(() => {
delete this.sourcePreviewNodes[sourceId];
}
});
}

setSourceNode(sourceId, node) {
let sourceNodes = this.sourceNodes[sourceId];
if (sourceNodes && sourceNodes.node === node) {
return;
}

if (sourceNodes && sourceNodes.node) {
sourceNodes.node.removeEventListener('dragstart', sourceNodes.dragstart);
sourceNodes.node.setAttribute('draggable', false);
}
connectSourceNode(sourceId, node) {
const handleDragStart = (e) => this.handleDragStart(e, sourceId);

if (node) {
this.sourceNodes[sourceId] = sourceNodes = {
node,
dragstart: (e) => this.handleDragStart(e, sourceId)
};
node.setAttribute('draggable', true);
node.addEventListener('dragstart', handleDragStart);

node.setAttribute('draggable', true);
node.addEventListener('dragstart', sourceNodes.dragstart);
} else {
delete this.sourceNodes[sourceId];
}
return new Disposable(() => {
node.removeEventListener('dragstart', handleDragStart);
node.setAttribute('draggable', false);
});
}

setTargetNode(targetId, node) {
let targetNodes = this.targetNodes[targetId];
if (targetNodes && targetNodes.node === node) {
return;
}
connectTargetNode(targetId, node) {
const handleDragEnter = (e) => this.handleDragEnter(e, targetId);
const handleDragOver = (e) => this.handleDragOver(e, targetId);
const handleDrop = (e) => this.handleDrop(e, targetId);

if (targetNodes && targetNodes.node) {
targetNodes.node.removeEventListener('dragenter', targetNodes.dragenter);
targetNodes.node.removeEventListener('dragover', targetNodes.dragover);
targetNodes.node.removeEventListener('drop', targetNodes.drop);
}
node.addEventListener('dragenter', handleDragEnter);
node.addEventListener('dragover', handleDragOver);
node.addEventListener('drop', handleDrop);

if (node) {
this.targetNodes[targetId] = targetNodes = {
node,
dragenter: (e) => this.handleDragEnter(e, targetId),
dragover: (e) => this.handleDragOver(e, targetId),
drop: (e) => this.handleDrop(e, targetId)
};

node.addEventListener('dragenter', targetNodes.dragenter);
node.addEventListener('dragover', targetNodes.dragover);
node.addEventListener('drop', targetNodes.drop);
} else {
delete this.targetNodes[targetId];
}
return new Disposable(() => {
node.removeEventListener('dragenter', handleDragEnter);
node.removeEventListener('dragover', handleDragOver);
node.removeEventListener('drop', handleDrop);
});
}
}
61 changes: 49 additions & 12 deletions modules/configureDragDrop.js
@@ -1,4 +1,5 @@
import React, { Component, PropTypes, findDOMNode } from 'react';
import { CompositeDisposable, SerialDisposable } from 'rx-lite';
import ComponentDragSource from './ComponentDragSource';
import ComponentDropTarget from './ComponentDropTarget';
import shallowEqual from './utils/shallowEqual';
Expand Down Expand Up @@ -32,9 +33,10 @@ export default function configureDragDrop(InnerComponent, {

this.handlerIds = {};
this.handlers = {};
this.resources = {};

this.componentRef = null;
this.connector = this.createConnector();
this.componentConnector = this.createComponentConnector();
this.attachHandlers(this.getNextHandlers(props));
this.state = this.getCurrentState();
}
Expand Down Expand Up @@ -70,7 +72,7 @@ export default function configureDragDrop(InnerComponent, {
monitor.removeChangeListener(this.handleChange);

this.detachHandlers();
this.connector = null;
this.componentConnector = null;
}

handleChange() {
Expand Down Expand Up @@ -144,15 +146,19 @@ export default function configureDragDrop(InnerComponent, {
attachHandler(key, handler) {
const registry = this.manager.getRegistry();

let handlerId;
if (handler instanceof ComponentDragSource) {
this.handlerIds[key] = registry.addSource(handler.type, handler);
handlerId = registry.addSource(handler.type, handler);
} else if (handler instanceof ComponentDropTarget) {
this.handlerIds[key] = registry.addTarget(handler.type, handler);
handlerId = registry.addTarget(handler.type, handler);
} else {
invariant(false, 'Handle is neither a source nor a target.');
}

this.handlerIds[key] = handlerId;
this.handlers[key] = handler;

this.resources[handlerId] = new CompositeDisposable();
}

detachHandler(key) {
Expand All @@ -167,6 +173,9 @@ export default function configureDragDrop(InnerComponent, {
invariant(false, 'Handle is neither a source nor a target.');
}

this.resources[handlerId].dispose();
delete this.resources[handlerId];

delete this.handlerIds[key];
delete this.handlers[key];
}
Expand All @@ -181,6 +190,11 @@ export default function configureDragDrop(InnerComponent, {
this.attachHandler(key, nextHandler);
}

useResource(handlerId, disposable) {
this.resources[handlerId].add(disposable);
return disposable;
}

getCurrentState() {
const monitor = this.manager.getMonitor();

Expand All @@ -189,21 +203,44 @@ export default function configureDragDrop(InnerComponent, {
handlerIds = handlerIds[DEFAULT_KEY];
}

return inject(this.connector, monitor, handlerIds);
return inject(this.componentConnector, monitor, handlerIds);
}

createConnector() {
createComponentConnector() {
const backend = this.manager.getBackend();
const connector = backend.getConnector();
const wrappedConnector = {};
const componentConnector = {};

Object.keys(connector).forEach(key => {
const connectBackend = connector[key].bind(connector);
const connectComponent = this.createComponentConnectorMethod(key, connectBackend);

Object.keys(connector).forEach(function (key) {
wrappedConnector[key] = memoize(handlerId => componentOrNode =>
connector[key].call(connector, handlerId, findDOMNode(componentOrNode))
);
componentConnector[key] = memoize(connectComponent);
});

return wrappedConnector;
return componentConnector;
}

createComponentConnectorMethod(key, connectBackend) {
return (handlerId) => {
const serialDisposable = this.useResource(handlerId, new SerialDisposable());
let currentNode = null;

return (componentOrNode) => {
var nextNode = findDOMNode(componentOrNode);
if (nextNode === currentNode) {
return;
}

serialDisposable.setDisposable(null);

if (nextNode) {
const nextDisposable = connectBackend(handlerId, nextNode);
serialDisposable.setDisposable(nextDisposable);
currentNode = nextNode;
}
};
};
}

render() {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -33,7 +33,8 @@
"dependencies": {
"dnd-core": "~0.7.0",
"flux": "^2.0.1",
"lodash": "^3.1.0"
"lodash": "^3.1.0",
"rx-lite": "^2.4.10"
},
"peerDependencies": {
"react": ">=0.12.0 <0.14.0"
Expand Down

0 comments on commit 725b01b

Please sign in to comment.