PageSourceSearch

https://voipawesome.com/assets/js/apps-20200307.js

js voipawesome.com collected 2026-10-02 01:48:10 UTC 79,757 bytes, 1,932 lines download raw bytes

1/*
2 Template Name: Awesome Portal - Responsive Admin Dashboard Template build with Twitter Bootstrap 3.3.5
3    ----------------------------
4        APPS CONTENT TABLE
5    ----------------------------
6
7    <!-- ======== GLOBAL SCRIPT SETTING ======== -->
8    01. Handle Scrollbar
9    02. Handle Sidebar - Menu
10    03. Handle Sidebar - Mobile View Toggle
11    04. Handle Sidebar - Minify / Expand
12    05. Handle Page Load - Fade in
13    06. Handle Panel - Remove / Reload / Collapse / Expand
14    07. Handle Panel - Draggable
15    08. Handle Tooltip & Popover Activation
16    09. Handle Scroll to Top Button Activation
17
18    <!-- ======== Added in V1.2 ======== -->
19    10. Handle Theme & Page Structure Configuration
20    11. Handle Theme Panel Expand
21    12. Handle After Page Load Add Class Function - added in V1.2
22
23    <!-- ======== Added in V1.5 ======== -->
24    13. Handle Save Panel Position Function - added in V1.5
25    14. Handle Draggable Panel Local Storage Function - added in V1.5
26    15. Handle Reset Local Storage - added in V1.5
27    16. Handle Ajax Page Load - added in V1.5
28    17. Handle Ajax Page Load Url - added in V1.5
29    18. Handle Ajax Sidebar Toggle Content - added in V1.5
30    19. Handle Url Hash Change - added in V1.5
31    20. Handle Pace Page Loading Plugins - added in V1.5
32
33    <!-- ======== Added in V1.6 ======== -->
34    21. Handle IE Full Height Page Compatibility - added in V1.6
35    22. Handle Unlimited Nav Tabs - added in V1.6
36
37    <!-- ======== Added in V1.7 ======== -->
38    23. Handle Mobile Sidebar Scrolling Feature - added in V1.7
39
40    <!-- ======== Added in V1.9 ======== -->
41    24. Handle Top Menu - Unlimited Top Menu Render - added in V1.9
42    25. Handle Top Menu - Sub Menu Toggle - added in V1.9
43    26. Handle Top Menu - Mobile Sub Menu Toggle - added in V1.9
44    27. Handle Top Menu - Mobile Top Menu Toggle - added in V1.9
45    28. Handle Clear Sidebar Selection & Hide Mobile Menu - added in V1.9
46
47    <!-- ======== Added by Jambu ======= -->
48    29. Save UI setting to profile with Ajax
49
50    <!-- ======== APPLICATION SETTING ======== -->
51    Application Controller
52*/
53
54/* 01. Handle Scrollbar
55------------------------------------------------ */
56var handleSlimScroll = function() {
57    "use strict";
58    $('[data-scrollbar=true]').each( function() {
59        generateSlimScroll($(this));
60    });
61};
62var generateSlimScroll = function(element) {
63    "use strict";
64    if ($(element).attr('data-init')) {
65        return;
66    }
67    var dataHeight = $(element).attr('data-height');
68        dataHeight = (!dataHeight) ? $(element).height() : dataHeight;
69
70    var scrollBarOption = {
71        height: dataHeight,
72        alwaysVisible: true
73    };
74    if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
75        $(element).css('height', dataHeight);
76        $(element).css('overflow-x','scroll');
77    } else {
78        $(element).slimScroll(scrollBarOption);
79    }
80    $(element).attr('data-init', true);
81};
82
83
84/* 02. Handle Sidebar - Menu
85------------------------------------------------ */
86var handleSidebarMenu = function() {
87    "use strict";
88    $('.sidebar .nav > .has-sub > a').click(function() {
89        var target = $(this).next('.sub-menu');
90        var otherMenu = '.sidebar .nav > li.has-sub > .sub-menu';
91
92        if ($('.page-sidebar-minified').length === 0) {
93            $(otherMenu).not(target).slideUp(250, function() {
94                $(this).closest('li').removeClass('expand');
95            });
96            $(target).slideToggle(250, function() {
97                var targetLi = $(this).closest('li');
98                if ($(targetLi).hasClass('expand')) {
99                    $(targetLi).removeClass('expand');
100                } else {
101                    $(targetLi).addClass('expand');
102                }
103            });
104        }
105    });
106    $('.sidebar .nav > .has-sub .sub-menu li.has-sub > a').click(function() {
107        if ($('.page-sidebar-minified').length === 0) {
108            var target = $(this).next('.sub-menu');
109            $(target).slideToggle(250);
110        }
111    });
112};
113
114
115/* 03. Handle Sidebar - Mobile View Toggle
116------------------------------------------------ */
117var sidebarAjaxOverride = false;
118var set_rightbar_minified = "full";
119var set_rightbar_minified_last = "";
120var timeoutMobileSidebarToggle;
121var delayMobileSidebarToggle = 1000;
122var handleMobileSidebarToggle = function() {
123    "use strict";
124    var sidebarProgress = false;
125    $('.sidebar').bind('click touchstart', function(e) {
126        if ($(e.target).closest('.sidebar').length !== 0) {
127            sidebarProgress = true;
128        } else {
129            sidebarProgress = false;
130            e.stopPropagation();
131        }
132    });
133
134    $(document).bind('click touchstart', function(e) {
135        if ($(e.target).closest('.sidebar').length === 0) {
136            sidebarProgress = false;
137        }
138        if (!e.isPropagationStopped() && sidebarProgress !== true) {
139            if ($('#page-container').hasClass('page-sidebar-toggled')) {
140                sidebarProgress = true;
141                $('#page-container').removeClass('page-sidebar-toggled');
142            }
143            if ($(window).width() <= 767) {
144                if ($('#page-container').hasClass('page-right-sidebar-toggled')) {
145                    sidebarProgress = true;
146                    $('#page-container').removeClass('page-right-sidebar-toggled');
147                }
148            }
149        }
150    });
151
152    $('[data-click=right-sidebar-toggled]').click(function(e) {
153        e.stopPropagation();
154        set_rightbar_minified = "full";
155        var targetContainer = '#page-container';
156        var targetClass = 'page-right-sidebar-collapsed';
157            targetClass = ($(window).width() < 979) ? 'page-right-sidebar-toggled' : targetClass;
158        if ($(targetContainer).hasClass(targetClass)) {
159            $(targetContainer).removeClass(targetClass);
160        } else if (sidebarProgress !== true) {
161            $(targetContainer).addClass(targetClass);
162            set_rightbar_minified = "mini";
163        } else {
164            sidebarProgress = false;
165            $(targetContainer).addClass(targetClass);
166            set_rightbar_minified = "mini";
167        }
168        if ($(window).width() <= 767) {
169            $('#page-container').removeClass('page-sidebar-toggled');
170        }
171        if ((set_rightbar_minified == "full") && (set_rightbar_minified_last != "full")) {
172            PageWithTwoSidebar.init();
173        }
174        if (targetClass == 'page-right-sidebar-collapsed') {
175            if (set_rightbar_minified != set_rightbar_minified_last) {
176                if (timeoutMobileSidebarToggle) { clearTimeout( timeoutMobileSidebarToggle ); }
177                timeoutMobileSidebarToggle = setTimeout(function() {
178                    set_rightbar_minified_last = set_rightbar_minified;
179                    SaveUserSetting("core", "rightbar_minified", set_rightbar_minified);
180                }, delayMobileSidebarToggle);
181            } // END IF set_rightbar_minified_last
182        } // END IF page-right-sidebar-collapsed
183    });
184
185    $('[data-click=sidebar-toggled]').click(function(e) {
186        e.stopPropagation();
187        var sidebarClass = 'page-sidebar-toggled';
188        var targetContainer = '#page-container';
189
190        if ($(targetContainer).hasClass(sidebarClass)) {
191            $(targetContainer).removeClass(sidebarClass);
192        } else if (sidebarProgress !== true) {
193            $(targetContainer).addClass(sidebarClass);
194        } else {
195            $(targetContainer).addClass(sidebarClass);
196            sidebarProgress = false;
197        }
198        if ($(window).width() <= 767) {
199            $('#page-container').removeClass('page-right-sidebar-toggled');
200        }
201    });
202};
203
204
205/* 04. Handle Sidebar - Minify / Expand
206------------------------------------------------ */
207var handleSidebarMinify = function() {
208    "use strict";
209    $('[data-click=sidebar-minify]').click(function(e) {
210        e.preventDefault();
211        var sidebarClass = 'page-sidebar-minified';
212        var targetContainer = '#page-container';
213        var set_navbar_minified = "mini";
214        $('#sidebar [data-scrollbar="true"]').css('margin-top','0');
215        $('#sidebar [data-scrollbar="true"]').removeAttr('data-init');
216        $('#sidebar [data-scrollbar=true]').stop();
217        if ($(targetContainer).hasClass(sidebarClass)) {
218            $(targetContainer).removeClass(sidebarClass);
219            if ($(targetContainer).hasClass('page-sidebar-fixed')) {
220                if ($('#sidebar .slimScrollDiv').length !== 0) {
221                    $('#sidebar [data-scrollbar="true"]').slimScroll({destroy: true});
222                    $('#sidebar [data-scrollbar="true"]').removeAttr('style');
223                }
224                generateSlimScroll($('#sidebar [data-scrollbar="true"]'));
225                $('#sidebar [data-scrollbar=true]').trigger('mouseover');
226            } else if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
227                if ($('#sidebar .slimScrollDiv').length !== 0) {
228                    $('#sidebar [data-scrollbar="true"]').slimScroll({destroy: true});
229                    $('#sidebar [data-scrollbar="true"]').removeAttr('style');
230                }
231                generateSlimScroll($('#sidebar [data-scrollbar="true"]'));
232            }
233            set_navbar_minified = "full";
234        } else {
235            $(targetContainer).addClass(sidebarClass);
236            if(!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
237                if ($(targetContainer).hasClass('page-sidebar-fixed')) {
238                    $('#sidebar [data-scrollbar="true"]').slimScroll({destroy: true});
239                    $('#sidebar [data-scrollbar="true"]').removeAttr('style');
240                }
241                $('#sidebar [data-scrollbar=true]').trigger('mouseover');
242            } else {
243                $('#sidebar [data-scrollbar="true"]').css('margin-top','0');
244                $('#sidebar [data-scrollbar="true"]').css('overflow', 'visible');
245            }
246        }
247        $(window).trigger('resize');
248        SaveUserSetting("core", "navbar_minified", set_navbar_minified);
249    });
250};
251
252
253/* 05. Handle Page Load - Fade in
254------------------------------------------------ */
255var handlePageContentView = function() {
256    "use strict";
257    $.when($('#page-loader').addClass('hide')).done(function() {
258        $('#page-container').addClass('in');
259    });
260};
261
262
263/* 06. Handle Panel - Remove / Reload / Collapse / Expand
264------------------------------------------------ */
265var panelActionRunning = false;
266var handlePanelAction = function() {
267    "use strict";
268
269    if (panelActionRunning) {
270        return false;
271    }
272    panelActionRunning = true;
273
274    // remove
275    $(document).on('hover', '[data-click=panel-remove]', function(e) {
276        $(this).tooltip({
277            title: 'Remove',
278            placement: 'bottom',
279            trigger: 'hover',
280            container: 'body'
281        });
282        $(this).tooltip('show');
283    });
284    $(document).on('click', '[data-click=panel-remove]', function(e) {
285        e.preventDefault();
286        $(this).tooltip('destroy');
287        $(this).closest('.panel').remove();
288    });
289
290    // collapse
291    $(document).on('hover', '[data-click=panel-collapse]', function(e) {
292        $(this).tooltip({
293            title: 'Collapse / Expand',
294            placement: 'bottom',
295            trigger: 'hover',
296            container: 'body'
297        });
298        $(this).tooltip('show');
299    });
300    $(document).on('click', '[data-click=panel-collapse]', function(e) {
301        e.preventDefault();
302        $(this).closest('.panel').find('.panel-body').slideToggle();
303    });
304
305    // reload
306    $(document).on('hover', '[data-click=panel-reload]', function(e) {
307        $(this).tooltip({
308            title: 'Reload',
309            placement: 'bottom',
310            trigger: 'hover',
311            container: 'body'
312        });
313        $(this).tooltip('show');
314    });
315    $(document).on('click', '[data-click=panel-reload]', function(e) {
316        e.preventDefault();
317        var target = $(this).closest('.panel');
318        if (!$(target).hasClass('panel-loading')) {
319            var targetBody = $(target).find('.panel-body');
320            var spinnerHtml = '<div class="panel-loader"><span class="spinner-small"></span></div>';
321            $(target).addClass('panel-loading');
322            $(targetBody).prepend(spinnerHtml);
323            setTimeout(function() {
324                $(target).removeClass('panel-loading');
325                $(target).find('.panel-loader').remove();
326            }, 2000);
327        }
328    });
329
330    // expand
331    $(document).on('hover', '[data-click=panel-expand]', function(e) {
332        $(this).tooltip({
333            title: 'Expand / Compress',
334            placement: 'bottom',
335            trigger: 'hover',
336            container: 'body'
337        });
338        $(this).tooltip('show');
339    });
340    $(document).on('click', '[data-click=panel-expand]', function(e) {
341        e.preventDefault();
342        var target = $(this).closest('.panel');
343        var targetBody = $(target).find('.panel-body');
344        var targetTop = 40;
345        if ($(targetBody).length !== 0) {
346            var targetOffsetTop = $(target).offset().top;
347            var targetBodyOffsetTop = $(targetBody).offset().top;
348            targetTop = targetBodyOffsetTop - targetOffsetTop;
349        }
350
351        if ($('body').hasClass('panel-expand') && $(target).hasClass('panel-expand')) {
352            $('body, .panel').removeClass('panel-expand');
353            $('.panel').removeAttr('style');
354            $(targetBody).removeAttr('style');
355        } else {
356            $('body').addClass('panel-expand');
357            $(this).closest('.panel').addClass('panel-expand');
358
359            if ($(targetBody).length !== 0 && targetTop != 40) {
360                var finalHeight = 40;
361                $(target).find(' > *').each(function() {
362                    var targetClass = $(this).attr('class');
363
364                    if (targetClass != 'panel-heading' && targetClass != 'panel-body') {
365                        finalHeight += $(this).height() + 30;
366                    }
367                });
368                if (finalHeight != 40) {
369                    // Removed by Jambu - Expand to full page... this add empty space for no reason:
370                    //$(targetBody).css('top', finalHeight + 'px');
371                }
372            }
373        }
374        $(window).trigger('resize');
375    });
376};
377
378
379/* 07. Handle Panel - Draggable
380------------------------------------------------ */
381var handleDraggablePanel = function() {
382    "use strict";
383    var target = $('.panel').parent('[class*=col]');
384    var targetHandle = '.panel-heading';
385    var connectedTarget = '.row > [class*=col]';
386
387    $(target).sortable({
388        handle: targetHandle,
389        connectWith: connectedTarget,
390        stop: function(event, ui) {
391            ui.item.find('.panel-title').append('<i class="fa fa-circle-o-notch fa-spin m-l-5" data-id="title-spinner"></i>');
392            handleSavePanelPosition(ui.item);
393        }
394    });
395};
396
397
398/* 08. Handle Tooltip & Popover Activation
399------------------------------------------------ */
400var handelTooltipPopoverActivation = function() {
401    "use strict";
402    $('[data-toggle=tooltip]').tooltip();
403};
404
405
406/* 09. Handle Scroll to Top Button Activation
407------------------------------------------------ */
408var handleScrollToTopButton = function() {
409    "use strict";
410    $(document).scroll( function() {
411        var totalScroll = $(document).scrollTop();
412
413        if (totalScroll >= 200) {
414            $('[data-click=scroll-top]').addClass('in');
415        } else {
416            $('[data-click=scroll-top]').removeClass('in');
417        }
418    });
419
420    $('[data-click=scroll-top]').click(function(e) {
421        e.preventDefault();
422        $('html, body').animate({
423            scrollTop: $("body").offset().top
424        }, 500);
425    });
426};
427
428
429/* 10. Handle Theme & Page Structure Configuration - added in V1.2
430------------------------------------------------ */
431var handleThemePageStructureControl = function() {
432    "use strict";
433    // COOKIE - Theme File Setting
434    if ($.cookie && $.cookie('theme')) {
435        if ($('.theme-list').length !== 0) {
436            $('.theme-list [data-theme]').closest('li').removeClass('active');
437            $('.theme-list [data-theme="'+ $.cookie('theme') +'"]').closest('li').addClass('active');
438        }
439        var cssFileSrc = 'assets/css/theme/' + $.cookie('theme') + '.css';
440        $('#theme').attr('href', cssFileSrc);
441    }
442
443    // COOKIE - Sidebar Styling Setting
444    if ($.cookie && $.cookie('sidebar-styling')) {
445        if ($('.sidebar').length !== 0 && $.cookie('sidebar-styling') == 'grid') {
446            $('.sidebar').addClass('sidebar-grid');
447            $('[name=sidebar-styling] option[value="2"]').prop('selected', true);
448        }
449    }
450
451    // COOKIE - Header Setting
452    if ($.cookie && $.cookie('header-styling')) {
453        if ($('.header').length !== 0 && $.cookie('header-styling') == 'navbar-inverse') {
454            $('.header').addClass('navbar-inverse');
455            $('[name=header-styling] option[value="2"]').prop('selected', true);
456        }
457    }
458
459    // COOKIE - Gradient Setting
460    if ($.cookie && $.cookie('content-gradient')) {
461        if ($('#page-container').length !== 0 && $.cookie('content-gradient') == 'enabled') {
462            $('#page-container').addClass('gradient-enabled');
463            $('[name=content-gradient] option[value="2"]').prop('selected', true);
464        }
465    }
466
467    // COOKIE - Content Styling Setting
468    if ($.cookie && $.cookie('content-styling')) {
469        if ($('body').length !== 0 && $.cookie('content-styling') == 'black') {
470            $('body').addClass('flat-black');
471            $('[name=content-styling] option[value="2"]').prop('selected', true);
472        }
473    }
474
475    // THEME - theme selection
476    $('.theme-list [data-theme]').click(function() {
477        var cssFileSrc = 'assets/css/theme/' + $(this).attr('data-theme') + '.css';
478        $('#theme').attr('href', cssFileSrc);
479        $('.theme-list [data-theme]').not(this).closest('li').removeClass('active');
480        $(this).closest('li').addClass('active');
481        $.cookie('theme', $(this).attr('data-theme'));
482    });
483
484    // HEADER - inverse or default
485    $('.theme-panel [name=header-styling]').on('change', function() {
486        var targetClassAdd = ($(this).val() == 1) ? 'navbar-default' : 'navbar-inverse';
487        var targetClassRemove = ($(this).val() == 1) ? 'navbar-inverse' : 'navbar-default';
488        $('#header').removeClass(targetClassRemove).addClass(targetClassAdd);
489        $.cookie('header-styling',targetClassAdd);
490    });
491
492    // SIDEBAR - grid or default
493    $('.theme-panel [name=sidebar-styling]').on('change', function() {
494        if ($(this).val() == 2) {
495            $('#sidebar').addClass('sidebar-grid');
496            $.cookie('sidebar-styling', 'grid');
497        } else {
498            $('#sidebar').removeClass('sidebar-grid');
499            $.cookie('sidebar-styling', 'default');
500        }
501    });
502
503    // CONTENT - gradient enabled or disabled
504    $('.theme-panel [name=content-gradient]').on('change', function() {
505        if ($(this).val() == 2) {
506            $('#page-container').addClass('gradient-enabled');
507            $.cookie('content-gradient', 'enabled');
508        } else {
509            $('#page-container').removeClass('gradient-enabled');
510            $.cookie('content-gradient', 'disabled');
511        }
512    });
513
514    // CONTENT - default or black
515    $(document).on('change', '.theme-panel [name=content-styling]', function() {
516        if ($(this).val() == 2) {
517            $('body').addClass('flat-black');
518            $.cookie('content-styling', 'black');
519        } else {
520            $('body').removeClass('flat-black');
521            $.cookie('content-styling', 'default');
522        }
523    });
524
525    // SIDEBAR - fixed or default
526    $(document).on('change', '.theme-panel [name=sidebar-fixed]', function() {
527        if ($(this).val() == 1) {
528            if ($('.theme-panel [name=header-fixed]').val() == 2) {
529                alert('Default Header with Fixed Sidebar option is not supported. Proceed with Fixed Header with Fixed Sidebar.');
530                $('.theme-panel [name=header-fixed] option[value="1"]').prop('selected', true);
531                $('#header').addClass('navbar-fixed-top');
532                $('#page-container').addClass('page-header-fixed');
533            }
534            $('#page-container').addClass('page-sidebar-fixed');
535            if (!$('#page-container').hasClass('page-sidebar-minified')) {
536                generateSlimScroll($('.sidebar [data-scrollbar="true"]'));
537            }
538        } else {
539            $('#page-container').removeClass('page-sidebar-fixed');
540            if ($('.sidebar .slimScrollDiv').length !== 0) {
541                if ($(window).width() <= 979) {
542                    $('.sidebar').each(function() {
543                        if (!($('#page-container').hasClass('page-with-two-sidebar') && $(this).hasClass('sidebar-right'))) {
544                            $(this).find('.slimScrollBar').remove();
545                            $(this).find('.slimScrollRail').remove();
546                            $(this).find('[data-scrollbar="true"]').removeAttr('style');
547                            var targetElement = $(this).find('[data-scrollbar="true"]').parent();
548                            var targetHtml = $(targetElement).html();
549                            $(targetElement).replaceWith(targetHtml);
550                        }
551                    });
552                } else if ($(window).width() > 979) {
553                    $('.sidebar [data-scrollbar="true"]').slimScroll({destroy: true});
554                    $('.sidebar [data-scrollbar="true"]').removeAttr('style');
555                }
556            }
557            if ($('#page-container .sidebar-bg').length === 0) {
558                $('#page-container').append('<div class="sidebar-bg"></div>');
559            }
560        }
561    });
562
563    // HEADER - fixed or default
564    $(document).on('change', '.theme-panel [name=header-fixed]', function() {
565        if ($(this).val() == 1) {
566            $('#header').addClass('navbar-fixed-top');
567            $('#page-container').addClass('page-header-fixed');
568            $.cookie('header-fixed', true);
569        } else {
570            if ($('.theme-panel [name=sidebar-fixed]').val() == 1) {
571                alert('Default Header with Fixed Sidebar option is not supported. Proceed with Default Header with Default Sidebar.');
572                $('.theme-panel [name=sidebar-fixed] option[value="2"]').prop('selected', true);
573                $('#page-container').removeClass('page-sidebar-fixed');
574                if ($('#page-container .sidebar-bg').length === 0) {
575                    $('#page-container').append('<div class="sidebar-bg"></div>');
576                }
577            }
578            $('#header').removeClass('navbar-fixed-top');
579            $('#page-container').removeClass('page-header-fixed');
580            $.cookie('header-fixed', false);
581        }
582    });
583};
584
585
586/* 11. Handle Theme Panel Expand - added in V1.2
587------------------------------------------------ */
588var handleThemePanelExpand = function() {
589    "use strict";
590    $(document).on('click', '[data-click="theme-panel-expand"]', function() {
591        var targetContainer = '.theme-panel';
592        var targetClass = 'active';
593        if ($(targetContainer).hasClass(targetClass)) {
594            $(targetContainer).removeClass(targetClass);
595        } else {
596            $(targetContainer).addClass(targetClass);
597        }
598    });
599};
600
601
602/* 12. Handle After Page Load Add Class Function - added in V1.2
603------------------------------------------------ */
604var handleAfterPageLoadAddClass = function() {
605    "use strict";
606    if ($('[data-pageload-addclass]').length !== 0) {
607        $(window).load(function() {
608            $('[data-pageload-addclass]').each(function() {
609                var targetClass = $(this).attr('data-pageload-addclass');
610                $(this).addClass(targetClass);
611            });
612        });
613    }
614};
615
616
617/* 13. Handle Save Panel Position Function - added in V1.5
618------------------------------------------------ */
619var handleSavePanelPosition = function(element) {
620    "use strict";
621    if ($('.ui-sortable').length !== 0) {
622        var newValue = [];
623        var index = 0;
624        $.when($('.ui-sortable').each(function() {
625            var panelSortableElement = $(this).find('[data-sortable-id]');
626            if (panelSortableElement.length !== 0) {
627                var columnValue = [];
628                $(panelSortableElement).each(function() {
629                    var targetSortId = $(this).attr('data-sortable-id');
630                    columnValue.push({id: targetSortId});
631                });
632                newValue.push(columnValue);
633            } else {
634                newValue.push([]);
635            }
636            index++;
637        })).done(function() {
638            var targetPage = window.location.href;
639                targetPage = targetPage.split('?');
640                targetPage = targetPage[0];
641            localStorage.setItem(targetPage, JSON.stringify(newValue));
642            $(element).find('[data-id="title-spinner"]').delay(500).fadeOut(500, function() {
643                $(this).remove();
644            });
645        });
646    }
647};
648
649
650/* 14. Handle Draggable Panel Local Storage Function - added in V1.5
651------------------------------------------------ */
652var handleLocalStorage = function() {
653    "use strict";
654    if (typeof(Storage) !== 'undefined' && typeof(localStorage) !== 'undefined') {
655        var targetPage = window.location.href;
656            targetPage = targetPage.split('?');
657            targetPage = targetPage[0];
658        var panelPositionData = localStorage.getItem(targetPage);
659
660        if (panelPositionData) {
661            panelPositionData = JSON.parse(panelPositionData);
662            var i = 0;
663            $('.panel').parent('[class*="col-"]').each(function() {
664                var storageData = panelPositionData[i];
665                var targetColumn = $(this);
666                if (storageData) {
667                    $.each(storageData, function(index, data) {
668                        var targetId = $('[data-sortable-id="'+ data.id +'"]').not('[data-init="true"]');
669                        if ($(targetId).length !== 0) {
670                            var targetHtml = $(targetId).clone();
671                            $(targetId).remove();
672                            $(targetColumn).append(targetHtml);
673                            $('[data-sortable-id="'+ data.id +'"]').attr('data-init','true');
674                        }
675                    });
676                }
677                i++;
678            });
679        }
680    } else {
681        alert('Your browser is not supported with the local storage');
682    }
683};
684
685
686/* 15. Handle Reset Local Storage - added in V1.5
687------------------------------------------------ */
688var handleResetLocalStorage = function() {
689    "use strict";
690    $(document).on('click', '[data-click=reset-local-storage]', function(e) {
691        e.preventDefault();
692
693        var targetModalHtml = ''+
694        '<div class="modal fade" data-modal-id="reset-local-storage-confirmation">'+
695        '    <div class="modal-dialog">'+
696        '        <div class="modal-content">'+
697        '            <div class="modal-header">'+
698        '                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>'+
699        '                <h4 class="modal-title"><i class="fa fa-circle-o-notch m-r-5"></i> Reset Local Storage Confirmation</h4>'+
700        '            </div>'+
701        '            <div class="modal-body">'+
702        '                <div class="alert alert-info m-b-0">Would you like to RESET all your saved widgets and clear Local Storage?</div>'+
703        '            </div>'+
704        '            <div class="modal-footer">'+
705        '                <a href="javascript:;" class="btn btn-sm btn-white" data-dismiss="modal"><i class="fa fa-close"></i> No</a>'+
706        '                <a href="javascript:;" class="btn btn-sm btn-inverse" data-click="confirm-reset-local-storage"><i class="fa fa-check"></i> Yes</a>'+
707        '            </div>'+
708        '        </div>'+
709        '    </div>'+
710        '</div>';
711        $('body').append(targetModalHtml);
712        $('[data-modal-id="reset-local-storage-confirmation"]').modal('show');
713    });
714    $(document).on('hidden.bs.modal', '[data-modal-id="reset-local-storage-confirmation"]', function(e) {
715        $('[data-modal-id="reset-local-storage-confirmation"]').remove();
716    });
717    $(document).on('click', '[data-click=confirm-reset-local-storage]', function(e) {
718        e.preventDefault();
719        var localStorageName = window.location.href;
720            localStorageName = localStorageName.split('?');
721            localStorageName = localStorageName[0];
722        localStorage.removeItem(localStorageName);
723        location.reload();
724    });
725}; // end function handleResetLocalStorage
726
727
728/* 16. Handle Ajax Page Load - added in V1.5
729------------------------------------------------ */
730var default_content = '<div class="p-t-40 p-b-40 text-center f-s-20 content"><i class="fa fa-warning fa-lg text-muted m-r-5"></i> <span class="f-w-600 text-inverse">Error 404! Page not found.</span></div>';
731var hashUrl = String(window.location.hash);
732var fullUrl = String(window.location.href);
733var pathName = String(window.location.pathname);
734var targetOutputType = "html";
735var targetOutputFormat = "full";
736var lastTargetMod = "";
737var targetMod = "";
738var lastTargetOp = "";
739var targetOp = "";
740
741var getTargetMod = function( hash ) {
742    "use strict";
743    // Update globals
744    hashUrl = (hash) ? hash : String(window.location.hash);
745    fullUrl = String(window.location.href);
746    domainUrl = get_url_domain();
747    pathName = String(window.location.pathname);
748    //console.log("fullUrl: "+fullUrl+", pathName: "+pathName+", hashUrl: "+hashUrl);
749
750    // Define locals
751    var newMod = "modules";
752    if (pathName && (pathName.substring(0, 3) == "/m/")) {
753      pathName = pathName.substring(2);
754    } else if (pathName && (pathName.substring(0, 3) == "/o/")) {
755      pathName = pathName.substring(2);
756    } else if (pathName && (pathName.substring(0, 3) == "/f/")) {
757      pathName = pathName.substring(2);
758    } // remove /m/ path
759    var modAjaxIndex = hashUrl.indexOf('#ajax/');
760    var modModIndex = fullUrl.indexOf('module=');
761    var modPathIndex = pathName.indexOf('/');
762
763    // Find the module
764    if ((hashUrl != "") && (modAjaxIndex >= 0)) {
765      newMod = hashUrl.substring((modAjaxIndex + 6));
766    } else if ((fullUrl != "") && (modModIndex >= 0)) {
767      newMod = fullUrl.substring((modModIndex + 7));
768    } else if ((pathName != "") && (modPathIndex >= 0)) {
769      newMod = pathName.substring(modPathIndex + 1);
770    } // END IF modAjaxIndex
771
772    modModIndex = newMod.indexOf('&');
773    if (modModIndex > 0) {
774      newMod = newMod.substring(0, modModIndex);
775    } // END IF modModIndex
776
777    modPathIndex = newMod.indexOf('/');
778    if (modPathIndex > 0) {
779      newMod = newMod.substring(0, modPathIndex);
780    } // END IF modPathIndex
781
782    if (newMod == "") { newMod = "modules"; }
783    //console.log(newMod);
784    return newMod;
785}; // end function getTargetMod
786
787var handleCheckActiveSession = function( checkTargetMod, dataJson ) {
788    "use strict";
789    //console.log("handleCheckActiveSession -> checkTargetMod", checkTargetMod);
790    //console.log("handleCheckActiveSession -> dataJson", dataJson);
791    var redirectMod = "login";
792    if ((checkTargetMod != "") && (dataJson != null) && (typeof dataJson == 'object')) {
793        if ((typeof dataJson.module_returned == 'string') && (dataJson.module_returned == checkTargetMod)) {
794            return true;
795        } else if ((typeof dataJson.module_returned == 'string') && (dataJson.module_returned != "")) {
796            if ((typeof dataJson.access_user != 'undefined') && (dataJson.access_user != "guest") &&
797                (typeof dataJson.login_required != 'undefined') && (dataJson.login_required === true) &&
798                (typeof dataJson.user_is_valid != 'undefined') && (dataJson.user_is_valid === false)) {
799                redirectMod = "modules";
800            }
801            //console.log("handleCheckActiveSession -> dataJson.module_returned [" + dataJson.module_returned + "] != checkTargetMod [" + checkTargetMod + "]");
802            if (checkTargetMod != redirectMod) { App.reloadPage( redirectMod ); }
803            return false;
804        } else if (typeof dataJson.error_code == 'undefined') {
805            return true;
806        } else {
807            if ((checkTargetMod != "modules") && (checkTargetMod != "login") && (checkTargetMod != "forgot-password") && (checkTargetMod != "404")) {
808                //console.log("handleCheckActiveSession ->
808 ERROR : Unexpected dataJson");
809                if (checkTargetMod != redirectMod) { App.reloadPage( redirectMod ); }
810                return false;
811            } else {
812                return true;
813            }
814        } // END IF dataJson.module_requested
815    } else {
816        //console.log("handleCheckActiveSession -> ERROR : Unexpected checkTargetMod OR dataJson");
817        if ($("#login_form").length > 0) {
818            checkTargetMod = "login";
819        } // end if login
820        if ((checkTargetMod != "modules") && (checkTargetMod != "login") && (checkTargetMod != "forgot-password") && (checkTargetMod != "404")) {
821            if (checkTargetMod != redirectMod) { App.reloadPage( redirectMod ); }
822        } else {
823            $('#ajax-content').html(default_content);
824        }
825        return false;
826    } // END IF checkTargetMod dataJson
827}; // end function handleCheckActiveSession
828
829var handleLoadPage = function( hashMod ) {
830    "use strict";
831    /// Check User is still logged in first
832    var checkTargetMod = hashMod;
833    if ((hashMod == "modules") || (hashMod == "login")) {
834        if ( $("#login_form").length ) {
835            hashMod = "login";
836        } else {
837            hashMod = "modules";
838        }
839    } // END IF login | modules
840
841    var checkUrl = "/o/json/" + checkTargetMod;
842    //console.log("handleLoadPage -> hashMod = " + hashMod);
843    //console.log("handleLoadPage -> checkTargetMod = " + checkTargetMod);
844    //console.log("handleLoadPage -> checkUrl = " + checkUrl);
845    var date = new Date();
846    checkUserPrefersColorScheme();
847    var dataSend = { 'now': date.getTime(), 'action': 'check_login', 'color-mode': userPrefersColorScheme };
848    var dataPost = $.param(dataSend);
849    $('#ajax-content').html('<div id="content" class="p-t-20 p-b-20 fnt96"><center><i class="fa fa-circle-o-notch fa-spin"></i></center></div>');
850    setPageMinHeight( "content" );
851
852    $.ajax({
853        cache: false,
854        type: 'POST',
855        url: checkUrl,
856        dataType: 'json',
857        data: dataPost,
858        success: function( dataJson ) {
859            if (handleCheckActiveSession( checkTargetMod, dataJson)) {
860                //console.log("handleLoadPage -> ajax.success -> handleCheckActiveSession -> hashMod = " + hashMod);
861                handleLoadModule( hashMod );
862            } // end if handleCheckActiveSession
863        }, // end function ajax.success
864        error: function(jqXHR, textStatus, errorThrown) {
865            console.log("Ajax Return Error, loading default content", errorThrown);
866            $('#ajax-content').html(default_content);
867        } // end function ajax.error
868    }); // end ajax
869}; // end function handleLoadPage
870
871var handleLoadModule = function( hashMod ) {
872    "use strict";
873    Pace.restart();
874    var targetUrl = '/f/content/' + hashMod;
875    var date = new Date();
876    checkUserPrefersColorScheme();
877    var dataSend = { 'now': date.getTime(), 'color-mode': userPrefersColorScheme };
878    var dataPost = $.param(dataSend);
879
880    $('.jvectormap-label, .jvector-label, .AutoFill_border, #gritter-notice-wrapper, .ui-autocomplete, .colorpicker, .FixedHeader_Header, .FixedHeader_Cloned .lightboxOverlay, .lightbox').remove();
881    $.ajax({
882        type: 'POST',
883        url: targetUrl,     //module content
884        dataType: 'html',   //expect html to be returned
885        data: dataPost,
886        success: function(data) {
887            //console.log("handleLoadModule -> ajax.success [" + hashMod + "]");
888            hashUrl = '#ajax/' + hashMod;
889            var thisSidebarLi = $('.sidebar').find('a[href="' + hashUrl + '"][data-toggle=ajax]')[0];
890            sidebarActiveModule( thisSidebarLi );
891            $('#ajax-content').html(data);
892            if ($('#content').length > 0) { handlePageHeight( 'content' ); }
893            $('html, body').animate({
894                scrollTop: $("body").offset().top
895            }, 250);
896        }, // end function ajax.success
897        error: function(jqXHR, textStatus, errorThrown) {
898            console.log("Ajax Return Error, loading default content", errorThrown);
899            $('#ajax-content').html(default_content);
900        } // end function ajax.error
901    }); // end ajax
902}; // end function handleLoadModule
903
904
905/* 17. Handle Ajax Page Load Url - added in V1.5
906------------------------------------------------ */
907var handleCheckPageLoadUrl = function( hash ) {
908    "use strict";
909    //console.log(hash);
910    hashUrl = (hash) ? hash : '#ajax/modules';
911    targetMod = getTargetMod();
912    //console.log(targetMod);
913    hash = '#ajax/' + targetMod;
914    if (hash === '') {
915        console.log("Error no hash, loading default content", targetMod);
916        $('#ajax-content').html(default_content);
917    } else {
918        handleLoadPage( targetMod );
919    } // end if hash
920}; // end function handleCheckPageLoadUrl
921
922
923/* 18. Handle Ajax Sidebar Toggle Content - added in V1.5
924------------------------------------------------ */
925var handleSidebarAjaxClick = function( ) {
926    "use strict";
927    $('.sidebar [data-toggle=ajax]').click(function() {
928        sidebarActiveModule(this);
929    });
930}; // end function handleSidebarAjaxClick
931
932var sidebarActiveModule = function( element ) {
933    "use strict";
934    //console.log( 'sidebarActiveModule.element', element );
935    var targetLi = $(element).closest('li');
936    var targetParentLi = $(element).parents();
937    $('.sidebar li').not('.sidebar-right li').not(targetLi).not(targetParentLi).removeClass('active');
938    $(targetLi).addClass('active');
939    $(targetParentLi).addClass('active');
940}; // end function sidebarActiveModule
941
942
943/* 19. Handle Url Hash Change - added in V1.5
944------------------------------------------------ */
945var handleHashChange = function() {
946    "use strict";
947    $(window).bind('hashchange', function() {
948        if (window.location.hash) {
949            hashUrl = window.location.hash;
950            targetMod = getTargetMod();
951            handleLoadPage( targetMod );
952        } else {
953            hashUrl = "#ajax/modules";
954            handleLoadPage( "modules" );
955        }
956    });
957}; // end function handleHashChange
958
959
960/* 20. Handle Pace Page Loading Plugins - added in V1.5
961------------------------------------------------ */
962var handlePaceLoadingPlugins = function() {
963    "use strict";
964    Pace.on('hide', function(){
965        $('.pace').addClass('hide');
966    });
967}; // end function handlePaceLoadingPlugins
968
969
970/* 21. Handle IE Full Height Page Compatibility - added in V1.6
971------------------------------------------------ */
972var handleIEFullHeightContent = function() {
973    "use strict";
974    var userAgent = window.navigator.userAgent;
975    var msie = userAgent.indexOf("MSIE ");
976
977    if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {
978        $('.vertical-box-row [data-scrollbar="true"][data-height="100%"]').each(function() {
979            var targetRow = $(this).closest('.vertical-box-row');
980            var targetHeight = $(targetRow).height();
981            $(targetRow).find('.vertical-box-cell').height(targetHeight);
982        });
983    }
984}; // end function handleIEFullHeightContent
985
986
987/* 22. Handle Unlimited Nav Tabs - added in V1.6
988------------------------------------------------ */
989var enableHandlePageLoadTabFocus = false;
990var handleUnlimitedTabsRender = function() {
991    "use strict";
992    // handle tab next button click action
993    $('[data-click="next-tab"]').on('click', function(e) {
994        e.preventDefault();
995        handleTabButtonAction(this,'next');
996    });
997    // handle tab prev button click action
998    $('[data-click="prev-tab"]').on('click', function(e) {
999        e.preventDefault();
1000        handleTabButtonAction(this,'prev');
1001
1002    });
1003    // handle unlimited tabs responsive setting
1004    enableHandlePageLoadTabFocus = true;
1005    handlePageLoadTabFocus();
1006}; // end function handleUnlimitedTabsRender
1007
1008// function handle tab overflow scroll width
1009var handleTabOverflowScrollWidth = function(obj, animationSpeed) {
1010        var marginLeft = parseInt($(obj).css('margin-left'));
1011        var viewWidth = $(obj).width();
1012        var prevWidth = $(obj).find('li.active').width();
1013        var speed = (animationSpeed > -1) ? animationSpeed : 150;
1014        var fullWidth = 0;
1015
1016        $(obj).find('li.active').prevAll().each(function() {
1017            prevWidth += $(this).width();
1018        });
1019
1020        $(obj).find('li').each(function() {
1021            fullWidth += $(this).width();
1022        });
1023
1024        if (prevWidth >= viewWidth) {
1025            var finalScrollWidth = prevWidth - viewWidth;
1026            if (fullWidth != prevWidth) {
1027                finalScrollWidth += 40;
1028            }
1029            $(obj).find('.nav.nav-tabs').animate({ marginLeft: '-' + finalScrollWidth + 'px'}, speed);
1030        }
1031
1032        if (prevWidth != fullWidth && fullWidth >= viewWidth) {
1033            $(obj).addClass('overflow-right');
1034        } else {
1035            $(obj).removeClass('overflow-right');
1036        }
1037
1038        if (prevWidth >= viewWidth && fullWidth >= viewWidth) {
1039            $(obj).addClass('overflow-left');
1040        } else {
1041            $(obj).removeClass('overflow-left');
1042        }
1043}; // end function handleTabOverflowScrollWidth
1044
1045// function handle tab button action - next / prev
1046var handleTabButtonAction = function(element, direction) {
1047    var obj = $(element).closest('.tab-overflow');
1048    var marginLeft = parseInt($(obj).find('.nav.nav-tabs').css('margin-left'));
1049    var containerWidth = $(obj).width();
1050    var totalWidth = 0;
1051    var finalScrollWidth = 0;
1052    var widthLeft = 0;
1053
1054    $(obj).find('li').each(function() {
1055        if (!$(this).hasClass('next-button') && !$(this).hasClass('prev-button')) {
1056            totalWidth += $(this).width();
1057        }
1058    });
1059
1060    switch (direction) {
1061        case 'next':
1062            widthLeft = totalWidth + marginLeft - containerWidth;
1063            if (widthLeft <= containerWidth) {
1064                finalScrollWidth = widthLeft - marginLeft;
1065                setTimeout(function() {
1066                    $(obj).removeClass('overflow-right');
1067                }, 150);
1068            } else {
1069                finalScrollWidth = containerWidth - marginLeft - 80;
1070            }
1071
1072            if (finalScrollWidth != 0) {
1073                $(obj).find('.nav.nav-tabs').animate({ marginLeft: '-' + finalScrollWidth + 'px'}, 150, function() {
1074                    $(obj).addClass('overflow-left');
1075                });
1076            }
1077            break;
1078        case 'prev':
1079            widthLeft = -marginLeft;
1080            if (widthLeft <= containerWidth) {
1081                $(obj).removeClass('overflow-left');
1082                finalScrollWidth = 0;
1083            } else {
1084                finalScrollWidth = widthLeft - containerWidth + 80;
1085            }
1086            $(obj).find('.nav.nav-tabs').animate({ marginLeft: '-' + finalScrollWidth + 'px'}, 150, function() {
1087                $(obj).addClass('overflow-right');
1088            });
1089            break;
1090    } // end switch direction
1091}; // end function handleTabButtonAction
1092
1093// handle page load active tab focus
1094var handlePageLoadTabFocus = function() {
1095    $('.tab-overflow').each(function() {
1096        var targetWidth = $(this).width();
1097        var targetInnerWidth = 0;
1098        var targetTab = $(this);
1099        var scrollWidth = targetWidth;
1100
1101        $(targetTab).find('li').each(function() {
1102            var targetLi = $(this);
1103            targetInnerWidth += $(targetLi).width();
1104            if ($(targetLi).hasClass('active') && targetInnerWidth > targetWidth) {
1105                scrollWidth -= targetInnerWidth;
1106            }
1107        });
1108
1109        handleTabOverflowScrollWidth(this, 0);
1110    });
1111}; // end function handlePageLoadTabFocus
1112
1113
1114/* 23. Handle Mobile Sidebar Scrolling Feature - added in V1.7
1115------------------------------------------------ */
1116var handleMobileSidebar = function() {
1117    "use strict";
1118    if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
1119        if ($('#page-container').hasClass('page-sidebar-minified')) {
1120            $('#sidebar [data-scrollbar="true"]').css('overflow', 'visible');
1121            $('.page-sidebar-minified #sidebar [data-scrollbar="true"]').slimScroll({destroy: true});
1122            $('.page-sidebar-minified #sidebar [data-scrollbar="true"]').removeAttr('style');
1123            $('.page-sidebar-minified #sidebar [data-scrollbar=true]').trigger('mouseover');
1124        }
1125    }
1126
1127    var oriTouch = 0;
1128    $('.page-sidebar-minified .sidebar [data-scrollbar=true] a').bind('touchstart', function(e) {
1129        var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
1130        var touchVertical = touch.pageY;
1131        oriTouch = touchVertical - parseInt($(this).closest('[data-scrollbar=true]').css('margin-top'));
1132    });
1133
1134    $('.page-sidebar-minified .sidebar [data-scrollbar=true] a').bind('touchmove',function(e){
1135        e.preventDefault();
1136        if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
1137            var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
1138            var touchVertical = touch.pageY;
1139            var elementTop = touchVertical - oriTouch;
1140
1141            $(this).closest('[data-scrollbar=true]').css('margin-top', elementTop + 'px');
1142        }
1143    });
1144
1145    $('.page-sidebar-minified .sidebar [data-scrollbar=true] a').bind('touchend', function(e) {
1146        var targetScrollBar = $(this).closest('[data-scrollbar=true]');
1147        var windowHeight = $(window).height();
1148        var sidebarTopPosition = parseInt($('#sidebar').css('padding-top'));
1149        var sidebarContainerHeight = $('#sidebar').height();
1150        oriTouch = $(targetScrollBar).css('margin-top');
1151
1152        var sidebarHeight = sidebarTopPosition;
1153        $('.sidebar').not('.sidebar-right').find('.nav').each(function() {
1154            sidebarHeight += $(this).height();
1155        });
1156        var finalHeight = -parseInt(oriTouch) + $('.sidebar').height();
1157        var finalMargin = 0;
1158        if (finalHeight >= sidebarHeight && windowHeight <= sidebarHeight && sidebarContainerHeight <= sidebarHeight) {
1159            finalMargin = windowHeight - sidebarHeight - 20;
1160            $(targetScrollBar).animate({marginTop: finalMargin + 'px'});
1161        } else if (parseInt(oriTouch) >= 0 || sidebarContainerHeight >= sidebarHeight) {
1162            $(targetScrollBar).animate({marginTop: '0px'});
1163        } else {
1164            finalMargin = oriTouch;
1165            $(targetScrollBar).animate({marginTop: finalMargin + 'px'});
1166        }
1167    });
1168}; // end function handleMobileSidebar
1169
1170
1171/* 24. Handle Top Menu - Unlimited Top Menu Render - added in V1.9
1172------------------------------------------------ */
1173var enableHandlePageLoadMenuFocus = false;
1174var handleUnlimitedTopMenuRender = function() {
1175    "use strict";
1176    // function handle menu button action - next / prev
1177
1178    // handle menu next button click action
1179    $('[data-click="next-menu"]').on('click', function(e) {
1180        e.preventDefault();
1181        handleMenuButtonAction(this,'next');
1182    });
1183
1184    // handle menu prev button click action
1185    $('[data-click="prev-menu"]').on('click', function(e) {
1186        e.preventDefault();
1187        handleMenuButtonAction(this,'prev');
1188
1189    });
1190
1191    // handle unlimited menu responsive setting
1192    enableHandlePageLoadMenuFocus = true;
1193    handlePageLoadMenuFocus();
1194}; // end function handleUnlimitedTopMenuRender
1195
1196var handleMenuButtonAction = function(element, direction) {
1197    var obj = $(element).closest('.nav');
1198    var marginLeft = parseInt($(obj).css('margin-left'));
1199    var containerWidth = $('.top-menu').width() - 88;
1200    var totalWidth = 0;
1201    var finalScrollWidth = 0;
1202    var widthLeft = 0;
1203
1204    $(obj).find('li').each(function() {
1205        if (!$(this).hasClass('menu-control')) {
1206            totalWidth += $(this).width();
1207        }
1208    });
1209
1210    switch (direction) {
1211        case 'next':
1212            widthLeft = totalWidth + marginLeft - containerWidth;
1213            if (widthLeft <= containerWidth) {
1214                finalScrollWidth = widthLeft - marginLeft + 128;
1215                setTimeout(function() {
1216                    $(obj).find('.menu-control.menu-control-right').removeClass('show');
1217                }, 150);
1218            } else {
1219                finalScrollWidth = containerWidth - marginLeft - 128;
1220            }
1221
1222            if (finalScrollWidth != 0) {
1223                $(obj).animate({ marginLeft: '-' + finalScrollWidth + 'px'}, 150, function() {
1224                    $(obj).find('.menu-control.menu-control-left').addClass('show');
1225                });
1226            }
1227            break;
1228        case 'prev':
1229            widthLeft = -marginLeft;
1230            if (widthLeft <= containerWidth) {
1231                $(obj).find('.menu-control.menu-control-left').removeClass('show');
1232                finalScrollWidth = 0;
1233            } else {
1234                finalScrollWidth = widthLeft - containerWidth + 88;
1235            }
1236            $(obj).animate({ marginLeft: '-' + finalScrollWidth + 'px'}, 150, function() {
1237                $(obj).find('.menu-control.menu-control-right').addClass('show');
1238            });
1239            break;
1240    } // end switch direction
1241}; // end function handleMenuButtonAction
1242
1243// handle page load active menu focus
1244var handlePageLoadMenuFocus = function() {
1245    var targetMenu = $('.top-menu .nav');
1246    var targetList = $('.top-menu .nav > li');
1247    var targetActiveList = $('.top-menu .nav > li.active');
1248    var targetContainer = $('.top-menu');
1249    var marginLeft = parseInt($(targetMenu).css('margin-left'));
1250    var viewWidth = $(targetContainer).width() - 128;
1251    var prevWidth = $('.top-menu .nav > li.active').width();
1252    var speed = 0;
1253    var fullWidth = 0;
1254
1255    $(targetActiveList).prevAll().each(function() {
1256        prevWidth += $(this).width();
1257    });
1258
1259    $(targetList).each(function() {
1260        if (!$(this).hasClass('menu-control')) {
1261            fullWidth += $(this).width();
1262        }
1263    });
1264
1265    if (prevWidth >= viewWidth) {
1266        var finalScrollWidth = prevWidth - viewWidth + 128;
1267        $(targetMenu).animate({ marginLeft: '-' + finalScrollWidth + 'px'}, speed);
1268    }
1269
1270    if (prevWidth != fullWidth && fullWidth >= viewWidth) {
1271        $(targetMenu).find('.menu-control.menu-control-right').addClass('show');
1272    } else {
1273        $(targetMenu).find('.menu-control.menu-control-right').removeClass('show');
1274    }
1275
1276    if (prevWidth >= viewWidth && fullWidth >= viewWidth) {
1277        $(targetMenu).find('.menu-control.menu-control-left').addClass('show');
1278    } else {
1279        $(targetMenu).find('.menu-control.menu-control-left').removeClass('show');
1280    }
1281}; // end function handlePageLoadMenuFocus
1282
1283
1284/* 25. Handle Top Menu - Sub Menu Toggle - added in V1.9
1285------------------------------------------------ */
1286var handleTopMenuSubMenu = function() {
1287    "use strict";
1288    $('.top-menu .sub-menu .has-sub > a').click(function() {
1289        var target = $(this).closest('li').find('.sub-menu').first();
1290        var otherMenu = $(this).closest('ul').find('.sub-menu').not(target);
1291        $(otherMenu).not(target).slideUp(250, function() {
1292            $(this).closest('li').removeClass('expand');
1293        });
1294        $(target).slideToggle(250, function() {
1295            var targetLi = $(this).closest('li');
1296            if ($(targetLi).hasClass('expand')) {
1297                $(targetLi).removeClass('expand');
1298            } else {
1299                $(targetLi).addClass('expand');
1300            }
1301        });
1302    });
1303};
1304
1305
1306/* 26. Handle Top Menu - Mobile Sub Menu Toggle - added in V1.9
1307------------------------------------------------ */
1308var handleMobileTopMenuSubMenu = function() {
1309    "use strict";
1310    $('.top-menu .nav > li.has-sub > a').click(function() {
1311        if ($(window).width() <= 767) {
1312            var target = $(this).closest('li').find('.sub-menu').first();
1313            var otherMenu = $(this).closest('ul').find('.sub-menu').not(target);
1314            $(otherMenu).not(target).slideUp(250, function() {
1315                $(this).closest('li').removeClass('expand');
1316            });
1317            $(target).slideToggle(250, function() {
1318                var targetLi = $(this).closest('li');
1319                if ($(targetLi).hasClass('expand')) {
1320                    $(targetLi).removeClass('expand');
1321                } else {
1322                    $(targetLi).addClass('expand');
1323                }
1324            });
1325        }
1326    });
1327};
1328
1329
1330/* 27. Handle Top Menu - Mobile Top Menu Toggle - added in V1.9
1331------------------------------------------------ */
1332var handleTopMenuMobileToggle = function() {
1333    "use strict";
1334    $('[data-click="top-menu-toggled"]').click(function() {
1335        $('.top-menu').slideToggle(250);
1336    });
1337};
1338
1339
1340/* 28. Handle Clear Sidebar Selection & Hide Mobile Menu - added in V1.9
1341------------------------------------------------ */
1342var handleClearSidebarSelection = function() {
1343    "use strict";
1344    $('.sidebar .nav > li, .sidebar .nav .sub-menu').removeClass('expand').removeAttr('style');
1345};
1346var handleClearSidebarMobileSelection = function() {
1347    "use strict";
1348    $('#page-container').removeClass('page-sidebar-toggled');
1349};
1350
1351
1352/* 29. Save UI setting to profile with Ajax - added by Jambu
1353------------------------------------------------ */
1354var lastSaveUserSetting = {};
1355var SaveUserSetting = function(setting_module, setting_var, setting_val) {
1356    "use strict";
1357    if ((!!setting_module) && (!!setting_var) && (setting_module != "") && (setting_var != "")) {
1358        if (!lastSaveUserSetting[setting_module]) { lastSaveUserSetting[setting_module] = {}; }
1359        if (!lastSaveUserSetting[setting_module][setting_var]) { lastSaveUserSetting[setting_module][setting_var] = ""; }
1360        if (lastSaveUserSetting[setting_module][setting_var] != setting_val) {
1361            lastSaveUserSetting[setting_module][setting_var] = setting_val;
1362            var date = new Date();
1363            if (setting_var != "color-mode") { checkUserPrefersColorScheme(); }
1364            var dataSend = { 'now': date.getTime(), 'setting_module': setting_module, 'setting_var': setting_var, 'setting_val': setting_val, 'color-mode': userPrefersColorScheme };
1365            var dataPost = $.param(dataSend);
1366            $.ajax({
1367                cache: false,
1368                type: 'POST',
1369                url: '/profile/json/update',
1370                dataType: 'json',
1371                data: dataPost
1372            }).done(function(dataJson) {
1373                if (handleCheckActiveSession( "profile", dataJson)) {
1374                    if (dataJson.error) {
1375                        console.log({"alert":"An Error Occurred: "+dataJson.error, "dataJson":dataJson });
1376                    } // END IF error
1377                } // END IF handleCheckActiveSession
1378            }).fail(function(xhr, status, errorThrown) {
1379                console.log({"alert":"An Error Occurred: Could Not Save! : "+errorThrown, "dataJson": dataJson });
1380            });
1381        } // END IF setting_val
1382    } // END IF setting_module && setting_var
1383};
1384
1385/* 30. Extract Domain from URL string - added by Jambu
1386------------------------------------------------ */
1387var get_url_domain = function( url ) {
1388    "use strict";
1389    var domain = '';
1390    if (url) {
1391      var matches = url.match(/(^https?\:\/\/[^\/?#]+)(?:[\/?#]|$)/i);
1392      domain = matches && matches[1];
1393    } else {
1394      domain = window.location.origin;
1395    }
1396    return domain;
1397};
1398var domainUrl = get_url_domain();
1399
1400/* 31. Convert system time to local user time - added by Jambu
1401------------------------------------------------ */
1402// Date stuff
1403var momentCalendar = {
1404    lastDay : "[Yesterday at] h:mm a",
1405    sameDay : "[Today at] h:mm a",
1406    nextDay : "[Tomorrow at] h:mm a",
1407    lastWeek : "[Last] ddd [at] h:mm a",
1408    nextWeek : "ddd [at] h:mm a",
1409    sameElse : "ddd, MMM Do YYYY [at] h:mm a"
1410};
1411var getMonthName = function( number ) {
1412    var month = [];
1413    month[0] = "January";
1414    month[1] = "February";
1415    month[2] = "March";
1416    month[3] = "April";
1417    month[4] = "May";
1418    month[5] = "Jun";
1419    month[6] = "July";
1420    month[7] = "August";
1421    month[8] = "September";
1422    month[9] = "October";
1423    month[10] = "November";
1424    month[11] = "December";
1425    return month[number];
1426};
1427var getDate = function( date ) {
1428    var currentDate = new Date(date);
1429    var dd = currentDate.getDate();
1430    var mm = currentDate.getMonth() + 1;
1431    var yyyy = currentDate.getFullYear();
1432
1433    if (dd < 10) {
1434        dd = '0' + dd;
1435    }
1436    if (mm < 10) {
1437        mm = '0' + mm;
1438    }
1439    currentDate = yyyy + '-' + mm + '-' + dd;
1440    return currentDate;
1441};
1442var jstz;
1443var myLocalTZ = []; myLocalTZ.name = function() { return "Etc/UTC"; };
1444var convertDateTZ = function(date, srcTZ, dstTZ) {
1445    "use strict";
1446    if ((date === null) || (date == '')) { return null; }
1447    if (!srcTZ) { srcTZ = "Etc/UTC"; }
1448    if (!dstTZ) { dstTZ = myLocalTZ.name(); }
1449    var srcDate = moment.tz(date, srcTZ);
1450    var returnDate = srcDate.clone().tz(dstTZ);
1451    return returnDate;
1452};
1453$.getScript('assets/plugins/jstz/1.0.6/jstz.min.js').done(function() {
1454    myLocalTZ = jstz.determine();
1455});
1456var local_date_format = function(date) {
1457    if ((date === null) || (date == '')) { return "Invalid date"; }
1458    var thisDateLocal = convertDateTZ(date);
1459    return thisDateLocal.calendar(null, momentCalendar);
1460};
1461var secToHHMMSS = function(tsec) {
1462    if ((tsec === null) || (tsec == '')) { return '00:00'; }
1463    var h=0, m=0, s=0, rsec = tsec, hhmmss='00:00';
1464    if (typeof tsec === 'number') {
1465        if (rsec > 3599) {
1466            h = Math.floor(rsec / 3600);
1467            rsec = rsec - (h * 3600);
1468        }
1469        if (rsec > 59) {
1470            m = Math.floor(rsec / 60);
1471            rsec = rsec - (m * 60);
1472        }
1473        if (rsec > 0) {
1474            s = rsec;
1475        }
1476        hhmmss = (h>0?h+":":"") + (m<10?"0":"") + m + ":" + (s<10?"0":"") + s;
1477    } // end if tsec
1478    return hhmmss;
1479}; // end function secToHHMMSS
1480var moment_format = function(date) {
1481    if ((date === null) || (date == '')) { return "Invalid date"; }
1482    var thisDateLocal = convertDateTZ(date);
1483    var thisDateLocalStr = thisDateLocal.fromNow();
1484    if ((occurrences(thisDateLocalStr, "second") == 0) && (occurrences(thisDateLocalStr, "minute") == 0)) {
1485        thisDateLocalStr = thisDateLocal.calendar(null, momentCalendar);
1486    } else if (occurrences(thisDateLocalStr, "Invalid date") > 0) {
1487        thisDateLocalStr = "Invalid date";
1488    }
1489    return thisDateLocalStr;
1490};
1491var number_format = function(number, decimals, dec_point, thousands_sep) {
1492    "use strict";
1493    // Strip all characters but numerical ones.
1494    number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
1495    var n = !isFinite(+number) ? 0 : +number,
1496        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
1497        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
1498        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
1499        s = '',
1500        toFixedFix = function (n, prec) {
1501            var k = Math.pow(10, prec);
1502            return '' + Math.round(n * k) / k;
1503        };
1504    // Fix for IE parseFloat(0.55).toFixed(0) = 0;
1505    s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
1506    if (s[0].length > 3) {
1507        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
1508    }
1509    if ((s[1] || '').length < prec) {
1510        s[1] = s[1] || '';
1511        s[1] += new Array(prec - s[1].length + 1).join('0');
1512    }
1513    return s.join(dec);
1514};
1515
1516
1517/* 32. Used for determining substring occurrences - added by Jambu
1518------------------------------------------------ */
1519var occurrences = function(string, subString, allowOverlapping) {
1520    "use strict";
1521    string += ""; subString += "";
1522    if (subString.length <= 0) return (string.length + 1);
1523    var n = 0, pos = 0, step = allowOverlapping ? 1 : subString.length;
1524    while (true) {
1525        pos = string.indexOf(subString, pos);
1526        if (pos >= 0) { ++n; pos += step; } else break;
1527    }
1528    return n;
1529};
1530
1531/* 33. Add to string prototype Capitalize First Letter - added by Jambu
1532------------------------------------------------ */
1533String.prototype.capitalizeFirstLetter = function() {
1534    "use strict";
1535    return this.charAt(0).toUpperCase() + this.slice(1);
1536};
1537
1538var browserIsFirefox = false;
1539var setPageMinHeight = function( element_id ) {
1540    "use strict";
1541    //var heightBuffer = ( $(window).width() <= 767 ? 54 : 115 );
1542    //var heightBuffer = ( browserIsFirefox === true ? 75 : 95 );
1543    var firefoxBuffer = 0; // ( browserIsFirefox === true ? 0 : 20 );
1544    var headerHeight = 0, elementHeight = 0, parentHeight = 0, footerHeight = 0, heightBuffer = 0;
1545    if ($('#header').length > 0) {
1546        headerHeight += 1* $('#header').height() +
1547                        1* parseInt($('#header').css('padding-top')) + 1* parseInt($('#header').css('padding-bottom')) +
1548                        1* parseInt($('#header').css('margin-top')) + 1* parseInt($('#header').css('margin-bottom')) +
1549                        1* parseInt($('#header').css('border-top')) + 1* parseInt($('#header').css('border-bottom'));
1550    } // end if header
1551    if ($('#' + element_id).length > 0) {
1552        elementHeight +=
1553                        1* parseInt($('#' + element_id).css('padding-top')) + 1* parseInt($('#' + element_id).css('padding-bottom')) +
1554                        1* parseInt($('#' + element_id).css('margin-top')) + 1* parseInt($('#' + element_id).css('margin-bottom')) +
1555                        1* parseInt($('#' + element_id).css('border-top')) + 1* parseInt($('#' + element_id).css('border-bottom'));
1556    } // end if element
1557    if ($('#' + element_id).parent().length > 0) {
1558        parentHeight +=
1559                        1* parseInt($('#' + element_id).parent().css('padding-top')) + 1* parseInt($('#' + element_id).parent().css('padding-bottom')) +
1560                        1* parseInt($('#' + element_id).parent().css('margin-top')) + 1* parseInt($('#' + element_id).parent().css('margin-bottom')) +
1561                        1* parseInt($('#' + element_id).parent().css('border-top')) + 1* parseInt($('#' + element_id).parent().css('border-bottom'));
1562    } // end if element parent
1563    if ($('#footer').length > 0) {
1564        footerHeight += 1* $('#footer').height() +
1565                        1* parseInt($('#footer').css('padding-top')) + 1* parseInt($('#footer').css('padding-bottom')) +
1566                        1* parseInt($('#footer').css('margin-top')) + 1* parseInt($('#footer').css('margin-bottom')) +
1567                        1* parseInt($('#footer').css('border-top')) + 1* parseInt($('#footer').css('border-bottom'));
1568    } // end if footer
1569
1570    //console.log('#' + element_id);
1571    //console.log('firefoxBuffer', firefoxBuffer);
1572    //console.log('headerHeight', headerHeight);
1573    //console.log('elementHeight', elementHeight);
1574    //console.log('parentHeight', parentHeight);
1575    //console.log('footerHeight', footerHeight);
1576
1577    heightBuffer = headerHeight + footerHeight + parentHeight + firefoxBuffer - ( $(window).width() <= 767 ? 1 : 0 );
1578    var pageMinHeight = $(window).height() - heightBuffer;
1579    //console.log('window.height()', $(window).height());
1580    //console.log('heightBuffer', heightBuffer);
1581    //console.log('pageMinHeight', pageMinHeight);
1582    if ((typeof pageMinHeight == 'undefined') || Number.isNaN(pageMinHeight) || (pageMinHeight === null) || (pageMinHeight == '')) {
1583        heightBuffer = ( $(window).width() <= 767 ? 115 : 95 );
1584        //console.log('heightBuffer', heightBuffer);
1585        firefoxBuffer = ( browserIsFirefox === true ? 0 : 20 );
1586        pageMinHeight = $(window).height() - heightBuffer - firefoxBuffer;
1587        //console.log('pageMinHeight', pageMinHeight);
1588    }
1589    //console.log('heightBuffer', heightBuffer);
1590    $('#' + element_id).css(  "min-height", pageMinHeight + "px" );
1591    $('#' + element_id).attr( "min-height", pageMinHeight + "px" );
1592    $('#' + element_id).attr( "win-height", $(window).height() + "px");
1593    $('#' + element_id).attr( "firefox-detected", (browserIsFirefox === true ? "yes" : "no" ));
1594
1595};
1596var lastWindowHeight = $(window).height();
1597var lastWindowWidth = $(window).width();
1598var handlePageHeight = function( element_id ) {
1599    "use strict";
1600    setPageMinHeight( element_id );
1601    $(window).resize(function() {
1602        handlePageHeightExec( element_id );
1603    }); // end resize window
1604}; // end function handlePageHeight
1605var handlePageHeightExec = function( element_id ) {
1606    "use strict";
1607    if (enableHandlePageLoadTabFocus === true) {
1608        $('.tab-overflow .nav.nav-tabs').removeAttr('style');
1609        handlePageLoadTabFocus();
1610    } // end if enableHandlePageLoadTabFocus
1611
1612    if (enableHandlePageLoadMenuFocus === true) {
1613        $('.top-menu .nav').removeAttr('style');
1614        handlePageLoadMenuFocus();
1615    } // end if enableHandlePageLoadMenuFocus
1616
1617    var thisWindowHeight = $(window).height();
1618    var thisWindowWidth =$(window).width();
1619    if ((thisWindowHeight != lastWindowHeight) || (thisWindowWidth != lastWindowWidth)) {
1620        lastWindowHeight = thisWindowHeight;
1621        lastWindowWidth = thisWindowWidth;
1622        setPageMinHeight( element_id );
1623    } // end if lastWindowHeight
1624}; // end function handlePageHeightExec
1625
1626
1627/* 34. Set the Page Background - added by Jambu
1628------------------------------------------------ */
1629// Background stuff
1630///// MOVED to private/tpl
1631
1632
1633/* 35. Loading the "My Info" - added by Jambu
1634------------------------------------------------ */
1635// Loading the user's info
1636
1637var myUserFullName = '';
1638var myUserFirstName = '';
1639var myUserLastName = '';
1640var myUserId = '';
1641var myUserPhotoId = '';
1642var getMyInfo = function(src='') {
1643    var date = new Date();
1644    if (src != 'color-mode') { checkUserPrefersColorScheme(); }
1645    var dataSend = { 'now': date.getTime(), 'output_type':'json', 'op':'view', 'action':'get_my_info', 'color-mode': userPrefersColorScheme };
1646    var dataPost = $.param(dataSend);
1647    $.ajax({
1648        cache: false,
1649        type: 'POST',
1650        url: '/profile',
1651        dataType: 'json',
1652        data: dataPost
1653    }).done( function( dataJson ) {
1654        if ((dataJson != null) && (typeof dataJson.error != 'undefined') && (dataJson.error != '')) {
1655            console.log('An Error Occurred : ' + dataJson.error);
1656        } else if (handleCheckActiveSession( "profile", dataJson )) {
1657            myUserFullName = dataJson.first_name + ' ' + dataJson.last_name;
1658            myUserFirstName = dataJson.first_name;
1659            myUserLastName = dataJson.last_name;
1660            myUserId = dataJson.user_id;
1661            myUserPhotoId = dataJson.photo_media_id;
1662        } // END IF error
1663    }).fail( function( xhr, status, errorThrown ) {
1664        console.log('An Error Occurred : Could Not Load : ' + errorThrown);
1665    });
1666};
1667
1668
1669/* 36. Handle Paroller
1670------------------------------------------------ */
1671
1672var handleParoller = function() {
1673    "use strict";
1674    if (typeof $.fn.paroller !== 'undefined') {
1675        if ($('[data-paroller="true"]').length !== 0) {
1676            $('[data-paroller="true"]').paroller();
1677        }
1678    }
1679};
1680
1681
1682/* 37. Handle Idle Detection
1683------------------------------------------------ */
1684
1685var appUserIdleTime = 0;
1686var appUserIdleTimeLastActivity = Math.round((new Date()).getTime() / 1000);
1687var checkInactivityTimeout = null;
1688var checkInactivityInterval = 1000 * 600; // Ten minutes -- in seconds
1689var resetInactivityTimer = function() {
1690    "use strict";
1691    //console.log('resetInactivityTimer', appUserIdleTime);
1692    clearTimeout(checkInactivityTimeout);
1693    appUserIdleTime = 0;
1694    appUserIdleTimeLastActivity = Math.round((new Date()).getTime() / 1000);
1695    checkInactivityTimeout = setTimeout(function() { setInactivityTimer(); }, checkInactivityInterval); // Check in ten minutes
1696};
1697var setInactivityTimer = function() {
1698    "use strict";
1699    //console.log('setInactivityTimer', appUserIdleTime);
1700    clearTimeout(checkInactivityTimeout);
1701    appUserIdleTime = Math.round((new Date()).getTime() / 1000) - appUserIdleTimeLastActivity;
1702    checkInactivityTimeout = setTimeout(function() { setInactivityTimer(); }, checkInactivityInterval); // Check in ten minutes
1703};
1704var handleInactivityTime = function() {
1705    "use strict";
1706    window.onload = resetInactivityTimer;
1707    // DOM Events
1708    document.onscroll = resetInactivityTimer;
1709    document.onmousemove = resetInactivityTimer;
1710    document.onkeypress = resetInactivityTimer;
1711    document.ontouchstart = resetInactivityTimer;
1712};
1713
1714
1715/* 38. Handle User Prefers Color Scheme
1716------------------------------------------------ */
1717
1718var reloadUserPrefersColorScheme = null;
1719var userPrefersColorScheme = '';
1720var lastUserPrefersColorScheme = '';
1721var checkPrefersColorScheme = function(mql=null) {
1722    var detectedColorScheme = '';
1723    if (mql && mql.matches) {
1724        // light mode
1725        //console.log('js: prefers-color-scheme: light', window.matchMedia('(prefers-color-scheme: light)').matches);
1726        detectedColorScheme = 'light';
1727    } else {
1728        // dark mode
1729        //console.log('js: prefers-color-scheme: dark', true); // window.matchMedia('(prefers-color-scheme: dark)').matches);
1730        detectedColorScheme = 'dark';
1731    } // end if prefers-color-scheme
1732    return detectedColorScheme;
1733}; // end function checkPrefersColorScheme
1734var checkUserPrefersColorScheme = function(mql=null) {
1735    if (!mql) { mql = window.matchMedia('(prefers-color-scheme: light)') || null; }
1736    userPrefersColorScheme = checkPrefersColorScheme(mql);
1737    if ((userPrefersColorScheme != '') && (userPrefersColorScheme != lastUserPrefersColorScheme)) {
1738        // Save and refresh
1739        //SaveUserSetting("profile", "color-mode", userPrefersColorScheme);
1740        //console.log('js: prefers-color-scheme:', lastUserPrefersColorScheme, ' -> ', userPrefersColorScheme);
1741        if (myUserId != '') { getMyInfo("color-mode"); }
1742        //reloadUserPrefersColorScheme = setTimeout(function() { window.location.reload(); }, 500);
1743        // Maybe we can just change the page/header classes
1744        if (userPrefersColorScheme == 'light') {
1745            $('.page-with-dark-sidebar').addClass('page-with-light-sidebar').removeClass('page-with-dark-sidebar');
1746            $('.navbar-inverse').addClass('navbar-default').removeClass('navbar-inverse');
1747        } else {
1748            $('.page-with-light-sidebar').addClass('page-with-dark-sidebar').removeClass('page-with-light-sidebar');
1749            $('.navbar-default').addClass('navbar-inverse').removeClass('navbar-default');
1750        } // end if userPrefersColorScheme
1751    } // end if lastUserPrefersColorScheme
1752    lastUserPrefersColorScheme = userPrefersColorScheme;
1753    return userPrefersColorScheme;
1754}; // end function checkUserPrefersColorScheme
1755var listenerUserPrefersColorScheme = function(mql=null) {
1756    var detectedColorScheme = checkUserPrefersColorScheme(mql);
1757    //console.log('listenerUserPrefersColorScheme', detectedColorScheme);
1758    return detectedColorScheme;
1759}; // end function listenerUserPrefersColorScheme
1760var handleCheckUserPrefersColorScheme = function() {
1761    var mql = window.matchMedia('(prefers-color-scheme: light)');
1762    mql.addListener(listenerUserPrefersColorScheme);
1763}; // end function handleCheckUserPrefersColorScheme
1764
1765
1766
1767/* 39. Array IndexOf (if not defined)
1768------------------------------------------------ */
1769
1770Array.prototype.indexOf = Array.prototype.indexOf || function(d, e) {
1771    "use strict";
1772    var a;
1773    if (null == this) throw new TypeError('"this" is null or not defined');
1774    var c = Object(this),
1775        b = c.length >>> 0;
1776    if (0 === b) return -1;
1777    a = +e || 0;
1778    if (Infinity === Math.abs(a) && (a = 0)) { return -1; }
1779    if (a >= b) return -1;
1780    for (a = Math.max(0 <= a ? a : b - Math.abs(a), 0); a < b;) {
1781        if (a in c && c[a] === d) return a;
1782        a++;
1783    }
1784    return -1;
1785}; // end function Array.indexOf
1786
1787
1788
1789
1790
1791
1792/* Application Controller
1793------------------------------------------------ */
1794var App = function () {
1795    "use strict";
1796    return {
1797        //main function
1798        init: function () {
1799            if (navigator.userAgent.indexOf("Firefox") > 0) {
1800                browserIsFirefox = true;
1801            }
1802            checkUserPrefersColorScheme();
1803            handleCheckUserPrefersColorScheme();
1804            resetInactivityTimer();
1805            handleInactivityTime();
1806            this.handleFocusTitle();
1807            this.initSidebar();
1808            this.initTopMenu();
1809            this.initPageLoad();
1810            this.initComponent();
1811            this.initLocalStorage();
1812            this.initThemePanel();
1813            this.initAjaxFunction();
1814            this.initFooter();
1815            this.initHandleParoller();
1816            loadBackgroundAsync( backgroundUrlTemp, backgroundUrlMain );
1817        },
1818        initSidebar: function() {
1819            handleSidebarMenu();
1820            handleMobileSidebarToggle();
1821            handleSidebarMinify();
1822            handleMobileSidebar();
1823        },
1824        initSidebarSelection: function() {
1825            handleClearSidebarSelection();
1826        },
1827        initSidebarMobileSelection: function() {
1828            handleClearSidebarMobileSelection();
1829        },
1830        initTopMenu: function() {
1831            handleUnlimitedTopMenuRender();
1832            handleTopMenuSubMenu();
1833            handleMobileTopMenuSubMenu();
1834            handleTopMenuMobileToggle();
1835        },
1836        initPageLoad: function() {
1837            handlePageContentView();
1838        },
1839        initComponent: function() {
1840            handleIEFullHeightContent();
1841            handleSlimScroll();
1842            handleUnlimitedTabsRender();
1843            handlePanelAction();
1844            handelTooltipPopoverActivation();
1845            handleScrollToTopButton();
1846            handleAfterPageLoadAddClass();
1847            handleDraggablePanel();
1848        },
1849        initLocalStorage: function() {
1850            handleLocalStorage();
1851        },
1852        initThemePanel: function() {
1853            handleThemePageStructureControl();
1854            handleThemePanelExpand();
1855            handleResetLocalStorage();
1856        },
1857        initAjaxFunction: function() {
1858            handleSidebarAjaxClick();
1859            hashUrl = String(window.location.hash);
1860            handleCheckPageLoadUrl( hashUrl );
1861            handleHashChange();
1862            // ajax cache setup
1863            $.ajaxSetup({
1864                cache: true
1865            });
1866        },
1867        initFooter: function() {
1868            //handlePageHeight( "ajax-content" );
1869            handlePageHeight( "content" );
1870        },
1871        initHandleParoller: function() {
1872            handleParoller();
1873        },
1874        pageTitle : '',
1875        setPageTitle: function( pageTitle = '' ) {
1876            //console.log('Setting page title', pageTitle, 'module', targetMod, 'this.pageTitle', this.pageTitle);
1877            if (pageTitle == '') { pageTitle = this.pageTitle; }
1878            if (pageTitle != '') {
1879                this.pageTitle = pageTitle;
1880                setTimeout(function() { document.title = ''; document.title = pageTitle; }, 5);
1881                //$(document).attr("title", pageTitle);
1882                //setTimeout(function() { $(document).attr("title", pageTitle); document.title = pageTitle; }, 50);
1883            }
1884        },
1885        handleFocusTitle : function() {
1886            if ("focus" in window) {
1887                $(window).on('focus', function() {
1888                    //console.log("Trying title reset, focus");
1889                    App.setPageTitle();
1890                });
1891            } else if ("focusin" in window) {
1892                $(window).on('focusin', function() {
1893                    //console.log("Trying title reset, focusin");
1894                    App.setPageTitle();
1895                });
1896            }
1897        },
1898        restartGlobalFunction: function() {
1899            this.initComponent();
1900            this.initTopMenu();
1901            this.initLocalStorage();
1902            loadBackgroundAsync( backgroundUrlTemp, backgroundUrlMain );
1903        },
1904        reloadPage: function( reloadTargetMod ) {
1905            //console.log("App.reloadPage -> reloadTargetMod = " + reloadTargetMod);
1906            if (reloadTargetMod && (reloadTargetMod != "")) {
1907                var newLocation = window.location.origin + "/" + reloadTargetMod;
1908                window.location.href = newLocation;
1909            } else {
1910                window.location.reload();
1911            } // END IF reloadTargetMod
1912        },
1913        GotoModule: function( newMod ) {
1914            hashUrl = '#ajax/' + newMod;
1915            targetMod = newMod;
1916            var thisSidebarLi = $('.sidebar').find('a[href="' + hashUrl + '"][data-toggle=ajax]')[0];
1917            sidebarActiveModule( thisSidebarLi );
1918            console.log('window.location', window.location);
1919            if (window.location.hash != hashUrl) {
1920                window.location.hash = hashUrl;
1921            } else {
1922                handleLoadPage( targetMod );
1923            }
1924        },
1925        scrollTop: function() {
1926            $('html, body').animate({
1927                scrollTop: $('body').offset().top
1928            }, 0);
1929        }
1930    };
1931}();
1932

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.