UNPKG

coffeescript-ui

Version:
301 lines (229 loc) 6.4 kB
### * coffeescript-ui - Coffeescript User Interface System (CUI) * Copyright (c) 2013 - 2016 Programmfabrik GmbH * MIT Licence * https://github.com/programmfabrik/coffeescript-ui, http://www.coffeescript-ui.org ### class CUI.Event extends CUI.Element constructor: (opts) -> super(opts) if @_require_node_in_dom console.debug "require node in dom", @isInDOM(), @__node CUI.util.assert(@isInDOM(), "new Event", "node is not in DOM, unable to create event.", opts: @opts) @__propagationStopped = false @__propagationImmediateStopped = false @__preventDefault = false @__dragPrevented = false initOpts: -> super() @addOpts type: mandatory: true check: (v) -> CUI.util.isString(v) and not CUI.util.isEmpty(v) and v.split(/\s+/).length == 1 # node to start from node: default: document.documentElement mandatory: true check: (v) -> CUI.dom.isNode(v) require_node_in_dom: default: false mandatory: true check: Boolean bubble: default: false check: Boolean sink: default: false check: Boolean # trigger skips the start node exclude_self: default: false check: Boolean # info to pass alongside the event info: default: {} check: "PlainObject" prevent_default: default: false check: Boolean readOpts: -> super() @__node = CUI.dom.getNode(@_node) # if @_exclude_self # CUI.util.assert(@_bubble != false, "new EventsEvent", "opts.exclude_self can only be set if bubble is set to true.", opts: @opts) if @_preventDefault @preventDefault() @__listenerClass = null @__isInDOM = null # CUI.util.assert(not @isDOMEvent() or @_bubble, "DOMEvent needs opts.bubble set.", opts: @opts) __setListener: (listener) -> if not @__listenerClass @__listenerClass = listener.getElementClass() else CUI.util.assert(@__listenerClass == listener.getElementClass(), "Event.setListener", "listener class cannot change during an events life cycle.", listener: listener, listenerClass: @__listenerClass) @ __setPhase: (@__phase) -> isExcludeSelf: -> @_exclude_self getPhase: -> @__phase getType: -> @_type getDebug: -> @_type+"["+@getUniqueId()+"]" getInfo: -> @_info getNode: -> @__node getElement: -> CUI.dom.data(@getNode(), "element") isBubble: -> @_bubble isSink: -> @_sink isInDOM: -> if @__isInDOM != null # cached result @__isInDOM else if @__node == document or @__node == window @__isInDOM = true else @__isInDOM = CUI.dom.isInDOM(@__node) setNativeEvent: (NativeEvent) -> # avoid checking instanceof, so external initializers like TestCafé work CUI.util.assert(typeof(NativeEvent) == 'object', "CUI.Event.setNativeEvent", "Event needs to be instanceof Event", Event: NativeEvent) @__NativeEvent = NativeEvent @ getNativeEvent: -> @__NativeEvent getPointTarget: -> document.elementFromPoint(@clientX(), @clientY()) getTarget: -> @__target or @getNativeEvent()?.target setTarget: (tg) -> @__target = tg getCurrentTarget: -> @__currentTarget or @getTarget() setCurrentTarget: (ct) -> @__currentTarget = ct getModifiers: -> mods = [] for k, v of { meta: "Meta" ctrl: "Control" alt: "Alt" shift: "Shift" } if @[k+"Key"]() mods.push(v) mods hasModifierKey: (includeShift=false) -> @metaKey() or @ctrlKey() or @altKey() or (includeShift and @shiftKey()) getButton: -> @getNativeEvent()?.button keyCode: -> @getNativeEvent()?.which metaKey: -> @getNativeEvent()?.metaKey ctrlKey: -> @getNativeEvent()?.ctrlKey altKey: -> @getNativeEvent()?.altKey shiftKey: -> @getNativeEvent()?.shiftKey clientX: -> @getNativeEvent()?.clientX clientY: -> @getNativeEvent()?.clientY pageX: -> @getNativeEvent()?.pageX pageY: -> @getNativeEvent()?.pageY stopImmediatePropagation: -> @__propagationImmediateStopped = true @getNativeEvent()?.stopImmediatePropagation() @ stopPropagation: -> @__propagationStopped = true @getNativeEvent()?.stopPropagation() @ preventDefault: -> @__defaultPrevented = true @getNativeEvent()?.preventDefault() @ isImmediatePropagationStopped: -> @__propagationImmediateStopped isPropagationStopped: -> @__propagationStopped isDefaultPrevented: -> @__defaultPrevented dispatch: -> # console.info "CUI.Events.trigger jQuery DOMEvent", event.getType() CUI.util.assert(not @getNativeEvent(), "CUI.Event.dispatch", "Can only dispatch once.", event: @) ev = document.createEvent("Event") ev.initEvent(@getType(), @isBubble(), true) ev.__cui_event = @ if @isExcludeSelf() # or @isSink() # when sinking, we touch the node while sinking, so # its ok to start with the parent to not trigger # it twice node = CUI.dom.parent(@getNode()) else # even is event.isBubble() === false # we trigger here using the bubble mechanism, # handleEvent takes care of the bubble check node = @getNode() if @isDefaultPrevented() ev.preventDefault() # if the dom event is not set yet on this # we set it now @setNativeEvent(ev) # console.error "dispatch event on node:", @getType(), node, @getUniqueId(), ev node.dispatchEvent(ev) ev dump: -> txt = @__cls+": **"+@getType()+"**" mods = @getModifiers() if mods.length > 0 txt += " Modifiers: **"+mods.join("+")+"**" txt stop: -> @preventDefault() @stopPropagation() @stopImmediatePropagation() false @require: (event, func) -> if CUI.util.isPlainObject(event) ev_info = CUI.Events.getEventType(event.type) if ev_info.eventClass eventClass = ev_info.eventClass else eventClass = CUI.Event CUI.util.mergeMap(event, ev_info) delete(event.eventClass) delete(event.listenerClass) ev = new eventClass(event) else ev = event CUI.util.assert(ev instanceof CUI.Event, "#{func}", "event needs to be PlainObject or instance of CUI.Event.") ev # cr @createFromDOMEvent: (event, eventClass) -> ev_info = CUI.Events.getEventType(event.type) if not eventClass if ev_info.eventClass eventClass = ev_info.eventClass else eventClass = CUI.Event ev = new eventClass type: event.type bubble: event.bubbles node: event.target # console.debug "Event.createFromDOMEvent", event.type, eventClass.name, ev.getUniqueId() ev.setNativeEvent(event) ev