104 lines
3.2 KiB
JavaScript
104 lines
3.2 KiB
JavaScript
|
import { mac } from "./browser.js"
|
||
|
import { indexOf } from "./misc.js"
|
||
|
|
||
|
// EVENT HANDLING
|
||
|
|
||
|
// Lightweight event framework. on/off also work on DOM nodes,
|
||
|
// registering native DOM handlers.
|
||
|
|
||
|
const noHandlers = []
|
||
|
|
||
|
export let on = function(emitter, type, f) {
|
||
|
if (emitter.addEventListener) {
|
||
|
emitter.addEventListener(type, f, false)
|
||
|
} else if (emitter.attachEvent) {
|
||
|
emitter.attachEvent("on" + type, f)
|
||
|
} else {
|
||
|
let map = emitter._handlers || (emitter._handlers = {})
|
||
|
map[type] = (map[type] || noHandlers).concat(f)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function getHandlers(emitter, type) {
|
||
|
return emitter._handlers && emitter._handlers[type] || noHandlers
|
||
|
}
|
||
|
|
||
|
export function off(emitter, type, f) {
|
||
|
if (emitter.removeEventListener) {
|
||
|
emitter.removeEventListener(type, f, false)
|
||
|
} else if (emitter.detachEvent) {
|
||
|
emitter.detachEvent("on" + type, f)
|
||
|
} else {
|
||
|
let map = emitter._handlers, arr = map && map[type]
|
||
|
if (arr) {
|
||
|
let index = indexOf(arr, f)
|
||
|
if (index > -1)
|
||
|
map[type] = arr.slice(0, index).concat(arr.slice(index + 1))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function signal(emitter, type /*, values...*/) {
|
||
|
let handlers = getHandlers(emitter, type)
|
||
|
if (!handlers.length) return
|
||
|
let args = Array.prototype.slice.call(arguments, 2)
|
||
|
for (let i = 0; i < handlers.length; ++i) handlers[i].apply(null, args)
|
||
|
}
|
||
|
|
||
|
// The DOM events that CodeMirror handles can be overridden by
|
||
|
// registering a (non-DOM) handler on the editor for the event name,
|
||
|
// and preventDefault-ing the event in that handler.
|
||
|
export function signalDOMEvent(cm, e, override) {
|
||
|
if (typeof e == "string")
|
||
|
e = {type: e, preventDefault: function() { this.defaultPrevented = true }}
|
||
|
signal(cm, override || e.type, cm, e)
|
||
|
return e_defaultPrevented(e) || e.codemirrorIgnore
|
||
|
}
|
||
|
|
||
|
export function signalCursorActivity(cm) {
|
||
|
let arr = cm._handlers && cm._handlers.cursorActivity
|
||
|
if (!arr) return
|
||
|
let set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = [])
|
||
|
for (let i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
|
||
|
set.push(arr[i])
|
||
|
}
|
||
|
|
||
|
export function hasHandler(emitter, type) {
|
||
|
return getHandlers(emitter, type).length > 0
|
||
|
}
|
||
|
|
||
|
// Add on and off methods to a constructor's prototype, to make
|
||
|
// registering events on such objects more convenient.
|
||
|
export function eventMixin(ctor) {
|
||
|
ctor.prototype.on = function(type, f) {on(this, type, f)}
|
||
|
ctor.prototype.off = function(type, f) {off(this, type, f)}
|
||
|
}
|
||
|
|
||
|
// Due to the fact that we still support jurassic IE versions, some
|
||
|
// compatibility wrappers are needed.
|
||
|
|
||
|
export function e_preventDefault(e) {
|
||
|
if (e.preventDefault) e.preventDefault()
|
||
|
else e.returnValue = false
|
||
|
}
|
||
|
export function e_stopPropagation(e) {
|
||
|
if (e.stopPropagation) e.stopPropagation()
|
||
|
else e.cancelBubble = true
|
||
|
}
|
||
|
export function e_defaultPrevented(e) {
|
||
|
return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false
|
||
|
}
|
||
|
export function e_stop(e) {e_preventDefault(e); e_stopPropagation(e)}
|
||
|
|
||
|
export function e_target(e) {return e.target || e.srcElement}
|
||
|
export function e_button(e) {
|
||
|
let b = e.which
|
||
|
if (b == null) {
|
||
|
if (e.button & 1) b = 1
|
||
|
else if (e.button & 2) b = 3
|
||
|
else if (e.button & 4) b = 2
|
||
|
}
|
||
|
if (mac && e.ctrlKey && b == 1) b = 3
|
||
|
return b
|
||
|
}
|