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 ... ``` #### 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 ================================================ Lobipanel - jQuery plugin for bootstrap panels. It extends panels with several common and useful functions.

Panel title

================================================ FILE: demo/stateful.html ================================================ Lobipanel - jQuery plugin for bootstrap panels. It extends panels with several common and useful functions.

Panel title

Panel 2

Panel title

Panel 3

Panel title

Panel 5
================================================ 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.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: '' }); }); 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 $('') .append('') .append(''); }, _generateEditTitle: function () { var me = this; var options = me.$options.editTitle; var control = $(''); control.append(''); if (options.tooltip && typeof options.tooltip === 'string') { control.append('' + options.tooltip + ''); control.attr('data-tooltip', options.tooltip); } me._attachEditTitleClickListener(control); return $('
  • ').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 = $(''); control.append(''); if (options.tooltip && typeof options.tooltip === 'string') { control.append('' + options.tooltip + ''); control.attr('data-tooltip', options.tooltip); } me._attachUnpinClickListener(control); return $('
  • ').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 = $(''); control.append(''); if (options.tooltip && typeof options.tooltip === 'string') { control.append('' + options.tooltip + ''); control.attr('data-tooltip', options.tooltip); } me._attachReloadClickListener(control); return $('
  • ').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 = $(''); control.append(''); if (options.tooltip && typeof options.tooltip === 'string') { control.append('' + options.tooltip + ''); control.attr('data-tooltip', options.tooltip); } me._attachMinimizeClickListener(control); return $('
  • ').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 = $(''); control.append(''); if (options.tooltip && typeof options.tooltip === 'string') { control.append('' + options.tooltip + ''); control.attr('data-tooltip', options.tooltip); } me._attachExpandClickListener(control); return $('
  • ').append(control); }, _generateChangeStyle: function () { var me = this; var options = me.$options.changeStyle; var $control = $(''); $control.append(''); if (options.tooltip && typeof options.tooltip === 'string') { $control.append('' + options.tooltip + ''); $control.attr('data-tooltip', options.tooltip); } // me._attachExpandClickListener(control); var $dropdown = $('
  • ').append($control); var $menu = $('
    ', { '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('
    '); } } $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 = $('
    ', { 'class': 'dropdown' }).append( $('