Skip to content

Commit

Permalink
Add "external-site-example.html" showing how to add SDX functionality…
Browse files Browse the repository at this point in the history
… to non-webclient apps
  • Loading branch information
hackerceo committed May 25, 2023
1 parent 5257a0e commit c92ef95
Showing 1 changed file with 255 additions and 0 deletions.
255 changes: 255 additions & 0 deletions external-site-example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>This is an example to show data transfer to an external site</title>

<!-- ===================================================================================================================== -->
<script>
if (!("i2b2" in window)) i2b2 = {};
i2b2.sdx = {};
i2b2.sdx.dd_events = {};
// List of acceptable SDX data types (modify to use only the types you need)
i2b2.sdx.TypeControllers = {
"CONCPT":{},
"QGDEF":{},
"QM":{},
"QI":{},
"PRC":{},
"PRS":{},
"ENS":{},
"PR":{},
"QDEF":{},
"WRK":{},
"XML":{}
};

//===========================================================
i2b2.sdx.AttachType = function(container, typeCode) {
// change the container into a DOM element reference
if (typeof container === "string") {
container = document.getElementById(container);
if (container.length === 0) {
container = null;
}
}

// manage if it is a document reference
if (container && container.length > 0) {
container = container[0];
}

//no valid container provided
if (!container) return false;

// add class for target bubbling
container.classList.add("i2b2DropTarget");

// confirm that it is a proper DOM node
let attrlist = [
"ondrag",
"ondragend",
"ondragenter",
"ondragover"
];

let isDomEl = true;

while (attrlist.length) {
if (typeof container[attrlist.pop()] !== "object") { isDomEl = false; }
}

// improper reference to a DOM element or element does not exist
if (!isDomEl) {
return false;
} else {
['drop', 'dragover', 'dragenter', 'dragleave'].forEach(function(e) {
container.addEventListener(e, i2b2.sdx.onDragDropEvents);
// save sdx type as valid for drop
let acceptedtypes = container.dataset.RegSdxTypes;
if (acceptedtypes === undefined) acceptedtypes = "[]";
let temp = JSON.parse(acceptedtypes);
temp.push(typeCode);
container.dataset.RegSdxTypes = JSON.stringify([...new Set(temp)]);
});
return true;
}
};

//===========================================================
i2b2.sdx.onDragDropEvents = function(e,a) {
// get a list of SDX types that are in this DD operation
let sdxTypeList = [];
for (let i in e.dataTransfer.types) {
if (String(e.dataTransfer.types[i]).toLowerCase().indexOf("application/i2b2-sdxtype+") === 0) {
let sdxTypes = String(e.dataTransfer.types[i]).toUpperCase().split("+");
sdxTypes.shift();
sdxTypeList = sdxTypeList.concat(sdxTypes);
}
}

let eventHandlers = i2b2.sdx.dd_events[this.id];
const acceptedtypes = JSON.parse(this.dataset.RegSdxTypes)

switch(e.type) {
case "drop":
// forward the event to the drop handler passing the object being dropped
while (sdxTypeList.length) {
let sdxType = sdxTypeList.pop();
if (typeof eventHandlers[sdxType] === "object" && typeof eventHandlers[sdxType].DropHandler === "function") {
let sdxJSON = JSON.parse(e.dataTransfer.getData("application/i2b2+json"));
eventHandlers[sdxType].DropHandler(sdxJSON, e);
}
}
e.stopImmediatePropagation();
e.currentTarget.classList.remove('dragging');
break;
case "dragover":
// enable drop if a drop handler exists for the object being dropped
while (sdxTypeList.length) {
let sdxType = sdxTypeList.pop();

if (acceptedtypes.includes(sdxType)) e.currentTarget.classList.add('dragging');

if (typeof eventHandlers[sdxType] === "object" && typeof eventHandlers[sdxType].DropHandler === "function") {
if (typeof eventHandlers[sdxType].DropChecker === "function") {
if (eventHandlers[sdxType].DropChecker(e.target, e, this)) {
// this is REQUIRED for proper drop
e.preventDefault();
}
} else {
// this is REQUIRED for proper drop
e.preventDefault();
}
}
}
break;
case "dragenter":
while (sdxTypeList.length) {
let sdxType = sdxTypeList.pop();

if (acceptedtypes.includes(sdxType)) e.currentTarget.classList.add('dragging');

if (typeof eventHandlers[sdxType] === "object" && typeof eventHandlers[sdxType].onHoverOver === "function") {
eventHandlers[sdxType].onHoverOver(e.target);
}
}
e.preventDefault();
break;
case "dragleave":
while (sdxTypeList.length) {
let sdxType = sdxTypeList.pop();
if (typeof eventHandlers[sdxType] === "object" && typeof eventHandlers[sdxType].onHoverOut === "function") {
eventHandlers[sdxType].onHoverOut(e.target);
}
}
e.preventDefault();
e.currentTarget.classList.remove('dragging');
break;
}
return false;
};

//===========================================================
i2b2.sdx.setHandlerCustom = function(container, typeCode, handlerName, newHandlerFunction) {
// containerID: string
// typeCode: string
// handlerName: string (example: DropHandler)
// newHandlerFunction: function to be used
// change the container into a DOM element reference

if (typeof container === "string") {
container = document.getElementById(container);
if (container.length === 0) {
container = null;
}
}

// manage if it is a document reference
if (container && container.length > 0) {
container = container[0];
}

//no valid container provided
if(!container){
return false;
}

// confirm that it is a proper DOM node
let attrlist = [
"ondrag",
"ondragend",
"ondragenter",
"ondragover"
];
let isDomEl = true;
while (attrlist.length) {
if (typeof container[attrlist.pop()] !== "object") {
isDomEl = false;
}
}

// improper reference to a DOM element or element does not exist
if (!isDomEl) {
return false;
} else {
if (typeof i2b2.sdx.dd_events[container.id] === "undefined") {
i2b2.sdx.dd_events[container.id] = {};
}

if (typeof i2b2.sdx.dd_events[container.id][typeCode] === "undefined") {
i2b2.sdx.dd_events[container.id][typeCode] = {};
}
// add new events
i2b2.sdx.dd_events[container.id][typeCode][handlerName] = newHandlerFunction;
return true;
}
};
</script>
<!-- ===================================================================================================================== -->

<!-- ===================================================================================================================== -->
<style>
.i2b2DropTarget {
background: lightgrey;
}

.i2b2DropTarget.dragging {
border-width: 3px !important;
background-color: #99CC99;
}
</style>
<!-- ===================================================================================================================== -->
</head>
<body>


<pre style="font-size:1.4rem">
This is an example of how to accept drag/drop operations from the i2b2 web client running in another window.
Drag and drop any i2b2 object onto the DIV below. The ".i2b2DropTarget" CSS class is applied to all containers
that are registered at i2b2 SDX drop targets. The ".i2b2DropTarget.dragging" CSS classes are applied to a
registered container that has a drag/drop operation occuring on it which contains a SDX data type that it has
been registered to accept. When the drop occurs your registered event handler is called with the SDX data object
being passed to it as the only parameter. See your browser's debug window console to view the data passed from
the main i2b2 web client window.
</pre>

<div style="width:50%; height:50%; left:25%; position:absolute; border:solid 1px" id="targetDiv"></div>


<script>
let funcDropHandler = function(data) {
console.dir(data);
alert("Drop Received");
};

Object.keys(i2b2.sdx.TypeControllers).forEach((sdxTypeCode) => {
// attach the SDX type to the container
i2b2.sdx.AttachType("targetDiv", sdxTypeCode);
// register a handler function for when that SDX type is dropped onto the container
i2b2.sdx.setHandlerCustom("targetDiv", sdxTypeCode, "DropHandler", funcDropHandler);
});
</script>

</body>
</html>

0 comments on commit c92ef95

Please sign in to comment.