text: //Author      : @arboshiki
  /**
   * Generates random string of n length.
   * String contains only letters and numbers
   *
   * @param {int} n
   * @returns {String}
   */
  Math.randomString = function (n) {
      var text = "";
      var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  
      for (var i = 0; i < n; i++)
          text += possible.charAt(Math.floor(Math.random() * possible.length));
  
      return text;
  };
  
  /**
   * This function is for HTML element style attribute.
   * It converts the style attribute to css object
   *
   * @returns {object}
   */
  String.prototype.getCss = function () {
      var css = {};
      var style = this.valueOf().split(';');
      for (var i = 0; i < style.length; i++) {
          style[i] = $.trim(style[i]);
          if (style[i]) {
              var s = style[i].split(':');
              css[$.trim(s[0])] = $.trim(s[1]);
          }
      }
      return css;
  };
  String.prototype.trim = function () {
      return this.replace(/^\s+|\s+$/g, "");
  };
  
  String.prototype.toCamel = function () {
      return this.replace(/(\-[a-z])/g, function ($1) {
          return $1.toUpperCase().replace('-', '');
      });
  };
  
  String.prototype.toDash = function () {
      return this.replace(/([A-Z])/g, function ($1) {
          return "-" + $1.toLowerCase();
      });
  };
  String.prototype.toUnderscore = function () {
      return this.replace(/([A-Z])/g, function ($1) {
          return "_" + $1.toLowerCase();
      });
  };
  
  /**
   * Checks if number is between two numbers
   *
   * @param {number} num1
   * @param {number} num2
   * @param {boolean} including "include these numbers in comparison or not" default false
   * @returns boolean
   */
  Number.prototype.isBetween = function (num1, num2, including) {
      if (!including) {
          if (this.valueOf() < num2 && this.valueOf() > num1) {
              return true;
          }
      } else {
          if (this.valueOf() <= num2 && this.valueOf() >= num1) {
              return true;
          }
      }
      return false;
  };
  
  /**
   * Inserts element at specific index in given elements children
   *
   * @param {number} i
   * @param {string} selector
   * @returns {undefined}
   */
  $.fn.insertAt = function (i, selector) {
      var object = selector;
      if (typeof selector === 'string') {
          object = $(selector);
      }
  
      i = Math.min(object.children().length, i);
      if (i == 0) {
          object.prepend(this);
          return this;
      }
      var oldIndex = this.data('index');
  
      this.attr('data-index', i);
      object.find(">*:nth-child(" + i + ")").after(this);
      object.children().each(function (index, el) {
          var $el = $(el);
          if (oldIndex < i && index > oldIndex && index <= i) {
              $el.attr('data-index', parseInt($el.data('data-index'), 10) - 1);
          } else if (oldIndex >= i && index > i && index <= oldIndex) {
              $el.attr('data-index', parseInt($el.attr('data-index'), 10) + 1);
          }
      });
      return this;
  };
  
  $.fn.disableSelection = function () {
      return this
          .attr('unselectable', 'on')
          .css('user-select', 'none')
          .on('selectstart', false);
  };
  
  $.fn.enableSelection = function () {
      return this
          .removeAttr('unselectable')
          .css('user-select', 'initial')
          .off('selectstart');
  };
  
  $(function () {
      var STORAGE_PREFIX = 'lobipanel_';
  
      var LobiPanel = function ($el, options) {
          var me = this;
  
          this.hasRandomId = false;
          this.storage = null;
  
  
          this.$el = $el;
          if (!me.$el.data('inner-id')) {
              me.hasRandomId = true;
              me.$el.attr('data-inner-id', Math.randomString(10));
          }
  
          this.innerId = me.$el.data('inner-id');
  
          this.$options = me._processInput(options);
          me.$heading = this.$el.find('>.panel-heading');
          me.$body = this.$el.find('>.panel-body');
          me._init();
          me.$el.css('display', 'none');
          me._applyState(me.$options.state, me.$options.stateParams);
          me.$el.css('display', 'block');
          me._applyIndex(me.$options.initialIndex);
      };
  
      LobiPanel.prototype = {
          _processInput: function (options) {
              var me = this;
              if (!options) {
                  options = {};
              }
  
  
              if (!me.hasRandomId) {
                  me.storage = localStorage.getItem(STORAGE_PREFIX + me.innerId);
                  me.storage = JSON.parse(me.storage) || {};
              }
              var opts = me._getOptionsFromAttributes();
  //            window.console.log(opts);
              options = $.extend({}, $.fn.lobiPanel.DEFAULTS, me.storage, options, opts);
              var objects = ['unpin', 'reload', 'expand', 'minimize', 'close', 'editTitle'];
              for (var i = 0; i < objects.length; i++) {
                  var prop = objects[i];
                  if (typeof options[prop] === 'object') {
                      options[prop] = $.extend({}, $.fn.lobiPanel.DEFAULTS[prop], options[prop], opts[prop]);
                  }
              }
              return options;
          },
          _init: function () {
              var me = this;
              me.$el.addClass('lobipanel');
  
              me.$heading.append(me._generateControls());
  //------------------------------------------------------------------------------
              var parent = me.$el.parent();
              me._appendInnerIdToParent(parent, me.innerId);
              me._enableSorting();
              me._onToggleIconsBtnClick();
              me._enableResponsiveness();
              me._setBodyHeight();
              if (me.$options.autoload) {
                  me.load();
              }
              var maxWidth = 'calc(100% - ' + me.$heading.find('.dropdown-menu').children().length * me.$heading.find('.dropdown-menu li').first().outerWidth() + "px)";
              me.$heading.find('.panel-title').css('max-width', maxWidth);
  
              me._triggerEvent("init");
          },
          /**
           * Checks if panel is initialized. Panel is initialized if it has
           * lobipanel class and data-inner-id="" attribute
           *
           * @returns {boolean}
           */
          isPanelInit: function () {
              var me = this;
              return me.$el.hasClass('lobipanel') && me.$el.data('inner-id');
          },
  
          /**
           * Checks if panel is pinned or unpinned
           *
           * @returns {Boolean}
           */
          isPinned: function () {
              var me = this;
              return !me.$el.hasClass('panel-unpin');
          },
  
          /**
           * Pin the panel
           *
           * @returns {LobiPanel}
           */
          pin: function () {
              var me = this;
  
              //disable resize functionality
              me.disableResize();
              me.disableDrag();
              me._enableSorting();
              //remove on panel click event (which brings the panel into front)
              me._offPanelClick();
              //remove panel-unpin class
              me.$el.removeClass('panel-unpin')
                  //save current position, z-index and size to use it for later unpin
                  .attr('old-style', me.$el.attr('style'))
                  .removeAttr('style')
                  .css('position', 'relative');
              me.$body.css({
                  width: '',
                  height: ''
              });
              me._setBodyHeight();
              me._insertInParent();
              return me;
          },
  
          /**
           * Unpin the panel
           *
           * @returns {LobiPanel}
           */
          unpin: function () {
              var me = this;
              if (me.$el.hasClass("panel-collapsed")) {
                  return me;
              }
              me._disableSorting();
              if (me.$el.attr('old-style')) {
                  me.$el.attr('style', me.$el.attr('old-style'));
              } else {
                  var width = me.$el.width();
                  var height = me.$el.height();
                  var left = Math.max(0, (($(window).width() - me.$el.outerWidth()) / 2));
                  var top = Math.max(0, ($(document).scrollTop() + ($(window).height() - me.$el.outerHeight()) / 2));
                  me.$el.css({
                      left: left,
                      top: top,
                      width: width,
                      height: height
                  });
              }
              var res = me._getMaxZIndex();
              me.$el.css('z-index', res['z-index'] + 1);
              me._onPanelClick();
  
              me.$el.addClass('panel-unpin');
              $('body').append(me.$el);
  
              var panelWidth = me._getAvailableWidth(me.$el.width());
              var panelHeight = me._getAvailableHeight(me.$el.height());
              me.$el.css({
                  position: 'absolute',
                  width: panelWidth,
                  height: panelHeight
              });
              //we give .panel-body to width and height in order .panel-body to start scroling
              var bHeight = me._calculateBodyHeight(panelHeight);
              var bWidth = me._calculateBodyWidth(panelWidth);
              me.$body.css({
                  width: bWidth,
                  height: bHeight
              });
  
              if (me.$options.draggable) {
                  me.enableDrag();
              }
              if (me.$options.resize !== 'none') {
                  me.enableResize();
              }
              return me;
          },
  
          /**
           * Toggles (pin or unpin) the panel
           *
           * @returns {LobiPanel}
           */
          togglePin: function () {
              var me = this;
              if (this.isPinned()) {
                  this.unpin();
              } else {
                  this.pin();
              }
              return me;
          },
  
          /**
           * Checks if panel is minimized or not. It does not matter if panel is pinned or not
           *
           * @returns {Boolean}
           */
          isMinimized: function () {
              var me = this;
              return me.$el.hasClass('panel-minimized') || me.$el.hasClass('panel-collapsed');
          },
  
          /**
           * Minimize the panel. If panel is pinned it is minimized on its place
           * if panel is unpinned it is minimized at the bottom of the page
           *
           * @returns {LobiPanel}
           */
          minimize: function () {
              var me = this;
              me._triggerEvent("beforeMinimize");
              if (me.isMinimized()) {
                  return me;
              }
              if (me.isPinned()) {
                  me.$body.slideUp();
                  me.$el.find('.panel-footer').slideUp();
                  me.$el.addClass('panel-collapsed');
                  me._saveState('collapsed');
                  me._changeClassOfControl(me.$heading.find('[data-func="minimize"]'));
              } else {
                  me.disableTooltips();
                  //get footer where we need to put panel
                  var footer = me._getFooterForMinimizedPanels();
                  //find other panels which are already inside footer
                  var children = footer.find('>*');
                  var left, top;
                  //get top coordinate of footer
                  top = footer.offset().top;
                  //if there are no other panels inside footer, this panel will be first
                  //and its left coordinate will be footer's left coordinate
                  if (children.length === 0) {
                      left = footer.offset().left;
                  } else {
                      //if there exist panels inside footer, then this panel's left
                      //coordinate will be last panel's (in footer) right coordinate
                      var ch = $(children[children.length - 1]);
                      left = ch.offset().left + ch.width();
                  }
                  //if panel was not expanded and it was jus unpin we need to save
                  //panel's style
                  if (!me.$el.hasClass('panel-expanded')) {
                      me.$el.attr('old-style', me.$el.attr('style'));
                  }
                  me.$el.animate({
                      left: left,
                      top: top,
                      width: 200,
                      height: footer.height()
                  }, 100, function () {
                      //if panel was expanded on full screen before we minimize it
                      //after minimization we remove 'panel-expanded' class and we change icon
                      if (me.$el.hasClass('panel-expanded')) {
                          me.$el.removeClass('panel-expanded');
                          me.$el.find('.panel-heading [data-func=expand] .' + LobiPanel.PRIVATE_OPTIONS.iconClass)
                              .removeClass(me.$options.expand.icon2)
                              .addClass(me.$options.expand.icon)
                          ;
                      }
                      //we add 'panel-minimized' class
                      me.$el.addClass('panel-minimized');
                      me.$el.removeAttr('style');
                      me.disableDrag();
                      me.disableResize();
                      me._expandOnHeaderClick();
                      //animation was made and panel is positioned in place we it must be
                      //so we append panel into footer
                      footer.append(me.$el);
                      $('body').addClass('lobipanel-minimized');
                      var maxWidth = 'calc(100% - ' + me.$heading.find('.dropdown-menu li>a:visible').length * me.$heading.find('.dropdown-menu li>a:visible').first().outerWidth() + "px)";
                      me.$heading.find('.panel-title').css('max-width', maxWidth);
                      me._saveState('minimized');
                      me._triggerEvent("onMinimize");
                  });
              }
              return me;
          },
  
          /**
           * Maximize the panel. This method works for minimized panel.
           * If panel is pinned it's maximized on its place.
           * If panel is unpinned it's maximized on position from which it was minimized
           *
           * @returns {LobiPanel}
           */
          maximize: function () {
              var me = this;
              me._triggerEvent("beforeMaximize");
              if (!me.isMinimized()) {
                  return me;
              }
              if (me.isPinned()) {
                  me.$body.slideDown();
                  me.$el.find('.panel-footer').slideDown();
                  me.$el.removeClass('panel-collapsed');
                  me._saveState('pinned');
                  me._changeClassOfControl(me.$heading.find('[data-func="minimize"]'));
              } else {
                  me.enableTooltips();
                  //we get css style which was saved before minimization
                  var css = me.$el.attr('old-style').getCss();
                  //we give panel these css properties, coz animation work
                  me.$el.css({
                      position: css.position || 'fixed',
                      'z-index': css['z-index'],
                      left: me.$el.offset().left,
                      top: me.$el.offset().top,
                      width: me.$el.width(),
                      height: me.$el.height()
                  });
                  //we append panel into body
                  $('body').append(me.$el);
                  //It is not possible to make animations to these propeties and we remove it
                  delete css['position'];
                  delete css['z-index'];
  //            css['position'] = 'absolute';
                  //and we animate panel to its saved style
                  me.$el.animate(css, 100, function () {
                      //we remove position property from style, before 'panel-unpin'
                      //class has it to absolute
                      me.$el.css('position', '');
                      me.$el.removeClass('panel-minimized');
                      //as panel is already in its place we remove 'old-style' property
                      me.$el.removeAttr('old-style');
                      if (me.$options.draggable) {
                          me.enableDrag();
                      }
                      me.enableResize();
                      me._removeExpandOnHeaderClick();
                      //If there are no other elements inside footer, remove it also
                      var footer = me._getFooterForMinimizedPanels();
                      if (footer.children().length === 0) {
                          footer.remove();
                      }
                      $('body').removeClass('lobipanel-minimized')
                          .addClass('lobipanel-minimized');
                      var maxWidth = 'calc(100% - ' + me.$heading.find('.dropdown-menu li').length * me.$heading.find('.dropdown-menu li').first().outerWidth() + "px)";
                      me.$heading.find('.panel-title').css('max-width', maxWidth);
                      me._updateUnpinnedState();
                      me._triggerEvent("onMaximize");
                  });
              }
              return me;
          },
  
          /**
           * Toggles (minimize or maximize) the panel state.
           *
           * @returns {LobiPanel}
           */
          toggleMinimize: function () {
              var me = this;
              if (me.isMinimized()) {
                  me.maximize();
              } else {
                  me.minimize();
              }
              return me;
          },
  
          /**
           * Checks if panel is on full screen
           *
           * @returns {Boolean}
           */
          isOnFullScreen: function () {
              var me = this;
              return me.$el.hasClass('panel-expanded');
          },
  
          /**
           * Expands the panel to full screen size
           *
           * @returns {LobiPanel}
           */
          toFullScreen: function () {
              var me = this;
              me._triggerEvent("beforeFullScreen");
              if (me.$el.hasClass("panel-collapsed")) {
                  return me;
              }
              me._changeClassOfControl(me.$heading.find('[data-func="expand"]'));
              me.$el.css('position', 'fixed');
              var res = me._getMaxZIndex();
              //if panel is pinned or minimized, its position is not absolute and
              //animation will not work correctly so we change its position and
              //other css properties and we append panel into body
              if (me.isPinned() || me.isMinimized()) {
                  me.enableTooltips();
                  me.$el.css({
                      "z-index": res["z-index"] + 1,
                      left: me.$el.offset().left,
                      top: me.$el.offset().top - $(window).scrollTop(),
                      width: me.$el.width(),
                      height: me.$el.height()
                  });
                  $('body').append(me.$el);
                  //If we are expanding panel to full screen from footer and in footer there are no more elements
                  //remove footer also
                  var footer = me._getFooterForMinimizedPanels();
                  if (footer.children().length === 0) {
                      footer.remove();
                  }
              } else {
                  me.$body.css({
                      width: '',
                      height: ''
                  });
                  me._setBodyHeight();
              }
              //if panel is not minimized we save its style property, because when
              //toSmallSize() method is called panel needs to have style, it had before calling method
              // toFullScreen()
              if (!me.isMinimized()) {
                  me.$el.attr('old-style', me.$el.attr('style'));
                  me.disableResize();
              } else {
                  me.$el.removeClass('panel-minimized');
                  me._removeExpandOnHeaderClick();
              }
              //get toolbar
              var toolbar = $('.' + LobiPanel.PRIVATE_OPTIONS.toolbarClass);
              var toolbarHeight = toolbar.outerHeight() || 0;
              me.$el.animate({
                  width: $(window).width(),
                  height: $(window).height() - toolbarHeight,
                  left: 0,
                  top: 0
              }, me.$options.expandAnimation, function () {
                  me.$el.css({
                      width: '',
                      height: '',
                      right: 0,
                      bottom: toolbarHeight
                  });
                  me.$el.addClass('panel-expanded');
                  $('body').css('overflow', 'hidden');
                  me.$body.css({
                      width: me._calculateBodyWidth(me.$el.width()),
                      height: me._calculateBodyHeight(me.$el.height())
                  });
                  me.disableDrag();
                  if (me.isPinned()) {
                      me._disableSorting();
                  }
                  me._saveState('fullscreen');
                  me._triggerEvent("onFullScreen");
              });
              return me;
          },
  
          /**
           * Collapse the panel to small size
           *
           * @returns {LobiPanel}
           */
          toSmallSize: function () {
              var me = this;
              me._triggerEvent("beforeSmallSize");
              me._changeClassOfControl(me.$heading.find('[data-func="expand"]'));
              var css = me.$el.attr('old-style').getCss();
              //we get css properties from old-style (saved before expanding)
              //and we animate panel to this css properties
              me.$el.animate({
                  position: 'absolute',
                  left: css.left,
                  top: css.top,
                  width: css.width,
                  height: css.height,
                  right: css.right,
                  bottom: css.bottom
              }, me.$options.collapseAnimation, function () {
                  //we remove old-style as we do not need it
                  me.$el.removeAttr('old-style');
                  //if panel is pinned we also remove its style attribute and we
                  //append panel in its parent element
                  if (!me.$el.hasClass('panel-unpin')) {
                      me.$el.removeAttr('style');
                      me._insertInParent();
                      me._enableSorting();
                  } else {
                      if (me.$options.draggable) {
                          me.enableDrag();
                      }
                      me.enableResize();
                  }
                  me.$el.removeClass('panel-expanded');
                  $('body').css('overflow', 'auto');
                  var bWidth = '';
                  var bHeight = '';
                  if (!me.isPinned()) {
                      bWidth = me._calculateBodyWidth(me.getWidth());
                      bHeight = me._calculateBodyHeight(me.getHeight());
                  } else if (me.$options.bodyHeight !== 'auto') {
                      bHeight = me.$options.bodyHeight;
                  }
                  if (me.$options.bodyHeight !== 'auto'){
                      me._saveState('pinnned');
                  } else {
                      me._updateUnpinnedState();
                  }
                  me.$body.css({
                      width: bWidth,
                      height: bHeight
                  });
                  me._triggerEvent("onSmallSize");
              });
              return me;
          },
  
          /**
           * Toggles (changes to full screen size or to small size) the panel size
           *
           * @returns {LobiPanel}
           */
          toggleSize: function () {
              var me = this;
              if (me.isOnFullScreen()) {
                  me.toSmallSize();
              } else {
                  me.toFullScreen();
              }
              return me;
          },
  
          /**
           * Closes the panel. Removes it from document
           *
           * @param {number} animationDuration
           * @returns {LobiPanel}
           */
          close: function (animationDuration) {
              var me = this,
                  animationDuration = animationDuration  === undefined ? 100 : animationDuration;
              me._triggerEvent('beforeClose');
              me.$el.hide(animationDuration, function () {
                  if (me.isOnFullScreen()) {
                      $('body').css('overflow', 'auto');
                  }
                  me._triggerEvent('onClose');
                  me.$el.remove();
                  var footer = me._getFooterForMinimizedPanels();
                  if (footer.children().length === 0) {
                      footer.remove();
                  }
              });
              return me;
          },
  
          /**
           * Moves unpinned panel to given position.
           * This method will do nothing if panel is pinned
           *
           * @param {number} left
           * @param {number} top
           * @param {number} animationDuration
           * @returns {LobiPanel}
           */
          setPosition: function (left, top, animationDuration) {
              var me = this,
                  animationDuration = animationDuration  === undefined ? 100 : animationDuration;
  
              //this method works only if panel is not pinned
              if (me.isPinned()) {
                  return me;
              }
              me.$el.animate({
                  'left': left,
                  'top': top
              }, animationDuration);
              return me;
          },
  
          /**
           * Set the width of the panel
           *
           * @param {number} w
           * @param {number} animationDuration
           * @returns {LobiPanel}
           */
          setWidth: function (w, animationDuration) {
              var me = this,
                  animationDuration = animationDuration  === undefined ? 100 : animationDuration;
              if (me.isPinned()) {
                  return me;
              }
              var bWidth = me._calculateBodyWidth(w);
              me.$el.animate({
                  width: w
              }, animationDuration);
              me.$body.animate({
                  width: bWidth
              }, animationDuration);
              return me;
          },
  
          /**
           * Set the height of the panel
           *
           * @param {number} h
           * @param {number} animationDuration
           * @returns {LobiPanel}
           */
          setHeight: function (h, animationDuration) {
              var me = this,
                  animationDuration = animationDuration  === undefined ? 100 : animationDuration;
              if (me.isPinned()) {
                  return me;
              }
              var bHeight = me._calculateBodyHeight(h);
              me.$el.animate({
                  height: h
              }, animationDuration);
              me.$body.animate({
                  height: bHeight
              }, animationDuration);
              return me;
          },
  
          /**
           * Set size (width and height) of the panel
           *
           * @param {number} w
           * @param {number} h
           * @param {number} animationDuration
           * @returns {LobiPanel}
           */
          setSize: function (w, h, animationDuration) {
              var me = this,
                  animationDuration = animationDuration  === undefined ? 100 : animationDuration;
              if (me.isPinned()) {
                  return me;
              }
              var bHeight = me._calculateBodyHeight(h);
              var bWidth = me._calculateBodyWidth(w);
              me.$el.animate({
                  height: h,
                  width: w
              }, animationDuration);
              me.$body.animate({
                  height: bHeight,
                  width: bWidth
              }, animationDuration);
              return me;
          },
  
          /**
           * Get the position of the panel.
           * Returns object where x is left coordinate and y is top coordinate
           *
           * @returns {Object}
           */
          getPosition: function () {
              var me = this;
              var offset = me.$el.offset();
              return {
                  x: offset.left,
                  y: offset.top
              };
          },
  
          /**
           * Get width of the panel
           *
           * @returns {number}
           */
          getWidth: function () {
              var me = this;
              return me.$el.width();
          },
  
          /**
           * Get height of the panel
           *
           * @returns {number}
           */
          getHeight: function () {
              var me = this;
              return me.$el.height();
          },
  
          /**
           * If panel is overlapped by another panel this panel will be shown on front
           * (this panel will overlap other panels)
           *
           * @returns {LobiPanel}
           */
          bringToFront: function () {
              var me = this;
              me._triggerEvent("beforeToFront");
              var res = me._getMaxZIndex();
              if (res['id'] === me.$el.data('inner-id')) {
                  return me;
              }
              me.$el.css('z-index', res['z-index'] + 1);
              me._triggerEvent("onToFront");
              return me;
          },
  
          /**
           * Enable dragging of panel
           *
           * @returns {LobiPanel}
           */
          enableDrag: function () {
              var me = this;
              me.$el.draggable({
                  handle: '.panel-heading',
                  containment: me.$options.constrain,
                  start: function () {
                      me.$el.css('position', 'absolute');
                  },
                  stop: function () {
                      me.$el.css('position', '');
                      me._updateUnpinnedState();
                  }
              });
              return me;
          },
  
          /**
           * Disable dragging of the panel
           *
           * @returns {LobiPanel}
           */
          disableDrag: function () {
              var me = this;
              if (me.$el.hasClass('ui-draggable')) {
                  me.$el.draggable("destroy");
              }
              return me;
          },
  
          /**
           * Enable resize of the panel
           *
           * @returns {LobiPanel}
           */
          enableResize: function () {
              var me = this;
              var handles = false;
              if (me.$options.resize === 'vertical') {
                  handles = 'n, s';
              } else if (me.$options.resize === 'horizontal') {
                  handles = 'e, w';
              } else if (me.$options.resize === 'both') {
                  handles = 'all';
              }
              if (!handles) {
                  return me;
              }
              me.$el.resizable({
                  minWidth: me.$options.minWidth,
                  maxWidth: me.$options.maxWidth,
                  minHeight: me.$options.minHeight,
                  maxHeight: me.$options.maxHeight,
                  handles: handles,
                  start: function () {
                      me.$el.disableSelection();
                      me._triggerEvent('resizeStart');
                  },
                  stop: function () {
                      me.$el.enableSelection();
                      me._triggerEvent('resizeStop');
                  },
                  resize: function () {
                      var bHeight = me._calculateBodyHeight(me.$el.height());
                      var bWidth = me._calculateBodyWidth(me.$el.width());
                      me.$body.css({
                          width: bWidth,
                          height: bHeight
                      });
                      me._updateUnpinnedState();
                      me._triggerEvent("onResize");
                  }
              });
              return me;
          },
  
          /**
           * Disable resize of the panel
           *
           * @returns {LobiPanel}
           */
          disableResize: function () {
              var me = this;
              if (me.$el.hasClass('ui-resizable')) {
                  me.$el.resizable("destroy");
              }
              return me;
          },
  
          /**
           * Start spinner of the panel loading
           *
           * @returns {LobiPanel}
           */
          startLoading: function () {
              var me = this;
              var spinner = me._generateWindow8Spinner();
              me.$el.append(spinner);
              var sp = spinner.find('.spinner');
              sp.css('margin-top', 50);
              return me;
          },
  
          /**
           * Stop spinner of the panel loading
           *
           * @returns {LobiPanel}
           */
          stopLoading: function () {
              var me = this;
              me.$el.find('.spinner-wrapper').remove();
              return me;
          },
  
          /**
           * Set url. This url will be used to load data when Reload button is clicked
           * or pegawai calls .load() method without url parameter
           *
           * @param {string} url
           * @returns {LobiPanel}
           */
          setLoadUrl: function (url) {
              var me = this;
              me.$options.loadUrl = url;
              return me;
          },
  
          /**
           * Load data into .panel-body.
           * params object is in format
           * {
           *      url: '', //Optional: load url
           *      data: 'PlainObject or String', //Optional: A plain object or string of parameters which is sent to the server with the request.
           *      callback: 'function' //Optional: callback function which is called when load is finished
           * }
           *
           * @param {Object} params
           * @returns {LobiPanel}
           */
          load: function (params) {
              var me = this;
              params = params || {};
              if (typeof params === 'string') {
                  params = {url: params};
              }
              var url = params.url || me.$options.loadUrl,
                  data = params.data || {},
                  callback = params.callback || null;
  
              if (!url) {
                  return me;
              }
              me._triggerEvent("beforeLoad");
              me.startLoading();
              me.$body.load(url, data, function (result, status, xhr) {
                  if (callback && typeof callback === 'function') {
                      me.callback(result, status, xhr);
                  }
                  me.stopLoading();
                  me._triggerEvent("loaded", result, status, xhr);
              });
              return me;
          },
  
          /**
           * Destroy the LobiPanel instance
           *
           * @returns {jQuery}
           */
          destroy: function () {
              var me = this;
              me.disableDrag();
              me.disableResize();
              me.$options.sortable = false;
              me._enableSorting();
              me._removeInnerIdFromParent(me.innerId);
              me.$el.removeClass('lobipanel')
                  .removeAttr('data-inner-id')
                  .removeAttr('data-index')
                  .removeData('lobiPanel');
              me.$heading.find('.dropdown').remove();
              return me.$el;
          },
  
          /**
           * Creates input field to edit panel title
           *
           * @returns {LobiPanel}
           */
          startTitleEditing: function () {
              var me = this;
              var title = me.$heading.find('.panel-title').text().trim();
              var input = $('<input value="' + title + '"/>');
              input.on('keydown', function (ev) {
                  if (ev.which === 13) {
                      me.finishTitleEditing();
                  } else if (ev.which === 27) {
                      me.cancelTitleEditing();
                  }
              });
              me.$heading.find('.panel-title')
                  .data('old-title', title)
                  .html("").append(input);
              input[0].focus();
              input[0].select();
              me._changeClassOfControl(me.$heading.find('[data-func="editTitle"]'));
              return me;
          },
  
          /**
           * Check if panel title is being edited (if it is in edit process)
           *
           * @returns {Boolean}
           */
          isTitleEditing: function () {
              var me = this;
              return me.$heading.find('.panel-title input').length > 0;
          },
  
          /**
           * Cancel the panel new title and return to previous title when it is changed but not saved
           *
           * @returns {LobiPanel}
           */
          cancelTitleEditing: function () {
              var me = this;
              var title = me.$heading.find('.panel-title');
              title.html(title.data('old-title'))
                  .find('input').remove();
              me._changeClassOfControl(me.$heading.find('[data-func="editTitle"]'));
              return me;
          },
  
          /**
           * Finish the panel title editing process and save new title
           *
           * @returns {LobiPanel}
           */
          finishTitleEditing: function () {
              var me = this,
                  input = me.$heading.find('input');
              if (me._triggerEvent('beforeTitleChange', input.val()) === false){
                  return me;
              }
              me.$heading.find('.panel-title').html(input.val());
              input.remove();
              me._changeClassOfControl(me.$heading.find('[data-func="editTitle"]'));
              me._triggerEvent('onTitleChange', input.val());
              return me;
          },
  
          /**
           * Enable tooltips on panel controls
           *
           * @returns {LobiPanel}
           */
          enableTooltips: function () {
              var me = this;
              if ($(window).width() < 768) {
                  return me;
              }
              var controls = me.$heading.find('.dropdown-menu>li>a');
              controls.each(function (index, el) {
                  var $el = $(el);
                  $el.attr('data-toggle', 'tooltip')
                      .attr('data-title', $el.data('tooltip'))
                      .attr('data-placement', 'bottom')
                  ;
              });
              controls.each(function (ind, el) {
                  $(el).tooltip({
                      container: 'body',
                      template: '<div class="tooltip lobipanel-tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
                  });
              });
              return me;
          },
  
          /**
           * Disable tooltips on panel controls
           *
           * @returns {LobiPanel}
           */
          disableTooltips: function () {
              var me = this;
              var $links = me.$heading.find('.dropdown-menu>li>a');
              $links.each(function(ind, el){
                  var bsTooltip = $(el).data('bs.tooltip');
                  if (bsTooltip){
                      $(el).tooltip('destroy');
                  }
              });
              // me.$heading.find('.dropdown-menu>li>a').tooltip('destroy');
              return me;
          },
  
          _generateControls: function () {
              var me = this;
              var dropdown = me._generateDropdown();
              var menu = dropdown.find('.dropdown-menu');
              if (me.$options.editTitle !== false) {
                  menu.append(me._generateEditTitle());
              }
              if (me.$options.unpin !== false) {
                  menu.append(me._generateUnpin());
              }
              if (me.$options.reload !== false) {
                  menu.append(me._generateReload());
              }
              if (me.$options.minimize !== false) {
                  menu.append(me._generateMinimize());
              }
              if (me.$options.expand !== false) {
                  menu.append(me._generateExpand());
              }
              if (me.$options.close !== false) {
                  menu.append(me._generateClose());
              }
              menu.find('>li>a').on('click', function (ev) {
                  ev.preventDefault();
                  ev.stopPropagation();
              });
              return dropdown;
          },
          _generateDropdown: function () {
              var me = this;
              return $('<div class="dropdown"></div>')
                  .append('<ul class="dropdown-menu dropdown-menu-right"></ul>')
                  .append('<div class="dropdown-toggle" data-toggle="dropdown"><span class="' + LobiPanel.PRIVATE_OPTIONS.iconClass + ' ' + me.$options.toggleIcon + '"></div>');
          },
          _generateEditTitle: function () {
              var me = this;
              var options = me.$options.editTitle;
              var control = $('<a data-func="editTitle"></a>');
              control.append('<i class="' + LobiPanel.PRIVATE_OPTIONS.iconClass + ' ' + options.icon + '"></i>');
              if (options.tooltip && typeof options.tooltip === 'string') {
                  control.append('<span class="control-title">' + options.tooltip + '</span>');
                  control.attr('data-tooltip', options.tooltip);
              }
  
              me._attachEditTitleClickListener(control);
              return $('<li></li>').append(control);
          },
          _attachEditTitleClickListener: function (control) {
              var me = this;
              control.on('mousedown', function (ev) {
                  ev.stopPropagation();
              });
              control.on('click', function (ev) {
                  ev.stopPropagation();
                  me.hideTooltip(control);
                  if (me.isTitleEditing()) {
                      me.finishTitleEditing();
                  } else {
                      me.startTitleEditing();
                  }
              });
          },
  
          hideTooltip: function($el){
              var bsTooltip = $el.data('bs.tooltip');
  
              if (bsTooltip){
                  $el.tooltip('hide');
              }
              return this;
          },
          _generateUnpin: function () {
              var me = this;
              var options = me.$options.unpin;
              var control = $('<a data-func="unpin"></a>');
              control.append('<i class="' + LobiPanel.PRIVATE_OPTIONS.iconClass + ' ' + options.icon + '"></i>');
              if (options.tooltip && typeof options.tooltip === 'string') {
                  control.append('<span class="control-title">' + options.tooltip + '</span>');
                  control.attr('data-tooltip', options.tooltip);
              }
              me._attachUnpinClickListener(control);
              return $('<li></li>').append(control);
          },
          _attachUnpinClickListener: function (control) {
              var me = this;
              //hide the tooltip
              control.on('mousedown', function (ev) {
                  ev.stopPropagation();
              });
              control.on('click', function () {
                  me.hideTooltip(control);
                  me.doTogglePin();
              });
          },
          _generateReload: function () {
              var me = this;
              var options = me.$options.reload;
              var control = $('<a data-func="reload"></a>');
              control.append('<i class="' + LobiPanel.PRIVATE_OPTIONS.iconClass + ' ' + options.icon + '"></i>');
              if (options.tooltip && typeof options.tooltip === 'string') {
                  control.append('<span class="control-title">' + options.tooltip + '</span>');
                  control.attr('data-tooltip', options.tooltip);
              }
              me._attachReloadClickListener(control);
              return $('<li></li>').append(control);
          },
          _attachReloadClickListener: function (control) {
              var me = this;
              control.on('mousedown', function (ev) {
                  ev.stopPropagation();
              });
              control.on('click', function () {
                  me.hideTooltip(control);
                  me.load();
              });
          },
          _generateMinimize: function () {
              var me = this;
              var options = me.$options.minimize;
              var control = $('<a data-func="minimize"></a>');
              control.append('<i class="' + LobiPanel.PRIVATE_OPTIONS.iconClass + ' ' + options.icon + '"></i>');
              if (options.tooltip && typeof options.tooltip === 'string') {
                  control.append('<span class="control-title">' + options.tooltip + '</span>');
                  control.attr('data-tooltip', options.tooltip);
              }
              me._attachMinimizeClickListener(control);
              return $('<li></li>').append(control);
          },
          _attachMinimizeClickListener: function (control) {
              var me = this;
              control.on('mousedown', function (ev) {
                  ev.stopPropagation();
              });
              control.on('click', function (ev) {
                  ev.stopPropagation();
                  me.hideTooltip(control);
                  me.toggleMinimize();
              });
          },
          _generateExpand: function () {
              var me = this;
              var options = me.$options.expand;
              var control = $('<a data-func="expand"></a>');
              control.append('<i class="' + LobiPanel.PRIVATE_OPTIONS.iconClass + ' ' + options.icon + '"></i>');
              if (options.tooltip && typeof options.tooltip === 'string') {
                  control.append('<span class="control-title">' + options.tooltip + '</span>');
                  control.attr('data-tooltip', options.tooltip);
              }
              me._attachExpandClickListener(control);
              return $('<li></li>').append(control);
          },
          _attachExpandClickListener: function (control) {
              var me = this;
              control.on('mousedown', function (ev) {
                  ev.stopPropagation();
              });
              control.on('click', function (ev) {
                  ev.stopPropagation();
                  me.hideTooltip(control);
                  me.toggleSize();
              });
          },
          _generateClose: function () {
              var me = this;
              var options = me.$options.close;
              var control = $('<a data-func="close"></a>');
              control.append('<i class="' + LobiPanel.PRIVATE_OPTIONS.iconClass + ' ' + options.icon + '"></i>');
              if (options.tooltip && typeof options.tooltip === 'string') {
                  control.append('<span class="control-title">' + options.tooltip + '</span>');
                  control.attr('data-tooltip', options.tooltip);
              }
              me._attachCloseClickListener(control);
              return $('<li></li>').append(control);
          },
          _attachCloseClickListener: function (control) {
              var me = this;
              control.on('mousedown', function (ev) {
                  ev.stopPropagation();
              });
              control.on('click', function (ev) {
                  ev.stopPropagation();
                  me.hideTooltip(control);
                  me.close();
              });
          },
          _getMaxZIndex: function () {
              var me = this;
              var panels = $('.lobipanel.panel-unpin:not(.panel-minimized.panel-expanded)'),
                  style,
                  max,
                  cur;
              if (panels.length === 0) {
                  return {
                      "id": "",
                      "z-index": LobiPanel.PRIVATE_OPTIONS.initialZIndex
                  };
              }
              style = $(panels[0]).attr('style');
              var id = $(panels[0]).data('inner-id');
              if (!style) {
                  max = LobiPanel.PRIVATE_OPTIONS.initialZIndex;
              } else {
                  max = style.getCss()['z-index'];
              }
              for (var i = 1; i < panels.length; i++) {
                  style = $(panels[i]).attr('style');
                  if (!style) {
                      cur = 0;
                  } else {
                      cur = style.getCss()['z-index'];
                  }
                  if (cur > max) {
                      id = $(panels[i]).data('inner-id');
                      max = cur;
                  }
              }
              return {
                  "id": id,
                  "z-index": parseInt(max, 10)
              };
          },
          _onPanelClick: function () {
              var me = this;
              me.$el.on('mousedown.lobiPanel', function () {
                  if (me.isPinned() ||
                      me.isMinimized() ||
                      me.isOnFullScreen()) {
                      return false;
                  }
                  me.bringToFront();
              });
          },
          _offPanelClick: function () {
              var me = this;
              me.$el.off('mousedown.lobiPanel');
          },
          _changeClassOfControl: function (el) {
              var me = this;
              el = $(el);
              var opts = me.$options[el.attr('data-func')];
              if (!opts.icon) {
                  return;
              }
              el.find('.' + LobiPanel.PRIVATE_OPTIONS.iconClass).toggleClass(opts.icon).toggleClass(opts.icon2);
          },
          _getFooterForMinimizedPanels: function () {
              var me = this;
              //we grab footer where minimized panels should go
              var minimizedCtr = $('.' + LobiPanel.PRIVATE_OPTIONS.toolbarClass);
              //if panel does not exist we create it and append to body
              if (minimizedCtr.length === 0) {
                  minimizedCtr = $('<div class="' + LobiPanel.PRIVATE_OPTIONS.toolbarClass + '"></div>');
                  $('body').append(minimizedCtr);
              }
              return minimizedCtr;
          },
          _expandOnHeaderClick: function () {
              var me = this;
              me.$heading.on('click.lobiPanel', function () {
                  me.maximize();
                  me.bringToFront();
              });
          },
          _removeExpandOnHeaderClick: function () {
              var me = this;
              me.$heading.off('click.lobiPanel');
          },
          _getAvailableWidth: function (calcWidth) {
              var me = this;
              if (me.$options.maxWidth) {
                  calcWidth = Math.min(calcWidth, me.$options.maxWidth);
              }
              if (me.$options.minWidth) {
                  calcWidth = Math.max(calcWidth, me.$options.minWidth);
              }
              return calcWidth;
          },
          _getAvailableHeight: function (calcHeight) {
              var me = this;
              if (me.$options.maxHeight) {
                  calcHeight = Math.min(calcHeight, me.$options.maxHeight);
              }
              if (me.$options.minHeight) {
                  calcHeight = Math.max(calcHeight, me.$options.minHeight);
              }
              return calcHeight;
          },
          _calculateBodyHeight: function (h) {
              var me = this;
              return h - me.$heading.outerHeight() - me.$el.find('.panel-footer').outerHeight();
          },
          _calculateBodyWidth: function (w) {
              var me = this;
              return w - 2;
          },
          _appendInnerIdToParent: function (parent, innerId) {
              var me = this;
              //If this is first lobipanel element of its parent
              if (parent.attr(LobiPanel.PRIVATE_OPTIONS.parentAttr) === undefined) {
                  parent.attr(LobiPanel.PRIVATE_OPTIONS.parentAttr, innerId);
              }
              //This means that parent already has LobiPanel instance
              else {
                  //if parent already has panel innerId than we do nothing
                  if (parent.attr(LobiPanel.PRIVATE_OPTIONS.parentAttr).indexOf(innerId) > -1) {
                      return;
                  }
                  var innerIds = parent.attr(LobiPanel.PRIVATE_OPTIONS.parentAttr);
                  parent.attr(LobiPanel.PRIVATE_OPTIONS.parentAttr, innerIds + " " + innerId);
              }
              me.$el.attr('data-index', me.$el.index());
          },
          _insertInParent: function () {
              var me = this;
              //find its parent element
              var parent = $('[' + LobiPanel.PRIVATE_OPTIONS.parentAttr + '~=' + me.innerId + ']');
              me.$el.insertAt(me.$el.attr('data-index'), parent);
          },
          _generateWindow8Spinner: function () {
              var me = this;
              var template = ['<div class="spinner spinner-windows8">',
                  '<div class="wBall">',
                  '<div class="wInnerBall">',
                  '</div>',
                  '</div>',
                  '<div class="wBall">',
                  '<div class="wInnerBall">',
                  '</div>',
                  '</div>',
                  '<div class="wBall">',
                  '<div class="wInnerBall">',
                  '</div>',
                  '</div>',
                  '<div class="wBall">',
                  '<div class="wInnerBall">',
                  '</div>',
                  '</div>',
                  '<div class="wBall">',
                  '<div class="wInnerBall">',
                  '</div>',
                  '</div>',
                  '</div>'].join("");
              return $('<div class="spinner-wrapper">' + template + '</div>');
          },
          _enableSorting: function () {
              var me = this;
              var parent = me.$el.parent();
              if (parent.hasClass('ui-sortable')) {
                  parent.sortable("destroy");
              }
              if (me.$options.sortable) {
                  me.$el.addClass('lobipanel-sortable');
                  parent.addClass('lobipanel-parent-sortable');
              } else {
                  me.$el.removeClass('lobipanel-sortable');
              }
              parent.sortable({
                  connectWith: '.lobipanel-parent-sortable',
                  items: '.lobipanel-sortable',
                  handle: '.panel-heading',
                  cursor: 'move',
                  placeholder: 'lobipanel-placeholder',
                  forcePlaceholderSize: true,
                  opacity: 0.7,
                  revert: 300,
                  update: function (event, ui) {
                      var innerId = ui.item.data('inner-id');
                      me._removeInnerIdFromParent(innerId);
                      me._appendInnerIdToParent(ui.item.parent(), innerId);
                      me._updateDataIndices(ui.item);
                      me._triggerEvent('dragged');
                  }
              });
          },
          _disableSorting: function () {
              var me = this;
              var parent = me.$el.parent();
              if (parent.hasClass('ui-sortable')) {
                  parent.sortable("destroy");
              }
          },
          _updateDataIndices: function (panel) {
              var me = this;
              var items = panel.parent().children();
              items.each(function (index, el) {
                  $(el).attr('data-index', index);
                  var lobiPanel = $(el).data('lobiPanel');
                  if (lobiPanel && lobiPanel.$options.stateful && !lobiPanel.hasRandomId){
                      lobiPanel._saveState('pinned', {index: index});
                  }
              });
              // me._saveState('pinned', {index: panel.index()})
              console.log("Save indices in localstorage");
  
          },
          _removeInnerIdFromParent: function (innerId) {
              var me = this;
              var parent = $('[' + LobiPanel.PRIVATE_OPTIONS.parentAttr + '~=' + innerId + ']');
              var innerIds = parent.attr(LobiPanel.PRIVATE_OPTIONS.parentAttr).replace(innerId, '').trim().replace(/\s{2,}/g, ' ');
              parent.attr(LobiPanel.PRIVATE_OPTIONS.parentAttr, innerIds);
          },
          _onToggleIconsBtnClick: function () {
              var me = this;
              me.$heading.find('.toggle-controls').on('click.lobiPanel', function () {
                  me.$el.toggleClass("controls-expanded");
              });
          },
          _adjustForScreenSize: function () {
              var me = this;
              me.disableTooltips();
              if ($(window).width() > 768 && me.$options.tooltips) {
                  me.enableTooltips();
              }
              if (me.isOnFullScreen()) {
                  me.$body.css({
                      width: me._calculateBodyWidth(me.$el.width()),
                      height: me._calculateBodyHeight(me.$el.height())
                  });
              }
          },
          _enableResponsiveness: function () {
              var me = this;
              me._adjustForScreenSize();
              $(window).on('resize.lobiPanel', function () {
                  me._adjustForScreenSize();
              });
          },
          _setBodyHeight: function () {
              var me = this;
              if (me.$options.bodyHeight !== 'auto') {
                  me.$body.css({
                      'height': me.$options.bodyHeight,
                      overflow: 'auto'
                  });
              }
          },
          _getOptionsFromAttributes: function () {
              var me = this;
              var $el = me.$el;
              var options = {};
              for (var key in $.fn.lobiPanel.DEFAULTS) {
                  var k = key.toDash();
                  var val = $el.data(k);
                  if (val !== undefined) {
                      if (typeof $.fn.lobiPanel.DEFAULTS[key] !== 'object') {
                          options[key] = val;
                      } else {
                          options[key] = eval('(' + val + ')');
                      }
                  }
              }
              return options;
          },
          _saveState: function (state, params) {
              var me = this;
              console.log("Save state ", state, params);
              if (!me.hasRandomId && me.$options.stateful) {
                  me.storage.state = state;
                  if (params) {
                      me.storage.stateParams = params;
                  }
                  me._saveLocalStorage(me.storage);
              }
          },
          _saveLocalStorage: function (storage) {
              var me = this;
              localStorage.setItem(STORAGE_PREFIX + me.innerId, JSON.stringify(storage));
          },
          _applyState: function (state, params) {
              var me = this;
              switch (state) {
                  case 'pinned':
                      if (params && params.index !== null && params.index !== undefined) {
                          me._applyIndex(params.index);
                      }
                      break;
                  case 'unpinned':
                      me.unpin();
                      me.setPosition(params.left, params.top, 0);
                      me.setSize(params.width, params.height, 0);
                      break;
                  case 'minimized':
                      me.unpin();
                      me.minimize();
                      break;
                  case 'collapsed':
                      me.minimize();
                      break;
                  case 'fullscreen':
                      me.toFullScreen();
                      break;
                  default:
                      break;
              }
          },
          _applyIndex: function (index) {
              var me = this;
              if (index !== null) {
                  me.$el.insertAt(index, me.$el.parent());
              }
          },
          _triggerEvent: function (eventType) {
              var me = this;
              var args = Array.prototype.slice.call(arguments, 1);
              args.unshift(me);
  
              me.$el.trigger(eventType + '.lobiPanel', args);
              if (me.$options[eventType] && typeof me.$options[eventType] === 'function'){
                  return me.$options[eventType].apply(me, args);
              }
  
              return true;
          },
          doPin: function(){
              var me = this;
              if (me._triggerEvent("beforePin") !== false){
                  me.pin();
                  me._saveState('pinned');
                  me._triggerEvent("onPin");
              }
              return me;
          },
          doUnpin: function(){
              var me = this;
              if (me._triggerEvent('beforeUnpin') !== false){
                  me.unpin();
                  me._updateUnpinnedState();
                  me._triggerEvent('onUnpin');
              }
              return me;
          },
          doTogglePin: function(){
              var me = this;
              if (this.isPinned()) {
                  this.doUnpin();
              } else {
                  this.doPin();
              }
              return me;
          },
          _updateUnpinnedState: function(){
              var me = this;
              me._saveState('unpinned', me.getAlignment());
          },
          getAlignment: function(){
              var me = this;
              return {
                  top: me.$el.css('top'),
                  left: me.$el.css('left'),
                  width: me.$el.css('width'),
                  height: me.$el.css('height')
              };
          }
      };
  
      $.fn.lobiPanel = function (option) {
          var args = arguments,
              ret = null;
          this.each(function () {
  
              var $this = $(this);
              var data = $this.data('lobiPanel');
              var options = typeof option === 'object' && option;
  
              if (!data) {
                  $this.data('lobiPanel', (data = new LobiPanel($this, options)));
              }
              if (typeof option === 'string') {
                  args = Array.prototype.slice.call(args, 1);
                  ret = data[option].apply(data, args);
              }
          });
          return ret;
      };
      LobiPanel.PRIVATE_OPTIONS = {
          //We need to know what is the parent of the panel, that's why we add
          //this attribute to parent element and it contains space seperated inner-ids of all its child lobipanel
          parentAttr: 'data-lobipanel-child-inner-id',
          toolbarClass: 'lobipanel-minimized-toolbar', //This class is added to container which contains all minimized panels
          //First instance on lobiPanel will get this z-index css property.
          //Every next instance will get 1 + previous z-index
          initialZIndex: 10000,
          //This class is attached to every panel-control icon
          iconClass: 'panel-control-icon'
      };
      $.fn.lobiPanel.DEFAULTS = {
          //Makes <b>unpinned</b> panel draggable
          //Warning!!! This requires jquery ui draggable widget to be included
          draggable: true,
          //Makes <b>pinned</b> panels sortable
          //Warning!!! This requires jquery ui sortable widget to be included
          sortable: false,
          //jquery ui sortable plugin option.
          //To avoid any problems this option must be same for all panels which are direct children of their parent
          connectWith: '.ui-sortable',
          //This parameter accepts string ['both', 'vertical', 'horizontal', 'none']. none means disable resize
          resize: 'both',
          //Minimum width <b>unpin, resizable</b> panel can have.
          minWidth: 200,
          //Minimum height <b>unpin, resizable</b> panel can have.
          minHeight: 100,
          //Maximum width <b>unpin, resizable</b> panel can have.
          maxWidth: 1200,
          //Maximum height <b>unpin, resizable</b> panel can have.
          maxHeight: 700,
          //The url which will be used to load content. If not provided reload button will do nothing
          loadUrl: "",
          //If loadUrl is provided plugin will load content as soon as plugin is initialized
          autoload: true,
          bodyHeight: 'auto',
          //This will enable tooltips on panel controls
          tooltips: true,
          toggleIcon: 'glyphicon glyphicon-cog',
          expandAnimation: 100,
          collapseAnimation: 100,
          state: 'pinned', // Initial state of the panel. Available options: pinned, unpinned, collapsed, minimized, fullscreen
          initialIndex: null, // Initial index of the panel among its siblings
          stateful: false, // If you set this to true you must specify data-inner-id. Plugin will save (in localStorage) it's states such as
                           // pinned, unpinned, collapsed, minimized, fullscreen, position among it's siblings
                           // and apply them when you reload the browser
          constrain: 'document', // 'parent', 'document', 'window'
          unpin: {
              icon: 'glyphicon glyphicon-move', //You can pegawai glyphicons if you do not want to use font-awesome
              tooltip: 'Unpin'               //tooltip text, If you want to disable tooltip, set it to false
          },
          reload: {
              icon: 'glyphicon glyphicon-refresh', //You can pegawai glyphicons if you do not want to use font-awesome
              tooltip: 'Reload'           //tooltip text, If you want to disable tooltip, set it to false
          },
          minimize: {
              icon: 'glyphicon glyphicon-minus', //icon is shown when panel is not minimized
              icon2: 'glyphicon glyphicon-plus', //icon2 is shown when panel is minimized
              tooltip: 'Minimize'         //tooltip text, If you want to disable tooltip, set it to false
          },
          expand: {
              icon: 'glyphicon glyphicon-resize-full', //icon is shown when panel is not on full screen
              icon2: 'glyphicon glyphicon-resize-small', //icon2 is shown when pane is on full screen state
              tooltip: 'Fullscreen'       //tooltip text, If you want to disable tooltip, set it to false
          },
          close: {
              icon: 'glyphicon glyphicon-remove', //You can pegawai glyphicons if you do not want to use font-awesome
              tooltip: 'Close'            //tooltip text, If you want to disable tooltip, set it to false
          },
          editTitle: {
              icon: 'glyphicon glyphicon-pencil',
              icon2: 'glyphicon glyphicon-floppy-disk',
              tooltip: 'Edit title'
          },
  
  
  
  
          // Events
          /**
           * @event beforeTitleChange
           * Fires before title change happens. Returning false will prevent title change from happening.
           * @param {LobiPanel} The <code>LobiPanel</code> instance
           */
          beforeTitleChange: null
      };
  
      $('.lobipanel').lobiPanel();
  });
  
  