Skip to content

CODAP Data Interactive API

Jonathan Sandoe edited this page Nov 12, 2016 · 36 revisions

Table of Contents generated with DocToc

The Data Interactive API

Introduction

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.

About Data Interactives

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.

About IFramePhone

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.

Definitions

  • 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.

API Overview

About Data Interactive-CODAP Communication Patterns

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.

Other patterns of interaction are possible, but the above pattern occurs pretty regularly.

Required Dependencies

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.

Establishing a IFramePhone link to CODAP

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.

Names, IDs, and Titles

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.

Collections and Cases versus Items

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.

The Structure of Messages

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.

Compound requests

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
      }
    }
  }]

Data Interactive-Initiated Actions

The command-specific arguments are documented by example in the sections below.

InteractiveFrames

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)

The interactiveFrame object

{
  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 */
}

Example: interactiveFrame update

Send:

{
  action: 'update',
  resource: 'interactiveFrame',
  values: {
    title: 'DataCard',
    version: 1.0,
    dimensions: {
      width: 320,
      height: 240
    }
  }
}

Receive:

{
  success: true
}

Example: interactiveFrame get

Send:

{
  action: 'get',
  resource: 'interactiveFrame'
}

Receive:

{
  success: true,
  values: {
    title: 'DataCard',
    version: '1.0',
    dimensions: {
      width: 320,
      height: 240
    },
    savedState: { 
      currentContext: 'Mammals' 
    }
  }
}

Example: interactiveFrame delete

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
}

DataContexts

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)

The dataContext object

{
  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. ) */
  }
}

Example: data context create

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'
  }
}

Example: dataContext update

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
}

Example: dataContext get

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 }
      ]
    }]
  }
}

Example: dataContext delete

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
}

Example: get dataContext list

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'
      }
    ]
}

Collections

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)

The collection object

{
    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'*/
}

Example: collection create

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
}

Example: collection update

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
}

Example: collection get

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'
    }
  }
}

Example: collection delete

  • If a collection is deleted, all its attributes will also be deleted.

Send:

{
  action: 'delete',
  resource: 'dataContext[DataCard].collections[People]'
}

Receive:

{
  success: true,
}

Example: collection list get

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

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)

The attribute object

{
  	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.*/
}

Example: attribute create

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
}

Example: attribute update

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,
    }
  }
}

Example: attribute get

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,
    }
  }
}

Example: attribute delete

Send:

{
  action: 'delete',
  resource: 'dataContext[DataCard].collections[Measurements].attribute[Flavor]'
                /* or 'collections[Measurements].attribute[Flavor]' for the
                 default data context */
}

Receive:

{
  success: true
}

Example: attribute list get

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'
    ]
  }
}

Cases

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)

The case object

{
  parent: /* {String} Case selector */
  values: /* {Object} key/value pairs, one for each attribute that gets a value.
  Key is attribute name.*/
}

Example: case create

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
    }
  ]
}

Example: case update

Effect: Updates a case.

Notes:

Send:

{
  action: 'update',
  resource: 'collection[People].caseByID[15]',
  values: {
    values: {
      Favorite: 'Chocolate',
    }
  }
}

Receive:

{
  success: true
}

Example: case get by index

  • 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
    }
  }
}

Example: case get by ID

Send:

{
  action: 'get',
  resource: 'collection[People].caseByID[15]'
}

Receive:

{
  success: true,
  values: {
    case: {
    id: 8,
      values: {
        Name: 'Jim',
        Age: 15,
        Height: 68
      }
    }
  }
}

Example: case get by Index

Send:

{
  action: 'get',
  resource: 'collection[People].caseByIndex[0]'
}

Receive:

{
  success: true,
  values: {
    case: {
    id: 8,
      values: {
        Name: 'Ann',
        Age: 14,
        Height: 61
      }
    }
  }
}

Example: case delete

Send:

{
  action: 'delete',
  resource: 'dataContext[DataCard].collections[Measurements].cases[15]'
}

Receive:

{
  success: true
}

Example: case count

Send:

{
  action: 'get',
  resource: 'dataContext[DataCard].collection[Measurements].caseCount'
}

Receive:

{
  success: true
  values: 43
}

SelectionLists

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

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
]

Example: selectionList create

Send:

{
  action: 'create',
  resource: 'dataContext[name].selectionList',
  values: [
      25,
      29,
      30
  ]
}

Receive:

{
  success: true
}

Example: selectionList update

Notes

  • selectionList update adds to the existing selection.

Send:

{
  action: 'update',
  resource: 'dataContext[name].selectionList',
  values: [
      25,
      29,
      30
  ]
}

Receive:

{
  success: true
}

Example: selectionList get

Send:

{
  action: 'get',
  resource: 'dataContext[name].selectionList'
}

Receive:

{
  success: true,
  values: [
    25,
    29,
    30
  ]
}

Items

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

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"
}

Example: item create one item

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
    ]
  }

Example: item create multiple items

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

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)

The graph object

{
  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 */
}

The caseTable object

{
  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 */
}

The map object

{
  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. */
}

The slider object

{
  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.*/,
}

The calculator object

{
  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.*/,
}

The text object

{
  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.*/
}

The webView object

{
  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.*/,
}

Example: create graph component

Send:

{
  action: 'create',
  resource: 'component',
  values: {
    type: 'graph',
    name: 'HeightAge',
    dimensions: {
      width: 240,
      height: 240
    },
    position: 'top',
	  xAttribute: 'Age',
  	yAttribute: 'Height'
  }
}

Receive:

{
  success: true
}

Example: update map component

Tells CODAP to change legend on a map.

Send:

{
  action: 'update',
  resource: 'component[myMap]',
  values: {
	  legendAttribute: 'Height'
  }
}

Receive:

{
  success: true,
}

Example: delete slider component

Tells CODAP to delete a slider.

Send:

{
  action: 'delete',
  resource: 'component[mySlider]',
}

Receive:

{
  success: true
}

Globals

LogActions

Tells CODAP to stream a given string.

Supported Operations: notify

Resource Selector Patterns:

  • 'logAction' (notify)

The logAction object

{
  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']*/
}

Example: logAction notify

Send:

{
  action: 'notify',
  resource: 'logAction',
  values: {
    formatStr: 'Launched rocket with %@ engine toward %@',
    replaceArgs: ['red', 'satellite']
  }
}

Receive:

{
  success: true
}

UndoChangeNotices

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)

The undoChangeNotice object

{
  operation: 'undoableActionPerformed'
  logMessage: /* {string} An optional log message. */
}

Example: undoChangeNotice notify

Send:

{
  action: 'notify',
  resource: 'undoChangeNotice'
  values: {
    operation: 'undoableActionPerformed',
    logMessage: 'Set focal length: 1m'
  }
}

Receive:

{
  success: true
}

CODAP-Initiated Actions

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.

interactiveState

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)

Example: 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
  }
}

undoChangeNotice

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)

The undoChangeNotice object

{
  operation: { 'undoAction' | 'redoAction' | 'clearUndo' | 'clearRedo' }
}

Example: undoChangeNotice notify

Send:

{
  action: 'notify',
  resource: 'undoChangeNotice'
  values: {
    operation: 'undoAction',
  }
}

Receive:

{
  success: true
}

documentChangeNotice

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)

The documentChangeNotice object

{
  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

Example: dataContextChangeNotice notify

Notes:

Send:

{
  action: 'notify'
  resource: 'documentChangeNotice'
  values: {
    operation: 'dataContextCountChanged'
  }
}

Receive:

{
  success: true
}

Collection change notifications

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)

The collection change notification object

[{
  operation: /* {string} operation name: createCollection or deleteCollection */
  result: /* */
}, { /* ... */ }
]

Example: Collection change notification

Notes:

Send:

{
  action: 'notify'
  resource: 'dataContext[Mammals].collection'
  values: {
    operation: 'createCollection'
    result: {
    }
  }
}

Receive:

{
  success: true
}

Attribute change notifications

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)

The Attribute change notification object

[{
  operation: /* {string} operation name: createAttribute, updateAttribute, deleteAttribute, moveAttribute */
  result: /* */
}, { /* ... */ }
]

Example: Attribute change notification

Notes:

Send:

{
  action: 'notify'
  resource: 'dataContext[Mammals].attribute'
  values: {
    operation: 'createAttribute'
    result: {
    }
  }
}

Receive:

{
  success: true
}

Case change notifications

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)

The case change notification object

[{
  operation: /* {string} operation name: createCase, createCases, updateCases, deleteCases */
  result: /* */
}, { /* ... */ }
]

Example: Case change notification

Notes:

Send:

{
  action: 'notify'
  resource: 'dataContext[Mammals].case'
  values: {
    operation: 'updateCases'
    result: {[
      34, 35, 69
    ]}
  }
}

Receive:

{
  success: true
}

Selection list change notifications

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)

The Selection list change notification object

[{
  operation: /* {string} operation name: selectCases */
  result: /* */
}, { /* ... */ }
]

Example: Selection list change notification

Notes:

Send:

{
  action: 'notify'
  resource: 'dataContext[Mammals].selectionList'
  values: {
    operation: 'selectCases'
    result: {[
      34, 35, 69
    ]}
  }
}

Receive:

{
  success: true
}