all files / ui/ GlobalEventHandler.js

33.33% Statements 11/33
12.5% Branches 2/16
33.33% Functions 3/9
33.33% Lines 11/33
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                                              206× 206× 206× 206×       206× 168× 168× 1008×                                                                                                              
/*
  Experimental
 
  We are seeking for a solution providing access to global DOM events
  while considering the current app state ~ document session state.
 
  This implementation is just a prototype and might change with the next releases.
*/
 
import { DOMElement, DOMEventListener, DefaultDOMElement } from '../dom'
import { platform } from '../util'
 
/*
  TODO: to be 100% safe we would need to introduce a hidden contenteditable
  where we put the selection in case of non-surface situations
  so that we are still able to receive events such as 'copy' -- actually only Edge is not dispatching
  to window.document.
*/
 
const events = [ 'keydown', 'keyup', 'keypress', 'mousedown', 'mouseup' , 'copy' ]
 
class GlobalEventHandler {
 
  constructor(editorSession, surfaceManager) {
    this.editorSession = editorSession
    this.surfaceManager = surfaceManager
    this.listeners = []
    this.initialize()
  }
 
  initialize() {
    if (platform.inBrowser) {
      let document = DefaultDOMElement.wrapNativeElement(window.document)
      events.forEach(function(name) {
        document.on(name, this._dispatch.bind(this, name), this)
      }.bind(this))
    }
  }
 
  dispose() {
    if (platform.inBrowser) {
      let document = DefaultDOMElement.wrapNativeElement(window.document)
      document.off(this)
    }
  }
 
  addEventListener(eventName, handler, options) {
    if (!options.id) {
      throw new Error("GlobalEventHandler can only be used with option 'id'")
    }
    let listener = new DOMEventListener(eventName, handler, options)
    this.listeners.push(listener)
  }
 
  removeEventListener(listener) {
    let idx = this.listeners.indexOf(listener);
    if (idx > -1) {
      this.listeners.splice(idx, 1)
    }
  }
 
  getEventListeners() {
    return this.listeners
  }
 
  _getActiveListener(eventName) {
    let editorSession = this.editorSession
    let sel = editorSession.getSelection()
    if (sel) {
      let surfaceId = sel.surfaceId
      for (let i = 0; i < this.listeners.length; i++) {
        let listener = this.listeners[i]
        if (listener.eventName === eventName && listener.options.id === surfaceId) {
          return listener
        }
      }
    }
  }
 
  _dispatch(eventName, e) {
    let listener = this._getActiveListener(eventName)
    if (listener) {
      listener.handler(e)
    }
  }
}
 
GlobalEventHandler.prototype.on = DOMElement.prototype.on
GlobalEventHandler.prototype.off = DOMElement.prototype.off
 
export default GlobalEventHandler