Full Code of arboshiki/lobipanel for AI

master f41b4bbdf939 cached
25 files
305.6 KB
76.6k tokens
20 symbols
1 requests
Download .txt
Showing preview only (317K chars total). Download the full file or copy to clipboard to get everything.
Repository: arboshiki/lobipanel
Branch: master
Commit: f41b4bbdf939
Files: 25
Total size: 305.6 KB

Directory structure:
gitextract_mvrfn518/

├── .gitignore
├── LICENSE
├── README.md
├── bootstrap/
│   └── js/
│       └── npm.js
├── bower.json
├── css/
│   └── lobipanel.css
├── demo/
│   ├── demo.css
│   ├── documentation.css
│   ├── iframe.html
│   └── stateful.html
├── dist/
│   ├── css/
│   │   └── lobipanel.css
│   └── js/
│       └── lobipanel.js
├── gulpfile.js
├── index.html
├── js/
│   └── lobipanel.js
├── less/
│   ├── loading-animation.less
│   ├── lobipanel.less
│   ├── main.less
│   └── variables.less
├── lib/
│   ├── font-awesome/
│   │   ├── css/
│   │   │   └── font-awesome.css
│   │   └── fonts/
│   │       └── FontAwesome.otf
│   ├── highlight/
│   │   ├── github.css
│   │   └── highlight.pack.js
│   └── jquery.ui.touch-punch.js
└── package.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.idea/
bower_components/
node_modules/

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 Zura Sekhniashvili

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



================================================
FILE: README.md
================================================
# LobiPanel
[![CDNJS](https://img.shields.io/cdnjs/v/lobipanel.svg)](https://cdnjs.com/libraries/lobipanel)

jQuery plugin for bootstrap panels. It extends panels with several common and useful functions.

[View Demo](http://lobianijs.com/site/lobipanel)

### Features

- Sort, drag, expand, resize, minimize bootstrap panels
- Specify url and load content in panel from this url
- Change the name of the panel
- Customize action icons and action tooltips
- Works for nested panels
- HTML5 localStorage support
    - Save panel state: (pinned, unpinned, collapsed, fullscreen, minimized) and apply it on page load
    - Save panel position among siblings and apply on next time

### Installation and dependecies

LobiPanel is depended on jQuery, jQuery ui and bootstrap.

#### 1. Include necessary css/js files

```html
<!DOCTYPE html>
<html>
   <head>
        <!--Default installation-->
        <link rel="stylesheet" href="lib/jquery-ui.min.css"/>
        <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
        <link rel="stylesheet" href="lib/font-awesome/css/font-awesome.min.css"/>

        <!--Installation using bower. Preferred!!! -->
        <!--<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"/>-->
        <!--<link rel="stylesheet" href="bower_components/jquery-ui/themes/ui-lightness/jquery-ui.min.css"/>-->
        <!--Run `bower install font-awesome` and uncomment this line to see font awesome examples-->
        <!--<link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.min.css"/>-->

        <link rel="stylesheet" href="dist/css/lobipanel.min.css"/>
   </head>

    <body>
        ...
        <!--Default installation-->
        <script src="lib/jquery.1.11.min.js"></script>
        <script src="lib/jquery-ui.min.js"></script>
        <script src="lib/jquery.ui.touch-punch.min.js"></script>
        <script src="bootstrap/js/bootstrap.min.js"></script>

        <!--Installation using bower. Preferred!!! -->
        <!--<script src="bower_components/jquery/dist/jquery.min.js"></script>-->
        <!--<script src="bower_components/jquery-ui/jquery-ui.min.js"></script>-->
        <!--<script src="bower_components/jquery-ui-touch-punch-improved/jquery.ui.touch-punch-improved.js"></script>-->
        <!--<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>-->

        <script src="dist/js/lobipanel.js"></script>

   </body>
</html>
```

#### 2. Initialize plugin and use it

#### Stateful panels
In order stateful panels to works you need to:
 - Give `stateful: true` to panel options.
 - Give `data-inner-id` to lobipanel element and parent element to keep track of the child
 which contacts lobipanels as unique identifier

### For documentation and examples visit the plugin's [home page](http://lobianijs.com/site/lobipanel)


================================================
FILE: bootstrap/js/npm.js
================================================
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')

================================================
FILE: bower.json
================================================
{
  "name": "lobipanel",
  "description": "jQuery plugin for bootstrap panels. It extends panels with several common and useful functions",
  "main": [
    "css/lobipanel.css",
    "js/lobipanel.js"
  ],
  "authors": [
    {
      "name": "Zura Sekhniashvili",
      "email": "zurasekhniashvili@gmail.com",
      "homepage": "https://github.com/arboshiki"
    }
  ],
  "license": "MIT",
  "keywords": [
    "jQuery",
    "plugin",
    "bootstrap panels",
    "floating windows",
    "ajax loading panels",
    "localStorage"
  ],
  "homepage": "https://github.com/arboshiki/lobibox",
  "moduleType": [],
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "bootstrap": "^3.3.6",
    "jquery-ui": "^1.11.4",
    "jquery-ui-touch-punch-improved": "^0.3.1"
  }
}


================================================
FILE: css/lobipanel.css
================================================
.spinner-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.5);
}
.spinner-windows8 {
  position: relative;
  display: block;
  margin: 0 auto;
  width: 50px;
  height: 50px;
  margin-top: 100px;
}
.spinner-windows8 .wBall {
  position: absolute;
  width: 48px;
  height: 48px;
  opacity: 0;
  -moz-transform: rotate(225deg);
  -moz-animation: orbit 2.75s infinite;
  -webkit-transform: rotate(225deg);
  -webkit-animation: orbit 2.75s infinite;
  -ms-transform: rotate(225deg);
  -ms-animation: orbit 2.75s infinite;
  -o-transform: rotate(225deg);
  -o-animation: orbit 2.75s infinite;
  transform: rotate(225deg);
  animation: orbit 2.75s infinite;
}
.spinner-windows8 .wBall .wInnerBall {
  position: absolute;
  width: 6px;
  height: 6px;
  background: #000000;
  left: 0px;
  top: 0px;
  -moz-border-radius: 6px;
  -webkit-border-radius: 6px;
  -ms-border-radius: 6px;
  -o-border-radius: 6px;
  border-radius: 6px;
  z-index: 2;
}
.spinner-windows8 .wBall:first-child {
  -moz-animation-delay: 0.6s;
  -webkit-animation-delay: 0.6s;
  -ms-animation-delay: 0.6s;
  -o-animation-delay: 0.6s;
  animation-delay: 0.6s;
}
.spinner-windows8 .wBall:nth-child(2) {
  -moz-animation-delay: 0.12s;
  -webkit-animation-delay: 0.12s;
  -ms-animation-delay: 0.12s;
  -o-animation-delay: 0.12s;
  animation-delay: 0.12s;
}
.spinner-windows8 .wBall:nth-child(3) {
  -moz-animation-delay: 0.24s;
  -webkit-animation-delay: 0.24s;
  -ms-animation-delay: 0.24s;
  -o-animation-delay: 0.24s;
  animation-delay: 0.24s;
}
.spinner-windows8 .wBall:nth-child(4) {
  -moz-animation-delay: 0.36s;
  -webkit-animation-delay: 0.36s;
  -ms-animation-delay: 0.36s;
  -o-animation-delay: 0.36s;
  animation-delay: 0.36s;
}
.spinner-windows8 .wBall:nth-child(5) {
  -moz-animation-delay: 0.48s;
  -webkit-animation-delay: 0.48s;
  -ms-animation-delay: 0.48s;
  -o-animation-delay: 0.48s;
  animation-delay: 0.48s;
}
@-moz-keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    -moz-transform: rotate(180deg);
    -moz-animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    -moz-transform: rotate(300deg);
    -moz-animation-timing-function: linear;
    -moz-origin: 0%;
  }
  30% {
    opacity: 1;
    -moz-transform: rotate(410deg);
    -moz-animation-timing-function: ease-in-out;
    -moz-origin: 7%;
  }
  39% {
    opacity: 1;
    -moz-transform: rotate(645deg);
    -moz-animation-timing-function: linear;
    -moz-origin: 30%;
  }
  70% {
    opacity: 1;
    -moz-transform: rotate(770deg);
    -moz-animation-timing-function: ease-out;
    -moz-origin: 39%;
  }
  75% {
    opacity: 1;
    -moz-transform: rotate(900deg);
    -moz-animation-timing-function: ease-out;
    -moz-origin: 70%;
  }
  76% {
    opacity: 0;
    -moz-transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    -moz-transform: rotate(900deg);
  }
}
@-webkit-keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    -webkit-transform: rotate(180deg);
    -webkit-animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    -webkit-transform: rotate(300deg);
    -webkit-animation-timing-function: linear;
    -webkit-origin: 0%;
  }
  30% {
    opacity: 1;
    -webkit-transform: rotate(410deg);
    -webkit-animation-timing-function: ease-in-out;
    -webkit-origin: 7%;
  }
  39% {
    opacity: 1;
    -webkit-transform: rotate(645deg);
    -webkit-animation-timing-function: linear;
    -webkit-origin: 30%;
  }
  70% {
    opacity: 1;
    -webkit-transform: rotate(770deg);
    -webkit-animation-timing-function: ease-out;
    -webkit-origin: 39%;
  }
  75% {
    opacity: 1;
    -webkit-transform: rotate(900deg);
    -webkit-animation-timing-function: ease-out;
    -webkit-origin: 70%;
  }
  76% {
    opacity: 0;
    -webkit-transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    -webkit-transform: rotate(900deg);
  }
}
@-ms-keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    -ms-transform: rotate(180deg);
    -ms-animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    -ms-transform: rotate(300deg);
    -ms-animation-timing-function: linear;
    -ms-origin: 0%;
  }
  30% {
    opacity: 1;
    -ms-transform: rotate(410deg);
    -ms-animation-timing-function: ease-in-out;
    -ms-origin: 7%;
  }
  39% {
    opacity: 1;
    -ms-transform: rotate(645deg);
    -ms-animation-timing-function: linear;
    -ms-origin: 30%;
  }
  70% {
    opacity: 1;
    -ms-transform: rotate(770deg);
    -ms-animation-timing-function: ease-out;
    -ms-origin: 39%;
  }
  75% {
    opacity: 1;
    -ms-transform: rotate(900deg);
    -ms-animation-timing-function: ease-out;
    -ms-origin: 70%;
  }
  76% {
    opacity: 0;
    -ms-transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    -ms-transform: rotate(900deg);
  }
}
@-o-keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    -o-transform: rotate(180deg);
    -o-animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    -o-transform: rotate(300deg);
    -o-animation-timing-function: linear;
    -o-origin: 0%;
  }
  30% {
    opacity: 1;
    -o-transform: rotate(410deg);
    -o-animation-timing-function: ease-in-out;
    -o-origin: 7%;
  }
  39% {
    opacity: 1;
    -o-transform: rotate(645deg);
    -o-animation-timing-function: linear;
    -o-origin: 30%;
  }
  70% {
    opacity: 1;
    -o-transform: rotate(770deg);
    -o-animation-timing-function: ease-out;
    -o-origin: 39%;
  }
  75% {
    opacity: 1;
    -o-transform: rotate(900deg);
    -o-animation-timing-function: ease-out;
    -o-origin: 70%;
  }
  76% {
    opacity: 0;
    -o-transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    -o-transform: rotate(900deg);
  }
}
@keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    transform: rotate(180deg);
    animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    transform: rotate(300deg);
    animation-timing-function: linear;
    origin: 0%;
  }
  30% {
    opacity: 1;
    transform: rotate(410deg);
    animation-timing-function: ease-in-out;
    origin: 7%;
  }
  39% {
    opacity: 1;
    transform: rotate(645deg);
    animation-timing-function: linear;
    origin: 30%;
  }
  70% {
    opacity: 1;
    transform: rotate(770deg);
    animation-timing-function: ease-out;
    origin: 39%;
  }
  75% {
    opacity: 1;
    transform: rotate(900deg);
    animation-timing-function: ease-out;
    origin: 70%;
  }
  76% {
    opacity: 0;
    transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    transform: rotate(900deg);
  }
}
.tooltip {
  z-index: 20000;
}
body.lobipanel-minimized {
  padding-bottom: 36px;
}
.lobipanel {
  position: relative;
  margin-bottom: 15px;
}
.lobipanel > .panel-heading {
  padding: 5px;
  position: relative;
  border-top-right-radius: 0px;
  border-top-left-radius: 0px;
}
.lobipanel > .panel-heading > .panel-title {
  float: left;
  max-width: calc(100% - 30px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 16px;
  line-height: 30px;
  padding-left: 15px;
}
.lobipanel > .panel-heading > .panel-title h1,
.lobipanel > .panel-heading > .panel-title h2,
.lobipanel > .panel-heading > .panel-title h3,
.lobipanel > .panel-heading > .panel-title h4,
.lobipanel > .panel-heading > .panel-title h5,
.lobipanel > .panel-heading > .panel-title h6 {
  margin: 0;
  line-height: 30px;
}
.lobipanel > .panel-heading > .panel-title input {
  color: inherit;
  line-height: 30px;
  border-radius: 2px;
  padding: 0 5px;
  width: 100%;
  background-color: rgba(0, 0, 0, 0.2);
  border: 1px solid transparent;
  outline: 0;
}
.lobipanel > .panel-heading > .panel-title input:focus {
  background-color: rgba(0, 0, 0, 0.15);
}
.lobipanel > .panel-heading .dropdown {
  display: inline-block;
  float: right;
  position: relative;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu {
  left: auto;
  right: 0;
  min-width: 0;
  margin-top: 0;
  border-radius: 0;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu > li > a .control-title {
  display: inline-block;
  margin-left: 15px;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item {
  position: relative;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list {
  position: absolute;
  background: #f5f5f5;
  box-shadow: 2px 2px 12px rgba(0, 0, 0, 0.3);
  padding: 4px;
  display: none;
  width: 92px;
  top: 100%;
  right: 0;
  z-index: 2;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list .style-item {
  cursor: pointer;
  display: inline-block;
  width: 24px;
  height: 24px;
  margin: 2px;
  border: 2px solid #f5f5f5;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list .style-item:hover {
  border-color: #FFF;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list .style-item:active {
  box-shadow: inset 2px 2px 10px rgba(0, 0, 0, 0.3);
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list.opened {
  display: block;
}
.lobipanel > .panel-heading .dropdown .dropdown-toggle {
  border: none;
  outline: 0;
  background-color: transparent;
  text-align: center;
  padding: 0;
  width: 30px;
  font-size: 14px;
  -webkit-transition: all 0.2s;
  -o-transition: all 0.2s;
  transition: all 0.2s;
}
.lobipanel > .panel-heading .dropdown .dropdown-toggle .panel-control-icon {
  top: 0;
  line-height: 30px;
}
.lobipanel > .panel-heading .dropdown .dropdown-toggle:hover,
.lobipanel > .panel-heading .dropdown .dropdown-toggle:hover:focus {
  text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6);
  background-color: rgba(0, 0, 0, 0.15);
}
.lobipanel > .panel-heading .dropdown.open .dropdown-toggle {
  text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6);
  background-color: rgba(0, 0, 0, 0.15);
}
.lobipanel > .panel-heading:before,
.lobipanel > .panel-heading:after {
  content: " ";
  display: table;
}
.lobipanel > .panel-heading:after {
  clear: both;
}
@media screen and (min-width: 768px) {
  .lobipanel .panel-heading .panel-title {
    max-width: calc(100% - 180px);
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu {
    position: static;
    display: inline-block;
    border: none;
    padding: 0;
    margin: 0;
    min-width: 0;
    width: auto;
    -webkit-box-shadow: none;
    box-shadow: none;
    background: transparent;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li {
    display: inline-block;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a {
    cursor: pointer;
    color: inherit;
    padding: 0;
    outline: 0;
    text-align: center;
    width: 30px;
    font-size: 14px;
    -webkit-transition: all 0.2s;
    -o-transition: all 0.2s;
    transition: all 0.2s;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a .panel-control-icon {
    top: 0;
    line-height: 30px;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a .control-title {
    display: none;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a:hover,
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a:focus:hover {
    text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6);
    background-color: rgba(0, 0, 0, 0.15);
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a:focus {
    text-shadow: none;
    background-color: transparent;
  }
  .lobipanel .panel-heading .dropdown .dropdown-toggle {
    display: none;
  }
}
.lobipanel > .panel-body {
  overflow: auto;
  position: relative;
}
.lobipanel .panel-loader {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #fff;
  opacity: 0.8;
}
.lobipanel.panel-collapsed > .panel-heading {
  border-bottom: none;
}
.lobipanel.panel-collapsed > .panel-heading .dropdown .dropdown-menu > li > a[data-func="unpin"],
.lobipanel.panel-collapsed > .panel-heading .dropdown .dropdown-menu > li > a[data-func="reload"] {
  display: none;
}
.lobipanel.panel-expanded,
.lobipanel.panel-unpin,
.lobipanel.panel-minimized.panel-unpin {
  margin-bottom: 0;
}
.lobipanel.panel-unpin {
  overflow: hidden;
  position: absolute;
  z-index: 10000;
  -webkit-box-shadow: 2px 2px 15px 5px rgba(10, 10, 10, 0.5);
  box-shadow: 2px 2px 15px 5px rgba(10, 10, 10, 0.5);
}
.lobipanel.panel-unpin > .panel-heading {
  cursor: move;
}
.lobipanel.panel-unpin.panel-minimized {
  float: left;
  position: static;
  border-radius: 0;
  -webkit-box-shadow: none;
  box-shadow: none;
  min-width: 170px;
  margin-right: 5px;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading {
  padding: 0;
  cursor: pointer;
  border-bottom: none;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title {
  max-width: calc(100% - 60px);
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h1,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h2,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h3,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h4,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h5,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h6 {
  overflow: hidden;
  text-overflow: ellipsis;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu {
  position: static;
  display: inline-block;
  border: none;
  padding: 0;
  margin: 0;
  min-width: 0;
  width: auto;
  -webkit-box-shadow: none;
  box-shadow: none;
  background: transparent;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li {
  display: inline-block;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a {
  cursor: pointer;
  color: inherit;
  padding: 0;
  outline: 0;
  text-align: center;
  width: 30px;
  font-size: 14px;
  -webkit-transition: all 0.2s;
  -o-transition: all 0.2s;
  transition: all 0.2s;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a .panel-control-icon {
  top: 0;
  line-height: 30px;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a .control-title {
  display: none;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a:hover,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a:focus:hover {
  text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6);
  background-color: rgba(0, 0, 0, 0.15);
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a:focus {
  text-shadow: none;
  background-color: transparent;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-toggle {
  display: none;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a {
  display: none;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a[data-func="close"],
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a[data-func="expand"] {
  display: inline-block;
}
.lobipanel.panel-unpin.panel-minimized > .panel-body,
.lobipanel.panel-unpin.panel-minimized > .panel-footer {
  display: none !important;
}
.lobipanel.panel-expanded > .panel-heading {
  cursor: default;
}
.lobipanel.panel-expanded > .panel-heading .dropdown .dropdown-menu > li > a[data-func="unpin"],
.lobipanel.panel-expanded > .panel-heading .dropdown .dropdown-menu > li > a[data-func="minimize"] {
  display: none;
}
.lobipanel.panel-expanded.panel-unpin > .panel-heading .panel-control[data-func="minimize"] {
  display: block;
}
.lobipanel-minimized-toolbar {
  position: fixed;
  height: 36px;
  padding: 2px;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 20000;
  background: rgba(34, 115, 182, 0.51);
}
.lobipanel-placeholder {
  background-color: #f9f5d1;
  border: 1px dashed #919191;
  margin-bottom: 15px;
}
.lobipanel-parent-sortable {
  min-height: 20px;
}


================================================
FILE: demo/demo.css
================================================
.highlight {
    overflow: auto;
    padding: 9px 14px;
    margin-bottom: 14px;
    background-color: #f7f7f9;
    border: 1px solid #e1e1e8;
    border-radius: 4px
}

.highlight pre {
    min-width: 400px;
    padding: 0;
    margin-top: 0;
    margin-bottom: 0;
    word-break: normal;
    white-space: nowrap;
    background-color: transparent;
    border: 0
}

.highlight pre code {
    padding: 0;
    background-color: transparent
}

.bs-example+.highlight {
    margin-top: -16px;
    border-top-right-radius: 0;
    border-top-left-radius: 0
}

.lobipanel-parent-sortable{
    border: 1px solid rgba(0, 0, 0, 0.3);
}

================================================
FILE: demo/documentation.css
================================================
.plugin-documentation .row{margin-left:0;margin-right:0;border-bottom:1px solid #ddd}.plugin-documentation .row-header .cell{text-transform:uppercase;font-size:.8em;color:#999;background-color:#eee}.plugin-documentation .cell{float:left;font-size:.95em;padding:6px 9px;width:100%}.plugin-documentation .cell pre{min-width:320px}.plugin-documentation .text-mobile{display:none}@media screen and (max-width:768px){.plugin-documentation .row{padding-left:0;padding-right:0}.plugin-documentation .row-header{display:none}.plugin-documentation .cell{width:100%!important;padding:0;margin-bottom:3px}.plugin-documentation .text-mobile{font-weight:400;display:inline}}.plugin-documentation.plugin-options .cell-name{width:16.66666667%}.plugin-documentation.plugin-options .cell-type{width:8.33333333%}.plugin-documentation.plugin-options .cell-default{width:25%}.plugin-documentation.plugin-options .cell-descr{width:50%}.plugin-documentation.plugin-methods .cell-name{width:16.66666667%}.plugin-documentation.plugin-methods .cell-params{width:33.33333333%}.plugin-documentation.plugin-methods .cell-params>div>i{font-weight:700}.plugin-documentation.plugin-methods .cell-return{width:16.66666667%}.plugin-documentation.plugin-methods .cell-descr{width:33.33333333%}.plugin-documentation.plugin-events .cell-name,.plugin-documentation.plugin-events .cell-params{width:25%}.plugin-documentation.plugin-events .cell-params>div>code{font-style:italic;font-weight:700}.plugin-documentation.plugin-events .cell-descr{width:50%}@media screen and (max-width:768px){.plugin-documentation .cell-name{font-size:102%;font-weight:700}.plugin-documentation .cell-default,.plugin-documentation .cell-descr,.plugin-documentation .cell-params,.plugin-documentation .cell-return{padding-left:30px}.plugin-documentation .cell-params>div{padding-left:20px}.plugin-documentation.plugin-options .cell-type{display:none}.plugin-documentation.plugin-methods .cell-params>div>i{font-weight:700}.plugin-documentation.plugin-methods .cell-return{display:none}}

================================================
FILE: demo/iframe.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Lobipanel - jQuery plugin for bootstrap panels. It extends panels with several common and useful
        functions.</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!--Default installation-->
    <link rel="stylesheet" href="../bower_components/jquery-ui/themes/ui-lightness/jquery-ui.min.css"/>
    <link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.css"/>
    <link rel="stylesheet" href="../lib/font-awesome/css/font-awesome.min.css"/>


    <!--Installation using bower. Preferred!!! -->
    <!--<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"/>-->
    <!--<link rel="stylesheet" href="bower_components/jquery-ui/themes/ui-lightness/jquery-ui.min.css"/>-->
    <!--Run `bower install font-awesome` and uncomment this line to see font awesome examples-->
    <!--<link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.min.css"/>-->

    <link rel="stylesheet" href="../css/lobipanel.css"/>

    <link rel="stylesheet" href="../lib/highlight/github.css"/>
    <link rel="stylesheet" href="../demo/documentation.css"/>
    <link rel="stylesheet" href="../demo/demo.css"/>
</head>
<body>

<div style="padding: 25px;">
    <div class="row lobipanel-parent-stateful">
        <div class="col-sm-6" data-inner-id="lobipanel-parent-stateful1">
            <div class="panel panel-primary" data-sortable="true" data-inner-id="lobipanel-primary">
                <div class="panel-heading">
                    <div class="panel-title">
                        <h4>Panel title</h4>
                    </div>
                </div>
                <div class="panel-body">
                    <div class="embed-responsive embed-responsive-4by3">
                        <iframe class="embed-responsive-item" src="https://transform-service.inpriva.net/app/"></iframe>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<!--Default installation-->
<script src="../bower_components/jquery/dist/jquery.js"></script>
<script src="../bower_components/jquery-ui/jquery-ui.js"></script>
<script src="../bower_components/jquery-ui-touch-punch-improved/jquery.ui.touch-punch-improved.js"></script>
<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>

<!--Installation using bower. Preferred!!! -->
<!--<script src="bower_components/jquery/dist/jquery.min.js"></script>-->
<!--<script src="bower_components/jquery-ui/jquery-ui.min.js"></script>-->
<!--<script src="bower_components/jquery-ui-touch-punch-improved/jquery.ui.touch-punch-improved.js"></script>-->
<!--<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>-->

<script src="../js/lobipanel.js"></script>

<script>
    $(function () {
        $('.lobipanel-parent-stateful .panel').lobiPanel({
            stateful: true
        });
    });
</script>

</body>
</html>

================================================
FILE: demo/stateful.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Lobipanel - jQuery plugin for bootstrap panels. It extends panels with several common and useful
        functions.</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!--Default installation-->
    <link rel="stylesheet" href="../bower_components/jquery-ui/themes/ui-lightness/jquery-ui.min.css"/>
    <link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.css"/>
    <link rel="stylesheet" href="../lib/font-awesome/css/font-awesome.min.css"/>


    <!--Installation using bower. Preferred!!! -->
    <!--<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"/>-->
    <!--<link rel="stylesheet" href="bower_components/jquery-ui/themes/ui-lightness/jquery-ui.min.css"/>-->
    <!--Run `bower install font-awesome` and uncomment this line to see font awesome examples-->
    <!--<link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.min.css"/>-->

    <link rel="stylesheet" href="../css/lobipanel.css"/>

    <link rel="stylesheet" href="../lib/highlight/github.css"/>
    <link rel="stylesheet" href="../demo/documentation.css"/>
    <link rel="stylesheet" href="../demo/demo.css"/>
</head>
<body>

<div style="padding: 25px;">
    <div class="row lobipanel-parent-stateful">
        <div class="col-sm-6" data-inner-id="lobipanel-parent-stateful1">
            <div class="panel panel-primary" data-sortable="true" data-inner-id="lobipanel-primary">
                <div class="panel-heading">
                    <div class="panel-title">
                        <h4>Panel title</h4>
                    </div>
                </div>
                <div class="panel-body">
                    Panel 2
                </div>
            </div>
            <div class="panel panel-default" data-sortable="true" data-inner-id="lobipanel-default">
                <div class="panel-heading">
                    <div class="panel-title">
                        <h4>Panel title</h4>
                    </div>
                </div>
                <div class="panel-body">
                    Panel 3
                </div>
            </div>
        </div>
        <div class="col-sm-6 lobipanel-parent-sortable" data-inner-id="lobipanel-parent-stateful2">
            <div class="panel panel-success" data-sortable="true" data-inner-id="lobipanel-success">
                <div class="panel-heading">
                    <div class="panel-title">
                        <h4>Panel title</h4>
                    </div>
                </div>
                <div class="panel-body">
                    <!-- Single button -->
                    <div class="btn-group">
                        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
                                aria-haspopup="true" aria-expanded="false">
                            Action <span class="caret"></span>
                        </button>
                        <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                        </ul>
                    </div>
                </div>
            </div>
            <div class="panel panel-danger" data-sortable="true" data-inner-id="lobipanel-danger">
                <div class="panel-heading">
                    <div class="panel-title">
                        <h4>Panel title</h4>
                    </div>
                </div>
                <div class="panel-body">
                    Panel 5
                </div>
            </div>
        </div>
    </div>
    <div class="row lobipanel-parent-stateful">

        <div class="col-sm-6 lobipanel-parent-sortable" data-inner-id="lobipanel-parent-stateful3">
        </div>
        <div class="col-sm-6 lobipanel-parent-sortable" data-inner-id="lobipanel-parent-stateful4">
        </div>
    </div>
</div>

<!--Default installation-->
<script src="../bower_components/jquery/dist/jquery.js"></script>
<script src="../bower_components/jquery-ui/jquery-ui.js"></script>
<script src="../bower_components/jquery-ui-touch-punch-improved/jquery.ui.touch-punch-improved.js"></script>
<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>

<!--Installation using bower. Preferred!!! -->
<!--<script src="bower_components/jquery/dist/jquery.min.js"></script>-->
<!--<script src="bower_components/jquery-ui/jquery-ui.min.js"></script>-->
<!--<script src="bower_components/jquery-ui-touch-punch-improved/jquery.ui.touch-punch-improved.js"></script>-->
<!--<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>-->

<script src="../js/lobipanel.js"></script>

<script>
    $(function () {
        $('.lobipanel-parent-stateful .panel').lobiPanel({
            stateful: true
        });
    });
</script>

</body>
</html>

================================================
FILE: dist/css/lobipanel.css
================================================
.spinner-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.5);
}
.spinner-windows8 {
  position: relative;
  display: block;
  margin: 0 auto;
  width: 50px;
  height: 50px;
  margin-top: 100px;
}
.spinner-windows8 .wBall {
  position: absolute;
  width: 48px;
  height: 48px;
  opacity: 0;
  -moz-transform: rotate(225deg);
  -moz-animation: orbit 2.75s infinite;
  -webkit-transform: rotate(225deg);
  -webkit-animation: orbit 2.75s infinite;
  -ms-transform: rotate(225deg);
  -ms-animation: orbit 2.75s infinite;
  -o-transform: rotate(225deg);
  -o-animation: orbit 2.75s infinite;
  transform: rotate(225deg);
  animation: orbit 2.75s infinite;
}
.spinner-windows8 .wBall .wInnerBall {
  position: absolute;
  width: 6px;
  height: 6px;
  background: #000000;
  left: 0px;
  top: 0px;
  -moz-border-radius: 6px;
  -webkit-border-radius: 6px;
  -ms-border-radius: 6px;
  -o-border-radius: 6px;
  border-radius: 6px;
  z-index: 2;
}
.spinner-windows8 .wBall:first-child {
  -moz-animation-delay: 0.6s;
  -webkit-animation-delay: 0.6s;
  -ms-animation-delay: 0.6s;
  -o-animation-delay: 0.6s;
  animation-delay: 0.6s;
}
.spinner-windows8 .wBall:nth-child(2) {
  -moz-animation-delay: 0.12s;
  -webkit-animation-delay: 0.12s;
  -ms-animation-delay: 0.12s;
  -o-animation-delay: 0.12s;
  animation-delay: 0.12s;
}
.spinner-windows8 .wBall:nth-child(3) {
  -moz-animation-delay: 0.24s;
  -webkit-animation-delay: 0.24s;
  -ms-animation-delay: 0.24s;
  -o-animation-delay: 0.24s;
  animation-delay: 0.24s;
}
.spinner-windows8 .wBall:nth-child(4) {
  -moz-animation-delay: 0.36s;
  -webkit-animation-delay: 0.36s;
  -ms-animation-delay: 0.36s;
  -o-animation-delay: 0.36s;
  animation-delay: 0.36s;
}
.spinner-windows8 .wBall:nth-child(5) {
  -moz-animation-delay: 0.48s;
  -webkit-animation-delay: 0.48s;
  -ms-animation-delay: 0.48s;
  -o-animation-delay: 0.48s;
  animation-delay: 0.48s;
}
@-moz-keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    -moz-transform: rotate(180deg);
    -moz-animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    -moz-transform: rotate(300deg);
    -moz-animation-timing-function: linear;
    -moz-origin: 0%;
  }
  30% {
    opacity: 1;
    -moz-transform: rotate(410deg);
    -moz-animation-timing-function: ease-in-out;
    -moz-origin: 7%;
  }
  39% {
    opacity: 1;
    -moz-transform: rotate(645deg);
    -moz-animation-timing-function: linear;
    -moz-origin: 30%;
  }
  70% {
    opacity: 1;
    -moz-transform: rotate(770deg);
    -moz-animation-timing-function: ease-out;
    -moz-origin: 39%;
  }
  75% {
    opacity: 1;
    -moz-transform: rotate(900deg);
    -moz-animation-timing-function: ease-out;
    -moz-origin: 70%;
  }
  76% {
    opacity: 0;
    -moz-transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    -moz-transform: rotate(900deg);
  }
}
@-webkit-keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    -webkit-transform: rotate(180deg);
    -webkit-animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    -webkit-transform: rotate(300deg);
    -webkit-animation-timing-function: linear;
    -webkit-origin: 0%;
  }
  30% {
    opacity: 1;
    -webkit-transform: rotate(410deg);
    -webkit-animation-timing-function: ease-in-out;
    -webkit-origin: 7%;
  }
  39% {
    opacity: 1;
    -webkit-transform: rotate(645deg);
    -webkit-animation-timing-function: linear;
    -webkit-origin: 30%;
  }
  70% {
    opacity: 1;
    -webkit-transform: rotate(770deg);
    -webkit-animation-timing-function: ease-out;
    -webkit-origin: 39%;
  }
  75% {
    opacity: 1;
    -webkit-transform: rotate(900deg);
    -webkit-animation-timing-function: ease-out;
    -webkit-origin: 70%;
  }
  76% {
    opacity: 0;
    -webkit-transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    -webkit-transform: rotate(900deg);
  }
}
@-ms-keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    -ms-transform: rotate(180deg);
    -ms-animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    -ms-transform: rotate(300deg);
    -ms-animation-timing-function: linear;
    -ms-origin: 0%;
  }
  30% {
    opacity: 1;
    -ms-transform: rotate(410deg);
    -ms-animation-timing-function: ease-in-out;
    -ms-origin: 7%;
  }
  39% {
    opacity: 1;
    -ms-transform: rotate(645deg);
    -ms-animation-timing-function: linear;
    -ms-origin: 30%;
  }
  70% {
    opacity: 1;
    -ms-transform: rotate(770deg);
    -ms-animation-timing-function: ease-out;
    -ms-origin: 39%;
  }
  75% {
    opacity: 1;
    -ms-transform: rotate(900deg);
    -ms-animation-timing-function: ease-out;
    -ms-origin: 70%;
  }
  76% {
    opacity: 0;
    -ms-transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    -ms-transform: rotate(900deg);
  }
}
@-o-keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    -o-transform: rotate(180deg);
    -o-animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    -o-transform: rotate(300deg);
    -o-animation-timing-function: linear;
    -o-origin: 0%;
  }
  30% {
    opacity: 1;
    -o-transform: rotate(410deg);
    -o-animation-timing-function: ease-in-out;
    -o-origin: 7%;
  }
  39% {
    opacity: 1;
    -o-transform: rotate(645deg);
    -o-animation-timing-function: linear;
    -o-origin: 30%;
  }
  70% {
    opacity: 1;
    -o-transform: rotate(770deg);
    -o-animation-timing-function: ease-out;
    -o-origin: 39%;
  }
  75% {
    opacity: 1;
    -o-transform: rotate(900deg);
    -o-animation-timing-function: ease-out;
    -o-origin: 70%;
  }
  76% {
    opacity: 0;
    -o-transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    -o-transform: rotate(900deg);
  }
}
@keyframes orbit {
  0% {
    opacity: 1;
    z-index: 99;
    transform: rotate(180deg);
    animation-timing-function: ease-out;
  }
  7% {
    opacity: 1;
    transform: rotate(300deg);
    animation-timing-function: linear;
    origin: 0%;
  }
  30% {
    opacity: 1;
    transform: rotate(410deg);
    animation-timing-function: ease-in-out;
    origin: 7%;
  }
  39% {
    opacity: 1;
    transform: rotate(645deg);
    animation-timing-function: linear;
    origin: 30%;
  }
  70% {
    opacity: 1;
    transform: rotate(770deg);
    animation-timing-function: ease-out;
    origin: 39%;
  }
  75% {
    opacity: 1;
    transform: rotate(900deg);
    animation-timing-function: ease-out;
    origin: 70%;
  }
  76% {
    opacity: 0;
    transform: rotate(900deg);
  }
  100% {
    opacity: 0;
    transform: rotate(900deg);
  }
}
.tooltip {
  z-index: 20000;
}
body.lobipanel-minimized {
  padding-bottom: 36px;
}
.lobipanel {
  position: relative;
  margin-bottom: 15px;
}
.lobipanel > .panel-heading {
  padding: 5px;
  position: relative;
  border-top-right-radius: 0px;
  border-top-left-radius: 0px;
}
.lobipanel > .panel-heading > .panel-title {
  float: left;
  max-width: calc(100% - 30px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 16px;
  line-height: 30px;
  padding-left: 15px;
}
.lobipanel > .panel-heading > .panel-title h1,
.lobipanel > .panel-heading > .panel-title h2,
.lobipanel > .panel-heading > .panel-title h3,
.lobipanel > .panel-heading > .panel-title h4,
.lobipanel > .panel-heading > .panel-title h5,
.lobipanel > .panel-heading > .panel-title h6 {
  margin: 0;
  line-height: 30px;
}
.lobipanel > .panel-heading > .panel-title input {
  color: inherit;
  line-height: 30px;
  border-radius: 2px;
  padding: 0 5px;
  width: 100%;
  background-color: rgba(0, 0, 0, 0.2);
  border: 1px solid transparent;
  outline: 0;
}
.lobipanel > .panel-heading > .panel-title input:focus {
  background-color: rgba(0, 0, 0, 0.15);
}
.lobipanel > .panel-heading .dropdown {
  display: inline-block;
  float: right;
  position: relative;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu {
  left: auto;
  right: 0;
  min-width: 0;
  margin-top: 0;
  border-radius: 0;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu > li > a .control-title {
  display: inline-block;
  margin-left: 15px;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item {
  position: relative;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list {
  position: absolute;
  background: #f5f5f5;
  box-shadow: 2px 2px 12px rgba(0, 0, 0, 0.3);
  padding: 4px;
  display: none;
  width: 92px;
  top: 100%;
  right: 0;
  z-index: 2;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list .style-item {
  cursor: pointer;
  display: inline-block;
  width: 24px;
  height: 24px;
  margin: 2px;
  border: 2px solid #f5f5f5;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list .style-item:hover {
  border-color: #FFF;
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list .style-item:active {
  box-shadow: inset 2px 2px 10px rgba(0, 0, 0, 0.3);
}
.lobipanel > .panel-heading .dropdown .dropdown-menu .style-change-item .style-list.opened {
  display: block;
}
.lobipanel > .panel-heading .dropdown .dropdown-toggle {
  border: none;
  outline: 0;
  background-color: transparent;
  text-align: center;
  padding: 0;
  width: 30px;
  font-size: 14px;
  -webkit-transition: all 0.2s;
  -o-transition: all 0.2s;
  transition: all 0.2s;
}
.lobipanel > .panel-heading .dropdown .dropdown-toggle .panel-control-icon {
  top: 0;
  line-height: 30px;
}
.lobipanel > .panel-heading .dropdown .dropdown-toggle:hover,
.lobipanel > .panel-heading .dropdown .dropdown-toggle:hover:focus {
  text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6);
  background-color: rgba(0, 0, 0, 0.15);
}
.lobipanel > .panel-heading .dropdown.open .dropdown-toggle {
  text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6);
  background-color: rgba(0, 0, 0, 0.15);
}
.lobipanel > .panel-heading:before,
.lobipanel > .panel-heading:after {
  content: " ";
  display: table;
}
.lobipanel > .panel-heading:after {
  clear: both;
}
@media screen and (min-width: 768px) {
  .lobipanel .panel-heading .panel-title {
    max-width: calc(100% - 180px);
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu {
    position: static;
    display: inline-block;
    border: none;
    padding: 0;
    margin: 0;
    min-width: 0;
    width: auto;
    -webkit-box-shadow: none;
    box-shadow: none;
    background: transparent;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li {
    display: inline-block;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a {
    cursor: pointer;
    color: inherit;
    padding: 0;
    outline: 0;
    text-align: center;
    width: 30px;
    font-size: 14px;
    -webkit-transition: all 0.2s;
    -o-transition: all 0.2s;
    transition: all 0.2s;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a .panel-control-icon {
    top: 0;
    line-height: 30px;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a .control-title {
    display: none;
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a:hover,
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a:focus:hover {
    text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6);
    background-color: rgba(0, 0, 0, 0.15);
  }
  .lobipanel .panel-heading .dropdown .dropdown-menu > li > a:focus {
    text-shadow: none;
    background-color: transparent;
  }
  .lobipanel .panel-heading .dropdown .dropdown-toggle {
    display: none;
  }
}
.lobipanel > .panel-body {
  overflow: auto;
  position: relative;
}
.lobipanel .panel-loader {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #fff;
  opacity: 0.8;
}
.lobipanel.panel-collapsed > .panel-heading {
  border-bottom: none;
}
.lobipanel.panel-collapsed > .panel-heading .dropdown .dropdown-menu > li > a[data-func="unpin"],
.lobipanel.panel-collapsed > .panel-heading .dropdown .dropdown-menu > li > a[data-func="reload"],
.lobipanel.panel-collapsed > .panel-heading .dropdown .dropdown-menu > li > a[data-func="expand"] {
  display: none;
}
.lobipanel.panel-expanded,
.lobipanel.panel-unpin,
.lobipanel.panel-minimized.panel-unpin {
  margin-bottom: 0;
}
.lobipanel.panel-unpin {
  overflow: hidden;
  position: absolute;
  z-index: 10000;
  -webkit-box-shadow: 2px 2px 15px 5px rgba(10, 10, 10, 0.5);
  box-shadow: 2px 2px 15px 5px rgba(10, 10, 10, 0.5);
}
.lobipanel.panel-unpin > .panel-heading {
  cursor: move;
}
.lobipanel.panel-unpin.panel-minimized {
  float: left;
  position: static;
  border-radius: 0;
  -webkit-box-shadow: none;
  box-shadow: none;
  min-width: 170px;
  margin-right: 5px;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading {
  padding: 0;
  cursor: pointer;
  border-bottom: none;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title {
  max-width: calc(100% - 60px);
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h1,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h2,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h3,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h4,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h5,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .panel-title h6 {
  overflow: hidden;
  text-overflow: ellipsis;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu {
  position: static;
  display: inline-block;
  border: none;
  padding: 0;
  margin: 0;
  min-width: 0;
  width: auto;
  -webkit-box-shadow: none;
  box-shadow: none;
  background: transparent;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li {
  display: inline-block;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a {
  cursor: pointer;
  color: inherit;
  padding: 0;
  outline: 0;
  text-align: center;
  width: 30px;
  font-size: 14px;
  -webkit-transition: all 0.2s;
  -o-transition: all 0.2s;
  transition: all 0.2s;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a .panel-control-icon {
  top: 0;
  line-height: 30px;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a .control-title {
  display: none;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a:hover,
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a:focus:hover {
  text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6);
  background-color: rgba(0, 0, 0, 0.15);
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a:focus {
  text-shadow: none;
  background-color: transparent;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-toggle {
  display: none;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a {
  display: none;
}
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a[data-func="close"],
.lobipanel.panel-unpin.panel-minimized > .panel-heading .dropdown .dropdown-menu > li > a[data-func="expand"] {
  display: inline-block;
}
.lobipanel.panel-unpin.panel-minimized > .panel-body,
.lobipanel.panel-unpin.panel-minimized > .panel-footer {
  display: none !important;
}
.lobipanel.panel-expanded > .panel-heading {
  cursor: default;
}
.lobipanel.panel-expanded > .panel-heading .dropdown .dropdown-menu > li > a[data-func="unpin"],
.lobipanel.panel-expanded > .panel-heading .dropdown .dropdown-menu > li > a[data-func="minimize"] {
  display: none;
}
.lobipanel.panel-expanded.panel-unpin > .panel-heading .panel-control[data-func="minimize"] {
  display: block;
}
.lobipanel-minimized-toolbar {
  position: fixed;
  height: 36px;
  padding: 2px;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 20000;
  background: rgba(34, 115, 182, 0.51);
}
.lobipanel-placeholder {
  background-color: #f9f5d1;
  border: 1px dashed #919191;
  margin-bottom: 15px;
}
.lobipanel-parent-sortable {
  min-height: 20px;
}


================================================
FILE: dist/js/lobipanel.js
================================================
//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');

    if (!i || isNaN(i)) {
        i = $object.children().length - 1;
    }
    this.attr('data-index', i);

    var $el = $object.children().eq(i - 1);
    if ($el.length) {
        $el.after(this);
    } else {
        $object.append(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 StorageLocal = function () {
        this.saveChildPositions = function (parentInnerId, positions) {
            if (positions !== undefined) {
                localStorage.setItem(STORAGE_PREFIX + 'parent_' + parentInnerId, JSON.stringify(positions));
            }
        };

        this.savePanelParams = function (innerId, storage) {
            localStorage.setItem(STORAGE_PREFIX + innerId, JSON.stringify(storage));
        };

        this.getAllPanelPositions = function () {
            var parents = [];
            for (var i in localStorage) {
                if (i.indexOf(STORAGE_PREFIX + 'parent_') === 0) {
                    var innerParentId = i.replace(STORAGE_PREFIX + 'parent_', '');
                    var $parent = $('.lobipanel-parent-sortable[data-inner-id=' + innerParentId + ']');
                    if ($parent.length) {
                        parents[innerParentId] = JSON.parse(localStorage[i]);
                    }
                }
            }
            return parents;
        };

        this.getPanelStorage = function (innerId) {
            var item = localStorage.getItem(STORAGE_PREFIX + innerId);
            return JSON.parse(item || null) || {};
        };

    };

    var LobiPanel = function ($el, options) {
        var me = this;

        this.hasRandomId = false;
        this.storage = {};


        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);
        me._triggerEvent("init");
    };

    LobiPanel.prototype = {
        _processInput: function (options) {
            var me = this;
            if (!options) {
                options = {};
            }


            this.storageObject = options.storageObject || new StorageLocal();
            if (!me.hasRandomId) {
                me.storage = this.storageObject.getPanelStorage(me.innerId);
            }
            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);

            if (me.getParam('panelTitle')) {
                me.$heading.find('.panel-title').html(me.getParam('panelTitle'));
            }

            var style = me.getParam('panelStyle');
            if (style) {
                me.applyStyle(style.bg, style.text);
            }

            // me.savepanelPositions();
            // 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();

            //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');

            var toRemoveProperties = [
                'position',
                'z-index',
                'left',
                'top',
                'width',
                'height'
            ];

            for (var i in toRemoveProperties) {
                me.$el.css(toRemoveProperties[i], '');
            }

            me.$body.css({
                width: '',
                height: ''
            });
            me._setBodyHeight();
            me._insertInParent();
            me._enableSorting();
            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"]'));
                me._triggerEvent("onMaximize");
            } 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.$el.attr('data-index', me.$el.index());
            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();

            var toRemoveProperties = [
                'position',
                'z-index',
                'left',
                'top',
                'width',
                'height'
            ];

            //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')) {
                    for (var i in toRemoveProperties) {
                        me.$el.css(toRemoveProperties[i], '');
                    }
                    // 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.isPinned()) {
                    me._saveState('pinned');
                } 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 user 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.saveParam('panelTitle', input.val());
            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.changeStyle !== false) {
                menu.append(me._generateChangeStyle());
            }
            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"'+(me.$options.forAngularJs ? ' uib-dropdown' : '')+'></div>')
                .append('<ul class="dropdown-menu dropdown-menu-right"'+(me.$options.forAngularJs ? ' uib-dropdown-menu' : '')+'></ul>')
                .append('<div class="dropdown-toggle"'+(me.$options.forAngularJs ? ' uib-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);
        },
        _generateChangeStyle: function () {
            var me = this;
            var options = me.$options.changeStyle;
            var $control = $('<a data-func="changeStyle"></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);

            var $dropdown = $('<li class="style-change-item"></li>').append($control);

            var $menu = $('<div>', {
                'class': 'style-list'
            }).appendTo($dropdown);

            if (me.$options.styles) {
                for (var i = 0; i < me.$options.styles.length; i++) {
                    var style = me.$options.styles[i];
                    $menu.append('<div class="style-item style-primary" style="background-color: ' +
                        style.bg + '" data-bg="' + style.bg + '" data-text="' + style.text + '"></div>');
                }
            }
            $menu.find('.style-item').on('click', function () {
                var $item = $(this);
                me.saveParam('panelStyle', {
                    bg: $item.data('bg'),
                    text: $item.data('text')
                });
                me.applyStyle($item.data('bg'), $item.data('text'));
                $menu.removeClass('opened');
            });

            $control.on('click', function () {
                var $this = $(this);
                var $parent = $this.closest('.style-change-item');
                $parent.find('.style-list').toggleClass('opened');
            });

            return $dropdown;
        },

        applyStyle: function (color, text) {
            var me = this;
            me.$heading.css('background-color', color);
            me.$heading.css('border-color', color);
            me.$heading.css('color', text);
            me.$el.css('border-color', color);
        },

        _createDropdownForStyleChange: function () {
            var me = this;
            var $dropdown = $('<div>', {
                'class': 'dropdown'
            }).append(
                $('<button>', {
                    'type': 'button',
                    'data-toggle': 'dropdown',
                    'class': 'btn btn-default btn-xs',
                    'html': '<i class="glyphicon glyphicon-th"></i>'
                })
            );
            var $menu = $('<div>', {
                'class': 'dropdown-menu dropdown-menu-right'
            }).appendTo($dropdown);

            for (var i = 0; i < 0; i++) {
                var st = me.$globalOptions.listStyles[i];
                var st = 'primary';
                $('<div class="' + st + '"></div>')
                    .on('mousedown', function (ev) {
                        ev.stopPropagation()
                    })
                    .click(function () {
                        var classes = me.$el[0].className.split(' ');
                        var oldClass = null;
                        for (var i = 0; i < classes.length; i++) {
                            if (me.$globalOptions.listStyles.indexOf(classes[i]) > -1) {
                                oldClass = classes[i];
                            }
                        }
                        me.$el.removeClass(me.$globalOptions.listStyles.join(" "))
                            .addClass(this.className);

                        me._triggerEvent('styleChange', [me, oldClass, this.className]);

                    })
                    .appendTo($menu);
            }

            return $dropdown;
        },
        _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) {
                    me.savepanelPositions();
                    var $panel = ui.item;

                    var innerId = $panel.data('inner-id');
                    me._removeInnerIdFromParent(innerId);
                    me._appendInnerIdToParent(ui.item.parent(), innerId);
                    me._triggerEvent('dragged');
                }
            });
        },

        savepanelPositions: function () {
            var me = this;
            var $parents = $('.lobipanel-parent-sortable');
            $parents.each(function (index, parent) {
                var $parent = $(parent);

                var parentInnerId = $parent.data('inner-id');
                if (!parentInnerId) {
                    console.error("Panel does not have parent id ", $parent);
                    return;
                }
                var $childPanels = $parent.find('.lobipanel');
                var positions = {};
                $childPanels.each(function (index, el) {
                    var $el = $(el);
                    positions[$el.data('inner-id')] = index;
                });
                me.storageObject.saveChildPositions(parentInnerId, positions);
            });
        },

        _disableSorting: function () {
            var me = this;
            var parent = me.$el.parent();
            if (parent.hasClass('ui-sortable')) {
                parent.sortable("destroy");
            }
        },
        _removeInnerIdFromParent: function (innerId) {
            var me = this;
            var parent = $('[' + LobiPanel.PRIVATE_OPTIONS.parentAttr + '~=' + innerId + ']');
            if (parent.length) {
                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);
            }
        },
        getParam: function (key, value) {
            var me = this;
            // console.log("Save state ", state, params);
            return me.storage[key];
        },
        saveParam: function (key, value) {
            var me = this;
            // console.log("Save state ", state, params);
            me.storage[key] = value;

            me._saveLocalStorage(me.storage);
        },
        _saveLocalStorage: function (storage) {
            var me = this;
            me.storageObject.savePanelParams(me.innerId, storage);
        },
        _applyState: function (state, params) {
            var me = this;
            switch (state) {
                case 'pinned':
                    if (!me.hasRandomId) {
                        var allPanelPositions = me.storageObject.getAllPanelPositions();
                        // console.log(allPanelPositions);
                        for (var i in allPanelPositions) {
                            var panelPositions = allPanelPositions[i];
                            var innerParentId = i;
                            var $parent = $('.lobipanel-parent-sortable[data-inner-id=' + innerParentId + ']');
                            for (var j in panelPositions) {
                                var $panel = $('[data-inner-id=' + j + ']');
                                me._removeInnerIdFromParent($panel.data('inner-id'));
                                me._appendInnerIdToParent($parent, $panel.data('inner-id'));
                                if (!$panel.hasClass('panel-unpin') && !$panel.hasClass('panel-expanded')) {
                                    $panel.insertAt(panelPositions[j], $parent);
                                }
                            }
                        }
                    }
                    // 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;
    };
    $.fn.lobiPanelParent = function (option) {
        this.each(function (index, parent) {
            var $parent = $(parent);
            if (!$parent.hasClass('ui-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) {
                        console.log(ui);
                        // me.savepanelPositions();
                        //
                        // // me._removeInnerIdFromParent(innerId);
                        // // me._appendInnerIdToParent(ui.item.parent(), innerId);
                        // me._triggerEvent('dragged');
                    }
                });
            }
        });
        return this;
    };
    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,
        forAngularJs: false,
        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 user 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 user 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
        },
        changeStyle: {
            icon: 'glyphicon glyphicon-th', //icon is shown when panel is not on full screen
            tooltip: 'Style'       //tooltip text, If you want to disable tooltip, set it to false
        },
        close: {
            icon: 'glyphicon glyphicon-remove', //You can user 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'
        },
        styles: [
            {
                bg: '#d9534f',
                text: '#FFF'
            },
            {
                bg: '#f0ad4e',
                text: '#FFF'
            },
            {
                bg: '#337ab7',
                text: '#FFF'
            },
            {
                bg: '#5bc0de',
                text: '#FFF'
            },
            {
                bg: '#4753e4',
                text: '#FFF'
            },
            {
                bg: '#9e4aea',
                text: '#FFF'
            }
        ],
        storageObject: null,

        // 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();

    var $parent = $('.lobipanel-parent-sortable');
    $parent.lobiPanelParent();
});



================================================
FILE: gulpfile.js
================================================
/**
 * Created by zura on 12/10/2017.
 */

'use strict';

var pjson = require('./package.json');

var less = require('gulp-less');
var path = require('path');
var gulp = require('gulp');
var copy = require('gulp-copy');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var cleanCSS = require('gulp-clean-css');
// var pump = require('pump');


gulp.task('less', function () {
  return gulp.src('./less/lobipanel.less')
    .pipe(less({
      paths: [path.join(__dirname, 'less', 'includes')]
    }))
    .pipe(gulp.dest('./css'));
});

gulp.task('copy', function () {
  gulp.src('./js/**/*.js')
    .pipe(gulp.dest('./dist/js'));
  gulp.src('./css/**/*.css')
    .pipe(gulp.dest('./dist/css'));

});

gulp.task('cssmin', function () {
  return gulp.src('./css/lobipanel.css')
    .pipe(cleanCSS({compatibility: 'ie8'}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest('./dist/css'));
});

gulp.task('scripts', function () {
  gulp.src([
    './js/lobipanel.js'
  ])

    .pipe(gulp.dest('./dist/js'))
    .pipe(uglify())
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest('./dist/js'))
});

gulp.task('watch', function () {
  gulp.watch('./less/**/*.less', ['less', 'cssmin', 'copy']);
  gulp.watch('./js/**/*.js', ['scripts', 'copy']);
});

gulp.task('default', ['less', 'copy', 'cssmin', 'scripts'], function () {
  gulp.start('watch');
});

================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Lobipanel - jQuery plugin for bootstrap panels. It extends panels with several common and useful functions.</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!--Default installation-->
    <link rel="stylesheet" href="lib/jquery-ui.min.css"/>
    <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
    <link rel="stylesheet" href="lib/font-awesome/css/font-awesome.min.css"/>


    <!--Installation using bower. Preferred!!! -->
    <!--<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"/>-->
    <!--<link rel="stylesheet" href="bower_components/jquery-ui/themes/ui-lightness/jquery-ui.min.css"/>-->
    <!--Run `bower install font-awesome` and uncomment this line to see font awesome examples-->
    <!--<link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.min.css"/>-->

    <link rel="stylesheet" href="css/lobipanel.css"/>

    <link rel="stylesheet" href="lib/highlight/github.css"/>
    <link rel="stylesheet" href="demo/documentation.css"/>
    <link rel="stylesheet" href="demo/demo.css"/>
</head>
<body>
    <div id="lobipanel">
        <div class="container">
            <p></p>
            <div class="alert alert-info">
                <p>For documentation visit <a href="http://lobianijs.com/site/lobipanel">Lobipanel webpage</a></p>
            </div>
            <!--Examples-->
            <div id="lobipanel-examples">
                <!--Basic example-->
                <div>
                    <h3>Basic example</h3>
                    <div class="bs-example">
                        <div id="lobipanel-basic" class="panel panel-default">
                            <div class="panel-heading">
                                <div class="panel-title">
                                    Panel title
                                </div>
                            </div>
                            <div class="panel-body">
                                Lorem ipsum dolor sit amet concealed leaf shah proper council binary. Concealed assured affairs faces, finish easily glows shouted faint. Sentence islands spouting we unbeguiled, faces concealed. Diam rays countries, faces fames peeling bind wary catch solomon, painting, they beats evil. Failing newer landscapes steal retinues vidi rays echoes sheltered evil. Veins concealed spouting obtaining delight wild. Venenatis failing wreaths shouted countries wild, privilege climbing.
                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>$('selector').lobiPanel();
</code></pre>
                    </div>
                </div>
                <!--Custom controls-->
                <div>
                    <h3>Disable control buttons</h3>
                    <div class="bs-example">
                        <div id="lobipanel-custom-control" class="panel panel-default">
                            <div class="panel-heading">
                                <div class="panel-title">
                                    Panel title
                                </div>
                            </div>
                            <div class="panel-body">
                                Lorem ipsum dolor sit amet concealed leaf shah proper council binary. Concealed assured affairs faces, finish easily glows shouted faint. Sentence islands spouting we unbeguiled, faces concealed. Diam rays countries, faces fames peeling bind wary catch solomon, painting, they beats evil. Failing newer landscapes steal retinues vidi rays echoes sheltered evil. Veins concealed spouting obtaining delight wild. Venenatis failing wreaths shouted countries wild, privilege climbing.
                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>$('selector').lobiPanel({
    reload: false,
    close: false,
    editTitle: false
});
</code></pre>
                    </div>
                </div>
                <!-- Stateful -->
                <div>
                    <h3>Stateful. <small>Saves its state in localStorage</small></h3>
                    <div class="bs-example">
                        <div id="lobipanel-stateful" class="panel panel-default" data-inner-id="lobipanel-stateful">
                            <div class="panel-heading">
                                <div class="panel-title">
                                    Panel title
                                </div>
                            </div>
                            <div class="panel-body">
                                Lorem ipsum dolor sit amet concealed leaf shah proper council binary. Concealed assured affairs faces, finish easily glows shouted faint. Sentence islands spouting we unbeguiled, faces concealed. Diam rays countries, faces fames peeling bind wary catch solomon, painting, they beats evil. Failing newer landscapes steal retinues vidi rays echoes sheltered evil. Veins concealed spouting obtaining delight wild. Venenatis failing wreaths shouted countries wild, privilege climbing.
                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>$('selector').lobiPanel({
    stateful: true
});
</code></pre>
                    </div>
                </div>
                <!--Font awesome controls-->
                <div>
                    <h3>Use font awesome icons</h3>
                    <div class="bs-example">
                        <div id="lobipanel-font-awesome" class="panel panel-info">
                            <div class="panel-heading">
                                <div class="panel-title">
                                    Panel title
                                </div>
                            </div>
                            <div class="panel-body">
                                Lorem ipsum dolor sit amet concealed leaf shah proper council binary. Concealed assured affairs faces, finish easily glows shouted faint. Sentence islands spouting we unbeguiled, faces concealed. Diam rays countries, faces fames peeling bind wary catch solomon, painting, they beats evil. Failing newer landscapes steal retinues vidi rays echoes sheltered evil. Veins concealed spouting obtaining delight wild. Venenatis failing wreaths shouted countries wild, privilege climbing.
                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>$('selector').lobiPanel({
    reload: {
        icon: 'fa fa-refresh'
    },
    editTitle: {
        icon: 'fa fa-edit',
        icon2: 'fa fa-save'
    },
    unpin: {
        icon: 'fa fa-arrows'
    },
    minimize: {
        icon: 'fa fa-chevron-up',
        icon2: 'fa fa-chevron-down'
    },
    close: {
        icon: 'fa fa-times-circle'
    },
    expand: {
        icon: 'fa fa-expand',
        icon2: 'fa fa-compress'
    }
});
</code></pre>
                    </div>
                </div>
                <!--Constrain panel size-->
                <div>
                    <h3>Constrain panel size</h3>
                    <p>Unpin the panel and try to resize it.</p>
                    <div class="bs-example">
                        <div id="lobipanel-constrain-size" class="panel panel-primary">
                            <div class="panel-heading">
                                <div class="panel-title">
                                    Panel title
                                </div>
                            </div>
                            <div class="panel-body">
                                Lorem ipsum dolor sit amet concealed leaf shah proper council binary. Concealed assured affairs faces, finish easily glows shouted faint. Sentence islands spouting we unbeguiled, faces concealed. Diam rays countries, faces fames peeling bind wary catch solomon, painting, they beats evil. Failing newer landscapes steal retinues vidi rays echoes sheltered evil. Veins concealed spouting obtaining delight wild. Venenatis failing wreaths shouted countries wild, privilege climbing.
                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>$('selector').lobiPanel({
    minWidth: 300,
    minHeight: 300,
    maxWidth: 600,
    maxHeight: 480
});
</code></pre>
                    </div>
                </div>
                <!--Load content from ajax-->
                <div>
                    <h3>Load content from url</h3>
                    <p>Load content from specified url and apply highlight code</p>
                    <div class="bs-example">
                        <div id="lobipanel-from-url" class="panel panel-success" data-autoload="false">
                            <div class="panel-heading">
                                <div class="panel-title">
                                    <h4>Content from url</h4>
                                </div>
                            </div>
                            <div class="panel-body" style="height: 400px; overflow: auto;">

                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>$('selector').on('loaded.lobiPanel', function(ev, lobiPanel){
    var $body = lobiPanel.$el.find('.panel-body');
    $body.html('&lt;div class="highlight">&ltpre>&lt;code>' + $body.html() + '&lt;/code>&lt;/pre>&lt;/div>');
    hljs.highlightBlock($body.find('code')[0]);
});
$('selector').lobiPanel({
    loadUrl: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.css',
    bodyHeight: 400
});
</code></pre>
                    </div>
                </div>
                <!--Multiple lobiPanels-->
                <div id="lobipanel-multiple">
                    <h3>Multiple panels with drag & drop</h3>
                    <p>Drag panels by clicking on the headers</p>
                    <div class="bs-example">
                        <div class="row">
                            <div id="lobipanel-parent" class="col-md-6 lobipanel-parent">
                                <div class="panel panel-default" data-stateful="true" data-inner-id="lobipanel-parent-default">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>Default title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        <div class="media">
                                            <div class="media-left">
                                                <a href="#">
                                                    <img class="media-object" data-src="holder.js/64x64" alt="64x64" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" data-holder-rendered="true" style="width: 64px; height: 64px;">
                                                </a>
                                            </div>
                                            <div class="media-body">
                                                <h4 class="media-heading">Media heading</h4>
                                                Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="panel panel-primary" data-stateful="true"  data-inner-id="lobipanel-parent-primary">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>primary title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        <div class="media">
                                            <div class="media-left">
                                                <a href="#">
                                                    <img class="media-object" data-src="holder.js/64x64" alt="64x64" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" data-holder-rendered="true" style="width: 64px; height: 64px;">
                                                </a>
                                            </div>
                                            <div class="media-body">
                                                <h4 class="media-heading">Media heading</h4>
                                                Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="panel panel-info" data-stateful="true"  data-inner-id="lobipanel-parent-info">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>Info title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        <div class="media">
                                            <div class="media-left">
                                                <a href="#">
                                                    <img class="media-object" data-src="holder.js/64x64" alt="64x64" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" data-holder-rendered="true" style="width: 64px; height: 64px;">
                                                </a>
                                            </div>
                                            <div class="media-body">
                                                <h4 class="media-heading">Media heading</h4>
                                                Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="panel panel-success" data-stateful="true" data-inner-id="lobipanel-parent-success">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>Success title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        <div class="media">
                                            <div class="media-left">
                                                <a href="#">
                                                    <img class="media-object" data-src="holder.js/64x64" alt="64x64" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" data-holder-rendered="true" style="width: 64px; height: 64px;">
                                                </a>
                                            </div>
                                            <div class="media-body">
                                                <h4 class="media-heading">Media heading</h4>
                                                Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="panel panel-warning" data-stateful="true" data-inner-id="lobipanel-parent-warning">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>Warning title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        <div class="media">
                                            <div class="media-left">
                                                <a href="#">
                                                    <img class="media-object" data-src="holder.js/64x64" alt="64x64" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" data-holder-rendered="true" style="width: 64px; height: 64px;">
                                                </a>
                                            </div>
                                            <div class="media-body">
                                                <h4 class="media-heading">Media heading</h4>
                                                Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="panel panel-danger" data-stateful="true" data-inner-id="lobipanel-parent-danger">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>Danger title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        <div class="media">
                                            <div class="media-left">
                                                <a href="#">
                                                    <img class="media-object" data-src="holder.js/64x64" alt="64x64" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjE0LjUiIHk9IjMyIiBzdHlsZT0iZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQ7ZG9taW5hbnQtYmFzZWxpbmU6Y2VudHJhbCI+NjR4NjQ8L3RleHQ+PC9nPjwvc3ZnPg==" data-holder-rendered="true" style="width: 64px; height: 64px;">
                                                </a>
                                            </div>
                                            <div class="media-body">
                                                <h4 class="media-heading">Media heading</h4>
                                                Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="col-md-6">
                                <div class="panel panel-success">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>Panel title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        <table class="table table-striped">
                                            <thead>
                                                <tr>
                                                    <th>#</th>
                                                    <th>First Name</th>
                                                    <th>Last Name</th>
                                                    <th>Username</th>
                                                </tr>
                                            </thead>
                                            <tbody>
                                                <tr>
                                                    <th scope="row">1</th>
                                                    <td>Mark</td>
                                                    <td>Otto</td>
                                                    <td>@mdo</td>
                                                </tr>
                                                <tr>
                                                    <th scope="row">2</th>
                                                    <td>Jacob</td>
                                                    <td>Thornton</td>
                                                    <td>@fat</td>
                                                </tr>
                                                <tr>
                                                    <th scope="row">3</th>
                                                    <td>Larry</td>
                                                    <td>the Bird</td>
                                                    <td>@twitter</td>
                                                </tr>
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                                <div class="panel panel-info">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>Panel title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        <table class="table table-striped">
                                            <thead>
                                                <tr>
                                                    <th>#</th>
                                                    <th>First Name</th>
                                                    <th>Last Name</th>
                                                    <th>Username</th>
                                                </tr>
                                            </thead>
                                            <tbody>
                                                <tr>
                                                    <th scope="row">1</th>
                                                    <td>Mark</td>
                                                    <td>Otto</td>
                                                    <td>@mdo</td>
                                                </tr>
                                                <tr>
                                                    <th scope="row">2</th>
                                                    <td>Jacob</td>
                                                    <td>Thornton</td>
                                                    <td>@fat</td>
                                                </tr>
                                                <tr>
                                                    <th scope="row">3</th>
                                                    <td>Larry</td>
                                                    <td>the Bird</td>
                                                    <td>@twitter</td>
                                                </tr>
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>$('.panel').lobiPanel({
    sortable: true
});
</code></pre>
                    </div>
                </div>
                <!--Initialize with data attributes-->
                <div>
                    <h3>Initialize with <code>data-*</code> attributes</h3>
                    <div class="bs-example">
                        <div class="panel panel-default lobipanel" data-stateful="true" data-inner-id="lobipanel-data-attributes" data-body-height="300" data-tooltips="false"
                             data-min-width="400" data-resize="horizontal" data-close="{tooltip: 'custom'}">
                            <div class="panel-heading">
                                <div class="panel-title">
                                    This is panel title
                                </div>
                            </div>
                            <div class="panel-body">
                                <table class="table table-striped">
                                    <thead>
                                        <tr>
                                            <th>#</th>
                                            <th>First Name</th>
                                            <th>Last Name</th>
                                            <th>Username</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr>
                                            <th scope="row">1</th>
                                            <td>Mark</td>
                                            <td>Otto</td>
                                            <td>@mdo</td>
                                        </tr>
                                        <tr>
                                            <th scope="row">2</th>
                                            <td>Jacob</td>
                                            <td>Thornton</td>
                                            <td>@fat</td>
                                        </tr>
                                        <tr>
                                            <th scope="row">3</th>
                                            <td>Larry</td>
                                            <td>the Bird</td>
                                            <td>@twitter</td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>&lt;div class=&quot;panel panel-default lobipanel&quot; data-inner-id=&quot;lobipanel-data-attributes&quot; data-body-height=&quot;300&quot; data-tooltips=&quot;false&quot; data-min-width=&quot;400&quot; data-resize=&quot;horizontal&quot; data-close=&quot;{tooltip: &apos;custom&apos;}&quot;&gt;
    &lt;div class=&quot;panel-heading&quot;&gt;
       &lt;div class=&quot;panel-title&quot;&gt;
           This is panel title
       &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;panel-body&quot;&gt;
        content
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>
                    </div>
                </div>
                <!--Nested LobiPanel-->
                <div id="lobipanel-nested-example">
                    <h4>Nested LobiPanel example</h4>
                    <div class="bs-example">
                        <div class="panel panel-info lobipanel">
                            <div class="panel-heading">
                                <div class="panel-title">
                                    <h4>LobiPanel title</h4>
                                </div>
                            </div>
                            <div class="panel-body">
                                <div class="panel panel-warning lobipanel">
                                    <div class="panel-heading">
                                        <div class="panel-title">
                                            <h4>Nested LobiPanel title</h4>
                                        </div>
                                    </div>
                                    <div class="panel-body">
                                        Panel 1
                                    </div>
                                </div>
                                <div class="row">
                                    <div class="col-lg-6">
                                        <div class="panel panel-default lobipanel" data-sortable="true">
                                            <div class="panel-heading">
                                                <div class="panel-title">
                                                    <h4>Panel title</h4>
                                                </div>
                                            </div>
                                            <div class="panel-body">
                                                Panel 2
                                            </div>
                                        </div>
                                        <div class="panel panel-default lobipanel" data-sortable="true">
                                            <div class="panel-heading">
                                                <div class="panel-title">
                                                    <h4>Panel title</h4>
                                                </div>
                                            </div>
                                            <div class="panel-body">
                                                Panel 3
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-lg-6">
                                        <div class="panel panel-default lobipanel" data-sortable="true">
                                            <div class="panel-heading">
                                                <div class="panel-title">
                                                    <h4>Panel title</h4>
                                                </div>
                                            </div>
                                            <div class="panel-body">
                                                Panel 4
                                            </div>
                                        </div>
                                        <div class="panel panel-default lobipanel" data-sortable="true">
                                            <div class="panel-heading">
                                                <div class="panel-title">
                                                    <h4>Panel title</h4>
                                                </div>
                                            </div>
                                            <div class="panel-body">
                                                Panel 5
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="highlight">
                        <pre><code>&lt;div class=&quot;panel panel-info lobipanel&quot;&gt;
    &lt;div class=&quot;panel-heading&quot;&gt;
        &lt;div class=&quot;panel-title&quot;&gt;
            &lt;h4&gt;LobiPanel title&lt;/h4&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;panel-body&quot;&gt;
        &lt;div class=&quot;panel panel-warning lobipanel&quot;&gt;
            &lt;div class=&quot;panel-heading&quot;&gt;
                &lt;div class=&quot;panel-title&quot;&gt;
                    &lt;h4&gt;Nested LobiPanel title&lt;/h4&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;panel-body&quot;&gt;
                Panel 1
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;row&quot;&gt;
            &lt;div class=&quot;col-lg-6&quot;&gt;
                &lt;div class=&quot;panel panel-default lobipanel&quot; data-sortable=&quot;true&quot;&gt;
                    &lt;div class=&quot;panel-heading&quot;&gt;
                        &lt;div class=&quot;panel-title&quot;&gt;
                            &lt;h4&gt;Panel title&lt;/h4&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;panel-body&quot;&gt;
                        Panel 2
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;div class=&quot;panel panel-default lobipanel&quot; data-sortable=&quot;true&quot;&gt;
                    &lt;div class=&quot;panel-heading&quot;&gt;
                        &lt;div class=&quot;panel-title&quot;&gt;
                            &lt;h4&gt;Panel title&lt;/h4&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;panel-body&quot;&gt;
                        Panel 3
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;col-lg-6&quot;&gt;
                &lt;div class=&quot;panel panel-default lobipanel&quot; data-sortable=&quot;true&quot;&gt;
                    &lt;div class=&quot;panel-heading&quot;&gt;
                        &lt;div class=&quot;panel-title&quot;&gt;
                            &lt;h4&gt;Panel title&lt;/h4&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;panel-body&quot;&gt;
                        Panel 4
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;div class=&quot;panel panel-default lobipanel&quot; data-sortable=&quot;true&quot;&gt;
                    &lt;div class=&quot;panel-heading&quot;&gt;
                        &lt;div class=&quot;panel-title&quot;&gt;
                            &lt;h4&gt;Panel title&lt;/h4&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;panel-body&quot;&gt;
                        Panel 5
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>
                    </div>
                </div>
            </div>
        </div>
    </div>


    <!--Default installation-->
    <script src="lib/jquery.1.11.min.js"></script>
    <script src="lib/jquery-ui.min.js"></script>
    <script src="lib/jquery.ui.touch-punch.min.js"></script>
    <script src="bootstrap/js/bootstrap.min.js"></script>

    <!--Installation using bower. Preferred!!! -->
    <!--<script src="bower_components/jquery/dist/jquery.min.js"></script>-->
    <!--<script src="bower_components/jquery-ui/jquery-ui.min.js"></script>-->
    <!--<script src="bower_components/jquery-ui-touch-punch-improved/jquery.ui.touch-punch-improved.js"></script>-->
    <!--<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>-->

    <script src="dist/js/lobipanel.js"></script>

    <script src="lib/highlight/highlight.pack.js"></script>
    <script>
        $(function(){
            var codes = $('.highlight code');
            codes.each(function (ind, el) {
                hljs.highlightBlock(el);
            });

            $('.lobipanel').lobiPanel();
            $('#demoPanel11').lobiPanel();
            $('#lobipanel-basic')
                    .on('beforeUnpin.lobiPanel', function () {
                        console.log("beforeClose");
                    })
                    .on('onClose.lobiPanel', function () {
                        console.log("onClose");
                    })
                    .on('onTitleChange.lobiPanel', function () {
                        console.log(this, arguments);

                    })
                    .lobiPanel();
            $('#lobipanel-custom-control').lobiPanel({
                reload: false,
                close: false,
                editTitle: false
            });
            $('#lobipanel-stateful').lobiPanel({
                stateful: true
            });
            $('#lobipanel-font-awesome').lobiPanel({
                reload: {
                    icon: 'fa fa-refresh'
                },
                editTitle: {
                    icon: 'fa fa-edit',
                    icon2: 'fa fa-save'
                },
                unpin: {
                    icon: 'fa fa-arrows'
                },
                minimize: {
                    icon: 'fa fa-chevron-up',
                    icon2: 'fa fa-chevron-down'
                },
                close: {
                    icon: 'fa fa-times-circle'
                },
                expand: {
                    icon: 'fa fa-expand',
                    icon2: 'fa fa-compress'
                }
            });
            $('#lobipanel-constrain-size').lobiPanel({
                minWidth: 300,
                minHeight: 300,
                maxWidth: 600,
                maxHeight: 480
            });
            $('#lobipanel-from-url').on('loaded.lobiPanel', function (ev, lobiPanel) {
                var $body = lobiPanel.$el.find('.panel-body');
                $body.html('<div class="highlight"><pre><code>' + $body.html() + '</code></pre></div>');
                hljs.highlightBlock($body.find('code')[0]);
            }).lobiPanel({
                loadUrl: 'bootstrap/dist/css/bootstrap.min.css',
                bodyHeight: 400
            });
            $('#lobipanel-multiple').find('.panel').lobiPanel({
                sortable: true,
                beforeTitleChange: function(lobiPanel, title){
                    console.log("beforeTitleChange", arguments);
                    if (!title) {
                        return false;
                    }
                }
            });
        });
    </script>
</body>
</html>

================================================
FILE: js/lobipanel.js
================================================
//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');

    if (!i || isNaN(i)) {
        i = $object.children().length - 1;
    }
    this.attr('data-index', i);

    var $el = $object.children().eq(i - 1);
    if ($el.length) {
        $el.after(this);
    } else {
        $object.append(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 StorageLocal = function () {
        this.saveChildPositions = function (parentInnerId, positions) {
            if (positions !== undefined) {
                localStorage.setItem(STORAGE_PREFIX + 'parent_' + parentInnerId, JSON.stringify(positions));
            }
        };

        this.savePanelParams = function (innerId, storage) {
            localStorage.setItem(STORAGE_PREFIX + innerId, JSON.stringify(storage));
        };

        this.getAllPanelPositions = function () {
            var parents = [];
            for (var i in localStorage) {
                if (i.indexOf(STORAGE_PREFIX + 'parent_') === 0) {
                    var innerParentId = i.replace(STORAGE_PREFIX + 'parent_', '');
                    var $parent = $('.lobipanel-parent-sortable[data-inner-id=' + innerParentId + ']');
                    if ($parent.length) {
                        parents[innerParentId] = JSON.parse(localStorage[i]);
                    }
                }
            }
            return parents;
        };

        this.getPanelStorage = function (innerId) {
            var item = localStorage.getItem(STORAGE_PREFIX + innerId);
            return JSON.parse(item || null) || {};
        };

    };

    var LobiPanel = function ($el, options) {
        var me = this;

        this.hasRandomId = false;
        this.storage = {};


        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);
        me._triggerEvent("init");
    };

    LobiPanel.prototype = {
        _processInput: function (options) {
            var me = this;
            if (!options) {
                options = {};
            }


            this.storageObject = options.storageObject || new StorageLocal();
            if (!me.hasRandomId) {
                me.storage = this.storageObject.getPanelStorage(me.innerId);
            }
            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);

            if (me.getParam('panelTitle')) {
                me.$heading.find('.panel-title').html(me.getParam('panelTitle'));
            }

            var style = me.getParam('panelStyle');
            if (style) {
                me.applyStyle(style.bg, style.text);
            }

            // me.savepanelPositions();
            // 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();

            //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');

            var toRemoveProperties = [
                'position',
                'z-index',
                'left',
                'top',
                'width',
                'height'
            ];

            for (var i in toRemoveProperties) {
                me.$el.css(toRemoveProperties[i], '');
            }

            me.$body.css({
                width: '',
                height: ''
            });
            me._setBodyHeight();
            me._insertInParent();
            me._enableSorting();
            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"]'));
                me._triggerEvent("onMaximize");
            } 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.$el.attr('data-index', me.$el.index());
            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();

            var toRemoveProperties = [
                'position',
                'z-index',
                'left',
                'top',
                'width',
                'height'
            ];

            //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')) {
                    for (var i in toRemoveProperties) {
                        me.$el.css(toRemoveProperties[i], '');
                    }
                    // 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.isPinned()) {
                    me._saveState('pinned');
                } 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: functio
Download .txt
gitextract_mvrfn518/

├── .gitignore
├── LICENSE
├── README.md
├── bootstrap/
│   └── js/
│       └── npm.js
├── bower.json
├── css/
│   └── lobipanel.css
├── demo/
│   ├── demo.css
│   ├── documentation.css
│   ├── iframe.html
│   └── stateful.html
├── dist/
│   ├── css/
│   │   └── lobipanel.css
│   └── js/
│       └── lobipanel.js
├── gulpfile.js
├── index.html
├── js/
│   └── lobipanel.js
├── less/
│   ├── loading-animation.less
│   ├── lobipanel.less
│   ├── main.less
│   └── variables.less
├── lib/
│   ├── font-awesome/
│   │   ├── css/
│   │   │   └── font-awesome.css
│   │   └── fonts/
│   │       └── FontAwesome.otf
│   ├── highlight/
│   │   ├── github.css
│   │   └── highlight.pack.js
│   └── jquery.ui.touch-punch.js
└── package.json
Download .txt
SYMBOL INDEX (20 symbols across 2 files)

FILE: lib/highlight/highlight.pack.js
  function n (line 1) | function n(e){return e.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").repl...
  function t (line 1) | function t(e){return e.nodeName.toLowerCase()}
  function r (line 1) | function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}
  function a (line 1) | function a(e){var n=(e.className+" "+(e.parentNode?e.parentNode.classNam...
  function o (line 1) | function o(e,n){var t={};for(var r in e)t[r]=e[r];if(n)for(var r in n)t[...
  function i (line 1) | function i(e){var n=[];return function r(e,a){for(var o=e.firstChild;o;o...
  function c (line 1) | function c(e,r,a){function o(){return e.length&&r.length?e[0].offset!=r[...
  function u (line 1) | function u(e){function n(e){return e&&e.source||e}function t(t,r){return...
  function s (line 1) | function s(e,t,a,o){function i(e,n){for(var t=0;t<n.c.length;t++)if(r(n....
  function l (line 1) | function l(e,t){t=t||E.languages||Object.keys(R);var r={r:0,value:n(e)},...
  function f (line 1) | function f(e){return E.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,fun...
  function g (line 1) | function g(e,n,t){var r=n?x[n]:t,a=[e.trim()];return e.match(/(\s|^)hljs...
  function p (line 1) | function p(e){var n=a(e);if(!/no(-?)highlight/.test(n)){var t;E.useBR?(t...
  function d (line 1) | function d(e){E=o(E,e)}
  function h (line 1) | function h(){if(!h.called){h.called=!0;var e=document.querySelectorAll("...
  function v (line 1) | function v(){addEventListener("DOMContentLoaded",h,!1),addEventListener(...
  function b (line 1) | function b(n,t){var r=R[n]=t(e);r.aliases&&r.aliases.forEach(function(e)...
  function m (line 1) | function m(){return Object.keys(R)}
  function N (line 1) | function N(e){return R[e]||R[x[e]]}

FILE: lib/jquery.ui.touch-punch.js
  function simulateMouseEvent (line 31) | function simulateMouseEvent (event, simulatedType) {
Condensed preview — 25 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (328K chars).
[
  {
    "path": ".gitignore",
    "chars": 38,
    "preview": ".idea/\nbower_components/\nnode_modules/"
  },
  {
    "path": "LICENSE",
    "chars": 1086,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Zura Sekhniashvili\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "README.md",
    "chars": 2855,
    "preview": "# LobiPanel\n[![CDNJS](https://img.shields.io/cdnjs/v/lobipanel.svg)](https://cdnjs.com/libraries/lobipanel)\n\njQuery plug"
  },
  {
    "path": "bootstrap/js/npm.js",
    "chars": 484,
    "preview": "// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.\nrequ"
  },
  {
    "path": "bower.json",
    "chars": 851,
    "preview": "{\n  \"name\": \"lobipanel\",\n  \"description\": \"jQuery plugin for bootstrap panels. It extends panels with several common and"
  },
  {
    "path": "css/lobipanel.css",
    "chars": 15954,
    "preview": ".spinner-wrapper {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background-color: rgba(255, 255"
  },
  {
    "path": "demo/demo.css",
    "chars": 625,
    "preview": ".highlight {\n    overflow: auto;\n    padding: 9px 14px;\n    margin-bottom: 14px;\n    background-color: #f7f7f9;\n    bord"
  },
  {
    "path": "demo/documentation.css",
    "chars": 2027,
    "preview": ".plugin-documentation .row{margin-left:0;margin-right:0;border-bottom:1px solid #ddd}.plugin-documentation .row-header ."
  },
  {
    "path": "demo/iframe.html",
    "chars": 3010,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>Lobipanel - jQuery plugin for bootstrap panels. It extends panels wit"
  },
  {
    "path": "demo/stateful.html",
    "chars": 5200,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>Lobipanel - jQuery plugin for bootstrap panels. It extends panels wit"
  },
  {
    "path": "dist/css/lobipanel.css",
    "chars": 16053,
    "preview": ".spinner-wrapper {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background-color: rgba(255, 255"
  },
  {
    "path": "dist/js/lobipanel.js",
    "chars": 75751,
    "preview": "//Author      : @arboshiki\n/**\n * Generates random string of n length.\n * String contains only letters and numbers\n *\n *"
  },
  {
    "path": "gulpfile.js",
    "chars": 1380,
    "preview": "/**\n * Created by zura on 12/10/2017.\n */\n\n'use strict';\n\nvar pjson = require('./package.json');\n\nvar less = require('gu"
  },
  {
    "path": "index.html",
    "chars": 42763,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>Lobipanel - jQuery plugin for bootstrap panels. It extends panels wit"
  },
  {
    "path": "js/lobipanel.js",
    "chars": 75751,
    "preview": "//Author      : @arboshiki\n/**\n * Generates random string of n length.\n * String contains only letters and numbers\n *\n *"
  },
  {
    "path": "less/loading-animation.less",
    "chars": 7688,
    "preview": ".spinner-wrapper{\n    position: absolute;\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    background-color: rg"
  },
  {
    "path": "less/lobipanel.less",
    "chars": 201,
    "preview": "\n@import \"../bower_components/bootstrap/less/variables.less\";\n@import \"../bower_components/bootstrap/less/mixins.less\";\n"
  },
  {
    "path": "less/main.less",
    "chars": 9733,
    "preview": ".tooltip {\n    z-index: 20000;\n}\n\nbody.lobipanel-minimized {\n    padding-bottom: @lobipanel-toolbar-height;\n}\n\n.lobipane"
  },
  {
    "path": "less/variables.less",
    "chars": 1399,
    "preview": "\n@lobipanel-basic-z-index                    : 10000;\n@lobipanel-panel-title-padding-horizontal   : 15px;\n@lobipanel-pan"
  },
  {
    "path": "lib/font-awesome/css/font-awesome.css",
    "chars": 32318,
    "preview": "/*!\n *  Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome\n *  License - http://fontawesome.io/lice"
  },
  {
    "path": "lib/highlight/github.css",
    "chars": 1652,
    "preview": "/*\n\ngithub.com style (c) Vasily Polovnyov <vast@whiteants.net>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padd"
  },
  {
    "path": "lib/highlight/highlight.pack.js",
    "chars": 10129,
    "preview": "!function(e){\"undefined\"!=typeof exports?e(exports):(window.hljs=e({}),\"function\"==typeof define&&define.amd&&define([],"
  },
  {
    "path": "lib/jquery.ui.touch-punch.js",
    "chars": 5072,
    "preview": "/*!\n * jQuery UI Touch Punch 0.2.3\n *\n * Copyright 2011–2014, Dave Furfero\n * Dual licensed under the MIT or GPL Version"
  },
  {
    "path": "package.json",
    "chars": 911,
    "preview": "{\n  \"name\": \"lobipanel\",\n  \"version\": \"1.0.0\",\n  \"description\": \"jQuery plugin for bootstrap panels. It extends panels w"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the arboshiki/lobipanel GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 25 files (305.6 KB), approximately 76.6k tokens, and a symbol index with 20 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!