Skip to content

PluginStructure

Tim Erickson edited this page Sep 22, 2018 · 7 revisions

The structure of a plugin

A typical plugin has a more-or-less common structure, although (a) it evolved during the course of the original project, 2015–2018; (b) Tim often changed the naming conventions arbitrarily due to forgetting what they were; and (c) some plugins require different resources, such as connections to php and mySQL.

the basic idea

Suppose we're looking at a plugin named foo.

  • foo.html file defines the overall visual appearance, aided by its associated foo.css.
  • A <script> block in foo.html executes foo.initilize(), which is defined along with the global foo in foo.js.
  • foo.initialize calls foo.CODAPconnect.initialize(), which sets up the iFrame and creates the initial dataContext. It also restores foo.state if we are using it for saving game state.
  • A routine in foo.ui — possibly foo.ui.update() — adjusts the visibility of DOM elements and their text to reflect the game state.
  • Event listeners, either explicitly defined or mentioned in the html, for example, in onclick clauses, call functions defined in files such as foo.js or foo.userActions.js. This is how user actions affect the game state.
  • When an action results in a change in CODAP, for example, a new case to be added, a routine is called in foo.codapConnect to perform that task.
  • When an action is complete, we call foo.ui.update() or its equivalent in order to change the display.

Of course, there are many more details, but that's the basic pattern.

the main directory

A plugin named foo resides in /plugins/foo/. Most of the code sits in that directory, with other resources in subfolders such as art/ or data/.

the html file

This is named foo.html

Its <head> section contains a slew of includes, often looking something like this:

    <link href='https://fonts.googleapis.com/css?family=Maven+Pro:700,900' rel='stylesheet'>
    <link href='https://fonts.googleapis.com/css?family=Rokkitt:300, 700' rel='stylesheet'>

    <link rel='stylesheet' type='text/css' href='foo.css'/>
    <link rel='stylesheet' type='text/css' href='../common/jqueryFolder/jquery-ui.min.css'/>

    <script src="../common/iframe-phone.js" language="javascript"></script>
    <script src="../common/codapInterface.js" language="javascript"></script>
    <script src="../common/pluginHelper.js" language="javascript"></script>
    <script src="../common/TEEUtils.js" language="javascript"></script>
    <script src="../common/jqueryFolder/jquery.min.js" language="javascript"></script>
    <script src="../common/jqueryFolder/jquery-ui.min.js" language="javascript"></script>

    <script src="foo.js" language="JavaScript"></script>

    <script src="fooGameConfigurations.js" language="JavaScript"></script>
    <script src="fooStrings.js" language="JavaScript"></script>

    <script src="foophpConnector.js" language="JavaScript"></script>
    <script src="fooCODAPConnector.js" language="JavaScript"></script>
    <script src="fooUI.js" language="JavaScript"></script>
    <script src="fooUserActions.js" language="JavaScript"></script>
    <script src="fooModel.js" language="JavaScript"></script>

Note that there is usually a foo.css to style the plugin.

foo.js

This is a central site for js functionality. As Tim developed a prototype, this was often the first js file he made, and then, as things got more complex, functions and members were offloaded into other files. In a more mature plugin, it functions as a controller, but often also implements functionality that has not yet found a home.

It defines the top-level global named foo; ideally it's the only one. So we often see:

let foo = {           //  top level global
    state : {},

at the top of this file. Note that this is where foo.state gets defined.

foo.constants.js

Sometimes the object foo.constants gets its own file; sometimes it lives in foo.js.

foo.CODAPConnect.js

Sometimes fooCODAPConnect.js or simply CODAPconnect.js or other variants. In ay case, defines the object foo.CODAPConnect or foo.connector.

This file has all the routines we use to communicate with CODAP, particularly emitting data we have generated into the platform. Here is an example from fishCODAPConnector.js:

    createFishItems: async function (iValues) {

        iValues = pluginHelper.arrayify(iValues);
        console.log("Fish ... createFishItems with " + iValues.length + " case(s)");

        try {
            res = await pluginHelper.createItems(iValues, fish.constants.kFishDataSetName);
            console.log("Resolving createFishItems() with " + JSON.stringify(res));
            return res;
        } catch {
            console.log("Problem creating items using iValues = " + JSON.stringify(iValues));
        }
    },

In this example, we have finally gotten wise to asynchronous coding (note the async function in the definition and the await where we ask pluginHelper to create the items). Earlier plugins do not have this; that's a good project to undertake one day.

foo.phpConnector.js

If the plugin needs a database (we've used mySQL during prototyping, but changing to something better would make sense), you will need php to communicate with it.

This file contains routines that set up the parameters for a specific task, and one method that actually makes the call. We are using the Fetch system of communicating.

See more details in a page about php and mySQL.

foo.ui.js

This file is responsible for adjusting the UI. This mostly involves

  • Changing the text of items, for example, updating the current time, reporting the number of widgets in a bin, or changing the text of a button from start to stop.
  • Changing the visibility of DOM objects, for example, by hiding buttons that are not relevant.

foo.model.js

If a pure model file makes sense, this is a good place to put it.

Clone this wiki locally