| @@ 2830-3041 (lines=212) @@ | ||
| 2827 | var hasTabstopData = function (elm) { |
|
| 2828 | return elm.getAttribute('data-mce-tabstop') ? true : false; |
|
| 2829 | }; |
|
| 2830 | function KeyboardNavigation (settings) { |
|
| 2831 | var root = settings.root; |
|
| 2832 | var focusedElement, focusedControl; |
|
| 2833 | function isElement(node) { |
|
| 2834 | return node && node.nodeType === 1; |
|
| 2835 | } |
|
| 2836 | try { |
|
| 2837 | focusedElement = document.activeElement; |
|
| 2838 | } catch (ex) { |
|
| 2839 | focusedElement = document.body; |
|
| 2840 | } |
|
| 2841 | focusedControl = root.getParentCtrl(focusedElement); |
|
| 2842 | function getRole(elm) { |
|
| 2843 | elm = elm || focusedElement; |
|
| 2844 | if (isElement(elm)) { |
|
| 2845 | return elm.getAttribute('role'); |
|
| 2846 | } |
|
| 2847 | return null; |
|
| 2848 | } |
|
| 2849 | function getParentRole(elm) { |
|
| 2850 | var role, parent$$1 = elm || focusedElement; |
|
| 2851 | while (parent$$1 = parent$$1.parentNode) { |
|
| 2852 | if (role = getRole(parent$$1)) { |
|
| 2853 | return role; |
|
| 2854 | } |
|
| 2855 | } |
|
| 2856 | } |
|
| 2857 | function getAriaProp(name$$1) { |
|
| 2858 | var elm = focusedElement; |
|
| 2859 | if (isElement(elm)) { |
|
| 2860 | return elm.getAttribute('aria-' + name$$1); |
|
| 2861 | } |
|
| 2862 | } |
|
| 2863 | function isTextInputElement(elm) { |
|
| 2864 | var tagName = elm.tagName.toUpperCase(); |
|
| 2865 | return tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT'; |
|
| 2866 | } |
|
| 2867 | function canFocus(elm) { |
|
| 2868 | if (isTextInputElement(elm) && !elm.hidden) { |
|
| 2869 | return true; |
|
| 2870 | } |
|
| 2871 | if (hasTabstopData(elm)) { |
|
| 2872 | return true; |
|
| 2873 | } |
|
| 2874 | if (/^(button|menuitem|checkbox|tab|menuitemcheckbox|option|gridcell|slider)$/.test(getRole(elm))) { |
|
| 2875 | return true; |
|
| 2876 | } |
|
| 2877 | return false; |
|
| 2878 | } |
|
| 2879 | function getFocusElements(elm) { |
|
| 2880 | var elements = []; |
|
| 2881 | function collect(elm) { |
|
| 2882 | if (elm.nodeType !== 1 || elm.style.display === 'none' || elm.disabled) { |
|
| 2883 | return; |
|
| 2884 | } |
|
| 2885 | if (canFocus(elm)) { |
|
| 2886 | elements.push(elm); |
|
| 2887 | } |
|
| 2888 | for (var i = 0; i < elm.childNodes.length; i++) { |
|
| 2889 | collect(elm.childNodes[i]); |
|
| 2890 | } |
|
| 2891 | } |
|
| 2892 | collect(elm || root.getEl()); |
|
| 2893 | return elements; |
|
| 2894 | } |
|
| 2895 | function getNavigationRoot(targetControl) { |
|
| 2896 | var navigationRoot, controls; |
|
| 2897 | targetControl = targetControl || focusedControl; |
|
| 2898 | controls = targetControl.parents().toArray(); |
|
| 2899 | controls.unshift(targetControl); |
|
| 2900 | for (var i = 0; i < controls.length; i++) { |
|
| 2901 | navigationRoot = controls[i]; |
|
| 2902 | if (navigationRoot.settings.ariaRoot) { |
|
| 2903 | break; |
|
| 2904 | } |
|
| 2905 | } |
|
| 2906 | return navigationRoot; |
|
| 2907 | } |
|
| 2908 | function focusFirst(targetControl) { |
|
| 2909 | var navigationRoot = getNavigationRoot(targetControl); |
|
| 2910 | var focusElements = getFocusElements(navigationRoot.getEl()); |
|
| 2911 | if (navigationRoot.settings.ariaRemember && 'lastAriaIndex' in navigationRoot) { |
|
| 2912 | moveFocusToIndex(navigationRoot.lastAriaIndex, focusElements); |
|
| 2913 | } else { |
|
| 2914 | moveFocusToIndex(0, focusElements); |
|
| 2915 | } |
|
| 2916 | } |
|
| 2917 | function moveFocusToIndex(idx, elements) { |
|
| 2918 | if (idx < 0) { |
|
| 2919 | idx = elements.length - 1; |
|
| 2920 | } else if (idx >= elements.length) { |
|
| 2921 | idx = 0; |
|
| 2922 | } |
|
| 2923 | if (elements[idx]) { |
|
| 2924 | elements[idx].focus(); |
|
| 2925 | } |
|
| 2926 | return idx; |
|
| 2927 | } |
|
| 2928 | function moveFocus(dir, elements) { |
|
| 2929 | var idx = -1; |
|
| 2930 | var navigationRoot = getNavigationRoot(); |
|
| 2931 | elements = elements || getFocusElements(navigationRoot.getEl()); |
|
| 2932 | for (var i = 0; i < elements.length; i++) { |
|
| 2933 | if (elements[i] === focusedElement) { |
|
| 2934 | idx = i; |
|
| 2935 | } |
|
| 2936 | } |
|
| 2937 | idx += dir; |
|
| 2938 | navigationRoot.lastAriaIndex = moveFocusToIndex(idx, elements); |
|
| 2939 | } |
|
| 2940 | function left() { |
|
| 2941 | var parentRole = getParentRole(); |
|
| 2942 | if (parentRole === 'tablist') { |
|
| 2943 | moveFocus(-1, getFocusElements(focusedElement.parentNode)); |
|
| 2944 | } else if (focusedControl.parent().submenu) { |
|
| 2945 | cancel(); |
|
| 2946 | } else { |
|
| 2947 | moveFocus(-1); |
|
| 2948 | } |
|
| 2949 | } |
|
| 2950 | function right() { |
|
| 2951 | var role = getRole(), parentRole = getParentRole(); |
|
| 2952 | if (parentRole === 'tablist') { |
|
| 2953 | moveFocus(1, getFocusElements(focusedElement.parentNode)); |
|
| 2954 | } else if (role === 'menuitem' && parentRole === 'menu' && getAriaProp('haspopup')) { |
|
| 2955 | enter(); |
|
| 2956 | } else { |
|
| 2957 | moveFocus(1); |
|
| 2958 | } |
|
| 2959 | } |
|
| 2960 | function up() { |
|
| 2961 | moveFocus(-1); |
|
| 2962 | } |
|
| 2963 | function down() { |
|
| 2964 | var role = getRole(), parentRole = getParentRole(); |
|
| 2965 | if (role === 'menuitem' && parentRole === 'menubar') { |
|
| 2966 | enter(); |
|
| 2967 | } else if (role === 'button' && getAriaProp('haspopup')) { |
|
| 2968 | enter({ key: 'down' }); |
|
| 2969 | } else { |
|
| 2970 | moveFocus(1); |
|
| 2971 | } |
|
| 2972 | } |
|
| 2973 | function tab(e) { |
|
| 2974 | var parentRole = getParentRole(); |
|
| 2975 | if (parentRole === 'tablist') { |
|
| 2976 | var elm = getFocusElements(focusedControl.getEl('body'))[0]; |
|
| 2977 | if (elm) { |
|
| 2978 | elm.focus(); |
|
| 2979 | } |
|
| 2980 | } else { |
|
| 2981 | moveFocus(e.shiftKey ? -1 : 1); |
|
| 2982 | } |
|
| 2983 | } |
|
| 2984 | function cancel() { |
|
| 2985 | focusedControl.fire('cancel'); |
|
| 2986 | } |
|
| 2987 | function enter(aria) { |
|
| 2988 | aria = aria || {}; |
|
| 2989 | focusedControl.fire('click', { |
|
| 2990 | target: focusedElement, |
|
| 2991 | aria: aria |
|
| 2992 | }); |
|
| 2993 | } |
|
| 2994 | root.on('keydown', function (e) { |
|
| 2995 | function handleNonTabOrEscEvent(e, handler) { |
|
| 2996 | if (isTextInputElement(focusedElement) || hasTabstopData(focusedElement)) { |
|
| 2997 | return; |
|
| 2998 | } |
|
| 2999 | if (getRole(focusedElement) === 'slider') { |
|
| 3000 | return; |
|
| 3001 | } |
|
| 3002 | if (handler(e) !== false) { |
|
| 3003 | e.preventDefault(); |
|
| 3004 | } |
|
| 3005 | } |
|
| 3006 | if (e.isDefaultPrevented()) { |
|
| 3007 | return; |
|
| 3008 | } |
|
| 3009 | switch (e.keyCode) { |
|
| 3010 | case 37: |
|
| 3011 | handleNonTabOrEscEvent(e, left); |
|
| 3012 | break; |
|
| 3013 | case 39: |
|
| 3014 | handleNonTabOrEscEvent(e, right); |
|
| 3015 | break; |
|
| 3016 | case 38: |
|
| 3017 | handleNonTabOrEscEvent(e, up); |
|
| 3018 | break; |
|
| 3019 | case 40: |
|
| 3020 | handleNonTabOrEscEvent(e, down); |
|
| 3021 | break; |
|
| 3022 | case 27: |
|
| 3023 | cancel(); |
|
| 3024 | break; |
|
| 3025 | case 14: |
|
| 3026 | case 13: |
|
| 3027 | case 32: |
|
| 3028 | handleNonTabOrEscEvent(e, enter); |
|
| 3029 | break; |
|
| 3030 | case 9: |
|
| 3031 | tab(e); |
|
| 3032 | e.preventDefault(); |
|
| 3033 | break; |
|
| 3034 | } |
|
| 3035 | }); |
|
| 3036 | root.on('focusin', function (e) { |
|
| 3037 | focusedElement = e.target; |
|
| 3038 | focusedControl = e.control; |
|
| 3039 | }); |
|
| 3040 | return { focusFirst: focusFirst }; |
|
| 3041 | } |
|
| 3042 | ||
| 3043 | var selectorCache = {}; |
|
| 3044 | var Container = Control$1.extend({ |
|
| @@ 2804-3015 (lines=212) @@ | ||
| 2801 | var hasTabstopData = function (elm) { |
|
| 2802 | return elm.getAttribute('data-mce-tabstop') ? true : false; |
|
| 2803 | }; |
|
| 2804 | function KeyboardNavigation (settings) { |
|
| 2805 | var root = settings.root; |
|
| 2806 | var focusedElement, focusedControl; |
|
| 2807 | function isElement(node) { |
|
| 2808 | return node && node.nodeType === 1; |
|
| 2809 | } |
|
| 2810 | try { |
|
| 2811 | focusedElement = document.activeElement; |
|
| 2812 | } catch (ex) { |
|
| 2813 | focusedElement = document.body; |
|
| 2814 | } |
|
| 2815 | focusedControl = root.getParentCtrl(focusedElement); |
|
| 2816 | function getRole(elm) { |
|
| 2817 | elm = elm || focusedElement; |
|
| 2818 | if (isElement(elm)) { |
|
| 2819 | return elm.getAttribute('role'); |
|
| 2820 | } |
|
| 2821 | return null; |
|
| 2822 | } |
|
| 2823 | function getParentRole(elm) { |
|
| 2824 | var role, parent$$1 = elm || focusedElement; |
|
| 2825 | while (parent$$1 = parent$$1.parentNode) { |
|
| 2826 | if (role = getRole(parent$$1)) { |
|
| 2827 | return role; |
|
| 2828 | } |
|
| 2829 | } |
|
| 2830 | } |
|
| 2831 | function getAriaProp(name$$1) { |
|
| 2832 | var elm = focusedElement; |
|
| 2833 | if (isElement(elm)) { |
|
| 2834 | return elm.getAttribute('aria-' + name$$1); |
|
| 2835 | } |
|
| 2836 | } |
|
| 2837 | function isTextInputElement(elm) { |
|
| 2838 | var tagName = elm.tagName.toUpperCase(); |
|
| 2839 | return tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT'; |
|
| 2840 | } |
|
| 2841 | function canFocus(elm) { |
|
| 2842 | if (isTextInputElement(elm) && !elm.hidden) { |
|
| 2843 | return true; |
|
| 2844 | } |
|
| 2845 | if (hasTabstopData(elm)) { |
|
| 2846 | return true; |
|
| 2847 | } |
|
| 2848 | if (/^(button|menuitem|checkbox|tab|menuitemcheckbox|option|gridcell|slider)$/.test(getRole(elm))) { |
|
| 2849 | return true; |
|
| 2850 | } |
|
| 2851 | return false; |
|
| 2852 | } |
|
| 2853 | function getFocusElements(elm) { |
|
| 2854 | var elements = []; |
|
| 2855 | function collect(elm) { |
|
| 2856 | if (elm.nodeType !== 1 || elm.style.display === 'none' || elm.disabled) { |
|
| 2857 | return; |
|
| 2858 | } |
|
| 2859 | if (canFocus(elm)) { |
|
| 2860 | elements.push(elm); |
|
| 2861 | } |
|
| 2862 | for (var i = 0; i < elm.childNodes.length; i++) { |
|
| 2863 | collect(elm.childNodes[i]); |
|
| 2864 | } |
|
| 2865 | } |
|
| 2866 | collect(elm || root.getEl()); |
|
| 2867 | return elements; |
|
| 2868 | } |
|
| 2869 | function getNavigationRoot(targetControl) { |
|
| 2870 | var navigationRoot, controls; |
|
| 2871 | targetControl = targetControl || focusedControl; |
|
| 2872 | controls = targetControl.parents().toArray(); |
|
| 2873 | controls.unshift(targetControl); |
|
| 2874 | for (var i = 0; i < controls.length; i++) { |
|
| 2875 | navigationRoot = controls[i]; |
|
| 2876 | if (navigationRoot.settings.ariaRoot) { |
|
| 2877 | break; |
|
| 2878 | } |
|
| 2879 | } |
|
| 2880 | return navigationRoot; |
|
| 2881 | } |
|
| 2882 | function focusFirst(targetControl) { |
|
| 2883 | var navigationRoot = getNavigationRoot(targetControl); |
|
| 2884 | var focusElements = getFocusElements(navigationRoot.getEl()); |
|
| 2885 | if (navigationRoot.settings.ariaRemember && 'lastAriaIndex' in navigationRoot) { |
|
| 2886 | moveFocusToIndex(navigationRoot.lastAriaIndex, focusElements); |
|
| 2887 | } else { |
|
| 2888 | moveFocusToIndex(0, focusElements); |
|
| 2889 | } |
|
| 2890 | } |
|
| 2891 | function moveFocusToIndex(idx, elements) { |
|
| 2892 | if (idx < 0) { |
|
| 2893 | idx = elements.length - 1; |
|
| 2894 | } else if (idx >= elements.length) { |
|
| 2895 | idx = 0; |
|
| 2896 | } |
|
| 2897 | if (elements[idx]) { |
|
| 2898 | elements[idx].focus(); |
|
| 2899 | } |
|
| 2900 | return idx; |
|
| 2901 | } |
|
| 2902 | function moveFocus(dir, elements) { |
|
| 2903 | var idx = -1; |
|
| 2904 | var navigationRoot = getNavigationRoot(); |
|
| 2905 | elements = elements || getFocusElements(navigationRoot.getEl()); |
|
| 2906 | for (var i = 0; i < elements.length; i++) { |
|
| 2907 | if (elements[i] === focusedElement) { |
|
| 2908 | idx = i; |
|
| 2909 | } |
|
| 2910 | } |
|
| 2911 | idx += dir; |
|
| 2912 | navigationRoot.lastAriaIndex = moveFocusToIndex(idx, elements); |
|
| 2913 | } |
|
| 2914 | function left() { |
|
| 2915 | var parentRole = getParentRole(); |
|
| 2916 | if (parentRole === 'tablist') { |
|
| 2917 | moveFocus(-1, getFocusElements(focusedElement.parentNode)); |
|
| 2918 | } else if (focusedControl.parent().submenu) { |
|
| 2919 | cancel(); |
|
| 2920 | } else { |
|
| 2921 | moveFocus(-1); |
|
| 2922 | } |
|
| 2923 | } |
|
| 2924 | function right() { |
|
| 2925 | var role = getRole(), parentRole = getParentRole(); |
|
| 2926 | if (parentRole === 'tablist') { |
|
| 2927 | moveFocus(1, getFocusElements(focusedElement.parentNode)); |
|
| 2928 | } else if (role === 'menuitem' && parentRole === 'menu' && getAriaProp('haspopup')) { |
|
| 2929 | enter(); |
|
| 2930 | } else { |
|
| 2931 | moveFocus(1); |
|
| 2932 | } |
|
| 2933 | } |
|
| 2934 | function up() { |
|
| 2935 | moveFocus(-1); |
|
| 2936 | } |
|
| 2937 | function down() { |
|
| 2938 | var role = getRole(), parentRole = getParentRole(); |
|
| 2939 | if (role === 'menuitem' && parentRole === 'menubar') { |
|
| 2940 | enter(); |
|
| 2941 | } else if (role === 'button' && getAriaProp('haspopup')) { |
|
| 2942 | enter({ key: 'down' }); |
|
| 2943 | } else { |
|
| 2944 | moveFocus(1); |
|
| 2945 | } |
|
| 2946 | } |
|
| 2947 | function tab(e) { |
|
| 2948 | var parentRole = getParentRole(); |
|
| 2949 | if (parentRole === 'tablist') { |
|
| 2950 | var elm = getFocusElements(focusedControl.getEl('body'))[0]; |
|
| 2951 | if (elm) { |
|
| 2952 | elm.focus(); |
|
| 2953 | } |
|
| 2954 | } else { |
|
| 2955 | moveFocus(e.shiftKey ? -1 : 1); |
|
| 2956 | } |
|
| 2957 | } |
|
| 2958 | function cancel() { |
|
| 2959 | focusedControl.fire('cancel'); |
|
| 2960 | } |
|
| 2961 | function enter(aria) { |
|
| 2962 | aria = aria || {}; |
|
| 2963 | focusedControl.fire('click', { |
|
| 2964 | target: focusedElement, |
|
| 2965 | aria: aria |
|
| 2966 | }); |
|
| 2967 | } |
|
| 2968 | root.on('keydown', function (e) { |
|
| 2969 | function handleNonTabOrEscEvent(e, handler) { |
|
| 2970 | if (isTextInputElement(focusedElement) || hasTabstopData(focusedElement)) { |
|
| 2971 | return; |
|
| 2972 | } |
|
| 2973 | if (getRole(focusedElement) === 'slider') { |
|
| 2974 | return; |
|
| 2975 | } |
|
| 2976 | if (handler(e) !== false) { |
|
| 2977 | e.preventDefault(); |
|
| 2978 | } |
|
| 2979 | } |
|
| 2980 | if (e.isDefaultPrevented()) { |
|
| 2981 | return; |
|
| 2982 | } |
|
| 2983 | switch (e.keyCode) { |
|
| 2984 | case 37: |
|
| 2985 | handleNonTabOrEscEvent(e, left); |
|
| 2986 | break; |
|
| 2987 | case 39: |
|
| 2988 | handleNonTabOrEscEvent(e, right); |
|
| 2989 | break; |
|
| 2990 | case 38: |
|
| 2991 | handleNonTabOrEscEvent(e, up); |
|
| 2992 | break; |
|
| 2993 | case 40: |
|
| 2994 | handleNonTabOrEscEvent(e, down); |
|
| 2995 | break; |
|
| 2996 | case 27: |
|
| 2997 | cancel(); |
|
| 2998 | break; |
|
| 2999 | case 14: |
|
| 3000 | case 13: |
|
| 3001 | case 32: |
|
| 3002 | handleNonTabOrEscEvent(e, enter); |
|
| 3003 | break; |
|
| 3004 | case 9: |
|
| 3005 | tab(e); |
|
| 3006 | e.preventDefault(); |
|
| 3007 | break; |
|
| 3008 | } |
|
| 3009 | }); |
|
| 3010 | root.on('focusin', function (e) { |
|
| 3011 | focusedElement = e.target; |
|
| 3012 | focusedControl = e.control; |
|
| 3013 | }); |
|
| 3014 | return { focusFirst: focusFirst }; |
|
| 3015 | } |
|
| 3016 | ||
| 3017 | var selectorCache = {}; |
|
| 3018 | var Container = Control$1.extend({ |
|