/** 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 = assetsPath + 'global/img/'; var globalPluginsPath = assetsPath + 'global/plugins/'; var loadedResources = {}; // 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(); $(this).closest(".portlet").remove(); if ($('body').hasClass('page-portlet-fullscreen')) { $('body').removeClass('page-portlet-fullscreen'); } }); // 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, .make-switch, .icheck), input[type=radio]:not(.toggle, .star, .make-switch, .icheck)"); if (test.size() > 0) { test.each(function() { if ($(this).parents(".checker").size() === 0) { $(this).show(); $(this).uniform(); } }); } }; // 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 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(); } }; // 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'); } }); $('body').on('show.bs.modal', '.modal', function() { if ($(this).hasClass("modal-scroll")) { $('body').addClass("modal-open-noscroll"); } }); $('body').on('hide.bs.modal', '.modal', function() { $('body').removeClass("modal-open-noscroll"); }); }; // 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(); e.preventDefault(); }); }; // Handle Hower Dropdowns var handleDropdownHover = function() { $('[data-hover="dropdown"]').not('.hover-initialized').each(function() { $(this).dropdownHover(); $(this).addClass('hover-initialized'); }); }; // 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 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 // 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 }, //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(); } 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 = '
  ' + (options.message ? options.message : 'LOADING...') + '
'; } else { html = '
  ' + (options.message ? options.message : 'LOADING...') + '
'; } 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('
  ' + (options && options.message ? options.message : 'Loading...') + '
'); } }, stopPageLoading: function() { $('.page-loading, .page-spinner-bar').remove(); }, alert: function(options) { options = $.extend(true, { container: "", // alerts parent container(by default placed after the page breadcrumbs) place: "append", // append or prepent in container type: 'success', // alert's type message: "", // alert's message close: true, // make alert closable reset: true, // close all previouse alerts first focus: true, // auto scroll to the alert after shown closeInSeconds: 0, // auto close after defined seconds icon: "" // put icon before the message }, options); var id = Metronic.getUniqueID("Metronic_alert"); var html = '
' + (options.close ? '' : '') + (options.icon !== "" ? ' ' : '') + options.message + '
'; if (options.reset) { $('.Metronic-alerts').remove(); } if (!options.container) { if ($('body').hasClass("page-container-bg-solid")) { $('.page-title').after(html); } else { if ($('.page-bar').size() > 0) { $('.page-bar').after(html); } else { $('.page-breadcrumb').after(html); } } } else { if (options.place == "append") { $(options.container).append(html); } else { $(options.container).prepend(html); } } if (options.focus) { Metronic.scrollTo($('#' + id)); } if (options.closeInSeconds > 0) { setTimeout(function() { $('#' + id).remove(); }, options.closeInSeconds * 1000); } return id; }, // initializes uniform elements initUniform: function(els) { if (els) { $(els).each(function() { if ($(this).parents(".checker").size() === 0) { $(this).show(); $(this).uniform(); } }); } else { handleUniform(); } }, //wrMetronicer function to update/sync jquery uniform checkbox & radios updateUniform: function(els) { $.uniform.update(els); // update the uniform checkbox & radios UI after the actual input control state changed }, //public function to initialize the fancybox plugin initFancybox: function() { handleFancybox(); }, //public helper function to get actual input value(used in IE9 and IE8 due to placeholder attribute not supported) getActualVal: function(el) { el = $(el); if (el.val() === el.attr("placeholder")) { return ""; } return el.val(); }, //public function to get a paremeter by name from URL getURLParameter: function(paramName) { var searchString = window.location.search.substring(1), i, val, params = searchString.split("&"); for (i = 0; i < params.length; i++) { val = params[i].split("="); if (val[0] == paramName) { return unescape(val[1]); } } return null; }, // check for device touch support isTouchDevice: function() { try { document.createEvent("TouchEvent"); return true; } catch (e) { return false; } }, // To get the correct viewport width based on http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/ getViewPort: function() { var e = window, a = 'inner'; if (!('innerWidth' in window)) { a = 'client'; e = document.documentElement || document.body; } return { width: e[a + 'Width'], height: e[a + 'Height'] }; }, getUniqueID: function(prefix) { return 'prefix_' + Math.floor(Math.random() * (new Date()).getTime()); }, // check IE8 mode isIE8: function() { return isIE8; }, // check IE9 mode isIE9: function() { return isIE9; }, //check RTL mode isRTL: function() { return isRTL; }, getAssetsPath: function() { return assetsPath; }, setAssetsPath: function(path) { assetsPath = path; }, setGlobalImgPath: function(path) { globalImgPath = assetsPath + path; }, getGlobalImgPath: function() { return globalImgPath; }, setGlobalPluginsPath: function(path) { globalPluginsPath = assetsPath + path; }, getGlobalPluginsPath: function() { return globalPluginsPath; }, // get layout color code by color name getBrandColor: function(name) { if (brandColors[name]) { return brandColors[name]; } else { return ''; } }, loadResources: function(resources, callback) { var counter = 0; var loaded = 0; for(var i in resources) { var resource = resources[i]; if (!loadedResources[resource.path]) { var el; loadedResources[resource.path] = true; if (resource.type === 'js') { counter++; var body = document.getElementsByTagName("body")[0]; el = document.createElement("script"); el.type = "text/javascript"; el.src = resource.path; // do callback only based on scripts if (callback) { el.onload = function(){ loaded++; if (loaded === counter) { callback(); } }; } body.appendChild(el); } else if (resource.type === 'css') { var head = document.getElementsByTagName("head")[0]; el = document.createElement("link"); el.type = "text/css"; el.href = resource.path; head.appendChild(el); } } } } }; }();