Skip to content

Commit 8eb689b

Browse files
Drag-and-drop nodes on touch devices
Add support for drag-and-drop of nodes on touch devices. Not 100% complete, as it does not include graphical effects during the 'drag' phase. Tested on Chrome dev tools with touch simulator on Win 10, Safari on Apple iPad, and Chrome on SurfacePro. This was originally developed against OrgChart version 2.0.8, so I've done a quick update based on today's master branch. Apologies if the indentation has gone a bit wrong (Visual Studio is set up for my typical style, and I think it can't cope with OrgChart.js being different!).
1 parent 0f8338b commit 8eb689b

File tree

1 file changed

+102
-1
lines changed

1 file changed

+102
-1
lines changed

src/js/jquery.orgchart.js

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,100 @@
10251025
.end().end().siblings().remove();
10261026
}
10271027
},
1028+
//
1029+
touchstartHandler: function (event) {
1030+
console.log("orgChart: touchstart 1: touchHandled=" + this.touchHandled + ", touchMoved=" + this.touchMoved + ", target=" + event.target.innerText);
1031+
if (this.touchHandled)
1032+
return;
1033+
this.touchHandled = true;
1034+
this.touchMoved = false; // this is so we can work out later if this was a 'press' or a 'drag' touch
1035+
event.preventDefault();
1036+
},
1037+
//
1038+
touchmoveHandler: function (event) {
1039+
if (!this.touchHandled)
1040+
return;
1041+
event.preventDefault();
1042+
if (!this.touchMoved) {
1043+
var nodeIsSelected = $(this).hasClass('focused');
1044+
console.log("orgChart: touchmove 1: " + event.touches.length + " touches, we have not moved, so simulate a drag start", event.touches);
1045+
// TODO: visualise the start of the drag (as would happen on desktop)
1046+
this.simulateMouseEvent(event, 'dragstart');
1047+
}
1048+
this.touchMoved = true;
1049+
var $touching = $(document.elementFromPoint(event.touches[0].clientX, event.touches[0].clientY));
1050+
var $touchingNode = $touching.closest('div.node');
1051+
1052+
if ($touchingNode.length > 0) {
1053+
var touchingNodeElement = $touchingNode[0];
1054+
// TODO: simulate the dragover visualisation
1055+
if ($touchingNode.is('.allowedDrop')) {
1056+
console.log("orgChart: touchmove 2: this node (" + touchingNodeElement.id + ") is allowed to be a drop target");
1057+
this.touchTargetNode = touchingNodeElement;
1058+
}
1059+
else {
1060+
console.log("orgChart: touchmove 3: this node (" + touchingNodeElement.id + ") is NOT allowed to be a drop target");
1061+
this.touchTargetNode = null;
1062+
}
1063+
}
1064+
else {
1065+
console.log("orgchart: touchmove 4: not touching a node");
1066+
this.touchTargetNode = null;
1067+
}
1068+
},
1069+
//
1070+
touchendHandler: function (event) {
1071+
console.log("orgChart: touchend 1: touchHandled=" + this.touchHandled + ", touchMoved=" + this.touchMoved + ", " + event.target.innerText + " ");
1072+
if (!this.touchHandled) {
1073+
console.log("orgChart: touchend 2: not handled by us, so aborting");
1074+
return;
1075+
}
1076+
if (this.touchMoved) {
1077+
// we've had movement, so this was a 'drag' touch
1078+
if (this.touchTargetNode) {
1079+
console.log("orgChart: touchend 3: moved to a node, so simulating drop");
1080+
var fakeEventForDropHandler = { delegateTarget: this.touchTargetNode };
1081+
this.dropHandler(fakeEventForDropHandler);
1082+
this.touchTargetNode = null;
1083+
}
1084+
console.log("orgChart: touchend 4: simulating dragend");
1085+
this.simulateMouseEvent(event, 'dragend');
1086+
}
1087+
else {
1088+
// we did not move, so assume this was a 'press' touch
1089+
console.log("orgChart: touchend 5: moved, so simulating click");
1090+
this.simulateMouseEvent(event, 'click');
1091+
}
1092+
this.touchHandled = false;
1093+
},
1094+
// simulate a mouse event (so we can fake them on a touch device)
1095+
simulateMouseEvent: function (event, simulatedType) {
1096+
// Ignore multi-touch events
1097+
if (event.originalEvent.touches.length > 1) {
1098+
return;
1099+
}
1100+
var touch = event.originalEvent.changedTouches[0];
1101+
var simulatedEvent = document.createEvent('MouseEvents');
1102+
simulatedEvent.initMouseEvent(
1103+
simulatedType, // type
1104+
true, // bubbles
1105+
true, // cancelable
1106+
window, // view
1107+
1, // detail
1108+
touch.screenX, // screenX
1109+
touch.screenY, // screenY
1110+
touch.clientX, // clientX
1111+
touch.clientY, // clientY
1112+
false, // ctrlKey
1113+
false, // altKey
1114+
false, // shiftKey
1115+
false, // metaKey
1116+
0, // button
1117+
null // relatedTarget
1118+
);
1119+
// Dispatch the simulated event to the target element
1120+
event.target.dispatchEvent(simulatedEvent);
1121+
},
10281122
// create node
10291123
createNode: function (nodeData, level, opts) {
10301124
var that = this;
@@ -1075,7 +1169,14 @@
10751169
$nodeDiv.on('dragstart', this.dragstartHandler.bind(this))
10761170
.on('dragover', this.dragoverHandler.bind(this))
10771171
.on('dragend', this.dragendHandler.bind(this))
1078-
.on('drop', this.dropHandler.bind(this));
1172+
.on('drop', this.dropHandler.bind(this))
1173+
.on('touchstart', this.touchstartHandler.bind(this))
1174+
.on('touchmove', this.touchmoveHandler.bind(this))
1175+
.on('touchend', this.touchendHandler.bind(this));
1176+
1177+
this.touchHandled = false;
1178+
this.touchMoved = false;
1179+
this.touchTargetNode = null;
10791180
}
10801181
// allow user to append dom modification after finishing node create of orgchart
10811182
if (opts.createNode) {

0 commit comments

Comments
 (0)