/**
* @file jQuery plugin that creates the basic interactivity for a button flyout
* @version 0.7.0
* @author Ian McBurnie <ianmcburnie@hotmail.com>
* @requires jquery-next-id
* @requires jquery-common-keydown
* @requires jquery-focusable
* @requires jquery-focus-exit
*/
(function($, window, document, undefined) {
/**
* jQuery plugin that creates the basic interactivity for a button flyout
*
* @method "jQuery.fn.buttonFlyout"
* @param {Object} [options]
* @param {boolean} [options.focusManagement]
* @param {boolean} [options.sticky]
* @fires {object} buttonFlyoutClose - the button flyout has closed
* @fires {object} buttonFlyoutOpen - the button flyout has opened
* @return {jQuery} chainable jQuery class
*/
$.fn.buttonFlyout = function buttonFlyout(options) {
options = $.extend({
focusManagement: false,
sticky: false,
isLiveRegion: false
}, options);
return this.each(function onEach() {
var $this = $(this);
var $button = $this.find('> button, > a[role=button]');
var $overlay = $this.find('> *:last-child');
var isAnchorTag = ($button.prop('tagName').toLowerCase() === 'a');
/**
* Opens the flyout
* @method openButtonFlyout
* @return void
*/
function openButtonFlyout(e) {
if ($button.attr('aria-expanded') === 'false') {
$button.attr('aria-expanded', 'true');
$overlay.attr('aria-hidden', 'false');
if (options.focusManagement === true) {
$overlay.focusable().first().focus();
}
$this.trigger('buttonFlyoutOpen');
}
}
/**
* Closes the flyout
* @method closeButtonFlyout
* @return void
*/
function closeButtonFlyout(e) {
if ($button.attr('aria-expanded') === 'true') {
$button.attr('aria-expanded', 'false');
$overlay.attr('aria-hidden', 'true');
$this.trigger('buttonFlyoutClose');
}
}
// assign next id in sequence if one doesn't already exist
$this.nextId('button-flyout');
if (options.isLiveRegion === true) {
$this.attr('aria-live', 'polite');
}
// sticky flyouts don't close on exit
if (options.sticky === false) {
$overlay.focusExit().on('focusExit', closeButtonFlyout);
$this.focusExit().on('focusExit', closeButtonFlyout);
}
// assign id to overlay and hide element
$overlay
.prop('id', $this.prop('id') + '-overlay')
.attr('aria-hidden', 'true');
// the button controls the overlay's expanded state
$button
.attr('aria-controls', $overlay.prop('id'))
.attr('aria-expanded', 'false');
// the button is a toggle button
$button.on('click', function onButtonClick(e) {
if (isAnchorTag === true) {
e.preventDefault();
}
if ($overlay.attr('aria-hidden') === 'true') {
openButtonFlyout();
} else {
closeButtonFlyout();
}
});
if (isAnchorTag === true) {
$this.commonKeyDown('> button').on('spaceKeyDown', function() {
$button.click();
});
}
// when focus is inside flyout, esc key must close flyout
$this.commonKeyDown('> div').on('escapeKeyDown', function onEscKeyDown(e) {
$button.focus();
});
});
};
}(jQuery, window, document));
/**
* The jQuery plugin namespace.
* @external "jQuery.fn"
* @see {@link http://learn.jquery.com/plugins/|jQuery Plugins}
*/
/**
* buttonFlyoutOpen event
*
* @event buttonFlyoutOpen
* @type {object}
* @property {object} event - event object
*/
/**
* buttonFlyoutClose event
*
* @event buttonFlyoutClose
* @type {object}
* @property {object} event - event object
*/