You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							116 lines
						
					
					
						
							3.1 KiB
						
					
					
				
			
		
		
	
	
							116 lines
						
					
					
						
							3.1 KiB
						
					
					
				import Parchment from 'parchment'; | 
						|
import TextBlot from './text'; | 
						|
 | 
						|
 | 
						|
class Cursor extends Parchment.Embed { | 
						|
  static value() { | 
						|
    return undefined; | 
						|
  } | 
						|
 | 
						|
  constructor(domNode, selection) { | 
						|
    super(domNode); | 
						|
    this.selection = selection; | 
						|
    this.textNode = document.createTextNode(Cursor.CONTENTS); | 
						|
    this.domNode.appendChild(this.textNode); | 
						|
    this._length = 0; | 
						|
  } | 
						|
 | 
						|
  detach() { | 
						|
    // super.detach() will also clear domNode.__blot | 
						|
    if (this.parent != null) this.parent.removeChild(this); | 
						|
  } | 
						|
 | 
						|
  format(name, value) { | 
						|
    if (this._length !== 0) { | 
						|
      return super.format(name, value); | 
						|
    } | 
						|
    let target = this, index = 0; | 
						|
    while (target != null && target.statics.scope !== Parchment.Scope.BLOCK_BLOT) { | 
						|
      index += target.offset(target.parent); | 
						|
      target = target.parent; | 
						|
    } | 
						|
    if (target != null) { | 
						|
      this._length = Cursor.CONTENTS.length; | 
						|
      target.optimize(); | 
						|
      target.formatAt(index, Cursor.CONTENTS.length, name, value); | 
						|
      this._length = 0; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  index(node, offset) { | 
						|
    if (node === this.textNode) return 0; | 
						|
    return super.index(node, offset); | 
						|
  } | 
						|
 | 
						|
  length() { | 
						|
    return this._length; | 
						|
  } | 
						|
 | 
						|
  position() { | 
						|
    return [this.textNode, this.textNode.data.length]; | 
						|
  } | 
						|
 | 
						|
  remove() { | 
						|
    super.remove(); | 
						|
    this.parent = null; | 
						|
  } | 
						|
 | 
						|
  restore() { | 
						|
    if (this.selection.composing || this.parent == null) return; | 
						|
    let textNode = this.textNode; | 
						|
    let range = this.selection.getNativeRange(); | 
						|
    let restoreText, start, end; | 
						|
    if (range != null && range.start.node === textNode && range.end.node === textNode) { | 
						|
      [restoreText, start, end] = [textNode, range.start.offset, range.end.offset]; | 
						|
    } | 
						|
    // Link format will insert text outside of anchor tag | 
						|
    while (this.domNode.lastChild != null && this.domNode.lastChild !== this.textNode) { | 
						|
      this.domNode.parentNode.insertBefore(this.domNode.lastChild, this.domNode); | 
						|
    } | 
						|
    if (this.textNode.data !== Cursor.CONTENTS) { | 
						|
      let text = this.textNode.data.split(Cursor.CONTENTS).join(''); | 
						|
      if (this.next instanceof TextBlot) { | 
						|
        restoreText = this.next.domNode; | 
						|
        this.next.insertAt(0, text); | 
						|
        this.textNode.data = Cursor.CONTENTS; | 
						|
      } else { | 
						|
        this.textNode.data = text; | 
						|
        this.parent.insertBefore(Parchment.create(this.textNode), this); | 
						|
        this.textNode = document.createTextNode(Cursor.CONTENTS); | 
						|
        this.domNode.appendChild(this.textNode); | 
						|
      } | 
						|
    } | 
						|
    this.remove(); | 
						|
    if (start != null) { | 
						|
      [start, end] = [start, end].map(function(offset) { | 
						|
        return Math.max(0, Math.min(restoreText.data.length, offset - 1)); | 
						|
      }); | 
						|
      return { | 
						|
        startNode: restoreText, | 
						|
        startOffset: start, | 
						|
        endNode: restoreText, | 
						|
        endOffset: end | 
						|
      }; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  update(mutations, context) { | 
						|
    if (mutations.some((mutation) => { | 
						|
      return mutation.type === 'characterData' && mutation.target === this.textNode; | 
						|
    })) { | 
						|
      let range = this.restore(); | 
						|
      if (range) context.range = range; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  value() { | 
						|
    return ''; | 
						|
  } | 
						|
} | 
						|
Cursor.blotName = 'cursor'; | 
						|
Cursor.className = 'ql-cursor'; | 
						|
Cursor.tagName = 'span'; | 
						|
Cursor.CONTENTS = "\uFEFF";   // Zero width no break space | 
						|
 | 
						|
 | 
						|
export default Cursor;
 | 
						|
 |