<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<!DOCTYPE html><html lang='en' class=''>
<head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/acronamy/pen/jqzmRM" />
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css'><link rel='stylesheet prefetch' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'>
<style class="cp-pen-styles">body {
overflow: hidden;
width: 100%;
min-height: 100vh;
background-color: #f1f1f1;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAMFBMVEU0mNsyl9tRpeAzmNtTpuA7m9xFn91Jot5And1Cnt1pseRKod5bquFhreJWqOBjruIMsMgkAAACaUlEQVR4nO3d227bMAwAUN9yay79/79d2nSiHzS4zdCtoo6eiECMcSDIJkrVGYb3MS7j8DHGaSOcq+Gw+rR82Xw8l3B3KBNW4RBz96e5pJ1qaXGJ8bD7PXfcH0vabh9zV2mEhISEhH8tHB9jGcuYqmFMmA+1cFyFkXa/ZgnP1bSYezqW8LifK2mrueddCfcR7iJtKJcYlsd4WcrYCKevhJdrCW+vMeG1Mne5XLbSYu71NpWwmhaXaGoNI+0ra5h/HxISEhISEn5z1TZsP/Frj+4nn/jzc1Xb9BgvUxlb4b142gpLdLuWT+/lVyWM732r2kpYTYtLvFVtJYy01dWWktbUGqraer3TEBISEhKq2lRtqrYM+5CQkJCQkDBXh/S5J/7n2qL/pkM6baT9oUNaS9MhTbUPCQkJCQkJVW2qtgjbXcP8+5CQkJCQkDBXh/S5J/4n26I6pD94DfPvQ0JCQkJCQlWbqi3Cdtcw/z4kJCQkJCTUIdUhjbDdNcy/DwkJCQkJCVVtqrYI213D/PuQkJCQkJBQhzRVh3Rqv0P63Ntb8u9DQkJCQkLCXFXbt76vbfkRVVuUaknPtanaer3TEBISEhL21SH1i1btd0hVbb3eaQgJCQkJ+6ra2j/XtpWmalO1ERISEhIS6pDW2qKNnWtL0CH13wi93mkICQkJCVVtzrW1VbX5W1uvdxpCQkJCwr46pM616ZBm3YeEhISEhISqNlVbhO2uYf59SEhISEhIqEOa6lxbgve1OdfW652GkJCQkLCvqs1bdlVtWfchISEhISFhrg5p+2/+8ItWqrZe7zSEhIT/XfgLXg8P0fI5wpkAAAAASUVORK5CYII=");
}
body.dragging {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: move;
}
.panel {
z-index: 1;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
min-width: 200px;
min-height: 40px;
margin: auto;
background-color: #dedede;
border: 1px solid #9c9c9c;
position: absolute;
margin: 0;
display: inline-block;
box-shadow: 0px 0px 18px 0px rgba(0,0,0,0.35);
transition: box-shadow 0.2s;
}
.panel.minimized {
box-shadow: initial !important;
border-radius: 0;
}
.panel.minimized .window-ctrl {
opacity: 0;
pointer-events: none;
width: 1px;
}
.panel.minimized .panel-heading {
border-radius: 0;
}
.panel.minimized .panel-heading .window-title {
position: absolute;
top: 0;
left: 0;
right: 0;
margin-top: 0.4em;
text-align: center;
color: #999;
font-size: 1.2em;
text-shadow: -1px -1px #fff;
}
.panel.focus {
box-shadow: 0px 0px 30px 0px rgba(0,0,0,0.45);
}
.panel .panel-body {
padding: 15px 3px;
}
.panel .inner {
z-index: 0;
padding-top: 40px;
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
}
.panel .panel-heading {
border-bottom: 1px solid #9c9c9c;
background-color: #dedede;
color: #222;
position: absolute;
width: 100%;
z-index: 1;
box-shadow: inset 0 1px 0 0 #fefefe, inset 1px 0 0 #f2f2f2, inset -1px 0 0 #f2f2f2, inset 0 -1px 0 0 #e6e6e6;
}
.panel .panel-heading .window-ctrl .glyphicon {
font-weight: 100;
color: #909090;
padding-left: 10px;
padding-right: ;
transform: scale(0.8);
}
.panel .panel-heading .window-ctrl .glyphicon:first-child {
padding-left: 0;
}
.panel .panel-heading .window-ctrl .glyphicon:last-child {
padding-right: 0;
}
.panel .list-group-item {
background-color: #fafafa;
border: #9c9c9c 1px solid;
color: #333;
border-radius: 0;
border-top: 0;
}
.panel .list-group-item:nth-child(even) {
background-color: #f1f1f1;
}
.panel .list-group-item:first-child {
border-top: #9c9c9c 1px solid;
}
.panel .frame {
background-color: rgba(255,255,255,0);
position: absolute;
}
.panel .frame.t {
top: -5px;
cursor: s-resize;
}
.panel .frame.b {
bottom: -5px;
cursor: n-resize;
}
.panel .frame.t,
.panel .frame.b {
width: 100%;
height: 10px;
left: -5px;
}
.panel .frame.l {
left: -5px;
}
.panel .frame.r {
right: -5px;
}
.panel .frame.l,
.panel .frame.r {
cursor: w-resize;
height: 100%;
width: 10px;
top: -5px;
}
.panel .frame.tl,
.panel .frame.tr,
.panel .frame.bl,
.panel .frame.br {
width: 10px;
height: 10px;
background-color: rgba(255,255,255,0);
z-index: 2;
}
.panel .frame.tl {
top: -5px;
left: -5px;
cursor: se-resize;
}
.panel .frame.tr {
top: -5px;
right: -5px;
cursor: sw-resize;
}
.panel .frame.bl {
bottom: -5px;
left: -5px;
cursor: ne-resize;
}
.panel .frame.br {
bottom: -5px;
right: -5px;
cursor: nw-resize;
}
.snap {
background-color: transparntify(#00f, 2%);
position: absolute;
}
.tray {
height: 40px;
width: 100%;
position: absolute;
background-color: #dedede;
bottom: 0;
z-index: 0;
box-shadow: inset 0 1px 0 0 #fefefe, inset 1px 0 0 #f2f2f2, inset -1px 0 0 #f2f2f2, inset 0 -1px 0 0 #e6e6e6;
border-top: 1px solid #9c9c9c;
}
</style></head><body>
<div class="snap"></div>
<div class="panel panel-dark" data-drag="true" data-title="Foo window">
<div class="panel-heading">
<div class="window-ctrl small"><span class="dismiss glyphicon glyphicon-remove"></span><span class="max glyphicon glyphicon-stop"></span><span class="min glyphicon glyphicon-minus"></span></div><span class="window-title hide"></span>
</div>
<div class="inner">
<div class="panel-body">
<ul class="list-group">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
</ul>
</div>
</div>
</div>
<div class="panel panel-dark" data-drag="true" data-top="150" data-left="150" data-title="Some window">
<div class="panel-heading">
<div class="window-ctrl small"><span class="dismiss glyphicon glyphicon-remove"></span><span class="max glyphicon glyphicon-stop"></span><span class="min glyphicon glyphicon-minus"></span></div><span class="window-title hide"></span>
</div>
<div class="inner">
<div class="panel-body">
<ul class="list-group">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
</ul>
</div>
</div>
</div>
<div class="tray"></div>
<!--# Credits--><a style="font-size:1px!important; pointer-events:none; visibility: hidden; display:block; width:0; overflow:hidden; position:absolute; bottom:0; left:0; z-index:-9999; color:rgba(255,255,255,0)!important" title="Acro Design (Acronamy) Performing magic tricks with Websites, S.E.O and Graphics for Local businesses in Bristol, Bath and the surrounding areas." href="https://www.facebook.com/Acronamy.design/">Acro Design (Acronamy) Facebook</a><a style="font-size:1px!important; pointer-events:none; visibility: hidden; display:block; width:0; overflow:hidden; position:absolute; bottom:0; left:0; z-index:-9999; color:rgba(255,255,255,0)!important" title="Acro Design (Acronamy) Performing magic tricks with Websites, S.E.O and Graphics for Local businesses in Bristol, Bath and the surrounding areas." href="https://twitter.com/Acronamy_design">Acro Design (Acronamy) Twitter</a><a style="font-size:1px!important; pointer-events:none; visibility: hidden; display:block; width:0; overflow:hidden; position:absolute; bottom:0; left:0; z-index:-9999; color:rgba(255,255,255,0)!important" title="Acro Design (Acronamy) Performing magic tricks with Websites, S.E.O and Graphics for Local businesses in Bristol, Bath and the surrounding areas." href="http://www.acronamy.com">Acro Design (Acronamy) Performing magic tricks with Websites, S.E.O and Graphics for Local businesses in Bristol, Bath and the surrounding areas.</a>
<script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js'></script>
<script >'use strict';
//## Vars
var Gui = {},
frame = ['tl', 'tr', 'bl', 'br', 'l', 't', 'r', 'b'],
minimizedSize = 200,
taskbarSize = 40,
snapTolerence = 10;
Gui.tracker = [];
Gui.trackerCount = 0, Gui.tray = [];
var selector = '.panel[data-drag="true"]',
el = {
panel: $(selector),
body: $('body'),
all: $('*'),
heading: $(selector).find('.panel-heading'),
snap: $('.snap')
};
//## Register
Gui.register = function (spec) {
Gui.trackerCount++;
var id = '0x' + Gui.trackerCount;
$(spec.element).find('.window-title').text($(spec.element).data('title'));
Gui.tracker.push({
id: id,
title: spec.element.data('title'),
state: 'natural'
});
spec.element.attr('data-id', id);
frame.forEach(function (item) {
spec.element.append('<div class="' + item + ' frame"></div>');
});
};
Gui.getFrame = function (spec) {
var getId = spec.id,
current = Gui.tracker.filter(function (item) {
return item.id === getId;
})[0];
return current;
};
Gui.dimention = function (spec) {
var win = {
w: $(window).width(),
h: $(window).height()
};
var current = Gui.getFrame({ id: $(spec.element).data('id') });
current.position = {
left: spec.left,
right: win.w - spec.width - spec.left,
top: spec.top,
bottom: win.h - spec.height - spec.top,
get width() {
return win.w - (this.left + this.right);
},
get height() {
return win.h - (this.top + this.bottom);
}
};
var styleObj = {
left: current.position.left,
right: current.position.right,
top: current.position.top,
bottom: current.position.bottom
};
//##Init
$(spec.element).css(styleObj);
$(window).resize(function () {
if (!current.state === 'minimized') {
var _win = {
w: $(window).width(),
h: $(window).height()
};
styleObj.right = _win.w - spec.width - spec.left;
styleObj.botton = _win.h - spec.height - spec.bottom;
$(spec.element).css(styleObj);
}
});
};
//##Resizing
Gui.clearMousemove = function () {
$('body').removeClass('dragging');
$(document).off('mousemove');
};
Gui.contextMenu = function (spec) {
var self = spec.element;
if (!!self.attr('data-context')) {
try {
var menu = JSON.parse(self.data('data-context'));
} catch (err) {
if (err) return false;
}
}
};
//loop each
el.panel.each(function () {
Gui.register({
element: $(this)
});
Gui.dimention({ //Starting from
element: $(this),
width: 300,
height: $(this).find('.inner').outerHeight(),
left: $(this).data('left') || 100,
top: $(this).data('left') || 100
});
Gui.contextMenu({ element: $(this) });
});
//Move
el.heading.mousedown(function (mouse_e) {
var innerOffset = {
x: mouse_e.offsetX,
y: mouse_e.offsetY
},
self = $(this).closest(selector),
selfData = Gui.getFrame({ id: self.data('id') });
if (selfData.state === 'natural') {
$('body').addClass('dragging');
$(document).mousemove(function (move_e) {
Gui.dimention({
element: self, //may need changing
width: selfData.position.width,
height: selfData.position.height,
left: move_e.clientX - innerOffset.x,
top: move_e.clientY - innerOffset.y
});
//snapping
if (move_e.clientX <= snapTolerence) {
selfData.snap = 'left';
} else if (move_e.clientX >= $(window).width() - snapTolerence) {
selfData.snap = 'right';
} else if (move_e.clientY <= snapTolerence) {
selfData.snap = 'top';
} else {
selfData.snap = false;
}
});
} else if (selfData.state === 'minimize') {
Gui.minimize({
element: self,
data: selfData
}).restore;
}
}).mouseup(function (e) {
var self = $(e.target).closest(el.panel),
selfData = Gui.getFrame({ id: self.data('id') });
var snap = selfData.snap;
//COMIT TO SNAP
if (snap === 'left') {} else if (snap === 'right') {} else if (snap === 'top') {
console.log('foo');
Gui.maximize({ element: self }).expand;
}
Gui.clearMousemove();
});
Gui.grappleTest = function (conf) {
if (conf.event.target.className.split(' ').indexOf(conf.direction) >= 0) {
conf.cb();
} else {
return false;
}
};
$('.l, .r, .t, .b, .tl, .tr, .bl, .br').mousedown(function (mouse_e) {
$('body').addClass('dragging');
var innerOffset = {
x: mouse_e.offsetX,
y: mouse_e.offsetY
},
self = $(this).closest(selector),
selfData = Gui.getFrame({ id: self.data('id') });
$(document).mousemove(function (move_e) {
Gui.grappleTest({
event: mouse_e,
direction: 'l',
cb: function cb() {
selfData.position.left = move_e.clientX;
self.css({ left: selfData.position.left });
}
});
Gui.grappleTest({
event: mouse_e,
direction: 't',
cb: function cb() {
selfData.position.top = move_e.clientY;
self.css({ top: selfData.position.top });
}
});
Gui.grappleTest({
event: mouse_e,
direction: 'r',
cb: function cb() {
selfData.position.right = $(window).width() - move_e.clientX;
self.css({ right: selfData.position.right });
}
});
Gui.grappleTest({
event: mouse_e,
direction: 'b',
cb: function cb() {
selfData.position.bottom = $(window).height() - move_e.clientY;
self.css({ bottom: selfData.position.bottom });
}
});
Gui.grappleTest({
event: mouse_e,
direction: 'tl',
cb: function cb() {
selfData.position.left = move_e.clientX;
selfData.position.top = move_e.clientY;
self.css({
top: selfData.position.top,
left: selfData.position.left
});
}
});
Gui.grappleTest({
event: mouse_e,
direction: 'tr',
cb: function cb() {
selfData.position.right = $(window).width() - move_e.clientX;
selfData.position.top = move_e.clientY;
self.css({
top: selfData.position.top,
right: selfData.position.right
});
}
});
Gui.grappleTest({
event: mouse_e,
direction: 'bl',
cb: function cb() {
selfData.position.left = move_e.clientX;
selfData.position.bottom = $(window).height() - move_e.clientY;
self.css({
left: selfData.position.left,
bottom: selfData.position.bottom
});
}
});
Gui.grappleTest({
event: mouse_e,
direction: 'br',
cb: function cb() {
selfData.position.right = $(window).width() - move_e.clientX;
selfData.position.bottom = $(window).height() - move_e.clientY;
self.css({
right: selfData.position.right,
bottom: selfData.position.bottom
});
}
});
});
}).mouseup(Gui.clearMousemove);
//focus
el.panel.mousedown(function () {
$(this).css({ zIndex: 10 }).addClass('focus').removeClass('unfocus').siblings(selector).css({ zIndex: 9 }).addClass('unfocus').removeClass('focus');
});
Gui.close = function (spec) {
spec.element.remove();
};
Gui.restore = function (spec) {
TweenMax.to(spec.element, .1, {
left: spec.data.position.left,
right: spec.data.position.right,
top: spec.data.position.top,
bottom: spec.data.position.bottom
});
spec.data.state = 'natural';
$(spec.element).find('.window-title').addClass('hide');
};
Gui.maximize = function (spec) {
return {
get expand() {
TweenMax.to(spec.element, .1, {
left: 0,
right: 0,
top: 0,
bottom: 40,
maxWidth: 'initial'
});
spec.data.state = 'maximize';
},
get restore() {
Gui.restore(spec);
}
};
};
Gui.minimize = function (spec) {
return {
get colapse() {
Gui.tray.push(spec.data);
TweenMax.to(spec.element, .1, {
left: minimizedSize * (Gui.tray.length - 1),
right: $(window).width(),
top: $(window).height() - 40,
bottom: 0
});
//heading
$(spec.element).find('.window-title').removeClass('hide');
spec.data.state = 'minimize';
$('.minimized').css({ maxWidth: minimizedSize + 'px' });
spec.element.addClass('minimized');
},
get restore() {
Gui.tray.shift();
Gui.restore(spec);
spec.data.state = 'natural';
spec.element.removeClass('minimized');
}
};
};
$('.window-ctrl > span').click(function (e) {
var self = $(this).closest(el.panel),
current = Gui.getFrame({ id: self.data('id') }),
requirements = {
element: self,
data: current
};
if ($(this).hasClass('dismiss')) {
Gui.close({ element: self });
} else if ($(this).hasClass('min')) {
Gui.minimize(requirements).colapse;
} else if ($(this).hasClass('max')) {
if (current.state === 'natural') {
Gui.maximize(requirements).expand;
} else if (current.state === 'maximize') {
Gui.maximize(requirements).restore;
}
}
});
//# sourceURL=pen.js
</script>
</body></html>