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.
- 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
|
+
)
|