Subversion Repositories Integrator Subversion

Rev

Details | Last modification | View Log | RSS feed

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