rsence-pre 2.2.2.1 → 2.3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/VERSION +1 -1
  2. data/conf/default_conf.yaml +6 -1
  3. data/js/comm/queue/queue.js +0 -1
  4. data/js/comm/transporter/transporter.js +32 -16
  5. data/js/comm/values/values.js +45 -13
  6. data/js/controls/sliders/slider/slider.js +5 -6
  7. data/js/controls/sliders/slider/themes/default/slider.css +34 -62
  8. data/js/controls/sliders/slider/themes/default/slider.html +4 -4
  9. data/js/controls/sliders/vslider/themes/default/vslider.css +43 -10
  10. data/js/controls/sliders/vslider/vslider.js +3 -1
  11. data/js/controls/stepper/stepper.js +1 -1
  12. data/js/controls/stringview/stringview.js +6 -8
  13. data/js/controls/stringview/themes/default/stringview.html +1 -1
  14. data/js/controls/textcontrol/textcontrol.js +22 -16
  15. data/js/controls/textcontrol/themes/default/textcontrol.css +23 -22
  16. data/js/controls/window/window.js +1 -1
  17. data/js/core/class/class.js +4 -4
  18. data/js/core/event/event.js +3 -2
  19. data/js/datetime/calendar/calendar.coffee +114 -58
  20. data/js/datetime/calendar/themes/default/calendar.css +4 -2
  21. data/js/foundation/control/control.js +2 -0
  22. data/js/foundation/control/dyncontrol/dyncontrol.js +15 -0
  23. data/js/foundation/control/eventresponder/eventresponder.js +29 -20
  24. data/js/foundation/eventmanager/eventmanager.coffee +1090 -0
  25. data/js/foundation/eventmanager/eventmanager.js +116 -28
  26. data/js/foundation/json_renderer/json_renderer.js +4 -2
  27. data/js/foundation/system/system.js +3 -0
  28. data/js/foundation/view/view.js +6 -30
  29. data/js/lists/listitems/listitems.js +8 -1
  30. data/js/lists/radiobuttonlist/radiobuttonlist.js +9 -4
  31. data/js/menus/minimenu/minimenu.js +11 -5
  32. data/js/menus/minimenuitem/minimenuitem.js +6 -4
  33. data/js/tables/table/table.coffee +19 -0
  34. data/js/tables/table/themes/default/table.css +0 -0
  35. data/js/tables/table/themes/default/table.html +19 -0
  36. data/lib/rsence/argv/initenv_argv.rb +1 -1
  37. data/lib/rsence/http/broker.rb +3 -1
  38. data/lib/rsence/msg.rb +1 -1
  39. data/lib/rsence/plugins/gui_plugin.rb +2 -0
  40. data/lib/rsence/sessionmanager.rb +7 -7
  41. data/lib/rsence/sessionstorage.rb +3 -1
  42. data/lib/rsence/transporter.rb +56 -32
  43. data/lib/rsence/valuemanager.rb +3 -3
  44. data/plugins/client_pkg/client_pkg.rb +5 -0
  45. data/plugins/client_pkg/lib/client_pkg_build.rb +29 -4
  46. metadata +10 -7
@@ -0,0 +1,1090 @@
1
+ # Copyright 2012 Juha-Jarmo Heinonen
2
+ #
3
+ # The EventManager is a proxy between the DOM-level
4
+ # events and the higher-lever GUI API's.
5
+ EventManagerApp = HApplication.extend
6
+ #
7
+ # Warning wrapper, only active in development mode
8
+ warn: ->
9
+ console.warn.apply( console, arguments ) unless @isProduction
10
+ #
11
+ # The default options array, each flag corresponds to events received.
12
+ _defaultEventOptions:
13
+ #
14
+ # The recipient's #mouseMove(x,y) method gets called,
15
+ # whether it has focus or not
16
+ mouseMove: false
17
+ #
18
+ # The recipient's #mouseDown(x,y,button) method gets called,
19
+ # if focused.
20
+ mouseDown: false
21
+ #
22
+ # The recipient's #click(x,y,button) method gets called,
23
+ # if focused.
24
+ click: false
25
+ #
26
+ # The recipient's #mouseUp(x,y,button) method gets called,
27
+ # if focused.
28
+ mouseUp: false
29
+ #
30
+ # The recipient's #startDrag( x, y ), #drag( x, y ) and
31
+ # #endDrag( x, y ) methods get called, if focused and
32
+ # a draging operation is done with the pointing device.
33
+ draggable: false
34
+ #
35
+ # The recipient's #startHover( dragObj ), #hover( dragObj ) and
36
+ # #endHover( dragObj ) methods get called, when a dragged object
37
+ # is hovered over it. See the rectHover option to set the topmost
38
+ # vs any mode.
39
+ droppable: false
40
+ #
41
+ # The drop modes define how the hover area responds to dragged objects
42
+ # false: point; the [x,y] point of the pointer
43
+ # true: area; the [l,t,r,b] contains rectangle of the dragged object
44
+ # 'contains': for areas; same as true
45
+ # 'intersects': for areas; intersection instead of containment
46
+ rectHover: false
47
+ #
48
+ # Allows multiple (other than the non-topmost drop target).
49
+ # Set on both the draggable as well as the drop target object.
50
+ multiDrop: false
51
+ #
52
+ # The recipient's #keyDown( keyCode ) method gets called,
53
+ # if active and a keyboard key is pressed.
54
+ keyDown: false
55
+ #
56
+ # The recipient's #keyUp( keyCode ) method gets called,
57
+ # if active and a keyboard key is released.
58
+ keyUp: false
59
+ #
60
+ # The recipient's #mouseWheel( delta) method gets called,
61
+ # if active and a scroll device is used.
62
+ mouseWheel: false
63
+ #
64
+ # The recipient's #resize() method gets called, when the
65
+ # browser's window or a HWindow (and similar components) are
66
+ # resized, this event is triggered on all recipients.
67
+ resize: false
68
+ #
69
+ # The recipient's #textEnter() method gets called, when a keyboard key
70
+ # has been pressed and released, whether it has focus or not.
71
+ textEnter: false
72
+ #
73
+ # The recipient's #doubleClick(x,y) method gets called, when
74
+ # the pointing device is double-clicked, if focused.
75
+ doubleClick: false
76
+ #
77
+ # The recipient's #contextMenu() method gets called, when the
78
+ # pointing device's or keyboard's context button (usually the
79
+ # right mouse button) has been pressed, if focused.
80
+ contextMenu: false
81
+ #
82
+ # The status object has a list of the most recent HID events by id and name.
83
+ # Each id and name and states are booleans.
84
+ # button1 => The state of the left mouse button.
85
+ # button2 => The state of the right mouse button.
86
+ # crsrX => The X-coordinate of the mouse cursor (or last point of touch).
87
+ # crsrY => The Y-coordinate of the mouse cursor (or last point of touch).
88
+ # keysDown => An Array of the key codes of keys being held down.
89
+ # altKeyDown => The state of the Alt key (or equivalent, like Option).
90
+ # ctrlKeyDown => The state of the Ctrl key.
91
+ # shiftKeyDown => The state of the Shift key.
92
+ # metaKeyDown => The state of the Meta key.
93
+ # cmdKeyDown => The state of the Command key (or equivalent, like the Windows key).
94
+ # Note: Will be deprecated in favor of an hash with keys instead of numeric indexes.
95
+ status:
96
+ 0: false
97
+ button1: false
98
+ setButton1: (f)->
99
+ @button1 = f
100
+ @[0] = f
101
+ 1: false
102
+ button2: false
103
+ setButton2: (f)->
104
+ @button2 = f
105
+ @[1] = f
106
+ 2: -1
107
+ crsrX: -1
108
+ setCrsrX: (x)->
109
+ @crsr[0] = x
110
+ @crsrX = x
111
+ @[2] = x
112
+ 3: -1
113
+ crsrY: -1
114
+ crsr: [ -1, -1 ]
115
+ setCrsrY: (y)->
116
+ @crsr[1] = y
117
+ @crsrY = y
118
+ @[3] = y
119
+ setCrsr: (x,y)->
120
+ @setCrsrX(x)
121
+ @setCrsrY(y)
122
+ 4: []
123
+ keysDown: []
124
+ hasKeyDown: (k)->
125
+ @keysDown.indexOf(k) != -1
126
+ addKeyDown: (k)->
127
+ if !@hasKeyDown(k)
128
+ @keysDown.push( k )
129
+ @[4] = @keysDown
130
+ delKeyDown: (k)->
131
+ i = @keysDown.indexOf(k)
132
+ if i != -1
133
+ @keysDown.splice( i, 1 )
134
+ @[4] = @keysDown
135
+ resetKeysDown: ->
136
+ @keysDown = []
137
+ @[4] = @keysDown
138
+ 5: false
139
+ altKeyDown: false
140
+ setAltKey: (f)->
141
+ @altKeyDown = f
142
+ @[5] = f
143
+ 6: false
144
+ ctrlKeyDown: false
145
+ setCtrlKey: (f)->
146
+ @ctrlKeyDown = f
147
+ @[6] = f
148
+ 7: false
149
+ shiftKeyDown: false
150
+ setShiftKey: (f)->
151
+ @shiftKeyDown = f
152
+ @[7] = f
153
+ 8: false
154
+ metaKeyDown: false
155
+ setMetaKey: (f)->
156
+ @metaKeyDown = f
157
+ @[8] = f
158
+ 9: false
159
+ cmdKeyDown: false
160
+ setCmdKey: (f)->
161
+ @cmdKeyDown = f
162
+ @[9] = f
163
+ length: 10
164
+ button1: 0
165
+ button2: 1
166
+ crsrX: 2
167
+ crsrY: 3
168
+ keysDown: 4
169
+ altKeyDown: 5
170
+ ctrlKeyDown: 6
171
+ shiftKeyDown: 7
172
+ metaKeyDown: 8
173
+ cmdKeyDown: 9
174
+ #
175
+ # Cleans up events that would be lost, when the browser window is blurred.
176
+ _domWindowBlur: ->
177
+ @status.resetKeysDown()
178
+ @status.setAltKey(false)
179
+ @status.setCtrlKey(false)
180
+ @status.setShiftKey(false)
181
+ @status.setMetaKey(false)
182
+ @status.setCmdKey(false)
183
+ @_origDroppableChecks = @enableDroppableChecks
184
+ @enableDroppableChecks = false
185
+ if HSystem.defaultInterval != HSystem._blurredInterval
186
+ @_sysDefaultInterval = HSystem.defaultInterval
187
+ COMM.Queue.push( (->
188
+ HSystem.defaultInterval = HSystem._blurredInterval
189
+ ) )
190
+ #
191
+ # Restores system poll frequency
192
+ _domWindowFocus: ->
193
+ @enableDroppableChecks = @_origDroppableChecks
194
+ if HSystem.defaultInterval == HSystem._blurredInterval and @_sysDefaultInterval
195
+ _this = @
196
+ COMM.Queue.push( (->
197
+ HSystem.defaultInterval = _this._sysDefaultInterval
198
+ ) )
199
+ #
200
+ # List of used event methods for global purposes:
201
+ _eventMethods: [
202
+ 'mouseMove', 'mouseUp', 'mouseDown', 'click', 'keyUp', 'keyDown',
203
+ 'contextMenu', 'resize', 'mouseWheel', 'doubleClick'
204
+ ]
205
+ #
206
+ # This structure keeps track of registered elem/event/object/method; see #observe and #stopObserving
207
+ _observerMethods: {}
208
+ #
209
+ # Observe event, cache anon function; eventName => elem => anonFn
210
+ observe: (_elem, _eventName, _targetMethodName, _targetObj, _capture)->
211
+ _targetObj = @ unless _targetObj?
212
+ _capture = false unless _capture?
213
+ _anonFn = (e)->
214
+ _targetObj[_targetMethodName](e)
215
+ unless @_observerMethods[_eventName]?
216
+ @_observerMethods[_eventName] = {
217
+ elems: []
218
+ fns: []
219
+ capture: []
220
+ }
221
+ _cache = @_observerMethods[_eventName]
222
+ _elemIdx = _cache.elems.indexOf( _elem )
223
+ if _elemIdx != -1
224
+ _prevFn = _cache.fns[_elemIdx]
225
+ _prevCapture = _cache.capture[_elemIdx]
226
+ Event.stopObserving( _elem, _eventName, _prevFn, _prevCapture )
227
+ _cache.elems.splice( _elemIdx, 1 )
228
+ _cache.fns.splice( _elemIdx, 1 )
229
+ _cache.capture.splice( _elemIdx, 1 )
230
+ Event.observe( _elem, _eventName, _anonFn, _capture )
231
+ _cache.elems.unshift( _elem )
232
+ _cache.fns.unshift( _anonFn )
233
+ _cache.capture.unshift( _capture )
234
+ true
235
+ #
236
+ # Stop observing event
237
+ stopObserving: (_elem, _eventName)->
238
+ return false unless @_observerMethods[_eventName]?
239
+ if @_observerMethods[_eventName].elems.length == 0
240
+ delete @_observerMethods[_eventName]
241
+ return false
242
+ _cache = @_observerMethods[_eventName]
243
+ _elemIdx = _cache.elems.indexOf(_elem)
244
+ return false if _elemIdx == -1
245
+ _prevFn = _cache.fns[_elemIdx]
246
+ _prevCapture = _cache.capture[_elemIdx]
247
+ Event.stopObserving( _elem, _eventName, _prevFn, _prevCapture )
248
+ _cache.elems.splice( _elemIdx, 1 )
249
+ _cache.fns.splice( _elemIdx, 1 )
250
+ _cache.capture.splice( _elemIdx, 1 )
251
+ return true
252
+ #
253
+ # This structure keeps track of view-event bindings:
254
+ _listeners: {
255
+ byId: {} # viewId => [ eventName, eventName, .. ]
256
+ _rectHoverIntersectMode: []
257
+ byEvent: # event names by viewId
258
+ mouseMove: [] # viewIds
259
+ mouseDown: [] # viewIds
260
+ mouseUp: [] # viewIds
261
+ draggable: [] # viewIds
262
+ droppable: [] # viewIds
263
+ rectHover: [] # viewIds
264
+ multiDrop: [] # viewIds
265
+ keyDown: [] # viewIds
266
+ keyUp: [] # viewIds
267
+ mouseWheel: [] # viewIds
268
+ textEnter: [] # viewIds
269
+ click: [] # viewIds
270
+ resize: [] # viewIds
271
+ doubleClick: [] # viewIds
272
+ contextMenu: [] # viewIds
273
+ focused: [] # viewIds
274
+ enabled: [] # viewIds
275
+ dragged: [] # viewIds
276
+ selected: [] # viewIds
277
+ hovered: [] # viewIds
278
+ active: [] # viewIds
279
+ }
280
+ #
281
+ # Returns the global target element based on browser type
282
+ _getGlobalTargetElem: ->
283
+ if BROWSER_TYPE.ie and !BROWSER_TYPE.ie9
284
+ return window.document
285
+ else
286
+ return window
287
+ #
288
+ # Starts EventManager
289
+ start: ->
290
+ @_views = HSystem.views # shortcut to system views
291
+ _targetElem = @_getGlobalTargetElem()
292
+ _methods = @_eventMethods
293
+ _methods.push( 'keyPress' ) unless BROWSER_TYPE.safari or BROWSER_TYPE.ie
294
+ for _methodName in _methods
295
+ if _methodName == 'doubleClick'
296
+ _eventName = 'dblclick'
297
+ else
298
+ _eventName = _methodName.toLowerCase()
299
+ @observe( _targetElem, _eventName, _methodName )
300
+ if window.addEventListener?
301
+ @observe( window, 'DOMMouseScroll', 'mouseWheel' )
302
+ @observe( window, 'resize', 'resize' )
303
+ @observe( window, 'blur', '_domWindowBlur' )
304
+ @observe( window, 'focus', '_domWindowFocus' )
305
+ @_legacyStart()
306
+ #
307
+ # Stops EventManager
308
+ stop: ->
309
+ delete @_views
310
+ _targetElem = @_getGlobalTargetElem()
311
+ _methods = @_eventMethods
312
+ _methods.push( 'keyPress' ) unless BROWSER_TYPE.safari or BROWSER_TYPE.ie
313
+ for _methodName in _methods
314
+ if _methodName == 'doubleClick'
315
+ _eventName = 'dblclick'
316
+ else
317
+ _eventName = _methodName.toLowerCase()
318
+ @stopObserving( _targetElem, _eventName, _methodName )
319
+ if window.addEventListener?
320
+ @stopObserving( window, 'DOMMouseScroll', 'mouseWheel' )
321
+ @stopObserving( window, 'resize', 'resize' )
322
+ @stopObserving( window, 'blur', '_domWindowBlur' )
323
+ @stopObserving( window, 'focus', '_domWindowFocus' )
324
+ #
325
+ ## LEGACY; to be removed
326
+ #
327
+ # Set to false, if your app don't need drop events.
328
+ # Setting this to false, when not needed, improves over-all performance,
329
+ # because the drop events need constant calculation of where the mouse
330
+ # curser (or last touch) was against all possible drop targets.
331
+ enableDroppableChecks: true
332
+ #
333
+ # Initializes the members used by the drop-related events.
334
+ # This method is called from within the EventMangaer and is never called,
335
+ # if @enableDroppableChecks is false
336
+ startDroppable: ->
337
+ @warn "EventManager#startDroppable is deprecated"
338
+ @hovered = [] # Drop-eligible items under the mouse cursor
339
+ @hoverInterval = 200 # Milliseconds between checks
340
+ @hoverTimer = new Date().getTime() # Time since last check was triggered
341
+ #
342
+ # Legacy startup, semi-compatible
343
+ _legacyStart: ->
344
+ @warn "EventManager#"+'_'+"legacyStart is deprecated"
345
+ @listeners = [] # NOT SUPPORTED
346
+ @focused = @_listeners.focused # DEPRECATED
347
+ @resizeListeners = @_listeners.byEvent.resize # DEPRECATED
348
+ @eventOptions = @_listeners.byId # DEPRECATED
349
+ @dragItems = @_listeners.dragged # DEPRECATED
350
+ @topmostDroppable = null # NOT SUPPORTED
351
+ @textEnterCtrls = @_listeners.byEvent.textEnter # DEPRECATED
352
+ @_coordCache = [] # NOT SUPPORTED
353
+ @_coordCacheFlag = true # NOT SUPPORTED
354
+ @_lastCoordFlushTimeout = null # NOT SUPPORTED
355
+ @activeControl = null # NOT SUPPORTED
356
+ @_lastKeyDown = null # NOT SUPPORTED
357
+ @_origDroppableChecks = @enableDroppablechecks # DEPRECATED
358
+ @startDroppable() if @enableDroppableChecks # DEPRECATED
359
+ #
360
+ # Flushes the position cache by elemId. If no elemId is specified,
361
+ # everything is flushed.
362
+ coordCacheFlush: (_elemId)->
363
+ @warn "EventManager#coordCacheFlush is deprecated"
364
+ if _elemId
365
+ @_coordCache[_elemId] = null
366
+ else
367
+ @_coordCache = []
368
+ #
369
+ # Flushed mouseMove timers, actually did more or less all the mouseMove work:
370
+ flushMouseMove: (x,y)->
371
+ @warn( "EventManager#flushMouseMove => Unsupported call, don't call it!", _ctrl )
372
+ return false
373
+ ## /LEGACY
374
+ #
375
+ # Ensures the type of the object is a HControl
376
+ _ensureValidControl: (_ctrl,_warnMethodName)->
377
+ _warnMethodName = '[unknown]' unless _warnMethodName
378
+ unless _ctrl.hasAncestor?
379
+ @warn( "EventManager##{_warnMethodName} => Not a HClass: ", _ctrl )
380
+ return false
381
+ unless _ctrl.hasAncestor( HView ) and _ctrl.isCtrl
382
+ @warn( "EventManager##{_warnMethodName} => Not a HControl: ", _ctrl )
383
+ return false
384
+ return true
385
+ #
386
+ # Ensure valid eventOptions
387
+ _ensureValidEventOptions: (_eventOptions,_warnMethodName)->
388
+ _warnMethodName = '[unknown]' unless _warnMethodName
389
+ if !( typeof _eventOptions == 'object' )
390
+ @warn( "EventManager##{_warnMethodName} => Invalid eventOptions: ", _eventOptions )
391
+ return false
392
+ return true
393
+ #
394
+ # Converts eventOptions into a list of enabled event names
395
+ _setEventOptions: (_ctrl,_eventOptions,_warnMethodName)->
396
+ _warnMethodName = '[unknown]' unless _warnMethodName
397
+ _viewId = _ctrl.viewId
398
+ _eventsOn = []
399
+ for _key of @_defaultEventOptions
400
+ continue if _key == 'base' or _key == 'constructor'
401
+ if @_listeners.byEvent[_key]? and _eventOptions[_key]?
402
+ _value = _eventOptions[_key]
403
+ if _value
404
+ _eventsOn.push( _key )
405
+ @_listeners.byEvent[_key].unshift( _viewId ) if @_listeners.byEvent[_key].indexOf(_viewId) == -1
406
+ if _key == 'rectHover' and _value == 'intersects' and @_listeners._rectHoverIntersectMode.indexOf( _viewId ) == -1
407
+ @_listeners._rectHoverIntersectMode.unshift( _viewId )
408
+ else
409
+ _idx = @_listeners.byEvent[_key].indexOf(_viewId)
410
+ if _idx != -1
411
+ @_listeners.byEvent[_key].splice( _idx, 1 )
412
+ else
413
+ @warn( "EventManager##{_warnMethodName} => Invalid event type: #{_key}" )
414
+ _this = @
415
+ @_listeners.byId[_viewId] = _eventsOn
416
+ if _ctrl.enabled
417
+ @_listeners.enabled.unshift( _viewId ) if @_listeners.enabled.indexOf(_viewId) == -1
418
+ _elem = ELEM.get( _ctrl.elemId )
419
+ @observe( _elem, 'mouseover', '_mouseOver' )
420
+ #
421
+ # Releases bindings done by #_setEventOptions
422
+ _unsetEventOptions: (_ctrl,_warnMethodName)->
423
+ _warnMethodName = '[unknown]' unless _warnMethodName
424
+ _viewId = _ctrl.viewId
425
+ if @_listeners.byId[_viewId]?
426
+ delete @_listeners.byId[_viewId]
427
+ else
428
+ @warn( "EventManager##{_warnMethodName} => viewId not registered: #{_viewId}" )
429
+ console.log(@_listeners.byId[_viewId],_viewId,_ctrl)
430
+ for _key, _value of @_listeners.byEvent
431
+ _viewIdx = _value.indexOf(_viewId)
432
+ if _viewIdx != -1
433
+ _value.splice(_viewIdx,1)
434
+ if _key == 'rectHover'
435
+ _intersectHoverIdx = @_listeners._rectHoverIntersectMode.indexOf( _viewId )
436
+ if _intersectHoverIdx != -1
437
+ @_listeners._rectHoverIntersectMode.splice( _intersectHoverIdx, 1 )
438
+ _wasFocused = false
439
+ _elem = ELEM.get( _ctrl.elemId )
440
+ for _statusItem in [ 'dragged', 'selected', 'hovered', 'active', 'focused', 'enabled' ]
441
+ _viewIdx = @_listeners[_statusItem].indexOf(_viewId)
442
+ if _viewIdx != -1
443
+ if _statusItem == 'dragged'
444
+ _ctrl.endDrag( @status.crsrX, @status.crsrY )
445
+ else if _statusItem == 'selected'
446
+ _ctrl.deSelect()
447
+ else if _statusItem == 'hovered'
448
+ _ctrl.endHover( null )
449
+ else if _statusItem == 'active'
450
+ _ctrl._lostActiveStatus( null )
451
+ else if _statusItem == 'focused'
452
+ # _ctrl._mouseOut()
453
+ @stopObserving( _elem, 'mouseout', '_mouseOut' )
454
+ _wasFocused = true
455
+ else if _statusItem == 'enabled'
456
+ unless _wasFocused
457
+ @stopObserving( _elem, 'mouseover', '_mouseOver' )
458
+ _ctrl.setEnabled( false ) if _ctrl.enabled
459
+ @_listeners[_statusItem].splice(_viewIdx,1)
460
+ #
461
+ # Registers the HControl -derived object _ctrl by event listener flags
462
+ # in _eventOptions.
463
+ reg: (_ctrl, _eventOptions)->
464
+ return false unless @_ensureValidControl( _ctrl, 'reg' )
465
+ return false unless @_ensureValidEventOptions( _eventOptions, 'reg' )
466
+ @_setEventOptions( _ctrl, _eventOptions, 'reg' )
467
+ return true
468
+ #
469
+ # Returns status of registration
470
+ _isreg: (_ctrl)->
471
+ return @_listeners.byId[_ctrl.viewId]?
472
+ #
473
+ # Unregisters the HControl -derived object from all its bindings
474
+ unreg: (_ctrl)->
475
+ return false unless @_ensureValidControl( _ctrl, 'unreg' )
476
+ return false unless @_isreg( _ctrl )
477
+ @_unsetEventOptions(_ctrl,'unreg')
478
+ #
479
+ #
480
+ ## Event responders; mid-level handlers.
481
+ ## These all receive the global events and check where to delegate them.
482
+ #
483
+ # Handle event modifiers
484
+ _modifiers: (e)->
485
+ [ _x, _y ] = ELEM.getScrollPosition(0)
486
+ [ x, y ] = [ Event.pointerX(e) - _x, Event.pointerY(e) - _y ]
487
+ unless isNaN(x) or isNaN(y)
488
+ @status.setCrsr( x, y )
489
+ @status.setAltKey( e.altKey )
490
+ @status.setCtrlKey( e.ctrlKey )
491
+ @status.setShiftKey( e.shiftKey )
492
+ @status.setMetaKey( e.metaKey )
493
+ #
494
+ # Resize is an event triggered by resizing the browser window
495
+ # (as well as the HWindow component, as a special case)
496
+ #
497
+ # The HSystem._updateFlexibleRects call may not be neccessary to call
498
+ # both before and after in all circumstances, but better be safe than sure.
499
+ resize: (e)->
500
+ HSystem._updateFlexibleRects()
501
+ for _viewId in @_listeners.byEvent.resize
502
+ _ctrl = @_views[_viewId]
503
+ _ctrl.resize() if _ctrl.resize?
504
+ ## Deprecate this:
505
+ if _ctrl.onResize?
506
+ @warn( "EventManager#resize => The 'onResize' event responder is deprecated. Please rename it to 'resize'." )
507
+ _ctrl.onResize()
508
+ ## /Deprecate
509
+ HSystem._updateFlexibleRects()
510
+ #
511
+ # Finds the next elem with a view_id attribute
512
+ _findViewId: (_elem)->
513
+ until _elem.view_id? or _elem == document.body
514
+ _elem = _elem.parentNode
515
+ return _elem
516
+ #
517
+ # Finds the ctrl based on the element by getting the view_id attribute
518
+ _findEventControl: (e,_warnMethodName,_stop)->
519
+ _warnMethodName = '[unknown]' unless _warnMethodName
520
+ _elem = Event.element(e)
521
+ _ctrl = null
522
+ until _ctrl
523
+ _elem = @_findViewId( _elem )
524
+ return false if _elem == document.body
525
+ unless _elem.view_id?
526
+ @warn( "EventManager##{_warnMethodName} => The element doesn't have an 'view_id' attribute.")
527
+ return false
528
+ _viewId = _elem.view_id
529
+ unless @_views[_viewId]?
530
+ @warn( "EventManager##{_warnMethodName} => The viewId:#{_viewId} doesn't have a view.")
531
+ return false
532
+ _ctrl = @_views[_viewId]
533
+ unless _ctrl.isCtrl #@_ensureValidControl(_ctrl,_warnMethodName)
534
+ _ctrl = null
535
+ _elem = _elem.parentNode
536
+ Event.stop(e) if _stop
537
+ return _ctrl
538
+ #
539
+ # Enables focused state of enabled HControls by listening to the
540
+ # view-element-specific mouseover event.
541
+ _mouseOver: (e)->
542
+ _ctrl = @_findEventControl(e, '_'+'mouseOver')
543
+ @focus(_ctrl) if _ctrl
544
+ #
545
+ # Disables focused state of enabled HControls by listening to the
546
+ # view-element-specific mouseout event.
547
+ _mouseOut: (e)->
548
+ _ctrl = @_findEventControl(e, '_'+'mouseOut')
549
+ @blur(_ctrl) if _ctrl
550
+ #
551
+ # Focuses a control, triggered based on the view-element-specific
552
+ # mouseover event.
553
+ focus: (_ctrl)->
554
+ _viewId = _ctrl.viewId
555
+ if @_listeners.focused.indexOf(_viewId) == -1
556
+ _elem = ELEM.get( _ctrl.elemId )
557
+ @observe( _elem, 'mouseout', '_mouseOut' )
558
+ @stopObserving( _elem, 'mouseover', '_mouseOver' )
559
+ @_listeners.focused.unshift(_viewId)
560
+ unless _ctrl.focus?
561
+ @warn( "EventManager#focus => The viewId:#{_viewId} doesn't have a 'focus' method.")
562
+ return false
563
+ _ctrl.focus()
564
+ #
565
+ # Blurs a control, triggered based on the view-element-specific
566
+ # mouseout event.
567
+ blur: (_ctrl)->
568
+ _viewId = _ctrl.viewId
569
+ _viewIdx = @_listeners.focused.indexOf(_viewId)
570
+ if _viewIdx != -1
571
+ _elem = ELEM.get( _ctrl.elemId )
572
+ @observe( _elem, 'mouseover', '_mouseOver' )
573
+ @stopObserving( _elem, 'mouseout', '_mouseOut' )
574
+ @_listeners.focused.splice(_viewIdx,1)
575
+ unless _ctrl.blur?
576
+ @warn( "EventManager#blur => The viewId:#{_viewId} doesn't have a 'blur' method.")
577
+ return false
578
+ ## Should probably perform additional de-registration on active events
579
+ ## dependant on focus here.
580
+ ##
581
+ ##
582
+ _ctrl.blur()
583
+ #
584
+ # Mouse movement manager. Triggered by the global mousemove event.
585
+ # Delegates the following event responder methods to focused HControl instances:
586
+ # - drag
587
+ # - mouseMove
588
+ # - endHover
589
+ # - startHover
590
+ mouseMove: (e)->
591
+ @_modifiers(e) # fetch event modifiers
592
+ [ x, y ] = @status.crsr
593
+ Event.stop(e) if @_handleMouseMove( x, y )
594
+ #
595
+ # Just split to gain namespace:
596
+ _handleMouseMove: ( x, y )->
597
+ @_delegateMouseMove(x,y)
598
+ _currentlyDragging = @_delegateDrag(x,y)
599
+ return _currentlyDragging
600
+ #
601
+ # Handle items being dragged, sending #drag(x,y) calls to them
602
+ _delegateDrag: (x, y)->
603
+ _dragItems = @_listeners.dragged
604
+ return false if _dragItems.length == 0
605
+ for _viewId in _dragItems
606
+ _ctrl = @_views[_viewId]
607
+ _ctrl.drag(x,y)
608
+ @_delegateHover( _ctrl, x, y )
609
+ return true
610
+ #
611
+ # Handle items wanting #mouseMove(x,y) calls
612
+ _delegateMouseMove: (x,y)->
613
+ _mouseMoveItems = @_listeners.byEvent.mouseMove
614
+ return false if _mouseMoveItems.length == 0
615
+ for _viewId in _mouseMoveItems
616
+ _ctrl = @_views[_viewId]
617
+ _ctrl.mouseMove(x,y)
618
+ return true
619
+ #
620
+ # Handle items wanting #startHover( _dragObj ),
621
+ # #hover( _dragObj ) and #endHover( _dragObj ) calls
622
+ _delegateHover: (_ctrl, x, y)->
623
+ _byEvent = @_listeners.byEvent
624
+ _findPoint = _byEvent.rectHover.indexOf( _ctrl.viewId ) == -1
625
+ _findTopmost = _byEvent.multiDrop.indexOf( _ctrl.viewId ) == -1
626
+ _findIntersect = true
627
+ if _findPoint
628
+ _area = HPoint.new( x, y )
629
+ _matchMethod = 'contains'
630
+ else
631
+ _rect = _ctrl.rect
632
+ _area = HRect.new( x, y, _rect.width, _rect.height )
633
+ if @_listeners._rectHoverIntersectMode.indexOf( _viewId ) == -1
634
+ _matchMethod = 'intersects'
635
+ else
636
+ _matchMethod = 'contains'
637
+ if _findTopmost
638
+ _hoverItems = @_findTopmostDroppable(_area,_matchMethod,_ctrl.viewId)
639
+ else
640
+ _hoverItems = @_findAllDroppable(_area,_matchMethod,_ctrl.viewid)
641
+ _endHover = []
642
+ for _hoverId in @_listeners.hovered
643
+ if _hoverItems.indexOf( _hoverId ) == -1
644
+ _endHover.push( _hoverId )
645
+ _startHover = []
646
+ for _hoverId in _hoverItems
647
+ if @_listeners.hovered.indexOf( _hoverId ) == -1
648
+ _startHover.push( _hoverId )
649
+ for _viewId in _startHover
650
+ @_views[_viewId].startHover(_ctrl)
651
+ for _viewId in _endHover
652
+ @_views[_viewId].endHover(_ctrl)
653
+ for _viewId in _hoverItems
654
+ @_views[_viewId].hover(_ctrl)
655
+ @_listeners.hovered = _hoverItems
656
+ #
657
+ # Finds the topmost drop/hover target within the area specified by rectHover
658
+ _findTopmostDroppable: (_area,_matchMethod,_selfId)->
659
+ _views = @_views
660
+ _droppable = @_listeners.byEvent.droppable
661
+ _search = (_parentIds)->
662
+ for _viewId in _parentIds
663
+ continue if _viewId == _selfId
664
+ _view = _views[_viewId]
665
+ if _view.hasAncestor? and _view.hasAncestor( HView ) and _view.rect[_matchMethod](_area)
666
+ if _droppable.indexOf( _viewId ) != -1
667
+ _dropId = _search( _view.viewsZOrder.slice().reverse() )
668
+ return _dropId if _dropId
669
+ return _viewId
670
+ return false
671
+ _dropId = _search( HSystem.viewsZOrder.slice().reverse() )
672
+ return [ _dropId ] if _dropId
673
+ return []
674
+ #
675
+ # Finds all drop/hover targets within the area specified by rectHover
676
+ _findAllDroppable: (_area,_matchMethod,_selfId)->
677
+ _views = @_views
678
+ _droppable = @_listeners.byEvent.droppable
679
+ _found = []
680
+ _search = (_parentIds)->
681
+ for _viewId in _parentIds
682
+ continue if _viewId == _selfId
683
+ _view = _views[_viewId]
684
+ if _view.hasAncestor? and _view.hasAncestor( HView ) and _view.rect[_matchMethod](_area)
685
+ _found.push( _viewId ) if _droppable.indexOf( _viewId ) != -1
686
+ _search( _view.viewsZOrder.slice().reverse() )
687
+ _search( HSystem.viewsZOrder.slice().reverse() )
688
+ return _found
689
+ #
690
+ # Removes the active control
691
+ delActiveControl: (_newActive)->
692
+ _active = @_listeners.active
693
+ _focused = @_listeners.focused
694
+ return null if _active.length == 0
695
+ if _active.length == 1
696
+ _prevActive = @_views[_active[0]]
697
+ else
698
+ @warn "Danger, too many active items: #{JSON.stringify(_active)}"
699
+ for _viewId in _active.slice()
700
+ continue if _newActive != null and _viewId == _newActive.viewId
701
+ _ctrl = @_views[_viewId]
702
+ _ctrl.active = false
703
+ _idx = _active.indexOf( _viewId )
704
+ _active.splice( _idx, 1 )
705
+ @blur(_ctrl) if _focused.indexOf(_viewId) != -1
706
+ _ctrl.lostActiveStatus(_newActive)
707
+ _prevActive
708
+ #
709
+ # Adds the active control
710
+ addActiveControl: (_ctrl,_prevActive)->
711
+ _active = @_listeners.active
712
+ _focused = @_listeners.focused
713
+ _idx = _active.indexOf( _ctrl.viewId )
714
+ if _idx == -1
715
+ _active.unshift(_ctrl.viewId)
716
+ @focus(_ctrl) if _focused.indexOf(_ctrl.viewId) == -1
717
+ _ctrl.active = true
718
+ _ctrl.gainedActiveStatus(_prevActive)
719
+ #
720
+ # Sets the active control
721
+ changeActiveControl: (_ctrl)->
722
+ _prevActive = @delActiveControl(_ctrl)
723
+ @addActiveControl(_ctrl, _prevActive) if _ctrl != null
724
+ #
725
+ # Method to be called, when you want to make an item draggable from outside of the EventManager
726
+ startDragging: (_ctrl)->
727
+ return if !_ctrl.enabled
728
+ _viewId = _ctrl.viewId
729
+ @focus( _viewId )
730
+ @changeActiveControl(_ctrl)
731
+ @_listeners.dragged.unshift( _viewId ) if @_listeners.dragged.indexOf( _viewId ) == -1
732
+ _ctrl.startDrag( @status.crsrX, @status.crsrY, @status.button2 )
733
+ #
734
+ # Cancels text selections, which happen by
735
+ _cancelTextSelection: ->
736
+ # Remove possible selections.
737
+ ELEM.get(0).focus()
738
+ #
739
+ # Mouse button press manager. Triggered by the global mouseDown event.
740
+ # Delegates the following event responder methods to active HControl instances:
741
+ # - mouseDown
742
+ # - startDrag
743
+ mouseDown: (e)->
744
+ @_modifiers(e)
745
+ _leftClick = Event.isLeftClick(e)
746
+ if _leftClick
747
+ @status.setButton1( true )
748
+ else
749
+ @status.setButton2( true )
750
+ _focused = @_listeners.focused
751
+ _active = @_listeners.active
752
+ _dragged = @_listeners.dragged
753
+ _mouseDownable = @_listeners.byEvent.mouseDown
754
+ _draggable = @_listeners.byEvent.draggable
755
+ _newActive = []
756
+ _mouseDownIds = []
757
+ _startDragIds = []
758
+ _stop = false
759
+ for _viewId in _focused
760
+ _newActive.push( _viewId ) if _active.indexOf(_viewId) == -1
761
+ _eventOptions = @_listeners.byId[_viewId]
762
+ if _mouseDownable.indexOf( _viewId ) != -1
763
+ _mouseDownIds.push( _viewId )
764
+ if _draggable.indexOf( _viewId ) != -1 and _dragged.indexOf( _viewId ) == -1
765
+ _startDragIds.push( _viewId )
766
+ for _viewId in _newActive
767
+ _ctrl = @_views[_viewId]
768
+ @changeActiveControl( _ctrl )
769
+ [ x, y ] = @status.crsr
770
+ for _viewId in _mouseDownIds
771
+ _ctrl = @_views[_viewId]
772
+ _stop = true if _ctrl.mouseDown( x, y, _leftClick )
773
+ for _viewId in _startDragIds
774
+ if _dragged.indexOf( _viewId ) == -1
775
+ _ctrl = @_views[_viewId]
776
+ _dragged.unshift( _viewId )
777
+ _stop = true if _ctrl.startDrag( x, y, _leftClick )
778
+ @_handleMouseMove(x,y)
779
+ @_cancelTextSelection() unless _startDragIds.length == 0 and _mouseDownIds.length == 0
780
+ Event.stop(e) if _stop
781
+ #
782
+ # Mouse button press manager. Triggered by the global mouseDown event.
783
+ # Delegates the following event responder methods to active HControl instances:
784
+ # - mouseUp
785
+ # - endDrag
786
+ # - endHover
787
+ # - drop
788
+ mouseUp: (e)->
789
+ @_modifiers(e)
790
+ _leftClick = Event.isLeftClick(e)
791
+ @status.setButton1( false )
792
+ @status.setButton2( false )
793
+ return false unless _leftClick
794
+ _focused = @_listeners.focused
795
+ _active = @_listeners.active
796
+ _dragged = @_listeners.dragged
797
+ _hovered = @_listeners.hovered
798
+ _mouseUppable = @_listeners.byEvent.mouseUp
799
+ _draggable = @_listeners.byEvent.draggable
800
+ _newActive = []
801
+ _mouseUpIds = []
802
+ _endDragIds = []
803
+ _stop = false
804
+ for _viewId in _focused
805
+ _newActive.push( _viewId ) if _active.indexOf(_viewId) == -1
806
+ _eventOptions = @_listeners.byId[_viewId]
807
+ if _mouseUppable.indexOf( _viewId ) != -1
808
+ _mouseUpIds.push( _viewId )
809
+ if _draggable.indexOf( _viewId ) != -1 and _dragged.indexOf( _viewId ) != -1
810
+ _endDragIds.push( _viewId )
811
+ for _viewId in _newActive
812
+ _ctrl = @_views[_viewId]
813
+ @changeActiveControl( _ctrl )
814
+ [ x, y ] = @status.crsr
815
+ for _viewId in _mouseUpIds
816
+ _ctrl = @_views[_viewId]
817
+ _stop = true if _ctrl.mouseUp( x, y, _leftClick )
818
+ for _viewId in _endDragIds
819
+ _dragIdx = _dragged.indexOf( _viewId )
820
+ unless _dragIdx == -1
821
+ _ctrl = @_views[_viewId]
822
+ _dragged.splice( _dragIdx, 1 )
823
+ for _dropViewId in _hovered
824
+ _dropCtrl = @_views[_dropViewId]
825
+ _dropCtrl.endHover(_ctrl) if _dropCtrl.endHover?
826
+ _dropCtrl.drop(_ctrl) if _dropCtrl.drop?
827
+ _stop = true if _ctrl.endDrag( x, y, _leftClick )
828
+ @_listeners.hovered = []
829
+ @_listeners.dragged = []
830
+ @_handleMouseMove(x,y)
831
+ @_cancelTextSelection() unless _endDragIds.length == 0 and _mouseUpIds.length == 0
832
+ Event.stop(e) if _stop
833
+ ## /jatka
834
+ #
835
+ # Handles mouse button clicks
836
+ # It's different from mouseUp/mouseDown, because it's a different event,
837
+ # and is supported by touch screen devices
838
+ click: (e)->
839
+ @_modifiers(e)
840
+ _leftClick = Event.isLeftClick(e)
841
+ if _leftClick
842
+ @status.setButton1( false )
843
+ else
844
+ # there is a separate event for context menu, and only
845
+ # Firefox fires click separately
846
+ return true
847
+ _focused = @_listeners.focused
848
+ _active = @_listeners.active
849
+ _clickable = @_listeners.byEvent.click
850
+ _newActive = []
851
+ _clickIds = []
852
+ _stop = false
853
+ for _viewId in _focused
854
+ _newActive.push( _viewId ) if _active.indexOf(_viewId) == -1
855
+ if _clickable.indexOf(_viewId) != -1
856
+ _clickIds.push( _viewId )
857
+ for _viewId in _newActive
858
+ _ctrl = @_views[_viewId]
859
+ @changeActiveControl( _ctrl )
860
+ [ x, y ] = @status.crsr
861
+ for _viewId in _clickIds
862
+ _ctrl = @_views[_viewId]
863
+ unless _ctrl.click? and typeof _ctrl.click == 'function'
864
+ @warn( 'no click:', _ctrl, _ctrl.click?, typeof _ctrl.click )
865
+ continue
866
+ _stop = true if _ctrl.click( x, y, _leftClick )
867
+ @_handleMouseMove(x,y)
868
+ Event.stop(e) if _stop
869
+ #
870
+ # Handles doubleClick events
871
+ doubleClick: (e)->
872
+ @_modifiers(e)
873
+ _leftClick = Event.isLeftClick(e)
874
+ @status.setButton1( false )
875
+ @status.setButton2( false )
876
+ [ x, y ] = @status.crsr
877
+ @_handleMouseMove(x,y)
878
+ _focused = @_listeners.focused
879
+ _doubleClicks = []
880
+ _doubleClickable = @_listeners.byEvent.doubleClick
881
+ _stop = false
882
+ for _viewId in _focused
883
+ if _doubleClickable.indexOf(_viewId) != -1
884
+ _doubleClicks.push( _viewId )
885
+ for _viewId in _doubleClickable
886
+ _ctrl = @_views[_viewId]
887
+ if _ctrl.doubleClick?
888
+ _stop = true if _ctrl.doubleClick(x,y,true)
889
+ Event.stop(e) if _stop
890
+ #
891
+ # Handles mouseWheel events (any HID scroll event)
892
+ mouseWheel: (e)->
893
+ e = window.event unless e
894
+ @_modifiers(e)
895
+ if e.wheelDelta
896
+ _delta = 0-(e.wheelDelta/120)
897
+ else if e.detail
898
+ _delta = 0-(e.detail/3)
899
+ if BROWSER_TYPE.opera or BROWSER_TYPE.safari or BROWSER_TYPE.ie
900
+ _delta = 0-_delta
901
+ _focused = @_listeners.focused
902
+ _mouseWheels = []
903
+ _mouseWheelable = @_listeners.byEvent.mouseWheel
904
+ _stop = false
905
+ for _viewId in _focused
906
+ if _mouseWheelable.indexOf(_viewId) != -1
907
+ _mouseWheels.push( _viewId )
908
+ for _viewId in _mouseWheels
909
+ _ctrl = @_views[_viewId]
910
+ if _ctrl.mouseWheel?
911
+ _stop = true if _ctrl.mouseWheel( _delta )
912
+ Event.stop(e) if _stop
913
+ #
914
+ # Handles the contextMenu event
915
+ contextMenu: (e)->
916
+ @_modifiers(e)
917
+ _stop = true
918
+ @status.setButton1( false )
919
+ @status.setButton2( false )
920
+ _focused = @_listeners.focused
921
+ _contextMenuable = @_listeners.byEvent.contextMenu
922
+ for _viewId in _focused
923
+ if _contextMenuable.indexOf(_viewId) != -1
924
+ _ctrl = @_views[_viewId]
925
+ _stop = false if _ctrl.contextMenu? and _ctrl.contextMenu()
926
+ Event.stop(e) if _stop
927
+ #
928
+ # Keycode translation tables
929
+ _keyTrans:
930
+ opera:
931
+ # Symbol keys:
932
+ 59: 186 # [;:]
933
+ 61: 187 # [=+]
934
+ 44: 188 # [,<]
935
+ 45: 189 # [-_]
936
+ 46: 190 # [.>]
937
+ 47: 191 # [/?]
938
+ 96: 192 # [`~]
939
+ 91: 219 # [[{]
940
+ 92: 220 # [\|]
941
+ 93: 221 # []}]
942
+ 39: 222 # ['"]
943
+
944
+ # Numeric keypad keys can't be mapped on Opera, because Opera
945
+ # doesn't differentiate between the keys on the numeric keypad
946
+ # versus the functionally same keys elsewhere on the keyboard.
947
+
948
+ # Branded keys:
949
+ # Apple Command keys are same as ctrl, but ctrl is 0; Can't be re-mapped reliably.
950
+ # The Windows Menu key also return 0, so it can't be re-mapped either.
951
+ 219: 91 # Left Windows key (Start)
952
+ 220: 92 # Right Windows key (Start)
953
+ mozilla:
954
+ # Symbol keys:
955
+ 59: 186 # [;:]
956
+ 61: 187 # [=+]
957
+ 109: 189 # [-_]
958
+
959
+ # Branded keys:
960
+ 224: 91 # Apple Command key to left windows key mapping
961
+ #
962
+ # Translates keyCodes to the normalized pseudo-ascii used by IE and WebKit browsers.
963
+ # Opera and Mozilla browsers use different codes, so they'll need translations.
964
+ translateKeyCodes: (_keyCode)->
965
+ # We use the WebKit and IE browsers as the normalization base, because
966
+ # there is no variance between in these. Returns the keyCode as-is for
967
+ # browsers in this category.
968
+ if BROWSER_TYPE.safari or BROWSER_TYPE.ie
969
+ return _keyCode
970
+ # Opera has its own keyCodes, which are different from all others.
971
+ else if BROWSER_TYPE.opera
972
+ _transCode = @_keyTrans.opera[_keyCode]
973
+ # The assumption is that the other browsers do what mozille does.
974
+ else
975
+ _transCode = @_keyTrans.mozilla[_keyCode]
976
+ # No translation needed:
977
+ return _keyCode if not _transCode? or _transCode == null
978
+ # Return translated:
979
+ return _transCode
980
+ #
981
+ # List of keycodes considered command keys
982
+ _cmdKeys: [
983
+ 17, # Ctrl
984
+ 91, # Others (Left Start Key or Left Command Key)
985
+ 92, # Others (Right Start Key)
986
+ 93 # Others (Menu Key or Right Command Key)
987
+ ]
988
+ _detectCmdKey: ( _keyCode )->
989
+ # On Opera, return true on any of the keycodes
990
+ if BROWSER_TYPE.opera
991
+ return @_cmdKeys.indexOf(_keyCode) != -1
992
+ # Any mac browser (except opera, above) uses left or right windows key
993
+ # equivalent as the Command key.
994
+ else if BROWSER_TYPE.mac
995
+ return _keyCode == 91 or _keyCode == 93
996
+ # Other platforms use CTRL as the command key.
997
+ return _keyCode == 17
998
+ #
999
+ # Handles the keyDown event
1000
+ keyDown: (e)->
1001
+ @_modifiers(e)
1002
+ _keyCode = @translateKeyCodes( e.keyCode )
1003
+ _stop = false
1004
+ if !@status.cmdKeyDown and @_detectCmdKey( _keyCode )
1005
+ @status.setCmdKey( true )
1006
+ _stop = true
1007
+ _active = @_listeners.active
1008
+ _keyDowners = @_listeners.byEvent.keyDown
1009
+ _keyDowns = []
1010
+ unless @status.hasKeyDown( _keyCode ) and @_lastKeyDown != _keyCode
1011
+ for _viewId in _active
1012
+ _keyDowns.push( _viewId ) if _keyDowners.indexOf( _viewId ) != -1
1013
+ @status.addKeyDown( _keyCode )
1014
+ # repeat not implemented yet
1015
+ for _viewId in _keyDowns
1016
+ _ctrl = @_views[_viewId]
1017
+ if _ctrl.keyDown?
1018
+ _stop = true if _ctrl.keyDown(_keyCode)
1019
+ @_lastKeyDown = _keyCode
1020
+ Event.stop(e) if _stop
1021
+ keyUp: (e)->
1022
+ @_modifiers(e)
1023
+ _keyCode = @translateKeyCodes( e.keyCode )
1024
+ _stop = false
1025
+ if @status.cmdKeyDown and @_detectCmdKey( _keyCode )
1026
+ @status.setCmdKey( false )
1027
+ _stop = true
1028
+ _active = @_listeners.active
1029
+ _enabled = @_listeners.enabled
1030
+ _keyUppers = @_listeners.byEvent.keyUp
1031
+ _keyUps = []
1032
+ _textEnterers = @_listeners.byEvent.textEnter
1033
+ _textEnters = []
1034
+ if @status.hasKeyDown( _keyCode )
1035
+ for _viewId in _active
1036
+ _keyUps.push( _viewId ) if _keyUppers.indexOf( _viewId ) != -1
1037
+ @status.delKeyDown( _keyCode )
1038
+ for _viewId in _keyUppers
1039
+ _ctrl = @_views[_viewId]
1040
+ if _ctrl.keyUp?
1041
+ _stop = true if _ctrl.keyUp( _keyCode )
1042
+ for _viewId in _textEnterers
1043
+ _textEnters.push( _viewId ) if _enabled.indexOf( _viewId ) != -1
1044
+ for _viewId in _textEnters
1045
+ _ctrl = @_views[_viewId]
1046
+ if _ctrl.textEnter?
1047
+ _stop = true if _ctrl.textEnter( _keyCode )
1048
+ Event.stop(e) if _stop
1049
+ keyPress: (e)->
1050
+ @warn('EventManager#keyPress not implemented')
1051
+ isKeyDown: (_keyCode)->
1052
+ @warn('EventManager#isKeyDown() is deprecated, use #status.hasKeyDown() instead')
1053
+ @status.hasKeyDown( _keyCode )
1054
+ isKeyUp: (_keyCode)->
1055
+ @warn('EventManager#isKeyUp() is deprecated, use !#status.hasKeyDown() instead')
1056
+ (not @status.hasKeyDown( _keyCode ))
1057
+ isAltKeyDown: ->
1058
+ @warn('EventManager#isAltKeyDown is deprecated, use #status.altKeyDown instead')
1059
+ @status.altKeyDown
1060
+ isCtrlKeyDown: ->
1061
+ @warn('EventManager#isCtrlKeyDown is deprecated, use #status.ctrlKeyDown instead')
1062
+ @status.ctrlKeyDown
1063
+ isShiftKeyDown: ->
1064
+ @warn('EventManager#isShiftKeyDown is deprecated, use #status.shiftKeyDown instead')
1065
+ @status.shiftKeyDown
1066
+ isMetaKeyDown: ->
1067
+ @warn('EventManager#isMetaKeyDown is deprecated, use #status.metaKeyDown instead')
1068
+ @status.metaKeyDown
1069
+ isCmdKeyDown: ->
1070
+ @warn('EventManager#isCmdKeyDown is deprecated, use #status.cmdKeyDown instead')
1071
+ @status.altKeyDown
1072
+ #
1073
+ # Debug output
1074
+ # idle: ->
1075
+ # console.log( 'focused: ',
1076
+ # JSON.stringify(@_listeners.focused),'active:',
1077
+ # JSON.stringify(@_listeners.active),'dragged:',
1078
+ # JSON.stringify(@_listeners.dragged),'hovered:',
1079
+ # JSON.stringify(@_listeners.hovered) )
1080
+ #
1081
+ # Cleans up structures
1082
+ die: ->
1083
+ @stop()
1084
+ @base()
1085
+ LOAD( ->
1086
+ window.EventManager = EventManagerApp.new( 500, 'EventManager' )
1087
+ # Alias:
1088
+ window.EVENT = EventManager
1089
+ EventManager.start()
1090
+ )