rsence-pre 2.2.2.1 → 2.3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ )