switch_access-rails 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +10 -0
- data/README.md +121 -0
- data/Rakefile +16 -0
- data/lib/switch_access-rails.rb +1 -0
- data/lib/switch_access/rails.rb +3 -0
- data/lib/switch_access/rails/engine.rb +6 -0
- data/lib/switch_access/rails/railtie.rb +14 -0
- data/lib/switch_access/rails/version.rb +5 -0
- data/lib/switch_access/rails/view_helpers.rb +109 -0
- data/vendor/assets/javascripts/switch_access.js +3 -0
- data/vendor/assets/javascripts/switch_access/execute_method.coffee +107 -0
- data/vendor/assets/javascripts/switch_access/jquery.csswatch.coffee +264 -0
- data/vendor/assets/javascripts/switch_access/log4javascript.js +5877 -0
- data/vendor/assets/javascripts/switch_access/switch_access.coffee +1007 -0
- data/vendor/assets/stylesheets/switch_access/example.css +2 -0
- data/vendor/assets/stylesheets/switch_access/example_highlighter.css +14 -0
- data/vendor/assets/stylesheets/switch_access/example_switch_element.css +14 -0
- metadata +125 -0
@@ -0,0 +1,1007 @@
|
|
1
|
+
###
|
2
|
+
Switch Access for webpages
|
3
|
+
(c) 2012 Leif Ringstad
|
4
|
+
Dual-licensed under GPL or commercial license (LICENSE and LICENSE.GPL)
|
5
|
+
Source: http://github.com/leifcr/switch_access
|
6
|
+
v 1.1.4
|
7
|
+
###
|
8
|
+
|
9
|
+
SwitchAccessCommon =
|
10
|
+
generateRandomUUID: ->
|
11
|
+
"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace /[xy]/g, (c) ->
|
12
|
+
r = Math.random() * 16 | 0
|
13
|
+
v = (if c is "x" then r else (r & 0x3 | 0x8))
|
14
|
+
v.toString 16
|
15
|
+
options:
|
16
|
+
###
|
17
|
+
Element highlighting using the built in Highlighter object feature
|
18
|
+
###
|
19
|
+
highlighter:
|
20
|
+
###
|
21
|
+
Use highlighter div element for each element. A div is positioned absolute
|
22
|
+
around the element and shown/hidden accordingly
|
23
|
+
Default: true
|
24
|
+
###
|
25
|
+
use: true
|
26
|
+
|
27
|
+
###
|
28
|
+
Additional content for the highlighter
|
29
|
+
Note: The content is placed within every highlighter and multiple
|
30
|
+
highlighters can be visible at the same time. It is best to not
|
31
|
+
use IDs on elements placed inside the highlighter, to avoid duplicate
|
32
|
+
IDs on a page
|
33
|
+
Default: ""
|
34
|
+
###
|
35
|
+
content: ""
|
36
|
+
|
37
|
+
###
|
38
|
+
Class for the highlighter
|
39
|
+
Default: "highlighter"
|
40
|
+
###
|
41
|
+
class: "highlighter"
|
42
|
+
|
43
|
+
###
|
44
|
+
The class when a highlighter is active/currently selected
|
45
|
+
Default: "current"
|
46
|
+
###
|
47
|
+
current_class: "current"
|
48
|
+
|
49
|
+
###
|
50
|
+
The class when set on a highlighter when activated action is triggered
|
51
|
+
Note: only usable if options.visual.delay_before_activating_element is > 0
|
52
|
+
Default: "activate"
|
53
|
+
###
|
54
|
+
activate_class: "activate"
|
55
|
+
|
56
|
+
###
|
57
|
+
Margin between the highlighter and the element
|
58
|
+
Default: 5
|
59
|
+
###
|
60
|
+
margin_to_element: 5
|
61
|
+
|
62
|
+
###
|
63
|
+
Selector to set size on. (Change in case you have content inside the highlighter you wish to highlight)
|
64
|
+
###
|
65
|
+
selector_for_set_to_size: ".highlighter"
|
66
|
+
|
67
|
+
###
|
68
|
+
Use CSS watch to watch the element for changes in position and dimensions
|
69
|
+
This is only needed if you have javascript or other DOM elements
|
70
|
+
that might change the position or size of a switch-enabled element
|
71
|
+
Default: false
|
72
|
+
###
|
73
|
+
watch_for_resize: false
|
74
|
+
# use_size_position_check: true
|
75
|
+
|
76
|
+
###
|
77
|
+
The ID for the holder for all highlighters. Unlikely to need changing
|
78
|
+
Default: "sw-highlighter-holder"
|
79
|
+
###
|
80
|
+
holder_id: "sw-highlighter-holder"
|
81
|
+
|
82
|
+
###
|
83
|
+
Options specific to highlighting
|
84
|
+
###
|
85
|
+
highlight:
|
86
|
+
###
|
87
|
+
Options specifict to highlighting a switch-element
|
88
|
+
###
|
89
|
+
element:
|
90
|
+
###
|
91
|
+
The class when a element is active/currently selected
|
92
|
+
Default: "current"
|
93
|
+
###
|
94
|
+
current_class: "current"
|
95
|
+
|
96
|
+
###
|
97
|
+
The class when set on a switch-element when activated
|
98
|
+
action is triggered
|
99
|
+
Note: options.visual.delay_before_activating_element must
|
100
|
+
be greater than 0
|
101
|
+
Default: "activate"
|
102
|
+
###
|
103
|
+
activate_class: "activate"
|
104
|
+
|
105
|
+
debug: false
|
106
|
+
|
107
|
+
###
|
108
|
+
Internal options, but can be changed if needed
|
109
|
+
###
|
110
|
+
internal:
|
111
|
+
###
|
112
|
+
The data attribute for the unique ID on each element and switch highlighter
|
113
|
+
Default: "sw-elem"
|
114
|
+
###
|
115
|
+
unique_element_data_attribute: "sw-elem"
|
116
|
+
|
117
|
+
###
|
118
|
+
Set a unique class on each element
|
119
|
+
Default: false
|
120
|
+
###
|
121
|
+
set_unique_element_class: false
|
122
|
+
|
123
|
+
###
|
124
|
+
Actions (Enumish)
|
125
|
+
These should not be overridden, as they are used internally
|
126
|
+
###
|
127
|
+
actions:
|
128
|
+
none: 0
|
129
|
+
moved_to_next_element: 1
|
130
|
+
moved_to_next_level: 2
|
131
|
+
moved_to_previous_level: 3
|
132
|
+
triggered_action: 10
|
133
|
+
triggered_delayed_action: 11
|
134
|
+
stayed_at_element: 20
|
135
|
+
|
136
|
+
|
137
|
+
|
138
|
+
class SwitchAccess
|
139
|
+
constructor: (options) ->
|
140
|
+
# return existing instance if already initialized, as there should only be one instance of Switch Access on a page
|
141
|
+
if typeof (window['__switch_access_sci']) != "undefined" && window['__switch_access_sci'] != null
|
142
|
+
window.__switch_access_sci.setoptions(options)
|
143
|
+
return window.__switch_access_sci
|
144
|
+
|
145
|
+
window.__switch_access_sci = this
|
146
|
+
###
|
147
|
+
Options
|
148
|
+
###
|
149
|
+
@options =
|
150
|
+
###
|
151
|
+
Switch/Key settings
|
152
|
+
###
|
153
|
+
switches:
|
154
|
+
|
155
|
+
###
|
156
|
+
The number of switches 0 = disable, 1 = single switch, 2 = two switches
|
157
|
+
Default: 2
|
158
|
+
###
|
159
|
+
number_of_switches: 0
|
160
|
+
|
161
|
+
###
|
162
|
+
Array for the keycodes to use as single switch (Multiple keycodes possible)
|
163
|
+
Default: [32, 13] (32 = 'Space', 13 = 'Enter')
|
164
|
+
###
|
165
|
+
keys_1: [32, 13] # Space / Enter
|
166
|
+
|
167
|
+
###
|
168
|
+
Array of two arrays for the keys to use as two switches
|
169
|
+
Default: [[32, 9], [13]] (9 = 'Tab, 32 = 'Space', 13 = 'Enter')
|
170
|
+
###
|
171
|
+
keys_2: [[9, 32], [13]] # Tab + Space / Enter
|
172
|
+
|
173
|
+
#keys_3: # forward/backward and select
|
174
|
+
|
175
|
+
###
|
176
|
+
Time for single switch scanning to move from element to element
|
177
|
+
Default: 1500 milliseconds
|
178
|
+
###
|
179
|
+
single_switch_move_time: 1500
|
180
|
+
|
181
|
+
###
|
182
|
+
If the single switch movement should restart/go to index 0 when restarted
|
183
|
+
Default: true
|
184
|
+
###
|
185
|
+
single_switch_restart_on_activate: true
|
186
|
+
|
187
|
+
###
|
188
|
+
Time after "triggering" a element to it's activated
|
189
|
+
Default: 0
|
190
|
+
###
|
191
|
+
delay_before_activating_element: 0
|
192
|
+
|
193
|
+
###
|
194
|
+
Delay before an keypress is "allowed" after last keypress.
|
195
|
+
Default: 250 ms
|
196
|
+
###
|
197
|
+
delay_for_allowed_keypress: 250
|
198
|
+
|
199
|
+
###
|
200
|
+
Groups enabled/disabled (If elements should be grouped or run as single elements)
|
201
|
+
Default: true
|
202
|
+
###
|
203
|
+
groups: true
|
204
|
+
|
205
|
+
###
|
206
|
+
DOM options
|
207
|
+
###
|
208
|
+
dom:
|
209
|
+
###
|
210
|
+
The class which all elements must have to be a switch controlled element
|
211
|
+
The class should be appended with numbers 1,2,3 etc to set order of elements.
|
212
|
+
order is unpredicaable if several elements have the same number within a group.
|
213
|
+
Use classnames switch-element-1 switch-element-2 or change this value
|
214
|
+
Default: "switch-element-"
|
215
|
+
###
|
216
|
+
element_class: "switch-element-"
|
217
|
+
###
|
218
|
+
The jQuery selector from where the first switch element should be searched for.
|
219
|
+
Usually this should be body or the first container on the webpage
|
220
|
+
Note: Use a selector which selects a single object. Else behaviour is unpredictable
|
221
|
+
###
|
222
|
+
start_element_selector: "body"
|
223
|
+
|
224
|
+
###
|
225
|
+
Other settings
|
226
|
+
###
|
227
|
+
# Use .search where you have class="search" or #search for id="search" (jQuery selectors)
|
228
|
+
key_filter_skip: [".search"]
|
229
|
+
|
230
|
+
###
|
231
|
+
If set to true, the first link within the element is "clicked".
|
232
|
+
Else the actual element is clicked.
|
233
|
+
FUTURE feature: (on the todo list)
|
234
|
+
A data attribute can be set on the element in order to override this on a per-element basis
|
235
|
+
###
|
236
|
+
activate_first_link: true # activate element or first link within
|
237
|
+
###
|
238
|
+
Enable/Disable debug
|
239
|
+
Note: log4javascript must be available if used
|
240
|
+
Default: false
|
241
|
+
###
|
242
|
+
debug: false
|
243
|
+
|
244
|
+
###
|
245
|
+
Visual settings
|
246
|
+
###
|
247
|
+
visual:
|
248
|
+
###
|
249
|
+
Scroll to ensure the entire element in focus is visible (if possible)
|
250
|
+
Default: true
|
251
|
+
###
|
252
|
+
ensure_visible_element: true # ensure element is visible on the page
|
253
|
+
|
254
|
+
###
|
255
|
+
The number of pixels for margin to the viewport/window when
|
256
|
+
the element is positioned in the viewport/window
|
257
|
+
Default: 15
|
258
|
+
###
|
259
|
+
scroll_offset: 15
|
260
|
+
|
261
|
+
###
|
262
|
+
Time in milliseconds the scroll will animate
|
263
|
+
(set to 0 if instant scroll is preferred)
|
264
|
+
Default: 200
|
265
|
+
###
|
266
|
+
animate_scroll_time: 200
|
267
|
+
###
|
268
|
+
The easing to use for animation
|
269
|
+
Default: "linear"
|
270
|
+
###
|
271
|
+
easing: "linear" # easing to use for scrolling
|
272
|
+
|
273
|
+
# hide_show_delay: 500
|
274
|
+
# move_fade_delay: 200
|
275
|
+
# pulsate: false
|
276
|
+
# play_sound: false
|
277
|
+
# highlight_sound: "./switch_move.mp3"
|
278
|
+
# activate_sound: "./switch_activate.mp3"
|
279
|
+
|
280
|
+
###
|
281
|
+
Runtime properties
|
282
|
+
###
|
283
|
+
@runtime =
|
284
|
+
active: false # switchaccess is active or not
|
285
|
+
element_list: null # an array with root elements
|
286
|
+
current_list: null # the current list
|
287
|
+
# (Root or an elements list of children)
|
288
|
+
|
289
|
+
parent_list: null # the list the parent is in after going into
|
290
|
+
# the group and highlighting the first child
|
291
|
+
|
292
|
+
element:
|
293
|
+
current: null # the current element within the active group
|
294
|
+
idx: 0 # the current element idx within the active group
|
295
|
+
level: 0 # the current level within a group or nested group
|
296
|
+
next_level: 0 # next level when moving to elements.
|
297
|
+
next_idx: 0 # next elements idx
|
298
|
+
parent_idx: 0 # the last idx on the parent before moving into the group
|
299
|
+
action_triggered: false # set to true if an action is triggered
|
300
|
+
keypress_allowed: true # keypress allowed or not
|
301
|
+
timers:
|
302
|
+
single_switch_id: null # The id of the single switch timer
|
303
|
+
|
304
|
+
highlighter_holder: null # The highlighter holder as a jquery object
|
305
|
+
|
306
|
+
@setoptions(options)
|
307
|
+
@init()
|
308
|
+
|
309
|
+
init: ->
|
310
|
+
if (@options.debug)
|
311
|
+
appender = null
|
312
|
+
@logger = log4javascript.getLogger()
|
313
|
+
if $('iframe[id*=log4javascript]').length <= 0
|
314
|
+
if $('#logger').length > 0
|
315
|
+
appender = new log4javascript.InPageAppender("logger")
|
316
|
+
appender.setWidth("100%")
|
317
|
+
appender.setHeight("100%")
|
318
|
+
else
|
319
|
+
appender = new log4javascript.InPageAppender()
|
320
|
+
appender.setHeight("500px")
|
321
|
+
|
322
|
+
appender.setThreshold(log4javascript.Level.ALL)
|
323
|
+
@logger.setLevel(log4javascript.Level.ALL)
|
324
|
+
@logger.addAppender(appender)
|
325
|
+
|
326
|
+
@log("init") if (@options.debug)
|
327
|
+
@createHighlighterHolder() if SwitchAccessCommon.options.highlighter.use
|
328
|
+
@registerCallbacks()
|
329
|
+
@start()
|
330
|
+
|
331
|
+
setoptions: (options) ->
|
332
|
+
@log "setoptions" if (@options.debug)
|
333
|
+
# @log options, "trace", true
|
334
|
+
@stop() if @runtime.active == true
|
335
|
+
jQuery.extend SwitchAccessCommon.options, {
|
336
|
+
highlighter: options.highlighter,
|
337
|
+
highlight: options.highlight,
|
338
|
+
internal: options.internal,
|
339
|
+
debug: options.debug
|
340
|
+
}
|
341
|
+
delete options.highlighter
|
342
|
+
delete options.highlight
|
343
|
+
delete options.internal
|
344
|
+
jQuery.extend true, @options, options
|
345
|
+
return
|
346
|
+
|
347
|
+
log: (msg, type = "debug", raw = false) ->
|
348
|
+
#console.log msg if @options.nested_debug
|
349
|
+
if (@options.debug)
|
350
|
+
if (raw)
|
351
|
+
@logger[type] msg
|
352
|
+
else
|
353
|
+
@logger[type] "SwitchAccess: " + msg
|
354
|
+
|
355
|
+
checkForNonNumberedElements: ->
|
356
|
+
if $(".#{@options.dom.element_class}").length > 0
|
357
|
+
msg = "Warning! #{$(".#{@options.dom.element_class}").length} element(s) without numbers found. Class selector is: #{@options.element_class}."
|
358
|
+
@log msg, "warning" if (@options.debug)
|
359
|
+
console.log "SwitchAccess: " + msg # Alert about no-numbered elements
|
360
|
+
return
|
361
|
+
|
362
|
+
buildListFromjqElement: (jq_element, parent, depth = 0) ->
|
363
|
+
not_str = "[class*=#{@options.dom.element_class}] [class*=#{@options.dom.element_class}]"
|
364
|
+
i = 0
|
365
|
+
while i < depth
|
366
|
+
not_str += " [class*=#{@options.dom.element_class}]"
|
367
|
+
i++
|
368
|
+
|
369
|
+
temp_list = jq_element.find("[class*=#{@options.dom.element_class}]").not(not_str)
|
370
|
+
@log "buildListFromjqElement - element count #{temp_list.length} depth: #{depth} element-classes:#{jq_element.attr("class")}", "trace" if (@options.debug)
|
371
|
+
return [] if temp_list.length <= 0
|
372
|
+
# warn if there are any elements that don't have any numbers
|
373
|
+
@hashAlizeAndRecurseList(@sortList(temp_list, @options.dom.element_class), parent, depth)
|
374
|
+
|
375
|
+
hashAlizeAndRecurseList: (list, parent, depth) ->
|
376
|
+
ret = []
|
377
|
+
i = 0
|
378
|
+
while i < list.length
|
379
|
+
new_element = new SwitchAccessElement($(list[i]), @runtime.highlighter_holder, @, parent)
|
380
|
+
new_element.children(@buildListFromjqElement($(list[i]), new_element, depth + 1 ))
|
381
|
+
ret.push( new_element )
|
382
|
+
i++
|
383
|
+
ret
|
384
|
+
|
385
|
+
sortList: (list, list_class) ->
|
386
|
+
@log "sortList Sorting list for #{list_class} Elements: #{list.length}" if (@options.debug)
|
387
|
+
search_regexp_class = ///#{list_class}\d+///
|
388
|
+
search_regexp_num = ///\d+///
|
389
|
+
list.sort (a,b) =>
|
390
|
+
item_class_name_a = search_regexp_class.exec($(a).attr("class"))
|
391
|
+
item_class_name_b = search_regexp_class.exec($(b).attr("class"))
|
392
|
+
num_a = 0
|
393
|
+
num_b = 0
|
394
|
+
if (item_class_name_a != null && item_class_name_b != null)
|
395
|
+
num_a = search_regexp_num.exec(item_class_name_a)
|
396
|
+
num_b = search_regexp_num.exec(item_class_name_b)
|
397
|
+
num_a - num_b
|
398
|
+
list
|
399
|
+
|
400
|
+
elementWithoutChildren: (element) ->
|
401
|
+
@log "elementWithoutChildren #{element.uniqueDataAttr()}" if (@options.debug)
|
402
|
+
ret = []
|
403
|
+
if element.children().length == 0
|
404
|
+
ret.push(element)
|
405
|
+
else
|
406
|
+
ret = ret.concat(@elementWithoutChildren(child)) for child in element.children()
|
407
|
+
element.children([]) # remove children from the element
|
408
|
+
element.destroy() # destroy the element, as the children have been returned
|
409
|
+
ret
|
410
|
+
|
411
|
+
|
412
|
+
flattenElementList: ->
|
413
|
+
@log "flattenElementList" if (@options.debug)
|
414
|
+
new_list = []
|
415
|
+
new_list = new_list.concat(@elementWithoutChildren(element)) for element in @runtime.element_list
|
416
|
+
new_list
|
417
|
+
|
418
|
+
buildElementList: ->
|
419
|
+
@runtime.element_list = @buildListFromjqElement($(@options.dom.start_element_selector), null, 0)
|
420
|
+
|
421
|
+
# if groups are disabled, flatten the list by moving children upwards
|
422
|
+
if @options.switches.groups == false
|
423
|
+
@runtime.element_list = @flattenElementList()
|
424
|
+
|
425
|
+
@log "buildElementList: count:#{@runtime.element_list.length}, class-name: #{@options.dom.element_class}" if (@options.debug)
|
426
|
+
return
|
427
|
+
|
428
|
+
deinit: ->
|
429
|
+
@log "deinit" if (@options.debug)
|
430
|
+
@stop()
|
431
|
+
@removeHighlightdiv()
|
432
|
+
|
433
|
+
start: ->
|
434
|
+
return if (@options.switches.number_of_switches == 0) || (@runtime.active == true)
|
435
|
+
@log "start" if (@options.debug)
|
436
|
+
@buildElementList()
|
437
|
+
# return
|
438
|
+
@runtime.active = true
|
439
|
+
@moveToFirstRootElement()
|
440
|
+
@startSingleSwitchTimer()
|
441
|
+
@runtime.action_triggered = false
|
442
|
+
|
443
|
+
stop: ->
|
444
|
+
return if (@runtime.active == false)
|
445
|
+
@log "stop" if (@options.debug)
|
446
|
+
@runtime.active = false
|
447
|
+
@removeHighlight()
|
448
|
+
@removeActivateClass()
|
449
|
+
@stopSingleSwitchTimer()
|
450
|
+
|
451
|
+
destroy: ->
|
452
|
+
@log "destroy" if (@options.debug)
|
453
|
+
@stop()
|
454
|
+
@removeCallbacks()
|
455
|
+
@destroy_elements(@runtime.element_list)
|
456
|
+
@removeHighlighterHolder()
|
457
|
+
@runtime.element_list = null
|
458
|
+
@runtime.current_list = null
|
459
|
+
@runtime.parent_list = null
|
460
|
+
@runtime.element.current = null
|
461
|
+
@runtime.highlighter_holder = null
|
462
|
+
window.__switch_access_sci = null
|
463
|
+
|
464
|
+
###
|
465
|
+
Destroy elements in a list
|
466
|
+
Children of the element will be destroyed by the element itself
|
467
|
+
###
|
468
|
+
destroy_elements: (list) ->
|
469
|
+
@log "destroy_elements", "trace" if (@options.debug)
|
470
|
+
element.destroy() for element in list
|
471
|
+
return
|
472
|
+
|
473
|
+
moveToFirstRootElement: ->
|
474
|
+
@runtime.element.idx = -1
|
475
|
+
@moveToNextElementAtLevel()
|
476
|
+
|
477
|
+
moveToNextElementAtLevel: ->
|
478
|
+
@log "moveToNextElementAtLevel", "trace" if (@options.debug)
|
479
|
+
@runtime.element.next_idx = @runtime.element.idx + 1
|
480
|
+
# verify that next idx is possible for "root"
|
481
|
+
if @runtime.element.next_level == @runtime.element.level and @runtime.element.level == 0
|
482
|
+
if (@runtime.element.next_idx >= @runtime.element_list.length)
|
483
|
+
@runtime.element.next_idx = 0
|
484
|
+
|
485
|
+
# see if we should move "out" of the current group
|
486
|
+
if @runtime.element.next_level isnt 0
|
487
|
+
if @runtime.element.next_idx >= @runtime.current_list.length
|
488
|
+
return @moveToPreviousLevel()
|
489
|
+
|
490
|
+
if @moveToNext()
|
491
|
+
@runtime.element.current.jq_element().triggerHandler("switch-access-move", [@runtime.element.idx, @runtime.element.level, @runtime.element.current])
|
492
|
+
return SwitchAccessCommon.actions.moved_to_next_element
|
493
|
+
else
|
494
|
+
return SwitchAccessCommon.actions.stayed_at_element
|
495
|
+
|
496
|
+
moveToNextLevel: ->
|
497
|
+
@log "moveToNextLevel", "trace" if (@options.debug)
|
498
|
+
# "catch" if the current element doesn't have children
|
499
|
+
if @runtime.element.current.children().length > 1
|
500
|
+
@runtime.element.next_level = @runtime.element.level + 1
|
501
|
+
@runtime.element.next_idx = 0
|
502
|
+
# return SwitchAccessCommon.actions.stayed_at_element
|
503
|
+
|
504
|
+
if @moveToNext()
|
505
|
+
@runtime.element.current.parent().jq_element().triggerHandler("switch-access-enter-group", [@runtime.element.idx, @runtime.element.level, @runtime.element.current])
|
506
|
+
return SwitchAccessCommon.actions.moved_to_next_level
|
507
|
+
else
|
508
|
+
return SwitchAccessCommon.actions.stayed_at_element
|
509
|
+
|
510
|
+
moveToPreviousLevel: ->
|
511
|
+
@log "moveToPreviousLevel", "trace" if (@options.debug)
|
512
|
+
@runtime.element.next_level = @runtime.element.level - 1
|
513
|
+
@runtime.element.next_idx = @runtime.element.parent_idx
|
514
|
+
# safety catch impossible levelss
|
515
|
+
if @runtime.element.next_level < 0
|
516
|
+
@runtime.element.next_level = 0
|
517
|
+
@runtime.element.next_idx = 0
|
518
|
+
|
519
|
+
if @moveToNext()
|
520
|
+
@runtime.element.current.jq_element().triggerHandler("switch-access-leave-group", [@runtime.element.idx, @runtime.element.level, @runtime.element.current])
|
521
|
+
return SwitchAccessCommon.actions.moved_to_previous_level
|
522
|
+
else
|
523
|
+
return SwitchAccessCommon.actions.stayed_at_element
|
524
|
+
|
525
|
+
moveToNext: ->
|
526
|
+
@log "moveToNext Current: I: #{@runtime.element.next_idx} L: #{@runtime.element.level} Next: I: #{@runtime.element.next_idx} L: #{@runtime.element.next_level}" if (@options.debug)
|
527
|
+
@runtime.action_triggered = true
|
528
|
+
|
529
|
+
# return if current level and idxs are equal
|
530
|
+
return false if (@runtime.element.next_level == @runtime.element.level) and (@runtime.element.idx == @runtime.element.next_idx)
|
531
|
+
|
532
|
+
@removeHighlight()
|
533
|
+
|
534
|
+
# find list to work on element
|
535
|
+
if @runtime.element.next_level > @runtime.element.level
|
536
|
+
list_n = @runtime.element.current.children()
|
537
|
+
@runtime.element.parent_idx = @runtime.element.idx
|
538
|
+
@runtime.parent_list = @runtime.current_list
|
539
|
+
@runtime.element.next_idx = 0
|
540
|
+
else if @runtime.element.next_level < @runtime.element.level
|
541
|
+
@runtime.element.next_idx = @runtime.element.parent_idx
|
542
|
+
if @runtime.element.current.parent() isnt null
|
543
|
+
list_n = @runtime.parent_list
|
544
|
+
else
|
545
|
+
list_n = @runtime.element_list
|
546
|
+
else if @runtime.element.next_level == 0
|
547
|
+
list_n = @runtime.element_list
|
548
|
+
else
|
549
|
+
list_n = @runtime.current_list
|
550
|
+
|
551
|
+
list_n[@runtime.element.next_idx].highlight()
|
552
|
+
|
553
|
+
@runtime.element.idx = @runtime.element.next_idx
|
554
|
+
@runtime.element.level = @runtime.element.next_level
|
555
|
+
@runtime.current_list = list_n
|
556
|
+
@runtime.element.current = list_n[@runtime.element.idx]
|
557
|
+
|
558
|
+
@makeElementVisible()
|
559
|
+
return true
|
560
|
+
|
561
|
+
removeHighlight: ->
|
562
|
+
@log "removeHighlight" if (@options.debug)
|
563
|
+
return if @runtime.element.current is null
|
564
|
+
@runtime.element.current.removeHighlight()
|
565
|
+
return
|
566
|
+
|
567
|
+
removeActivateClass: ->
|
568
|
+
@log "removeHighlight" if (@options.debug)
|
569
|
+
return if @runtime.current_list is null
|
570
|
+
if @runtime.element.current.children().length == 0
|
571
|
+
@runtime.element.current.removeActivateClass()
|
572
|
+
else
|
573
|
+
# else it's most likely that the children should be highlighted
|
574
|
+
child.removeActivateClass() for child in @runtime.element.current.children()
|
575
|
+
return
|
576
|
+
|
577
|
+
###
|
578
|
+
Make the element(s) visible. If the current selected element is a group, they are all moved inside the visible area of the screen
|
579
|
+
###
|
580
|
+
makeElementVisible: ->
|
581
|
+
return unless @options.visual.ensure_visible_element == true
|
582
|
+
@log "makeElementVisible", "trace" if (@options.debug)
|
583
|
+
scrollval = null
|
584
|
+
scroll_top = $(document).scrollTop()
|
585
|
+
element = @runtime.element.current.jq_element()
|
586
|
+
# positive scroll:
|
587
|
+
if ($(window).height() + scroll_top) < (element.offset().top + element.outerHeight() + @options.visual.scroll_offset)
|
588
|
+
diff_to_make_visible = (element.offset().top + element.outerHeight() + @options.visual.scroll_offset) - ($(document).scrollTop() + $(window).height())
|
589
|
+
if (diff_to_make_visible > 0)
|
590
|
+
scrollval = diff_to_make_visible + scroll_top
|
591
|
+
# negative scroll:
|
592
|
+
else if (scroll_top > (element.offset().top - @options.visual.scroll_offset))
|
593
|
+
if (element.offset().top - @options.visual.scroll_offset < 0)
|
594
|
+
scrollval = 0
|
595
|
+
else
|
596
|
+
scrollval = element.offset().top - @options.visual.scroll_offset
|
597
|
+
|
598
|
+
if (scroll_top != scrollval) && scrollval != null
|
599
|
+
if (@options.visual.animate_scroll_time == 0)
|
600
|
+
# for FF
|
601
|
+
$("html").scrollTop(scrollval)
|
602
|
+
# for Chrome
|
603
|
+
$("html body").scrollTop(scrollval)
|
604
|
+
else
|
605
|
+
# for FF
|
606
|
+
$("html").animate({scrollTop: scrollval}, @options.visual.animate_scroll_time, @options.visual.easing);
|
607
|
+
# for Chrome
|
608
|
+
$("html body").animate({scrollTop: scrollval}, @options.visual.animate_scroll_time, @options.visual.easing);
|
609
|
+
|
610
|
+
|
611
|
+
activateElement: ->
|
612
|
+
@log "activateElement" if (@options.debug)
|
613
|
+
@runtime.action_triggered = true
|
614
|
+
@stopSingleSwitchTimer()
|
615
|
+
|
616
|
+
@log "Activate Element: idx: #{@runtime.element.idx} level: IDX: #{@runtime.element.level} uuid: #{@runtime.element.current.uniqueDataAttr()}" if (@options.debug)
|
617
|
+
if (@options.switches.delay_before_activating_element == 0)
|
618
|
+
return @activateElementCallBack()
|
619
|
+
else
|
620
|
+
@runtime.element.current.jq_element().addClass(@options.element_activate_class)
|
621
|
+
if @runtime.element.current.children().length > 0
|
622
|
+
child.addActivateClass() for child in @runtime.element.current.children()
|
623
|
+
else
|
624
|
+
@runtime.element.current.addActivateClass()
|
625
|
+
|
626
|
+
window.setTimeout(( => @removeActivateClass(); @activateElementCallBack(); return), @options.switches.delay_before_activating_element)
|
627
|
+
return SwitchAccessCommon.actions.triggered_delayed_action
|
628
|
+
|
629
|
+
activateElementCallBack: ->
|
630
|
+
@log "activateElementCallBack" if (@options.debug)
|
631
|
+
|
632
|
+
# see if the element has children, if so go into level
|
633
|
+
if @runtime.element.current.children().length > 0
|
634
|
+
@startSingleSwitchTimer()
|
635
|
+
return @moveToNextLevel()
|
636
|
+
# else the element should "activate"
|
637
|
+
|
638
|
+
if ((@runtime.element.current.jq_element().is("a")) || (@activate_first_link == false))
|
639
|
+
element_to_click = @runtime.element.current.jq_element()
|
640
|
+
else
|
641
|
+
# if element isn't a link, find first link within element and go to the url/trigger it
|
642
|
+
element_to_click = @runtime.element.current.jq_element().find("a")
|
643
|
+
|
644
|
+
# safety catch
|
645
|
+
if (element_to_click.length <= 0)
|
646
|
+
element_to_click = @runtime.element.current.jq_element()
|
647
|
+
|
648
|
+
@log "Triggering Element: IDX: #{@runtime.element.current_idx} Element Tag: #{$(element_to_click).get(0).tagName.toLowerCase()} Text: #{$(element_to_click).text()}" if (@options.debug)
|
649
|
+
|
650
|
+
@runtime.element.current.jq_element().triggerHandler("switch-access-activate", [@runtime.element.idx, @runtime.element.level, element_to_click, @runtime.element.current])
|
651
|
+
if element_to_click.length > 0
|
652
|
+
element_to_click[0].click() #trigger("click")
|
653
|
+
# if (ret == true) && element_to_click.is("a")
|
654
|
+
# document.location = element_to_click.attr("href")
|
655
|
+
if (@options.switches.number_of_switches == 1)
|
656
|
+
@runtime.next_element_idx = -1 if (@options.single_switch_restart_on_activate)
|
657
|
+
@runtime.next_level = 0
|
658
|
+
@startSingleSwitchTimer()
|
659
|
+
else
|
660
|
+
msg = "Nothing to do. Verify options passed to SwitchAccess"
|
661
|
+
@log msg, "warn" if (@options.debug)
|
662
|
+
console.log "SwitchAccess: Warning: " + msg
|
663
|
+
return SwitchAccessCommon.actions.none
|
664
|
+
|
665
|
+
return SwitchAccessCommon.actions.triggered_action
|
666
|
+
|
667
|
+
|
668
|
+
singleSwitchTimerCallback: ->
|
669
|
+
@log "singleSwitchTimerCallback", "trace" if (@options.debug)
|
670
|
+
@moveToNextElementAtLevel()
|
671
|
+
|
672
|
+
allowKeyPressCallback: ->
|
673
|
+
@log "allowKeyPressCallback", "trace" if (@options.debug)
|
674
|
+
@runtime.keypress_allowed = true
|
675
|
+
|
676
|
+
createHighlighterHolder: ->
|
677
|
+
if $("div##{SwitchAccessCommon.options.holder_id}").length == 0
|
678
|
+
@runtime.highlighter_holder = $("<div id=\"#{SwitchAccessCommon.options.highlighter.holder_id}\"></div>")
|
679
|
+
$('body').append(@runtime.highlighter_holder)
|
680
|
+
return
|
681
|
+
|
682
|
+
removeHighlighterHolder: ->
|
683
|
+
$("div##{SwitchAccessCommon.options.highlighter.holder_id}").remove()
|
684
|
+
|
685
|
+
callbackForKeyPress: (event) ->
|
686
|
+
@log "callbackForKeyPress keycode: #{event.which} Allowed: #{@runtime.keypress_allowed}" if (@options.debug)
|
687
|
+
return if (@options.switches.number_of_switches == 0)
|
688
|
+
action = 0
|
689
|
+
|
690
|
+
if @options.switches.number_of_switches == 1
|
691
|
+
if event.which in @options.switches.keys_1
|
692
|
+
if !@runtime.keypress_allowed
|
693
|
+
event.stopPropagation()
|
694
|
+
return false
|
695
|
+
action = @activateElement()
|
696
|
+
|
697
|
+
else if @options.switches.number_of_switches == 2
|
698
|
+
if (event.which in @options.switches.keys_2[0]) || (event.which in @options.switches.keys_2[1])
|
699
|
+
if !@runtime.keypress_allowed
|
700
|
+
event.stopPropagation()
|
701
|
+
return false
|
702
|
+
action = @moveToNextElementAtLevel() if event.which in @options.switches.keys_2[0]
|
703
|
+
action = @activateElement() if event.which in @options.switches.keys_2[1]
|
704
|
+
|
705
|
+
if (@runtime.action_triggered)
|
706
|
+
@runtime.action_triggered = false
|
707
|
+
@runtime.keypress_allowed = false
|
708
|
+
timeout = @options.switches.delay_for_allowed_keypress
|
709
|
+
if (action == SwitchAccessCommon.actions.triggered_action) || (action == SwitchAccessCommon.actions.triggered_delayed_action)
|
710
|
+
if (@options.switches.number_of_switches == 1)
|
711
|
+
if (@options.switches.single_switch_move_time > @options.switches.delay_before_activating_element)
|
712
|
+
timeout = @options.switches.single_switch_move_time
|
713
|
+
else
|
714
|
+
timeout = @options.switches.delay_before_activating_element
|
715
|
+
else
|
716
|
+
if (@options.switches.delay_before_activating_element > timeout)
|
717
|
+
timeout = @options.switches.delay_before_activating_element
|
718
|
+
|
719
|
+
if timeout == 0
|
720
|
+
@allowKeyPressCallback()
|
721
|
+
else
|
722
|
+
window.setTimeout((=>@allowKeyPressCallback();return), timeout)
|
723
|
+
|
724
|
+
event.stopPropagation()
|
725
|
+
return false
|
726
|
+
else
|
727
|
+
return true
|
728
|
+
|
729
|
+
startSingleSwitchTimer: ->
|
730
|
+
return unless @options.switches.number_of_switches == 1
|
731
|
+
@log "startSingleSwitchTimer", "trace" if (@options.debug)
|
732
|
+
@runtime.single_switch_timer_id = window.setInterval(( => @singleSwitchTimerCallback();return), @options.switches.single_switch_move_time)
|
733
|
+
|
734
|
+
stopSingleSwitchTimer: ->
|
735
|
+
return unless @options.switches.number_of_switches == 1
|
736
|
+
@log "stopSingleSwitchTimer", "trace" if (@options.debug)
|
737
|
+
window.clearInterval(@runtime.single_switch_timer_id)
|
738
|
+
|
739
|
+
removeCallbacks: ->
|
740
|
+
@log "removeCallbacks", "trace" if (@options.debug)
|
741
|
+
$(document).off("keydown.switch_access")
|
742
|
+
|
743
|
+
registerCallbacks: ->
|
744
|
+
@log "registerCallbacks", "trace" if (@options.debug)
|
745
|
+
$(document).on("keydown.switch_access", (event) =>
|
746
|
+
@callbackForKeyPress(event)
|
747
|
+
)
|
748
|
+
return
|
749
|
+
|
750
|
+
window.SwitchAccess = SwitchAccess
|
751
|
+
|
752
|
+
class SwitchAccessElement
|
753
|
+
constructor: (jq_element, highlight_holder = null, logger = null, parent = null, children = []) ->
|
754
|
+
@options =
|
755
|
+
debug: false
|
756
|
+
|
757
|
+
@runtime =
|
758
|
+
jq_highlighter: null # jquery object of the highlighter belonging to this element
|
759
|
+
jq_element: jq_element # jquery object of this element
|
760
|
+
uuid: null # The UUID for this element
|
761
|
+
watching: false # if csswatch is enabled for this element
|
762
|
+
csswatch_init: false # if csswatch has been initialized on/for this element
|
763
|
+
parent: parent # the parent switch-element of this element
|
764
|
+
children: children # the child switch-elements of this element
|
765
|
+
highlight_holder: null # the highlight holder from SwitchAccess
|
766
|
+
|
767
|
+
@options.debug = SwitchAccessCommon.options.debug
|
768
|
+
@logger = logger if (@options.debug)
|
769
|
+
|
770
|
+
@runtime.highlight_holder = if highlight_holder == null then $('body') else highlight_holder
|
771
|
+
|
772
|
+
@init(@runtime.highlight_holder)
|
773
|
+
|
774
|
+
init: (highlight_holder)->
|
775
|
+
@uniqueDataAttr(true)
|
776
|
+
@createHighlighter(highlight_holder)
|
777
|
+
@log "init", "trace" if (@options.debug)
|
778
|
+
|
779
|
+
destroy: ->
|
780
|
+
@log "destroy", "trace" if (@options.debug)
|
781
|
+
@destroyHighlighter()
|
782
|
+
# destroy any children
|
783
|
+
child.destroy() for child in @children()
|
784
|
+
|
785
|
+
parent = null
|
786
|
+
children = null
|
787
|
+
jq_element = null
|
788
|
+
|
789
|
+
parent: (parent = null) ->
|
790
|
+
if parent == null
|
791
|
+
@runtime.parent
|
792
|
+
else
|
793
|
+
@runtime.parent = parent
|
794
|
+
|
795
|
+
children: (children = null) ->
|
796
|
+
if children == null
|
797
|
+
@runtime.children
|
798
|
+
else
|
799
|
+
@runtime.children = children
|
800
|
+
|
801
|
+
jq_element: (jq_element = null) ->
|
802
|
+
if (jq_element == null)
|
803
|
+
@runtime.jq_element
|
804
|
+
else
|
805
|
+
@runtime.jq_element = jq_element
|
806
|
+
|
807
|
+
log: (msg, type = "debug", raw = false) ->
|
808
|
+
if @options.debug && @logger != null
|
809
|
+
if (raw)
|
810
|
+
@logger.log "Element: #{@runtime.uuid} :", type
|
811
|
+
@logger.log msg, type, true
|
812
|
+
else
|
813
|
+
@logger.log "Element: #{@runtime.uuid} : #{msg}", type
|
814
|
+
|
815
|
+
###
|
816
|
+
Trigger the active element, link or event depending on options
|
817
|
+
###
|
818
|
+
trigger: ->
|
819
|
+
@log "trigger" if (@options.debug)
|
820
|
+
|
821
|
+
###
|
822
|
+
Show the highlighter and add highlight class to current object
|
823
|
+
###
|
824
|
+
highlight: (check_children = true) ->
|
825
|
+
@log "highlight" if (@options.debug)
|
826
|
+
# if the element has children, it's most likely that the children should be highlighted
|
827
|
+
if @children().length > 0 and check_children == true
|
828
|
+
child.highlight(false) for child in @children()
|
829
|
+
return
|
830
|
+
|
831
|
+
# if the next element doesn't have any children, highlight it
|
832
|
+
@runtime.jq_element.addClass(SwitchAccessCommon.options.highlight.element.current_class)
|
833
|
+
return unless SwitchAccessCommon.options.highlighter.use
|
834
|
+
@runtime.jq_highlighter.addClass(SwitchAccessCommon.options.highlighter.current_class)
|
835
|
+
@runtime.jq_highlighter.show()
|
836
|
+
# Must show the element before moving, else the offset will not be correct
|
837
|
+
@setHighlighterSizeAndPosition()
|
838
|
+
if SwitchAccessCommon.options.highlighter.watch_for_resize
|
839
|
+
if @runtime.watching == false
|
840
|
+
@enableCSSWatch()
|
841
|
+
|
842
|
+
###
|
843
|
+
Hide highlighter and remove highlight class on the current object(s)
|
844
|
+
###
|
845
|
+
removeHighlight: (check_children = true) ->
|
846
|
+
@log "removeHighlight" if (@options.debug)
|
847
|
+
|
848
|
+
# if set to check for children:
|
849
|
+
if @children().length > 0 and check_children == true
|
850
|
+
child.removeHighlight(false) for child in @children()
|
851
|
+
return
|
852
|
+
|
853
|
+
@runtime.jq_element.removeClass(SwitchAccessCommon.options.highlight.element.current_class)
|
854
|
+
@runtime.jq_element.removeClass(SwitchAccessCommon.options.highlight.element.activate_class)
|
855
|
+
return unless SwitchAccessCommon.options.highlighter.use
|
856
|
+
@runtime.jq_highlighter.removeClass(SwitchAccessCommon.options.highlighter.current_class)
|
857
|
+
@runtime.jq_highlighter.removeClass(SwitchAccessCommon.options.highlighter.activate_class)
|
858
|
+
@runtime.jq_highlighter.hide()
|
859
|
+
if SwitchAccessCommon.options.highlighter.watch_for_resize
|
860
|
+
@disableCSSWatch()
|
861
|
+
|
862
|
+
addActivateClass: ->
|
863
|
+
@runtime.jq_element.addClass(SwitchAccessCommon.options.highlight.element.activate_class)
|
864
|
+
return unless SwitchAccessCommon.options.highlighter.use
|
865
|
+
@runtime.jq_highlighter.addClass(SwitchAccessCommon.options.highlighter.activate_class)
|
866
|
+
|
867
|
+
removeActivateClass: ->
|
868
|
+
@log "removeActivateClass" if (@options.debug)
|
869
|
+
@runtime.jq_element.removeClass(SwitchAccessCommon.options.highlight.element.activate_class)
|
870
|
+
return unless SwitchAccessCommon.options.highlighter.use
|
871
|
+
@runtime.jq_highlighter.removeClass(SwitchAccessCommon.options.highlighter.activate_class)
|
872
|
+
|
873
|
+
###
|
874
|
+
Set Highlighter size and position
|
875
|
+
###
|
876
|
+
setHighlighterSizeAndPosition: ->
|
877
|
+
@setHighlighterSize(@runtime.jq_element, @runtime.jq_highlighter)
|
878
|
+
@setHighlighterPosition(@runtime.jq_element, @runtime.jq_highlighter)
|
879
|
+
|
880
|
+
###
|
881
|
+
Set highlighter position
|
882
|
+
###
|
883
|
+
setHighlighterPosition: (element, highlighter) ->
|
884
|
+
# posshift = SwitchAccessCommon.options.highlighter.margin_to_element #+ ((highlighter.outerWidth() - highlighter.innerWidth())/2)
|
885
|
+
@log "m_to_el: #{SwitchAccessCommon.options.highlighter.margin_to_element}, outerW-innerW: #{highlighter.outerWidth() - highlighter.width()} outerH-innerH: #{highlighter.outerHeight() - highlighter.innerHeight()}", "trace" if (@options.debug)
|
886
|
+
position = {
|
887
|
+
top: element.offset().top - SwitchAccessCommon.options.highlighter.margin_to_element - (highlighter.outerHeight() - highlighter.innerHeight())/2
|
888
|
+
left: element.offset().left - SwitchAccessCommon.options.highlighter.margin_to_element - (highlighter.outerWidth() - highlighter.innerWidth())/2
|
889
|
+
}
|
890
|
+
return if (highlighter.offset().top == position.top) and (highlighter.offset().left == position.left)
|
891
|
+
highlighter.offset(position)
|
892
|
+
@log "setHighlighterPosition left: #{position.left} top: #{position.top}", "trace" if (@options.debug)
|
893
|
+
return
|
894
|
+
|
895
|
+
###
|
896
|
+
Set size on the Highlighter object to the match the given element
|
897
|
+
###
|
898
|
+
setHighlighterSize: (element, highlighter) ->
|
899
|
+
w = element.outerWidth(false) + (SwitchAccessCommon.options.highlighter.margin_to_element * 2)
|
900
|
+
h = element.outerHeight(false) + (SwitchAccessCommon.options.highlighter.margin_to_element * 2)
|
901
|
+
|
902
|
+
highlighter.width(w)
|
903
|
+
highlighter.height(h)
|
904
|
+
@log "setHighlighterSize w: #{w}, h: #{h}", "trace" if (@options.debug)
|
905
|
+
return
|
906
|
+
|
907
|
+
###
|
908
|
+
Create the highlighter DOM object
|
909
|
+
###
|
910
|
+
createHighlighter: (jq_holder)->
|
911
|
+
return if (SwitchAccessCommon.options.highlighter.use is false) or
|
912
|
+
(@runtime.jq_highlighter isnt null)
|
913
|
+
@log "createHighlight" if (@options.debug)
|
914
|
+
|
915
|
+
@runtime.jq_highlighter = $("<div id=\"sw-el-#{@runtime.uuid}\" class=\"#{SwitchAccessCommon.options.highlighter.class}\"></div>")
|
916
|
+
jq_holder.append(@runtime.jq_highlighter)
|
917
|
+
@runtime.jq_highlighter.css('position','absolute')
|
918
|
+
@runtime.jq_highlighter.hide()
|
919
|
+
@runtime.jq_highlighter.append(SwitchAccessCommon.options.highlighter.content)
|
920
|
+
|
921
|
+
if SwitchAccessCommon.options.watch_for_resize
|
922
|
+
# check if content contains selector to use for resizeing
|
923
|
+
if @runtime.jq_highlighter.find(SwitchAccessCommon.options.highlighter.selector_for_set_to_size).length == 0
|
924
|
+
@runtime.jq_highlighter.addClass(SwitchAccessCommon.options.highlighter.selector_for_set_to_size)
|
925
|
+
|
926
|
+
###
|
927
|
+
Destroy the highlighter DOM object
|
928
|
+
###
|
929
|
+
destroyHighlighter: ->
|
930
|
+
return if @runtime.jq_highlighter == null
|
931
|
+
@log "destroyHighlight", "trace" if (@options.debug)
|
932
|
+
@disableCSSWatch()
|
933
|
+
|
934
|
+
@runtime.jq_highlighter.remove()
|
935
|
+
@runtime.jq_highlighter = null
|
936
|
+
|
937
|
+
###
|
938
|
+
Enable wathcing CSS changes on the element belonging to this object
|
939
|
+
###
|
940
|
+
enableCSSWatch: ->
|
941
|
+
return unless SwitchAccessCommon.options.highlighter.use == true and
|
942
|
+
SwitchAccessCommon.options.highlighter.watch_for_resize == true
|
943
|
+
@log "enableCSSWatch", "trace" if (@options.debug)
|
944
|
+
@runtime.watching = true
|
945
|
+
if @runtime.csswatch_init
|
946
|
+
@runtime.jq_element.csswatch('start')
|
947
|
+
else
|
948
|
+
@runtime.csswatch_init = true
|
949
|
+
@runtime.jq_element.csswatch({
|
950
|
+
props: "top,left,bottom,right,width,height"
|
951
|
+
props_functions: {
|
952
|
+
top: "offset().top"
|
953
|
+
left: "offset().left"
|
954
|
+
bottom: "offset().bottom"
|
955
|
+
right: "offset().right"
|
956
|
+
outerwidth: "outerWidth(false)"
|
957
|
+
outerheight: "outerHeight(false)"
|
958
|
+
}
|
959
|
+
callback: (->@callbackForResize????)
|
960
|
+
})
|
961
|
+
|
962
|
+
###
|
963
|
+
Disable watching CSS changes on the element belonging to this object
|
964
|
+
###
|
965
|
+
disableCSSWatch: ->
|
966
|
+
return unless SwitchAccessCommon.options.highlighter.use == true and
|
967
|
+
SwitchAccessCommon.options.highlighter.watch_for_resize == true
|
968
|
+
@log "disableCSSWatch", "trace" if (@options.debug)
|
969
|
+
@runtime.watching = false
|
970
|
+
@runtime.jq_element.csswatch('stop')
|
971
|
+
|
972
|
+
###
|
973
|
+
Add a data attribute to the element that has a unique ID.
|
974
|
+
Will also add the same attribute as a class if option
|
975
|
+
set_unique_element_class is enabled.
|
976
|
+
###
|
977
|
+
uniqueDataAttr: (create = false) ->
|
978
|
+
@log "uniqueDataAttr: Create: #{create}", "trace" if (@options.debug)
|
979
|
+
if create
|
980
|
+
@runtime.uuid = SwitchAccessCommon.generateRandomUUID()
|
981
|
+
@runtime.jq_element.data(SwitchAccessCommon.options.internal.unique_element_data_attribute, @runtime.uuid)
|
982
|
+
if SwitchAccessCommon.options.set_unique_element_class == true
|
983
|
+
@runtime.jq_element.addClass("#{SwitchAccessCommon.options.internal.unique_element_data_attribute}+uuid")
|
984
|
+
@runtime.uuid
|
985
|
+
else
|
986
|
+
@runtime.uuid
|
987
|
+
|
988
|
+
###
|
989
|
+
Callback for resize event on this particular element
|
990
|
+
###
|
991
|
+
callbackForResize: (event, changes) ->
|
992
|
+
@log "callbackForResize", "trace" if (@options.debug)
|
993
|
+
return unless SwitchAccessCommon.options.highlighter.use
|
994
|
+
@setHighlighterSize(@runtime.jq_element, @runtime.jq_highlighter)
|
995
|
+
@setHighlighterPosition(@runtime.jq_element, @runtime.jq_highlighter)
|
996
|
+
# if (changes.keys)
|
997
|
+
|
998
|
+
###
|
999
|
+
Play the sound for the current element upon highlight
|
1000
|
+
###
|
1001
|
+
# playHighlightSound: ->
|
1002
|
+
|
1003
|
+
|
1004
|
+
###
|
1005
|
+
Play the sound for the current element upon activation
|
1006
|
+
###
|
1007
|
+
# playActivateSound: ->
|