@@ -693,19 +693,45 @@ function setupMobileSidebarKeyboardHandlers() {
693
693
}
694
694
695
695
/**
696
- * When the page loads or the window resizes check all elements with
697
- * [data-tabindex="0"], and if they have scrollable overflow, set tabIndex = 0.
696
+ * When the page loads, or the window resizes, or descendant nodes are added or
697
+ * removed from the main element, check all code blocks and Jupyter notebook
698
+ * outputs, and for each one that has scrollable overflow, set tabIndex = 0.
698
699
*/
699
- function setupLiteralBlockTabStops ( ) {
700
+ function addTabStopsToScrollableElements ( ) {
700
701
const updateTabStops = ( ) => {
701
- document . querySelectorAll ( '[data-tabindex="0"]' ) . forEach ( ( el ) => {
702
- el . tabIndex =
703
- el . scrollWidth > el . clientWidth || el . scrollHeight > el . clientHeight
704
- ? 0
705
- : - 1 ;
706
- } ) ;
702
+ document
703
+ . querySelectorAll (
704
+ '[data-tabindex="0"], ' + // code blocks
705
+ ".output_area, " + // NBSphinx notebook output
706
+ ".output, " + // Myst-NB
707
+ ".jp-RenderedHTMLCommon" // ipywidgets
708
+ )
709
+ . forEach ( ( el ) => {
710
+ el . tabIndex =
711
+ el . scrollWidth > el . clientWidth || el . scrollHeight > el . clientHeight
712
+ ? 0
713
+ : - 1 ;
714
+ } ) ;
707
715
} ;
708
- window . addEventListener ( "resize" , debounce ( updateTabStops , 300 ) ) ;
716
+ const debouncedUpdateTabStops = debounce ( updateTabStops , 300 ) ;
717
+
718
+ // On window resize
719
+ window . addEventListener ( "resize" , debouncedUpdateTabStops ) ;
720
+
721
+ // The following MutationObserver is for ipywidgets, which take some time to
722
+ // finish loading and rendering on the page (so even after the "load" event is
723
+ // fired, they still have not finished rendering). Would be nice to replace
724
+ // the MutationObserver if there is a way to hook into the ipywidgets code to
725
+ // know when it is done.
726
+ const mainObserver = new MutationObserver ( debouncedUpdateTabStops ) ;
727
+
728
+ // On descendant nodes added/removed from main element
729
+ mainObserver . observe ( document . getElementById ( "main-content" ) , {
730
+ subtree : true ,
731
+ childList : true ,
732
+ } ) ;
733
+
734
+ // On page load
709
735
updateTabStops ( ) ;
710
736
}
711
737
function debounce ( callback , wait ) {
@@ -729,4 +755,7 @@ documentReady(setupSearchButtons);
729
755
documentReady ( initRTDObserver ) ;
730
756
documentReady ( setupMobileSidebarKeyboardHandlers ) ;
731
757
documentReady ( fixMoreLinksInMobileSidebar ) ;
732
- documentReady ( setupLiteralBlockTabStops ) ;
758
+
759
+ // Use load event because determining whether an element has scrollable content
760
+ // depends on stylesheets (which come after DOMContentLoaded)
761
+ window . addEventListener ( "load" , addTabStopsToScrollableElements ) ;
0 commit comments