Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions to manage math items within a given container. (#351) #502

Merged
merged 4 commits into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ts/adaptors/HTMLAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export interface MinHTMLElement<N, T> {
/* tslint:disable:jsdoc-require */
getElementsByTagName(name: string): N[] | HTMLCollectionOf<Element>;
getElementsByTagNameNS(ns: string, name: string): N[] | HTMLCollectionOf<Element>;
contains(child: N | T): boolean;
appendChild(child: N | T): N | T | Node;
removeChild(child: N | T): N | T | Node;
replaceChild(nnode: N | T, onode: N | T): N | T | Node;
Expand Down Expand Up @@ -254,6 +255,13 @@ AbstractDOMAdaptor<N, T, D> implements MinHTMLAdaptor<N, T, D> {
return containers;
}

/**
* @override
*/
public contains(container: N, node: N | T) {
return container.contains(node);
}

/**
* @override
*/
Expand Down
12 changes: 12 additions & 0 deletions ts/adaptors/liteAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,16 @@ export class LiteAdaptor extends AbstractDOMAdaptor<LiteElement, LiteText, LiteD
return containers;
}

/**
* @override
*/
public contains(container: LiteNode, node: LiteNode | LiteText) {
while (node && node !== container) {
node = this.parent(node);
}
return !!node;
}

/**
* @override
*/
Expand Down Expand Up @@ -295,6 +305,8 @@ export class LiteAdaptor extends AbstractDOMAdaptor<LiteElement, LiteText, LiteD
const i = this.childIndex(onode);
if (i >= 0) {
onode.parent.children[i] = nnode;
nnode.parent = onode.parent;
onode.parent = null;
}
return onode;
}
Expand Down
13 changes: 10 additions & 3 deletions ts/components/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,19 +327,26 @@ export namespace Startup {
* TypeseClear() clears all the MathItems from the document.
*/
export function makeTypesetMethods() {
MathJax.typeset = (elements: any = null) => {
MathJax.typeset = (elements: any[] = null) => {
document.options.elements = elements;
document.reset();
document.render();
};
MathJax.typesetPromise = (elements: any = null) => {
MathJax.typesetPromise = (elements: any[] = null) => {
document.options.elements = elements;
document.reset();
return mathjax.handleRetriesFor(() => {
document.render();
});
};
MathJax.typesetClear = () => document.clear();
MathJax.typesetClear = (elements: any[] = null) => {
if (elements) {
document.reset();
document.clearMathItemsWithin(elements);
} else {
document.clear();
}
};
}

/**
Expand Down
14 changes: 14 additions & 0 deletions ts/core/DOMAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ export interface DOMAdaptor<N, T, D> {
*/
getElements(nodes: (string | N | N[])[], document: D): N[];

/**
* Determine if a container node contains a given node in somewhere in its DOM tree
dpvc marked this conversation as resolved.
Show resolved Hide resolved
*
* @param {N} container The container to search
* @param {N|T} node The node to look for
* @return {boolean} True if the node is in the container's DOM tree
*/
contains(container: N, node: N | T): boolean;

/**
* @param {N|T} node The HTML node whose parent is to be obtained
* @return {N} The parent node of the given one
Expand Down Expand Up @@ -431,6 +440,11 @@ export abstract class AbstractDOMAdaptor<N, T, D> implements DOMAdaptor<N, T, D>
*/
public abstract getElements(nodes: (string | N | N[])[], document: D): N[];

/**
* @override
*/
public abstract contains(container: N, node: N | T): boolean;

/**
* @override
*/
Expand Down
55 changes: 55 additions & 0 deletions ts/core/MathDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,15 @@ export class RenderList<N, T, D> extends PrioritizedList<RenderData<N, T, D>> {

}

/*****************************************************************/
/**
* The ways of specifying a container (a selector string, an actual node,
* or an array of those (e.g., the result of document.getElementsByTagName())
*
* @template N The HTMLElement node class
*/
export type ContainerList<N> = string | N | (string | N | N[])[];

/*****************************************************************/
/**
* The MathDocument interface
Expand Down Expand Up @@ -428,6 +437,24 @@ export interface MathDocument<N, T, D> {
*/
concat(list: MathList<N, T, D>): MathDocument<N, T, D>;

/**
* Clear the typeset MathItems that are within the given container
* from the document's MathList. (E.g., when the content of the
* container has been updated and you want to remove the
* associated MathItems)
*
* @param {ContainerList<N>} elements The container DOM elements whose math items are to be removed
*/
clearMathItemsWithin(containers: ContainerList<N>): void;

/**
* Get the typeset MathItems that are within a given container.
*
* @param {ContainerList<N>} elements The container DOM elements whose math items are to be found
* @return {MathItem<N,T,D>[]} The list of MathItems within that container
*/
getMathItemsWithin(elements: ContainerList<N>): MathItem<N, T, D>[];

}

/*****************************************************************/
Expand Down Expand Up @@ -857,6 +884,34 @@ export abstract class AbstractMathDocument<N, T, D> implements MathDocument<N, T
return this;
}

/**
* @override
*/
public clearMathItemsWithin(containers: ContainerList<N>) {
this.math.remove(...this.getMathItemsWithin(containers));
}

/**
* @override
*/
public getMathItemsWithin(elements: ContainerList<N>) {
if (!Array.isArray(elements)) {
elements = [elements];
}
const adaptor = this.adaptor;
const items = [] as MathItem<N, T, D>[];
const containers = adaptor.getElements(elements, this.document);
ITEMS: for (const item of this.math) {
dpvc marked this conversation as resolved.
Show resolved Hide resolved
for (const container of containers) {
if (item.start.node && adaptor.contains(container, item.start.node)) {
items.push(item);
continue ITEMS;
}
}
}
return items;
}

}

/**
Expand Down
24 changes: 23 additions & 1 deletion ts/util/LinkedList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* A symbol used to mark the special node used to indicate
* the start and end of the list.
*/
const END = Symbol();
export const END = Symbol();

/**
* Shorthand type for the functions used to sort the data items
Expand Down Expand Up @@ -190,6 +190,28 @@ export class LinkedList<DataClass> {
return item.data as DataClass;
}

/**
* Remove items from the list
*
* @param {DataClass[]} items The items to remove
*/
public remove(...items: DataClass[]) {
const map = new Map<DataClass, boolean>();
for (const item of items) {
map.set(item, true);
}
let item = this.list.next;
while (item.data !== END) {
const next = item.next;
if (map.has(item.data as DataClass)) {
item.prev.next = item.next;
item.next.prev = item.prev;
item.next = item.prev = null;
}
item = next;
}
}

/**
* Empty the list
*
Expand Down