Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
776 lars 1
/**
2
Core script to handle the entire theme and core functions
3
**/
4
var Layout = function () {
5
 
6
    var layoutImgPath = 'layouts/layout2/img/';
7
 
8
    var layoutCssPath = 'layouts/layout2/css/';
9
 
10
    var resBreakpointMd = App.getResponsiveBreakpoint('md');
11
 
12
    var ajaxContentSuccessCallbacks = [];
13
    var ajaxContentErrorCallbacks = [];
14
 
15
    //* BEGIN:CORE HANDLERS *//
16
    // this function handles responsive layout on screen size resize or mobile device rotate.
17
 
18
    // Set proper height for sidebar and content. The content and sidebar height must be synced always.
19
    var handleSidebarAndContentHeight = function () {
20
        var content = $('.page-content');
21
        var sidebar = $('.page-sidebar');
22
        var body = $('body');
23
        var height;
24
 
25
        if (body.hasClass("page-footer-fixed") === true && body.hasClass("page-sidebar-fixed") === false) {
26
            var available_height = App.getViewPort().height - $('.page-footer').outerHeight() - $('.page-header').outerHeight();
27
            if (content.height() < available_height) {
28
                content.attr('style', 'min-height:' + available_height + 'px');
29
            }
30
        } else {
31
            if (body.hasClass('page-sidebar-fixed')) {
32
                height = _calculateFixedSidebarViewportHeight();
33
                if (body.hasClass('page-footer-fixed') === false) {
34
                    height = height - $('.page-footer').outerHeight();
35
                }
36
            } else {
37
                var headerHeight = $('.page-header').outerHeight();
38
                var footerHeight = $('.page-footer').outerHeight();
39
 
40
                if (App.getViewPort().width < resBreakpointMd) {
41
                    height = App.getViewPort().height - headerHeight - footerHeight;
42
                } else {
43
                    height = sidebar.height() + 20;
44
                }
45
 
46
                if ((height + headerHeight + footerHeight) <= App.getViewPort().height) {
47
                    height = App.getViewPort().height - headerHeight - footerHeight;
48
                }
49
            }
50
            content.attr('style', 'min-height:' + height + 'px');
51
        }
52
    };
53
 
54
    // Handle sidebar menu links
55
    var handleSidebarMenuActiveLink = function(mode, el) {
56
        var url = location.hash.toLowerCase();
57
 
58
        var menu = $('.page-sidebar-menu');
59
 
60
        if (mode === 'click' || mode === 'set') {
61
            el = $(el);
62
        } else if (mode === 'match') {
63
            menu.find("li > a").each(function() {
64
                var path = $(this).attr("href").toLowerCase();
65
                // url match condition
66
                if (path.length > 1 && url.substr(1, path.length - 1) == path.substr(1)) {
67
                    el = $(this);
68
                    return;
69
                }
70
            });
71
        }
72
 
73
        if (!el || el.size() == 0) {
74
            return;
75
        }
76
 
77
        if (el.attr('href').toLowerCase() === 'javascript:;' || el.attr('href').toLowerCase() === '#') {
78
            return;
79
        }
80
 
81
        var slideSpeed = parseInt(menu.data("slide-speed"));
82
        var keepExpand = menu.data("keep-expanded");
83
 
84
        // begin: handle active state
85
        if (menu.hasClass('page-sidebar-menu-hover-submenu') === false) {
86
            menu.find('li.nav-item.open').each(function() {
87
                var match = false;
88
                $(this).find('li').each(function(){
89
                    if ($(this).find(' > a').attr('href') === el.attr('href')) {
90
                        match = true;
91
                        return;
92
                    }
93
                });
94
 
95
                if (match === true) {
96
                    return;
97
                }
98
 
99
                $(this).removeClass('open');
100
                $(this).find('> a > .arrow.open').removeClass('open');
101
                $(this).find('> .sub-menu').slideUp();
102
            });
103
        } else {
104
             menu.find('li.open').removeClass('open');
105
        }
106
 
107
        menu.find('li.active').removeClass('active');
108
        menu.find('li > a > .selected').remove();
109
        // end: handle active state
110
 
111
        el.parents('li').each(function () {
112
            $(this).addClass('active');
113
            $(this).find('> a > span.arrow').addClass('open');
114
 
115
            if ($(this).parent('ul.page-sidebar-menu').size() === 1) {
116
                $(this).find('> a').append('<span class="selected"></span>');
117
            }
118
 
119
            if ($(this).children('ul.sub-menu').size() === 1) {
120
                $(this).addClass('open');
121
            }
122
        });
123
 
124
        if (mode === 'click') {
125
            if (App.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page
126
                $('.page-header .responsive-toggler').click();
127
            }
128
        }
129
    };
130
 
131
    // Handle sidebar menu
132
    var handleSidebarMenu = function () {
133
        // handle sidebar link click
134
        $('.page-sidebar-menu').on('click', 'li > a.nav-toggle, li > a > span.nav-toggle', function (e) {
135
            var that = $(this).closest('.nav-item').children('.nav-link');
136
 
137
            if (App.getViewPort().width >= resBreakpointMd && !$('.page-sidebar-menu').attr("data-initialized") && $('body').hasClass('page-sidebar-closed') &&  that.parent('li').parent('.page-sidebar-menu').size() === 1) {
138
                return;
139
            }
140
 
141
            var hasSubMenu = that.next().hasClass('sub-menu');
142
 
143
            if (App.getViewPort().width >= resBreakpointMd && that.parents('.page-sidebar-menu-hover-submenu').size() === 1) { // exit of hover sidebar menu
144
                return;
145
            }
146
 
147
            if (hasSubMenu === false) {
148
                if (App.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page
149
                    $('.page-header .responsive-toggler').click();
150
                }
151
                return;
152
            }
153
 
154
            var parent =that.parent().parent();
155
            var the = that;
156
            var menu = $('.page-sidebar-menu');
157
            var sub = that.next();
158
 
159
            var autoScroll = menu.data("auto-scroll");
160
            var slideSpeed = parseInt(menu.data("slide-speed"));
161
            var keepExpand = menu.data("keep-expanded");
162
 
163
            if (keepExpand !== true) {
164
                parent.children('li.open').children('a').children('.arrow').removeClass('open');
165
                parent.children('li.open').children('.sub-menu:not(.always-open)').slideUp(slideSpeed);
166
                parent.children('li.open').removeClass('open');
167
            }
168
 
169
            var slideOffeset = -200;
170
 
171
            if (sub.is(":visible")) {
172
                $('.arrow', the).removeClass("open");
173
                the.parent().removeClass("open");
174
                sub.slideUp(slideSpeed, function () {
175
                    if (autoScroll === true && $('body').hasClass('page-sidebar-closed') === false) {
176
                        if ($('body').hasClass('page-sidebar-fixed')) {
177
                            menu.slimScroll({
178
                                'scrollTo': (the.position()).top
179
                            });
180
                        } else {
181
                            App.scrollTo(the, slideOffeset);
182
                        }
183
                    }
184
                    handleSidebarAndContentHeight();
185
                });
186
            } else if (hasSubMenu) {
187
                $('.arrow', the).addClass("open");
188
                the.parent().addClass("open");
189
                sub.slideDown(slideSpeed, function () {
190
                    if (autoScroll === true && $('body').hasClass('page-sidebar-closed') === false) {
191
                        if ($('body').hasClass('page-sidebar-fixed')) {
192
                            menu.slimScroll({
193
                                'scrollTo': (the.position()).top
194
                            });
195
                        } else {
196
                            App.scrollTo(the, slideOffeset);
197
                        }
198
                    }
199
                    handleSidebarAndContentHeight();
200
                });
201
            }
202
 
203
            e.preventDefault();
204
        });
205
 
206
        // handle menu close for angularjs version
207
        if (App.isAngularJsApp()) {
208
            $(".page-sidebar-menu li > a").on("click", function(e) {
209
                if (App.getViewPort().width < resBreakpointMd && $(this).next().hasClass('sub-menu') === false) {
210
                    $('.page-header .responsive-toggler').click();
211
                }
212
            });
213
        }
214
 
215
        // handle ajax links within sidebar menu
216
        $('.page-sidebar').on('click', ' li > a.ajaxify', function (e) {
217
            e.preventDefault();
218
            App.scrollTop();
219
 
220
            var url = $(this).attr("href");
221
            var menuContainer = $('.page-sidebar ul');
222
 
223
            menuContainer.children('li.active').removeClass('active');
224
            menuContainer.children('arrow.open').removeClass('open');
225
 
226
            $(this).parents('li').each(function () {
227
                $(this).addClass('active');
228
                $(this).children('a > span.arrow').addClass('open');
229
            });
230
            $(this).parents('li').addClass('active');
231
 
232
            if (App.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page
233
                $('.page-header .responsive-toggler').click();
234
            }
235
 
236
            Layout.loadAjaxContent(url, $(this));
237
        });
238
 
239
        // handle ajax link within main content
240
        $('.page-content').on('click', '.ajaxify', function (e) {
241
            e.preventDefault();
242
            App.scrollTop();
243
 
244
            var url = $(this).attr("href");
245
 
246
            App.startPageLoading();
247
 
248
            if (App.getViewPort().width < resBreakpointMd && $('.page-sidebar').hasClass("in")) { // close the menu on mobile view while laoding a page
249
                $('.page-header .responsive-toggler').click();
250
            }
251
 
252
            Layout.loadAjaxContent(url);
253
        });
254
 
255
        // handle scrolling to top on responsive menu toggler click when header is fixed for mobile view
256
        $(document).on('click', '.page-header-fixed-mobile .page-header .responsive-toggler', function(){
257
            App.scrollTop();
258
        });
259
 
260
        // handle sidebar hover effect
261
        handleFixedSidebarHoverEffect();
262
 
263
        // handle the search bar close
264
        $('.page-sidebar').on('click', '.sidebar-search .remove', function (e) {
265
            e.preventDefault();
266
            $('.sidebar-search').removeClass("open");
267
        });
268
 
269
        // handle the search query submit on enter press
270
        $('.page-sidebar .sidebar-search').on('keypress', 'input.form-control', function (e) {
271
            if (e.which == 13) {
272
                $('.sidebar-search').submit();
273
                return false; //<---- Add this line
274
            }
275
        });
276
 
277
        // handle the search submit(for sidebar search and responsive mode of the header search)
278
        $('.sidebar-search .submit').on('click', function (e) {
279
            e.preventDefault();
280
            if ($('body').hasClass("page-sidebar-closed")) {
281
                if ($('.sidebar-search').hasClass('open') === false) {
282
                    if ($('.page-sidebar-fixed').size() === 1) {
283
                        $('.page-sidebar .sidebar-toggler').click(); //trigger sidebar toggle button
284
                    }
285
                    $('.sidebar-search').addClass("open");
286
                } else {
287
                    $('.sidebar-search').submit();
288
                }
289
            } else {
290
                $('.sidebar-search').submit();
291
            }
292
        });
293
 
294
        // handle close on body click
295
        if ($('.sidebar-search').size() !== 0) {
296
            $('.sidebar-search .input-group').on('click', function(e){
297
                e.stopPropagation();
298
            });
299
 
300
            $('body').on('click', function() {
301
                if ($('.sidebar-search').hasClass('open')) {
302
                    $('.sidebar-search').removeClass("open");
303
                }
304
            });
305
        }
306
    };
307
 
308
    // Handles the horizontal menu
309
    var handleHeader = function() {
310
        // handle search box expand/collapse
311
        $('.page-header').on('click', '.search-form', function(e) {
312
            $(this).addClass("open");
313
            $(this).find('.form-control').focus();
314
 
315
            $('.page-header .search-form .form-control').on('blur', function(e) {
316
                $(this).closest('.search-form').removeClass("open");
317
                $(this).unbind("blur");
318
            });
319
        });
320
 
321
        // handle hor menu search form on enter press
322
        $('.page-header').on('keypress', '.hor-menu .search-form .form-control', function(e) {
323
            if (e.which == 13) {
324
                $(this).closest('.search-form').submit();
325
                return false;
326
            }
327
        });
328
 
329
        // handle header search button click
330
        $('.page-header').on('mousedown', '.search-form.open .submit', function(e) {
331
            e.preventDefault();
332
            e.stopPropagation();
333
            $(this).closest('.search-form').submit();
334
        });
335
    };
336
 
337
    // Helper function to calculate sidebar height for fixed sidebar layout.
338
    var _calculateFixedSidebarViewportHeight = function () {
339
        var sidebarHeight = App.getViewPort().height - $('.page-header').outerHeight();
340
        if ($('body').hasClass("page-footer-fixed")) {
341
            sidebarHeight = sidebarHeight - $('.page-footer').outerHeight();
342
        }
343
 
344
        return sidebarHeight;
345
    };
346
 
347
    // Handles fixed sidebar
348
    var handleFixedSidebar = function () {
349
        var menu = $('.page-sidebar-menu');
350
 
351
        App.destroySlimScroll(menu);
352
 
353
        if ($('.page-sidebar-fixed').size() === 0) {
354
            handleSidebarAndContentHeight();
355
            return;
356
        }
357
 
358
        if (App.getViewPort().width >= resBreakpointMd) {
359
            menu.attr("data-height", _calculateFixedSidebarViewportHeight());
360
            App.initSlimScroll(menu);
361
            handleSidebarAndContentHeight();
362
        }
363
    };
364
 
365
    // Handles sidebar toggler to close/hide the sidebar.
366
    var handleFixedSidebarHoverEffect = function () {
367
        var body = $('body');
368
        if (body.hasClass('page-sidebar-fixed')) {
369
            $('.page-sidebar').on('mouseenter', function () {
370
                if (body.hasClass('page-sidebar-closed')) {
371
                    $(this).find('.page-sidebar-menu').removeClass('page-sidebar-menu-closed');
372
                }
373
            }).on('mouseleave', function () {
374
                if (body.hasClass('page-sidebar-closed')) {
375
                    $(this).find('.page-sidebar-menu').addClass('page-sidebar-menu-closed');
376
                }
377
            });
378
        }
379
    };
380
 
381
    // Hanles sidebar toggler
382
    var handleSidebarToggler = function () {
383
        var body = $('body');
384
        if ($.cookie && $.cookie('sidebar_closed') === '1' && App.getViewPort().width >= resBreakpointMd) {
385
            $('body').addClass('page-sidebar-closed');
386
            $('.page-sidebar-menu').addClass('page-sidebar-menu-closed');
387
        }
388
 
389
        // handle sidebar show/hide
390
        $('body').on('click', '.sidebar-toggler', function (e) {
391
            var sidebar = $('.page-sidebar');
392
            var sidebarMenu = $('.page-sidebar-menu');
393
            $(".sidebar-search", sidebar).removeClass("open");
394
 
395
            if (body.hasClass("page-sidebar-closed")) {
396
                body.removeClass("page-sidebar-closed");
397
                sidebarMenu.removeClass("page-sidebar-menu-closed");
398
                if ($.cookie) {
399
                    $.cookie('sidebar_closed', '0');
400
                }
401
            } else {
402
                body.addClass("page-sidebar-closed");
403
                sidebarMenu.addClass("page-sidebar-menu-closed");
404
                if (body.hasClass("page-sidebar-fixed")) {
405
                    sidebarMenu.trigger("mouseleave");
406
                }
407
                if ($.cookie) {
408
                    $.cookie('sidebar_closed', '1');
409
                }
410
            }
411
 
412
            $(window).trigger('resize');
413
        });
414
    };
415
 
416
    // Handles Bootstrap Tabs.
417
    var handleTabs = function () {
418
        // fix content height on tab click
419
        $('body').on('shown.bs.tab', 'a[data-toggle="tab"]', function () {
420
            handleSidebarAndContentHeight();
421
        });
422
    };
423
 
424
    // Handles the go to top button at the footer
425
    var handleGoTop = function () {
426
        var offset = 300;
427
        var duration = 500;
428
 
429
        if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {  // ios supported
430
            $(window).bind("touchend touchcancel touchleave", function(e){
431
               if ($(this).scrollTop() > offset) {
432
                    $('.scroll-to-top').fadeIn(duration);
433
                } else {
434
                    $('.scroll-to-top').fadeOut(duration);
435
                }
436
            });
437
        } else {  // general
438
            $(window).scroll(function() {
439
                if ($(this).scrollTop() > offset) {
440
                    $('.scroll-to-top').fadeIn(duration);
441
                } else {
442
                    $('.scroll-to-top').fadeOut(duration);
443
                }
444
            });
445
        }
446
 
447
        $('.scroll-to-top').click(function(e) {
448
            e.preventDefault();
449
            $('html, body').animate({scrollTop: 0}, duration);
450
            return false;
451
        });
452
    };
453
 
454
    // Hanlde 100% height elements(block, portlet, etc)
455
    var handle100HeightContent = function () {
456
 
457
        $('.full-height-content').each(function(){
458
            var target = $(this);
459
            var height;
460
 
461
            height = App.getViewPort().height -
462
                $('.page-header').outerHeight(true) -
463
                $('.page-footer').outerHeight(true) -
464
                $('.page-title').outerHeight(true) -
465
                $('.page-bar').outerHeight(true);
466
 
467
            if (target.hasClass('portlet')) {
468
                var portletBody = target.find('.portlet-body');
469
 
470
                App.destroySlimScroll(portletBody.find('.full-height-content-body')); // destroy slimscroll
471
 
472
                height = height -
473
                    target.find('.portlet-title').outerHeight(true) -
474
                    parseInt(target.find('.portlet-body').css('padding-top')) -
475
                    parseInt(target.find('.portlet-body').css('padding-bottom')) - 2;
476
 
477
                if (App.getViewPort().width >= resBreakpointMd && target.hasClass("full-height-content-scrollable")) {
478
                    height = height - 35;
479
                    portletBody.find('.full-height-content-body').css('height', height);
480
                    App.initSlimScroll(portletBody.find('.full-height-content-body'));
481
                } else {
482
                    portletBody.css('min-height', height);
483
                }
484
            } else {
485
               App.destroySlimScroll(target.find('.full-height-content-body')); // destroy slimscroll
486
 
487
                if (App.getViewPort().width >= resBreakpointMd && target.hasClass("full-height-content-scrollable")) {
488
                    height = height - 35;
489
                    target.find('.full-height-content-body').css('height', height);
490
                    App.initSlimScroll(target.find('.full-height-content-body'));
491
                } else {
492
                    target.css('min-height', height);
493
                }
494
            }
495
        });
496
    };
497
    //* END:CORE HANDLERS *//
498
 
499
    return {
500
        // Main init methods to initialize the layout
501
        //IMPORTANT!!!: Do not modify the core handlers call order.
502
 
503
        initHeader: function() {
504
             handleHeader();
505
        },
506
 
507
        setSidebarMenuActiveLink: function(mode, el) {
508
            handleSidebarMenuActiveLink(mode, el);
509
        },
510
 
511
        initSidebar: function() {
512
            //layout handlers
513
            handleFixedSidebar(); // handles fixed sidebar menu
514
            handleSidebarMenu(); // handles main menu
515
            handleSidebarToggler(); // handles sidebar hide/show
516
 
517
            if (App.isAngularJsApp()) {
518
                handleSidebarMenuActiveLink('match'); // init sidebar active links
519
            }
520
 
521
            App.addResizeHandler(handleFixedSidebar); // reinitialize fixed sidebar on window resize
522
        },
523
 
524
        initContent: function() {
525
            handle100HeightContent(); // handles 100% height elements(block, portlet, etc)
526
            handleTabs(); // handle bootstrah tabs
527
 
528
            App.addResizeHandler(handleSidebarAndContentHeight); // recalculate sidebar & content height on window resize
529
            App.addResizeHandler(handle100HeightContent); // reinitialize content height on window resize
530
        },
531
 
532
        initFooter: function() {
533
            handleGoTop(); //handles scroll to top functionality in the footer
534
        },
535
 
536
        init: function () {
537
            this.initHeader();
538
            this.initSidebar();
539
            this.initContent();
540
            this.initFooter();
541
        },
542
 
543
        loadAjaxContent: function(url, sidebarMenuLink) {
544
            var pageContent = $('.page-content .page-content-body');
545
 
546
            App.startPageLoading({animate: true});
547
 
548
            $.ajax({
549
                type: "GET",
550
                cache: false,
551
                url: url,
552
                dataType: "html",
553
                success: function (res) {
554
                    App.stopPageLoading();
555
 
556
                    for (var i = 0; i < ajaxContentSuccessCallbacks.length; i++) {
557
                        ajaxContentSuccessCallbacks[i].call(res);
558
                    }
559
 
560
                    if (sidebarMenuLink.size() > 0 && sidebarMenuLink.parents('li.open').size() === 0) {
561
                        $('.page-sidebar-menu > li.open > a').click();
562
                    }
563
 
564
                    pageContent.html(res);
565
                    Layout.fixContentHeight(); // fix content height
566
                    App.initAjax(); // initialize core stuff
567
                },
568
                error: function (res, ajaxOptions, thrownError) {
569
                    App.stopPageLoading();
570
                    pageContent.html('<h4>Could not load the requested content.</h4>');
571
 
572
                    for (var i = 0; i < ajaxContentErrorCallbacks.length; i++) {
573
                        ajaxContentSuccessCallbacks[i].call(res);
574
                    }
575
                }
576
            });
577
        },
578
 
579
        addAjaxContentSuccessCallback: function(callback) {
580
            ajaxContentSuccessCallbacks.push(callback);
581
        },
582
 
583
        addAjaxContentErrorCallback: function(callback) {
584
            ajaxContentErrorCallbacks.push(callback);
585
        },
586
 
587
        //public function to fix the sidebar and content height accordingly
588
        fixContentHeight: function () {
589
            handleSidebarAndContentHeight();
590
        },
591
 
592
        initFixedSidebarHoverEffect: function() {
593
            handleFixedSidebarHoverEffect();
594
        },
595
 
596
        initFixedSidebar: function() {
597
            handleFixedSidebar();
598
        },
599
 
600
        getLayoutImgPath: function () {
601
            return App.getAssetsPath() + layoutImgPath;
602
        },
603
 
604
        getLayoutCssPath: function () {
605
            return App.getAssetsPath() + layoutCssPath;
606
        }
607
    };
608
 
609
}();
610
 
611
if (App.isAngularJsApp() === false) {
612
    jQuery(document).ready(function() {
613
        Layout.init(); // init metronic core componets
614
    });
615
}