all files / model/ Selection.js

54.55% Statements 24/44
41.67% Branches 5/12
59.09% Functions 13/22
54.55% Lines 24/44
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172              1197× 1197×         1197×                             55× 55×     55×       1653×                     1425× 1425×           409×         756×         1714×         1776×   3771×                   29×                           16×   16×   16×   16×         16×                                                                             1240×                                              
/**
  A document selection. Refers to a Substance document model, not to the DOM.
*/
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
    Iif (!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()
  }
 
  /**
    @returns {Boolean} true if selection equals `other` selection
  */
  equals(other) {
    Iif (this === other) {
      return true
    } else Iif (!other) {
      return false
    } else Iif (this.isNull() !== other.isNull()) {
      return false
    } else Iif (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) {
    let SelectionClass = this.constructor
    let data = this.toJSON()
    Object.assign(data, update)
    return SelectionClass.fromJSON(data)
  }
}
 
// for duck-typed instanceof
Selection.prototype._isSelection = true
 
/*
  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}
*/
 
Selection.nullSelection = Object.freeze(new NullSelection())
 
export default Selection