modules_SnackBar_index.js
import {
consoleError,
getNodes,
setAttributes,
speak,
trigger,
} from '@gravityforms/utils';
export const el = {
closeTrigger: null,
container: null,
target: null,
};
export const state = {
hideTimer: () => {},
hideAnimationTimer: () => {},
};
export const defaults = {
attributes: {},
autoHide: true,
autoHideDelay: 4000,
closeButton: true,
closeTitle: '',
container: '',
ctaLink: '',
ctaTarget: '_self',
ctaText: '',
icon: '',
message: '',
onClose: () => {},
onReveal: () => {},
position: 'bottomleft',
speak: true,
type: 'normal',
wrapperClasses: 'gform-snackbar',
};
export let options = {};
/**
* @function snackBarHtml
* @description Uses our options to render the snackbar.
*
* @return {string} The html for the snackbar.
*/
export const snackBarHtml = () => ( `
<article
class="${ options.wrapperClasses } gform-snackbar--${ options.position } gform-snackbar--${ options.type }${ options.closeButton ? ` gform-snackbar--has-close` : `` }"
data-js="gform-snackbar"
>
${ options.icon ? `<span class="gform-snackbar__icon gform-icon gform-icon--${ options.icon }"></span>` : `` }
${ options.message ? `<span class="gform-snackbar__message">${ options.message }</span>` : `` }
${ options.ctaLink ? `
<a
class="gform-snackbar__cta"
href="${ options.ctaLink }"
target="${ options.ctaTarget }"
${ options.ctaTarget === '_blank' ? `rel="noopener"` : `` }
>
${ options.ctaText }
</a>
` : `` }
${ options.closeButton ? `
<button
class="gform-snackbar__close gform-icon gform-icon--delete"
data-js="gform-snackbar-close"
title="${ options.closeTitle }"
></button>
` : `` }
</article>
` );
/**
* @function cleanUp
* @description Clears timeouts and does all needed garbage cleanup.
*
*/
export const cleanUp = () => {
if ( ! el.container ) {
return;
}
el.target.style.position = '';
el.container.parentNode.removeChild( el.container );
if ( el.closeTrigger ) {
el.closeTrigger.removeEventListener( 'click', close );
}
clearTimeout( state.hideTimer );
clearTimeout( state.hideAnimationTimer );
el.container = null;
el.closeTrigger = null;
el.target = null;
};
/**
* @function close
* @description Animates out the snackbar and then removes it from dom.
*
*/
export const close = () => {
el.container.classList.remove( 'gform-snackbar--reveal' );
state.hideAnimationTimer = setTimeout( () => {
trigger( { event: 'gform/snackbar/close', native: false, data: {
el,
options,
state,
},
} );
cleanUp();
}, 300 );
};
/**
* @function reveal
* @description Reveals the snackbar and if autohide true it starts the hide timer. If speak is true, announces the
* message as well to screenreaders.
*
*/
export const reveal = () => {
trigger( { event: 'gform/snackbar/pre_reveal', native: false, data: {
el,
options,
state,
},
} );
setTimeout( () => {
el.container.classList.add( 'gform-snackbar--reveal' );
if ( options.autoHide ) {
state.hideTimer = setTimeout( () => {
close();
}, options.autoHideDelay );
}
if ( options.speak ) {
speak( options.message );
}
options.onReveal();
}, 20 );
};
/**
* @function render
* @description Renders the snackbar in the passed container option.
*
*/
export const render = () => {
el.target = getNodes( options.container, false, document, true )[ 0 ];
if ( ! el.target ) {
consoleError( `Gform snackBar couldn't find ${ options.container } to instantiate in.` );
}
el.target.style.position = 'relative';
el.target.insertAdjacentHTML( 'beforeend', snackBarHtml() );
el.container = getNodes( 'gform-snackbar', false, el.target )[ 0 ];
el.closeTrigger = getNodes( 'gform-snackbar-close', false, el.target )[ 0 ];
setAttributes( el.container, options.attributes );
};
/**
* @function setOptions
* @description Merges the default options with the passed args.
*
*/
export const setOptions = ( args = {} ) => {
options = Object.assign( {}, defaults, args );
trigger( { event: 'gform/snackbar/pre_init', native: false, data: options } );
};
/**
* @function bindEvents
* @description Bind event handlers
*
*/
const bindEvents = () => {
if ( el.closeTrigger ) {
el.closeTrigger.addEventListener( 'click', close );
}
};
/**
* @function init
* @description Initialize and execute a snackbar.
*
*/
const init = ( args ) => {
cleanUp();
setOptions( args );
render();
reveal();
bindEvents();
};
export default init;