@@ -163,7 +163,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
163
163
// {@link Attribute#$observe } on it. For more details please see {@link TableColumnResize }.
164
164
scope . $isRendered = true ;
165
165
166
- // Deferred object that will be resolved when this modal is render .
166
+ // Deferred object that will be resolved when this modal is rendered .
167
167
var modalRenderDeferObj = $q . defer ( ) ;
168
168
// Resolve render promise post-digest
169
169
scope . $$postDigest ( function ( ) {
@@ -196,7 +196,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
196
196
197
197
/**
198
198
* If something within the freshly-opened modal already has focus (perhaps via a
199
- * directive that causes focus). then no need to try and focus anything.
199
+ * directive that causes focus) then there's no need to try to focus anything.
200
200
*/
201
201
if ( ! ( $document [ 0 ] . activeElement && element [ 0 ] . contains ( $document [ 0 ] . activeElement ) ) ) {
202
202
var inputWithAutofocus = element [ 0 ] . querySelector ( '[autofocus]' ) ;
@@ -254,6 +254,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
254
254
} ;
255
255
var topModalIndex = 0 ;
256
256
var previousTopOpenedModal = null ;
257
+ var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count' ;
257
258
258
259
//Modal focus behavior
259
260
var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' +
@@ -529,6 +530,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
529
530
'role' : 'dialog' ,
530
531
'aria-labelledby' : modal . ariaLabelledBy ,
531
532
'aria-describedby' : modal . ariaDescribedBy ,
533
+ 'aria-live' : 'polite' ,
532
534
'size' : modal . size ,
533
535
'index' : topModalIndex ,
534
536
'animate' : 'animate' ,
@@ -555,20 +557,65 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
555
557
556
558
openedWindows . top ( ) . value . modalDomEl = angularDomEl ;
557
559
openedWindows . top ( ) . value . modalOpener = modalOpener ;
560
+
561
+ applyAriaHidden ( angularDomEl [ 0 ] ) ;
562
+
563
+ function applyAriaHidden ( el ) {
564
+ if ( ! el || el . tagName === 'BODY' ) {
565
+ return ;
566
+ }
567
+
568
+ getSiblings ( el ) . forEach ( function ( sibling ) {
569
+ var elemIsAlreadyHidden = sibling . getAttribute ( 'aria-hidden' ) === 'true' ,
570
+ ariaHiddenCount =
571
+ parseInt ( sibling . getAttribute ( ARIA_HIDDEN_ATTRIBUTE_NAME ) , 10 ) ||
572
+ elemIsAlreadyHidden ? 1 : 0 ;
573
+
574
+ sibling . setAttribute ( ARIA_HIDDEN_ATTRIBUTE_NAME , ariaHiddenCount + 1 ) ;
575
+ sibling . setAttribute ( 'aria-hidden' , 'true' ) ;
576
+ } ) ;
577
+
578
+ return applyAriaHidden ( el . parentElement ) ;
579
+
580
+ function getSiblings ( el ) {
581
+ var children = el . parentElement ? el . parentElement . children : [ ] ;
582
+
583
+ return Array . prototype . filter . call ( children , function ( child ) {
584
+ return child !== el ;
585
+ } ) ;
586
+ }
587
+ }
558
588
} ;
559
589
560
590
function broadcastClosing ( modalWindow , resultOrReason , closing ) {
561
591
return ! modalWindow . value . modalScope . $broadcast ( 'modal.closing' , resultOrReason , closing ) . defaultPrevented ;
562
592
}
563
593
564
594
$modalStack . close = function ( modalInstance , result ) {
565
- var modalWindow = openedWindows . get ( modalInstance ) ;
595
+ var modalWindow ;
596
+
597
+ Array . prototype . forEach . call (
598
+ document . querySelectorAll ( '[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']' ) ,
599
+ function ( hiddenEl ) {
600
+ var ariaHiddenCount = parseInt ( hiddenEl . getAttribute ( ARIA_HIDDEN_ATTRIBUTE_NAME ) , 10 ) ,
601
+ newHiddenCount = ariaHiddenCount - 1 ;
602
+ hiddenEl . setAttribute ( ARIA_HIDDEN_ATTRIBUTE_NAME , newHiddenCount ) ;
603
+
604
+ if ( ! newHiddenCount ) {
605
+ hiddenEl . removeAttribute ( ARIA_HIDDEN_ATTRIBUTE_NAME ) ;
606
+ hiddenEl . removeAttribute ( 'aria-hidden' ) ;
607
+ }
608
+ }
609
+ ) ;
610
+
611
+ modalWindow = openedWindows . get ( modalInstance ) ;
566
612
if ( modalWindow && broadcastClosing ( modalWindow , result , true ) ) {
567
613
modalWindow . value . modalScope . $$uibDestructionScheduled = true ;
568
614
modalWindow . value . deferred . resolve ( result ) ;
569
615
removeModalWindow ( modalInstance , modalWindow . value . modalOpener ) ;
570
616
return true ;
571
617
}
618
+
572
619
return ! modalWindow ;
573
620
} ;
574
621
0 commit comments