UNPKG

substance

Version:

Substance is a JavaScript library for web-based content editing. It provides building blocks for realizing custom text editors and web-based publishing system. It is developed to power our online editing platform [Substance](http://substance.io).

173 lines (143 loc) 3.28 kB
/** A document selection. Refers to a Substance document model, not to the DOM. */ export default class Selection { constructor () { // Internal stuff var _internal = {} Object.defineProperty(this, '_internal', { enumerable: false, value: _internal }) // set when attached to document _internal.doc = null } clone () { var newSel = this._clone() if (this._internal.doc) { newSel.attach(this._internal.doc) } return newSel } /** @returns {Document} The attached document instance */ getDocument () { var doc = this._internal.doc if (!doc) { throw new Error('Selection is not attached to a document.') } return doc } isAttached () { return Boolean(this._internal.doc) } /** Attach document to the selection. @internal @param {Document} doc document to attach @returns {this} */ attach (doc) { this._internal.doc = doc return this } /** @returns {Boolean} true when selection is null. */ isNull () { return false } /** @returns {Boolean} true for property selections */ isPropertySelection () { return false } /** @returns {Boolean} true if selection is a {@link model/ContainerSelection} */ isContainerSelection () { return false } /** @returns {Boolean} true if selection is a {@link model/NodeSelection} */ isNodeSelection () { return false } isCustomSelection () { return false } /** @returns {Boolean} true when selection is collapsed */ isCollapsed () { return true } /** @returns {Boolean} true if startOffset < endOffset */ isReverse () { return false } getType () { throw new Error('Selection.getType() is abstract.') } get type () { return this.getType() } getNodeId () { return null } /** @returns {Boolean} true if selection equals `other` selection */ equals (other) { if (this === other) { return true } else if (!other) { return false } else if (this.isNull() !== other.isNull()) { return false } else if (this.getType() !== other.getType()) { return false } else { // Note: returning true here, so that sub-classes // can call this as a predicate in their expression return true } } /** @returns {String} This selection as human readable string. */ toString () { return 'null' } /** Convert container selection to JSON. @abstract @returns {Object} */ toJSON () { throw new Error('This method is abstract.') } createWith (update) { const SelectionClass = this.constructor const data = this.toJSON() Object.assign(data, update) return SelectionClass.fromJSON(data) } // for duck-typed instanceof get _isSelection () { return true } static get nullSelection () { return NULL_SELECTION } } /* Class to represent null selections. @internal */ class NullSelection extends Selection { isNull () { return true } getType () { return 'null' } toJSON () { return null } clone () { return this } } /** We use a singleton to represent NullSelections. @type {model/Selection} */ const NULL_SELECTION = Object.freeze(new NullSelection())