(function() {
    var App = new function() {

        // IE mode
        var isRTL = false;
        var isIE8 = false;
        var isIE9 = false;
        var isIE10 = false;

        var log = true;

        var resizeHandlers = [];
        var events = [];

        var assetsPath = '/assets/';

        var globalImgPath = 'global/img/';

        var globalPluginsPath = 'global/plugins/';

        var globalCssPath = 'global/css/';

        var proc = false;

        var loaded = [];

        var config = {
            ws: {
            }
        };

        var ajaxQueue = true;
        var ajaxRequests = [];
        var ajaxStall = null;
        var ajaxQueueTO;

        // theme layout color set

        var brandColors = {
            'blue': '#89C4F4',
            'red': '#F3565D',
            'green': '#1bbc9b',
            'purple': '#9b59b6',
            'grey': '#95a5a6',
            'yellow': '#F8CB00'
        };

        String.prototype.trimToLength = function( m ) {
          return (this.length > m)
            ? jQuery.trim( this ).substring(0, m).split(" ")[0] + "..."
            : this;
        };

        var trigger = function( event, data ) {
            var e = 0,
                res;

            if ( events[ event ] ) {
                for (e; e < events[ event ].length; e++) {
                    res = events[event][e].apply(self, data);
                    if ( res === false ) return;
                }
            } else {
                console.log('No handler for', event);
            }
        };

        var on = function( event, cb ) {
            var e, eve = event.split(/\,/g);

            for (e in eve) {
                if (!events[eve[e]]) events[eve[e]] = [];
                events[eve[e]].push(cb);
            }
        };

        $.fn.followTo = function (elem) {
              var _this = this,
                  _window = $(window),
                  elementHeight = _this.height(),
                  elementPos,
                  anotherElement,
                  anotherElementHeight,
                  anotherElementTop,
                  anotherElementMargin,
                  currentWindowPos,
                  lastPos,
              untilPos,
                  maxMargin;


              var set = function(first){
              if(first) {
                anotherElement = $(elem);
                anotherElementTop = anotherElement.offset().top;
              }

              var _anotherElementHeight = anotherElement.height();

              if(_anotherElementHeight !== anotherElementHeight) {
                anotherElementHeight = _anotherElementHeight;
                anotherElementMargin = (anotherElement.outerHeight(true) - anotherElementHeight);
                untilPos = anotherElementTop + (anotherElementHeight - anotherElementMargin);
                maxMargin = untilPos - (_this.offset().top + elementHeight);
              } else {
                untilPos = anotherElementTop + (anotherElementHeight - anotherElementMargin);
              }
              };

              set(true);

              _window.scroll(function (e) {
                currentWindowPos = _window.scrollTop();

                set();

                elementPos = _this.offset().top + elementHeight;

                if(currentWindowPos <= maxMargin) {
                  margin = currentWindowPos;
                } else {
                  margin = maxMargin;
                }

                _this.stop().animate({
                marginTop: margin + 'px'
                  }, 'fast');
              });
          };


        // initializes main settings
        var handleInit = function() {
            $.fn.extend({
              moveToAnimation: function(newParent, duration) {
                var oldOffset, newOffset, $element, temp, width, height;
                duration = duration || 'slow';

                $element = $(this);
                width = $element.width() * 0.5;
                height = $element.height() * 0.5;

                newParent = $(newParent);
                oldOffset = $element.offset();
                $(this).appendTo(newParent);
                newOffset = $element.offset();

                temp = $element.clone().addClass('moving').appendTo('body');

                temp.css({
                    'position': 'absolute',
                    'left': oldOffset.left + (width / 2),
                    'top': oldOffset.top,
                    'zIndex': 1000,
                    'width': width,
                    'height': height
                });

                $element.hide();

                temp.animate({
                  'top': newOffset.top,
                  'left': newOffset.left
                }, duration, function() {
                    $element.show();
                    temp.remove();
                });
              }
            });

            if ($('body').css('direction') === 'rtl') {
                isRTL = true;
            }

            isIE8 = !!navigator.userAgent.match(/MSIE 8.0/);
            isIE9 = !!navigator.userAgent.match(/MSIE 9.0/);
            isIE10 = !!navigator.userAgent.match(/MSIE 10.0/);

            if (isIE10) {
                $('html').addClass('ie10'); // detect IE10 version
            }

            if (isIE10 || isIE9 || isIE8) {
                $('html').addClass('ie'); // detect IE10 version
            }

            $.ajaxSetup({
                headers: {
                  'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                }
            });
        };

        // runs callback functions set by App.addResponsiveHandler().
        var _runResizeHandlers = function() {
            // reinitialize other subscribed elements
            for (var i = 0; i < resizeHandlers.length; i++) {
                var each = resizeHandlers[i];
                each.call();
            }
        };

        // handle the layout reinitialization on window resize
        var handleOnResize = function() {
            var resize;
            if (isIE8) {
                var currheight;
                $(window).resize(function() {
                    if (currheight == document.documentElement.clientHeight) {
                        return; //quite event since only body resized not window.
                    }
                    if (resize) {
                        clearTimeout(resize);
                    }
                    resize = setTimeout(function() {
                        _runResizeHandlers();
                    }, 50); // wait 50ms until window resize finishes.
                    currheight = document.documentElement.clientHeight; // store last body client height
                });
            } else {
                $(window).resize(function() {
                    if (resize) {
                        clearTimeout(resize);
                    }
                    resize = setTimeout(function() {
                        _runResizeHandlers();
                    }, 50); // wait 50ms until window resize finishes.
                });
            }
        };

        // Handles portlet tools & actions
        var handlePortletTools = function() {
            // handle portlet remove
            $('body').on('click', '.portlet > .portlet-title > .tools > a.remove', function(e) {
                e.preventDefault();
                var portlet = $(this).closest(".portlet");

                if ($('body').hasClass('page-portlet-fullscreen')) {
                    $('body').removeClass('page-portlet-fullscreen');
                }

                portlet.find('.portlet-title .fullscreen').tooltip('destroy');
                portlet.find('.portlet-title > .tools > .reload').tooltip('destroy');
                portlet.find('.portlet-title > .tools > .remove').tooltip('destroy');
                portlet.find('.portlet-title > .tools > .config').tooltip('destroy');
                portlet.find('.portlet-title > .tools > .collapse, .portlet > .portlet-title > .tools > .expand').tooltip('destroy');

                portlet.remove();
            });

            // handle portlet fullscreen
            $('body').on('click', '.portlet > .portlet-title .fullscreen', function(e) {
                e.preventDefault();
                var portlet = $(this).closest(".portlet");
                if (portlet.hasClass('portlet-fullscreen')) {
                    $(this).removeClass('on');
                    portlet.removeClass('portlet-fullscreen');
                    $('body').removeClass('page-portlet-fullscreen');
                    portlet.children('.portlet-body').css('height', 'auto');
                } else {
                    var height = App.getViewPort().height -
                        portlet.children('.portlet-title').outerHeight() -
                        parseInt(portlet.children('.portlet-body').css('padding-top')) -
                        parseInt(portlet.children('.portlet-body').css('padding-bottom'));

                    $(this).addClass('on');
                    portlet.addClass('portlet-fullscreen');
                    $('body').addClass('page-portlet-fullscreen');
                    portlet.children('.portlet-body').css('height', height);
                }
            });


            // load ajax data on page init
            $('.portlet .portlet-title a.reload[data-load="true"]').click();

            $('body').on('click', '.portlet > .portlet-title > .tools > .collapse, .portlet .portlet-title > .tools > .expand', function(e) {
                e.preventDefault();
                var el = $(this).closest(".portlet").children(".portlet-body");
                if ($(this).hasClass("collapse")) {
                    $(this).removeClass("collapse").addClass("expand");
                    el.slideUp(200);
                } else {
                    $(this).removeClass("expand").addClass("collapse");
                    el.slideDown(200);
                }
            });
        };

        // Handles custom checkboxes & radios using jQuery Uniform plugin
        var handleUniform = function() {
            if (!$().uniform) {
                return;
            }

            var test = $("input[type=checkbox]:not(.toggle, .md-check, .md-radiobtn, .make-switch, .icheck, .mail-checkbox), input[type=radio]:not(.toggle, .md-check, .md-radiobtn, .star, .make-switch, .icheck, .mail-checkbox)");
            if (test.size() > 0) {
                test.each(function() {
                    if ($(this).parents(".checker").size() === 0) {
                        $(this).show();
                        $(this).uniform();
                    }
                });
            }
        };

        // Handlesmaterial design checkboxes
        var handleMaterialDesign = function() {

            // Material design ckeckbox and radio effects
            $('body').on('click', '.md-checkbox > label, .md-radio > label', function() {
                var the = $(this);
                // find the first span which is our circle/bubble
                var el = $(this).children('span:first-child');

                // add the bubble class (we do this so it doesnt show on page load)
                el.addClass('inc');

                // clone it
                var newone = el.clone(true);

                // add the cloned version before our original
                el.before(newone);

                // remove the original so that it is ready to run on next click
                $("." + el.attr("class") + ":last", the).remove();
            });

            if ($('body').hasClass('page-md')) {
                // Material design click effect
                // credit where credit's due; http://thecodeplayer.com/walkthrough/ripple-click-effect-google-material-design
                var element, circle, d, x, y;
                $('body').on('click', 'a.btn, button.btn, input.btn, label.btn', function(e) {
                    element = $(this);

                    if(element.find(".md-click-circle").length == 0) {
                        element.prepend("<span class='md-click-circle'></span>");
                    }

                    circle = element.find(".md-click-circle");
                    circle.removeClass("md-click-animate");

                    if(!circle.height() && !circle.width()) {
                        d = Math.max(element.outerWidth(), element.outerHeight());
                        circle.css({height: d, width: d});
                    }

                    x = e.pageX - element.offset().left - circle.width()/2;
                    y = e.pageY - element.offset().top - circle.height()/2;

                    circle.css({top: y+'px', left: x+'px'}).addClass("md-click-animate");

                    setTimeout(function() {
                        circle.remove();
                    }, 1000);
                });
            }

            // Floating labels
            var handleInput = function(el) {
                if (el.val() != "") {
                    el.addClass('edited');
                } else {
                    el.removeClass('edited');
                }
            }

            $('body').on('keydown', '.form-md-floating-label .form-control', function(e) {
                handleInput($(this));
            });
            $('body').on('blur', '.form-md-floating-label .form-control', function(e) {
                handleInput($(this));
            });

            $('.form-md-floating-label .form-control').each(function(){
                if ($(this).val().length > 0) {
                    $(this).addClass('edited');
                }
            });
        }

        // Handles custom checkboxes & radios using jQuery iCheck plugin
        var handleiCheck = function() {
            if (!$().iCheck) {
                return;
            }

            $('.icheck').each(function() {
                var checkboxClass = $(this).attr('data-checkbox') ? $(this).attr('data-checkbox') : 'icheckbox_minimal-grey';
                var radioClass = $(this).attr('data-radio') ? $(this).attr('data-radio') : 'iradio_minimal-grey';

                if (checkboxClass.indexOf('_line') > -1 || radioClass.indexOf('_line') > -1) {
                    $(this).iCheck({
                        checkboxClass: checkboxClass,
                        radioClass: radioClass,
                        insert: '<div class="icheck_line-icon"></div>' + $(this).attr("data-label")
                    });
                } else {
                    $(this).iCheck({
                        checkboxClass: checkboxClass,
                        radioClass: radioClass
                    });
                }
            });
        };

        // Handles Bootstrap switches
        var handleBootstrapSwitch = function() {
            if (!$().bootstrapSwitch) {
                return;
            }
            $('.make-switch').bootstrapSwitch();
        };

        // Handles Bootstrap confirmations
        var handleBootstrapConfirmation = function() {
            if (!$().confirmation) {
                return;
            }
            $('[data-toggle=confirmation]').confirmation({ container: 'body', btnOkClass: 'btn btn-sm btn-success', btnCancelClass: 'btn btn-sm btn-danger'});
        }

        // Handles Bootstrap Accordions.
        var handleAccordions = function() {
            $('body').on('shown.bs.collapse', '.accordion.scrollable', function(e) {
                App.scrollTo($(e.target));
            });
        };

        // Handles Bootstrap Tabs.
        var handleTabs = function() {
            //activate tab if tab id provided in the URL
            if (location.hash) {
                var tabid = encodeURI(location.hash.substr(1));
                $('a[href="#' + tabid + '"]').parents('.tab-pane:hidden').each(function() {
                    var tabid = $(this).attr("id");
                    $('a[href="#' + tabid + '"]').click();
                });
                $('a[href="#' + tabid + '"]').click();
            }

            if ($().tabdrop) {
                $('.tabbable-tabdrop .nav-pills, .tabbable-tabdrop .nav-tabs').tabdrop({
                    text: '<i class="fa fa-ellipsis-v"></i>&nbsp;<i class="fa fa-angle-down"></i>'
                });
            }
        };

        // Handles Bootstrap Modals.
        var handleModals = function() {
            // fix stackable modal issue: when 2 or more modals opened, closing one of modal will remove .modal-open class.
            $('body').on('hide.bs.modal', function() {
                if ($('.modal:visible').size() > 1 && $('html').hasClass('modal-open') === false) {
                    $('html').addClass('modal-open');
                } else if ($('.modal:visible').size() <= 1) {
                    $('html').removeClass('modal-open');
                }
            });

            // fix page scrollbars issue
            $('body').on('show.bs.modal', '.modal', function() {
                if ($(this).hasClass("modal-scroll")) {
                    $('body').addClass("modal-open-noscroll");
                }
            });

            // fix page scrollbars issue
            $('body').on('hide.bs.modal', '.modal', function() {
                $('body').removeClass("modal-open-noscroll");
            });

            // remove ajax content and remove cache on modal closed
            $('body').on('hidden.bs.modal', '.modal:not(.modal-cached)', function () {
                $(this).removeData('bs.modal');
            });
        };

        // Handles Bootstrap Tooltips.
        var handleTooltips = function() {
            // global tooltips
            $('.tooltips').tooltip();

            // portlet tooltips
            $('.portlet > .portlet-title .fullscreen').tooltip({
                container: 'body',
                title: 'Fullscreen'
            });
            $('.portlet > .portlet-title > .tools > .reload').tooltip({
                container: 'body',
                title: 'Reload'
            });
            $('.portlet > .portlet-title > .tools > .remove').tooltip({
                container: 'body',
                title: 'Remove'
            });
            $('.portlet > .portlet-title > .tools > .config').tooltip({
                container: 'body',
                title: 'Settings'
            });
            $('.portlet > .portlet-title > .tools > .collapse, .portlet > .portlet-title > .tools > .expand').tooltip({
                container: 'body',
                title: 'Collapse/Expand'
            });
        };

        // Handles Bootstrap Dropdowns
        var handleDropdowns = function() {
            /*
              Hold dropdown on click
            */
            $('body').on('click', '.dropdown-menu.hold-on-click', function(e) {
                e.stopPropagation();
            });
        };

        var handleAlerts = function() {
            $('body').on('click', '[data-close="alert"]', function(e) {
                $(this).parent('.alert').hide();
                $(this).closest('.note').hide();
                e.preventDefault();
            });

            $('body').on('click', '[data-close="note"]', function(e) {
                $(this).closest('.note').hide();
                e.preventDefault();
            });

            $('body').on('click', '[data-remove="note"]', function(e) {
                $(this).closest('.note').remove();
                e.preventDefault();
            });
        };

        // Handle Hower Dropdowns
        var handleDropdownHover = function() {
            $('[data-hover="dropdown"]').not('.hover-initialized').each(function() {
                $(this).dropdownHover();
                $(this).addClass('hover-initialized');
            });
        };

        // Handle textarea autosize
        var handleTextareaAutosize = function() {
            if (typeof(autosize) == "function") {
                autosize(document.querySelector('textarea.autosizeme'));
            }
        }

        // Handles Bootstrap Popovers

        // last popep popover
        var lastPopedPopover;

        var handlePopovers = function() {
            $('.popovers').popover();

            // close last displayed popover

            $(document).on('click.bs.popover.data-api', function(e) {
                if (lastPopedPopover) {
                    lastPopedPopover.popover('hide');
                }
            });
        };

        // Handles scrollable contents using jQuery SlimScroll plugin.
        var handleScrollers = function() {
            App.initSlimScroll('.scroller');
        };

        var setupHeaderEvents = function() {
            $('li#header_notification_bar').click(function(){
                getNotifications();

            });

            $('.notification-list').on('click', 'li a', function (e) {
                e.preventDefault();
                var self = $(this), li = self.parent('li'), link = self.attr('href');

                App.ajax({
                    url: ajax_notification_click,
                    data: {
                        id: li.attr('id')
                    },
                    block: true,
                    blockTarget: '.notification-list'
                }, function(){
                    window.location = link;
                });
            });
        };

        var doAjax = function( options, callback, errorCb ) {
            $.ajax({
                url: options.url,
                type: options.type || 'POST',
                dataType: options.dataType || 'json',
                cache: options.cache || false,
                data: options.data || {},
                complete: options.complete || function(){},
                beforeSend: options.beforeSend || function() {
                    if( options.block ) {
                        App.blockUI({
                            target: options.blockTarget
                        });
                    }
                },
                success: options.success || function ( data ) {
                    if( options.block ) {
                        App.unblockUI( options.blockTarget );
                    }

                    if( data.error ) {
                        if( log ) {
                            App.notification( 'error', 'System Error', data.error );
                            console.log( data.error );
                        }

                        if( errorCb ) errorCb( XMLHttpRequest.responseText );
                        return;
                    }

                    if( callback ) callback( data );
                },
                error: options.error || function( XMLHttpRequest, textStatus, errorThrown ) {
                    if( XMLHttpRequest.status == 401 ) {
                        window.location.reload();
                        return;
                    }

                    if( options.block ) {
                        App.unblockUI( options.blockTarget );
                    }

                    if( log ) {
                        App.notification( 'error', 'Ajax Error', 'Check console for the details.' );
                        console.log( XMLHttpRequest.responseText );
                    }

                    if( errorCb ) errorCb( XMLHttpRequest.responseText );
                }
            });
        };

        var runAjaxQueue = function() {
            if( ajaxRequests.length )
            {
                ajaxStall = ajaxRequests[0].complete;
                ajaxRequests[0].options.complete = completeAjax.bind(App);

                var _request = ajaxRequests[0];

                doAjax(_request.options, _request.callback, _request.errorCb);
            }
            else
            {
                ajaxQueueTO = setTimeout(function() {
                    runAjaxQueue.apply(this, []);
                }.bind(App), 50);
            }
        };

        var stopAjaxQueue = function() {
            ajaxRequests = [];
            clearTimeout(ajaxQueueTO);
        };

        var completeAjax = function()
        {
            if( typeof ajaxStall === 'function' ) ajaxStall();
            ajaxRequests.shift();
            runAjaxQueue.apply(this, []);
        };

        var Paginator = function( element, options ) {
            this.$element = $(element);
            this._element = element;
            this.options = $.extend({}, {
                totalPages: 1,
                startPage: 1,
                visiblePages: 5,
                visiblePagesDefault: 8,
                initiateStartPageClick: false,
                href: '#page={{page}}',
                hrefVariable: '{{pageNumber}}',
                pageVariable: '{{page}}',
                totalPagesVariable: '{{total_pages}}',
                page: null,
                first: 'First',
                prev: 'Previous',
                next: 'Next',
                last: 'Last',
                loop: false,
                onlyArrows: false,
                onPageClick: null,
                itemContent: null,
                itemContainer: false,
                dynamic: false,
                container: true,
                paginationClass: 'pagination',
                nextClass: 'next',
                prevClass: 'prev',
                lastClass: 'last',
                firstClass: 'first',
                pageClass: 'page',
                activeClass: 'active',
                disabledClass: 'disabled'
            }, options);

            if (this.options.startPage < 1 || this.options.startPage > this.options.totalPages) {
                App.error('Start page option is incorrect');
            }

            this.options.totalPages = parseInt(this.options.totalPages);
            if (isNaN(this.options.totalPages)) {
                App.error('Total pages option is not correct!');
            }

            this.options.visiblePages = parseInt(this.options.visiblePages);
            this.options.visiblePagesDefault = this.options.visiblePages;
            if (isNaN(this.options.visiblePages)) {
                App.error('Visible pages option is not correct!');
            }

            if (this.options.totalPages < this.options.visiblePages) {
                this.options.visiblePages = this.options.totalPages;
            }

            if (this.options.onPageClick instanceof Function) {
                this.$element.on('page', this.options.onPageClick);
            }

            if (this.options.href) {
                var match, regexp = this.options.href.replace(/[-\/\\^$*+?.|[\]]/g, '\\$&');
                regexp = regexp.replace(this.options.pageVariable, '(\\d+)');
                if ((match = new RegExp(regexp, 'i').exec(window.location.href)) != null) {
                    var p = parseInt(match[1], 10);
                    if( p < 1 || p > this.options.totalPages ) {
                        this.options.startPage = 1;
                    } else {
                        this.options.startPage = parseInt(match[1], 10);
                    }
                }
            }

            //var tagName = (typeof this.$element.prop === 'function') ?
            //    this.$element.prop('tagName') : this.$element.attr('tagName');

            if ( this.options.container ) {
                this.$listContainer = $('<ul></ul>');
                this.$listContainer.addClass(this.options.paginationClass);
                this.$element.append(this.$listContainer);
            } else {
                this.$listContainer = this.$element;
                this.$listContainer.addClass(this.options.paginationClass);
            }

            if (this.options.initiateStartPageClick) {
                this.show(this.options.startPage);
            } else {
                this.render(this.getPages(this.options.startPage));
                this.setupEvents();
            }

            return this;
        };

        Paginator.prototype = {

            constructor: Paginator,

            destroy: function() {
                this.$element.empty();
                this.$element.off('page');
                return this;
            },

            show: function( page ) {
                if (page < 1 || page > this.options.totalPages) {
                    App.error('Page is incorrect.');
                }

                //this.$element.trigger('page', page);
                var _this = this;
                _this._disabled = true;

                this.options.onPageClick.apply( this, [ page, function(){
                    _this.render( _this.getPages(page) );
                    _this.setupEvents();
                    _this._disabled = false;
                } ]);
            },

            update: function( options, callback ) {
                if( this.options.dynamic ) {
                    this.$element = $(this._element);

                    if ( this.options.container ) {
                        this.$listContainer = $('<ul></ul>');
                        this.$listContainer.addClass(this.options.paginationClass);
                        this.$element.append(this.$listContainer);
                    } else {
                        this.$listContainer = this.$element;
                        this.$listContainer.addClass(this.options.paginationClass);
                    }
                }

                this.options.startPage = parseInt(options.startPage) || this.options.startPage;
                this.options.totalPages = parseInt(options.totalPages) || this.options.totalPages;

                if ( this.options.totalPages < this.options.visiblePages ) {
                    this.options.visiblePages = this.options.totalPages;
                } else if( this.options.totalPages < this.options.visiblePagesDefault ) {
                    this.options.visiblePages = this.options.totalPages;
                } else {
                    this.options.visiblePages = this.options.visiblePagesDefault;
                }

                //this.destroy();
                this.render( this.getPages( this.options.startPage ) );
                this.setupEvents();

                if( callback ) callback.apply(this, [{
                    total: this.options.totalPages,
                    current: this.options.startPage
                }]);
                //this.show( this.options.startPage );
            },

            buildListItems: function (pages) {
                var listItems = [];

                // Add "first" page button
                if (!this.options.onlyArrows && this.options.first) {
                    listItems.push(this.buildItem('first', 1));
                }
                // Add "previous" page button
                if (this.options.prev) {
                    var prev = pages.currentPage > 1 ? pages.currentPage - 1 : this.options.loop ? this.options.totalPages  : 1;
                    listItems.push(this.buildItem('prev', prev));
                }
                if( !this.options.onlyArrows ) {
                    // Add "pages"
                    for (var i = 0; i < pages.numeric.length; i++) {
                        listItems.push(this.buildItem('page', pages.numeric[i]));
                    }
                }
                // Add "next" page button
                if (this.options.next) {
                    var next = pages.currentPage < this.options.totalPages ? pages.currentPage + 1 : this.options.totalPages;
                    listItems.push(this.buildItem('next', next));
                }
                // Add "last" page button
                if (!this.options.onlyArrows && this.options.last) {
                    listItems.push(this.buildItem('last', this.options.totalPages));
                }

                return listItems;
            },

            buildItem: function (type, page) {
                var $itemContainer = ( this.options.itemContainer ) ? $( this.options.itemContainer ) : $('<li></li>'),
                    $itemContent = ( this.options.itemContent == null ) ? $('<a></a>') : this.options.itemContent,
                    itemText = null;

                itemText = this.options[type] ? this.makeText(this.options[type], page) : page;

                $itemContainer.addClass(this.options[type + 'Class']);
                $itemContainer.data('page', page);
                $itemContainer.data('page-type', type);

                if( $itemContent ) {
                    $itemContainer.append($itemContent.attr('href', this.makeHref(page)).html(itemText));
                } else {
                    $itemContainer.attr('href', this.makeHref(page)).html(itemText);
                }

                return $itemContainer;
            },

            getPages: function (currentPage) {
                var pages = [];

                var half = Math.floor(this.options.visiblePages / 2);
                var start = currentPage - half + 1 - this.options.visiblePages % 2;
                var end = currentPage + half;

                // handle boundary case
                if (start <= 0) {
                    start = 1;
                    end = this.options.visiblePages;
                }
                if (end > this.options.totalPages) {
                    start = this.options.totalPages - this.options.visiblePages + 1;
                    end = this.options.totalPages;
                }

                var itPage = start;
                while (itPage <= end) {
                    pages.push(itPage);
                    itPage++;
                }

                return { "currentPage": currentPage, "numeric": pages };
            },

            render: function (pages) {
                var _this = this;
                this.$listContainer.children().remove();
                var items = this.buildListItems(pages);
                jQuery.each(items, function(key, item){
                    _this.$listContainer.append(item);
                });

                this.$listContainer.children().each(function () {
                    var $this = $(this),
                        pageType = $this.data('page-type');

                    switch (pageType) {
                        case 'page':
                            if ($this.data('page') == pages.currentPage) {
                                $this.addClass(_this.options.activeClass);
                            }
                            break;
                        case 'first':
                                $this.toggleClass(_this.options.disabledClass, pages.currentPage == 1);
                            break;
                        case 'last':
                                $this.toggleClass(_this.options.disabledClass, pages.currentPage == _this.options.totalPages);
                            break;
                        case 'prev':
                                $this.toggleClass(_this.options.disabledClass, !_this.options.loop && pages.currentPage == 1);
                            break;
                        case 'next':
                                $this.toggleClass(_this.options.disabledClass,
                                    !_this.options.loop && pages.currentPage == _this.options.totalPages);
                            break;
                        default:
                            break;
                    }

                });

                //if( this.options.href ) window.location.hash = this.makeText(this.options.href, pages.currentPage);
            },

            setupEvents: function () {
                var _this = this;
                this.$listContainer.children().each(function () {//find('li').each(function () {
                    var $this = $(this);
                    $this.off();
                    if ($this.hasClass(_this.options.disabledClass) || $this.hasClass(_this.options.activeClass)) {
                        $this.on('click', false);
                        return;
                    }
                    $this.click(function (evt) {
                        // Prevent click event if href is not set.
                        !_this.options.href && evt.preventDefault();
                        if( _this._disabled ) return;
                        _this.show(parseInt($this.data('page')));
                    });
                });
            },

            makeHref: function (page) {
                return this.options.href ? this.makeText(this.options.href, page) : "#";
            },

            makeText: function (text, page) {
                return text.replace(this.options.pageVariable, page)
                    .replace(this.options.totalPagesVariable, this.options.totalPages)
            },

            _disabled: false
        };

        // Handles Image Preview using jQuery Fancybox plugin
        var handleFancybox = function() {
            if (!jQuery.fancybox) {
                return;
            }

            if ($(".fancybox-button").size() > 0) {
                $(".fancybox-button").fancybox({
                    groupAttr: 'data-rel',
                    prevEffect: 'none',
                    nextEffect: 'none',
                    closeBtn: true,
                    helpers: {
                        title: {
                            type: 'inside'
                        }
                    }
                });
            }
        };

        // Handles counterup plugin wrapper
        var handleCounterup = function() {
            if (!$().counterUp) {
                return;
            }

            $("[data-counter='counterup']").counterUp({
                delay: 10,
                time: 1000
            });
        };

        // Fix input placeholder issue for IE8 and IE9
        var handleFixInputPlaceholderForIE = function() {
            //fix html5 placeholder attribute for ie7 & ie8
            if (isIE8 || isIE9) { // ie8 & ie9
                // this is html5 placeholder fix for inputs, inputs with placeholder-no-fix class will be skipped(e.g: we need this for password fields)
                $('input[placeholder]:not(.placeholder-no-fix), textarea[placeholder]:not(.placeholder-no-fix)').each(function() {
                    var input = $(this);

                    if (input.val() === '' && input.attr("placeholder") !== '') {
                        input.addClass("placeholder").val(input.attr('placeholder'));
                    }

                    input.focus(function() {
                        if (input.val() == input.attr('placeholder')) {
                            input.val('');
                        }
                    });

                    input.blur(function() {
                        if (input.val() === '' || input.val() == input.attr('placeholder')) {
                            input.val(input.attr('placeholder'));
                        }
                    });
                });
            }
        };

        var initWebsocket = function(){
            

        };

        var notificationItemTemplate = $('#notification-item');

        var addNotItem = function( parent, item, prepend ) {
            var newRow;

            if( notificationItemTemplate.length ) {
                newRow = notificationItemTemplate.clone();
                newRow.attr('id', item.id);
                newRow.removeClass('hidden');

                if( item[ 'status' ] == 0 ) newRow.addClass('unread');

                newRow = newRow.prop('outerHTML');

                for( ik in item ) {
                    if( ik == 'avatar' ) {
                        newRow = App.replaceAll( newRow, '%' + ik + '%', item[ ik ], '%avatar%', function(){
                            //return '<img src="' + item[ ik ] + '" class="avatar-img" width="20px" />'
                            return '';
                        } );
                    } else {
                        newRow = App.replaceAll( newRow, '%' + ik + '%', item[ ik ] );
                    }
                }

                if( prepend )
                    parent.prepend(newRow);
                else
                    parent.append(newRow);
            } else {
                if(act_lang === 'en') {
                    parent.html('<div class="text-center"><h4>No notifications</h4></div>');
                }
                else if(act_lang === 'cn'){
                    parent.html('<div class="text-center"><h4>没有通知</h4></div>');
                }
            }
        };

        var getNotifications = function( cb ) {
            //if( loaded.indexOf('notifications') < 0 ) {
            //$('.notification-list').empty();

                loaded.push('notifications');

                App.ajax({
                    url: ajax_url_notifications,
                    block: true,
                    blockTarget: '.notification-list'
                }, function ( result ) {
                    var item, list = $('.notification-list'),
                        data = result.data, i, l = data.length, ik;
                    if( l ) {

                        list.empty();

                        for( i = 0; i < l; i++ ) {
                            item = data[ i ];

                            addNotItem( list, item );
                        }

                        var act_content = $('#header_notification_bar li.external').html();
                        //var act_content = list.html();
                        //list.html(act_content + '<div class="pull-right"><h4>ASD</h4></div>');

                        if($('#header_notification_bar li.external').html().toString().indexOf('class="fa fa-check') == -1) {
                            if(act_lang === 'en') {
                                $('#header_notification_bar li.external').html(act_content + '<h3 style="font-size: 70%; letter-spacing: 0px;" class="pull-right"><a id="read-all-nots" data-toggle="tooltip" title="Read" href="javascript:clearNotificationList()"><i class="fa fa-check not-icon"></i></a> | <a id="del-all-nots" data-toggle="tooltip" title="Clear" href="javascript:deleteNotificationList()"><i class="fa fa-trash-o not-icon"></i></a></h3>');
                            }
                            else if(act_lang === 'cn'){
                                $('#header_notification_bar li.external').html(act_content + '<h3 style="font-size: 70%; letter-spacing: 0px;" class="pull-right"><a id="read-all-nots" data-toggle="tooltip" title="读" href="javascript:clearNotificationList()"><i class="fa fa-check not-icon"></i></a> | <a id="del-all-nots" data-toggle="tooltip" title="明确" href="javascript:deleteNotificationList()"><i class="fa fa-trash-o not-icon"></i></a></h3>');
                            }

                            $('#read-all-nots').tooltip();
                            $('#del-all-nots').tooltip();
                        }


                    }
                    else {
                        if(act_lang === 'en') {
                            list.html('<div class="text-center"><h4>No notifications</h4></div>');
                        }
                        else if(act_lang === 'cn'){
                            list.html('<div class="text-center"><h4>没有通知</h4></div>');
                        }
                    }

                    if( cb )
                        cb();
                });
           // }
        };

        // Handle Select2 Dropdowns
        var handleSelect2 = function() {
            if ($().select2) {
                $.fn.select2.defaults.set("theme", "bootstrap");
                $('.select2me').select2({
                    placeholder: "Select",
                    width: 'auto',
                    allowClear: true
                });
            }
        };

        // handle group element heights
       var handleHeight = function() {
           $('[data-auto-height]').each(function() {
                var parent = $(this);
                var items = $('[data-height]', parent);
                var height = 0;
                var mode = parent.attr('data-mode');
                var offset = parseInt(parent.attr('data-offset') ? parent.attr('data-offset') : 0);

                items.each(function() {
                    if ($(this).attr('data-height') == "height") {
                        $(this).css('height', '');
                    } else {
                        $(this).css('min-height', '');
                    }

                    var height_ = (mode == 'base-height' ? $(this).outerHeight() : $(this).outerHeight(true));
                    if (height_ > height) {
                        height = height_;
                    }
                });

                height = height + offset;

                items.each(function() {
                    if ($(this).attr('data-height') == "height") {
                        $(this).css('height', height);
                    } else {
                        $(this).css('min-height', height);
                    }
                });

                if(parent.attr('data-related')) {
                    $(parent.attr('data-related')).css('height', parent.height());
                }
           });
        }

        //* END:CORE HANDLERS *//

        return {

            //main function to initiate the theme
            init: function() {
                //IMPORTANT!!!: Do not modify the core handlers call order.

                //Core handlers
                handleInit(); // initialize core variables
                handleOnResize(); // set and handle responsive

                setupHeaderEvents();

                //UI Component handlers
                handleMaterialDesign(); // handle material design
                handleUniform(); // hanfle custom radio & checkboxes
                handleiCheck(); // handles custom icheck radio and checkboxes
                handleBootstrapSwitch(); // handle bootstrap switch plugin
                handleScrollers(); // handles slim scrolling contents
                handleFancybox(); // handle fancy box
                handleSelect2(); // handle custom Select2 dropdowns
                handlePortletTools(); // handles portlet action bar functionality(refresh, configure, toggle, remove)
                handleAlerts(); //handle closabled alerts
                handleDropdowns(); // handle dropdowns
                handleTabs(); // handle tabs
                handleTooltips(); // handle bootstrap tooltips
                handlePopovers(); // handles bootstrap popovers
                handleAccordions(); //handles accordions
                handleModals(); // handle modals
                handleBootstrapConfirmation(); // handle bootstrap confirmations
                handleTextareaAutosize(); // handle autosize textareas
                handleCounterup(); // handle counterup instances

                //Handle group element heights
                handleHeight();
                this.addResizeHandler(handleHeight); // handle auto calculating height on window resize

                // Hacks
                handleFixInputPlaceholderForIE(); //IE8 & IE9 input placeholder issue fix
                this.initComponents();

                //this.startPageLoading();
            },

            //main function to initiate core javascript after ajax complete
            initAjax: function() {
                runAjaxQueue();
                initWebsocket();
            },

            on: on,

            trigger: trigger,

            //init main components
            initComponents: function() {
                this.initAjax();
                //handleNotifications();
            },

            //public function to remember last opened popover that needs to be closed on click
            setLastPopedPopover: function(el) {
                lastPopedPopover = el;
            },

            //public function to add callback a function which will be called on window resize
            addResizeHandler: function(func) {
                resizeHandlers.push(func);
            },

            //public functon to call _runresizeHandlers
            runResizeHandlers: function() {
                _runResizeHandlers();
            },

            replaceAll: function (str, find, replace, useFn, extraFn) {
                if( useFn == find && extraFn ) replace = extraFn();
                return str.replace(new RegExp(find, 'g'), replace);
            },

            ajax: function( options, callback, errorCb ) {
                if( ajaxQueue )
                    return ajaxRequests.push({ options: options, callback: callback, errorCb: errorCb });

                doAjax( options, callback, errorCb );
            },

            notification: function( status, title, message ) {
                toastr.options = {
                  "closeButton": true,
                  "debug": false,
                  "positionClass": "toast-bottom-left",
                  "onclick": null,
                  "showDuration": "2000",
                  "hideDuration": "2000",
                  "timeOut": "8000",
                  "extendedTimeOut": "2000",
                  "showEasing": "swing",
                  "hideEasing": "linear",
                  "showMethod": "fadeIn",
                  "hideMethod": "fadeOut"
                };

                toastr[ status ](message, title);
            },

            error: function( message ) {
                App.notification( 'error', 'Application error!', message );
            },

            paginator: function( element, options ) {
                var args = Array.prototype.slice.call(arguments, 1);
                var methodReturn;

                var $this = $(element);
                var data = $this.data('pagination');
                var options = typeof options === 'object' ? options : {};

                if (!data) $this.data('pagination', (data = new Paginator(element, options) ));
                //methodReturn = data[ options ].apply(data, args);

                return data;
            },

            // wrApper function to scroll(focus) to an element
            scrollTo: function(el, offeset) {
                var pos = (el && el.size() > 0) ? el.offset().top : 0;

                if (el) {
                    if ($('body').hasClass('page-header-fixed')) {
                        pos = pos - $('.page-header').height();
                    } else if ($('body').hasClass('page-header-top-fixed')) {
                        pos = pos - $('.page-header-top').height();
                    } else if ($('body').hasClass('page-header-menu-fixed')) {
                        pos = pos - $('.page-header-menu').height();
                    }
                    pos = pos + (offeset ? offeset : -1 * el.height());
                }

                $('html,body').animate({
                    scrollTop: pos
                }, 'slow');
            },




        initSlimScroll: function(el) {
                $(el).each(function() {
                    //console.log($(this));
                    if ($(this).attr("data-initialized")) {
                        return; // exit
                    }

                    var height;

                    if ($(this).attr("data-height")) {
                        height = $(this).attr("data-height");
                    } else {
                        height = $(this).css('height');
                    }

                    $(this).slimScroll({
                        //allowPageScroll: true, // allow page scroll when the element scroll is ended
                        size: '7px',
                        color: ($(this).attr("data-handle-color") ? $(this).attr("data-handle-color") : '#bbb'),
                        wrapperClass: ($(this).attr("data-wrapper-class") ? $(this).attr("data-wrapper-class") : 'slimScrollDiv'),
                        railColor: ($(this).attr("data-rail-color") ? $(this).attr("data-rail-color") : '#eaeaea'),
                        position: isRTL ? 'left' : 'right',
                        height: height,
                        alwaysVisible: ($(this).attr("data-always-visible") == "1" ? true : false),
                        railVisible: ($(this).attr("data-rail-visible") == "1" ? true : false),
                        disableFadeOut: true
                    });

                    /*$("#header_notification_bar").on("shown.bs.dropdown", function(e) {

                    });

                    $("#header_notification_bar").on("hidden.bs.dropdown", function(e) {

                    });*/

                    $(this).attr("data-initialized", "1");


                });
            },

            destroySlimScroll: function(el) {
                $(el).each(function() {
                    if ($(this).attr("data-initialized") === "1") { // destroy existing instance before updating the height
                        $(this).removeAttr("data-initialized");
                        $(this).removeAttr("style");

                        var attrList = {};

                        // store the custom attribures so later we will reassign.
                        if ($(this).attr("data-handle-color")) {
                            attrList["data-handle-color"] = $(this).attr("data-handle-color");
                        }
                        if ($(this).attr("data-wrapper-class")) {
                            attrList["data-wrapper-class"] = $(this).attr("data-wrapper-class");
                        }
                        if ($(this).attr("data-rail-color")) {
                            attrList["data-rail-color"] = $(this).attr("data-rail-color");
                        }
                        if ($(this).attr("data-always-visible")) {
                            attrList["data-always-visible"] = $(this).attr("data-always-visible");
                        }
                        if ($(this).attr("data-rail-visible")) {
                            attrList["data-rail-visible"] = $(this).attr("data-rail-visible");
                        }

                        $(this).slimScroll({
                            wrapperClass: ($(this).attr("data-wrapper-class") ? $(this).attr("data-wrapper-class") : 'slimScrollDiv'),
                            destroy: true
                        });

                        var the = $(this);

                        // reassign custom attributes
                        $.each(attrList, function(key, value) {
                            the.attr(key, value);
                        });

                    }
                });
            },

            // function to scroll to the top
            scrollTop: function() {
                App.scrollTo();
            },

            // wrApper function to  block element(indicate loading)
            blockUI: function(options) {
                options = $.extend(true, {}, options);
                var html = '';
                if (options.animate) {
                    html = '<div class="loading-message ' + (options.boxed ? 'loading-message-boxed' : '') + '">' + '<div class="block-spinner-bar"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>' + '</div>';
                } else if (options.iconOnly) {
                    html = '<div class="loading-message ' + (options.boxed ? 'loading-message-boxed' : '') + '"><img src="' + this.getGlobalImgPath() + 'loading-spinner-grey.gif" align=""></div>';
                } else if (options.textOnly) {
                    if(act_lang === 'en') {
                        html = '<div class="loading-message ' + (options.boxed ? 'loading-message-boxed' : '') + '"><span>&nbsp;&nbsp;' + (options.message ? options.message : 'LOADING...') + '</span></div>';
                    }
                    else if(act_lang === 'cn'){
                        html = '<div class="loading-message ' + (options.boxed ? 'loading-message-boxed' : '') + '"><span>&nbsp;&nbsp;' + (options.message ? options.message : '炉料...') + '</span></div>';
                    }
                } else {
                    if(act_lang === 'en') {
                        html = '<div class="loading-message ' + (options.boxed ? 'loading-message-boxed' : '') + '"><img src="' + this.getGlobalImgPath() + 'loading-spinner-grey.gif" align=""><span>&nbsp;&nbsp;' + (options.message ? options.message : 'LOADING...') + '</span></div>';
                    }
                    else if(act_lang === 'cn'){
                        html = '<div class="loading-message ' + (options.boxed ? 'loading-message-boxed' : '') + '"><img src="' + this.getGlobalImgPath() + 'loading-spinner-grey.gif" align=""><span>&nbsp;&nbsp;' + (options.message ? options.message : '炉料...') + '</span></div>';
                    }
                }

                if (options.target) { // element blocking
                    var el = $(options.target);
                    if (el.height() <= ($(window).height())) {
                        options.cenrerY = true;
                    }
                    el.block({
                        message: html,
                        baseZ: options.zIndex ? options.zIndex : 1000,
                        centerY: options.cenrerY !== undefined ? options.cenrerY : false,
                        css: {
                            top: '10%',
                            border: '0',
                            padding: '0',
                            backgroundColor: 'none'
                        },
                        overlayCSS: {
                            backgroundColor: options.overlayColor ? options.overlayColor : '#555',
                            opacity: options.boxed ? 0.05 : 0.1,
                            cursor: 'wait'
                        }
                    });
                } else { // page blocking
                    $.blockUI({
                        message: html,
                        baseZ: options.zIndex ? options.zIndex : 1000,
                        css: {
                            border: '0',
                            padding: '0',
                            backgroundColor: 'none'
                        },
                        overlayCSS: {
                            backgroundColor: options.overlayColor ? options.overlayColor : '#555',
                            opacity: options.boxed ? 0.05 : 0.1,
                            cursor: 'wait'
                        }
                    });
                }
            },

            // wrApper function to  un-block element(finish loading)
            unblockUI: function(target) {
                if (target) {
                    $(target).unblock({
                        onUnblock: function() {
                            $(target).css('position', '');
                            $(target).css('zoom', '');
                        }
                    });
                } else {
                    $.unblockUI();
                }
            },

            startPageLoading: function(options) {
                if (options && options.animate) {
                    $('.page-spinner-bar').remove();
                    $('body').append('<div class="page-spinner-bar"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>');
                } else {
                    $('.page-loading').remove();
                    if(act_lang === 'en') {
                        $('body').append('<div class="page-loading"><img src="' + this.getGlobalImgPath() + 'loading-spinner-grey.gif"/>&nbsp;&nbsp;<span>' + (options && options.message ? options.message : 'Loading...') + '</span></div>');
                    }
                    else if(act_lang === 'cn'){
                        $('body').append('<div class="page-loading"><img src="' + this.getGlobalImgPath() + 'loading-spinner-grey.gif"/>&nbsp;&nbsp;<span>' + (options && options.message ? options.message : '炉料...') + '</span></div>');
                    }
                }
            },

            stopPageLoading: function() {
                $('.page-loading, .page-spinner-bar').remove();
            },

            alert: function(options) {

                options = $.extend(true, {
                    container: "", // alerts parent container(by default placed after the page breadcrumbs)
                    place: "append", // "append" or "prepend" in container
                    type: 'success', // alert's type
                    message: "", // alert's message
                    close: true, // make alert closable
                    reset: true, // close all previouse alerts first
                    focus: true, // auto scroll to the alert after shown
                    closeInSeconds: 0, // auto close after defined seconds
                    icon: "" // put icon before the message
                }, options);

                var id = App.getUniqueID("App_alert");

                var html = '<div id="' + id + '" class="custom-alerts alert alert-' + options.type + ' fade in">' + (options.close ? '<button type="button" class="close" data-dismiss="alert" aria-hidden="true"></button>' : '') + (options.icon !== "" ? '<i class="fa-lg fa fa-' + options.icon + '"></i>  ' : '') + options.message + '</div>';

                if (options.reset) {
                    $('.custom-alerts').remove();
                }

                if (!options.container) {
                    if ($('body').hasClass("page-container-bg-solid") || $('body').hasClass("page-content-white")) {
                        $('.page-title').after(html);
                    } else {
                        if ($('.page-bar').size() > 0) {
                            $('.page-bar').after(html);
                        } else {
                            $('.page-breadcrumb').after(html);
                        }
                    }
                } else {
                    if (options.place == "append") {
                        $(options.container).append(html);
                    } else {
                        $(options.container).prepend(html);
                    }
                }

                if (options.focus) {
                    App.scrollTo($('#' + id));
                }

                if (options.closeInSeconds > 0) {
                    setTimeout(function() {
                        $('#' + id).remove();
                    }, options.closeInSeconds * 1000);
                }

                return id;
            },

            // initializes uniform elements
            initUniform: function(els) {
                if (els) {
                    $(els).each(function() {
                        if ($(this).parents(".checker").size() === 0) {
                            $(this).show();
                            $(this).uniform();
                        }
                    });
                } else {
                    handleUniform();
                }
            },

            //wrApper function to update/sync jquery uniform checkbox & radios
            updateUniform: function(els) {
                $.uniform.update(els); // update the uniform checkbox & radios UI after the actual input control state changed
            },

            //public function to initialize the fancybox plugin
            initFancybox: function() {
                handleFancybox();
            },

            //public helper function to get actual input value(used in IE9 and IE8 due to placeholder attribute not supported)
            getActualVal: function(el) {
                el = $(el);
                if (el.val() === el.attr("placeholder")) {
                    return "";
                }
                return el.val();
            },

            //public function to get a paremeter by name from URL
            getURLParameter: function(paramName) {
                var searchString = window.location.search.substring(1),
                    i, val, params = searchString.split("&");

                for (i = 0; i < params.length; i++) {
                    val = params[i].split("=");
                    if (val[0] == paramName) {
                        return unescape(val[1]);
                    }
                }
                return null;
            },

            // check for device touch support
            isTouchDevice: function() {
                try {
                    document.createEvent("TouchEvent");
                    return true;
                } catch (e) {
                    return false;
                }
            },

            // To get the correct viewport width based on  http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
            getViewPort: function() {
                var e = window,
                    a = 'inner';
                if (!('innerWidth' in window)) {
                    a = 'client';
                    e = document.documentElement || document.body;
                }

                return {
                    width: e[a + 'Width'],
                    height: e[a + 'Height']
                };
            },

            getUniqueID: function(prefix) {
                return 'prefix_' + Math.floor(Math.random() * (new Date()).getTime());
            },

            // check IE8 mode
            isIE8: function() {
                return isIE8;
            },

            // check IE9 mode
            isIE9: function() {
                return isIE9;
            },

            //check RTL mode
            isRTL: function() {
                return isRTL;
            },

            getAssetsPath: function() {
                return assetsPath;
            },

            setAssetsPath: function(path) {
                assetsPath = path;
            },

            setGlobalImgPath: function(path) {
                globalImgPath = path;
            },

            getGlobalImgPath: function() {
                return assetsPath + globalImgPath;
            },

            setGlobalPluginsPath: function(path) {
                globalPluginsPath = path;
            },

            getGlobalPluginsPath: function() {
                return assetsPath + globalPluginsPath;
            },

            getGlobalCssPath: function() {
                return assetsPath + globalCssPath;
            },

            // get layout color code by color name
            getBrandColor: function(name) {
                if (brandColors[name]) return brandColors[name];
                else return '';
            },

            getResponsiveBreakpoint: function(size) {
                // bootstrap responsive breakpoints
                var sizes = {
                    'xs' : 480,     // extra small
                    'sm' : 768,     // small
                    'md' : 992,     // medium
                    'lg' : 1200     // large
                };

                return sizes[size] ? sizes[size] : 0;
            }
        };

    }();

    Object.freeze(App);

    $(document).ready(function(){
        App.init();
    });

    window.App = App;
})();

function deleteNotificationList() {
    App.ajax({
        url: ajax_url_notifications_delete,
        block: true,
        blockTarget: '.notification-list'
    }, function ( result ) {
        var item, list = $('.notification-list'),
            data = result.data, i, l = data.length, ik;
        if( l ) {

            list.empty();

            for( i = 0; i < l; i++ ) {
                item = data[ i ];

                addNotItem( list, item );
            }

        } else {
            if(act_lang === 'en') {
                list.html('<div class="text-center"><h4>No notifications</h4></div>');
            }
            else if(act_lang === 'cn') {
                list.html('<div class="text-center"><h4>没有通知</h4></div>');
            }
        }

        setNotificationCounterToNull();

        //if( cb ) cb();
    });
}

function clearNotificationList() {

    App.ajax({
        url: ajax_url_notifications_clear,
        block: true,
        blockTarget: '.notification-list'
    }, function ( result ) {
        $('#notification_counter_2').text(0);
        setNotificationCounterToNull();
    });
}

function setNotificationCounterToNull()
{
    //console.log('Incrementing notifs...');
    var act_value = $('#notification_counter').text();
    var act_class = $('#notification_counter').attr('class');
    $('#notification_counter').text(0);
    if(act_class != 'badge badge-default hidden'){
        $('#notification_counter').attr('class', 'badge badge-default hidden');
    }
}
