', {
'class': 'dropdown-menu dropdown-menu-right'
}).appendTo($dropdown);
for (var i = 0; i < 0; i++) {
var st = me.$globalOptions.listStyles[i];
var st = 'primary';
$('
')
.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 = $('
');
control.append('
');
if (options.tooltip && typeof options.tooltip === 'string') {
control.append('
' + options.tooltip + ' ');
control.attr('data-tooltip', options.tooltip);
}
me._attachCloseClickListener(control);
return $('
').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 = $('
');
$('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 = ['
'].join("");
return $('
' + template + '
');
},
_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
unpinned panel draggable
//Warning!!! This requires jquery ui draggable widget to be included
draggable: true,
//Makes
pinned 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
unpin, resizable panel can have.
minWidth: 200,
//Minimum height
unpin, resizable panel can have.
minHeight: 100,
//Maximum width
unpin, resizable panel can have.
maxWidth: 1200,
//Maximum height
unpin, resizable 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
LobiPanel 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
================================================
Lobipanel - jQuery plugin for bootstrap panels. It extends panels with several common and useful functions.
Basic example
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.
$('selector').lobiPanel();
Disable control buttons
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.
$('selector').lobiPanel({
reload: false,
close: false,
editTitle: false
});
Stateful. Saves its state in localStorage
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.
$('selector').lobiPanel({
stateful: true
});
Use font awesome icons
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.
$('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'
}
});
Constrain panel size
Unpin the panel and try to resize it.
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.
$('selector').lobiPanel({
minWidth: 300,
minHeight: 300,
maxWidth: 600,
maxHeight: 480
});
Load content from url
Load content from specified url and apply highlight code
$('selector').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]);
});
$('selector').lobiPanel({
loadUrl: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.css',
bodyHeight: 400
});
Multiple panels with drag & drop
Drag panels by clicking on the headers
#
First Name
Last Name
Username
1
Mark
Otto
@mdo
2
Jacob
Thornton
@fat
3
Larry
the Bird
@twitter
#
First Name
Last Name
Username
1
Mark
Otto
@mdo
2
Jacob
Thornton
@fat
3
Larry
the Bird
@twitter
$('.panel').lobiPanel({
sortable: true
});
Initialize with data-* attributes
#
First Name
Last Name
Username
1
Mark
Otto
@mdo
2
Jacob
Thornton
@fat
3
Larry
the Bird
@twitter
<div class="panel panel-default lobipanel" 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">
content
</div>
</div>
Nested LobiPanel 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>
================================================
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: 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(
$('
', {
'type': 'button',
'data-toggle': 'dropdown',
'class': 'btn btn-default btn-xs',
'html': ' '
})
);
var $menu = $('', {
'class': 'dropdown-menu dropdown-menu-right'
}).appendTo($dropdown);
for (var i = 0; i < 0; i++) {
var st = me.$globalOptions.listStyles[i];
var st = 'primary';
$('
')
.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 = $('
');
control.append('
');
if (options.tooltip && typeof options.tooltip === 'string') {
control.append('
' + options.tooltip + ' ');
control.attr('data-tooltip', options.tooltip);
}
me._attachCloseClickListener(control);
return $('
').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 = $('
');
$('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 = ['
'].join("");
return $('
' + template + '
');
},
_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
unpinned panel draggable
//Warning!!! This requires jquery ui draggable widget to be included
draggable: true,
//Makes
pinned 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
unpin, resizable panel can have.
minWidth: 200,
//Minimum height
unpin, resizable panel can have.
minHeight: 100,
//Maximum width
unpin, resizable panel can have.
maxWidth: 1200,
//Maximum height
unpin, resizable 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
LobiPanel instance
*/
beforeTitleChange: null
};
$('.lobipanel').lobiPanel();
var $parent = $('.lobipanel-parent-sortable');
$parent.lobiPanelParent();
});
================================================
FILE: less/loading-animation.less
================================================
.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;
.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;
.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;
}
&: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;
}
&: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;
}
&: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;
}
&: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;
}
&: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);
}
}
================================================
FILE: less/lobipanel.less
================================================
@import "../bower_components/bootstrap/less/variables.less";
@import "../bower_components/bootstrap/less/mixins.less";
@import "variables.less";
@import "loading-animation.less";
@import "main.less";
================================================
FILE: less/main.less
================================================
.tooltip {
z-index: 20000;
}
body.lobipanel-minimized {
padding-bottom: @lobipanel-toolbar-height;
}
.lobipanel {
position: relative;
margin-bottom: @lobipanel-panel-margin-bottom;
> .panel-heading {
padding: 5px;
position: relative;
.border-top-radius(0px);
> .panel-title {
float: left;
max-width: calc(%(~"100% - %a", @lobipanel-panel-control-width));
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: @lobipanel-panel-title-font-size;
line-height: @lobipanel-panel-title-line-height;
padding-left: @lobipanel-panel-title-padding-horizontal;
h1, h2, h3, h4, h5, h6 {
margin: 0;
line-height: @lobipanel-panel-title-line-height;
}
input {
color: inherit;
line-height: @lobipanel-panel-title-line-height;
border-radius: 2px;
padding: 0 5px;
width: 100%;
background-color: rgba(0, 0, 0, 0.2);
border: 1px solid transparent;
outline: 0;
&:focus {
background-color: rgba(0, 0, 0, 0.15);
}
}
}
.dropdown {
display: inline-block;
float: right;
position: relative;
.dropdown-menu {
left: auto;
right: 0;
min-width: 0;
margin-top: 0;
border-radius: 0;
> li > a {
.control-title {
display: inline-block;
margin-left: 15px;
}
}
.style-change-item {
position: relative;
.style-list {
position: absolute;
background: #f5f5f5;
box-shadow: 2px 2px 12px rgba(0, 0, 0, 0.3);
padding: @lobipanel-style-change-list-padding;
display: none;
width: @lobipanel-style-change-item-count-in-a-row * @lobipanel-style-change-item-size
+ (@lobipanel-style-change-item-count-in-a-row * 2) * @lobipanel-style-change-item-margin
+ @lobipanel-style-change-list-padding * 2;
top: 100%;
right: 0;
z-index: 2;
.style-item{
cursor: pointer;
display: inline-block;
width: @lobipanel-style-change-item-size;
height: @lobipanel-style-change-item-size;
margin: @lobipanel-style-change-item-margin;
border: 2px solid #f5f5f5;
&:hover{
border-color: #FFF;
}
&:active{
box-shadow: inset 2px 2px 10px rgba(0, 0, 0, 0.3);
}
}
&.opened{
display: block;
}
}
}
}
.dropdown-toggle {
border: none;
outline: 0;
background-color: transparent;
text-align: center;
padding: 0;
width: @lobipanel-panel-control-width;
font-size: @lobipanel-panel-control-font-size;
.transition(all @lobipanel-transition-duration);
.panel-control-icon {
top: 0;
line-height: @lobipanel-panel-title-line-height;
}
&:hover,
&:hover:focus {
text-shadow: @lobipanel-panel-control-hover-text-shadow;
background-color: @lobipanel-panel-control-hover-bg;
}
}
&.open {
.dropdown-toggle {
text-shadow: @lobipanel-panel-control-hover-text-shadow;
background-color: @lobipanel-panel-control-hover-bg;
}
}
}
.clearfix();
}
@media screen and (min-width: @screen-sm-min) {
.panel-heading {
.panel-title {
max-width: calc(%(~"100% - %a", @lobipanel-panel-control-width * 6));
}
.lobipanel-dropdown-screen-lg();
}
}
> .panel-body {
overflow: auto;
position: relative;
}
.panel-loader {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #fff;
opacity: 0.8;
}
&.panel-collapsed {
> .panel-heading {
border-bottom: none;
.dropdown {
.dropdown-menu {
> li {
> a {
&[data-func="unpin"],
&[data-func="reload"] {
display: none;
}
}
}
}
}
}
}
&.panel-expanded,
&.panel-unpin,
&.panel-minimized.panel-unpin {
margin-bottom: 0;
}
&.panel-unpin {
overflow: hidden;
position: absolute;
z-index: @lobipanel-basic-z-index;
.box-shadow(@lobipanel-panel-unpin-box-shadow);
> .panel-heading {
cursor: move;
}
&.panel-minimized {
float: left;
position: static;
border-radius: 0;
.box-shadow(none);
min-width: @lobipanel-panel-minimized-min-width;
margin-right: @lobipanel-panel-minimized-margin-right;
> .panel-heading {
padding: 0;
cursor: pointer;
border-bottom: none;
.panel-title {
max-width: calc(%(~"100% - %a", @lobipanel-panel-control-width * 2));
h1, h2, h3, h4, h5, h6 {
overflow: hidden;
text-overflow: ellipsis;
}
}
.lobipanel-dropdown-screen-lg();
.dropdown {
.dropdown-menu {
> li {
> a {
display: none;
&[data-func="close"],
&[data-func="expand"] {
display: inline-block;
}
}
}
}
}
}
> .panel-body,
> .panel-footer {
display: none !important;
}
}
}
&.panel-expanded {
> .panel-heading {
cursor: default;
.dropdown {
.dropdown-menu {
> li {
> a {
&[data-func="unpin"],
&[data-func="minimize"] {
display: none;
}
}
}
}
}
}
&.panel-unpin {
> .panel-heading {
.panel-control[data-func="minimize"] {
display: block;
}
}
}
}
}
.lobipanel-minimized-toolbar {
position: fixed;
height: @lobipanel-toolbar-height;
padding: @lobipanel-toolbar-padding;
bottom: 0;
left: 0;
right: 0;
z-index: 20000;
background: @lobipanel-toolbar-bg;
}
.lobipanel-placeholder {
background-color: #f9f5d1;
border: 1px dashed #919191;
margin-bottom: @lobipanel-panel-margin-bottom;
}
.lobipanel-dropdown-screen-lg() {
.dropdown {
.dropdown-menu {
position: static;
display: inline-block;
border: none;
padding: 0;
margin: 0;
min-width: 0;
width: auto;
.box-shadow(none);
background: transparent;
> li {
display: inline-block;
> a {
cursor: pointer;
color: inherit;
padding: 0;
outline: 0;
text-align: center;
width: @lobipanel-panel-control-width;
font-size: @lobipanel-panel-control-font-size;
.transition(all @lobipanel-transition-duration);
.panel-control-icon {
top: 0;
line-height: @lobipanel-panel-title-line-height;
}
.control-title {
display: none;
}
&:hover, &:focus:hover {
text-shadow: @lobipanel-panel-control-hover-text-shadow;
background-color: @lobipanel-panel-control-hover-bg;
}
&:focus {
text-shadow: none;
background-color: transparent;
}
}
}
}
.dropdown-toggle {
display: none;
}
}
}
.lobipanel-parent-sortable {
min-height: 20px;
}
================================================
FILE: less/variables.less
================================================
@lobipanel-basic-z-index : 10000;
@lobipanel-panel-title-padding-horizontal : 15px;
@lobipanel-panel-title-font-size : 16px;
@lobipanel-panel-title-line-height : 30px;
@lobipanel-panel-margin-bottom : 15px;
@lobipanel-transition-duration : 0.2s;
@lobipanel-panel-control-font-size : 14px;
@lobipanel-panel-control-width : 30px;
@lobipanel-panel-control-border-left : 1px solid rgba(0, 0, 0, 0.05);
@lobipanel-panel-control-hover-bg : rgba(0, 0, 0, 0.15);
@lobipanel-panel-control-hover-text-shadow : 2px 2px 5px rgba(0, 0, 0, 0.6);
@lobipanel-panel-unpin-box-shadow : 2px 2px 15px 5px rgba(10, 10, 10, 0.5);
@lobipanel-panel-minimized-min-width : 170px;
@lobipanel-panel-minimized-margin-right : 5px;
@lobipanel-toolbar-height : 36px;
@lobipanel-toolbar-padding : 2px;
@lobipanel-toolbar-bg : rgba(34, 115, 182, 0.51);
@lobipanel-resize-width : 10px;
@lobipanel-resize-height : @lobipanel-resize-width;
@lobipanel-resize-offset : -@lobipanel-resize-width/2;
@lobipanel-style-change-list-padding: 4px;
@lobipanel-style-change-item-size: 24px;
@lobipanel-style-change-item-margin: 2px;
@lobipanel-style-change-item-count-in-a-row:3;
================================================
FILE: lib/font-awesome/css/font-awesome.css
================================================
/*!
* Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
*/
/* FONT PATH
* -------------------------- */
@font-face {
font-family: 'FontAwesome';
src: url('../fonts/fontawesome-webfont.eot?v=4.4.0');
src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');
font-weight: normal;
font-style: normal;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* makes the font 33% larger relative to the icon container */
.fa-lg {
font-size: 1.33333333em;
line-height: 0.75em;
vertical-align: -15%;
}
.fa-2x {
font-size: 2em;
}
.fa-3x {
font-size: 3em;
}
.fa-4x {
font-size: 4em;
}
.fa-5x {
font-size: 5em;
}
.fa-fw {
width: 1.28571429em;
text-align: center;
}
.fa-ul {
padding-left: 0;
margin-left: 2.14285714em;
list-style-type: none;
}
.fa-ul > li {
position: relative;
}
.fa-li {
position: absolute;
left: -2.14285714em;
width: 2.14285714em;
top: 0.14285714em;
text-align: center;
}
.fa-li.fa-lg {
left: -1.85714286em;
}
.fa-border {
padding: .2em .25em .15em;
border: solid 0.08em #eeeeee;
border-radius: .1em;
}
.fa-pull-left {
float: left;
}
.fa-pull-right {
float: right;
}
.fa.fa-pull-left {
margin-right: .3em;
}
.fa.fa-pull-right {
margin-left: .3em;
}
/* Deprecated as of 4.4.0 */
.pull-right {
float: right;
}
.pull-left {
float: left;
}
.fa.pull-left {
margin-right: .3em;
}
.fa.pull-right {
margin-left: .3em;
}
.fa-spin {
-webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear;
}
.fa-pulse {
-webkit-animation: fa-spin 1s infinite steps(8);
animation: fa-spin 1s infinite steps(8);
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fa-rotate-90 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
-webkit-transform: rotate(270deg);
-ms-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);
-webkit-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.fa-flip-vertical {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);
-webkit-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);
}
:root .fa-rotate-90,
:root .fa-rotate-180,
:root .fa-rotate-270,
:root .fa-flip-horizontal,
:root .fa-flip-vertical {
filter: none;
}
.fa-stack {
position: relative;
display: inline-block;
width: 2em;
height: 2em;
line-height: 2em;
vertical-align: middle;
}
.fa-stack-1x,
.fa-stack-2x {
position: absolute;
left: 0;
width: 100%;
text-align: center;
}
.fa-stack-1x {
line-height: inherit;
}
.fa-stack-2x {
font-size: 2em;
}
.fa-inverse {
color: #ffffff;
}
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
readers do not read off random characters that represent icons */
.fa-glass:before {
content: "\f000";
}
.fa-music:before {
content: "\f001";
}
.fa-search:before {
content: "\f002";
}
.fa-envelope-o:before {
content: "\f003";
}
.fa-heart:before {
content: "\f004";
}
.fa-star:before {
content: "\f005";
}
.fa-star-o:before {
content: "\f006";
}
.fa-user:before {
content: "\f007";
}
.fa-film:before {
content: "\f008";
}
.fa-th-large:before {
content: "\f009";
}
.fa-th:before {
content: "\f00a";
}
.fa-th-list:before {
content: "\f00b";
}
.fa-check:before {
content: "\f00c";
}
.fa-remove:before,
.fa-close:before,
.fa-times:before {
content: "\f00d";
}
.fa-search-plus:before {
content: "\f00e";
}
.fa-search-minus:before {
content: "\f010";
}
.fa-power-off:before {
content: "\f011";
}
.fa-signal:before {
content: "\f012";
}
.fa-gear:before,
.fa-cog:before {
content: "\f013";
}
.fa-trash-o:before {
content: "\f014";
}
.fa-home:before {
content: "\f015";
}
.fa-file-o:before {
content: "\f016";
}
.fa-clock-o:before {
content: "\f017";
}
.fa-road:before {
content: "\f018";
}
.fa-download:before {
content: "\f019";
}
.fa-arrow-circle-o-down:before {
content: "\f01a";
}
.fa-arrow-circle-o-up:before {
content: "\f01b";
}
.fa-inbox:before {
content: "\f01c";
}
.fa-play-circle-o:before {
content: "\f01d";
}
.fa-rotate-right:before,
.fa-repeat:before {
content: "\f01e";
}
.fa-refresh:before {
content: "\f021";
}
.fa-list-alt:before {
content: "\f022";
}
.fa-lock:before {
content: "\f023";
}
.fa-flag:before {
content: "\f024";
}
.fa-headphones:before {
content: "\f025";
}
.fa-volume-off:before {
content: "\f026";
}
.fa-volume-down:before {
content: "\f027";
}
.fa-volume-up:before {
content: "\f028";
}
.fa-qrcode:before {
content: "\f029";
}
.fa-barcode:before {
content: "\f02a";
}
.fa-tag:before {
content: "\f02b";
}
.fa-tags:before {
content: "\f02c";
}
.fa-book:before {
content: "\f02d";
}
.fa-bookmark:before {
content: "\f02e";
}
.fa-print:before {
content: "\f02f";
}
.fa-camera:before {
content: "\f030";
}
.fa-font:before {
content: "\f031";
}
.fa-bold:before {
content: "\f032";
}
.fa-italic:before {
content: "\f033";
}
.fa-text-height:before {
content: "\f034";
}
.fa-text-width:before {
content: "\f035";
}
.fa-align-left:before {
content: "\f036";
}
.fa-align-center:before {
content: "\f037";
}
.fa-align-right:before {
content: "\f038";
}
.fa-align-justify:before {
content: "\f039";
}
.fa-list:before {
content: "\f03a";
}
.fa-dedent:before,
.fa-outdent:before {
content: "\f03b";
}
.fa-indent:before {
content: "\f03c";
}
.fa-video-camera:before {
content: "\f03d";
}
.fa-photo:before,
.fa-image:before,
.fa-picture-o:before {
content: "\f03e";
}
.fa-pencil:before {
content: "\f040";
}
.fa-map-marker:before {
content: "\f041";
}
.fa-adjust:before {
content: "\f042";
}
.fa-tint:before {
content: "\f043";
}
.fa-edit:before,
.fa-pencil-square-o:before {
content: "\f044";
}
.fa-share-square-o:before {
content: "\f045";
}
.fa-check-square-o:before {
content: "\f046";
}
.fa-arrows:before {
content: "\f047";
}
.fa-step-backward:before {
content: "\f048";
}
.fa-fast-backward:before {
content: "\f049";
}
.fa-backward:before {
content: "\f04a";
}
.fa-play:before {
content: "\f04b";
}
.fa-pause:before {
content: "\f04c";
}
.fa-stop:before {
content: "\f04d";
}
.fa-forward:before {
content: "\f04e";
}
.fa-fast-forward:before {
content: "\f050";
}
.fa-step-forward:before {
content: "\f051";
}
.fa-eject:before {
content: "\f052";
}
.fa-chevron-left:before {
content: "\f053";
}
.fa-chevron-right:before {
content: "\f054";
}
.fa-plus-circle:before {
content: "\f055";
}
.fa-minus-circle:before {
content: "\f056";
}
.fa-times-circle:before {
content: "\f057";
}
.fa-check-circle:before {
content: "\f058";
}
.fa-question-circle:before {
content: "\f059";
}
.fa-info-circle:before {
content: "\f05a";
}
.fa-crosshairs:before {
content: "\f05b";
}
.fa-times-circle-o:before {
content: "\f05c";
}
.fa-check-circle-o:before {
content: "\f05d";
}
.fa-ban:before {
content: "\f05e";
}
.fa-arrow-left:before {
content: "\f060";
}
.fa-arrow-right:before {
content: "\f061";
}
.fa-arrow-up:before {
content: "\f062";
}
.fa-arrow-down:before {
content: "\f063";
}
.fa-mail-forward:before,
.fa-share:before {
content: "\f064";
}
.fa-expand:before {
content: "\f065";
}
.fa-compress:before {
content: "\f066";
}
.fa-plus:before {
content: "\f067";
}
.fa-minus:before {
content: "\f068";
}
.fa-asterisk:before {
content: "\f069";
}
.fa-exclamation-circle:before {
content: "\f06a";
}
.fa-gift:before {
content: "\f06b";
}
.fa-leaf:before {
content: "\f06c";
}
.fa-fire:before {
content: "\f06d";
}
.fa-eye:before {
content: "\f06e";
}
.fa-eye-slash:before {
content: "\f070";
}
.fa-warning:before,
.fa-exclamation-triangle:before {
content: "\f071";
}
.fa-plane:before {
content: "\f072";
}
.fa-calendar:before {
content: "\f073";
}
.fa-random:before {
content: "\f074";
}
.fa-comment:before {
content: "\f075";
}
.fa-magnet:before {
content: "\f076";
}
.fa-chevron-up:before {
content: "\f077";
}
.fa-chevron-down:before {
content: "\f078";
}
.fa-retweet:before {
content: "\f079";
}
.fa-shopping-cart:before {
content: "\f07a";
}
.fa-folder:before {
content: "\f07b";
}
.fa-folder-open:before {
content: "\f07c";
}
.fa-arrows-v:before {
content: "\f07d";
}
.fa-arrows-h:before {
content: "\f07e";
}
.fa-bar-chart-o:before,
.fa-bar-chart:before {
content: "\f080";
}
.fa-twitter-square:before {
content: "\f081";
}
.fa-facebook-square:before {
content: "\f082";
}
.fa-camera-retro:before {
content: "\f083";
}
.fa-key:before {
content: "\f084";
}
.fa-gears:before,
.fa-cogs:before {
content: "\f085";
}
.fa-comments:before {
content: "\f086";
}
.fa-thumbs-o-up:before {
content: "\f087";
}
.fa-thumbs-o-down:before {
content: "\f088";
}
.fa-star-half:before {
content: "\f089";
}
.fa-heart-o:before {
content: "\f08a";
}
.fa-sign-out:before {
content: "\f08b";
}
.fa-linkedin-square:before {
content: "\f08c";
}
.fa-thumb-tack:before {
content: "\f08d";
}
.fa-external-link:before {
content: "\f08e";
}
.fa-sign-in:before {
content: "\f090";
}
.fa-trophy:before {
content: "\f091";
}
.fa-github-square:before {
content: "\f092";
}
.fa-upload:before {
content: "\f093";
}
.fa-lemon-o:before {
content: "\f094";
}
.fa-phone:before {
content: "\f095";
}
.fa-square-o:before {
content: "\f096";
}
.fa-bookmark-o:before {
content: "\f097";
}
.fa-phone-square:before {
content: "\f098";
}
.fa-twitter:before {
content: "\f099";
}
.fa-facebook-f:before,
.fa-facebook:before {
content: "\f09a";
}
.fa-github:before {
content: "\f09b";
}
.fa-unlock:before {
content: "\f09c";
}
.fa-credit-card:before {
content: "\f09d";
}
.fa-feed:before,
.fa-rss:before {
content: "\f09e";
}
.fa-hdd-o:before {
content: "\f0a0";
}
.fa-bullhorn:before {
content: "\f0a1";
}
.fa-bell:before {
content: "\f0f3";
}
.fa-certificate:before {
content: "\f0a3";
}
.fa-hand-o-right:before {
content: "\f0a4";
}
.fa-hand-o-left:before {
content: "\f0a5";
}
.fa-hand-o-up:before {
content: "\f0a6";
}
.fa-hand-o-down:before {
content: "\f0a7";
}
.fa-arrow-circle-left:before {
content: "\f0a8";
}
.fa-arrow-circle-right:before {
content: "\f0a9";
}
.fa-arrow-circle-up:before {
content: "\f0aa";
}
.fa-arrow-circle-down:before {
content: "\f0ab";
}
.fa-globe:before {
content: "\f0ac";
}
.fa-wrench:before {
content: "\f0ad";
}
.fa-tasks:before {
content: "\f0ae";
}
.fa-filter:before {
content: "\f0b0";
}
.fa-briefcase:before {
content: "\f0b1";
}
.fa-arrows-alt:before {
content: "\f0b2";
}
.fa-group:before,
.fa-users:before {
content: "\f0c0";
}
.fa-chain:before,
.fa-link:before {
content: "\f0c1";
}
.fa-cloud:before {
content: "\f0c2";
}
.fa-flask:before {
content: "\f0c3";
}
.fa-cut:before,
.fa-scissors:before {
content: "\f0c4";
}
.fa-copy:before,
.fa-files-o:before {
content: "\f0c5";
}
.fa-paperclip:before {
content: "\f0c6";
}
.fa-save:before,
.fa-floppy-o:before {
content: "\f0c7";
}
.fa-square:before {
content: "\f0c8";
}
.fa-navicon:before,
.fa-reorder:before,
.fa-bars:before {
content: "\f0c9";
}
.fa-list-ul:before {
content: "\f0ca";
}
.fa-list-ol:before {
content: "\f0cb";
}
.fa-strikethrough:before {
content: "\f0cc";
}
.fa-underline:before {
content: "\f0cd";
}
.fa-table:before {
content: "\f0ce";
}
.fa-magic:before {
content: "\f0d0";
}
.fa-truck:before {
content: "\f0d1";
}
.fa-pinterest:before {
content: "\f0d2";
}
.fa-pinterest-square:before {
content: "\f0d3";
}
.fa-google-plus-square:before {
content: "\f0d4";
}
.fa-google-plus:before {
content: "\f0d5";
}
.fa-money:before {
content: "\f0d6";
}
.fa-caret-down:before {
content: "\f0d7";
}
.fa-caret-up:before {
content: "\f0d8";
}
.fa-caret-left:before {
content: "\f0d9";
}
.fa-caret-right:before {
content: "\f0da";
}
.fa-columns:before {
content: "\f0db";
}
.fa-unsorted:before,
.fa-sort:before {
content: "\f0dc";
}
.fa-sort-down:before,
.fa-sort-desc:before {
content: "\f0dd";
}
.fa-sort-up:before,
.fa-sort-asc:before {
content: "\f0de";
}
.fa-envelope:before {
content: "\f0e0";
}
.fa-linkedin:before {
content: "\f0e1";
}
.fa-rotate-left:before,
.fa-undo:before {
content: "\f0e2";
}
.fa-legal:before,
.fa-gavel:before {
content: "\f0e3";
}
.fa-dashboard:before,
.fa-tachometer:before {
content: "\f0e4";
}
.fa-comment-o:before {
content: "\f0e5";
}
.fa-comments-o:before {
content: "\f0e6";
}
.fa-flash:before,
.fa-bolt:before {
content: "\f0e7";
}
.fa-sitemap:before {
content: "\f0e8";
}
.fa-umbrella:before {
content: "\f0e9";
}
.fa-paste:before,
.fa-clipboard:before {
content: "\f0ea";
}
.fa-lightbulb-o:before {
content: "\f0eb";
}
.fa-exchange:before {
content: "\f0ec";
}
.fa-cloud-download:before {
content: "\f0ed";
}
.fa-cloud-upload:before {
content: "\f0ee";
}
.fa-user-md:before {
content: "\f0f0";
}
.fa-stethoscope:before {
content: "\f0f1";
}
.fa-suitcase:before {
content: "\f0f2";
}
.fa-bell-o:before {
content: "\f0a2";
}
.fa-coffee:before {
content: "\f0f4";
}
.fa-cutlery:before {
content: "\f0f5";
}
.fa-file-text-o:before {
content: "\f0f6";
}
.fa-building-o:before {
content: "\f0f7";
}
.fa-hospital-o:before {
content: "\f0f8";
}
.fa-ambulance:before {
content: "\f0f9";
}
.fa-medkit:before {
content: "\f0fa";
}
.fa-fighter-jet:before {
content: "\f0fb";
}
.fa-beer:before {
content: "\f0fc";
}
.fa-h-square:before {
content: "\f0fd";
}
.fa-plus-square:before {
content: "\f0fe";
}
.fa-angle-double-left:before {
content: "\f100";
}
.fa-angle-double-right:before {
content: "\f101";
}
.fa-angle-double-up:before {
content: "\f102";
}
.fa-angle-double-down:before {
content: "\f103";
}
.fa-angle-left:before {
content: "\f104";
}
.fa-angle-right:before {
content: "\f105";
}
.fa-angle-up:before {
content: "\f106";
}
.fa-angle-down:before {
content: "\f107";
}
.fa-desktop:before {
content: "\f108";
}
.fa-laptop:before {
content: "\f109";
}
.fa-tablet:before {
content: "\f10a";
}
.fa-mobile-phone:before,
.fa-mobile:before {
content: "\f10b";
}
.fa-circle-o:before {
content: "\f10c";
}
.fa-quote-left:before {
content: "\f10d";
}
.fa-quote-right:before {
content: "\f10e";
}
.fa-spinner:before {
content: "\f110";
}
.fa-circle:before {
content: "\f111";
}
.fa-mail-reply:before,
.fa-reply:before {
content: "\f112";
}
.fa-github-alt:before {
content: "\f113";
}
.fa-folder-o:before {
content: "\f114";
}
.fa-folder-open-o:before {
content: "\f115";
}
.fa-smile-o:before {
content: "\f118";
}
.fa-frown-o:before {
content: "\f119";
}
.fa-meh-o:before {
content: "\f11a";
}
.fa-gamepad:before {
content: "\f11b";
}
.fa-keyboard-o:before {
content: "\f11c";
}
.fa-flag-o:before {
content: "\f11d";
}
.fa-flag-checkered:before {
content: "\f11e";
}
.fa-terminal:before {
content: "\f120";
}
.fa-code:before {
content: "\f121";
}
.fa-mail-reply-all:before,
.fa-reply-all:before {
content: "\f122";
}
.fa-star-half-empty:before,
.fa-star-half-full:before,
.fa-star-half-o:before {
content: "\f123";
}
.fa-location-arrow:before {
content: "\f124";
}
.fa-crop:before {
content: "\f125";
}
.fa-code-fork:before {
content: "\f126";
}
.fa-unlink:before,
.fa-chain-broken:before {
content: "\f127";
}
.fa-question:before {
content: "\f128";
}
.fa-info:before {
content: "\f129";
}
.fa-exclamation:before {
content: "\f12a";
}
.fa-superscript:before {
content: "\f12b";
}
.fa-subscript:before {
content: "\f12c";
}
.fa-eraser:before {
content: "\f12d";
}
.fa-puzzle-piece:before {
content: "\f12e";
}
.fa-microphone:before {
content: "\f130";
}
.fa-microphone-slash:before {
content: "\f131";
}
.fa-shield:before {
content: "\f132";
}
.fa-calendar-o:before {
content: "\f133";
}
.fa-fire-extinguisher:before {
content: "\f134";
}
.fa-rocket:before {
content: "\f135";
}
.fa-maxcdn:before {
content: "\f136";
}
.fa-chevron-circle-left:before {
content: "\f137";
}
.fa-chevron-circle-right:before {
content: "\f138";
}
.fa-chevron-circle-up:before {
content: "\f139";
}
.fa-chevron-circle-down:before {
content: "\f13a";
}
.fa-html5:before {
content: "\f13b";
}
.fa-css3:before {
content: "\f13c";
}
.fa-anchor:before {
content: "\f13d";
}
.fa-unlock-alt:before {
content: "\f13e";
}
.fa-bullseye:before {
content: "\f140";
}
.fa-ellipsis-h:before {
content: "\f141";
}
.fa-ellipsis-v:before {
content: "\f142";
}
.fa-rss-square:before {
content: "\f143";
}
.fa-play-circle:before {
content: "\f144";
}
.fa-ticket:before {
content: "\f145";
}
.fa-minus-square:before {
content: "\f146";
}
.fa-minus-square-o:before {
content: "\f147";
}
.fa-level-up:before {
content: "\f148";
}
.fa-level-down:before {
content: "\f149";
}
.fa-check-square:before {
content: "\f14a";
}
.fa-pencil-square:before {
content: "\f14b";
}
.fa-external-link-square:before {
content: "\f14c";
}
.fa-share-square:before {
content: "\f14d";
}
.fa-compass:before {
content: "\f14e";
}
.fa-toggle-down:before,
.fa-caret-square-o-down:before {
content: "\f150";
}
.fa-toggle-up:before,
.fa-caret-square-o-up:before {
content: "\f151";
}
.fa-toggle-right:before,
.fa-caret-square-o-right:before {
content: "\f152";
}
.fa-euro:before,
.fa-eur:before {
content: "\f153";
}
.fa-gbp:before {
content: "\f154";
}
.fa-dollar:before,
.fa-usd:before {
content: "\f155";
}
.fa-rupee:before,
.fa-inr:before {
content: "\f156";
}
.fa-cny:before,
.fa-rmb:before,
.fa-yen:before,
.fa-jpy:before {
content: "\f157";
}
.fa-ruble:before,
.fa-rouble:before,
.fa-rub:before {
content: "\f158";
}
.fa-won:before,
.fa-krw:before {
content: "\f159";
}
.fa-bitcoin:before,
.fa-btc:before {
content: "\f15a";
}
.fa-file:before {
content: "\f15b";
}
.fa-file-text:before {
content: "\f15c";
}
.fa-sort-alpha-asc:before {
content: "\f15d";
}
.fa-sort-alpha-desc:before {
content: "\f15e";
}
.fa-sort-amount-asc:before {
content: "\f160";
}
.fa-sort-amount-desc:before {
content: "\f161";
}
.fa-sort-numeric-asc:before {
content: "\f162";
}
.fa-sort-numeric-desc:before {
content: "\f163";
}
.fa-thumbs-up:before {
content: "\f164";
}
.fa-thumbs-down:before {
content: "\f165";
}
.fa-youtube-square:before {
content: "\f166";
}
.fa-youtube:before {
content: "\f167";
}
.fa-xing:before {
content: "\f168";
}
.fa-xing-square:before {
content: "\f169";
}
.fa-youtube-play:before {
content: "\f16a";
}
.fa-dropbox:before {
content: "\f16b";
}
.fa-stack-overflow:before {
content: "\f16c";
}
.fa-instagram:before {
content: "\f16d";
}
.fa-flickr:before {
content: "\f16e";
}
.fa-adn:before {
content: "\f170";
}
.fa-bitbucket:before {
content: "\f171";
}
.fa-bitbucket-square:before {
content: "\f172";
}
.fa-tumblr:before {
content: "\f173";
}
.fa-tumblr-square:before {
content: "\f174";
}
.fa-long-arrow-down:before {
content: "\f175";
}
.fa-long-arrow-up:before {
content: "\f176";
}
.fa-long-arrow-left:before {
content: "\f177";
}
.fa-long-arrow-right:before {
content: "\f178";
}
.fa-apple:before {
content: "\f179";
}
.fa-windows:before {
content: "\f17a";
}
.fa-android:before {
content: "\f17b";
}
.fa-linux:before {
content: "\f17c";
}
.fa-dribbble:before {
content: "\f17d";
}
.fa-skype:before {
content: "\f17e";
}
.fa-foursquare:before {
content: "\f180";
}
.fa-trello:before {
content: "\f181";
}
.fa-female:before {
content: "\f182";
}
.fa-male:before {
content: "\f183";
}
.fa-gittip:before,
.fa-gratipay:before {
content: "\f184";
}
.fa-sun-o:before {
content: "\f185";
}
.fa-moon-o:before {
content: "\f186";
}
.fa-archive:before {
content: "\f187";
}
.fa-bug:before {
content: "\f188";
}
.fa-vk:before {
content: "\f189";
}
.fa-weibo:before {
content: "\f18a";
}
.fa-renren:before {
content: "\f18b";
}
.fa-pagelines:before {
content: "\f18c";
}
.fa-stack-exchange:before {
content: "\f18d";
}
.fa-arrow-circle-o-right:before {
content: "\f18e";
}
.fa-arrow-circle-o-left:before {
content: "\f190";
}
.fa-toggle-left:before,
.fa-caret-square-o-left:before {
content: "\f191";
}
.fa-dot-circle-o:before {
content: "\f192";
}
.fa-wheelchair:before {
content: "\f193";
}
.fa-vimeo-square:before {
content: "\f194";
}
.fa-turkish-lira:before,
.fa-try:before {
content: "\f195";
}
.fa-plus-square-o:before {
content: "\f196";
}
.fa-space-shuttle:before {
content: "\f197";
}
.fa-slack:before {
content: "\f198";
}
.fa-envelope-square:before {
content: "\f199";
}
.fa-wordpress:before {
content: "\f19a";
}
.fa-openid:before {
content: "\f19b";
}
.fa-institution:before,
.fa-bank:before,
.fa-university:before {
content: "\f19c";
}
.fa-mortar-board:before,
.fa-graduation-cap:before {
content: "\f19d";
}
.fa-yahoo:before {
content: "\f19e";
}
.fa-google:before {
content: "\f1a0";
}
.fa-reddit:before {
content: "\f1a1";
}
.fa-reddit-square:before {
content: "\f1a2";
}
.fa-stumbleupon-circle:before {
content: "\f1a3";
}
.fa-stumbleupon:before {
content: "\f1a4";
}
.fa-delicious:before {
content: "\f1a5";
}
.fa-digg:before {
content: "\f1a6";
}
.fa-pied-piper:before {
content: "\f1a7";
}
.fa-pied-piper-alt:before {
content: "\f1a8";
}
.fa-drupal:before {
content: "\f1a9";
}
.fa-joomla:before {
content: "\f1aa";
}
.fa-language:before {
content: "\f1ab";
}
.fa-fax:before {
content: "\f1ac";
}
.fa-building:before {
content: "\f1ad";
}
.fa-child:before {
content: "\f1ae";
}
.fa-paw:before {
content: "\f1b0";
}
.fa-spoon:before {
content: "\f1b1";
}
.fa-cube:before {
content: "\f1b2";
}
.fa-cubes:before {
content: "\f1b3";
}
.fa-behance:before {
content: "\f1b4";
}
.fa-behance-square:before {
content: "\f1b5";
}
.fa-steam:before {
content: "\f1b6";
}
.fa-steam-square:before {
content: "\f1b7";
}
.fa-recycle:before {
content: "\f1b8";
}
.fa-automobile:before,
.fa-car:before {
content: "\f1b9";
}
.fa-cab:before,
.fa-taxi:before {
content: "\f1ba";
}
.fa-tree:before {
content: "\f1bb";
}
.fa-spotify:before {
content: "\f1bc";
}
.fa-deviantart:before {
content: "\f1bd";
}
.fa-soundcloud:before {
content: "\f1be";
}
.fa-database:before {
content: "\f1c0";
}
.fa-file-pdf-o:before {
content: "\f1c1";
}
.fa-file-word-o:before {
content: "\f1c2";
}
.fa-file-excel-o:before {
content: "\f1c3";
}
.fa-file-powerpoint-o:before {
content: "\f1c4";
}
.fa-file-photo-o:before,
.fa-file-picture-o:before,
.fa-file-image-o:before {
content: "\f1c5";
}
.fa-file-zip-o:before,
.fa-file-archive-o:before {
content: "\f1c6";
}
.fa-file-sound-o:before,
.fa-file-audio-o:before {
content: "\f1c7";
}
.fa-file-movie-o:before,
.fa-file-video-o:before {
content: "\f1c8";
}
.fa-file-code-o:before {
content: "\f1c9";
}
.fa-vine:before {
content: "\f1ca";
}
.fa-codepen:before {
content: "\f1cb";
}
.fa-jsfiddle:before {
content: "\f1cc";
}
.fa-life-bouy:before,
.fa-life-buoy:before,
.fa-life-saver:before,
.fa-support:before,
.fa-life-ring:before {
content: "\f1cd";
}
.fa-circle-o-notch:before {
content: "\f1ce";
}
.fa-ra:before,
.fa-rebel:before {
content: "\f1d0";
}
.fa-ge:before,
.fa-empire:before {
content: "\f1d1";
}
.fa-git-square:before {
content: "\f1d2";
}
.fa-git:before {
content: "\f1d3";
}
.fa-y-combinator-square:before,
.fa-yc-square:before,
.fa-hacker-news:before {
content: "\f1d4";
}
.fa-tencent-weibo:before {
content: "\f1d5";
}
.fa-qq:before {
content: "\f1d6";
}
.fa-wechat:before,
.fa-weixin:before {
content: "\f1d7";
}
.fa-send:before,
.fa-paper-plane:before {
content: "\f1d8";
}
.fa-send-o:before,
.fa-paper-plane-o:before {
content: "\f1d9";
}
.fa-history:before {
content: "\f1da";
}
.fa-circle-thin:before {
content: "\f1db";
}
.fa-header:before {
content: "\f1dc";
}
.fa-paragraph:before {
content: "\f1dd";
}
.fa-sliders:before {
content: "\f1de";
}
.fa-share-alt:before {
content: "\f1e0";
}
.fa-share-alt-square:before {
content: "\f1e1";
}
.fa-bomb:before {
content: "\f1e2";
}
.fa-soccer-ball-o:before,
.fa-futbol-o:before {
content: "\f1e3";
}
.fa-tty:before {
content: "\f1e4";
}
.fa-binoculars:before {
content: "\f1e5";
}
.fa-plug:before {
content: "\f1e6";
}
.fa-slideshare:before {
content: "\f1e7";
}
.fa-twitch:before {
content: "\f1e8";
}
.fa-yelp:before {
content: "\f1e9";
}
.fa-newspaper-o:before {
content: "\f1ea";
}
.fa-wifi:before {
content: "\f1eb";
}
.fa-calculator:before {
content: "\f1ec";
}
.fa-paypal:before {
content: "\f1ed";
}
.fa-google-wallet:before {
content: "\f1ee";
}
.fa-cc-visa:before {
content: "\f1f0";
}
.fa-cc-mastercard:before {
content: "\f1f1";
}
.fa-cc-discover:before {
content: "\f1f2";
}
.fa-cc-amex:before {
content: "\f1f3";
}
.fa-cc-paypal:before {
content: "\f1f4";
}
.fa-cc-stripe:before {
content: "\f1f5";
}
.fa-bell-slash:before {
content: "\f1f6";
}
.fa-bell-slash-o:before {
content: "\f1f7";
}
.fa-trash:before {
content: "\f1f8";
}
.fa-copyright:before {
content: "\f1f9";
}
.fa-at:before {
content: "\f1fa";
}
.fa-eyedropper:before {
content: "\f1fb";
}
.fa-paint-brush:before {
content: "\f1fc";
}
.fa-birthday-cake:before {
content: "\f1fd";
}
.fa-area-chart:before {
content: "\f1fe";
}
.fa-pie-chart:before {
content: "\f200";
}
.fa-line-chart:before {
content: "\f201";
}
.fa-lastfm:before {
content: "\f202";
}
.fa-lastfm-square:before {
content: "\f203";
}
.fa-toggle-off:before {
content: "\f204";
}
.fa-toggle-on:before {
content: "\f205";
}
.fa-bicycle:before {
content: "\f206";
}
.fa-bus:before {
content: "\f207";
}
.fa-ioxhost:before {
content: "\f208";
}
.fa-angellist:before {
content: "\f209";
}
.fa-cc:before {
content: "\f20a";
}
.fa-shekel:before,
.fa-sheqel:before,
.fa-ils:before {
content: "\f20b";
}
.fa-meanpath:before {
content: "\f20c";
}
.fa-buysellads:before {
content: "\f20d";
}
.fa-connectdevelop:before {
content: "\f20e";
}
.fa-dashcube:before {
content: "\f210";
}
.fa-forumbee:before {
content: "\f211";
}
.fa-leanpub:before {
content: "\f212";
}
.fa-sellsy:before {
content: "\f213";
}
.fa-shirtsinbulk:before {
content: "\f214";
}
.fa-simplybuilt:before {
content: "\f215";
}
.fa-skyatlas:before {
content: "\f216";
}
.fa-cart-plus:before {
content: "\f217";
}
.fa-cart-arrow-down:before {
content: "\f218";
}
.fa-diamond:before {
content: "\f219";
}
.fa-ship:before {
content: "\f21a";
}
.fa-user-secret:before {
content: "\f21b";
}
.fa-motorcycle:before {
content: "\f21c";
}
.fa-street-view:before {
content: "\f21d";
}
.fa-heartbeat:before {
content: "\f21e";
}
.fa-venus:before {
content: "\f221";
}
.fa-mars:before {
content: "\f222";
}
.fa-mercury:before {
content: "\f223";
}
.fa-intersex:before,
.fa-transgender:before {
content: "\f224";
}
.fa-transgender-alt:before {
content: "\f225";
}
.fa-venus-double:before {
content: "\f226";
}
.fa-mars-double:before {
content: "\f227";
}
.fa-venus-mars:before {
content: "\f228";
}
.fa-mars-stroke:before {
content: "\f229";
}
.fa-mars-stroke-v:before {
content: "\f22a";
}
.fa-mars-stroke-h:before {
content: "\f22b";
}
.fa-neuter:before {
content: "\f22c";
}
.fa-genderless:before {
content: "\f22d";
}
.fa-facebook-official:before {
content: "\f230";
}
.fa-pinterest-p:before {
content: "\f231";
}
.fa-whatsapp:before {
content: "\f232";
}
.fa-server:before {
content: "\f233";
}
.fa-user-plus:before {
content: "\f234";
}
.fa-user-times:before {
content: "\f235";
}
.fa-hotel:before,
.fa-bed:before {
content: "\f236";
}
.fa-viacoin:before {
content: "\f237";
}
.fa-train:before {
content: "\f238";
}
.fa-subway:before {
content: "\f239";
}
.fa-medium:before {
content: "\f23a";
}
.fa-yc:before,
.fa-y-combinator:before {
content: "\f23b";
}
.fa-optin-monster:before {
content: "\f23c";
}
.fa-opencart:before {
content: "\f23d";
}
.fa-expeditedssl:before {
content: "\f23e";
}
.fa-battery-4:before,
.fa-battery-full:before {
content: "\f240";
}
.fa-battery-3:before,
.fa-battery-three-quarters:before {
content: "\f241";
}
.fa-battery-2:before,
.fa-battery-half:before {
content: "\f242";
}
.fa-battery-1:before,
.fa-battery-quarter:before {
content: "\f243";
}
.fa-battery-0:before,
.fa-battery-empty:before {
content: "\f244";
}
.fa-mouse-pointer:before {
content: "\f245";
}
.fa-i-cursor:before {
content: "\f246";
}
.fa-object-group:before {
content: "\f247";
}
.fa-object-ungroup:before {
content: "\f248";
}
.fa-sticky-note:before {
content: "\f249";
}
.fa-sticky-note-o:before {
content: "\f24a";
}
.fa-cc-jcb:before {
content: "\f24b";
}
.fa-cc-diners-club:before {
content: "\f24c";
}
.fa-clone:before {
content: "\f24d";
}
.fa-balance-scale:before {
content: "\f24e";
}
.fa-hourglass-o:before {
content: "\f250";
}
.fa-hourglass-1:before,
.fa-hourglass-start:before {
content: "\f251";
}
.fa-hourglass-2:before,
.fa-hourglass-half:before {
content: "\f252";
}
.fa-hourglass-3:before,
.fa-hourglass-end:before {
content: "\f253";
}
.fa-hourglass:before {
content: "\f254";
}
.fa-hand-grab-o:before,
.fa-hand-rock-o:before {
content: "\f255";
}
.fa-hand-stop-o:before,
.fa-hand-paper-o:before {
content: "\f256";
}
.fa-hand-scissors-o:before {
content: "\f257";
}
.fa-hand-lizard-o:before {
content: "\f258";
}
.fa-hand-spock-o:before {
content: "\f259";
}
.fa-hand-pointer-o:before {
content: "\f25a";
}
.fa-hand-peace-o:before {
content: "\f25b";
}
.fa-trademark:before {
content: "\f25c";
}
.fa-registered:before {
content: "\f25d";
}
.fa-creative-commons:before {
content: "\f25e";
}
.fa-gg:before {
content: "\f260";
}
.fa-gg-circle:before {
content: "\f261";
}
.fa-tripadvisor:before {
content: "\f262";
}
.fa-odnoklassniki:before {
content: "\f263";
}
.fa-odnoklassniki-square:before {
content: "\f264";
}
.fa-get-pocket:before {
content: "\f265";
}
.fa-wikipedia-w:before {
content: "\f266";
}
.fa-safari:before {
content: "\f267";
}
.fa-chrome:before {
content: "\f268";
}
.fa-firefox:before {
content: "\f269";
}
.fa-opera:before {
content: "\f26a";
}
.fa-internet-explorer:before {
content: "\f26b";
}
.fa-tv:before,
.fa-television:before {
content: "\f26c";
}
.fa-contao:before {
content: "\f26d";
}
.fa-500px:before {
content: "\f26e";
}
.fa-amazon:before {
content: "\f270";
}
.fa-calendar-plus-o:before {
content: "\f271";
}
.fa-calendar-minus-o:before {
content: "\f272";
}
.fa-calendar-times-o:before {
content: "\f273";
}
.fa-calendar-check-o:before {
content: "\f274";
}
.fa-industry:before {
content: "\f275";
}
.fa-map-pin:before {
content: "\f276";
}
.fa-map-signs:before {
content: "\f277";
}
.fa-map-o:before {
content: "\f278";
}
.fa-map:before {
content: "\f279";
}
.fa-commenting:before {
content: "\f27a";
}
.fa-commenting-o:before {
content: "\f27b";
}
.fa-houzz:before {
content: "\f27c";
}
.fa-vimeo:before {
content: "\f27d";
}
.fa-black-tie:before {
content: "\f27e";
}
.fa-fonticons:before {
content: "\f280";
}
================================================
FILE: lib/highlight/github.css
================================================
/*
github.com style (c) Vasily Polovnyov
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
-webkit-text-size-adjust: none;
}
.hljs-comment,
.diff .hljs-header,
.hljs-javadoc {
color: #998;
font-style: italic;
}
.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #008080;
}
.hljs-string,
.hljs-tag .hljs-value,
.hljs-phpdoc,
.hljs-dartdoc,
.tex .hljs-formula {
color: #d14;
}
.hljs-title,
.hljs-id,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}
.hljs-list .hljs-keyword,
.hljs-subst {
font-weight: normal;
}
.hljs-class .hljs-title,
.hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rules .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}
.hljs-attribute,
.hljs-variable,
.lisp .hljs-body {
color: #008080;
}
.hljs-regexp {
color: #009926;
}
.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.clojure .hljs-keyword,
.scheme .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}
.hljs-built_in {
color: #0086b3;
}
.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.diff .hljs-change {
background: #0086b3;
}
.hljs-chunk {
color: #aaa;
}
================================================
FILE: lib/highlight/highlight.pack.js
================================================
!function(e){"undefined"!=typeof exports?e(exports):(window.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&").replace(//gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){var n=(e.className+" "+(e.parentNode?e.parentNode.className:"")).split(/\s+/);return n=n.map(function(e){return e.replace(/^lang(uage)?-/,"")}),n.filter(function(e){return N(e)||/no(-?)highlight/.test(e)})[0]}function o(e,n){var t={};for(var r in e)t[r]=e[r];if(n)for(var r in n)t[r]=n[r];return t}function i(e){var n=[];return function r(e,a){for(var o=e.firstChild;o;o=o.nextSibling)3==o.nodeType?a+=o.nodeValue.length:1==o.nodeType&&(n.push({event:"start",offset:a,node:o}),a=r(o,a),t(o).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:o}));return a}(e,0),n}function c(e,r,a){function o(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset"}function c(e){l+=""+t(e)+">"}function u(e){("start"==e.event?i:c)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=o();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){f.reverse().forEach(c);do u(g.splice(0,1)[0]),g=o();while(g==e&&g.length&&g[0].offset==s);f.reverse().forEach(i)}else"start"==g[0].event?f.push(g[0].node):f.pop(),u(g.splice(0,1)[0])}return l+n(a.substr(s))}function u(e){function n(e){return e&&e.source||e}function t(t,r){return RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var c={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");c[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):Object.keys(a.k).forEach(function(e){u(e,a.k[e])}),a.k=c}a.lR=t(a.l||/\b[A-Za-z0-9_]+\b/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function s(e,t,a,o){function i(e,n){for(var t=0;t";return o+=e+'">',o+n+i}function d(){if(!w.k)return n(y);var e="",t=0;w.lR.lastIndex=0;for(var r=w.lR.exec(y);r;){e+=n(y.substr(t,r.index-t));var a=g(w,r);a?(B+=a[1],e+=p(a[0],n(r[0]))):e+=n(r[0]),t=w.lR.lastIndex,r=w.lR.exec(y)}return e+n(y.substr(t))}function h(){if(w.sL&&!R[w.sL])return n(y);var e=w.sL?s(w.sL,y,!0,L[w.sL]):l(y);return w.r>0&&(B+=e.r),"continuous"==w.subLanguageMode&&(L[w.sL]=e.top),p(e.language,e.value,!1,!0)}function v(){return void 0!==w.sL?h():d()}function b(e,t){var r=e.cN?p(e.cN,"",!0):"";e.rB?(M+=r,y=""):e.eB?(M+=n(t)+r,y=""):(M+=r,y=t),w=Object.create(e,{parent:{value:w}})}function m(e,t){if(y+=e,void 0===t)return M+=v(),0;var r=i(t,w);if(r)return M+=v(),b(r,t),r.rB?0:t.length;var a=c(w,t);if(a){var o=w;o.rE||o.eE||(y+=t),M+=v();do w.cN&&(M+=""),B+=w.r,w=w.parent;while(w!=a.parent);return o.eE&&(M+=n(t)),y="",a.starts&&b(a.starts,""),o.rE?0:t.length}if(f(t,w))throw new Error('Illegal lexeme "'+t+'" for mode "'+(w.cN||"")+'"');return y+=t,t.length||1}var x=N(e);if(!x)throw new Error('Unknown language: "'+e+'"');u(x);for(var w=o||x,L={},M="",k=w;k!=x;k=k.parent)k.cN&&(M=p(k.cN,"",!0)+M);var y="",B=0;try{for(var C,j,I=0;;){if(w.t.lastIndex=I,C=w.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}m(t.substr(I));for(var k=w;k.parent;k=k.parent)k.cN&&(M+="");return{r:B,value:M,language:e,top:w}}catch(A){if(-1!=A.message.indexOf("Illegal"))return{r:0,value:n(t)};throw A}}function l(e,t){t=t||E.languages||Object.keys(R);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(N(n)){var t=s(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function f(e){return E.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,E.tabReplace)})),E.useBR&&(e=e.replace(/\n/g," ")),e}function g(e,n,t){var r=n?x[n]:t,a=[e.trim()];return e.match(/(\s|^)hljs(\s|$)/)||a.push("hljs"),r&&a.push(r),a.join(" ").trim()}function p(e){var n=a(e);if(!/no(-?)highlight/.test(n)){var t;E.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/ /g,"\n")):t=e;var r=t.textContent,o=n?s(n,r,!0):l(r),u=i(t);if(u.length){var p=document.createElementNS("http://www.w3.org/1999/xhtml","div");p.innerHTML=o.value,o.value=c(u,i(p),r)}o.value=f(o.value),e.innerHTML=o.value,e.className=g(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){E=o(E,e)}function h(){if(!h.called){h.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",h,!1),addEventListener("load",h,!1)}function b(n,t){var r=R[n]=t(e);r.aliases&&r.aliases.forEach(function(e){x[e]=n})}function m(){return Object.keys(R)}function N(e){return R[e]||R[x[e]]}var E={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},R={},x={};return e.highlight=s,e.highlightAuto=l,e.fixMarkup=f,e.highlightBlock=p,e.configure=d,e.initHighlighting=h,e.initHighlightingOnLoad=v,e.registerLanguage=b,e.listLanguages=m,e.getLanguage=N,e.inherit=o,e.IR="[a-zA-Z][a-zA-Z0-9_]*",e.UIR="[a-zA-Z_][a-zA-Z0-9_]*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},e.CLCM={cN:"comment",b:"//",e:"$",c:[e.PWM]},e.CBCM={cN:"comment",b:"/\\*",e:"\\*/",c:[e.PWM]},e.HCM={cN:"comment",b:"#",e:"$",c:[e.PWM]},e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",a={cN:"function",b:c+"\\(",rB:!0,eE:!0,e:"\\("};return{cI:!0,i:"[=/|']",c:[e.CBCM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{cN:"at_rule",b:"@",e:"[{;]",c:[{cN:"keyword",b:/\S+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[a,e.ASM,e.QSM,e.CSSNM]}]},{cN:"tag",b:c,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[e.CBCM,{cN:"rule",b:"[^\\s]",rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:!0,i:"[^\\s]",starts:{cN:"value",eW:!0,eE:!0,c:[a,e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"hexcolor",b:"#[0-9A-Fa-f]+"},{cN:"important",b:"!important"}]}}]}]}]}});hljs.registerLanguage("xml",function(){var t="[A-Za-z0-9\\._:-]+",e={b:/<\?(php)?(?!\w)/,e:/\?>/,sL:"php",subLanguageMode:"continuous"},c={eW:!0,i:/,r:0,c:[e,{cN:"attribute",b:t,r:0},{b:"=",r:0,c:[{cN:"value",c:[e],v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s\/>]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xsl","plist"],cI:!0,c:[{cN:"doctype",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"",rE:!0,sL:"css"}},{cN:"tag",b:"",rE:!0,sL:"javascript"}},e,{cN:"pi",b:/<\?\w+/,e:/\?>/,r:10},{cN:"tag",b:"?",e:"/?>",c:[{cN:"title",b:/[^ \/><\n\t]+/,r:0},c]}]}});hljs.registerLanguage("javascript",function(r){return{aliases:["js"],k:{keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document"},c:[{cN:"pi",r:10,v:[{b:/^\s*('|")use strict('|")/},{b:/^\s*('|")use asm('|")/}]},r.ASM,r.QSM,r.CLCM,r.CBCM,r.CNM,{b:"("+r.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[r.CLCM,r.CBCM,r.RM,{b:/,e:/>;/,r:0,sL:"xml"}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[r.inherit(r.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,c:[r.CLCM,r.CBCM],i:/["'\(]/}],i:/\[|%/},{b:/\$[(.]/},{b:"\\."+r.IR,r:0}]}});
================================================
FILE: lib/jquery.ui.touch-punch.js
================================================
/*!
* jQuery UI Touch Punch 0.2.3
*
* Copyright 2011–2014, Dave Furfero
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Depends:
* jquery.ui.widget.js
* jquery.ui.mouse.js
*/
(function ($) {
// Detect touch support
$.support.touch = 'ontouchend' in document;
// Ignore browsers without touch support
if (!$.support.touch) {
return;
}
var mouseProto = $.ui.mouse.prototype,
_mouseInit = mouseProto._mouseInit,
_mouseDestroy = mouseProto._mouseDestroy,
touchHandled;
/**
* Simulate a mouse event based on a corresponding touch event
* @param {Object} event A touch event
* @param {String} simulatedType The corresponding mouse event
*/
function simulateMouseEvent (event, simulatedType) {
// Ignore multi-touch events
if (event.originalEvent.touches.length > 1) {
return;
}
event.preventDefault();
var touch = event.originalEvent.changedTouches[0],
simulatedEvent = document.createEvent('MouseEvents');
// Initialize the simulated mouse event using the touch event's coordinates
simulatedEvent.initMouseEvent(
simulatedType, // type
true, // bubbles
true, // cancelable
window, // view
1, // detail
touch.screenX, // screenX
touch.screenY, // screenY
touch.clientX, // clientX
touch.clientY, // clientY
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey
0, // button
null // relatedTarget
);
// Dispatch the simulated event to the target element
event.target.dispatchEvent(simulatedEvent);
}
/**
* Handle the jQuery UI widget's touchstart events
* @param {Object} event The widget element's touchstart event
*/
mouseProto._touchStart = function (event) {
var self = this;
// Ignore the event if another widget is already being handled
if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
return;
}
// Set the flag to prevent other widgets from inheriting the touch event
touchHandled = true;
// Track movement to determine if interaction was a click
self._touchMoved = false;
// Simulate the mouseover event
simulateMouseEvent(event, 'mouseover');
// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');
// Simulate the mousedown event
simulateMouseEvent(event, 'mousedown');
};
/**
* Handle the jQuery UI widget's touchmove events
* @param {Object} event The document's touchmove event
*/
mouseProto._touchMove = function (event) {
// Ignore event if not handled
if (!touchHandled) {
return;
}
// Interaction was not a click
this._touchMoved = true;
// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');
};
/**
* Handle the jQuery UI widget's touchend events
* @param {Object} event The document's touchend event
*/
mouseProto._touchEnd = function (event) {
// Ignore event if not handled
if (!touchHandled) {
return;
}
// Simulate the mouseup event
simulateMouseEvent(event, 'mouseup');
// Simulate the mouseout event
simulateMouseEvent(event, 'mouseout');
// If the touch interaction did not move, it should trigger a click
if (!this._touchMoved) {
// Simulate the click event
simulateMouseEvent(event, 'click');
}
// Unset the flag to allow other widgets to inherit the touch event
touchHandled = false;
};
/**
* A duck punch of the $.ui.mouse _mouseInit method to support touch events.
* This method extends the widget with bound touch event handlers that
* translate touch events to mouse events and pass them to the widget's
* original mouse event handling methods.
*/
mouseProto._mouseInit = function () {
var self = this;
// Delegate the touch handlers to the widget's element
self.element.bind({
touchstart: $.proxy(self, '_touchStart'),
touchmove: $.proxy(self, '_touchMove'),
touchend: $.proxy(self, '_touchEnd')
});
// Call the original $.ui.mouse init method
_mouseInit.call(self);
};
/**
* Remove the touch event handlers
*/
mouseProto._mouseDestroy = function () {
var self = this;
// Delegate the touch handlers to the widget's element
self.element.unbind({
touchstart: $.proxy(self, '_touchStart'),
touchmove: $.proxy(self, '_touchMove'),
touchend: $.proxy(self, '_touchEnd')
});
// Call the original $.ui.mouse destroy method
_mouseDestroy.call(self);
};
})(jQuery);
================================================
FILE: package.json
================================================
{
"name": "lobipanel",
"version": "1.0.0",
"description": "jQuery plugin for bootstrap panels. It extends panels with several common and useful functions.",
"repository": {
"type": "git",
"url": "https://github.com/arboshiki/lobipanel"
},
"keywords": [
"jQuery plugin",
"bootstrap",
"floating panels",
"minimizable",
"bootstrap panels",
"ajax loading"
],
"author": {
"name": "Zura Sekhniashvili",
"email": "zurasekhniashvili@gmail.com",
"url": "https://github.com/arboshiki"
},
"license": "MIT",
"devDependencies": {
"gulp": "^3.9.1",
"gulp-clean-css": "^3.9.0",
"gulp-concat": "^2.6.1",
"gulp-copy": "^1.0.1",
"gulp-cssnano": "^2.1.2",
"gulp-less": "^3.3.2",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^3.0.0",
"path": "^0.12.7"
},
"dependencies": {
"bootstrap": "^3.3.7",
"jquery": "^3.2.1"
}
}