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.
- data/VERSION +1 -1
- data/conf/default_conf.yaml +6 -1
- data/js/comm/queue/queue.js +0 -1
- data/js/comm/transporter/transporter.js +32 -16
- data/js/comm/values/values.js +45 -13
- data/js/controls/sliders/slider/slider.js +5 -6
- data/js/controls/sliders/slider/themes/default/slider.css +34 -62
- data/js/controls/sliders/slider/themes/default/slider.html +4 -4
- data/js/controls/sliders/vslider/themes/default/vslider.css +43 -10
- data/js/controls/sliders/vslider/vslider.js +3 -1
- data/js/controls/stepper/stepper.js +1 -1
- data/js/controls/stringview/stringview.js +6 -8
- data/js/controls/stringview/themes/default/stringview.html +1 -1
- data/js/controls/textcontrol/textcontrol.js +22 -16
- data/js/controls/textcontrol/themes/default/textcontrol.css +23 -22
- data/js/controls/window/window.js +1 -1
- data/js/core/class/class.js +4 -4
- data/js/core/event/event.js +3 -2
- data/js/datetime/calendar/calendar.coffee +114 -58
- data/js/datetime/calendar/themes/default/calendar.css +4 -2
- data/js/foundation/control/control.js +2 -0
- data/js/foundation/control/dyncontrol/dyncontrol.js +15 -0
- data/js/foundation/control/eventresponder/eventresponder.js +29 -20
- data/js/foundation/eventmanager/eventmanager.coffee +1090 -0
- data/js/foundation/eventmanager/eventmanager.js +116 -28
- data/js/foundation/json_renderer/json_renderer.js +4 -2
- data/js/foundation/system/system.js +3 -0
- data/js/foundation/view/view.js +6 -30
- data/js/lists/listitems/listitems.js +8 -1
- data/js/lists/radiobuttonlist/radiobuttonlist.js +9 -4
- data/js/menus/minimenu/minimenu.js +11 -5
- data/js/menus/minimenuitem/minimenuitem.js +6 -4
- data/js/tables/table/table.coffee +19 -0
- data/js/tables/table/themes/default/table.css +0 -0
- data/js/tables/table/themes/default/table.html +19 -0
- data/lib/rsence/argv/initenv_argv.rb +1 -1
- data/lib/rsence/http/broker.rb +3 -1
- data/lib/rsence/msg.rb +1 -1
- data/lib/rsence/plugins/gui_plugin.rb +2 -0
- data/lib/rsence/sessionmanager.rb +7 -7
- data/lib/rsence/sessionstorage.rb +3 -1
- data/lib/rsence/transporter.rb +56 -32
- data/lib/rsence/valuemanager.rb +3 -3
- data/plugins/client_pkg/client_pkg.rb +5 -0
- data/plugins/client_pkg/lib/client_pkg_build.rb +29 -4
- 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
|
+
)
|