107 lines
3.6 KiB
JavaScript
107 lines
3.6 KiB
JavaScript
H5P.JoubelTip = (function ($) {
|
|
var $conv = $('<div/>');
|
|
|
|
/**
|
|
* Creates a new tip element.
|
|
*
|
|
* NOTE that this may look like a class but it doesn't behave like one.
|
|
* It returns a jQuery object.
|
|
*
|
|
* @param {string} tipHtml The text to display in the popup
|
|
* @param {Object} [behaviour] Options
|
|
* @param {string} [behaviour.tipLabel] Set to use a custom label for the tip button (you want this for good A11Y)
|
|
* @param {boolean} [behaviour.helpIcon] Set to 'true' to Add help-icon classname to Tip button (changes the icon)
|
|
* @param {boolean} [behaviour.showSpeechBubble] Set to 'false' to disable functionality (you may this in the editor)
|
|
* @param {boolean} [behaviour.tabcontrol] Set to 'true' if you plan on controlling the tabindex in the parent (tabindex="-1")
|
|
* @return {H5P.jQuery|undefined} Tip button jQuery element or 'undefined' if invalid tip
|
|
*/
|
|
function JoubelTip(tipHtml, behaviour) {
|
|
|
|
// Keep track of the popup that appears when you click the Tip button
|
|
var speechBubble;
|
|
|
|
// Parse tip html to determine text
|
|
var tipText = $conv.html(tipHtml).text().trim();
|
|
if (tipText === '') {
|
|
return; // The tip has no textual content, i.e. it's invalid.
|
|
}
|
|
|
|
// Set default behaviour
|
|
behaviour = $.extend({
|
|
tipLabel: tipText,
|
|
helpIcon: false,
|
|
showSpeechBubble: true,
|
|
tabcontrol: false
|
|
}, behaviour);
|
|
|
|
// Create Tip button
|
|
var $tipButton = $('<div/>', {
|
|
class: 'joubel-tip-container' + (behaviour.showSpeechBubble ? '' : ' be-quiet'),
|
|
title: behaviour.tipLabel,
|
|
'aria-label': behaviour.tipLabel,
|
|
'aria-expanded': false,
|
|
role: 'button',
|
|
tabindex: (behaviour.tabcontrol ? -1 : 0),
|
|
click: function (event) {
|
|
// Toggle show/hide popup
|
|
toggleSpeechBubble();
|
|
event.preventDefault();
|
|
},
|
|
keydown: function (event) {
|
|
if (event.which === 32 || event.which === 13) { // Space & enter key
|
|
// Toggle show/hide popup
|
|
toggleSpeechBubble();
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
}
|
|
else { // Any other key
|
|
// Toggle hide popup
|
|
toggleSpeechBubble(false);
|
|
}
|
|
},
|
|
// Add markup to render icon
|
|
html: '<span class="joubel-icon-tip-normal ' + (behaviour.helpIcon ? ' help-icon': '') + '">' +
|
|
'<span class="h5p-icon-shadow"></span>' +
|
|
'<span class="h5p-icon-speech-bubble"></span>' +
|
|
'<span class="h5p-icon-info"></span>' +
|
|
'</span>'
|
|
// IMPORTANT: All of the markup elements must have 'pointer-events: none;'
|
|
});
|
|
|
|
const $tipAnnouncer = $('<div>', {
|
|
'class': 'hidden-but-read',
|
|
'aria-live': 'polite',
|
|
appendTo: $tipButton,
|
|
});
|
|
|
|
/**
|
|
* Tip button interaction handler.
|
|
* Toggle show or hide the speech bubble popup when interacting with the
|
|
* Tip button.
|
|
*
|
|
* @private
|
|
* @param {boolean} [force] 'true' shows and 'false' hides.
|
|
*/
|
|
var toggleSpeechBubble = function (force) {
|
|
if (speechBubble !== undefined && speechBubble.isCurrent($tipButton)) {
|
|
// Hide current popup
|
|
speechBubble.remove();
|
|
speechBubble = undefined;
|
|
|
|
$tipButton.attr('aria-expanded', false);
|
|
$tipAnnouncer.html('');
|
|
}
|
|
else if (force !== false && behaviour.showSpeechBubble) {
|
|
// Create and show new popup
|
|
speechBubble = H5P.JoubelSpeechBubble($tipButton, tipHtml);
|
|
$tipButton.attr('aria-expanded', true);
|
|
$tipAnnouncer.html(tipHtml);
|
|
}
|
|
};
|
|
|
|
return $tipButton;
|
|
}
|
|
|
|
return JoubelTip;
|
|
})(H5P.jQuery);
|