42
42
el . removeAttr ( attr )
43
43
}
44
44
}
45
+
46
+ // selectors Courtesy: https://github.com/jquery/jquery-ui/blob/master/ui/core.js
47
+ var focusable = function ( element , isTabIndexNotNaN ) {
48
+ var map , mapName , img ,
49
+ nodeName = element . nodeName . toLowerCase ( ) ;
50
+ if ( "area" === nodeName ) {
51
+ map = element . parentNode ;
52
+ mapName = map . name ;
53
+ if ( ! element . href || ! mapName || map . nodeName . toLowerCase ( ) !== "map" ) {
54
+ return false ;
55
+ }
56
+ img = $ ( "img[usemap='#" + mapName + "']" ) [ 0 ] ;
57
+ return ! ! img && visible ( img ) ;
58
+ }
59
+ return ( / i n p u t | s e l e c t | t e x t a r e a | b u t t o n | o b j e c t / . test ( nodeName ) ?
60
+ ! element . disabled :
61
+ "a" === nodeName ?
62
+ element . href || isTabIndexNotNaN :isTabIndexNotNaN ) && visible ( element ) ; // the element and all of its ancestors must be visible
63
+ }
64
+ var visible = function ( element ) {
65
+ return $ . expr . filters . visible ( element ) &&
66
+ ! $ ( element ) . parents ( ) . addBack ( ) . filter ( function ( ) {
67
+ return $ . css ( this , "visibility" ) === "hidden" ;
68
+ } ) . length ;
69
+ }
70
+
71
+ $ . extend ( $ . expr [ ":" ] , {
72
+ data : $ . expr . createPseudo ?
73
+ $ . expr . createPseudo ( function ( dataName ) {
74
+ return function ( elem ) {
75
+ return ! ! $ . data ( elem , dataName ) ;
76
+ } ;
77
+ } ) :
78
+ // support: jQuery <1.8
79
+ function ( elem , i , match ) {
80
+ return ! ! $ . data ( elem , match [ 3 ] ) ;
81
+ } ,
82
+
83
+ focusable : function ( element ) {
84
+ return focusable ( element , ! isNaN ( $ . attr ( element , "tabindex" ) ) ) ;
85
+ } ,
86
+
87
+ tabbable : function ( element ) {
88
+ var tabIndex = $ . attr ( element , "tabindex" ) ,
89
+ isTabIndexNaN = isNaN ( tabIndex ) ;
90
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable ( element , ! isTabIndexNaN ) ;
91
+ }
92
+ } ) ;
93
+
45
94
// Alert Extension
46
95
// ===============================
47
96
48
97
$ ( '.alert' ) . attr ( 'role' , 'alert' )
49
98
$ ( '.close' ) . removeAttr ( 'aria-hidden' ) . wrapInner ( '<span aria-hidden="true"></span>' ) . append ( '<span class="sr-only">Close</span>' )
50
99
51
- // TOOLTIP Extension
52
- // ===============================
53
-
54
- var showTooltip = $ . fn . tooltip . Constructor . prototype . show
55
- , hideTooltip = $ . fn . tooltip . Constructor . prototype . hide
56
-
57
- $ . fn . tooltip . Constructor . prototype . show = function ( ) {
58
- showTooltip . apply ( this , arguments )
59
- var $tip = this . tip ( )
60
- , tooltipID = $tip . attr ( 'id' ) || uniqueId ( 'ui-tooltip' )
61
- $tip . attr ( { 'role' :'tooltip' , 'id' : tooltipID } )
62
- this . $element . attr ( 'aria-describedby' , tooltipID )
63
- }
64
-
65
- $ . fn . tooltip . Constructor . prototype . hide = function ( ) {
66
- hideTooltip . apply ( this , arguments )
67
- removeMultiValAttributes ( this . $element , 'aria-describedby' , this . tip ( ) . attr ( 'id' ) )
68
- return this
69
- }
70
- // Popover Extension
71
- // ===============================
72
-
73
- var showPopover = $ . fn . popover . Constructor . prototype . setContent
74
- , hidePopover = $ . fn . popover . Constructor . prototype . hide
75
-
76
- $ . fn . popover . Constructor . prototype . setContent = function ( ) {
77
- showPopover . apply ( this , arguments )
78
- var $tip = this . tip ( )
79
- , tooltipID = $tip . attr ( 'id' ) || uniqueId ( 'ui-tooltip' )
80
- $tip . attr ( { 'role' :'alert' , 'id' : tooltipID } )
81
- this . $element . attr ( 'aria-describedby' , tooltipID )
82
- this . $element . focus ( )
83
- }
84
- $ . fn . popover . Constructor . prototype . hide = function ( ) {
85
- hidePopover . apply ( this , arguments )
86
- removeMultiValAttributes ( this . $element , 'aria-describedby' , this . tip ( ) . attr ( 'id' ) )
87
- return this
88
- }
89
-
90
100
// Modal Extension
91
101
// ===============================
92
102
@@ -95,9 +105,23 @@ $('.close').removeAttr('aria-hidden').wrapInner('<span aria-hidden="true"></span
95
105
$ . fn . modal . Constructor . prototype . hide = function ( ) {
96
106
var modalOpener = this . $element . parent ( ) . find ( '[data-target="#' + this . $element . attr ( 'id' ) + '"]' )
97
107
modalhide . apply ( this , arguments )
98
- console . log ( 'modalOpener' , modalOpener )
99
108
modalOpener . focus ( )
109
+ $ ( document ) . off ( 'keydown.bs.modal' )
100
110
}
111
+
112
+ var modalfocus = $ . fn . modal . Constructor . prototype . enforceFocus
113
+ $ . fn . modal . Constructor . prototype . enforceFocus = function ( ) {
114
+ var focEls = this . $element . find ( ":tabbable" )
115
+ , lastEl = focEls [ focEls . length - 1 ]
116
+ $ ( document ) . on ( 'keydown.bs.modal' , $ . proxy ( function ( ev ) {
117
+ if ( ! this . $element . has ( ev . target ) . length && ev . shiftKey && ev . keyCode === 9 ) {
118
+ lastEl . focus ( )
119
+ ev . preventDefault ( ) ;
120
+ }
121
+ } , this ) )
122
+
123
+ modalfocus . apply ( this , arguments )
124
+ }
101
125
// DROPDOWN Extension
102
126
// ===============================
103
127
@@ -115,11 +139,13 @@ $('.close').removeAttr('aria-hidden').wrapInner('<span aria-hidden="true"></span
115
139
$par = $ ( this )
116
140
var $toggle = $par . find ( toggle )
117
141
$toggle . attr ( 'aria-expanded' , 'true' )
142
+ $toggle . on ( 'keydown.bs.modal' , $ . proxy ( function ( ev ) {
143
+ setTimeout ( function ( ) {
144
+ firstItem = $ ( '.dropdown-menu [role=menuitem]:visible' , $par ) [ 0 ]
145
+ try { firstItem . focus ( ) } catch ( ex ) { }
146
+ } , focusDelay )
147
+ } , this ) )
118
148
119
- setTimeout ( function ( ) {
120
- firstItem = $ ( '.dropdown-menu [role=menuitem]:visible' , $par ) [ 0 ]
121
- try { firstItem . focus ( ) } catch ( ex ) { }
122
- } , focusDelay )
123
149
} )
124
150
125
151
$ ( toggle ) . parent ( ) . on ( 'hidden.bs.dropdown' , function ( e ) {
@@ -128,20 +154,10 @@ $('.close').removeAttr('aria-hidden').wrapInner('<span aria-hidden="true"></span
128
154
$toggle . attr ( 'aria-expanded' , 'false' )
129
155
} )
130
156
131
- //Adding Space Key Behaviour, opens on spacebar
132
- $ . fn . dropdown . Constructor . prototype . keydown = function ( e ) {
133
- var $par
134
- , firstItem
135
- if ( ! / ( 3 2 ) / . test ( e . keyCode ) ) return
136
- $par = $ ( this ) . parent ( )
137
- $ ( this ) . trigger ( "click" )
138
- e . preventDefault ( ) && e . stopPropagation ( )
139
- }
140
-
141
157
$ ( document )
142
158
. on ( 'focusout.dropdown.data-api' , '.dropdown-menu' , function ( e ) {
143
159
var $this = $ ( this )
144
- , that = this
160
+ , that = this
145
161
setTimeout ( function ( ) {
146
162
if ( ! $ . contains ( that , document . activeElement ) ) {
147
163
$this . parent ( ) . removeClass ( 'open' )
@@ -242,10 +258,10 @@ $('.close').removeAttr('aria-hidden').wrapInner('<span aria-hidden="true"></span
242
258
if ( collparent ) {
243
259
collparent . attr ( { 'role' : 'tablist' , 'aria-multiselectable' : 'true' } )
244
260
if ( collpanel . hasClass ( 'in' ) ) {
245
- colltab . attr ( { 'aria-controls' : colltab . attr ( 'href' ) . substr ( 1 ) , 'aria-selected' :'true' , 'aria-expanded' :'true' , 'tabindex' :'0' } )
261
+ colltab . attr ( { 'aria-controls' : collpanel . attr ( 'id' ) , 'aria-selected' :'true' , 'aria-expanded' :'true' , 'tabindex' :'0' } )
246
262
collpanel . attr ( { 'role' :'tabpanel' , 'tabindex' :'0' , 'aria-labelledby' :collid , 'aria-hidden' :'false' } )
247
263
} else {
248
- colltab . attr ( { 'aria-controls' : colltab . attr ( 'href' ) . substr ( 1 ) , 'tabindex' :'-1' } )
264
+ colltab . attr ( { 'aria-controls' : collpanel . attr ( 'id' ) , 'tabindex' :'-1' } )
249
265
collpanel . attr ( { 'role' :'tabpanel' , 'tabindex' :'-1' , 'aria-labelledby' :collid , 'aria-hidden' :'true' } )
250
266
}
251
267
}
@@ -361,40 +377,50 @@ $('.close').removeAttr('aria-hidden').wrapInner('<span aria-hidden="true"></span
361
377
slideCarousel . apply ( this , arguments )
362
378
363
379
$active
364
- . one ( $ . support . transition . end , function ( ) {
365
- $active . attr ( { 'aria-selected' :false , 'tabIndex' : '-1' } )
366
- $next . attr ( { 'aria-selected' :true , 'tabIndex' : '0' } )
367
- //.focus()
380
+ . one ( 'bsTransitionEnd' , function ( ) {
381
+ $active . attr ( { 'aria-selected' :false , 'tabIndex' : '-1' } )
382
+ $next . attr ( { 'aria-selected' :true , 'tabIndex' : '0' } )
383
+ //.focus()
368
384
} )
369
385
}
370
386
371
- $ . fn . carousel . Constructor . prototype . keydown = function ( e ) {
372
- var $this = $ ( this )
373
- , $ul = $this . closest ( 'div[role=listbox]' )
387
+ var $this ;
388
+ $ . fn . carousel . Constructor . prototype . keydown = function ( e ) {
389
+ $this = $this || $ ( this )
390
+ if ( this instanceof Node ) $this = $ ( this )
391
+ var $ul = $this . closest ( 'div[role=listbox]' )
374
392
, $items = $ul . find ( '[role=option]' )
375
393
, $parent = $ul . parent ( )
376
394
, k = e . which || e . keyCode
377
395
, index
378
396
, i
379
397
380
398
if ( ! / ( 3 7 | 3 8 | 3 9 | 4 0 ) / . test ( k ) ) return
381
-
382
399
index = $items . index ( $items . filter ( '.active' ) )
383
400
if ( k == 37 || k == 38 ) { // Up
384
- $parent . carousel ( 'prev' )
401
+
385
402
index --
386
403
if ( index < 0 ) index = $items . length - 1
387
- else $this . prev ( ) . focus ( )
404
+ else {
405
+ $parent . carousel ( 'prev' )
406
+ setTimeout ( function ( ) {
407
+ $items [ index ] . focus ( )
408
+ // $this.prev().focus()
409
+ } , 150 )
410
+ }
388
411
389
412
}
390
413
if ( k == 39 || k == 40 ) { // Down
391
- $parent . carousel ( 'next' )
392
414
index ++
393
- if ( index == $items . length ) index = 0
415
+ if ( index == $items . length ) {
416
+ index = 0
417
+ }
394
418
else {
395
- $this . one ( $ . support . transition . end , function ( ) {
396
- $this . next ( ) . focus ( )
397
- } )
419
+ $parent . carousel ( 'next' )
420
+ setTimeout ( function ( ) {
421
+ $items [ index ] . focus ( )
422
+ // $this.next().focus()
423
+ } , 150 )
398
424
}
399
425
400
426
}
@@ -404,4 +430,5 @@ $('.close').removeAttr('aria-hidden').wrapInner('<span aria-hidden="true"></span
404
430
}
405
431
$ ( document ) . on ( 'keydown.carousel.data-api' , 'div[role=option]' , $ . fn . carousel . Constructor . prototype . keydown )
406
432
433
+
407
434
} ) ( jQuery ) ;
0 commit comments