-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add "external-site-example.html" showing how to add SDX functionality…
… to non-webclient apps
- Loading branch information
Showing
1 changed file
with
255 additions
and
0 deletions.
There are no files selected for viewing
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
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> |