-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
761 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,19 @@ | ||
body { | ||
background-color: aliceblue; | ||
margin : 0; | ||
padding : 0; | ||
height : 100vh; | ||
} | ||
|
||
#header { | ||
padding: 0.5em 1em 0.5em 1em ; | ||
} | ||
|
||
#content { | ||
padding: 0.5em 1em 0.5em 1em ; | ||
} | ||
|
||
#theSVG { | ||
background-color: white; | ||
width : 100%; | ||
} |
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,51 @@ | ||
<!DOCTYPE html> | ||
|
||
<!-- | ||
local just this: http://localhost/~tim/plugins/templ8/ | ||
local in local codap : | ||
http://localhost/~tim/codap/static/dg/en/cert/index.html?di=https://localhost/~tim/plugins/templ8Modular/ | ||
--> | ||
|
||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>templ8</title> | ||
|
||
<link rel="stylesheet" | ||
href="https://fonts.googleapis.com/css2?family=Sirin+Stencil:wght@400;700"> | ||
|
||
<link rel='stylesheet' type='text/css' href='css/templ8.css'/> | ||
|
||
<script src="https://d3js.org/d3.v7.min.js"></script> | ||
|
||
<script src="strings/localize.js"></script> | ||
|
||
<!-- These five scripts take care of the communication with CODAP --> | ||
<script src="../common/iframe-phone.js"></script> | ||
<script src="../common/codap_helper_newAPI.js"></script> | ||
<script src="../common/codapInterface.js"></script> | ||
<script src="../common/pluginHelper.js"></script> | ||
<script src="../common/pluginLang.js"></script> | ||
|
||
|
||
</head> | ||
<body> | ||
|
||
<div id="header">Template Plugin</div> | ||
<div id="content"> | ||
<svg id="theSVG"></svg> | ||
<div id="status"></div> | ||
<input type="button" id="counterButton" value="click to count"> | ||
<label for="counterButton" id="counterButtonLabel"></label> | ||
</div> | ||
|
||
</body> | ||
|
||
<script type="module"> | ||
import {initialize} from "./src/templ8.js"; | ||
|
||
initialize(); | ||
</script> | ||
|
||
</html> |
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,136 @@ | ||
/** | ||
* communicates with CODAP | ||
*/ | ||
|
||
import * as HANDLERS from "./handlers.js" | ||
import * as TEMPL8 from "./templ8.js" | ||
|
||
let theDSD; | ||
|
||
export async function initialize() { | ||
|
||
await codapInterface.init( | ||
getIFrameDescriptor(), | ||
HANDLERS.restorePluginFromStore // restores the state, if any | ||
); | ||
await allowReorg(); | ||
await renameIFrame(localize.getString("frameTitle")); // localize the frame title | ||
|
||
theDSD = getDatasetDescriptor(); | ||
await pluginHelper.initDataSet(theDSD); // open the output dataset | ||
|
||
} | ||
|
||
export async function emitData(iValues) { | ||
const theMessage = { | ||
action: "create", | ||
resource: `dataContext[${theDSD.name}].item`, | ||
values: iValues | ||
} | ||
|
||
try { | ||
await codapInterface.sendRequest(theMessage); | ||
} catch (err) { | ||
alert(`Error creating CODAP items: ${err}`) | ||
} | ||
|
||
makeCaseTableAppear(theDSD.name, localize.getString("outputDatasetTitle")); | ||
} | ||
|
||
export async function getAllItems(iDSName) { | ||
let out = null; | ||
|
||
const theMessage = { | ||
action : "get", | ||
resource : `dataContext[${iDSName}].itemSearch[*]` | ||
} | ||
|
||
try { | ||
const result = await codapInterface.sendRequest(theMessage); | ||
if (result.success) { | ||
return result.values; | ||
} | ||
} catch(err) { | ||
alert(`ERROR getting items: ${err}`); | ||
} | ||
|
||
return out; | ||
} | ||
|
||
async function makeCaseTableAppear(contextName, title) { | ||
const theMessage = { | ||
action: "create", | ||
resource: "component", | ||
values: { | ||
type: 'caseTable', | ||
dataContext: contextName, | ||
title: title, | ||
cannotClose: true | ||
} | ||
}; | ||
await codapInterface.sendRequest(theMessage); | ||
} | ||
|
||
|
||
|
||
async function renameIFrame(iName) { | ||
const theMessage = { | ||
action: "update", | ||
resource: "interactiveFrame", | ||
values: { | ||
title: iName, | ||
} | ||
}; | ||
await codapInterface.sendRequest(theMessage); | ||
} | ||
|
||
|
||
/** | ||
* Kludge to ensure that a dataset is reorg-able. | ||
* | ||
* @returns {Promise<void>} | ||
*/ | ||
async function allowReorg() { | ||
const tMutabilityMessage = { | ||
"action": "update", | ||
"resource": "interactiveFrame", | ||
"values": { | ||
"preventBringToFront": false, | ||
"preventDataContextReorg": false | ||
} | ||
}; | ||
|
||
codapInterface.sendRequest(tMutabilityMessage); | ||
} | ||
|
||
function getDatasetDescriptor() { | ||
return { | ||
name : TEMPL8.constants.outputDatasetName, | ||
title : localize.getString("outputDatasetTitle"), | ||
collections : [ | ||
{ | ||
name: "data", | ||
title: localize.getString("dataCollectionTitle"), | ||
attrs: [ | ||
{ name : localize.getString("attributeNames.count") }, | ||
{ name : localize.getString("attributeNames.time"), type : "date", unit : "UTC" }, | ||
{ name : localize.getString("attributeNames.interval"), unit : "sec" } | ||
|
||
] | ||
} | ||
] | ||
} | ||
} | ||
|
||
/** | ||
* Constant descriptor for the iFrame. | ||
* Find and edit the values in `templ8.constants` | ||
*/ | ||
function getIFrameDescriptor() { | ||
return { | ||
name: TEMPL8.constants.pluginName, | ||
title: localize.getString("frameTitle"), | ||
version: TEMPL8.constants.version, | ||
dimensions: TEMPL8.constants.dimensions, // dimensions, | ||
} | ||
} |
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,162 @@ | ||
import * as TEMPL8 from "./templ8.js" | ||
import * as UI from "./ui.js" | ||
|
||
let caseChangeSubscriberIndex = null; | ||
let attributeDragDropSubscriberIndex = null; | ||
|
||
let currentlyDraggingCODAPAttribute = false; | ||
|
||
/** | ||
* Set up handlers, e.g., event handlers | ||
*/ | ||
export function initialize() { | ||
registerForDragDropEvents(); // if you're accepting drops! | ||
|
||
// note: these subscriptions must happen BEFORE `connect.initialize()` so that the `.on` there does not | ||
// override our handlers. | ||
|
||
codapInterface.on('update', 'interactiveState', "", restorePluginFromStore); | ||
codapInterface.on('get', 'interactiveState', "", getPluginState); | ||
|
||
document.getElementById("counterButton").addEventListener('click', pressCountButton); | ||
|
||
} | ||
|
||
function getPluginState() { | ||
return { | ||
success: true, | ||
values: { | ||
store: TEMPL8.state, | ||
} | ||
}; | ||
} | ||
|
||
function restorePluginFromStore(iStorage) { | ||
if (iStorage) { | ||
TEMPL8.state = iStorage.store; | ||
} | ||
} | ||
|
||
/** | ||
* handler for our initial button | ||
*/ | ||
function pressCountButton() { | ||
TEMPL8.doButton(); | ||
} | ||
|
||
/** | ||
* Handlers for drag and drop of attributes frm CODAP | ||
* @param iMessage | ||
* @returns {Promise<void>} | ||
*/ | ||
export async function handleDragDrop(iMessage) { | ||
|
||
switch (iMessage.values.operation) { | ||
case `dragstart`: | ||
currentlyDraggingCODAPAttribute = true; | ||
console.log(` drag start`); | ||
break; | ||
case `dragend`: | ||
currentlyDraggingCODAPAttribute = false; | ||
highlightNone(); | ||
console.log(` drag end`); | ||
break; | ||
case `drag`: | ||
handleDrag(iMessage.values.position); | ||
break; | ||
case `drop`: | ||
await TEMPL8.copeWithAttributeDrop( | ||
iMessage.values.context, | ||
iMessage.values.collection, | ||
iMessage.values.attribute, | ||
iMessage.values.position | ||
); | ||
UI.redraw(); | ||
break; | ||
case `dragenter`: | ||
console.log(` drag enter`); | ||
highlightNear(); | ||
break; | ||
case `dragleave`: | ||
highlightNone(); | ||
console.log(` drag leave`); | ||
break; | ||
} | ||
} | ||
|
||
/** | ||
* CODAP has told us that a case has changed. | ||
* This will cause a re-get of all data and a re-analysis. | ||
* | ||
* @param iMessage | ||
* @returns {Promise<void>} | ||
*/ | ||
export async function handleCaseChangeNotice(iMessage) { | ||
const theOp = iMessage.values.operation; | ||
|
||
switch (theOp) { | ||
case 'createCases': | ||
case 'updateCases': | ||
case 'deleteCases': | ||
case `dependentCases`: // fires on rerandomize | ||
case `updateAttributes`: | ||
case `deleteAttributes`: | ||
case `createAttributes`: | ||
TEMPL8.copeWithCaseChange(); | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
// console.log(`end ${tMess}`); | ||
|
||
} | ||
|
||
function handleDrag(iPosition) { | ||
|
||
} | ||
|
||
function highlightNone() { | ||
|
||
} | ||
|
||
function highlightNear() { | ||
|
||
} | ||
|
||
/** | ||
* Register for the dragDrop[attribute] event. | ||
* | ||
* Called from connect.initialize(); | ||
*/ | ||
function registerForDragDropEvents() { | ||
const tResource = `dragDrop[attribute]`; | ||
|
||
attributeDragDropSubscriberIndex = codapInterface.on( | ||
'notify', tResource, handleDragDrop | ||
) | ||
console.log(`registered for drags and drops. Index ${attributeDragDropSubscriberIndex}`); | ||
} | ||
|
||
/** | ||
* register to receive notifications about changes to the data context (including selection) | ||
* called from templ8.setDataset() | ||
*/ | ||
export async function registerForCaseChanges(iName) { | ||
if (caseChangeSubscriberIndex) { // zero is a valid index... :P but it should be the "get" | ||
codapInterface.off(caseChangeSubscriberIndex); // blank that subscription. | ||
} | ||
|
||
const theResource = `dataContextChangeNotice[${iName}]`; | ||
// const sResource = `dataContext[${iName}].case`; | ||
try { | ||
caseChangeSubscriberIndex = codapInterface.on( | ||
'notify', | ||
theResource, | ||
handleCaseChangeNotice | ||
); | ||
console.log(`registered for case changes in ${iName}. Index ${this.caseChangeSubscriberIndex}`); | ||
} catch (msg) { | ||
console.log(`problem registering for case changes: ${msg}`); | ||
} | ||
} |
Oops, something went wrong.