UNPKG

wed

Version:

Wed is a schema-aware editor for XML documents.

177 lines 7 kB
define(["require", "exports", "./domutil", "./selection-mode"], function (require, exports, domutil_1, selection_mode_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // tslint:disable-next-line:no-http-string exports.CLIPBOARD_NS = "http://mangalamresearch.org/ns/wed/clipboard"; /** * An internal clipboard for wed editors. * * Due to the limitations of the clipboard API, wed maintains an internal * clipboard which allows it to transfer data in a way meaningful to wed. */ class Clipboard { constructor() { this.tree = new DOMParser().parseFromString("<div/>", "text/xml"); this.top = this.tree.firstElementChild; this._mode = selection_mode_1.SelectionMode.SPAN; } /** * The clipboard switches selection mode on the basis of how data is added to * it, and the mode remains in effect until data is added in a way that * changes the mode. * * Note that this property is **independent** of what the GUI is showing to * the user. The property "remembers", so to speak, how the clipboard has been * used. */ get mode() { return this._mode; } /** * Sets the selection mode of this clipboard. * * @param vale The new mode. */ setMode(value) { if (value !== this._mode) { this.clear(); } this._mode = value; } /** * Clear the clipboard. * * Note that this clears only the contents of this object. **IT DOES NOT * AFFECT THE BROWSER'S CLIPBOARD!** */ clear() { // Empty the div. // tslint:disable-next-line:no-inner-html this.top.innerHTML = ""; } /** * Puts a span of nodes into the clipboard. This method switches the clipboard * to the span mode. * * Note that the clipboard is cleared before adding the nodes. * * @param nodes The nodes to put. These nodes become property of the clipboard * after being added. If you want to keep the nodes in another document, clone * them first. */ putSpan(span) { this.clear(); this.setMode(selection_mode_1.SelectionMode.SPAN); if (typeof span === "string") { this.top.textContent = span; } else { const { tree, top } = this; for (const node of span) { top.appendChild(tree.adoptNode(node)); } } } /** * Check whether a node can be added to this clipboard's data. Clipboards * cannot contain heterogenous data. An attribute can be added only if the * clipboard is empty or contains attributes. Another type of node can be * added only if the clipboard does not contain attributes. * * @param node The node to check. * * @returns Whether the node can be added to this clipboard's data. */ canAddUnit(node) { const { top } = this; return domutil_1.isAttr(node) ? (top.firstElementChild === null || containsClipboardAttributeCollection(top)) : !containsClipboardAttributeCollection(top); } /** * Puts a DOM node in the clipboard. This method switches the clipboard to * unit mode. * * Note that the clipboard is cleared before adding the node. * * @param node The node to put. This node becomes property of the clipboard * after being added. If you want to keep it in another document, clone it * first. * * @param add Add to the clipboard, rather than replace the contents. */ putUnit(node, add) { this.setMode(selection_mode_1.SelectionMode.UNIT); const { top } = this; if (domutil_1.isAttr(node)) { let collection; if (add && containsClipboardAttributeCollection(top)) { collection = top.firstElementChild; } else { // In order to record a collection of attributes, we set the tree to // contain a single element on which we set the attributes we want to // move around. this.clear(); collection = top.ownerDocument.createElementNS(exports.CLIPBOARD_NS, "wed:attributes"); top.appendChild(collection); } collection.setAttributeNode(node); } else { if (!add || containsClipboardAttributeCollection(top)) { this.clear(); } top.appendChild(this.tree.adoptNode(node)); } } /** * Determines whether, in a paste operation, the tree that is stored in this * clipboard, serialized, is equal to some text. * * This can be used as an optimization to avoid parsing anew ``text`` if the * tree in the clipboard is already a parsed representation of that text. * * @param text The text to test against. */ isSerializedTree(text) { return this.top.innerHTML === text; } /** * @returns A deep copy of the tree in this clipboard. */ cloneTree() { return this.top.cloneNode(true); } /** * Set the DOM clipboard data to reflect what is stored in this wed-internal * clipboard. Note that any old data in the DOM clipboard data is cleared * before setting the new data. * * @param clipboardData The object to set. */ setupDOMClipboardData(clipboardData) { const { top } = this; clipboardData.clearData(); clipboardData.setData("text/plain", top.textContent); clipboardData.setData("text/xml", top.innerHTML); } } exports.Clipboard = Clipboard; /** * Check whether the element has a single child element which is a collection of * attributes. * * @param el The element to check. * * @returns Whether the element contains an attribute collection. */ function containsClipboardAttributeCollection(el) { const first = el.firstElementChild; return el.childNodes.length === 1 && first !== null && first.namespaceURI === exports.CLIPBOARD_NS && first.localName === "attributes"; } exports.containsClipboardAttributeCollection = containsClipboardAttributeCollection; }); //# sourceMappingURL=clipboard.js.map