@teachinglab/omd 0.5.7 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -77
- package/README.old.md +138 -0
- package/index.js +3 -0
- package/npm-docs/DOCUMENTATION_SUMMARY.md +220 -0
- package/npm-docs/README.md +251 -0
- package/npm-docs/api/api-reference.md +85 -0
- package/npm-docs/api/configuration-options.md +198 -0
- package/npm-docs/api/eventManager.md +83 -0
- package/npm-docs/api/expression-nodes.md +561 -0
- package/npm-docs/api/focusFrameManager.md +145 -0
- package/npm-docs/api/index.md +106 -0
- package/npm-docs/api/main.md +63 -0
- package/npm-docs/api/omdBinaryExpressionNode.md +86 -0
- package/npm-docs/api/omdCanvas.md +84 -0
- package/npm-docs/api/omdConfigManager.md +113 -0
- package/npm-docs/api/omdConstantNode.md +53 -0
- package/npm-docs/api/omdDisplay.md +87 -0
- package/npm-docs/api/omdEquationNode.md +174 -0
- package/npm-docs/api/omdEquationSequenceNode.md +259 -0
- package/npm-docs/api/omdEquationStack.md +193 -0
- package/npm-docs/api/omdFunctionNode.md +83 -0
- package/npm-docs/api/omdGroupNode.md +79 -0
- package/npm-docs/api/omdHelpers.md +88 -0
- package/npm-docs/api/omdLeafNode.md +86 -0
- package/npm-docs/api/omdNode.md +202 -0
- package/npm-docs/api/omdOperationDisplayNode.md +118 -0
- package/npm-docs/api/omdOperatorNode.md +92 -0
- package/npm-docs/api/omdParenthesisNode.md +134 -0
- package/npm-docs/api/omdPopup.md +192 -0
- package/npm-docs/api/omdPowerNode.md +132 -0
- package/npm-docs/api/omdRationalNode.md +145 -0
- package/npm-docs/api/omdSequenceNode.md +128 -0
- package/npm-docs/api/omdSimplification.md +79 -0
- package/npm-docs/api/omdSqrtNode.md +144 -0
- package/npm-docs/api/omdStepVisualizer.md +147 -0
- package/npm-docs/api/omdStepVisualizerHighlighting.md +66 -0
- package/npm-docs/api/omdStepVisualizerInteractiveSteps.md +109 -0
- package/npm-docs/api/omdStepVisualizerLayout.md +71 -0
- package/npm-docs/api/omdStepVisualizerNodeUtils.md +140 -0
- package/npm-docs/api/omdStepVisualizerTextBoxes.md +77 -0
- package/npm-docs/api/omdToolbar.md +131 -0
- package/npm-docs/api/omdTranscriptionService.md +96 -0
- package/npm-docs/api/omdTreeDiff.md +170 -0
- package/npm-docs/api/omdUnaryExpressionNode.md +137 -0
- package/npm-docs/api/omdUtilities.md +83 -0
- package/npm-docs/api/omdVariableNode.md +123 -0
- package/npm-docs/api/selectTool.md +74 -0
- package/npm-docs/api/simplificationEngine.md +98 -0
- package/npm-docs/api/simplificationRules.md +77 -0
- package/npm-docs/api/simplificationUtils.md +64 -0
- package/npm-docs/api/transcribe.md +43 -0
- package/npm-docs/guides/equations.md +854 -0
- package/npm-docs/guides/factory-functions.md +354 -0
- package/npm-docs/guides/getting-started.md +318 -0
- package/npm-docs/guides/quick-examples.md +525 -0
- package/npm-docs/guides/visualizations.md +682 -0
- package/npm-docs/json-schemas.md +826 -0
- package/omd/utils/omdTranscriptionService.js +1 -1
- package/package.json +4 -3
- package/src/index.js +2 -0
- package/src/omdFactory.js +150 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# omdFunctionNode
|
|
2
|
+
|
|
3
|
+
Represents a mathematical function call, such as `sin(x)`, `sqrt(9)`, or `log(x, 10)`. This node handles the rendering of the function name, its arguments, and surrounding parentheses. It supports evaluation, simplification, and conversion to/from math.js AST.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdFunctionNode extends omdNode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
### `new omdFunctionNode(astNodeData)`
|
|
14
|
+
|
|
15
|
+
Creates a new `omdFunctionNode` instance.
|
|
16
|
+
|
|
17
|
+
- **`astNodeData`** (`object`): The math.js AST node for the function. It should contain:
|
|
18
|
+
- `fn.name` or `name`: The name of the function (e.g., `"sin"`, `"log"`).
|
|
19
|
+
- `args`: An array of AST nodes for the function's arguments.
|
|
20
|
+
|
|
21
|
+
## Static Methods
|
|
22
|
+
|
|
23
|
+
### `fromString(functionString)`
|
|
24
|
+
|
|
25
|
+
Creates an `omdFunctionNode` from a string representation of a function call. This method requires `window.math` (math.js library) to be available globally for parsing.
|
|
26
|
+
|
|
27
|
+
- **`functionString`** (`string`): The function call as a string (e.g., `"sqrt(16)"`, `"log(100, 10)"`).
|
|
28
|
+
- **Returns**: `omdFunctionNode` - A new instance of `omdFunctionNode`.
|
|
29
|
+
- **Throws**: `Error` if `math.js` is not available, if the string cannot be parsed, or if it does not represent a valid function call.
|
|
30
|
+
|
|
31
|
+
## Public Properties
|
|
32
|
+
|
|
33
|
+
- **`functionName`** (`string`): The name of the function (e.g., `"sin"`, `"log"`).
|
|
34
|
+
- **`args`** (`Array<omdNode>`): An array of `omdNode` instances representing the arguments of the function.
|
|
35
|
+
|
|
36
|
+
## Public Methods
|
|
37
|
+
|
|
38
|
+
### `computeDimensions()`
|
|
39
|
+
|
|
40
|
+
Calculates the bounding box of the function node, taking into account the dimensions of the function name, arguments, and parentheses. It also sets the font sizes for the function name and arguments (arguments are typically scaled down slightly).
|
|
41
|
+
|
|
42
|
+
### `updateLayout()`
|
|
43
|
+
|
|
44
|
+
Positions the function name, arguments, and parentheses within the node's bounding box. It ensures proper spacing and vertical alignment of all elements.
|
|
45
|
+
|
|
46
|
+
### `highlightAll()`
|
|
47
|
+
|
|
48
|
+
Applies a highlight to the function node itself (its background rectangle) and recursively highlights all of its argument nodes.
|
|
49
|
+
|
|
50
|
+
### `unhighlightAll()`
|
|
51
|
+
|
|
52
|
+
Removes the highlight from the function node and recursively unhighlights all of its argument nodes.
|
|
53
|
+
|
|
54
|
+
### `clone()`
|
|
55
|
+
|
|
56
|
+
Creates a deep, structural clone of the function node, including all its argument nodes and their associated SVG elements. The clone's provenance array is updated to include the original node's ID.
|
|
57
|
+
|
|
58
|
+
- **Returns**: `omdFunctionNode` - A new, identical instance of the function node.
|
|
59
|
+
|
|
60
|
+
### `toMathJSNode()`
|
|
61
|
+
|
|
62
|
+
Converts the `omdFunctionNode` back into its math.js AST representation. This includes converting its function name and all argument nodes.
|
|
63
|
+
|
|
64
|
+
- **Returns**: `object` - A math.js-compatible `FunctionNode` AST object.
|
|
65
|
+
|
|
66
|
+
### `toString()`
|
|
67
|
+
|
|
68
|
+
Converts the function node to its string representation (e.g., `"sqrt(x^2)"`, `"log(100, 10)"`).
|
|
69
|
+
|
|
70
|
+
- **Returns**: `string` - The function as a string.
|
|
71
|
+
|
|
72
|
+
### `evaluate(variables)`
|
|
73
|
+
|
|
74
|
+
Evaluates the function by first evaluating its arguments and then applying the function to the results. It primarily uses `window.math` (math.js) for evaluation. If `math.js` is not available, it falls back to standard JavaScript `Math` functions for common cases (e.g., `sin`, `cos`, `sqrt`).
|
|
75
|
+
|
|
76
|
+
- **`variables`** (`object`, optional): A map of variable names to their numeric values (e.g., `{ x: 2 }`).
|
|
77
|
+
- **Returns**: `number` - The result of the function evaluation.
|
|
78
|
+
- **Throws**: `Error` if the function is unknown or cannot be evaluated.
|
|
79
|
+
|
|
80
|
+
## Internal Methods
|
|
81
|
+
|
|
82
|
+
- **`createTextElements()`**: Creates `jsvgTextLine` elements for the function name and parentheses.
|
|
83
|
+
- **`createArgumentNodes()`**: Iterates through the AST arguments, creates corresponding `omdNode` instances for each, and adds them as children.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# omdGroupNode
|
|
2
|
+
|
|
3
|
+
Represents a single grouping symbol, such as `(` or `)`, as a leaf node in the expression tree. This node is primarily used for visual representation and layout, rather than mathematical operations.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdGroupNode extends omdLeafNode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
### `new omdGroupNode(nodeData)`
|
|
14
|
+
|
|
15
|
+
Creates a new `omdGroupNode` instance.
|
|
16
|
+
|
|
17
|
+
- **`nodeData`** (`string`): The single character string representing the grouping symbol (e.g., `'('`, `')'`, `'['`, `']'`).
|
|
18
|
+
|
|
19
|
+
## Public Properties
|
|
20
|
+
|
|
21
|
+
- **`symbol`** (`string`): The grouping symbol character (e.g., `'('`).
|
|
22
|
+
- **`type`** (`string`): Always `"parenthesis"` for this node type.
|
|
23
|
+
- **`textElement`** (`jsvgTextLine`): The internal `jsvgTextLine` instance responsible for rendering the symbol.
|
|
24
|
+
|
|
25
|
+
## Public Methods
|
|
26
|
+
|
|
27
|
+
### `clone()`
|
|
28
|
+
|
|
29
|
+
Creates a deep clone of the group node. The new node's `provenance` array is updated to include the original node's ID.
|
|
30
|
+
|
|
31
|
+
- **Returns**: `omdGroupNode` - A new, identical instance of the group node.
|
|
32
|
+
|
|
33
|
+
### `computeDimensions()`
|
|
34
|
+
|
|
35
|
+
Calculates the dimensions of the node based on its text content. Unlike other leaf nodes, `omdGroupNode` does *not* add extra padding around the symbol, allowing for tighter visual integration.
|
|
36
|
+
|
|
37
|
+
- **Overrides**: `omdLeafNode.computeDimensions()`.
|
|
38
|
+
|
|
39
|
+
### `updateLayout()`
|
|
40
|
+
|
|
41
|
+
Updates the position of the node's internal text element. This method primarily calls the superclass's `updateLayout`.
|
|
42
|
+
|
|
43
|
+
- **Overrides**: `omdLeafNode.updateLayout()`.
|
|
44
|
+
|
|
45
|
+
### `toMathJSNode()`
|
|
46
|
+
|
|
47
|
+
Converts the `omdGroupNode` to a math.js-compatible AST format. It represents the grouping symbol as a `SymbolNode`.
|
|
48
|
+
|
|
49
|
+
- **Returns**: `object` - A math.js-compatible AST node with `type: "SymbolNode"` and `name` set to the grouping symbol. The returned object also includes a `clone` method for compatibility.
|
|
50
|
+
|
|
51
|
+
## Internal Methods
|
|
52
|
+
|
|
53
|
+
- **`parseSymbol(nodeData)`**: Extracts the symbol from the constructor's `nodeData`. Returns the input string unchanged.
|
|
54
|
+
- **`parseType()`**: Sets the node's type. Always returns `"parenthesis"`.
|
|
55
|
+
|
|
56
|
+
## Example
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
// Create grouping symbols
|
|
60
|
+
const leftParen = new omdGroupNode('(');
|
|
61
|
+
const rightParen = new omdGroupNode(')');
|
|
62
|
+
const leftBracket = new omdGroupNode('[');
|
|
63
|
+
|
|
64
|
+
// Render a symbol
|
|
65
|
+
const node = new omdGroupNode('(');
|
|
66
|
+
node.setFontSize(24);
|
|
67
|
+
node.initialize(); // Computes dimensions and layout
|
|
68
|
+
|
|
69
|
+
// Add to an SVG container to display
|
|
70
|
+
// const svgContainer = new jsvgContainer();
|
|
71
|
+
// svgContainer.addChild(node);
|
|
72
|
+
// document.body.appendChild(svgContainer.svgObject);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## See Also
|
|
76
|
+
|
|
77
|
+
- [`omdLeafNode`](./omdLeafNode.md) - The parent class for all leaf nodes.
|
|
78
|
+
- [`omdNode`](./omdNode.md) - The base class for all OMD nodes.
|
|
79
|
+
- [`omdParenthesisNode`](./omdParenthesisNode.md) - For complete parenthetical expressions that contain other nodes.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# omdHelpers
|
|
2
|
+
|
|
3
|
+
`omdHelpers` is a collection of convenience functions designed to simplify common tasks when working with the OMD library. These helpers abstract away underlying complexities, making it easier to create and manipulate mathematical expressions and visualizations.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `omdHelpers` object is exported from the main `omd/core/index.js` entry point, making its functions readily available for use in your project.
|
|
8
|
+
|
|
9
|
+
## Functions
|
|
10
|
+
|
|
11
|
+
### `createNodeFromExpression(expression, mathInstance)`
|
|
12
|
+
|
|
13
|
+
Creates an `omdNode` instance from a string representation of a mathematical expression. This function parses the expression using the provided math.js instance and instantiates the appropriate `omdNode` subclass.
|
|
14
|
+
|
|
15
|
+
- **`expression`** (`string`): The mathematical expression as a string (e.g., `"x^2 + 2x + 1"`).
|
|
16
|
+
- **`mathInstance`** (`object`): The math.js instance to use for parsing the expression (e.g., `window.math`).
|
|
17
|
+
- **Returns**: `omdNode` - The root `omdNode` of the created expression tree.
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
import { omdHelpers } from '@teachinglab/omd';
|
|
21
|
+
// Assuming math.js is loaded globally as window.math
|
|
22
|
+
|
|
23
|
+
const expressionNode = omdHelpers.createNodeFromExpression('2x + 5', window.math);
|
|
24
|
+
// expressionNode will be an instance of omdBinaryExpressionNode or another omdNode subclass
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### `createEquation(equationString)`
|
|
28
|
+
|
|
29
|
+
Creates an `omdEquationNode` instance from a string representation of an equation. This is a specialized helper for equations, ensuring proper parsing and node creation.
|
|
30
|
+
|
|
31
|
+
- **`equationString`** (`string`): The equation as a string (e.g., `"x + 2 = 5"`).
|
|
32
|
+
- **Returns**: `omdEquationNode` - The created `omdEquationNode`.
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
import { omdHelpers } from '@teachinglab/omd';
|
|
36
|
+
|
|
37
|
+
const equation = omdHelpers.createEquation('3y - 7 = 14');
|
|
38
|
+
// equation will be an instance of omdEquationNode
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### `createStepVisualizer(equationStrings)`
|
|
42
|
+
|
|
43
|
+
Creates an `omdStepVisualizer` instance from an array of equation strings. This is useful for quickly setting up a step-by-step solution display.
|
|
44
|
+
|
|
45
|
+
- **`equationStrings`** (`Array<string>`): An array of strings, where each string represents an equation step (e.g., `["2x = 10", "x = 5"]`).
|
|
46
|
+
- **Returns**: `omdStepVisualizer` - The created `omdStepVisualizer` instance.
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import { omdHelpers } from '@teachinglab/omd';
|
|
50
|
+
|
|
51
|
+
const steps = [
|
|
52
|
+
'4x + 8 = 20',
|
|
53
|
+
'4x = 12',
|
|
54
|
+
'x = 3'
|
|
55
|
+
];
|
|
56
|
+
const visualizer = omdHelpers.createStepVisualizer(steps);
|
|
57
|
+
// visualizer will be an instance of omdStepVisualizer
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Example Usage
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
import { omdDisplay, omdHelpers } from '@teachinglab/omd';
|
|
64
|
+
// Assuming math.js is loaded globally as window.math
|
|
65
|
+
|
|
66
|
+
// Get a container element (assuming it exists in your HTML)
|
|
67
|
+
const container = document.getElementById('math-display-area');
|
|
68
|
+
|
|
69
|
+
// Create an expression node using a helper
|
|
70
|
+
const expression = omdHelpers.createNodeFromExpression('a^2 + b^2', window.math);
|
|
71
|
+
|
|
72
|
+
// Create an equation using a helper
|
|
73
|
+
const equation = omdHelpers.createEquation('E = mc^2');
|
|
74
|
+
|
|
75
|
+
// Create a step visualizer using a helper
|
|
76
|
+
const solutionSteps = [
|
|
77
|
+
'x + 5 = 10',
|
|
78
|
+
'x = 5'
|
|
79
|
+
];
|
|
80
|
+
const stepVisualizer = omdHelpers.createStepVisualizer(solutionSteps);
|
|
81
|
+
|
|
82
|
+
// You can then render these nodes using omdDisplay or omdCanvas
|
|
83
|
+
const display = new omdDisplay(container);
|
|
84
|
+
display.render(expression);
|
|
85
|
+
|
|
86
|
+
// Or for the step visualizer
|
|
87
|
+
// display.render(stepVisualizer);
|
|
88
|
+
```
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# omdLeafNode
|
|
2
|
+
|
|
3
|
+
Represents a base class for all leaf nodes in the OMD expression tree, such as constants, variables, operators, and grouping symbols. This class provides fundamental functionalities for handling text content, computing dimensions, and managing layout for single-element nodes.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdLeafNode extends omdNode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
### `new omdLeafNode(astNodeData)`
|
|
14
|
+
|
|
15
|
+
Creates a new `omdLeafNode` instance. This is an abstract base class; you should use its concrete subclasses (e.g., `omdConstantNode`, `omdVariableNode`) instead.
|
|
16
|
+
|
|
17
|
+
- **`astNodeData`** (`object`): The abstract syntax tree (AST) node data from a parser like math.js, containing information relevant to the leaf node.
|
|
18
|
+
|
|
19
|
+
## Public Properties
|
|
20
|
+
|
|
21
|
+
- **`textElement`** (`jsvgTextLine`): The internal `jsvgTextLine` instance that renders the text content of the leaf node.
|
|
22
|
+
|
|
23
|
+
## Public Methods
|
|
24
|
+
|
|
25
|
+
### `clone()`
|
|
26
|
+
|
|
27
|
+
Creates a deep clone of the leaf node. This method uses the original node's constructor to create a new instance, ensuring that the correct subclass is instantiated. The clone's `provenance` array is updated to include the original node's ID.
|
|
28
|
+
|
|
29
|
+
- **Returns**: `omdLeafNode` - A new instance of the specific leaf node subclass.
|
|
30
|
+
|
|
31
|
+
### `updateTextElement(text)`
|
|
32
|
+
|
|
33
|
+
Updates the text content displayed by the node's `textElement`. After updating the text, you typically need to call `computeDimensions()` and `updateLayout()` to reflect the change visually.
|
|
34
|
+
|
|
35
|
+
- **`text`** (`string` | `number`): The new text content to display.
|
|
36
|
+
|
|
37
|
+
### `computeDimensions()`
|
|
38
|
+
|
|
39
|
+
Calculates the dimensions (width and height) of the node based on its text content and current font size. It uses the `getTextBounds` utility function to accurately measure the text. This method also updates the font size of the internal `textElement`.
|
|
40
|
+
|
|
41
|
+
- **Overrides**: `omdNode.computeDimensions()`.
|
|
42
|
+
|
|
43
|
+
### `updateLayout()`
|
|
44
|
+
|
|
45
|
+
Updates the position of the node's internal text element to center it within the node's bounding box. This method primarily calls the internal `updateTextPosition()`.
|
|
46
|
+
|
|
47
|
+
- **Overrides**: `omdNode.updateLayout()`.
|
|
48
|
+
|
|
49
|
+
## Internal Methods
|
|
50
|
+
|
|
51
|
+
- **`createTextElement(text)`**: Creates and initializes a `jsvgTextLine` element with the given text. It sets the text anchor to `'middle'` and dominant baseline to `'middle'` for proper centering, and adds it as a child of this node.
|
|
52
|
+
- **Returns**: `jsvgTextLine` - The created text element.
|
|
53
|
+
- **`updateTextPosition()`**: Positions the `textElement` at the center of the node's calculated width and height.
|
|
54
|
+
|
|
55
|
+
## Example
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
// omdLeafNode is an abstract class—use concrete subclasses
|
|
59
|
+
import { omdConstantNode } from './omdConstantNode.js';
|
|
60
|
+
import { omdVariableNode } from './omdVariableNode.js';
|
|
61
|
+
import { omdOperatorNode } from './omdOperatorNode.js';
|
|
62
|
+
|
|
63
|
+
const constant = new omdConstantNode({ value: 5 });
|
|
64
|
+
const variable = new omdVariableNode({ name: 'x' });
|
|
65
|
+
const operator = new omdOperatorNode({ op: '+' });
|
|
66
|
+
|
|
67
|
+
// All leaf nodes handle text rendering and layout similarly
|
|
68
|
+
constant.initialize(); // Computes dimensions and layout
|
|
69
|
+
variable.initialize();
|
|
70
|
+
operator.initialize();
|
|
71
|
+
|
|
72
|
+
// You can then add these to an omdDisplay or other container
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## See Also
|
|
76
|
+
|
|
77
|
+
Concrete implementations:
|
|
78
|
+
|
|
79
|
+
- [`omdConstantNode`](./omdConstantNode.md) - For numeric values.
|
|
80
|
+
- [`omdVariableNode`](./omdVariableNode.md) - For variables.
|
|
81
|
+
- [`omdOperatorNode`](./omdOperatorNode.md) - For operators.
|
|
82
|
+
- [`omdGroupNode`](./omdGroupNode.md) - For grouping symbols.
|
|
83
|
+
|
|
84
|
+
Base class:
|
|
85
|
+
|
|
86
|
+
- [`omdNode`](./omdNode.md) - The fundamental base class for all OMD nodes.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# omdNode
|
|
2
|
+
|
|
3
|
+
The abstract base class for all nodes in the mathematical expression tree. It provides the core functionality for tree structure (parent-child relationships), layout calculations, rendering, and provenance tracking. All specific mathematical elements (constants, variables, operators, functions, equations) extend this class.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdNode extends omdMetaExpression
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This class is not meant to be instantiated directly. Instead, you should use one of its concrete subclasses (e.g., `omdConstantNode`, `omdBinaryExpressionNode`).
|
|
12
|
+
|
|
13
|
+
### Key Concepts
|
|
14
|
+
|
|
15
|
+
- **AST (Abstract Syntax Tree):** Each `omdNode` is typically created from a node in the math.js AST, providing a structured representation of the mathematical expression.
|
|
16
|
+
- **Tree Structure:** Nodes are organized in a hierarchical tree with `parent` and `childList` properties, enabling traversal and manipulation of the expression.
|
|
17
|
+
- **Layout:** The `computeDimensions()` and `updateLayout()` methods are fundamental for determining the size and position of a node and its children, ensuring correct visual rendering.
|
|
18
|
+
- **Provenance:** The `provenance` array on each node tracks its history. When a node is cloned (e.g., during a simplification step), the new node's provenance array will contain the ID of the original node, creating a traceable link back to its predecessor. This is crucial for features like step-by-step explanations and highlighting.
|
|
19
|
+
|
|
20
|
+
## Public Properties
|
|
21
|
+
|
|
22
|
+
- **`id`** (`number`): A unique identifier for each node instance, automatically assigned upon creation.
|
|
23
|
+
- **`type`** (`string`): A string indicating the specific type of the OMD node (e.g., `"omdConstantNode"`, `"omdBinaryExpressionNode"`).
|
|
24
|
+
- **`parent`** (`omdNode` | `null`): A reference to the parent node in the expression tree. `null` for the root node.
|
|
25
|
+
- **`astNodeData`** (`object`): The original math.js AST node from which this `omdNode` was created. This preserves the raw parsed data.
|
|
26
|
+
- **`provenance`** (`Array<number>`): An array of IDs from which this node was derived. This forms a historical chain, linking a node back through transformations or simplifications.
|
|
27
|
+
- **`argumentNodeList`** (`object`): A map (or object) containing references to the node's structurally significant children (e.g., `left`, `right` for binary expressions, `args` for functions). This is used for recursive operations and provenance tracking.
|
|
28
|
+
- **`isExplainHighlighted`** (`boolean`): A flag indicating if the node is currently highlighted for explanation purposes. This acts as a lock, preventing other highlights from overriding it.
|
|
29
|
+
- **`x`** (`number`): The x-coordinate of the node's top-left corner relative to its parent.
|
|
30
|
+
- **`y`** (`number`): The y-coordinate of the node's top-left corner relative to its parent.
|
|
31
|
+
- **`width`** (`number`): The calculated width of the node's bounding box.
|
|
32
|
+
- **`height`** (`number`): The calculated height of the node's bounding box.
|
|
33
|
+
- **`fontSize`** (`number`): The base font size applied to this node and its children.
|
|
34
|
+
- **`svgElement`** (`SVGElement`): The root SVG element that represents this node visually.
|
|
35
|
+
|
|
36
|
+
## Public Methods
|
|
37
|
+
|
|
38
|
+
### `initialize()`
|
|
39
|
+
|
|
40
|
+
Initializes the node by recursively computing its dimensions and updating its layout. This method should be called after a node and its children have been fully constructed to ensure proper sizing and positioning.
|
|
41
|
+
|
|
42
|
+
### `clone()`
|
|
43
|
+
|
|
44
|
+
Creates a deep, structural clone of the node. The new node will have a new `id`, and its `provenance` will link back to the original node's `id`, establishing a historical connection.
|
|
45
|
+
|
|
46
|
+
- **Returns**: `omdNode` - A new instance of the same type as the original, with all children also cloned.
|
|
47
|
+
|
|
48
|
+
### `replaceWith(newNode, options)`
|
|
49
|
+
|
|
50
|
+
Replaces this node with a `newNode` in the expression tree. This updates all parent and child references and triggers a re-layout and re-rendering of the affected parts of the SVG.
|
|
51
|
+
|
|
52
|
+
- **`newNode`** (`omdNode`): The node to substitute in.
|
|
53
|
+
- **`options`** (`object`, optional): Configuration for the replacement.
|
|
54
|
+
- `updateLayout` (`boolean`): If `true` (default), the layout of the entire tree will be recalculated upwards from the point of replacement.
|
|
55
|
+
- **Returns**: `boolean` - `true` if the replacement was successful.
|
|
56
|
+
|
|
57
|
+
### `simplify()`
|
|
58
|
+
|
|
59
|
+
Asynchronously attempts to simplify the expression rooted at this node by invoking the central simplification engine (`simplifyStep`).
|
|
60
|
+
|
|
61
|
+
- **Returns**: `Promise<object>` - A promise that resolves to an object like `{ success, foldedCount, newRoot, message }`. Throws an error if the `simplifyStep` function is not set.
|
|
62
|
+
|
|
63
|
+
### `toMathJSNode()`
|
|
64
|
+
|
|
65
|
+
Converts the `omdNode` and its children back into a math.js-compatible AST object. This method must be implemented by all concrete subclasses.
|
|
66
|
+
|
|
67
|
+
- **Returns**: `object` - The math.js AST node.
|
|
68
|
+
- **Throws**: `Error` if not implemented by the subclass.
|
|
69
|
+
|
|
70
|
+
### `toString()`
|
|
71
|
+
|
|
72
|
+
Converts the node into a human-readable string representation. It typically uses the `toMathJSNode()` method internally to leverage math.js's string conversion capabilities.
|
|
73
|
+
|
|
74
|
+
- **Returns**: `string`.
|
|
75
|
+
|
|
76
|
+
### `render()`
|
|
77
|
+
|
|
78
|
+
Generates or retrieves the SVG representation of the node. This method calls `renderSelf()` if the SVG element has not been created yet.
|
|
79
|
+
|
|
80
|
+
- **Returns**: `SVGElement` - The root SVG element representing this node.
|
|
81
|
+
|
|
82
|
+
### `renderSelf()`
|
|
83
|
+
|
|
84
|
+
Abstract method that must be implemented by subclasses. This method is responsible for creating the specific SVG elements and structure for the node's visual representation.
|
|
85
|
+
|
|
86
|
+
- **Returns**: `SVGElement` - The SVG element created for this node.
|
|
87
|
+
- **Throws**: `Error` if not implemented by the subclass.
|
|
88
|
+
|
|
89
|
+
### `setFontSize(size)`
|
|
90
|
+
|
|
91
|
+
Sets the base font size for this node and recursively propagates the new font size to all its children.
|
|
92
|
+
|
|
93
|
+
- **`size`** (`number`): The font size in pixels.
|
|
94
|
+
|
|
95
|
+
### `moveTo(x, y)`
|
|
96
|
+
|
|
97
|
+
Moves the node to a new absolute position (`x`, `y`) relative to its parent. It also recursively moves all children by the same delta.
|
|
98
|
+
|
|
99
|
+
- **`x`** (`number`): The new x-coordinate.
|
|
100
|
+
- **`y`** (`number`): The new y-coordinate.
|
|
101
|
+
|
|
102
|
+
### `show()`
|
|
103
|
+
|
|
104
|
+
Makes the node and its SVG representation visible.
|
|
105
|
+
|
|
106
|
+
### `hide()`
|
|
107
|
+
|
|
108
|
+
Hides the node and its SVG representation.
|
|
109
|
+
|
|
110
|
+
### `getDepth()`
|
|
111
|
+
|
|
112
|
+
Calculates the depth of the node in the expression tree (0 for the root node).
|
|
113
|
+
|
|
114
|
+
- **Returns**: `number` - The depth of the node.
|
|
115
|
+
|
|
116
|
+
### `findParentOfType(type)`
|
|
117
|
+
|
|
118
|
+
Traverses up the tree to find the nearest parent node of a specific type.
|
|
119
|
+
|
|
120
|
+
- **`type`** (`string`): The `type` property of the node to search for (e.g., `"omdEquationNode"`).
|
|
121
|
+
- **Returns**: `omdNode` | `null` - The found parent node or `null` if not found.
|
|
122
|
+
|
|
123
|
+
### `validateProvenance(nodeMap)`
|
|
124
|
+
|
|
125
|
+
Validates the provenance integrity of this node and all its descendants. It checks for duplicate IDs, invalid references, and self-references in the `provenance` arrays.
|
|
126
|
+
|
|
127
|
+
- **`nodeMap`** (`Map`, optional): An optional map of all known nodes in the system, used for cross-referencing provenance IDs.
|
|
128
|
+
- **Returns**: `Array<object>` - An array of validation issues found, each describing the type of issue, the node involved, and relevant IDs.
|
|
129
|
+
|
|
130
|
+
### `setHighlight(highlightOn, color)`
|
|
131
|
+
|
|
132
|
+
Applies or removes a highlight from the node's background. If `isExplainHighlighted` is `true`, this method will not override the existing explanation highlight.
|
|
133
|
+
|
|
134
|
+
- **`highlightOn`** (`boolean`): `true` to highlight, `false` to remove.
|
|
135
|
+
- **`color`** (`string`, optional): The color of the highlight. Defaults to `omdColor.highlightColor`.
|
|
136
|
+
|
|
137
|
+
### `lowlight()`
|
|
138
|
+
|
|
139
|
+
Reduces the opacity of the node's background. Similar to `setHighlight`, it respects the `isExplainHighlighted` lock.
|
|
140
|
+
|
|
141
|
+
### `setFillColor(color)`
|
|
142
|
+
|
|
143
|
+
Sets the fill color of the node's background rectangle. This method also respects the `isExplainHighlighted` lock.
|
|
144
|
+
|
|
145
|
+
## Abstract Methods (to be implemented by subclasses)
|
|
146
|
+
|
|
147
|
+
- **`computeDimensions()`**: Calculates the `width` and `height` of the node based on its content and children. Provides a default empty implementation.
|
|
148
|
+
- **`updateLayout()`**: Positions the node's children relative to itself. Provides a default empty implementation.
|
|
149
|
+
- **`getAlignmentBaseline()`**: Returns the vertical y-coordinate within the node's bounding box that should be used for alignment with its siblings. By default, this is the vertical center (`this.height / 2`).
|
|
150
|
+
- **`isConstant()`**: Determines if the node represents a constant numerical value. Returns `false` by default.
|
|
151
|
+
- **`getValue()`**: Retrieves the numerical value of a constant node. Throws an error if the node is not constant.
|
|
152
|
+
- **`getRationalValue()`**: Retrieves the rational value of a constant node as a numerator/denominator pair. Throws an error if the node is not a constant rational expression.
|
|
153
|
+
|
|
154
|
+
## Internal Methods
|
|
155
|
+
|
|
156
|
+
- **`_syncProvenanceFrom(originalNode)`**: Recursively walks a cloned node tree and sets the provenance of each node to point back to the corresponding node in the original tree. This is a crucial part of maintaining the provenance chain during cloning operations.
|
|
157
|
+
- **`replaceNodeInParent(newNode)`**: Helper method used by `replaceWith` to update specific references to this node within its parent's `argumentNodeList` and other properties.
|
|
158
|
+
- **`updateSvg(newNode)`**: Helper method used by `replaceWith` to perform the actual DOM manipulation (replacing SVG elements).
|
|
159
|
+
- **`updateLayoutUpwards()`**: Traverses up the tree from this node's parent to re-calculate dimensions and layouts for all ancestors, ensuring the entire affected tree is correctly rendered after a change.
|
|
160
|
+
- **`_validateStepsProvenance(issues)`**: Helper for `validateProvenance` to check provenance within steps.
|
|
161
|
+
- **`_findOrphanedNodes(issues)`**: Helper for `validateProvenance` to find nodes in the `nodeMap` that are no longer part of the active tree.
|
|
162
|
+
- **`_collectAllProvenanceIds(newNodeMap)`**: Collects all provenance IDs from nodes in a given map.
|
|
163
|
+
- **`_collectNodeProvenanceIds(node, referencedIds, processedNodes)`**: Recursively collects provenance IDs for a single node.
|
|
164
|
+
- **`_preserveReferencedNodes(referencedIds, newNodeMap)`**: Ensures that historical nodes referenced in provenance chains are kept in the `nodeMap`.
|
|
165
|
+
- **`_preserveNodeAndContext(id, newNodeMap, processedIds)`**: Preserves a historical node and its relevant parent/sibling context.
|
|
166
|
+
- **`_preserveParentContext(node, newNodeMap)`**: Preserves the parent nodes of a historical node.
|
|
167
|
+
- **`_preserveSiblingContext(node, newNodeMap)`**: Preserves the sibling nodes of a historical node.
|
|
168
|
+
|
|
169
|
+
## Example
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
// omdNode is an abstract class - use concrete subclasses
|
|
173
|
+
import { omdConstantNode } from './omdConstantNode.js';
|
|
174
|
+
import { omdBinaryExpressionNode } from './omdBinaryExpressionNode.js';
|
|
175
|
+
import { omdDisplay } from '../display/omdDisplay.js';
|
|
176
|
+
|
|
177
|
+
// Create a simple expression tree
|
|
178
|
+
const two = new omdConstantNode({ value: 2 });
|
|
179
|
+
const x = new omdVariableNode({ name: 'x' });
|
|
180
|
+
const twoX = new omdBinaryExpressionNode({
|
|
181
|
+
type: 'OperatorNode', op: '*', fn: 'multiply',
|
|
182
|
+
args: [two.astNodeData, x.astNodeData],
|
|
183
|
+
implicit: true
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Initialize the root node (this will recursively initialize children)
|
|
187
|
+
twoX.initialize();
|
|
188
|
+
|
|
189
|
+
// Render it using omdDisplay
|
|
190
|
+
const container = document.getElementById('math-container');
|
|
191
|
+
const display = new omdDisplay(container);
|
|
192
|
+
display.render(twoX);
|
|
193
|
+
|
|
194
|
+
console.log(twoX.toString()); // Output: 2x
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## See Also
|
|
198
|
+
|
|
199
|
+
- [`omdLeafNode`](./omdLeafNode.md) - The base class for nodes with no children (constants, variables, operators).
|
|
200
|
+
- [`omdBinaryExpressionNode`](./omdBinaryExpressionNode.md) - For nodes with two children (e.g., addition, subtraction, multiplication).
|
|
201
|
+
- [`omdFunctionNode`](./omdFunctionNode.md) - For function calls (e.g., `sin(x)`).
|
|
202
|
+
- [`omdEquationNode`](./omdEquationNode.md) - For representing mathematical equations.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# omdOperationDisplayNode
|
|
2
|
+
|
|
3
|
+
Represents a visual node for displaying an operation applied to both sides of an equation. This node is designed to show the operation (e.g., `+5` or `×2`) on both the left and right sides of an equation, typically used in step-by-step solution visualizers. It is non-interactive and non-highlightable by design.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdOperationDisplayNode extends omdNode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Static Properties
|
|
12
|
+
|
|
13
|
+
### `OPERATOR_SYMBOLS`
|
|
14
|
+
|
|
15
|
+
A static map that defines the display symbols for various operations.
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
static OPERATOR_SYMBOLS = {
|
|
19
|
+
'add': '+',
|
|
20
|
+
'subtract': '-',
|
|
21
|
+
'multiply': '×',
|
|
22
|
+
'divide': '÷'
|
|
23
|
+
};
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Constructor
|
|
27
|
+
|
|
28
|
+
### `new omdOperationDisplayNode(operation, value)`
|
|
29
|
+
|
|
30
|
+
Creates a new `omdOperationDisplayNode` instance.
|
|
31
|
+
|
|
32
|
+
- **`operation`** (`string`): The type of operation (e.g., `'add'`, `'subtract'`, `'multiply'`, `'divide'`).
|
|
33
|
+
- **`value`** (`number` | `string` | `omdNode`): The value being applied in the operation. Can be a number, a variable name string, or an `omdNode` instance.
|
|
34
|
+
|
|
35
|
+
During construction, the node initializes its display, creates the visual elements for the operation, disables all user interactions and highlighting, and adds the elements as children.
|
|
36
|
+
|
|
37
|
+
## Public Properties
|
|
38
|
+
|
|
39
|
+
- **`operation`** (`string`): The type of operation (e.g., `'add'`, `'subtract'`).
|
|
40
|
+
- **`value`** (`number` | `string` | `omdNode`): The value used in the operation.
|
|
41
|
+
- **`type`** (`string`): Always `"omdOperationDisplayNode"`.
|
|
42
|
+
- **`leftToken`** (`omdVariableNode`): The `omdVariableNode` representing the operation and value on the left side.
|
|
43
|
+
- **`rightToken`** (`omdVariableNode`): The `omdVariableNode` representing the operation and value on the right side.
|
|
44
|
+
- **`gap`** (`number`): The horizontal spacing between the left and right operation tokens.
|
|
45
|
+
- **`leftClusterWidth`** (`number`): The calculated width of the left operation token, used for alignment in equation sequences.
|
|
46
|
+
|
|
47
|
+
## Public Methods
|
|
48
|
+
|
|
49
|
+
### `computeDimensions()`
|
|
50
|
+
|
|
51
|
+
Calculates the dimensions (width and height) of the operation display node. It determines the total width by summing the widths of the left and right tokens and the `gap` between them. The height is based on the tallest token with some vertical padding.
|
|
52
|
+
|
|
53
|
+
### `updateLayout()`
|
|
54
|
+
|
|
55
|
+
Updates the layout of the operation display node. It positions the `leftToken` at the beginning and the `rightToken` after the calculated `gap`, ensuring they are vertically centered within the node's height.
|
|
56
|
+
|
|
57
|
+
### `getLeftWidthForAlignment()`
|
|
58
|
+
|
|
59
|
+
Returns the effective width of the left operation cluster. This is used by `omdEquationSequenceNode` to align the equals signs of equations with the center of the gap in the operation display.
|
|
60
|
+
|
|
61
|
+
- **Returns**: `number`.
|
|
62
|
+
|
|
63
|
+
### `showLeftOnly()`
|
|
64
|
+
|
|
65
|
+
Hides the right operation token and recalculates the dimensions and layout to display only the left operation. This is useful for scenarios where only one side of the operation needs to be shown.
|
|
66
|
+
|
|
67
|
+
### `clone()`
|
|
68
|
+
|
|
69
|
+
Creates a deep clone of the `omdOperationDisplayNode`. The cloned node will have the same operation and value, and its provenance will link back to the original node. The cloned node is also made non-highlightable.
|
|
70
|
+
|
|
71
|
+
- **Returns**: `omdOperationDisplayNode` - A new, identical instance.
|
|
72
|
+
|
|
73
|
+
## Internal Methods
|
|
74
|
+
|
|
75
|
+
- **`_initializeDisplay()`**: Sets up the initial display properties, making the background transparent and ensuring the node is non-highlightable.
|
|
76
|
+
- **`_createOperationElements()`**: Creates the `leftToken` and `rightToken` `omdVariableNode` instances based on the operation and value, and immediately disables their highlighting.
|
|
77
|
+
- **`_disableAllInteractions()`**: Calls helper methods to disable mouse interactions and highlighting for both operation tokens.
|
|
78
|
+
- **`_addChildElements()`**: Adds the `leftToken` and `rightToken` as children of this node.
|
|
79
|
+
- **`_getOperatorSymbol(operation)`**: Converts the operation name (e.g., `'add'`) to its corresponding display symbol (e.g., `'+'`).
|
|
80
|
+
- **`_valueToString(value)`**: Converts the input `value` (number, string, or `omdNode`) into a string representation for display.
|
|
81
|
+
- **`_disableElement(element)`**: Recursively disables background, mouse interactions, and highlighting for a given `omdNode` and its children.
|
|
82
|
+
- **`_hideElementBackground(element)`**: Sets the background of an element to transparent.
|
|
83
|
+
- **`_disableMouseInteractions(element)`**: Removes mouse event listeners and sets the cursor to `'default'`.
|
|
84
|
+
- **`_disableHighlighting(element)`**: Overrides highlighting methods (`setHighlight`, `lowlight`, `setFillColor`) on an element to prevent it from being highlighted.
|
|
85
|
+
- **`_makeNodeNonHighlightable()`**: Applies the `_disableHighlighting` logic to the `omdOperationDisplayNode` itself.
|
|
86
|
+
- **`_disableChildElements(element)`**: Recursively calls `_disableElement` on all children of a given element.
|
|
87
|
+
|
|
88
|
+
## Example
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
// Create operation display for subtracting 3
|
|
92
|
+
const subtractNode = new omdOperationDisplayNode('subtract', 3);
|
|
93
|
+
|
|
94
|
+
// Create operation display for multiplying by 'x'
|
|
95
|
+
const multiplyNode = new omdOperationDisplayNode('multiply', 'x');
|
|
96
|
+
|
|
97
|
+
// Create operation display for dividing by a complex expression
|
|
98
|
+
const complexDivideNode = new omdOperationDisplayNode('divide', {
|
|
99
|
+
type: 'OperatorNode',
|
|
100
|
+
op: '+',
|
|
101
|
+
args: [
|
|
102
|
+
{ type: 'ConstantNode', value: 1 },
|
|
103
|
+
{ type: 'SymbolNode', name: 'x' }
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// To render these, you would typically add them to an omdEquationSequenceNode
|
|
108
|
+
// or an omdDisplay.
|
|
109
|
+
// For example:
|
|
110
|
+
// const display = new omdDisplay(document.getElementById('container'));
|
|
111
|
+
// display.render(subtractNode);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## See Also
|
|
115
|
+
|
|
116
|
+
- [`omdNode`](./omdNode.md) - The base class for all OMD nodes.
|
|
117
|
+
- [`omdEquationNode`](./omdEquationNode.md) - For representing mathematical equations.
|
|
118
|
+
- [`omdEquationSequenceNode`](./omdEquationSequenceNode.md) - For managing sequences of equation steps.
|