Quellcode durchsuchen

Ticket #5046 - Accessibility: Operable - Keyboard Accessible.

AntonLV vor 1 Jahr
Ursprung
Commit
1ef6f7ec33

+ 7 - 1
inc/js/classes/BxDolMenuMoreAuto.js

@@ -102,7 +102,13 @@ BxDolMenuMoreAuto.prototype.more = function(oElement)
             el: oElement
         }, 
         moveToDocRoot: false,
-        cssClass: 'bx-popup-menu'
+        cssClass: 'bx-popup-menu',
+        onShow: function(oPopup) {
+            oPopup.find('.bx-popup-content a:first').focus();
+        },
+        onHide: function(oPopup) {
+            $(oElement).focus();
+        }
     });
 }
 

+ 33 - 3
inc/js/functions.js

@@ -420,9 +420,22 @@ function bx_center_content (sSel, sBlockStyle, bListenOnResize) {
 function bx_menu_popup (o, e, options, vars) {
     var options = options || {};
     var vars = vars || {};
-    var o = $.extend({}, $.fn.dolPopupDefaultOptions, {id: o, url: bx_append_url_params('menu.php', $.extend({o:o}, vars)), cssClass: 'bx-popup-menu'}, options);
+
     if ('undefined' == typeof(e))
         e = window;
+
+    var o = $.extend({}, $.fn.dolPopupDefaultOptions, {
+        id: o, 
+        url: bx_append_url_params('menu.php', $.extend({o:o}, vars)), 
+        cssClass: 'bx-popup-menu',
+        onShow: function(oPopup) {
+            oPopup.find('.bx-popup-content a:first').focus();
+        },
+        onHide: function(oPopup) {
+            $(e).focus();
+        }
+    }, options);
+
     $(e).dolPopupAjax(o);
 }
 
@@ -437,16 +450,24 @@ function bx_menu_popup_inline (jSel, e, options) {
         $(jSel).dolPopupHide(); 
     else {
         var options = options || {};
+
+        var bElement = e != undefined && $(e).length != 0;
+
         var o = $.extend({}, $.fn.dolPopupDefaultOptions, options, {
-            pointer: e != undefined && $(e).length != 0 ? {el:$(e)} : false, 
+            pointer: bElement ? {el:$(e)} : false, 
             cssClass: 'bx-popup-menu',
             onShow: function(oPopup) {
+                oPopup.find('.bx-popup-content a:first').focus();
                 oPopup.find('a').each(function () {
                     $(this).off('click.bx-popup-menu');
                     $(this).on('click.bx-popup-menu', function() {
                         $(jSel).dolPopupHide();
                     });
                 });
+            },
+            onHide: function(oPopup) {
+                if(bElement)
+                    $(e).focus();
             }
         });
 
@@ -462,7 +483,7 @@ function bx_menu_popup_inline (jSel, e, options) {
  * @param oVars - additional GET variables
  */
 function bx_menu_slide (sObject, oElement, sPosition, oOptions, oVars) {
-	var oVars = oVars || {};
+    var oVars = oVars || {};
     var oOptions = oOptions || {};
     oOptions = $.extend({}, {parent: 'body', container: '.bx-sliding-menu-content'}, oOptions);
 
@@ -596,6 +617,7 @@ function bx_menu_slide_inline (sMenu, e, sPosition) {
 
     if (eSlider.is(':visible')) {
         fClose();
+        $(e).focus();
 
         $(document).off('click.bx-sliding-menu touchend.bx-sliding-menu');
         $(window).off('resize.bx-sliding-menu');
@@ -607,6 +629,7 @@ function bx_menu_slide_inline (sMenu, e, sPosition) {
         $(window).off('resize.bx-sliding-menu');
 
         fOpen();
+        eSlider.find('.bx-popup-content a:first').focus();
         eSlider.find('a').each(function () {
             $(this).off('click.bx-sliding-menu');
             $(this).on('click.bx-sliding-menu', function () {
@@ -1504,6 +1527,13 @@ function bx_check_mq()
     return window.getComputedStyle(document.querySelector('body'), '::before').getPropertyValue('content').replace(/'/g, "").replace(/"/g, "");
 }
 
+function bx_get_focusable(oContext = 'document')
+{
+  return Array.from(oContext.querySelectorAll('button, [href], input:not([type="hidden"]), textarea, select, [tabindex]:not([tabindex="-1"])')).filter(function(oElement) { 
+      return !oElement.closest('[hidden]'); 
+  });
+}
+
 /**
  * This function loads the passed list of CSS files. In case when this function is called for dynamic loading 
  * of the same file but many times it allows to avoid multiply loadings of the same file.

+ 24 - 0
inc/js/jquery.dolPopup.js

@@ -647,6 +647,14 @@
 
             oAPopup.dolPopupHide();
         });
+        
+        var fOnShow = options.onShow;
+        options.onShow = function(oPopup) {
+            oBtnOk.focus();
+
+            if(typeof(fOnShow) == 'function')
+                fOnShow(oAPopup);
+        };
 
         var fOnHide = options.onHide;
         options.onHide = function(oPopup) {
@@ -715,6 +723,14 @@
             oCPopup.dolPopupHide();
         });
 
+        var fOnShow = options.onShow;
+        options.onShow = function(oPopup) {
+            oBtnYes.focus();
+
+            if(typeof(fOnShow) == 'function')
+                fOnShow(oCPopup);
+        };
+
         var fOnHide = options.onHide;
         options.onHide = function(oPopup) {
             if(typeof(fOnHide) == 'function')
@@ -793,6 +809,14 @@
             oPPopup.dolPopupHide();
         });
 
+        var fOnShow = options.onShow;
+        options.onShow = function(oPopup) {
+            oBtnOk.focus();
+
+            if(typeof(fOnShow) == 'function')
+                fOnShow(oPPopup);
+        };
+
         var fOnHide = options.onHide;
         options.onHide = function(oPopup) {
             if(typeof(fOnHide) == 'function')

+ 1 - 1
modules/boonex/artificer/data/template/mod_profile/menu_custom_item_actions.html

@@ -1,4 +1,4 @@
-<span class="__class_wrp__ truncate">
+<span class="__class_wrp__">
     <a class="__class_link__ bx-stl-mil-gaps-sm flex flex-row flex-nowrap sm:items-center" href="__link__" onclick="__onclick__" title="__title_attr__"__attrs__><span class="bx-mi-icon flex items-center justify-center h-5 w-5"><bx_if:icon><i class="sys-icon __icon__"></i></bx_if:icon><bx_if:image><img class="h-5 w-5" style="background-image:url(__icon_url__)" src="<bx_icon_url:spacer.gif />" /></bx_if:image></span><bx_if:title><span class="bx-mi-text ltr:ml-1.5 ltr:first:ml-0 rtl:mr-1.5 rtl:first:mr-0 whitespace-nowrap truncate">__title__</span></bx_if:title></a>
     <bx_if:addon>__addon__</bx_if:addon>
 </span>

+ 10 - 2
modules/boonex/artificer/data/template/system/_header_js_custom.html

@@ -50,10 +50,18 @@
 
         return oSidebar.hasClass('bx-sidebar-active');
     }
-    
+
     function bx_sidebar_toggle(sType) {
         var oSidebar = bx_sidebar_get(sType);
-        oSidebar.toggleClass('bx-sidebar-active', !bx_sidebar_active(sType));
+        var bSidebarActive = bx_sidebar_active(sType);
+
+        oSidebar.toggleClass('bx-sidebar-active', !bSidebarActive);
+
+        if(!bSidebarActive) {
+            var aFocusable = bx_get_focusable(oSidebar.get(0));
+            if(aFocusable && aFocusable.length > 0)
+                $(aFocusable[0]).focus();
+        }
     }
 
     function bx_sidebar_dropdown_toggle(oLink) {

+ 9 - 1
template/css/tailwind.css

@@ -687,6 +687,10 @@
         @apply hover:no-underline;
         @apply hover:-translate-y-px;
     }
+    .bx-btn-focus {
+        @apply focus:border-blue-500 dark:focus:border-blue-500 focus:border-opacity-70 focus:ring-2 focus:ring-blue-500 focus:ring-opacity-20 focus:outline-none;
+    }
+    
     .bx-btn-active {
         @apply active:bg-gray-300 dark:active:bg-gray-800;
         @apply active:border-gray-400 dark:active:border-gray-700;
@@ -701,7 +705,7 @@
         @apply bx-btn-text;
         @apply transform-gpu transition-all duration-150;
         @apply cursor-pointer;
-        @apply bx-btn-hover bx-btn-active;
+        @apply bx-btn-hover bx-btn-focus bx-btn-active;
     }
     .bx-btn i, 
     .bx-btn u {
@@ -1013,6 +1017,10 @@
         @apply bx-stl-mil-hover-bg;
     }
 
+    .bx-stl-mil-focus {
+        @apply focus:border-blue-500 dark:focus:border-blue-500 focus:border-opacity-70 focus:ring-2 focus:ring-blue-500 focus:ring-opacity-20 focus:outline-none;
+    }
+    
     .bx-stl-mil-active-bg {
         @apply active:border-gray-300 dark:active:border-gray-700;
         @apply active:bg-gray-300 dark:active:bg-black/50;

+ 1 - 1
template/scripts/BxBaseFunctions.php

@@ -350,7 +350,7 @@ class BxBaseFunctions extends BxDolFactory implements iBxDolSingleton
 
         // add button width popup
         $sId = 'bx-str-limit-' . rand(1, PHP_INT_MAX);
-        $sPopup = '<span class="bx-str-limit" onclick="$(\'#' . $sId . '\').dolPopup({pointer:{el:$(this), offset:\'10 1\'}})"/><i class="sys-icon ellipsis-h"></i></span>';
+        $sPopup = '<a class="bx-str-limit" href="javascript:void(0)"  onclick="$(\'#' . $sId . '\').dolPopup({pointer:{el:$(this), offset:\'10 1\'}})"><i class="sys-icon ellipsis-h"></i></a>';
         $sPopup .= '<div id="' . $sId . '" style="display:none;">' . BxTemplFunctions::getInstance()->transBox('', '<div class="bx-def-padding">'.$sString.'</div>') . '</div>';
 
         return $bReturnString ? $sResult . $sPopup : array($sResult, $sPopup);