/** Core script to handle the entire theme and core functions **/ var Metronic = function() { // IE mode var isRTL = false; var isIE8 = false; var isIE9 = false; var isIE10 = false; var resizeHandlers = []; var assetsPath = '../../assets/'; var globalImgPath = 'global/img/'; var globalPluginsPath = 'global/plugins/'; var globalCssPath = 'global/css/'; // theme layout color set var brandColors = { 'blue': '#89C4F4', 'red': '#F3565D', 'green': '#1bbc9b', 'purple': '#9b59b6', 'grey': '#95a5a6', 'yellow': '#F8CB00' }; // initializes main settings var handleInit = function() { if ($('body').css('direction') === 'rtl') { isRTL = true; } isIE8 = !!navigator.userAgent.match(/MSIE 8.0/); isIE9 = !!navigator.userAgent.match(/MSIE 9.0/); isIE10 = !!navigator.userAgent.match(/MSIE 10.0/); if (isIE10) { $('html').addClass('ie10'); // detect IE10 version } if (isIE10 || isIE9 || isIE8) { $('html').addClass('ie'); // detect IE10 version } }; // runs callback functions set by Metronic.addResponsiveHandler(). var _runResizeHandlers = function() { // reinitialize other subscribed elements for (var i = 0; i < resizeHandlers.length; i++) { var each = resizeHandlers[i]; each.call(); } }; // handle the layout reinitialization on window resize var handleOnResize = function() { var resize; if (isIE8) { var currheight; $(window).resize(function() { if (currheight == document.documentElement.clientHeight) { return; //quite event since only body resized not window. } if (resize) { clearTimeout(resize); } resize = setTimeout(function() { _runResizeHandlers(); }, 50); // wait 50ms until window resize finishes. currheight = document.documentElement.clientHeight; // store last body client height }); } else { $(window).resize(function() { if (resize) { clearTimeout(resize); } resize = setTimeout(function() { _runResizeHandlers(); }, 50); // wait 50ms until window resize finishes. }); } }; // Handles portlet tools & actions var handlePortletTools = function() { // handle portlet remove $('body').on('click', '.portlet > .portlet-title > .tools > a.remove', function(e) { e.preventDefault(); var portlet = $(this).closest(".portlet"); if ($('body').hasClass('page-portlet-fullscreen')) { $('body').removeClass('page-portlet-fullscreen'); } portlet.find('.portlet-title .fullscreen').tooltip('destroy'); portlet.find('.portlet-title > .tools > .reload').tooltip('destroy'); portlet.find('.portlet-title > .tools > .remove').tooltip('destroy'); portlet.find('.portlet-title > .tools > .config').tooltip('destroy'); portlet.find('.portlet-title > .tools > .collapse, .portlet > .portlet-title > .tools > .expand').tooltip('destroy'); portlet.remove(); }); // handle portlet fullscreen $('body').on('click', '.portlet > .portlet-title .fullscreen', function(e) { e.preventDefault(); var portlet = $(this).closest(".portlet"); if (portlet.hasClass('portlet-fullscreen')) { $(this).removeClass('on'); portlet.removeClass('portlet-fullscreen'); $('body').removeClass('page-portlet-fullscreen'); portlet.children('.portlet-body').css('height', 'auto'); } else { var height = Metronic.getViewPort().height - portlet.children('.portlet-title').outerHeight() - parseInt(portlet.children('.portlet-body').css('padding-top')) - parseInt(portlet.children('.portlet-body').css('padding-bottom')); $(this).addClass('on'); portlet.addClass('portlet-fullscreen'); $('body').addClass('page-portlet-fullscreen'); portlet.children('.portlet-body').css('height', height); } }); $('body').on('click', '.portlet > .portlet-title > .tools > a.reload', function(e) { e.preventDefault(); var el = $(this).closest(".portlet").children(".portlet-body"); var url = $(this).attr("data-url"); var error = $(this).attr("data-error-display"); if (url) { Metronic.blockUI({ target: el, animate: true, overlayColor: 'none' }); $.ajax({ type: "GET", cache: false, url: url, dataType: "html", success: function(res) { Metronic.unblockUI(el); el.html(res); }, error: function(xhr, ajaxOptions, thrownError) { Metronic.unblockUI(el); var msg = 'Error on reloading the content. Please check your connection and try again.'; if (error == "toastr" && toastr) { toastr.error(msg); } else if (error == "notific8" && $.notific8) { $.notific8('zindex', 11500); $.notific8(msg, { theme: 'ruby', life: 3000 }); } else { alert(msg); } } }); } else { // for demo purpose Metronic.blockUI({ target: el, animate: true, overlayColor: 'none' }); window.setTimeout(function() { Metronic.unblockUI(el); }, 1000); } }); // load ajax data on page init $('.portlet .portlet-title a.reload[data-load="true"]').click(); $('body').on('click', '.portlet > .portlet-title > .tools > .collapse, .portlet .portlet-title > .tools > .expand', function(e) { e.preventDefault(); var el = $(this).closest(".portlet").children(".portlet-body"); if ($(this).hasClass("collapse")) { $(this).removeClass("collapse").addClass("expand"); el.slideUp(200); } else { $(this).removeClass("expand").addClass("collapse"); el.slideDown(200); } }); }; // Handles custom checkboxes & radios using jQuery Uniform plugin var handleUniform = function() { if (!$().uniform) { return; } var test = $("input[type=checkbox]:not(.toggle, .md-check, .md-radiobtn, .make-switch, .icheck), input[type=radio]:not(.toggle, .md-check, .md-radiobtn, .star, .make-switch, .icheck)"); if (test.size() > 0) { test.each(function() { if ($(this).parents(".checker").size() === 0) { $(this).show(); $(this).uniform(); } }); } }; // Handlesmaterial design checkboxes var handleMaterialDesign = function() { // Material design ckeckbox and radio effects $('body').on('click', '.md-checkbox > label, .md-radio > label', function() { var the = $(this); // find the first span which is our circle/bubble var el = $(this).children('span:first-child'); // add the bubble class (we do this so it doesnt show on page load) el.addClass('inc'); // clone it var newone = el.clone(true); // add the cloned version before our original el.before(newone); // remove the original so that it is ready to run on next click $("." + el.attr("class") + ":last", the).remove(); }); if ($('body').hasClass('page-md')) { // Material design click effect // credit where credit's due; http://thecodeplayer.com/walkthrough/ripple-click-effect-google-material-design $('body').on('click', 'a.btn, button.btn, input.btn, label.btn', function(e) { var element, circle, d, x, y; element = $(this); if(element.find(".md-click-circle").length == 0) { element.prepend(""); } circle = element.find(".md-click-circle"); circle.removeClass("md-click-animate"); if(!circle.height() && !circle.width()) { d = Math.max(element.outerWidth(), element.outerHeight()); circle.css({height: d, width: d}); } x = e.pageX - element.offset().left - circle.width()/2; y = e.pageY - element.offset().top - circle.height()/2; circle.css({top: y+'px', left: x+'px'}).addClass("md-click-animate"); }); } // Floating labels var handleInput = function(el) { if (el.val() != "") { el.addClass('edited'); } else { el.removeClass('edited'); } } $('body').on('keydown', '.form-md-floating-label .form-control', function(e) { handleInput($(this)); }); $('body').on('blur', '.form-md-floating-label .form-control', function(e) { handleInput($(this)); }); } // Handles custom checkboxes & radios using jQuery iCheck plugin var handleiCheck = function() { if (!$().iCheck) { return; } $('.icheck').each(function() { var checkboxClass = $(this).attr('data-checkbox') ? $(this).attr('data-checkbox') : 'icheckbox_minimal-grey'; var radioClass = $(this).attr('data-radio') ? $(this).attr('data-radio') : 'iradio_minimal-grey'; if (checkboxClass.indexOf('_line') > -1 || radioClass.indexOf('_line') > -1) { $(this).iCheck({ checkboxClass: checkboxClass, radioClass: radioClass, insert: '
' + $(this).attr("data-label") }); } else { $(this).iCheck({ checkboxClass: checkboxClass, radioClass: radioClass }); } }); }; // Handles Bootstrap switches var handleBootstrapSwitch = function() { if (!$().bootstrapSwitch) { return; } $('.make-switch').bootstrapSwitch(); }; // Handles Bootstrap confirmations var handleBootstrapConfirmation = function() { if (!$().confirmation) { return; } $('[data-toggle=confirmation]').confirmation({ container: 'body', btnOkClass: 'btn-xs btn-success', btnCancelClass: 'btn-xs btn-danger'}); } // Handles Bootstrap Accordions. var handleAccordions = function() { $('body').on('shown.bs.collapse', '.accordion.scrollable', function(e) { Metronic.scrollTo($(e.target)); }); }; // Handles Bootstrap Tabs. var handleTabs = function() { //activate tab if tab id provided in the URL if (location.hash) { var tabid = location.hash.substr(1); $('a[href="#' + tabid + '"]').parents('.tab-pane:hidden').each(function() { var tabid = $(this).attr("id"); $('a[href="#' + tabid + '"]').click(); }); $('a[href="#' + tabid + '"]').click(); } if ($().tabdrop) { $('.tabbable-tabdrop .nav-pills, .tabbable-tabdrop .nav-tabs').tabdrop({ text: ' ' }); } }; // Handles Bootstrap Modals. var handleModals = function() { // fix stackable modal issue: when 2 or more modals opened, closing one of modal will remove .modal-open class. $('body').on('hide.bs.modal', function() { if ($('.modal:visible').size() > 1 && $('html').hasClass('modal-open') === false) { $('html').addClass('modal-open'); } else if ($('.modal:visible').size() <= 1) { $('html').removeClass('modal-open'); } }); // fix page scrollbars issue $('body').on('show.bs.modal', '.modal', function() { if ($(this).hasClass("modal-scroll")) { $('body').addClass("modal-open-noscroll"); } }); // fix page scrollbars issue $('body').on('hide.bs.modal', '.modal', function() { $('body').removeClass("modal-open-noscroll"); }); // remove ajax content and remove cache on modal closed $('body').on('hidden.bs.modal', '.modal:not(.modal-cached)', function () { $(this).removeData('bs.modal'); }); }; // Handles Bootstrap Tooltips. var handleTooltips = function() { // global tooltips $('.tooltips').tooltip(); // portlet tooltips $('.portlet > .portlet-title .fullscreen').tooltip({ container: 'body', title: 'Fullscreen' }); $('.portlet > .portlet-title > .tools > .reload').tooltip({ container: 'body', title: 'Reload' }); $('.portlet > .portlet-title > .tools > .remove').tooltip({ container: 'body', title: 'Remove' }); $('.portlet > .portlet-title > .tools > .config').tooltip({ container: 'body', title: 'Settings' }); $('.portlet > .portlet-title > .tools > .collapse, .portlet > .portlet-title > .tools > .expand').tooltip({ container: 'body', title: 'Collapse/Expand' }); }; // Handles Bootstrap Dropdowns var handleDropdowns = function() { /* Hold dropdown on click */ $('body').on('click', '.dropdown-menu.hold-on-click', function(e) { e.stopPropagation(); }); }; var handleAlerts = function() { $('body').on('click', '[data-close="alert"]', function(e) { $(this).parent('.alert').hide(); $(this).closest('.note').hide(); e.preventDefault(); }); $('body').on('click', '[data-close="note"]', function(e) { $(this).closest('.note').hide(); e.preventDefault(); }); $('body').on('click', '[data-remove="note"]', function(e) { $(this).closest('.note').remove(); e.preventDefault(); }); }; // Handle Hower Dropdowns var handleDropdownHover = function() { $('[data-hover="dropdown"]').not('.hover-initialized').each(function() { $(this).dropdownHover(); $(this).addClass('hover-initialized'); }); }; // Handle textarea autosize var handleTextareaAutosize = function() { if (typeof(autosize) == "function") { autosize(document.querySelector('textarea.autosizeme')); } } // Handles Bootstrap Popovers // last popep popover var lastPopedPopover; var handlePopovers = function() { $('.popovers').popover(); // close last displayed popover $(document).on('click.bs.popover.data-api', function(e) { if (lastPopedPopover) { lastPopedPopover.popover('hide'); } }); }; // Handles scrollable contents using jQuery SlimScroll plugin. var handleScrollers = function() { Metronic.initSlimScroll('.scroller'); }; // Handles Image Preview using jQuery Fancybox plugin var handleFancybox = function() { if (!jQuery.fancybox) { return; } if ($(".fancybox-button").size() > 0) { $(".fancybox-button").fancybox({ groupAttr: 'data-rel', prevEffect: 'none', nextEffect: 'none', closeBtn: true, helpers: { title: { type: 'inside' } } }); } }; // Fix input placeholder issue for IE8 and IE9 var handleFixInputPlaceholderForIE = function() { //fix html5 placeholder attribute for ie7 & ie8 if (isIE8 || isIE9) { // ie8 & ie9 // this is html5 placeholder fix for inputs, inputs with placeholder-no-fix class will be skipped(e.g: we need this for password fields) $('input[placeholder]:not(.placeholder-no-fix), textarea[placeholder]:not(.placeholder-no-fix)').each(function() { var input = $(this); if (input.val() === '' && input.attr("placeholder") !== '') { input.addClass("placeholder").val(input.attr('placeholder')); } input.focus(function() { if (input.val() == input.attr('placeholder')) { input.val(''); } }); input.blur(function() { if (input.val() === '' || input.val() == input.attr('placeholder')) { input.val(input.attr('placeholder')); } }); }); } }; // Handle Select2 Dropdowns var handleSelect2 = function() { if ($().select2) { $('.select2me').select2({ placeholder: "Select", allowClear: true }); } }; //* END:CORE HANDLERS *// return { //main function to initiate the theme init: function() { //IMPORTANT!!!: Do not modify the core handlers call order. //Core handlers handleInit(); // initialize core variables handleOnResize(); // set and handle responsive //UI Component handlers handleMaterialDesign(); // handle material design handleUniform(); // hanfle custom radio & checkboxes handleiCheck(); // handles custom icheck radio and checkboxes handleBootstrapSwitch(); // handle bootstrap switch plugin handleScrollers(); // handles slim scrolling contents handleFancybox(); // handle fancy box handleSelect2(); // handle custom Select2 dropdowns handlePortletTools(); // handles portlet action bar functionality(refresh, configure, toggle, remove) handleAlerts(); //handle closabled alerts handleDropdowns(); // handle dropdowns handleTabs(); // handle tabs handleTooltips(); // handle bootstrap tooltips handlePopovers(); // handles bootstrap popovers handleAccordions(); //handles accordions handleModals(); // handle modals handleBootstrapConfirmation(); // handle bootstrap confirmations handleTextareaAutosize(); // handle autosize textareas // Hacks handleFixInputPlaceholderForIE(); //IE8 & IE9 input placeholder issue fix }, //main function to initiate core javascript after ajax complete initAjax: function() { handleUniform(); // handles custom radio & checkboxes handleiCheck(); // handles custom icheck radio and checkboxes handleBootstrapSwitch(); // handle bootstrap switch plugin handleDropdownHover(); // handles dropdown hover handleScrollers(); // handles slim scrolling contents handleSelect2(); // handle custom Select2 dropdowns handleFancybox(); // handle fancy box handleDropdowns(); // handle dropdowns handleTooltips(); // handle bootstrap tooltips handlePopovers(); // handles bootstrap popovers handleAccordions(); //handles accordions handleBootstrapConfirmation(); // handle bootstrap confirmations }, //init main components initComponents: function() { this.initAjax(); }, //public function to remember last opened popover that needs to be closed on click setLastPopedPopover: function(el) { lastPopedPopover = el; }, //public function to add callback a function which will be called on window resize addResizeHandler: function(func) { resizeHandlers.push(func); }, //public functon to call _runresizeHandlers runResizeHandlers: function() { _runResizeHandlers(); }, // wrMetronicer function to scroll(focus) to an element scrollTo: function(el, offeset) { var pos = (el && el.size() > 0) ? el.offset().top : 0; if (el) { if ($('body').hasClass('page-header-fixed')) { pos = pos - $('.page-header').height(); } else if ($('body').hasClass('page-header-top-fixed')) { pos = pos - $('.page-header-top').height(); } else if ($('body').hasClass('page-header-menu-fixed')) { pos = pos - $('.page-header-menu').height(); } pos = pos + (offeset ? offeset : -1 * el.height()); } $('html,body').animate({ scrollTop: pos }, 'slow'); }, initSlimScroll: function(el) { $(el).each(function() { if ($(this).attr("data-initialized")) { return; // exit } var height; if ($(this).attr("data-height")) { height = $(this).attr("data-height"); } else { height = $(this).css('height'); } $(this).slimScroll({ allowPageScroll: true, // allow page scroll when the element scroll is ended size: '7px', color: ($(this).attr("data-handle-color") ? $(this).attr("data-handle-color") : '#bbb'), wrapperClass: ($(this).attr("data-wrapper-class") ? $(this).attr("data-wrapper-class") : 'slimScrollDiv'), railColor: ($(this).attr("data-rail-color") ? $(this).attr("data-rail-color") : '#eaeaea'), position: isRTL ? 'left' : 'right', height: height, alwaysVisible: ($(this).attr("data-always-visible") == "1" ? true : false), railVisible: ($(this).attr("data-rail-visible") == "1" ? true : false), disableFadeOut: true }); $(this).attr("data-initialized", "1"); }); }, destroySlimScroll: function(el) { $(el).each(function() { if ($(this).attr("data-initialized") === "1") { // destroy existing instance before updating the height $(this).removeAttr("data-initialized"); $(this).removeAttr("style"); var attrList = {}; // store the custom attribures so later we will reassign. if ($(this).attr("data-handle-color")) { attrList["data-handle-color"] = $(this).attr("data-handle-color"); } if ($(this).attr("data-wrapper-class")) { attrList["data-wrapper-class"] = $(this).attr("data-wrapper-class"); } if ($(this).attr("data-rail-color")) { attrList["data-rail-color"] = $(this).attr("data-rail-color"); } if ($(this).attr("data-always-visible")) { attrList["data-always-visible"] = $(this).attr("data-always-visible"); } if ($(this).attr("data-rail-visible")) { attrList["data-rail-visible"] = $(this).attr("data-rail-visible"); } $(this).slimScroll({ wrapperClass: ($(this).attr("data-wrapper-class") ? $(this).attr("data-wrapper-class") : 'slimScrollDiv'), destroy: true }); var the = $(this); // reassign custom attributes $.each(attrList, function(key, value) { the.attr(key, value); }); } }); }, // function to scroll to the top scrollTop: function() { Metronic.scrollTo(); }, // wrMetronicer function to block element(indicate loading) blockUI: function(options) { options = $.extend(true, {}, options); var html = ''; if (options.animate) { html = ' '; } else if (options.iconOnly) { html = ''; } else if (options.textOnly) { html = ' '; } else { html = ' '; } if (options.target) { // element blocking var el = $(options.target); if (el.height() <= ($(window).height())) { options.cenrerY = true; } el.block({ message: html, baseZ: options.zIndex ? options.zIndex : 1000, centerY: options.cenrerY !== undefined ? options.cenrerY : false, css: { top: '10%', border: '0', padding: '0', backgroundColor: 'none' }, overlayCSS: { backgroundColor: options.overlayColor ? options.overlayColor : '#555', opacity: options.boxed ? 0.05 : 0.1, cursor: 'wait' } }); } else { // page blocking $.blockUI({ message: html, baseZ: options.zIndex ? options.zIndex : 1000, css: { border: '0', padding: '0', backgroundColor: 'none' }, overlayCSS: { backgroundColor: options.overlayColor ? options.overlayColor : '#555', opacity: options.boxed ? 0.05 : 0.1, cursor: 'wait' } }); } }, // wrMetronicer function to un-block element(finish loading) unblockUI: function(target) { if (target) { $(target).unblock({ onUnblock: function() { $(target).css('position', ''); $(target).css('zoom', ''); } }); } else { $.unblockUI(); } }, startPageLoading: function(options) { if (options && options.animate) { $('.page-spinner-bar').remove(); $('body').append(' '); } else { $('.page-loading').remove(); $('body').append('