Project API Docs

Installation guide

Loading the API

The API is designed to be loaded from the Math I Can Do Web site to ensure that users always have access to the latest version of the editor. (If you are interested in embedding the code or hosting it on your own server, contact us to discuss details.) Depending on your needs, the API can be loaded different ways:

Each method is described in detail below. Choose whichever one suits your project and experience level.

Important: These examples use an API key that is all zeroes. This key will only work when testing your page on localhost. Deployed apps will not work unless you replace the API_KEY value in main.ts with a valid key. Contact us to get an API key.

Using an ES6 module

To load the API in an ES6 module, import the createApi function as follows:

import { createApi } from "https://www.mathicando.com/api/micd/mathicando.js";

Your script can then call the createApi function to load the API when required. It must pass a valid API key, and can also pass an options object if desired. The function returns a Promise that resolves to the micd namespace object. For example:

import { createApi } from "https://www.mathicando.com/api/micd/mathicando.js";

const API_KEY = "000-0000-0000-0000-0000-000";

createApi(API_KEY).then(micd => {
    let view = new micd.View();
    view.addToDom(document.body);
    view.type("1+1=2");
    view.focus();
    // ...
});

Or, if your target environment supports top-level await, you could use code like the following:

import { createApi } from "https://www.mathicando.com/api/micd/mathicando.js";

const micd = await createApi(API_KEY);
const shell = await micd.shell.create(document.body);
// ...

If your environment does not support top-level await, you can simulate support by wrapping your code as follows:

import { createApi } from "https://www.mathicando.com/api/micd/mathicando.js";

(async function() {
    const micd = await createApi(API_KEY);
    const shell = await micd.shell.create(document.body);
    // ...
})();

Global configuration options can be passed to createApi as a second argument:

await createApi(API_KEY, { theme: { sBaseTheme: "dark" } });

Important: In your Web page, the script tag that loads an ES6 module script must have the type="module" attribute. For example:

index.html

<!DOCTYPE html>
<html>
<head>
  <title>Example</title>
  <script defer type="module" src="main.js"></script>
</head>
<body>
   ...
</body>
</html>

main.js

import { createApi } from "https://www.mathicando.com/api/micd/mathicando.js";
// ...

Using node.js

Node.js is a JavaScript runtime that runs outside of the browser. It is commonly used to develop front ends for Web applications using bundling tools like webpack, Rollup, or Parcel.js.

Note: As there are myriad Node.js development setups, this section can only offer general guidance. Experienced Node.js developers should be fine, but if you are a beginner you should check out the quick start tutorial.

If you have not already done so, create a directory for your project and create an empty package.json. For example:

cd path/to/my/project
npm init -y

Now install the Math I Can Do API node module in your project directory:

npm install https://www.mathicando.com/api/micd/mathicando-api.tgz

Then you can start using the API by requiring the module and calling createApi to load the API. This will start the API asynchronously, returning a Promise that resolves when the API is ready to use:

index.js

const { createApi } = require("mathicando-api");

const API_KEY = "000-0000-0000-0000-0000-000";

createApi(API_KEY).then(micd => {
    new micd.View().addToDom(document.body);
});

A development environment like VS Code should provide code completion and type checking automatically using the type information included with the module, but if not you may be able to nudge it along with an appropriate jsconfig.json file in your project directory. For example:

jsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "checkJs": true,
        "moduleResolution": "node"
    }
}

Using a script tag

To load the API directly into a page using a <script> tag, you must first define a global micd object that contains a key property set to your API key. Then add a script tag to load the API:

<script>micd = { key: "000-0000-0000-0000-0000-000" }</script>
<script data-cfasync="false" src="https://www.mathicando.com/api/micd/micd_loader/micd_loader.nocache.js"></script>

Once initialized, the API is available through the global variable micd:

var view = new micd.View();
view.addToDom(document.body);

To know when the API has loaded, add a property named onReady to the micd object that you created for the API key. Set this to a function you wish to call once the API is ready to use:

<script>
micd = {
  key: "000-0000-0000-0000-0000-000",
  onReady: callWhenMicdHasLoaded
};

function callWhenMicdHasLoaded() {
  // append a new editor to the page
  new micd.View().addToDom(document.body);
}
</script>
<script defer data-cfasync="false" src="https://www.mathicando.com/api/micd/micd_loader/micd_loader.nocache.js"></script>

If you prefer a Promise that resolves when the API is available, you could instead use code like the following:

<script>
micd = { key: "000-0000-0000-0000-0000-000" };
apiLoadedPromise = new Promise(resolve => micd.onReady = resolve);
</script>    
<script defer data-cfasync="false" src="https://www.mathicando.com/api/micd/micd_loader/micd_loader.nocache.js"></script>
<script defer src="main.js"></script>

Then in main.js you could use code like the following:

apiLoadedPromise
.then(()=>{
  // append a new editor to the page
  new micd.View().addToDom(document.body);    
});

Global configuration options can be specified by defining the config property before loading the API. For example:

<script>
micd = {
  key: "000-0000-0000-0000-0000-000",
  onReady: callWhenMicdHasLoaded,
  config: {
      theme: { sBaseTheme: "dark" },
      // ... more config options
  }
};
</script>

Create your first editor

If you have successfully loaded the API using any of the examples above, then you have already created your first editor! Each of those examples creates a View and adds it to the page using code like the following:

let view = new micd.View();
view.addToDom(document.body);
view.focus();

Views are the simplest way to interact with an editor. They are similar to a <textarea>, except that they contain math notation instead of plain text.

Note: It is important to keep in mind that the API loads asynchronously. Make sure the API is loaded before executing any of the code in this section. If you are not sure how, refer back to the instructions for your chosen loading method. (Essentially, wait for the createApi Promise to resolve or for your onReady function to be invoked.)

The API also includes a rich, app-like interface, the Shell. To create a Shell instead of a View, you could use code like the following:

micd.shell.create(document.body);

To keep load times down for pages that don't use a Shell, they are created asynchronously. That way, the additional resources needed to create the Shell interface are only loaded if you actually need them. The function called above, micd.shell.create returns a Promise that resolves to the new Shell. If you want to use properties or methods on the Shell (or the View or Editor that it includes), you need to wait for that Promise to resolve first. For example (in an async function):

const shell = await micd.shell.create(document.body);
shell.view.type("2");
shell.editor.apply("selectLine");
shell.editor.apply("squareRoot");

Setting an editor's size

Shells size themselves to their parent element. One way to control their size is to create them in an appropriately styled container. For example:

style.css

#container {
    width: 800px;
    height: 600px;
}

main.js

let container = document.createElement("div");
container.id = "container";
document.body.appendChild(container);
micd.shell.create(container);

Views do not have a preset size, although they may have a minimum size. You can size a View by styling its View.rootElement or by placing it in a container element that sizes its children.


Back to contents

This API is still under development and is subject to change. Copyright © Math I Can Do Solutions Incorporated and/or its licensors.