-
Notifications
You must be signed in to change notification settings - Fork 39
CODAP Data Interactive API
Table of Contents generated with DocToc
-
The Data Interactive API
- Introduction
- API Overview
- Data Interactive-Initiated Actions
- CODAP-Initiated Actions
This document is intended to aid developers of CODAP Data Interactives. It describes the API by which Data Interactives interact with their CODAP host environment and send data for presentation by other CODAP components.
Data Interactives are a class of components that may be employed in a CODAP workspace. Their role is to provide to CODAP data for analysis. For example, Data Games are Data Interactives that export to CODAP the internal data generated during the execution of simple video games. By analyzing this data students can learn how to improve his or her performance in the game. The Inquiry Space project created a number of Data Interactives for sensor- or simulation-based investigation of the physical world. A student can perform an experiment and then export the data he or she created to CODAP for immediate analysis.
Data Interactives are loosely coupled with CODAP. They can be considered to be plug-ins in this respect. They need not have the same origin web server as the CODAP instance in which they are run. They are contained in IFrames and communicate with the CODAP engine through PostMessage-based transport.
The Data Interactives API uses IFramePhone as a transport library to implement communication between an installed Data Interactive and CODAP. IFramePhone is a wrapper for the PostMessage API. It simplifies the establishment of the connection and implements a simple remote procedure call (RPC) interface.
CODAP defines command object structures and response object structures that are passed through the IFramePhone connectors to the CODAP instance. In most cases, the Data Interactive initiates a command and passes a callback to receive the response object. Some commands are initiated from the CODAP side. The mechanics of IFramePhone interchange are the same in either case.
- Case: An individual record or relation. Cases have attributes.
- Attribute: A field of a Case record. Cases of a given Collection all have the same set of Attributes.
- Collection: A set of Cases with the same set of Attributes. Typically, Data Interactives will define a parent and a child Collection where zero, one, or many child Cases are associated with each parent case and exactly one parent case associate with each child case.
- Data Context A set of collections. Data contexts define a chain of parent/child relationships among collections. There can be any number of collections in a data context. A typical data interactive will interact with a single data context. In CODAP a Data Context is synonymous with a data set.
CODAP is oriented to the handling of hierarchically structured data. Often, the hierarchy is a natural consequence of the repetition of a process in the Data Interactive. For example, in scientific data interactives, the hierarchy will come about from the repetition of an experiment. The parent collections will describe the overall conditions and parameters of experiments, and the child collections, the samples taken during the execution of each experiment. Similarly, game Data Interactives are built on the natural repetitions built into game play. A game Data Interactive will have parent collections that represent the conditions and outcomes of the games, and the child collections will describe the moves or other events that occurred during the play of an individual game. The execution of such a program will be like this:
- Set up environment
- In a loop repeat:
- Begin an experiment (or game)
- Collect experimental samples (or game moves)
- Conclude experiment (or game)
A Data Interactive following the above pattern would look like this:
-
Set up environment
- Initialize IFramePhone connection
- Finding out if the interactive has saved prior state by getting the interactiveFrame.
- Setting the desired layout in CODAP by updating the interactiveFrame
- Establishing the structure of the data by creating a data context. This call will create collections and attributes.
-
In a loop repeat:
-
Begin an experiment (or game)
- Call openCase to create the parent case. In the callback, fetch and store the case id.
-
Collect experimental samples (or game moves)
- Call createCase to create a child case for each sample or game move.
-
Conclude experiment (or game)
- Call closeCase to close the parent case.
-
Begin an experiment (or game)
Other patterns of interaction are possible, but the above pattern occurs pretty regularly.
This API requires the IFramePhone Library. It may be included in your HTML page, like this:
<script src="js/iframe-phone.js" language="javascript"></script>
There are no other dependencies for a Data Interactive. The Data Interactive will be placed in an IFrame and will be a draggable, resizable component within the CODAP workspace.
As soon as possible during the initialization process of the javascript you should initiate a communication link with the CODAP application. This permits exchange of messages between the Data Interactive and CODAP. Like this:
this.codapPhone = new iframePhone.IframePhoneRpcEndpoint(
doCommandHandler, "data-interactive", window.parent);
Arguments:
- handler: a function to respond to commands initiated from CODAP, see, CODAP-Initiated Actions.
- name: a string identifying the Data Interactive to CODAP. The value must be "data-interactive".
- target: the parent element. Generally you will pass window.parent.
Returns: an IFramePhone instance. This object has a method, call, that is used to issue commands to CODAP.
CODAP has a two parallel schemes for referencing objects. Data Interactives may refer to objects by the value of their 'name' property. Data Interactives will generally specify the value of this property and are responsible for its uniqueness within its scope. Internally, CODAP will also assign an 'id' property and will use these values in references. The purpose of this dual naming is to facilitate the writing of data interactives without having to deal with the complexities of chaining asynchronous requests.
Generally, objects will be required to be created with names and these names are immutable once created. Names should be composed of letters, digits, or underscores, with the initial character being a letter. Often objects will also define a 'title' property. Titles are generally mutable. Titles are arbitrary strings. The title is employed whereever the object is referred to in the user interface, but, if absent, the name will be used.
CODAP presents a hierarchical view of a data set. A data set may have multiple collections organized in series. Each collection has a set of cases and cases in a superordinate collection are related to one or more cases (called child cases) in the immediate subordinate collection. Every case in a subordinate collection is related to exactly one parent case in the collection's immediately superordinate collection.
This collections and cases view of a data set is engrained deeply in CODAP and is the Data Interactive API primarily supports this view. However, there is another view of data that has limited support through this API, that of Data Items. You can think of a Data Item as the union of attributes of a case in the most subordinate collection with the attributes of each of its ancestor cases. For example, using JSON object syntax to describe cases, if you have two collections, and a case in the parent collection has attributes:
{ 'Mfr': 'Chevrolet`, 'Model': 'Equinox' }
and a child case has:
{ 'Year': 20016, 'MSRP': 23100 }
Then the corresponding item has the attributes of the parent case and the child case, as follows:
{ 'Mfr': 'Chevrolet`, 'Model': 'Equinox', 'Year': 20016, 'MSRP': 23100 }
From the perspective of the Data Interactive, there can be several benefits to this view of data. If the data interactive is creating data and adding it to a data set in CODAP, it can be simpler to create items than it is to manage cases in a collection hierarchy. A CODAP user can reorganize the collection hierarchy, unless specifically prevented by the Data Interactive owning the data set. If the Data Interactive is only adding items, it permit this sort of reorganization.
Note: At this moment, creation is the only operation supported for data items.
Request objects, generally, are JSON objects with 'action', 'resource', and 'values' properties. This is true whether the request was initiated by the Data Interactive or by CODAP. They look like this:
{
action: 'create',
resource: 'component',
values: {
type: 'graph',
name: 'myGraph',
dimensions: {width: 320, height: 240},
xAttribute: 'Age',
yAttribute: 'Height'
}
}
-
action: one of 'create', 'update', 'get', 'delete', or 'notify'
-
create requests the creation of a resource in CODAP
-
update requests a modification of a resource in CODAP
-
get requests a facsimile of a resource from CODAP
-
delete requests the removal of a resource from CODAP
-
notify informs CODAP or the DI of an event, possibly providing identifying information about resources involved in the event.
-
resource: selects a resource or collection of resources. Resource selectors are strings.
-
values: An object or an array. For the 'create' action, passes one or more instances of the named object. For update, passes an object fragment with changed values.
Generally, 'create', 'update', and 'notify' requests require a 'values' property, and 'get' and 'delete' requests do not.
Response objects look like this:
{
success: true,
values: {
}
}
- success: a boolean indicating whether the action completed successfully.
- values: Optional.
Generally, a success value will always be provided. 'Create' requests will return identifying information about the objects created. 'Get' requests will return a copy of the current state of the object. It will have a high degree of resemblance to the corresponding section of a CODAP document.
Often the API provides a list resource parallel to the principal object types. These are, naturally enough, named by appending 'List' to the base type. For example, the list resource for the DataContext base type is DataContextList and the list resource for the Attribute base type is AttributeList. List resources are provided as as a basic query capability. They generally only support the 'get' action, and they will return only identifying properties of the objects.
Requests from data interactives to CODAP may be combined into an array. They will be processed in the order they appear in the array. CODAP will return an array of return objects one for each request object and in order. For example,
Send:
[{
"action": "update",
"resource": "interactiveFrame",
"values": {
"title": "DI-API Test",
"version": "0.1",
"preventBringToFront": false,
"dimensions": {
"width": 600,
"height": 500
}
}
},{
"action": "get",
"resource": "interactiveFrame"
}]
Receive:
[{
"success": true
},{
"success": true,
"values": {
"title": "DI-API Test",
"version": "0.1",
"dimensions": {
"width": 600,
"height": 500
}
}
}]
The command-specific arguments are documented by example in the sections below.
Used to pass information relevant to the embedding of the interactive's iFrame in CODAP. The 'create' action is not supported, because, the frame will have already been created for the Data Interactive to exist. If the action is 'delete', CODAP will delete the Data Interactive's component, causing the Data Interactive to be deleted.
Supported Operations: update, get, delete
Resource Selector Patterns:
- 'interactiveFrame' (update, get, delete)
{
name: /* {String} The name of the interactive frame, will be synthesized by codap from the data interactive url. */
title: /* {String} Settable and modifiable by the interactive, that will appear in the interactive's titlebar */
version: /* {String} Settable and modifiable by the interactive, that will appear right-justified in the interactive's titlebar */
dimensions: { /* Defines the dimensions of the interactive's screen real estate. */
width: {Number} in pixels,
height: {Number} in pixels
},
preventBringToFront: {Boolean} /* If true prevents the data interactive
from coming to the foreground upon selection. This may be desirable to allow
graphs to be superimposed above the interactive. */
savedState: /* {object} Content determined by data interactive, having been
saved in a prior response to CODAP interactiveFrame request */
}
Send:
{
action: 'update',
resource: 'interactiveFrame',
values: {
title: 'DataCard',
version: 1.0,
dimensions: {
width: 320,
height: 240
}
}
}
Receive:
{
success: true
}
Send:
{
action: 'get',
resource: 'interactiveFrame'
}
Receive:
{
success: true,
values: {
title: 'DataCard',
version: '1.0',
dimensions: {
width: 320,
height: 240
},
savedState: {
currentContext: 'Mammals'
}
}
}
Notes:
- Will cause the Data Interactive's component to be removed from CODAP, so the data interactive will cease to be. Use with care.
Send:
{
action: 'delete',
resource: 'interactiveFrame'
}
Receive:
{
success: true
}
Specifies the properties of the set of collections that are organized in a hierarchy. An interactive may create more than one data context. A data context will be created by default for each data interactive at the time it is first requested. The default data context can be referred to by the name dataContext without brackets.
Supported Operations: create, update, get, delete
Resource Selector Patterns:
- dataContext (for create action or to refer to Data Interactive's default data context for update, get, and delete actions)
- dataContext[name] (update, get, delete)
- dataContextList (get list)
{
values: {
name: /* {String} A unique string by which the interactive will refer to
this data context. Once set, is cannot be changed.*/
title: /* {String} Optional string to be used as the title of the case table
for this data context. If not provided, _name_ will be displayed.*/
description: /* {String} Currently not used but may be displayed in the future. */
collections: /* {Object} Collections contained by the data context. (See
below for object definition. ) */
}
}
Notes:
- The collections for a data context can be created with this command simply by providing the collection object in the values property of the request. See below for the structure of the collection object.
Send:
{
action: 'create',
resource: 'dataContext',
values: {
name: 'DataSet2',
title: 'A second data set'
collections: [ {
name: 'People',
title: 'Data about People',
labels: {
singleCase: 'person',
pluralCase: 'people'
},
attrs: [
{ name: 'Name' },
{ name: 'Age', type: 'numeric', precision: 0 }
]
}]
}
}
Receive:
{
success: true,
values: {
id: 2,
name: 'DataSet2'
}
}
Notes:
- The data context name, once created, cannot be changed.
- Although collections can be created through the above 'create' action, they cannot be updated through this dataContext 'update' action. Use the 'update operation of the 'collection' object.
Send:
{
action: 'update',
resource: 'dataContext[DataCard2]', /* or 'dataContext' to update default */
values: {
title: 'A new title for the data set'
}
}
Receive:
{
success: true
}
Notes:
- The get operation will return an object that contains any collections defined for the dataContext, and the collection attributes, but will not contain any case data.
Send:
{
action: 'get',
resource: 'dataContext[DataCard2]' /* or 'dataContext' to get default */
}
Receive:
{
success: true,
values: {
id: 2,
name: 'DataCard2',
title: 'A new title for the data set',
collections: [ {
name: 'People',
title: 'Data about People',
labels: {
singleCase: 'person',
pluralCase: 'people'
},
attrs: [
{ name: 'Name' },
{ name: 'Age', type: 'numeric', precision: 0 }
]
}]
}
}
Notes:
- The named data context will be removed from CODAP with all its collections and thier associated attributes and case data.
Send:
{
action: 'delete',
resource: 'dataContext[DataCard]'
}
Receive:
{
success: true
}
Notes:
- Will return identifying properties for each dataContext.
Send:
{
action: 'get',
resource: 'dataContextList'
}
Receive:
{
success: true,
values: [ {
id: 2,
name: 'DataCard2',
title: 'A new title for the data set'
},
values: {
id: 3,
name: 'DataCard3',
title: 'Another title for the data set'
}
]
}
A collection is a set of cases with a particular group of attributes. A collection is a part of a Data Context. It may have a parent collection and/or a child collection. If it has a parent collection, then each of its cases will have exactly one parent case in the parent collection. If it has a child collection, then each member case will have some number of child cases in the child collection.
Supported Operations: create, update, get, delete
Resource Selector Patterns:
- 'collection' (create)
- 'collection[name]' (update, get, delete of default data context's collections)
- 'collectionList' (get list)
- 'dataContext[name].collection' (create)
- 'dataContext[name].collection[name]' (update, get, delete)
- 'dataContext[name].collectionList' (get list)
{
name: /* {String} A unique string by which the interactive will refer to this collection. Once set, is cannot be changed.*/,
title: /* {String} Optional string to be used as the title of this collection as reflected in the case table*/,
description: /* {String} Currently not used but may be displayed in the future.*/,
parent: /* {String} Name of parent collection. The parent collection should have been created before it can be referred to.*/
attrs:/* {[Object]} Optional array of attribute objects. The attribute object is defined below.*/,
labels: /* {Object} Each of these fields is optional. */
singleCase: /* {String} used to refer to a single case. E.g. 'observation'*/,
pluralCase: /* {String} used to refer to more than one case. E.g. 'observations'*/,
singleCaseWithArticle: /* {String} showing how to prefix with an article. E.g. 'an observation'*/,
setOfCases: /* {String} used to refer to a group of cases. E.g. 'experiment'*/,
setOfCasesWithArticle: /* {String} showing how to prefix a set of cases with an article. E.g. 'an experiment'*/
}
Notes:
- Collection name must be unique within the data context.
- Collection attributes can be specified within this request or, later, in a separate request.
- A collection hierarchy is a strict hierarchy, so each collection can have at most one parent and child and every collection for a data context is in the hierarchy with no cycles.
- The example creates a collection for the default data context.
- The values property can contain either a single collection or an array of collections. If an array is specified, they should be ordered first parent to last child. The example shows a hierarchy with two collections, "People" and "Measurements". "Measurements is a child collection of "People."
Send:
{
action: 'create',
resource: 'collection',
values: [{
name: 'People',
title: 'Data about People',
labels: {
singleCase: 'person',
pluralCase: 'people'
}
},
{
name: 'Measurements',
title: 'Measurements',
parent: 'People'
}
]
}
Receive:
{
success: true
}
Notes:
- The collection name, once created, cannot be changed.
- The 'update' action of collection should not be used to update the attribute definitions. If these are to be updated, the attribute object should be used.
- Only one object can be updated per request.
Send:
{
action: 'update',
resource: 'dataContext[DataCard2].collection[People]', /* or
'collection[People]' for the default dataContext */
values: {
title: 'Students'
labels: {
singleCase: 'student',
pluralCase: 'students'
}
}
}
Receive:
{
success: true
}
Send:
{
action: 'get',
resource: 'dataContext[DataCard2].collections[People]' /* or
'collection[People]' for the default dataContext */
}
Receive:
{
success: true,
values: {
id: 3,
name: 'People'
title: 'Students'
labels: {
singleCase: 'student',
pluralCase: 'students'
}
}
}
- If a collection is deleted, all its attributes will also be deleted.
Send:
{
action: 'delete',
resource: 'dataContext[DataCard].collections[People]'
}
Receive:
{
success: true,
}
Send:
{
action: 'get',
resource: 'dataContext[DataCard2].collectionList' /* or 'collectionList' for
the default dataContext */
}
Receive:
{
success: true,
values: {
[
{
id: 45,
name: 'People',
title: 'People',
attrs: [
{name: 'Name'},
{name: 'Age', type: 'numeric', precision: 0}
]
},
{
id: 46,
name: 'Measurements',
title: 'Measurements',
}
]
}
}
Attributes are typed properties of cases. They may be numeric or categorical (numbers or strings).
Supported Operations: create, update, get, delete
Resource Selector Patterns:
- 'collection[name].attribute' (create, for the default data context)
- 'collection[name].attribute[name]' (update, get, delete for the default data context)
- 'collection[name].attributeList' (get list)
- 'dataContext[name].collection[name].attribute' (create)
- 'dataContext[name].collection[name].attribute[name]' (update, get, delete)
- 'dataContext[name].collection[name].attributeList' (get list)
{
name: /* {String} Optional. If not specified, the name of an attribute is
its name when created.*/
name: /* {String}. Attribute names must be unique within a collection.
If attribute names are to be used in formulas, they should
not have spaces in them.*/,
type: /* {'numeric' | 'categorical'} If not
specified, CODAP will decide dynamically whether to treat
the attribute as numeric or categorical based on the
presence of non-null, non-numeric values.*/,
description: /* {String} that will appear in various situations when user
hovers over attribute name.*/,
precision: /* {Number} specifying, for numeric attributes the number of
digits to the right of the decimal point that will be
displayed in case table.*/,
formula: /* {String} evaluated for each case*/,
colormap: /* {Object}. See below.*/
}
Notes:
- Attribute name must be unique within the data context.
Send:
{
action: 'create',
resource: 'dataContext[DataCard2].collections[Measurements].attribute', /* or
'collection[name].attribute' for the default data context */
values: [ {
name: 'sampleDate',
title: 'date of sample',
type: 'dateTime'
}, {
name: 'Age',
title: 'Age',
type: 'numeric',
description: 'Age of person in years',
precision: 0,
}, {
name: 'Height',
title: 'Height',
type: 'numeric',
description: 'Height of person in inches',
precision: 1,
}, {
name: 'Flavor',
title: 'Favorite ice cream flavor',
type: 'categorical',
}
]
}
Receive:
{
success: true
}
Notes:
- The attribute name, once created, cannot be changed.
Send:
{
action: 'update',
resource: 'dataContext[DataCard2].collections[People].attribute[Height]',
/* or 'collection[name].attribute[Height]' for
the default data context */
values: {
precision: 2,
}
}
}
Receive:
{
success: true,
values: {
id: 8,
name: 'Height',
title: 'Height',
type: 'numeric',
description: 'Height of person in inches',
precision: 2,
}
}
}
Send:
{
action: 'get',
resource: 'dataContext[DataCard2].collections[People].attribute[Height]'
/* or 'collections[Measurements].attribute[Height]' for the
default data context */
}
Receive:
{
success: true,
values: {
id: 8,
name: 'Height',
title: 'Height',
type: 'numeric',
description: 'Height of person in inches',
precision: 2,
}
}
}
Send:
{
action: 'delete',
resource: 'dataContext[DataCard].collections[Measurements].attribute[Flavor]'
/* or 'collections[Measurements].attribute[Flavor]' for the
default data context */
}
Receive:
{
success: true
}
Send:
{
action: 'get',
resource: 'dataContext[DataCard2].collection[Measurements].attributeList'
/* or 'collection[Measurements].attributeList' for the default
data context */
}
Receive:
{
success: true,
values: {
[
'SampleDate',
'Height',
'Age',
'Flavor'
]
}
}
A case is an item which can be characterized by some knowable attributes. It may be a thing that can be measured and described, or it may be an event or observation. A case may describe the characteristics of an aggregate or it may be an individual member of a larger aggregate.
Supported Operations: create, update, get, delete
Resource Selector Patterns:
- 'collection[name].case' (create for the default data context).
- 'collection[name].caseByID[id]' (get, update, delete)
- 'collection[name].caseByIndex[id]' (get, update, delete)
- 'dataContext[name].collection[name].case' (create)
- 'dataContext[name].collection[name].caseByID[id]' (get, update, delete)
- 'dataContext[name].collection[name].caseByIndex[index]' (get, update, delete)
- 'dataContext[name].collection[name].caseCount (get)
{
parent: /* {String} Case selector */
values: /* {Object} key/value pairs, one for each attribute that gets a value.
Key is attribute name.*/
}
Notes:
Send:
{
action: 'create',
resource: 'collection[Measurements].case',
values:[
{
parent: 12,
values: {
SampleDate: '12/1/2015',
Age: 12,
Height: 66,
Favorite: 'Vanilla'
}
}, {
parent: 13,
values: {
SampleDate: '12/1/2015',
Age: 11,
Height: 63,
Favorite: 'Rocky Road'
}
}
]
}
Receive:
{
success: true,
values: [
{
id: 15
}, {
id: 16
}
]
}
Effect: Updates a case.
Notes:
Send:
{
action: 'update',
resource: 'collection[People].caseByID[15]',
values: {
values: {
Favorite: 'Chocolate',
}
}
}
Receive:
{
success: true
}
- Index values are numeric and range from 0 to n-1 where n is the number of cases in the collection.
- Cases are ordered as in the case tables: grouped so that the children of each parent are together. Within this group they are ordered by arrival: oldest cases first.
Send:
{
action: 'get',
resource: 'collection[People].caseByIndex[0]'
}
Receive:
{
success: true,
values: {
id: 8,
values: {
Name: 'Jim',
Age: 15,
Height: 68
}
}
}
Send:
{
action: 'get',
resource: 'collection[People].caseByID[15]'
}
Receive:
{
success: true,
values: {
case: {
id: 8,
values: {
Name: 'Jim',
Age: 15,
Height: 68
}
}
}
}
Send:
{
action: 'get',
resource: 'collection[People].caseByIndex[0]'
}
Receive:
{
success: true,
values: {
case: {
id: 8,
values: {
Name: 'Ann',
Age: 14,
Height: 61
}
}
}
}
Send:
{
action: 'delete',
resource: 'dataContext[DataCard].collections[Measurements].cases[15]'
}
Receive:
{
success: true
}
Send:
{
action: 'get',
resource: 'dataContext[DataCard].collection[Measurements].caseCount'
}
Receive:
{
success: true
values: 43
}
This API is for managing selection of cases in CODAP.
Supported Operations: create, update, get
Resource Selection Patterns:
- 'dataContext[name].selectionList' (create, update, get)
- 'selectionList' (create, update, get for default data context)
The selectionList object is just an array of case ids. Cases may belong to different collections. Selection is inherited by the children of cases, so more cases may be displayed in CODAP after the selectionList request is sent.
[
25,
29,
30
]
Send:
{
action: 'create',
resource: 'dataContext[name].selectionList',
values: [
25,
29,
30
]
}
Receive:
{
success: true
}
Notes
- selectionList update adds to the existing selection.
Send:
{
action: 'update',
resource: 'dataContext[name].selectionList',
values: [
25,
29,
30
]
}
Receive:
{
success: true
}
Send:
{
action: 'get',
resource: 'dataContext[name].selectionList'
}
Receive:
{
success: true,
values: [
25,
29,
30
]
}
Data Items are an alternate view of a data set. A data item can be thought of as a "complete" case: the union of a leaf (rightmost) case with its ancestor cases. That is, if you have a data set with three hierarchical collections, "A", "B", and "C", and suppose you have a case in collection "C", then its associated Data Item is the tuple consisting of the values of attributes this case, the values the attributes of its parent case in collection "B" and the values of the attributes of its grandparent case in collection "A".
At this time the only supported action on this object type is "create". One can create an individual item or a set of items. The create operation returns a list of cases that compose the new item. That is one case for each collection for each item creation.
Supported Operations: create
Resource Selection Patterns:
- 'dataContext[name].item' (create)
- 'item' (create)
The item object is a map of non-formula attribute names to values. For example:
{
"Mammal": "Lion",
"Order": "Carnivora",
"LifeSpan": 15,
"Height": 2.5,
"Mass": 250,
"Sleep": 20,
"Speed": 80,
"Habitat": "land",
"Diet": "meat"
}
Send:
{
action: 'create',
resource: 'item'
values: {
"Mammal": "Lion",
"Order": "Carnivora",
"LifeSpan": 15,
"Height": 2.5,
"Mass": 250,
"Sleep": 20,
"Speed": 80,
"Habitat": "land",
"Diet": "meat"
}
}
Receive:
{
success: true;
values: {
caseIDs: [
6, 7, 8, 9
]
}
Send:
{
action: 'create',
resource: 'item'
values: [{
"Mammal": "Jaguar",
"Order": "Carnivora",
"LifeSpan": 20,
"Height": 1.8,
"Mass": 115,
"Sleep": 11,
"Speed": 60,
"Habitat": "land",
"Diet": "meat"
},{
"guid": 29,
"values": {
"Mammal": "Killer Whale",
"Order": "Cetacea",
"LifeSpan": 50,
"Height": 6.5,
"Mass": 4000,
"Sleep": "",
"Speed": 48,
"Habitat": "water",
"Diet": "meat"
}
}
]
}
Receive:
{
success: true;
values: {
caseIDs: [
4, 5
]
}
Components are interactive graphical representations of data. For example, case tables, graphs, maps and sliders are all components. Indeed, data interactives are components. Each component type has its own object structure.
Supported Operations: create, update, delete
Resource Selection Patterns:
- 'component[name]' (create, update, delete)
{
type: 'graph',
name: /*{String}. Must be unique. */,
title: /*{String} Optional. Displayed in graph titlebar. If omitted, graph name is used. */,
dimensions: {
width: /* {Number} in pixels*/,
height: /* {Number in pixels */
},
position: /*{String} Default is 'top'. If 'bottom' CODAP will position the graph in empty space as close to the bottom of the document as it can manage.*/,
dataContext: /* {String} Name of a data context */
xAttribute: /* {String} An attribute name within the data context */,
yAttribute: /* {String} An attribute name within the data context */,
y2Attribute: /* {String} An attribute name within the data context */,
legendAttribute: /* {String} An attribute name within the data context */
}
{
type: 'caseTable',
name: /*{String}. Must be unique, and is settable only at create time. */,
title: /*{String} Optional. Displayed in graph titlebar. If omitted, graph name is used. */,
dimensions: {
width: /* {Number} in pixels*/,
height: /* {Number in pixels */
},
position: /*{String} Default is 'top'. If 'bottom' CODAP will position the graph in empty space as close to the bottom of the document as it can manage.*/,
dataContext: /* {String} Name of a data context */
}
{
type: 'map',
name: /*{String}. Must be unique, and is settable only at create time. */,
title: /*{String} Optional. Displayed in graph titlebar. If omitted, graph name is used. */,
dimensions: {
width: /* {Number} in pixels*/,
height: /* {Number in pixels */
},
position: /*{String} Default is 'top'. If 'bottom' CODAP will position the graph in empty space as close to the bottom of the document as it can manage.*/,
dataContext: /* {String} Name of a data context */
legendAttribute: /* {String} Name of the attribute to be displayed in the legend. Optional. */
}
{
type: 'slider',
name: /*{String}. Must be unique, and is settable only at create time. */,
title: /*{String} Optional. Displayed in graph titlebar. If omitted, graph name is used. */,
dimensions: {
width: /* {Number} in pixels*/,
height: /* {Number in pixels */
},
position: /*{String} Default is 'top'. If 'bottom' CODAP will position the graph in empty space as close to the bottom of the document as it can manage.*/,
}
{
type: 'calculator',
name: /*{String}. Must be unique. */,
title: /*{String} Optional. Displayed in graph titlebar. If omitted, graph name is used. */,
dimensions: {
width: /* {Number} in pixels. Not settable.*/,
height: /* {Number in pixels. Not settable. */
},
position: /*{String} Default is 'top'. If 'bottom' CODAP will position the graph in empty space as close to the bottom of the document as it can manage.*/,
}
{
type: 'text',
name: /*{String}. Must be unique. */,
title: /*{String} Optional. Displayed in graph titlebar. If omitted, graph name is used. */,
dimensions: {
width: /* {Number} in pixels*/,
height: /* {Number in pixels */
},
position: /*{String} Default is 'top'. If 'bottom' CODAP will position the graph in empty space as close to the bottom of the document as it can manage.*/,
value: /*{Number}. Default is 1. This is the value used in formulas that refer to the slider
by name.*/
}
{
type: 'webView',
name: /*{String}. Must be unique. */,
title: /*{String} Optional. Displayed in graph titlebar. If omitted, graph name is used. */,
dimensions: {
width: /* {Number} in pixels*/,
height: /* {Number in pixels */
},
position: /*{String} Default is 'top'. If 'bottom' CODAP will position the graph in empty space as close to the bottom of the document as it can manage.*/,
}
Send:
{
action: 'create',
resource: 'component',
values: {
type: 'graph',
name: 'HeightAge',
dimensions: {
width: 240,
height: 240
},
position: 'top',
xAttribute: 'Age',
yAttribute: 'Height'
}
}
Receive:
{
success: true
}
Tells CODAP to change legend on a map.
Send:
{
action: 'update',
resource: 'component[myMap]',
values: {
legendAttribute: 'Height'
}
}
Receive:
{
success: true,
}
Tells CODAP to delete a slider.
Send:
{
action: 'delete',
resource: 'component[mySlider]',
}
Receive:
{
success: true
}
Tells CODAP to stream a given string.
Supported Operations: notify
Resource Selector Patterns:
- 'logAction' (notify)
{
formatStr: /* Format string for the log statement. Use %@ for replaceable
parameters. The format string follows SproutCore string format conventions,
so %@1 can be used for specific identification. E.g. 'Launched rocket with
%@ engine toward %@' */,
replaceArgs: /* [*] An array of values used to replace %@ instances in
formatStr. E.g. ['red', 'satellite']*/
}
Send:
{
action: 'notify',
resource: 'logAction',
values: {
formatStr: 'Launched rocket with %@ engine toward %@',
replaceArgs: ['red', 'satellite']
}
}
Receive:
{
success: true
}
Notifies CODAP that the DI has performed an undoable action. This is used when the DI expects CODAP to take control over undoing and redoing actions.
No arguments are sent, CODAP simply adds a "data interactive undoable action" to its undo stack, and when a user clicks Undo and Redo at the appropriate point in the stack, CODAP sends undoAction or redoAction to the DI as appropriate. The Data Interactive is responsible for maintaining its own undo stack, CODAP is simply responsible for initiating the undo or redo events.
Supported Operations: notify
Resource Selector Patterns:
- 'undoChangeNotice' (notify)
{
operation: 'undoableActionPerformed'
logMessage: /* {string} An optional log message. */
}
Send:
{
action: 'notify',
resource: 'undoChangeNotice'
values: {
operation: 'undoableActionPerformed',
logMessage: 'Set focal length: 1m'
}
}
Receive:
{
success: true
}
The IFramePhone-based API is entirely symmetric. It is a full duplex channel. The mechanism for CODAP-initiated actions is the same as for Data Interactive-initiated actions. The request is encapsulated in a command object, and the requester receives replies asynchronously through a callback.
The Data Interactive should register a dispatch function by providing it as an argument when initiating IFramePhone. Like this:
this.codapPhone = new iframePhone.IframePhoneRpcEndpoint(requestHandler,
"codap-game", window.parent);
Here, 'requestHandler' is a function that will be called to handle requests from CODAP. As with the Data Interactive to CODAP request traffic, the payload of the CODAP to Data Interactive requests is a serializable object of the same form. The object will have an 'action' and 'resource' field, and may have a 'values' field. The payload of the response from the Data Interactive should consist of a serializable object with a 'success' field and possibly a 'values field.
{
action: 'get',
resource: 'interactiveState'
}
The form of the callback function might look like this:
function requestHandler( iCommand, callback) {
switch( iCommand.resource) {
case 'interactiveState':
if (iCommand.action = 'get') {
callback(cartGame.model.saveState());
} else {
callback({success: false});
}
break;
case 'undoChangeNotice':
// ...
break;
default:
callback({success: false});
}
}
We see that the requestHandler function is passed a callback. It should be called with the results of executing the command handler.
If the Data Interactive has persistent state, it should implement a request handler that dispatches to implementation of saveState function. It should implement a 'get' request to 'interactiveState' as a part of its initialization to retrieve the state it may have previously saved. If it does not have persistent state, it need not implement a request handler at this time. The requests from CODAP will be ignored.
Likewise, if the data interactive does not support exchange of other resources, it can ignore these actions as well.
Most actions flowing from CODAP to the data interactives are notifications. The intent is to alert the data interactive of some event occurring in CODAP that may be of interest to the interactive. Often, no meaningful data will accompany the request. The interactive is expected to query further if it requires details.
The interactiveState is an arbitrary JSON object defined by the Data Interactive. It is requested by CODAP when CODAP wishes to save the state of the entire CODAP application. It can be retrieved by the data interactive as a part of the interactiveState object.
Supported Operations: get
Resource Selector Patterns:
- 'interactiveState' (get)
Notes:
- Occurs when CODAP is about to save its application state as a document.
- If the data interactive does not maintain state from one invocation to another it can ignore this request.
CODAP Sends:
{
action: 'get',
resource: 'interactiveState',
}
Data Interactive Sends:
{
success: true
values: {
// an arbitrary blob
}
}
This request notifies the interactive of undo request activity. These notifications refer to undoableActionPerformed notices sent from the interactive to CODAP. If an interactive implements undo and/or redo and wishes to participate in CODAP's undo/redo stack, these actions permit this.
The following notifications are possible:
- 'undoAction' will be sent when a user requests undo and a previously registered 'undoableActionPerformed' notice from this DI is at the top of the undo stack.
- 'redoAction' will be sent when a user requests redo and a previously registered 'undoableActionPerformed' notice from this DI is at the top of the redo stack.
- 'clearUndo' will be sent when a user requests an activity that would break the undo stack and this DI has previously registered an 'undoableActionPerformed' notice.
- 'redoAction' will be sent when a user requests an activity that would break the undo stack and this DI has previously registered an 'undoableActionPerformed' notice that has been undone.
Supported Operations: notify
Resource Selector Patterns:
- 'undoChangeNotice' (notify)
{
operation: { 'undoAction' | 'redoAction' | 'clearUndo' | 'clearRedo' }
}
Send:
{
action: 'notify',
resource: 'undoChangeNotice'
values: {
operation: 'undoAction',
}
}
Receive:
{
success: true
}
This request notifies the interactive of document level activity. Examples of such activity include the creation or destruction of components, globals, or data contexts.
Supported Operations: notify
Resource Selector Patterns:
- 'documentChangeNotice' (notify)
{
operation: /* {string} operation name. See below */
}
The following operations are possible:
Operation | Description |
---|---|
dataContextCountChanged | This count of dataContexts change, indicating addition or removal of one or more data contexts |
Notes:
Send:
{
action: 'notify'
resource: 'documentChangeNotice'
values: {
operation: 'dataContextCountChanged'
}
}
Receive:
{
success: true
}
This message notifies the interactive of change to a collection. Examples of such activity include the creation, modification, or destruction of collection instances. Events initiated directly by the data interactive are suppressed from this notification, although events that are an indirect consequence may result in a notice. Notifications may or may not provide some information about the event.
Supported Operations: notify
Resource Selector Patterns:
- 'dataContext[dataContextName].collection' (notify)
[{
operation: /* {string} operation name: createCollection or deleteCollection */
result: /* */
}, { /* ... */ }
]
Notes:
Send:
{
action: 'notify'
resource: 'dataContext[Mammals].collection'
values: {
operation: 'createCollection'
result: {
}
}
}
Receive:
{
success: true
}
This message notifies the interactive of change to an attribute. Examples of such activity include the creation, modification, repositioning, or destruction of attribute instances. Events initiated directly by the data interactive are suppressed from this notification, although events that are an indirect consequence may result in a notice. Notifications may or may not provide some information about the event.
Supported Operations: notify
Resource Selector Patterns:
- 'dataContext[dataContextName].attribute' (notify)
[{
operation: /* {string} operation name: createAttribute, updateAttribute, deleteAttribute, moveAttribute */
result: /* */
}, { /* ... */ }
]
Notes:
Send:
{
action: 'notify'
resource: 'dataContext[Mammals].attribute'
values: {
operation: 'createAttribute'
result: {
}
}
}
Receive:
{
success: true
}
This message notifies the interactive of change to one or more cases. Examples of such activity include the creation, modification, or destruction of cases. Events initiated directly by the data interactive are suppressed from this notification, although events that are an indirect consequence may result in a notice. Notifications may or may not provide some information about the event.
Supported Operations: notify
Resource Selector Patterns:
- 'dataContext[dataContextName].case' (notify)
[{
operation: /* {string} operation name: createCase, createCases, updateCases, deleteCases */
result: /* */
}, { /* ... */ }
]
Notes:
Send:
{
action: 'notify'
resource: 'dataContext[Mammals].case'
values: {
operation: 'updateCases'
result: {[
34, 35, 69
]}
}
}
Receive:
{
success: true
}
This message notifies the interactive of change to the selection list for a data context. Each data context has exactly one selection list, though the list may be empty at any given moment. Selection lists are lists of case ids. Examples of such activity include the changes in the membership of a selection list. Events initiated directly by the data interactive are suppressed from this notification, although events that are an indirect consequence may result in a notice.
Supported Operations: notify
Resource Selector Patterns:
- 'dataContext[dataContextName].selectionList' (notify)
[{
operation: /* {string} operation name: selectCases */
result: /* */
}, { /* ... */ }
]
Notes:
Send:
{
action: 'notify'
resource: 'dataContext[Mammals].selectionList'
values: {
operation: 'selectCases'
result: {[
34, 35, 69
]}
}
}
Receive:
{
success: true
}