event.js (3262B)
1 import { mac } from "./browser.js" 2 import { indexOf } from "./misc.js" 3 4 // EVENT HANDLING 5 6 // Lightweight event framework. on/off also work on DOM nodes, 7 // registering native DOM handlers. 8 9 const noHandlers = [] 10 11 export let on = function(emitter, type, f) { 12 if (emitter.addEventListener) { 13 emitter.addEventListener(type, f, false) 14 } else if (emitter.attachEvent) { 15 emitter.attachEvent("on" + type, f) 16 } else { 17 let map = emitter._handlers || (emitter._handlers = {}) 18 map[type] = (map[type] || noHandlers).concat(f) 19 } 20 } 21 22 export function getHandlers(emitter, type) { 23 return emitter._handlers && emitter._handlers[type] || noHandlers 24 } 25 26 export function off(emitter, type, f) { 27 if (emitter.removeEventListener) { 28 emitter.removeEventListener(type, f, false) 29 } else if (emitter.detachEvent) { 30 emitter.detachEvent("on" + type, f) 31 } else { 32 let map = emitter._handlers, arr = map && map[type] 33 if (arr) { 34 let index = indexOf(arr, f) 35 if (index > -1) 36 map[type] = arr.slice(0, index).concat(arr.slice(index + 1)) 37 } 38 } 39 } 40 41 export function signal(emitter, type /*, values...*/) { 42 let handlers = getHandlers(emitter, type) 43 if (!handlers.length) return 44 let args = Array.prototype.slice.call(arguments, 2) 45 for (let i = 0; i < handlers.length; ++i) handlers[i].apply(null, args) 46 } 47 48 // The DOM events that CodeMirror handles can be overridden by 49 // registering a (non-DOM) handler on the editor for the event name, 50 // and preventDefault-ing the event in that handler. 51 export function signalDOMEvent(cm, e, override) { 52 if (typeof e == "string") 53 e = {type: e, preventDefault: function() { this.defaultPrevented = true }} 54 signal(cm, override || e.type, cm, e) 55 return e_defaultPrevented(e) || e.codemirrorIgnore 56 } 57 58 export function signalCursorActivity(cm) { 59 let arr = cm._handlers && cm._handlers.cursorActivity 60 if (!arr) return 61 let set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []) 62 for (let i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1) 63 set.push(arr[i]) 64 } 65 66 export function hasHandler(emitter, type) { 67 return getHandlers(emitter, type).length > 0 68 } 69 70 // Add on and off methods to a constructor's prototype, to make 71 // registering events on such objects more convenient. 72 export function eventMixin(ctor) { 73 ctor.prototype.on = function(type, f) {on(this, type, f)} 74 ctor.prototype.off = function(type, f) {off(this, type, f)} 75 } 76 77 // Due to the fact that we still support jurassic IE versions, some 78 // compatibility wrappers are needed. 79 80 export function e_preventDefault(e) { 81 if (e.preventDefault) e.preventDefault() 82 else e.returnValue = false 83 } 84 export function e_stopPropagation(e) { 85 if (e.stopPropagation) e.stopPropagation() 86 else e.cancelBubble = true 87 } 88 export function e_defaultPrevented(e) { 89 return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false 90 } 91 export function e_stop(e) {e_preventDefault(e); e_stopPropagation(e)} 92 93 export function e_target(e) {return e.target || e.srcElement} 94 export function e_button(e) { 95 let b = e.which 96 if (b == null) { 97 if (e.button & 1) b = 1 98 else if (e.button & 2) b = 3 99 else if (e.button & 4) b = 2 100 } 101 if (mac && e.ctrlKey && b == 1) b = 3 102 return b 103 }