diff --git a/.gitignore b/.gitignore index 18ff1d0..ade14b9 100755 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store npm-debug.log +node_modules diff --git a/.npm/package/.gitignore b/.npm/package/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/.npm/package/README b/.npm/package/README new file mode 100644 index 0000000..3d49255 --- /dev/null +++ b/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/.npm/package/npm-shrinkwrap.json b/.npm/package/npm-shrinkwrap.json new file mode 100644 index 0000000..44f5481 --- /dev/null +++ b/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,10 @@ +{ + "lockfileVersion": 1, + "dependencies": { + "animate.css": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.0.tgz", + "integrity": "sha512-0aVcfWDeU9ykV6vjn1P67ZSs01jxoUQZCGaYbkk0SIIelIG8kUdLrIkua1+VabHfTtsSivDRMMn0ILPvZum2gw==" + } + } +} diff --git a/bert.js b/bert.js index 289bc00..3fb650c 100755 --- a/bert.js +++ b/bert.js @@ -1,13 +1,27 @@ +import 'animate.css'; + +// Helper function got get a single element with the class name +function getElementByClassName(className) { + const elems = document.getElementsByClassName(className); + return elems.length > 0 ? elems[0] : undefined; +} + class BertAlert { constructor() { - this.styles = [ - 'fixed-top', - 'fixed-bottom', - 'growl-top-left', - 'growl-top-right', - 'growl-bottom-left', - 'growl-bottom-right' - ]; + // lookup animate.css classes from bert styles + this.animation = new Map([ + ['fixed-top', {in: 'fadeInDownBig', out: 'fadeOutUpBig'}], + ['fixed-bottom', {in: 'fadeInUpBig', out: 'fadeOutDownBig'}], + ['growl-top-left', {in: 'fadeInLeftBig', out: 'fadeOutLeftBig'}], + ['growl-top-right', {in: 'fadeInRightBig', out: 'fadeOutRightBig'}], + ['growl-bottom-left', {in: 'fadeInLeftBig', out: 'fadeOutLeftBig'}], + ['growl-bottom-right', {in: 'fadeInRightBig', out: 'fadeOutRightBig'}] + ]); + + this.animClasses = { + in: ['animate__fadeInDownBig', 'animate__fadeInUpBig', 'animate__fadeInLeftBig', 'animate__fadeInRightBig'], + out: ['animate__fadeOutDownBig', 'animate__fadeOutUpBig', 'animate__fadeOutLeftBig', 'animate__fadeOutRightBig'] + }; this.types = [ 'default', @@ -30,10 +44,12 @@ class BertAlert { style: 'fixed-top', type: 'default' }; + + this.clickHandler = () => this.hide(); } alert() { - if ( this.isVisible() ) { + if( this.isVisible() ) { this.hide(); setTimeout( () => { this.handleAlert( arguments ); }, 300 ); } else { @@ -42,19 +58,29 @@ class BertAlert { } isVisible() { - return $( '.bert-alert' ).hasClass( 'show' ); + return getElementByClassName('bert-alert').classList.contains('show'); + } + + getAnimation() { + // always get animation type from the current + // session bert style + const session = Session.get('bertAlert'); + return this.animation.get(session?.style || this.defaults.style); } handleAlert( alert ) { this.registerClickHandler(); this.setBertOnSession( alert ); - requestAnimationFrame(() => this.show()); - this.bertTimer(); + requestAnimationFrame(() => { + this.show(); + this.bertTimer(); + }); } registerClickHandler() { - $( '.bert-alert' ).off( 'click' ); - $( '.bert-alert' ).on( 'click', () => { this.hide(); } ); + const ba = getElementByClassName('bert-alert'); + ba.removeEventListener('click', this.clickHandler); + ba.addEventListener('click', this.clickHandler); } bertTimer() { @@ -64,43 +90,50 @@ class BertAlert { } show() { - $( '.bert-alert' ).addClass( 'show' ).delay( 25 ).queue( () => { - $( '.bert-alert' ).addClass( 'animate' ).dequeue(); + const ba = getElementByClassName('bert-alert'); + const self = this; + const anim = self.getAnimation(); + requestAnimationFrame(() => { + ba.classList.add('show', 'animate__animated', `animate__${anim.in}`); }); } hide() { - $( '.bert-alert' ).removeClass( 'animate' ); + const anim = this.getAnimation(); + const ba = getElementByClassName('bert-alert'); + // by removing all in animation styles, this will self-heal with timing issues + ba.classList.remove( ...this.animClasses.in ); + ba.classList.add( 'animate__animated', `animate__${anim.out}` ); setTimeout( () => { - $( '.bert-alert' ).removeClass( 'show' ); - $( '.bert-icon').remove(); + ba.classList.remove( 'show' ); + // by removing all out animation styles, this will self-heal with timing issues + ba.classList.remove( 'animate__animated', ...this.animClasses.out ); + getElementByClassName('bert-icon')?.remove(); Session.set( 'bertAlert', null ); - }, 300 ); + // flush is required to make sure that the alert helper + // toggles from null to a valid object + Tracker.flush(); + }, 200 ); } setBertOnSession( alert ) { - if ( typeof alert[0] === 'object' ) { - let type = alert[0].type || this.defaults.type; - const icon = alert[0].icon || this.icons[ type ]; - - Session.set( 'bertAlert', { - title: alert[0].title || "", - message: alert[0].message || "", - type: type, - style: alert[0].style || this.defaults.style, - icon: `
` - }); - } else { - let type = alert[1] || this.defaults.type; - const icon = alert[3] || this.icons[ type ]; - - Session.set( 'bertAlert', { - message: alert[0] || "", - type: type, - style: alert[2] || this.defaults.style, - icon: `` - }); - } + // args can come in as an object or ordered arguments + const style = alert[0].style || alert[2] || this.defaults.style; + const title = alert[0].title || ''; + const message = alert[0].message || alert[0] || ''; + const type = alert[0].type || alert[1] || this.defaults.type; + const iconClass = alert[0].icon || alert[3] || this.icons[ type ]; + const icon = ``; + + const baData = { + title, + message, + type, + style, + icon + }; + + Session.set( 'bertAlert', baData); } } diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b6312dd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "bert", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "animate.css": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.0.tgz", + "integrity": "sha512-0aVcfWDeU9ykV6vjn1P67ZSs01jxoUQZCGaYbkk0SIIelIG8kUdLrIkua1+VabHfTtsSivDRMMn0ILPvZum2gw==" + } + } +} diff --git a/package.js b/package.js index 4bd6837..df7a803 100755 --- a/package.js +++ b/package.js @@ -9,10 +9,17 @@ Package.describe({ Package.onUse(function (api) { api.versionsFrom("1.2.0.2"); - api.use( - ["ecmascript", "templating", "session", "jquery", "fourseven:scss@4.12.0"], - "client" - ); + Npm.depends({ + 'animate.css': '4.1.0', + }); + + api.use([ + 'ecmascript', + 'templating', + 'session', + 'fourseven:scss@4.12.0', + 'tracker' + ], 'client'); api.addFiles( [ diff --git a/package.json b/package.json new file mode 100644 index 0000000..707669c --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "bert", + "version": "1.0.0", + "description": "Bert is a client side, multi-style alerts system for Meteor.", + "main": "bert.js", + "directories": { + "test": "tests" + }, + "dependencies": { + "animate.css": "^4.1.0" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/brucejo75/bert.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/brucejo75/bert/issues" + }, + "homepage": "https://github.com/brucejo75/bert#readme" +} diff --git a/stylesheets/bert.scss b/stylesheets/bert.scss index 1330198..3986fba 100755 --- a/stylesheets/bert.scss +++ b/stylesheets/bert.scss @@ -103,25 +103,13 @@ $transition: cubic-bezier( 0.500, -0, 0.275, 1.110 ); } .bert-alert.fixed-top { - top: -100%; + top: 0px; padding-top: 20px; - -webkit-transition: top .8s $transition; - - &.animate { - padding-top: 20px; - top: -6px; - } } .bert-alert.fixed-bottom { - bottom: -100%; + bottom: 0px; padding-bottom: 20px; - -webkit-transition: bottom .8s $transition; - - &.animate { - padding-bottom: 20px; - bottom: -6px; - } } .bert-alert[class*="growl-"] { @@ -143,14 +131,9 @@ $transition: cubic-bezier( 0.500, -0, 0.275, 1.110 ); .bert-alert.growl-top-left, .bert-alert.growl-bottom-left { - left: -100%; + left: 0px; right: auto; width: calc( 100% - 30px ); - -webkit-transition: left .8s $transition; - - &.animate { - left: 15px; - } } .bert-alert.growl-top-left, @@ -165,14 +148,9 @@ $transition: cubic-bezier( 0.500, -0, 0.275, 1.110 ); .bert-alert.growl-top-right, .bert-alert.growl-bottom-right { - right: -100%; + right: 0px; left: auto; width: calc( 100% - 30px ); - -webkit-transition: right .8s $transition; - - &.animate { - right: 15px; - } } @media screen and ( min-width: 350px ) { @@ -182,23 +160,13 @@ $transition: cubic-bezier( 0.500, -0, 0.275, 1.110 ); .bert-alert.growl-top-left, .bert-alert.growl-bottom-left { - left: -100%; + left: 15px; right: auto; - -webkit-transition: left .8s $transition; - - &.animate { - left: 15px; - } } .bert-alert.growl-top-right, .bert-alert.growl-bottom-right { - right: -100%; + right: 15px; left: auto; - -webkit-transition: right .8s $transition; - - &.animate { - right: 15px; - } } }