docs: function RangeTreeNode(parent) {
  
        /** @type {onselect.RangeTreeNode} */
        this.parent = parent;
  
        /** @type {{node: Node, index: number}} */
        this.start = undefined;
  
        /** @type {{node: Node, index: number}} */
        this.end = undefined;
  
        /** @type {[onselect.RangeTreeNode]} */
        this.children = [];
  
        /**
         * @memberOf onselect.RangeTreeNode
         * @name setStart
         * @param {Node} node
         * @param {number} index
         *
         * @description
         *
         */
        this.setStart = function (node, index) {
          this.start = {node: node, index: index};
        };
  
        this.setEnd = function (node, index) {
          this.end = {node: node, index: index};
        };
  
        this.getParent = function () {
          if (!this.parent) {
            this.parent = new RangeTreeNode();
            this.parent.children.push(this);
          }
          return this.parent;
        };
  
        this.createNewChild = function () {
          var child = new RangeTreeNode(this);
          this.children.push(child);
          return child;
        };
  
        this.getNextSibling = function () {
          return this.getParent().createNewChild();
        };
  
        this.toRanges = function () {
          var top = this;
          while (top.parent) {
            top = top.parent;
          }
          return _toRangesRecursive(top, []);
        };
  
        function _toRangesRecursive(node, list) {
          if (node.start && node.end) {
            var range = $window.document.createRange();
            range.setStart(node.start.node, node.start.index);
            range.setEnd(node.end.node, node.end.index);
  
            list.push(range);
          }
  
          for (var c in node.children) {
            _toRangesRecursive(node.children[c], list);
          }
  
          return list;
        }
      }