---
title: "Author content"
description: "Build accessible HTML, CSS, and JavaScript activities with the Interactive Content XBlock browser APIs."
source: "https://docs.blend-ed.com/interactive-content-xblock/authoring/"
---

# Author content

The Studio editor keeps the activity in 3 separate fields: HTML, CSS, and JavaScript. The LMS places the HTML inside the component, adds the CSS to the page, then executes the JavaScript.

> **Author code is not sandboxed in the LMS**
> HTML, CSS, and JavaScript run in the Open edX course page context. Use code only from trusted authors. Do not place secrets in the content, and do not load unreviewed third-party scripts.

## Submit an interaction
Call the global `submitInteraction(data)` function with a JSON-serializable object. The complete object is saved as the learner’s latest response.

```
submitInteraction({  answer: "Paris",  correct: true,  feedback: "Paris has been France's capital since 987.",  timeSpent: 12});
```
The XBlock interprets these conventional properties:

| Property | Type | Purpose |
| --- | --- | --- |
| `answer` | string-compatible | Compared with a configured single answer when JavaScript does not supply `correct`. |
| `correct` | boolean | Awards the full weight when `true` and zero when `false`. |
| `feedback` | string | Overrides the configured correct or incorrect feedback for this response. |
| `timeSpent` | number | Stored with the response and displayed with previous feedback. The XBlock does not calculate it. |

You can include additional JSON-compatible properties for state or analytics. Every call replaces the saved latest response and increments the learner’s interaction count.

`submitInteraction()` sends its request asynchronously and does not return a promise or response value to author code. Render immediate custom UI in your own JavaScript; the XBlock displays its configured grading feedback after the server responds.

## Mark a manual activity complete
When **Completion Mode** is **Manual**, call:

```
window.markComplete();
```
This records completion once without saving a response or publishing a grade. It can also complete an **On view** block early. The server rejects the call in **On submit** mode.

## Runtime constraints
- Write plain browser JavaScript. Do not use `import` or `export` .
- Use top-level function declarations for functions referenced by inline HTML
attributes such as `onclick` .
- Prefix CSS classes and element IDs for your activity to avoid collisions with
Open edX and other course components.
- Keep the activity compact. It renders inline within a course unit, not as a
standalone page.
- Use unique global function names. Author JavaScript shares the page’s global
scope.
- Prefer built-in browser APIs and self-contained assets. External resources add
privacy, availability, and content-security-policy dependencies.

## Accessibility checklist
- Use native buttons, inputs, labels, fieldsets, and headings.
- Make every action usable with a keyboard.
- Keep visible focus states and sufficient color contrast.
- Use `aria-live` or `role="status"` for dynamic custom results when appropriate.
- Do not communicate correctness through color alone.
- Test the published activity at narrow widths and browser zoom up to 200%.

## A compact example
```
<div class="capital-check">  <p id="capital-check-question">What is the capital of France?</p>  <div aria-labelledby="capital-check-question">    <button type="button" onclick="capitalCheckSubmit('Paris')">Paris</button>    <button type="button" onclick="capitalCheckSubmit('London')">London</button>  </div>  <p id="capital-check-result" role="status"></p></div>
```
```
.capital-check {  padding: 16px;  border: 1px solid #d9d9d9;  border-radius: 9px;}
.capital-check button {  margin: 8px 8px 0 0;}
```
```
var capitalCheckStartedAt = Date.now();
function capitalCheckSubmit(answer) {  var correct = answer === "Paris";  document.getElementById("capital-check-result").textContent =    correct ? "Correct" : "Try again";
  submitInteraction({    answer: answer,    correct: correct,    timeSpent: Math.round((Date.now() - capitalCheckStartedAt) / 1000)  });}
```
For scoring behavior, continue to [Grading and completion](/interactive-content-xblock/grading-and-completion/).
