gocodebox/lifterlms

View on GitHub
assets/js/llms-notifications.js

Summary

Maintainability
B
4 hrs
Test Coverage
;/**
 * LifterLMS Basic Notifications Displayer
 *
 * @since    3.8.0
 * @version  3.22.0
 */( function( $ ) {

    var llms_notifications = function() {

        var self          = this,
            notifications = [];

        /**
         * Bind dom events
         *
         * @return   void
         * @since    3.8.0
         * @version  3.8.0
         */
        function bind_events() {
            $( 'body' ).on( 'click', '.llms-notification-dismiss', function() {
                self.dismiss( $( this ).closest( '.llms-notification' ) );
            } );
        };

        /**
         * Initialize
         *
         * @return   void
         * @since    3.8.0
         * @version  3.22.0
         */
        this.init = function() {

            var self = this;

            if ( ! this.is_user_logged_in() ) {
                return;
            }

            if ( window.llms.queued_notifications ) {
                self.queue( window.llms.queued_notifications );
                self.show_all();
            }

            bind_events();

        };

        /**
         * Queue notifications to be displayed
         *
         * @param    object   new_notis  array of notifications
         * @return   void
         * @since    3.8.0
         * @version  3.8.0
         */
        this.queue = function( new_notis ) {

            var self = this;

            for ( var n in new_notis ) {

                if ( ! new_notis.hasOwnProperty( n ) ) {
                    continue;
                }

                // add the new notification if it doesnt exist
                if ( false === self.notification_exists( new_notis[ n ].id ) ) {

                    notifications.push( new_notis[ n ] );

                }

            }

        };

        /**
         * Dismiss a notification
         *
         * @param    obj   $el  notification dom element
         * @return   void
         * @since    3.8.0
         * @version  3.22.0
         */
        this.dismiss = function( $el ) {
            var self = this;
            $el.removeClass( 'visible' );
            setTimeout( function() {
                self.reposition( $el.next( '.llms-notification.visible' ) );
            }, 10 );
        };

        /**
         * Determine if a notification already exists in the notifications array
         *
         * @param    int        id  notification id
         * @return   int|false      index of the notification in the array OR false if not found
         * @since    3.8.0
         * @version  3.8.0
         */
        this.notification_exists = function( id ) {

            for ( var noti in notifications ) {

                if ( ! notifications.hasOwnProperty( noti ) ) {
                    continue;
                }

                if ( id === notifications[ noti ].id ) {
                    return noti;
                }

            }

            return false;

        };

        /**
         * Get the vertical offset (on screen) relative to an element
         * used for notification positioning
         *
         * @param    obj   $relative_el  element to get an offset relative to
         * @return   int
         * @since    3.8.0
         * @version  3.8.0
         */
        this.get_offset = function( $relative_el ) {

            var spacer = 12;

            if ( ! $relative_el ) {
                $relative_el = $( '.llms-notification.visible' ).last()
            }

            if ( ! $relative_el.offset() ) {
                return 24;
            }

            var top    = $relative_el.offset().top,
                height = $relative_el.outerHeight();

            return top + height + spacer;

        };

        /**
         * Determine if there are notifications to show
         *
         * @return   Boolean
         * @since    3.8.0
         * @version  3.8.0
         */
        this.has_notifications = function() {
            return ( notifications.length );
        };

        /**
         * Determine if a user is logged in
         *
         * @return   boolean
         * @since    3.8.0
         * @version  3.8.0
         */
        this.is_user_logged_in = function() {
            return $( 'body' ).hasClass( 'logged-in' );
        };

        /**
         * Reposition elements, starting with the specified element
         *
         * @param    obj   $start_el  element to start repositioning with
         * @return   void
         * @since    3.8.0
         * @version  3.8.0
         */
        this.reposition = function( $start_el ) {

            var self     = this,
                selector = '.llms-notification.visible',
                $next_el;

            if ( ! $start_el.length ) {
                $start_el = $( selector ).first();
            }

            $start_el.css( 'top', self.get_offset( $start_el.prevAll( selector ).first() ) );

            $next_el = $start_el.next( selector );
            if ( $next_el.length ) {
                setTimeout( function() {
                    self.reposition( $next_el );
                }, 150 );
            }

        };

        /**
         * Show all queued notifications
         *
         * @return   void
         * @since    3.8.0
         * @version  3.8.0
         */
        this.show_all = function() {

            var self = this,
                i    = 0,
                interval;

            interval = setInterval( function() {

                if ( i < notifications.length ) {

                    if ( ! notifications[ i ].shown ) {
                        notifications[ i ].shown = true;
                        self.show_one( notifications[ i ] );
                    }
                    i++;

                } else {

                    clearInterval( interval );

                }

            }, 100 );

        }

        /**
         * Show a single notification
         *
         * @param    object   n  notification object data
         * @return   void
         * @since    3.8.0
         * @version  3.22.0
         */
        this.show_one = function( n ) {

            var self  = this,
                $html = $( n.html );

            $html.find( 'a' ).on( 'click', function( e ) {
                e.preventDefault();
                var $this       = $( this );
                window.location = $this.attr( 'href' );
            } );

            $( 'body' ).append( $html );
            $html.css( 'top', self.get_offset() );

            setTimeout( function() {
                $html.addClass( 'visible' );
            }, 1 );

            // if it's auto dismissing, set up a dismissal
            if ( $html.attr( 'data-auto-dismiss' ) ) {
                setTimeout( function() {
                    self.dismiss( $html );
                }, $html.attr( 'data-auto-dismiss' ) );
            }

        }

        // initialize
        this.init();

        return this;

    };

    window.llms               = window.llms || {};
    window.llms.notifications = new llms_notifications();

} )( jQuery );