text: /*
   *  Document   : app.js
   *  Author     : pixelcave
   *  Description: UI Framework Custom Functionality (available to all pages)
   *
   */
  
  var App = function() {
      // Helper variables - set in uiInit()
      var $lHtml, $lBody, $lPage, $lSidebar, $lSidebarScroll, $lSideOverlay, $lSideOverlayScroll, $lHeader, $lMain, $lFooter;
  
      /*
       ********************************************************************************************
       *
       * BASE UI FUNCTIONALITY
       *
       * Functions which handle vital UI functionality such as main navigation and layout
       * They are auto initialized in every page
       *
       *********************************************************************************************
       */
  
      // User Interface init
      var uiInit = function() {
          // Set variables
          $lHtml              = jQuery('html');
          $lBody              = jQuery('body');
          $lPage              = jQuery('#page-container');
          $lSidebar           = jQuery('#sidebar');
          $lSidebarScroll     = jQuery('#sidebar-scroll');
          $lSideOverlay       = jQuery('#side-overlay');
          $lSideOverlayScroll = jQuery('#side-overlay-scroll');
          $lHeader            = jQuery('#header-navbar');
          $lMain              = jQuery('#main-container');
          $lFooter            = jQuery('#page-footer');
  
          // Initialize Tooltips
          jQuery('[data-toggle="tooltip"], .js-tooltip').tooltip({
              container: 'body',
              animation: false
          });
  
          // Initialize Popovers
          jQuery('[data-toggle="popover"], .js-popover').popover({
              container: 'body',
              animation: true,
              trigger: 'hover'
          });
  
          // Initialize Tabs
          jQuery('[data-toggle="tabs"] a, .js-tabs a').click(function(e){
              e.preventDefault();
              jQuery(this).tab('show');
          });
  
          // Init form placeholder (for IE9)
          jQuery('.form-control').placeholder();
      };
  
      // Layout functionality
      var uiLayout = function() {
          // Resizes #main-container min height (push footer to the bottom)
          var $resizeTimeout;
  
          if ($lMain.length) {
              uiHandleMain();
  
              jQuery(window).on('resize orientationchange', function(){
                  clearTimeout($resizeTimeout);
  
                  $resizeTimeout = setTimeout(function(){
                      uiHandleMain();
                  }, 150);
              });
          }
  
          // Init sidebar and side overlay custom scrolling
          uiHandleScroll('init');
  
          // Init transparent header functionality (solid on scroll - used in frontend)
          if ($lPage.hasClass('header-navbar-fixed') && $lPage.hasClass('header-navbar-transparent')) {
              jQuery(window).on('scroll', function(){
                  if (jQuery(this).scrollTop() > 20) {
                      $lPage.addClass('header-navbar-scroll');
                  } else {
                      $lPage.removeClass('header-navbar-scroll');
                  }
              });
          }
  
          // Call layout API on button click
          jQuery('[data-toggle="layout"]').on('click', function(){
              var $btn = jQuery(this);
  
              uiLayoutApi($btn.data('action'));
  
              if ($lHtml.hasClass('no-focus')) {
                  $btn.blur();
              }
          });
      };
  
      // Resizes #main-container to fill empty space if exists
      var uiHandleMain = function() {
          var $hWindow     = jQuery(window).height();
          var $hHeader     = $lHeader.outerHeight();
          var $hFooter     = $lFooter.outerHeight();
  
          if ($lPage.hasClass('header-navbar-fixed')) {
              $lMain.css('min-height', $hWindow - $hFooter);
          } else {
              $lMain.css('min-height', $hWindow - ($hHeader + $hFooter));
          }
      };
  
      // Handles sidebar and side overlay custom scrolling functionality
      var uiHandleScroll = function($mode) {
          var $windowW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  
          // Init scrolling
          if ($mode === 'init') {
              // Init scrolling only if required the first time
              uiHandleScroll();
  
              // Handle scrolling on resize or orientation change
              var $sScrollTimeout;
  
              jQuery(window).on('resize orientationchange', function(){
                  clearTimeout($sScrollTimeout);
  
                  $sScrollTimeout = setTimeout(function(){
                      uiHandleScroll();
                  }, 150);
              });
          } else {
              // If screen width is greater than 991 pixels and .side-scroll is added to #page-container
              if ($windowW > 991 && $lPage.hasClass('side-scroll')) {
                  // Turn scroll lock off (sidebar and side overlay - slimScroll will take care of it)
                  jQuery($lSidebar).scrollLock('disable');
                  jQuery($lSideOverlay).scrollLock('disable');
  
                  // If sidebar scrolling does not exist init it..
                  if ($lSidebarScroll.length && (!$lSidebarScroll.parent('.slimScrollDiv').length)) {
                      $lSidebarScroll.slimScroll({
                          height: $lSidebar.outerHeight(),
                          color: '#fff',
                          size: '5px',
                          opacity : .35,
                          wheelStep : 15,
                          distance : '2px',
                          railVisible: false,
                          railOpacity: 1
                      });
                  }
                  else { // ..else resize scrolling height
                      $lSidebarScroll
                          .add($lSidebarScroll.parent())
                          .css('height', $lSidebar.outerHeight());
                  }
              } else {
                  // Turn scroll lock on (sidebar and side overlay)
                  jQuery($lSidebar).scrollLock();
                  jQuery($lSideOverlay).scrollLock();
  
                  // If sidebar scrolling exists destroy it..
                  if ($lSidebarScroll.length && $lSidebarScroll.parent('.slimScrollDiv').length) {
                      $lSidebarScroll
                          .slimScroll({destroy: true});
                      $lSidebarScroll
                          .attr('style', '');
                  }
              }
          }
      };
  
      // Layout API
      var uiLayoutApi = function($mode) {
          var $windowW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  
          // Mode selection
          switch($mode) {
              case 'sidebar_pos_toggle':
                  $lPage.toggleClass('sidebar-l sidebar-r');
                  break;
              case 'sidebar_pos_left':
                  $lPage
                      .removeClass('sidebar-r')
                      .addClass('sidebar-l');
                  break;
              case 'sidebar_pos_right':
                  $lPage
                      .removeClass('sidebar-l')
                      .addClass('sidebar-r');
                  break;
              case 'sidebar_toggle':
                  if ($windowW > 991) {
                      $lPage.toggleClass('sidebar-o');
                  } else {
                      $lPage.toggleClass('sidebar-o-xs');
                  }
                  break;
              case 'sidebar_open':
                  if ($windowW > 991) {
                      $lPage.addClass('sidebar-o');
                  } else {
                      $lPage.addClass('sidebar-o-xs');
                  }
                  break;
              case 'sidebar_close':
                  if ($windowW > 991) {
                      $lPage.removeClass('sidebar-o');
                  } else {
                      $lPage.removeClass('sidebar-o-xs');
                  }
                  break;
              case 'sidebar_mini_toggle':
                  if ($windowW > 991) {
                      if ($lPage.hasClass('sidebar-mini')) {
                          $lPage.removeClass('sidebar-mini');
                          Cookies.remove('sidebarMini');
                      } else {
                          $lPage.addClass('sidebar-mini');
                          Cookies.set('sidebarMini', 'true', { expires: 7 });
                      }
                  }
                  break;
              case 'sidebar_mini_on':
                  if ($windowW > 991) {
                      $lPage.addClass('sidebar-mini');
                  }
                  break;
              case 'sidebar_mini_off':
                  if ($windowW > 991) {
                      $lPage.removeClass('sidebar-mini');
                  }
                  break;
              case 'side_overlay_toggle':
                  // If side overlay scrolling does not exist init it..
                  if ($lSideOverlayScroll.length && (!$lSideOverlayScroll.parent('.slimScrollDiv').length)) {
                      $lSideOverlayScroll.slimScroll({
                          height: $lSideOverlay.outerHeight(),
                          color: '#000',
                          size: '5px',
                          opacity : .35,
                          wheelStep : 15,
                          distance : '2px',
                          railVisible: false,
                          railOpacity: 1
                      });
                  }
                  else { // ..else resize scrolling height
                      $lSideOverlayScroll
                          .add($lSideOverlayScroll.parent())
                          .css('height', $lSideOverlay.outerHeight());
                  }
                  $lPage.toggleClass('side-overlay-o');
                  break;
              case 'side_overlay_open':
                  $lPage.addClass('side-overlay-o');
                  break;
              case 'side_overlay_close':
                  // If side overlay scrolling exists destroy it..
                  if ($lSideOverlayScroll.length && $lSideOverlayScroll.parent('.slimScrollDiv').length) {
                      $lSideOverlayScroll
                          .slimScroll({destroy: true});
                      $lSideOverlayScroll
                          .attr('style', '');
                  }
                  $lPage.removeClass('side-overlay-o');
                  break;
              case 'side_overlay_hoverable_toggle':
                  $lPage.toggleClass('side-overlay-hover');
                  break;
              case 'side_overlay_hoverable_on':
                  $lPage.addClass('side-overlay-hover');
                  break;
              case 'side_overlay_hoverable_off':
                  $lPage.removeClass('side-overlay-hover');
                  break;
              case 'header_fixed_toggle':
                  $lPage.toggleClass('header-navbar-fixed');
                  break;
              case 'header_fixed_on':
                  $lPage.addClass('header-navbar-fixed');
                  break;
              case 'header_fixed_off':
                  $lPage.removeClass('header-navbar-fixed');
                  break;
              case 'side_scroll_toggle':
                  $lPage.toggleClass('side-scroll');
                  uiHandleScroll();
                  break;
              case 'side_scroll_on':
                  $lPage.addClass('side-scroll');
                  uiHandleScroll();
                  break;
              case 'side_scroll_off':
                  $lPage.removeClass('side-scroll');
                  uiHandleScroll();
                  break;
              default:
                  return false;
          }
      };
  
      // Main navigation functionality
      var uiNav = function() {
          // When a submenu link is clicked
          jQuery('[data-toggle="nav-submenu"]').on('click', function(e){
              // Get link
              var $link = jQuery(this);
  
              // Get link's parent
              var $parentLi = $link.parent('li');
  
              if ($parentLi.hasClass('open')) { // If submenu is open, close it..
                  $parentLi.removeClass('open');
              } else { // .. else if submenu is closed, close all other (same level) submenus first before open it
                  $link
                      .closest('ul')
                      .find('> li')
                      .removeClass('open');
  
                  $parentLi
                      .addClass('open');
              }
  
              // Remove focus from submenu link
              if ($lHtml.hasClass('no-focus')) {
                  $link.blur();
              }
  
              return false;
          });
      };
  
      // Blocks options functionality
      var uiBlocks = function() {
          // Init default icons fullscreen and content toggle buttons
          uiBlocksApi(false, 'init');
  
          // Call blocks API on option button click
          jQuery('[data-toggle="block-option"]').on('click', function(){
              uiBlocksApi(jQuery(this).closest('.block'), jQuery(this).data('action'));
          });
      };
  
      // Blocks API
      var uiBlocksApi = function($block, $mode) {
          // Set default icons for fullscreen and content toggle buttons
          var $iconFullscreen         = 'si si-size-fullscreen';
          var $iconFullscreenActive   = 'si si-size-actual';
          var $iconContent            = 'si si-arrow-up';
          var $iconContentActive      = 'si si-arrow-down';
  
          if ($mode === 'init') {
              // Auto add the default toggle icons to fullscreen and content toggle buttons
              jQuery('[data-toggle="block-option"][data-action="fullscreen_toggle"]').each(function(){
                  var $this = jQuery(this);
  
                  $this.html('<i class="' + (jQuery(this).closest('.block').hasClass('block-opt-fullscreen') ? $iconFullscreenActive : $iconFullscreen) + '"></i>');
              });
  
              jQuery('[data-toggle="block-option"][data-action="content_toggle"]').each(function(){
                  var $this = jQuery(this);
  
                  $this.html('<i class="' + ($this.closest('.block').hasClass('block-opt-hidden') ? $iconContentActive : $iconContent) + '"></i>');
              });
          } else {
              // Get block element
              var $elBlock = ($block instanceof jQuery) ? $block : jQuery($block);
  
              // If element exists, procceed with blocks functionality
              if ($elBlock.length) {
                  // Get block option buttons if exist (need them to update their icons)
                  var $btnFullscreen  = jQuery('[data-toggle="block-option"][data-action="fullscreen_toggle"]', $elBlock);
                  var $btnToggle      = jQuery('[data-toggle="block-option"][data-action="content_toggle"]', $elBlock);
  
                  // Mode selection
                  switch($mode) {
                      case 'fullscreen_toggle':
                          $elBlock.toggleClass('block-opt-fullscreen');
  
                          // Enable/disable scroll lock to block
                          if ($elBlock.hasClass('block-opt-fullscreen')) {
                              jQuery($elBlock).scrollLock();
                          } else {
                              jQuery($elBlock).scrollLock('disable');
                          }
  
                          // Update block option icon
                          if ($btnFullscreen.length) {
                              if ($elBlock.hasClass('block-opt-fullscreen')) {
                                  jQuery('i', $btnFullscreen)
                                      .removeClass($iconFullscreen)
                                      .addClass($iconFullscreenActive);
                              } else {
                                  jQuery('i', $btnFullscreen)
                                      .removeClass($iconFullscreenActive)
                                      .addClass($iconFullscreen);
                              }
                          }
                          if (typeof(init_table) === "function") {
                              init_table();
                          }
                          break;
                      case 'fullscreen_on':
                          $elBlock.addClass('block-opt-fullscreen');
  
                          // Enable scroll lock to block
                          jQuery($elBlock).scrollLock();
  
                          // Update block option icon
                          if ($btnFullscreen.length) {
                              jQuery('i', $btnFullscreen)
                                  .removeClass($iconFullscreen)
                                  .addClass($iconFullscreenActive);
                          }
                          break;
                      case 'fullscreen_off':
                          $elBlock.removeClass('block-opt-fullscreen');
  
                          // Disable scroll lock to block
                          jQuery($elBlock).scrollLock('disable');
  
                          // Update block option icon
                          if ($btnFullscreen.length) {
                              jQuery('i', $btnFullscreen)
                                  .removeClass($iconFullscreenActive)
                                  .addClass($iconFullscreen);
                          }
                          break;
                      case 'content_toggle':
                          $elBlock.toggleClass('block-opt-hidden');
  
                          // Update block option icon
                          if ($btnToggle.length) {
                              if ($elBlock.hasClass('block-opt-hidden')) {
                                  jQuery('i', $btnToggle)
                                      .removeClass($iconContent)
                                      .addClass($iconContentActive);
                              } else {
                                  jQuery('i', $btnToggle)
                                      .removeClass($iconContentActive)
                                      .addClass($iconContent);
                              }
                          }
                          break;
                      case 'content_hide':
                          $elBlock.addClass('block-opt-hidden');
  
                          // Update block option icon
                          if ($btnToggle.length) {
                              jQuery('i', $btnToggle)
                                  .removeClass($iconContent)
                                  .addClass($iconContentActive);
                          }
                          break;
                      case 'content_show':
                          $elBlock.removeClass('block-opt-hidden');
  
                          // Update block option icon
                          if ($btnToggle.length) {
                              jQuery('i', $btnToggle)
                                  .removeClass($iconContentActive)
                                  .addClass($iconContent);
                          }
                          break;
                      case 'refresh_toggle':
                          $elBlock.toggleClass('block-opt-refresh');
  
                          // Return block to normal state if the demostration mode is on in the refresh option button - data-action-mode="demo"
                          if (jQuery('[data-toggle="block-option"][data-action="refresh_toggle"][data-action-mode="demo"]', $elBlock).length) {
                              setTimeout(function(){
                                  $elBlock.removeClass('block-opt-refresh');
                              }, 2000);
                          }
                          break;
                      case 'state_loading':
                          $elBlock.addClass('block-opt-refresh');
                          break;
                      case 'state_normal':
                          $elBlock.removeClass('block-opt-refresh');
                          break;
                      case 'close':
                          $elBlock.hide();
                          break;
                      case 'open':
                          $elBlock.show();
                          break;
                      default:
                          return false;
                  }
              }
          }
      };
  
      // Material inputs helper
      var uiForms = function() {
          jQuery('.form-material.floating > .form-control').each(function(){
              var $input  = jQuery(this);
              var $parent = $input.parent('.form-material');
  
              if ($input.val()) {
                  $parent.addClass('open');
              }
  
              $input.on('change', function(){
                  if ($input.val()) {
                      $parent.addClass('open');
                  } else {
                      $parent.removeClass('open');
                  }
              });
          });
      };
  
      // Set active color themes functionality
      var uiHandleTheme = function() {
          var $cssTheme = jQuery('#css-theme');
  
          // When a color theme link is clicked
          jQuery('[data-toggle="theme"]').on('click', function(){
              var $this   = jQuery(this);
              var $theme  = $this.data('theme');
              var $css    = $this.data('css');
  
              Dolphin.loading();
              jQuery.get(dolphin.theme_url, {theme: $theme}, function (res) {
                  Dolphin.loading('hide');
                  if (res.code) {
                      // Set this color theme link as active
                      jQuery('[data-toggle="theme"]')
                          .parent('li')
                          .removeClass('active');
  
                      jQuery('[data-toggle="theme"][data-theme="' + $theme + '"]')
                          .parent('li')
                          .addClass('active');
  
                      // Update color theme
                      if ($theme === 'default') {
                          if ($cssTheme.length) {
                              $cssTheme.remove();
                          }
                      } else {
                          if ($cssTheme.length) {
                              $cssTheme.attr('href', $css);
                          } else {
                              jQuery('#css-main')
                                  .after('<link rel="stylesheet" id="css-theme" href="' + $css + '">');
                          }
                      }
                      $cssTheme = jQuery('#css-theme');
                      Dolphin.notify(res.msg, 'success');
                  } else {
                      Dolphin.notify(res.msg, 'danger');
                  }
              });
          });
      };
  
      // Scroll to element animation helper
      var uiScrollTo = function() {
          jQuery('[data-toggle="scroll-to"]').on('click', function(){
              var $this   = jQuery(this);
              var $target = $this.data('target');
              var $speed  = $this.data('speed') ? $this.data('speed') : 1000;
  
              jQuery('html, body').animate({
                  scrollTop: jQuery($target).offset().top
              }, $speed);
          });
      };
  
      // Toggle class helper
      var uiToggleClass = function() {
          jQuery('[data-toggle="class-toggle"]').on('click', function(){
              var $el = jQuery(this);
  
              jQuery($el.data('target').toString()).toggleClass($el.data('class').toString());
  
              if ($lHtml.hasClass('no-focus')) {
                  $el.blur();
              }
          });
      };
  
      // Add the correct copyright year
      var uiYearCopy = function() {
          var $date       = new Date();
          var $yearCopy   = jQuery('.js-year-copy');
  
          if ($date.getFullYear() === 2015) {
              $yearCopy.html('2015');
          } else {
              $yearCopy.html('2015-' + $date.getFullYear().toString().substr(2,2));
          }
      };
  
      // Manage page loading screen functionality
      var uiLoader = function($mode) {
          var $lpageLoader = jQuery('#page-loader');
  
          if ($mode === 'show') {
              if ($lpageLoader.length) {
                  $lpageLoader.fadeIn(250);
              } else {
                  $lBody.prepend('<div id="page-loader"></div>');
              }
          } else if ($mode === 'hide') {
              if ($lpageLoader.length) {
                  $lpageLoader.fadeOut(250);
              }
          }
  
          return false;
      };
  
      /*
       ********************************************************************************************
       *
       * UI HELPERS (ON DEMAND)
       *
       * Third party plugin inits or various custom user interface helpers to extend functionality
       * They need to be called in a page to be initialized. They are included here to be easy to
       * init them on demand on multiple pages (usually repeated init code in common components)
       *
       ********************************************************************************************
       */
  
      /*
       * Print Page functionality
       *
       * App.initHelper('print-page');
       *
       */
      var uiHelperPrint = function() {
          // Store all #page-container classes
          var $pageCls = $lPage.prop('class');
  
          // Remove all classes from #page-container
          $lPage.prop('class', '');
  
          // Print the page
          window.print();
  
          // Restore all #page-container classes
          $lPage.prop('class', $pageCls);
      };
  
      /*
       * Custom Table functionality such as section toggling or checkable rows
       *
       * App.initHelper('table-tools');
       *
       */
  
      // Table sections functionality
      var uiHelperTableToolsSections = function(){
          // For each table
          jQuery('.js-table-sections').each(function(){
              var $table = jQuery(this);
  
              // When a row is clicked in tbody.js-table-sections-header
              jQuery('.js-table-sections-header > tr', $table).on('click', function(e) {
                  var $row    = jQuery(this);
                  var $tbody  = $row.parent('tbody');
  
                  if (! $tbody.hasClass('open')) {
                      jQuery('tbody', $table).removeClass('open');
                  }
  
                  $tbody.toggleClass('open');
              });
          });
      };
  
      // Checkable table functionality
      var uiHelperTableToolsCheckable = function() {
          // For each table
          jQuery('.js-table-checkable').each(function(){
              var $table = jQuery(this);
              var $table_target = jQuery('.js-table-checkable-target');
  
              // When a checkbox is clicked in thead
              jQuery('thead input:checkbox', $table).on('click', function() {
                  var $checkedStatus = jQuery(this).prop('checked');
  
                  // Check or uncheck all checkboxes in tbody
                  jQuery('tbody input[name="ids[]"]:checkbox', $table_target).each(function() {
                      var $checkbox = jQuery(this);
  
                      $checkbox.prop('checked', $checkedStatus);
                      uiHelperTableToolscheckRow($checkbox, $checkedStatus);
                  });
              });
  
              // When a checkbox is clicked in tbody
              jQuery('tbody input[name="ids[]"]:checkbox', $table_target).on('click', function() {
                  var $checkbox = jQuery(this);
  
                  uiHelperTableToolscheckRow($checkbox, $checkbox.prop('checked'));
              });
          });
  
          jQuery('.js-table-checkable-left').each(function(){
              var $table = jQuery(this);
              var $table_target = jQuery('.js-table-checkable-target-left');
              var $tr = $table_target.find('tr');
  
              // When a checkbox is clicked in thead
              jQuery('thead input:checkbox', $table).on('click', function() {
                  var $checkedStatus = jQuery(this).prop('checked');
  
                  // Check or uncheck all checkboxes in tbody
                  jQuery('tbody input[name="ids[]"]:checkbox', $table_target).each(function() {
                      var $checkbox = jQuery(this);
                      var $index = $table_target.find('input[name="ids[]"]:checkbox').index($(this));
                      $checkbox.prop('checked', $checkedStatus);
                      uiHelperTableToolscheckRow($checkbox, $checkedStatus, $index);
                  });
              });
  
              // When a checkbox is clicked in tbody
              jQuery('tbody input[name="ids[]"]:checkbox', $table_target).on('click', function(e) {
                  var $checkbox = jQuery(this);
                  var $index = $table_target.find('input[name="ids[]"]:checkbox').index($(this));
  
                  uiHelperTableToolscheckRow($checkbox, $checkbox.prop('checked'), $index);
              });
          });
      };
  
      // Checkable table functionality helper - Checks or unchecks table row
      var uiHelperTableToolscheckRow = function($checkbox, $checkedStatus, $index) {
          if ($checkedStatus) {
              $checkbox
                  .closest('tr')
                  .addClass('active');
              $('.js-table-checkable-target').find('tr').eq($index).addClass('active');
              $('#builder-table-right-body-inner').find('tr').eq($index).addClass('active');
          } else {
              $checkbox
                  .closest('tr')
                  .removeClass('active');
              $('.js-table-checkable-target').find('tr').eq($index).removeClass('active');
              $('#builder-table-right-body-inner').find('tr').eq($index).removeClass('active');
          }
      };
  
      /*
       * jQuery Appear, for more examples you can check out https://github.com/bas2k/jquery.appear
       *
       * App.initHelper('appear');
       *
       */
      var uiHelperAppear = function(){
          // Add a specific class on elements (when they become visible on scrolling)
          jQuery('[data-toggle="appear"]').each(function(){
              var $windowW    = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
              var $this       = jQuery(this);
              var $class      = $this.data('class') ? $this.data('class') : 'animated fadeIn';
              var $offset     = $this.data('offset') ? $this.data('offset') : 0;
              var $timeout    = ($lHtml.hasClass('ie9') || $windowW < 992) ? 0 : ($this.data('timeout') ? $this.data('timeout') : 0);
  
              $this.appear(function() {
                  setTimeout(function(){
                      $this
                          .removeClass('visibility-hidden')
                          .addClass($class);
                  }, $timeout);
              },{accY: $offset});
          });
      };
  
      /*
       * jQuery Appear + jQuery countTo, for more examples you can check out https://github.com/bas2k/jquery.appear and https://github.com/mhuggins/jquery-countTo
       *
       * App.initHelper('appear-countTo');
       *
       */
      var uiHelperAppearCountTo = function(){
          // Init counter functionality
          jQuery('[data-toggle="countTo"]').each(function(){
              var $this       = jQuery(this);
              var $after      = $this.data('after');
              var $before     = $this.data('before');
              var $speed      = $this.data('speed') ? $this.data('speed') : 1500;
              var $interval   = $this.data('interval') ? $this.data('interval') : 15;
  
              $this.appear(function() {
                  $this.countTo({
                      speed: $speed,
                      refreshInterval: $interval,
                      onComplete: function() {
                          if($after) {
                              $this.html($this.html() + $after);
                          } else if ($before) {
                              $this.html($before + $this.html());
                          }
                      }
                  });
              });
          });
      };
  
      /*
       * jQuery SlimScroll, for more examples you can check out http://rocha.la/jQuery-slimScroll
       *
       * App.initHelper('slimscroll');
       *
       */
      var uiHelperSlimscroll = function(){
          // Init slimScroll functionality
          jQuery('[data-toggle="slimscroll"]').each(function(){
              var $this       = jQuery(this);
              var $height     = $this.data('height') ? $this.data('height') : '200px';
              var $size       = $this.data('size') ? $this.data('size') : '5px';
              var $position   = $this.data('position') ? $this.data('position') : 'right';
              var $color      = $this.data('color') ? $this.data('color') : '#000';
              var $avisible   = $this.data('always-visible') ? true : false;
              var $rvisible   = $this.data('rail-visible') ? true : false;
              var $rcolor     = $this.data('rail-color') ? $this.data('rail-color') : '#999';
              var $ropacity   = $this.data('rail-opacity') ? $this.data('rail-opacity') : .3;
  
              $this.slimScroll({
                  height: $height,
                  size: $size,
                  position: $position,
                  color: $color,
                  alwaysVisible: $avisible,
                  railVisible: $rvisible,
                  railColor: $rcolor,
                  railOpacity: $ropacity
              });
          });
      };
  
      /*
       ********************************************************************************************
       *
       * All the following helpers require each plugin's resources (JS, CSS) to be included in order to work
       *
       ********************************************************************************************
       */
  
      /*
       * Magnific Popup functionality, for more examples you can check out http://dimsemenov.com/plugins/magnific-popup/
       *
       * App.initHelper('magnific-popup');
       *
       */
      var uiHelperMagnific = function(){
          // Simple Gallery init
          jQuery('.js-gallery').each(function(){
              jQuery(this).viewer({url: 'data-original'});
          });
  
          // Advanced Gallery init
          jQuery('.js-gallery-advanced').each(function(){
              jQuery(this).magnificPopup({
                  delegate: 'a.img-lightbox',
                  type: 'image',
                  gallery: {
                      enabled: true
                  }
              });
          });
      };
  
      /*
       * CKEditor init, for more examples you can check out http://ckeditor.com/
       *
       * App.initHelper('ckeditor');
       *
       */
      var uiHelperCkeditor = function(){
          // Disable auto init when contenteditable property is set to true
          CKEDITOR.disableAutoInline = true;
  
          // Init inline text editor
          jQuery('.js-ckeditor-inlin').each(function () {
              var editor_id = $(this).attr('id');
              CKEDITOR.inline(editor_id);
          });
  
          // Init full text editor
          jQuery('.js-ckeditor').each(function () {
              var editor_id = $(this).attr('id');
              var editor    = CKEDITOR.replace(editor_id, {
                  filebrowserImageUploadUrl: dolphin.ckeditor_img_upload_url,
                  image_previewText: ' ',
                  height: $(this).data('height') || 400,
                  width: $(this).data('width') || '100%',
                  toolbarCanCollapse: true
              });
              editor.on('change', function( evt ) {
                  editor.updateElement();
              });
          });
      };
  
      /*
       * Summernote init, for more examples you can check out http://summernote.org/
       *
       * App.initHelper('summernote');
       *
       */
      var uiHelperSummernote = function(){
          // Init text editor in air mode (inline)
          jQuery('.js-summernote-air').summernote({
              airMode: true
            });
  
          // Init full text editor
          jQuery('.js-summernote').each(function () {
              var $summernote = $(this);
              $summernote.summernote({
                  width: $summernote.data('width') || '100%',
                  height: $summernote.data('height') || 350,
                  minHeight: null,
                  maxHeight: null,
                  lang: 'zh-CN',
                  callbacks: {
                      onImageUpload: function(files) {
                          //上传图片到服务器
                          var formData = new FormData();
                          $.each(files, function () {
                              formData.append('file', $(this)[0]);
                              $.ajax({
                                  url : dolphin.image_upload_url,//后台文件上传接口
                                  type : 'POST',
                                  data : formData,
                                  cache: false,
                                  processData : false,
                                  contentType : false,
                                  success : function(res) {
                                      if (res.code) {
                                          $summernote.summernote('insertImage', res.path);
                                      } else {
                                          Dolphin.notify(res.info, 'danger');
                                      }
                                  }
                              });
                          });
                      }
                  }
              });
          });
      };
  
      /*
       * Slick init, for more examples you can check out http://kenwheeler.github.io/slick/
       *
       * App.initHelper('slick');
       *
       */
      var uiHelperSlick = function(){
          // Get each slider element (with .js-slider class)
          jQuery('.js-slider').each(function(){
              var $slider = jQuery(this);
  
              // Get each slider's init data
              var $sliderArrows       = $slider.data('slider-arrows') ? $slider.data('slider-arrows') : false;
              var $sliderDots         = $slider.data('slider-dots') ? $slider.data('slider-dots') : false;
              var $sliderNum          = $slider.data('slider-num') ? $slider.data('slider-num') : 1;
              var $sliderAuto         = $slider.data('slider-autoplay') ? $slider.data('slider-autoplay') : false;
              var $sliderAutoSpeed    = $slider.data('slider-autoplay-speed') ? $slider.data('slider-autoplay-speed') : 3000;
  
              // Init slick slider
              $slider.slick({
                  arrows: $sliderArrows,
                  dots: $sliderDots,
                  slidesToShow: $sliderNum,
                  autoplay: $sliderAuto,
                  autoplaySpeed: $sliderAutoSpeed
              });
          });
      };
  
      /*
       * Bootstrap Datepicker init, for more examples you can check out https://github.com/eternicode/bootstrap-datepicker
       *
       * App.initHelper('datepicker');
       *
       */
      var uiHelperDatepicker = function(){
          // Init datepicker (with .js-datepicker and .input-daterange class)
          jQuery('.js-datepicker').add('.input-daterange').each(function () {
              var $datepicker = jQuery(this);
              var $weekStart = $datepicker.data('week-start') || 1;
              var $autoclose = $datepicker.data('autoclose') === undefined ? true : $datepicker.data('autoclose');
              var $todayHighlight = $datepicker.data('today-highlight') === undefined ? true : $datepicker.data('today-highlight');
              var $language = $datepicker.data('language') || 'zh-CN';
              var $startDate = $datepicker.data('start-date') === undefined ? -Infinity : $datepicker.data('start-date');
              var $endDate = $datepicker.data('end-date') === undefined ? Infinity : $datepicker.data('end-date');
              var $startView = $datepicker.data('start-view') === undefined ? 0 : $datepicker.data('start-view');
              var $minViewMode = $datepicker.data('min-view-mode') === undefined ? 0 : $datepicker.data('min-view-mode');
              var $maxViewMode = $datepicker.data('max-view-mode') === undefined ? 4 : $datepicker.data('max-view-mode');
              var $todayBtn = $datepicker.data('today-btn') === undefined ? false : $datepicker.data('today-btn');
              var $clearBtn = $datepicker.data('clear-btn') === undefined ? false : $datepicker.data('clear-btn');
              var $orientation = $datepicker.data('orientation') === undefined ? "auto" : $datepicker.data('orientation');
              var $multidate = $datepicker.data('multidate') === undefined ? false : $datepicker.data('multidate');
              var $multidateSeparator = $datepicker.data('multidate-separator') === undefined ? ',' : $datepicker.data('multidate-separator');
              var $daysOfWeekDisabled = $datepicker.data('days-of-week-disabled') === undefined ? [] : $datepicker.data('days-of-week-disabled');
              var $daysOfWeekHighlighted = $datepicker.data('days-of-week-highlighted') === undefined ? [] : $datepicker.data('days-of-week-highlighted');
              var $calendarWeeks = $datepicker.data('calendar-weeks') === undefined ? false : $datepicker.data('calendar-weeks');
              var $keyboardNavigation = $datepicker.data('keyboard-navigation') === undefined ? true : $datepicker.data('keyboard-navigation');
              var $forceParse = $datepicker.data('force-parse') === undefined ? true : $datepicker.data('force-parse');
              var $datesDisabled = $datepicker.data('dates-disabled') === undefined ? [] : $datepicker.data('dates-disabled');
              var $toggleActive = $datepicker.data('toggle-active') === undefined ? false : $datepicker.data('toggle-active');
  
              $datepicker.datepicker({
                  weekStart: $weekStart,
                  autoclose: $autoclose,
                  todayHighlight: $todayHighlight,
                  language: $language,
                  startDate: $startDate,
                  endDate: $endDate,
                  startView: $startView,
                  minViewMode: $minViewMode,
                  maxViewMode: $maxViewMode,
                  todayBtn: $todayBtn,
                  clearBtn: $clearBtn,
                  orientation: $orientation,
                  multidate: $multidate,
                  multidateSeparator: $multidateSeparator,
                  daysOfWeekDisabled: $daysOfWeekDisabled,
                  daysOfWeekHighlighted: $daysOfWeekHighlighted,
                  calendarWeeks: $calendarWeeks,
                  keyboardNavigation: $keyboardNavigation,
                  forceParse: $forceParse,
                  datesDisabled: $datesDisabled,
                  toggleActive: $toggleActive
              });
          });
      };
  
      /*
       * 日期时间范围
       *
       * App.initHelper('daterangepicker');
       *
       */
      var uiHelperDaterangepicker = function () {
          jQuery('.js-daterangepicker').each(function () {
              var $daterangepicker = jQuery(this);
              var $format = $daterangepicker.data('format') === undefined ? "YYYY-MM-DD" : $daterangepicker.data('format');
              var $autoUpdateInput = $daterangepicker.data('auto-update-input') === undefined ? false : $daterangepicker.data('auto-update-input');
              var $showDropdowns = $daterangepicker.data('show-dropdowns') === undefined ? true : $daterangepicker.data('show-dropdowns');
              var $singleDatePicker = $daterangepicker.data('single-date-picker') === undefined ? false : $daterangepicker.data('single-date-picker');
  
              $daterangepicker.daterangepicker({
                  autoUpdateInput: $autoUpdateInput,
                  showDropdowns: $showDropdowns,
                  locale: {
                      "format": $format,
                      "separator": " - ",
                      "applyLabel": "确定",
                      "cancelLabel": "取消",
                      "fromLabel": "From",
                      "toLabel": "To",
                      "customRangeLabel": "Custom",
                      "weekLabel": "W",
                      "daysOfWeek": ["日", "一", "二", "三", "四", "五", "六"],
                      "monthNames": ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
                  }
              });
  
              if (!$singleDatePicker) {
                  $daterangepicker.on('apply.daterangepicker', function(ev, picker) {
                      $(this).val(picker.startDate.format($format) + ' - ' + picker.endDate.format($format));
                  });
              } else {
                  $daterangepicker.on('apply.daterangepicker', function(ev, picker) {
                      $(this).val(picker.startDate.format($format));
                  });
              }
  
              $daterangepicker.on('cancel.daterangepicker', function(ev, picker) {
                  $(this).val('');
              });
          });
      };
  
      /*
       * Bootstrap Colorpicker init, for more examples you can check out http://mjolnic.com/bootstrap-colorpicker/
       *
       * App.initHelper('colorpicker');
       *
       */
      var uiHelperColorpicker = function(){
          // Get each colorpicker element (with .js-colorpicker class)
          jQuery('.js-colorpicker').each(function(){
              var $colorpicker = jQuery(this);
  
              // Get each colorpicker's init data
              var $colorpickerMode    = $colorpicker.data('colorpicker-mode') ? $colorpicker.data('colorpicker-mode') : 'hex';
              var $colorpickerinline  = $colorpicker.data('colorpicker-inline') ? true : false;
  
              // Init colorpicker
              $colorpicker.colorpicker({
                  'format': $colorpickerMode,
                  'inline': $colorpickerinline
              });
          });
      };
  
      /*
       * Masked Inputs, for more examples you can check out http://digitalbush.com/projects/masked-input-plugin/
       *
       * App.initHelper('masked-inputs');
       *
       */
      var uiHelperMaskedInputs = function(){
          // Init Masked Inputs
          // a - Represents an alpha character (A-Z,a-z)
          // 9 - Represents a numeric character (0-9)
          // * - Represents an alphanumeric character (A-Z,a-z,0-9)
          jQuery('.js-masked-date').mask('99/99/9999');
          jQuery('.js-masked-date-dash').mask('99-99-9999');
          jQuery('.js-masked-phone').mask('(999) 999-9999');
          jQuery('.js-masked-phone-ext').mask('(999) 999-9999? x99999');
          jQuery('.js-masked-taxid').mask('99-9999999');
          jQuery('.js-masked-ssn').mask('999-99-9999');
          jQuery('.js-masked-pkey').mask('a*-999-a999');
          jQuery('.js-masked-time').mask('99:99');
      };
  
      /*
       * Tags Inputs, for more examples you can check out https://github.com/xoxco/jQuery-Tags-Input
       *
       * App.initHelper('tags-inputs');
       *
       */
      var uiHelperTagsInputs = function(){
          // Init Tags Inputs (with .js-tags-input class)
          jQuery('.js-tags-input').tagsInput({
              height: '36px',
              width: '100%',
              defaultText: '添加标签',
              removeWithBackspace: true,
              delimiter: [',']
          });
      };
  
      /*
       * Select2, for more examples you can check out https://github.com/select2/select2
       *
       * App.initHelper('select2');
       *
       */
      var uiHelperSelect2 = function(){
          // Init Select2 (with .js-select2 class)
          jQuery('.js-select2').each(function () {
              var $select2 = jQuery(this);
              var $width = $select2.data('width') || '100%';
              $select2.select2({
                  width: $width, //设置下拉框的宽度
                  language: "zh-CN"
              });
          });
      };
  
      /*
       * Highlight.js, for more examples you can check out https://highlightjs.org/usage/
       *
       * App.initHelper('highlightjs');
       *
       */
      var uiHelperHighlightjs = function(){
          // Init Highlight.js
          hljs.initHighlightingOnLoad();
      };
  
      /*
       * Bootstrap Notify, for more examples you can check out http://bootstrap-growl.remabledesigns.com/
       *
       * App.initHelper('notify');
       *
       */
      var uiHelperNotify = function(){
          // Init notifications (with .js-notify class)
          jQuery('.js-notify').on('click', function(){
              var $notify         = jQuery(this);
              var $notifyMsg      = $notify.data('notify-message');
              var $notifyType     = $notify.data('notify-type') ? $notify.data('notify-type') : 'info';
              var $notifyFrom     = $notify.data('notify-from') ? $notify.data('notify-from') : 'top';
              var $notifyAlign    = $notify.data('notify-align') ? $notify.data('notify-align') : 'right';
              var $notifyIcon     = $notify.data('notify-icon') ? $notify.data('notify-icon') : '';
              var $notifyUrl      = $notify.data('notify-url') ? $notify.data('notify-url') : '';
  
              jQuery.notify({
                      icon: $notifyIcon,
                      message: $notifyMsg,
                      url: $notifyUrl
                  },
                  {
                      element: 'body',
                      type: $notifyType,
                      allow_dismiss: true,
                      newest_on_top: true,
                      showProgressbar: false,
                      placement: {
                          from: $notifyFrom,
                          align: $notifyAlign
                      },
                      offset: 20,
                      spacing: 10,
                      z_index: 1033,
                      delay: 5000,
                      timer: 1000,
                      animate: {
                          enter: 'animated fadeIn',
                          exit: 'animated fadeOutDown'
                      }
                  });
          });
      };
  
      /*
       * Draggable items with jQuery, for more examples you can check out https://jqueryui.com/sortable/
       *
       * App.initHelper('draggable-items');
       *
       */
      var uiHelperDraggableItems = function(){
          // Init draggable items functionality (with .js-draggable-items class)
          jQuery('.js-draggable-items > .draggable-column').sortable({
              connectWith: '.draggable-column',
              items: '.draggable-item',
              dropOnEmpty: true,
              opacity: .75,
              handle: '.draggable-handler',
              placeholder: 'draggable-placeholder',
              tolerance: 'pointer',
              start: function(e, ui){
                  ui.placeholder.css({
                      'height': ui.item.outerHeight(),
                      'margin-bottom': ui.item.css('margin-bottom')
                  });
              }
          });
      };
  
      /*
       * Easy Pie Chart, for more examples you can check out http://rendro.github.io/easy-pie-chart/
       *
       * App.initHelper('easy-pie-chart');
       *
       */
      var uiHelperEasyPieChart = function(){
          // Init Easy Pie Charts (with .js-pie-chart class)
          jQuery('.js-pie-chart').easyPieChart({
              barColor: jQuery(this).data('bar-color') ? jQuery(this).data('bar-color') : '#777777',
              trackColor: jQuery(this).data('track-color') ? jQuery(this).data('track-color') : '#eeeeee',
              lineWidth: jQuery(this).data('line-width') ? jQuery(this).data('line-width') : 3,
              size: jQuery(this).data('size') ? jQuery(this).data('size') : '80',
              animate: 750,
              scaleColor: jQuery(this).data('scale-color') ? jQuery(this).data('scale-color') : false
          });
      };
  
      /*
       * Bootstrap Maxlength, for more examples you can check out https://github.com/mimo84/bootstrap-maxlength
       *
       * App.initHelper('maxlength');
       *
       */
      var uiHelperMaxlength = function(){
          // Init Bootstrap Maxlength (with .js-maxlength class)
          jQuery('.js-maxlength').each(function(){
              var $input = jQuery(this);
  
              $input.maxlength({
                  alwaysShow: $input.data('always-show') ? true : false,
                  threshold: $input.data('threshold') ? $input.data('threshold') : 10,
                  warningClass: $input.data('warning-class') ? $input.data('warning-class') : 'label label-warning',
                  limitReachedClass: $input.data('limit-reached-class') ? $input.data('limit-reached-class') : 'label label-danger',
                  placement: $input.data('placement') ? $input.data('placement') : 'bottom',
                  preText: $input.data('pre-text') ? $input.data('pre-text') : '',
                  separator: $input.data('separator') ? $input.data('separator') : '/',
                  postText: $input.data('post-text') ? $input.data('post-text') : ''
              });
          });
      };
  
      /*
       * Bootstrap Datetimepicker, for more examples you can check out https://github.com/Eonasdan/bootstrap-datetimepicker
       *
       * App.initHelper('datetimepicker');
       *
       */
      var uiHelperDatetimepicker = function(){
          // Init Bootstrap Datetimepicker (with .js-datetimepicker class)
          jQuery('.js-datetimepicker').each(function(){
              var $input = jQuery(this);
  
              $input.datetimepicker({
                  format: $input.data('format') ? $input.data('format') : false,
                  useCurrent: $input.data('use-current') ? $input.data('use-current') : false,
                  locale: moment.locale('' + ($input.data('locale') ? $input.data('locale') : '') +''),
                  showTodayButton: $input.data('show-today-button') ? $input.data('show-today-button') : false,
                  showClear: $input.data('show-clear') ? $input.data('show-clear') : false,
                  showClose: $input.data('show-close') ? $input.data('show-close') : false,
                  sideBySide: $input.data('side-by-side') ? $input.data('side-by-side') : false,
                  inline: $input.data('inline') ? $input.data('inline') : false,
                  icons: {
                      time: 'si si-clock',
                      date: 'si si-calendar',
                      up: 'si si-arrow-up',
                      down: 'si si-arrow-down',
                      previous: 'si si-arrow-left',
                      next: 'si si-arrow-right',
                      today: 'si si-size-actual',
                      clear: 'si si-trash',
                      close: 'si si-close'
                  }
              });
          });
      };
  
      /*
       * Ion Range Slider, for more examples you can check out https://github.com/IonDen/ion.rangeSlider
       *
       * App.initHelper('rangeslider');
       *
       */
      var uiHelperRangeslider = function(){
          // Init Ion Range Slider (with .js-rangeslider class)
          jQuery('.js-rangeslider').each(function(){
              var $input = jQuery(this);
  
              $input.ionRangeSlider({
                  input_values_separator: ';'
              });
          });
      };
  
      return {
          init: function($func) {
              switch ($func) {
                  case 'uiInit':
                      uiInit();
                      break;
                  case 'uiLayout':
                      uiLayout();
                      break;
                  case 'uiNav':
                      uiNav();
                      break;
                  case 'uiBlocks':
                      uiBlocks();
                      break;
                  case 'uiForms':
                      uiForms();
                      break;
                  case 'uiHandleTheme':
                      uiHandleTheme();
                      break;
                  case 'uiToggleClass':
                      uiToggleClass();
                      break;
                  case 'uiScrollTo':
                      uiScrollTo();
                      break;
                  case 'uiYearCopy':
                      uiYearCopy();
                      break;
                  case 'uiLoader':
                      uiLoader('hide');
                      break;
                  default:
                      // Init all vital functions
                      uiInit();
                      uiLayout();
                      uiNav();
                      uiBlocks();
                      uiForms();
                      uiHandleTheme();
                      uiToggleClass();
                      uiScrollTo();
                      uiYearCopy();
                      uiLoader('hide');
              }
          },
          layout: function($mode) {
              uiLayoutApi($mode);
          },
          loader: function($mode) {
              uiLoader($mode);
          },
          blocks: function($block, $mode) {
              uiBlocksApi($block, $mode);
          },
          initHelper: function($helper) {
              switch ($helper) {
                  case 'print-page':
                      uiHelperPrint();
                      break;
                  case 'table-tools':
                      uiHelperTableToolsSections();
                      uiHelperTableToolsCheckable();
                      break;
                  case 'appear':
                      uiHelperAppear();
                      break;
                  case 'appear-countTo':
                      uiHelperAppearCountTo();
                      break;
                  case 'slimscroll':
                      uiHelperSlimscroll();
                      break;
                  case 'magnific-popup':
                      uiHelperMagnific();
                      break;
                  case 'ckeditor':
                      uiHelperCkeditor();
                      break;
                  case 'summernote':
                      uiHelperSummernote();
                      break;
                  case 'slick':
                      uiHelperSlick();
                      break;
                  case 'datepicker':
                      uiHelperDatepicker();
                      break;
                  case 'daterangepicker':
                      uiHelperDaterangepicker();
                      break;
                  case 'colorpicker':
                      uiHelperColorpicker();
                      break;
                  case 'tags-inputs':
                      uiHelperTagsInputs();
                      break;
                  case 'masked-inputs':
                      uiHelperMaskedInputs();
                      break;
                  case 'select2':
                      uiHelperSelect2();
                      break;
                  case 'highlightjs':
                      uiHelperHighlightjs();
                      break;
                  case 'notify':
                      uiHelperNotify();
                      break;
                  case 'draggable-items':
                      uiHelperDraggableItems();
                      break;
                  case 'easy-pie-chart':
                      uiHelperEasyPieChart();
                      break;
                  case 'maxlength':
                      uiHelperMaxlength();
                      break;
                  case 'datetimepicker':
                      uiHelperDatetimepicker();
                      break;
                  case 'rangeslider':
                      uiHelperRangeslider();
                      break;
                  default:
                      return false;
              }
          },
          initHelpers: function($helpers) {
              if ($helpers instanceof Array) {
                  for(var $index in $helpers) {
                      App.initHelper($helpers[$index]);
                  }
              } else {
                  App.initHelper($helpers);
              }
          }
      };
  }();
  
  // Create an alias for App (you can use OneUI in your pages instead of App if you like)
  var OneUI = App;
  
  // Initialize app when page loads
  jQuery(function(){
      if (typeof angular == 'undefined') {
          App.init();
      }
  });