mirror of
https://github.com/moodle/moodle.git
synced 2025-01-31 12:45:04 +01:00
MDL-72456 theme_boost: add tooltips to drawers
This commit is contained in:
parent
73cfbea3ee
commit
844681f54f
2
theme/boost/amd/build/drawers.min.js
vendored
2
theme/boost/amd/build/drawers.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -25,11 +25,23 @@ import Templates from 'core/templates';
|
||||
import * as Aria from 'core/aria';
|
||||
import {dispatchEvent} from 'core/event_dispatcher';
|
||||
import {debounce} from 'core/utils';
|
||||
import Pending from 'core/pending';
|
||||
// The jQuery module is only used for interacting with Boostrap 4. It can we removed when MDL-71979 is integrated.
|
||||
import jQuery from 'jquery';
|
||||
|
||||
let backdropPromise = null;
|
||||
|
||||
const drawerMap = new Map();
|
||||
|
||||
const SELECTORS = {
|
||||
BUTTONS: '[data-toggler="drawers"]',
|
||||
CLOSEBTN: '[data-toggler="drawers"][data-action="closedrawer"]',
|
||||
OPENBTN: '[data-toggler="drawers"][data-action="opendrawer"]',
|
||||
TOGGLEBTN: '[data-toggler="drawers"][data-action="toggle"]',
|
||||
DRAWERS: '[data-region="fixed-drawer"]',
|
||||
CONTAINER: '#page.drawers',
|
||||
};
|
||||
|
||||
/**
|
||||
* Maximum sizes for breakpoints. This needs to correspond with Bootstrap
|
||||
* Breakpoints
|
||||
@ -96,6 +108,71 @@ const getBackdrop = () => {
|
||||
return backdropPromise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the button element to open a specific drawer.
|
||||
*
|
||||
* @param {String} drawerId the drawer element Id
|
||||
* @return {HTMLElement|undefined} the open button element
|
||||
* @private
|
||||
*/
|
||||
const getDrawerOpenButton = (drawerId) => {
|
||||
let openButton = document.querySelector(`${SELECTORS.OPENBTN}[data-target="${drawerId}"]`);
|
||||
if (!openButton) {
|
||||
openButton = document.querySelector(`${SELECTORS.TOGGLEBTN}[data-target="${drawerId}"]`);
|
||||
}
|
||||
return openButton;
|
||||
};
|
||||
|
||||
/**
|
||||
* Disable drawer tooltips.
|
||||
*
|
||||
* @param {HTMLElement} drawerNode the drawer main node
|
||||
* @private
|
||||
*/
|
||||
const disableDrawerTooltips = (drawerNode) => {
|
||||
const buttons = [
|
||||
drawerNode.querySelector(SELECTORS.CLOSEBTN),
|
||||
getDrawerOpenButton(drawerNode.id),
|
||||
];
|
||||
buttons.forEach(button => {
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
if (button.hasAttribute('data-original-title')) {
|
||||
// The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.
|
||||
jQuery(button).tooltip('disable');
|
||||
} else {
|
||||
button.dataset.disabledToggle = button.dataset.toggle;
|
||||
button.removeAttribute('data-toggle');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Enable drawer tooltips.
|
||||
*
|
||||
* @param {HTMLElement} drawerNode the drawer main node
|
||||
* @private
|
||||
*/
|
||||
const enableDrawerTooltips = (drawerNode) => {
|
||||
const buttons = [
|
||||
drawerNode.querySelector(SELECTORS.CLOSEBTN),
|
||||
getDrawerOpenButton(drawerNode.id),
|
||||
];
|
||||
buttons.forEach(button => {
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
// The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.
|
||||
if (button.hasAttribute('data-original-title')) {
|
||||
jQuery(button).tooltip('enable');
|
||||
} else if (button.dataset.disabledToggle) {
|
||||
button.dataset.toggle = button.dataset.disabledToggle;
|
||||
jQuery(button).tooltip();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* The Drawers class is used to control on-screen drawer elements.
|
||||
*
|
||||
@ -164,6 +241,11 @@ export default class Drawers {
|
||||
Aria.hide(this.drawerNode);
|
||||
}
|
||||
|
||||
// Disable tooltips in small screens.
|
||||
if (isSmall()) {
|
||||
disableDrawerTooltips(this.drawerNode);
|
||||
}
|
||||
|
||||
drawerMap.set(drawerNode, this);
|
||||
}
|
||||
|
||||
@ -278,11 +360,23 @@ export default class Drawers {
|
||||
* @param {boolean} [args.focusOnCloseButton=true] Whether to alter page focus when opening the drawer
|
||||
*/
|
||||
openDrawer({focusOnCloseButton = true} = {}) {
|
||||
|
||||
const pendingPromise = new Pending('theme_boost/drawers:open');
|
||||
const showEvent = this.dispatchEvent(Drawers.eventTypes.drawerShow, true);
|
||||
if (showEvent.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide close button while the drawer is showing to prevent glitchy effects.
|
||||
this.drawerNode.querySelector(SELECTORS.CLOSEBTN)?.classList.toggle('hidden', true);
|
||||
|
||||
// Remove open tooltip if still visible.
|
||||
let openButton = getDrawerOpenButton(this.drawerNode.id);
|
||||
if (openButton && openButton.hasAttribute('data-original-title')) {
|
||||
// The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.
|
||||
jQuery(openButton)?.tooltip('hide');
|
||||
}
|
||||
|
||||
Aria.unhide(this.drawerNode);
|
||||
this.drawerNode.classList.add('show');
|
||||
|
||||
@ -308,10 +402,15 @@ export default class Drawers {
|
||||
.catch();
|
||||
}
|
||||
|
||||
if (focusOnCloseButton) {
|
||||
const closeButton = this.drawerNode.querySelector('[data-toggle="drawers"][data-action="closedrawer"]');
|
||||
closeButton.focus();
|
||||
}
|
||||
// Show close button once the drawer is fully opened.
|
||||
setTimeout(() => {
|
||||
const closeButton = this.drawerNode.querySelector(SELECTORS.CLOSEBTN);
|
||||
closeButton.classList.toggle('hidden', false);
|
||||
if (focusOnCloseButton) {
|
||||
closeButton.focus();
|
||||
}
|
||||
pendingPromise.resolve();
|
||||
}, 300);
|
||||
|
||||
this.dispatchEvent(Drawers.eventTypes.drawerShown);
|
||||
}
|
||||
@ -320,11 +419,23 @@ export default class Drawers {
|
||||
* Close the drawer.
|
||||
*/
|
||||
closeDrawer() {
|
||||
|
||||
const pendingPromise = new Pending('theme_boost/drawers:close');
|
||||
|
||||
const hideEvent = this.dispatchEvent(Drawers.eventTypes.drawerHide, true);
|
||||
if (hideEvent.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide close button while the drawer is hiding to prevent glitchy effects.
|
||||
const closeButton = this.drawerNode.querySelector(SELECTORS.CLOSEBTN);
|
||||
closeButton?.classList.toggle('hidden', true);
|
||||
// Remove the close button tooltip if visible.
|
||||
if (closeButton.hasAttribute('data-original-title')) {
|
||||
// The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.
|
||||
jQuery(closeButton)?.tooltip('hide');
|
||||
}
|
||||
|
||||
const preference = this.drawerNode.dataset.preference;
|
||||
if (preference) {
|
||||
M.util.set_user_preference(preference, false);
|
||||
@ -350,6 +461,15 @@ export default class Drawers {
|
||||
})
|
||||
.catch();
|
||||
|
||||
// Move focus to the open drawer (or toggler) button once the drawer is hidden.
|
||||
setTimeout(() => {
|
||||
let openButton = getDrawerOpenButton(this.drawerNode.id);
|
||||
if (openButton) {
|
||||
openButton.focus();
|
||||
}
|
||||
pendingPromise.resolve();
|
||||
}, 300);
|
||||
|
||||
this.dispatchEvent(Drawers.eventTypes.drawerHidden);
|
||||
}
|
||||
|
||||
@ -396,7 +516,7 @@ export default class Drawers {
|
||||
*/
|
||||
const scroller = () => {
|
||||
const body = document.querySelector('body');
|
||||
const drawerLayout = document.querySelector('#page.drawers');
|
||||
const drawerLayout = document.querySelector(SELECTORS.CONTAINER);
|
||||
if (drawerLayout) {
|
||||
drawerLayout.addEventListener("scroll", () => {
|
||||
if (drawerLayout.scrollTop >= window.innerHeight) {
|
||||
@ -415,7 +535,7 @@ const scroller = () => {
|
||||
*/
|
||||
const setLastUsedToggle = (toggleButton) => {
|
||||
if (toggleButton.dataset.target) {
|
||||
document.querySelectorAll('[data-toggle="drawers"][data-target="' + toggleButton.dataset.target + '"]')
|
||||
document.querySelectorAll(`${SELECTORS.BUTTONS}[data-target="${toggleButton.dataset.target}"]`)
|
||||
.forEach(btn => {
|
||||
btn.dataset.lastused = false;
|
||||
});
|
||||
@ -428,7 +548,7 @@ const setLastUsedToggle = (toggleButton) => {
|
||||
* @param {string} target The drawer target.
|
||||
*/
|
||||
const focusLastUsedToggle = (target) => {
|
||||
const lastUsedButton = document.querySelector('[data-toggle="drawers"][data-target="' + target + '"][data-lastused="true"');
|
||||
const lastUsedButton = document.querySelector(`${SELECTORS.BUTTONS}[data-target="${target}"][data-lastused="true"`);
|
||||
if (lastUsedButton) {
|
||||
lastUsedButton.focus();
|
||||
}
|
||||
@ -442,7 +562,7 @@ const focusLastUsedToggle = (target) => {
|
||||
const registerListeners = () => {
|
||||
// Listen for show/hide events.
|
||||
document.addEventListener('click', e => {
|
||||
const toggleButton = e.target.closest('[data-toggle="drawers"][data-action="toggle"]');
|
||||
const toggleButton = e.target.closest(SELECTORS.TOGGLEBTN);
|
||||
if (toggleButton && toggleButton.dataset.target) {
|
||||
e.preventDefault();
|
||||
const targetDrawer = document.getElementById(toggleButton.dataset.target);
|
||||
@ -452,7 +572,7 @@ const registerListeners = () => {
|
||||
drawerInstance.toggleVisibility();
|
||||
}
|
||||
|
||||
const openDrawerButton = e.target.closest('[data-toggle="drawers"][data-action="opendrawer"]');
|
||||
const openDrawerButton = e.target.closest(SELECTORS.OPENBTN);
|
||||
if (openDrawerButton && openDrawerButton.dataset.target) {
|
||||
e.preventDefault();
|
||||
const targetDrawer = document.getElementById(openDrawerButton.dataset.target);
|
||||
@ -462,7 +582,7 @@ const registerListeners = () => {
|
||||
drawerInstance.openDrawer();
|
||||
}
|
||||
|
||||
const closeDrawerButton = e.target.closest('[data-toggle="drawers"][data-action="closedrawer"]');
|
||||
const closeDrawerButton = e.target.closest(SELECTORS.CLOSEBTN);
|
||||
if (closeDrawerButton && closeDrawerButton.dataset.target) {
|
||||
e.preventDefault();
|
||||
const targetDrawer = document.getElementById(closeDrawerButton.dataset.target);
|
||||
@ -485,6 +605,7 @@ const registerListeners = () => {
|
||||
if (isSmall()) {
|
||||
let anyOpen = false;
|
||||
drawerMap.forEach(drawerInstance => {
|
||||
disableDrawerTooltips(drawerInstance.drawerNode);
|
||||
if (drawerInstance.isOpen) {
|
||||
if (drawerInstance.closeOnResize) {
|
||||
drawerInstance.closeDrawer();
|
||||
@ -498,6 +619,9 @@ const registerListeners = () => {
|
||||
getBackdrop().then(backdrop => backdrop.show()).catch();
|
||||
}
|
||||
} else {
|
||||
drawerMap.forEach(drawerInstance => {
|
||||
enableDrawerTooltips(drawerInstance.drawerNode);
|
||||
});
|
||||
getBackdrop().then(backdrop => backdrop.hide()).catch();
|
||||
}
|
||||
};
|
||||
@ -508,5 +632,5 @@ const registerListeners = () => {
|
||||
scroller();
|
||||
registerListeners();
|
||||
|
||||
const drawers = document.querySelectorAll('[data-region="fixed-drawer"]');
|
||||
const drawers = document.querySelectorAll(SELECTORS.DRAWERS);
|
||||
drawers.forEach(drawerNode => Drawers.getDrawerInstanceForNode(drawerNode));
|
||||
|
@ -21,7 +21,7 @@
|
||||
{
|
||||
"drawerclasses": "drawer drawer-right",
|
||||
"drawertrigger": "toggleblocks",
|
||||
"drawerheading": "Blocks",
|
||||
"tooltipplacement": "right",
|
||||
"drawerconent": "Content for the blocks region"
|
||||
}
|
||||
}}
|
||||
@ -35,7 +35,15 @@
|
||||
}} data-close-on-resize="{{$drawercloseonresize}}0{{/drawercloseonresize}}"{{!
|
||||
}}>
|
||||
<div class="drawerheader">
|
||||
<button class="btn drawertoggle icon-no-margin" data-toggle="drawers" data-action="closedrawer" data-target="{{$id}}{{/id}}">
|
||||
<button
|
||||
class="btn drawertoggle icon-no-margin hidden"
|
||||
data-toggler="drawers"
|
||||
data-action="closedrawer"
|
||||
data-target="{{$id}}{{/id}}"
|
||||
data-toggle="tooltip"
|
||||
data-placement="{{$tooltipplacement}}right{{/tooltipplacement}}"
|
||||
title="{{#str}}closedrawer, core{{/str}}"
|
||||
>
|
||||
{{#pix}}e/cancel, core, {{#str}}closedrawer, core{{/str}}{{/pix}}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -62,23 +62,18 @@
|
||||
{{< theme_boost/drawer }}
|
||||
{{$id}}theme_boost-drawers-courseindex{{/id}}
|
||||
{{$drawerclasses}}drawer drawer-left {{#courseindexopen}}show{{/courseindexopen}}{{/drawerclasses}}
|
||||
{{$drawerheading}}
|
||||
{{#str}}courseindex, core_courseformat{{/str}}
|
||||
{{/drawerheading}}
|
||||
{{$drawercontent}}
|
||||
{{{courseindex}}}
|
||||
{{/drawercontent}}
|
||||
{{$drawerpreferencename}}drawer-open-index{{/drawerpreferencename}}
|
||||
{{$drawerstate}}show-drawer-left{{/drawerstate}}
|
||||
{{$tooltipplacement}}right{{/tooltipplacement}}
|
||||
{{/ theme_boost/drawer}}
|
||||
{{/courseindex}}
|
||||
{{#hasblocks}}
|
||||
{{< theme_boost/drawer }}
|
||||
{{$id}}theme_boost-drawers-blocks{{/id}}
|
||||
{{$drawerclasses}}drawer drawer-right{{#blockdraweropen}} show{{/blockdraweropen}}{{/drawerclasses}}
|
||||
{{$drawerheading}}
|
||||
{{#str}} blocks {{/str}}
|
||||
{{/drawerheading}}
|
||||
{{$drawercontent}}
|
||||
<section class="d-print-none" aria-label="{{#str}}blocks{{/str}}">
|
||||
{{{ sidepreblocks }}}
|
||||
@ -87,6 +82,7 @@
|
||||
{{$drawerpreferencename}}drawer-open-block{{/drawerpreferencename}}
|
||||
{{$forceopen}}{{#forceblockdraweropen}}1{{/forceblockdraweropen}}{{/forceopen}}
|
||||
{{$drawerstate}}show-drawer-right{{/drawerstate}}
|
||||
{{$tooltipplacement}}left{{/tooltipplacement}}
|
||||
{{$drawercloseonresize}}1{{/drawercloseonresize}}
|
||||
{{/ theme_boost/drawer}}
|
||||
{{/hasblocks}}
|
||||
@ -97,9 +93,12 @@
|
||||
<div class="drawer-toggler drawer-left-toggle open-nav">
|
||||
<button
|
||||
class="shadow-sm btn icon-no-margin"
|
||||
data-toggle="drawers"
|
||||
data-toggler="drawers"
|
||||
data-action="toggle"
|
||||
data-target="theme_boost-drawers-courseindex"
|
||||
data-toggle="tooltip"
|
||||
data-placement="right"
|
||||
title="{{#str}}opendrawerindex, core{{/str}}"
|
||||
>
|
||||
<span class="sr-only">{{#str}}opendrawerindex, core{{/str}}</span>
|
||||
{{#pix}} t/index_drawer, moodle {{/pix}}
|
||||
@ -110,9 +109,12 @@
|
||||
<div class="drawer-toggler drawer-right-toggle ml-auto">
|
||||
<button
|
||||
class="shadow-sm btn icon-no-margin"
|
||||
data-toggle="drawers"
|
||||
data-toggler="drawers"
|
||||
data-action="toggle"
|
||||
data-target="theme_boost-drawers-blocks"
|
||||
data-toggle="tooltip"
|
||||
data-placement="right"
|
||||
title="{{#str}}opendrawerblocks, core{{/str}}"
|
||||
>
|
||||
<span class="sr-only">{{#str}}opendrawerblocks, core{{/str}}</span>
|
||||
{{#pix}}t/blocks_drawer, core, {{#str}}opendrawerblocks, core{{/str}}{{/pix}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user