<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>KSL Assets Menu Demo</title>
<meta name="description" content="KSL Assets Menu Demo" />
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" type="text/css" />
<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="ksl-assets container">
<div class="inner">
<div class="header">
<div class="inner">
<i class="fa fa-bars fa-2x menu-left-toggle"></i>
<h1>Menu Demo</h1>
<i class="fa fa-bars fa-2x menu-right-toggle"></i>
</div>
</div>
<div class="content">
<div class="header">
<div class="reserved"></div>
</div>
<div class="ksl-assets menu menu-left">
<div class="head">
Menu
</div>
<div class="body">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
<li>Item 16</li>
<li>Item 17</li>
<li>Item 18</li>
<li>Item 19</li>
<li>Item 20</li>
</ul>
</div>
</div>
<div class="ksl-assets menu menu-right">
<div class="inner">
<div class="head">
Right Menu
</div>
<div class="body">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
<li>Item 16</li>
<li>Item 17</li>
<li>Item 18</li>
<li>Item 19</li>
<li>Item 20</li>
</ul>
</div>
</div>
</div>
<h3>Requirements</h3>
<ul class="fa-ul issues">
<li x><i class="fa-li fa"></i>Push the page over.</li>
<li x><i class="fa-li fa"></i>Smooth animation.</li>
<li x><i class="fa-li fa"></i>Disable vertical page scrolling when menu open.</li>
<li x><i class="fa-li fa"></i>Disable horizontal page scrolling when menu open.</li>
<li x><i class="fa-li fa"></i>Maintain page scroll position through opening and closing.</li>
<li x><i class="fa-li fa"></i>Must play well with fixed position elements on screen.</li>
<li x><i class="fa-li fa"></i>Reset scroll within the menu to top when opening a second time.</li>
<li x><i class="fa-li fa"></i>Click outside to close (clicks should not trigger anything on the page, just close the menu).</li>
<li x><i class="fa-li fa"></i>Menu scrolls independent of page.</li>
<li x><i class="fa-li fa"></i>Smooth scrolling.</li>
<li x><i class="fa-li fa"></i>Needs to be easy to pop back into page layout.</li>
<li x><i class="fa-li fa"></i>Content should not get smooshed when menu is open.</li>
<li x><i class="fa-li fa"></i>Right menu using modifier class.</li>
<li x="?"><i class="fa-li fa"></i>Must meet requirements in Firefox, Chrome, Safari, Mobile Safari, IE10, IE11, Android.</li>
</ul>
<h3>Issues</h3>
<ul class="fa-ul issues">
<li x><i class="fa-li fa"></i>Mobile Safari: Address and tool bar in the way.</li>
<li x><i class="fa-li fa"></i>Mobile Safari: Landscape pushes page up.</li>
<li x><i class="fa-li fa"></i>IE8: Cannot scroll page after menu close.</li>
<li x><i class="fa-li fa"></i>IE10, IE8: Click outside to close not working.</li>
<li x><i class="fa-li fa"></i>Mobile Safari: Minor flicker. Verdict was "Good enough".</li>
<li x><i class="fa-li fa"></i>Mobile Safari: Elements disappear when scrolling. Caused by `-webkit-overflow-scrolling: auto`.</li>
<li x><i class="fa-li fa"></i>IE10, IE11: Reserved space for menu scroll bar between menu inner and rest of page rather than under the actual scroll bar.</li>
<li x><i class="fa-li fa"></i>Mobile Safari: White background showing when you scroll past top or bottom of menu.</li>
<li x><i class="fa-li fa"></i>Firefox: Css transition on page not working, while others on menu and header are. Odd.</li>
<li><i class="fa-li fa"></i>Android 2.3 (released in 2010): Unable to scroll menu.</li>
</ul>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus congue porta felis non fringilla. Etiam nisl turpis, volutpat ut ipsum id, semper ornare velit. Aliquam non lectus rhoncus, laoreet nisl eget, elementum nisi. Nullam diam ligula, faucibus quis orci rhoncus, blandit facilisis odio. Curabitur iaculis convallis felis ut iaculis. Etiam ut orci ullamcorper ligula elementum elementum vel at odio. Pellentesque feugiat lorem leo, non interdum nisl tristique nec. Suspendisse iaculis urna non convallis
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus congue porta felis non fringilla. Etiam nisl turpis, volutpat ut ipsum id, semper ornare velit. Aliquam non lectus rhoncus, laoreet nisl eget, elementum nisi. Nullam diam ligula, faucibus quis orci rhoncus, blandit facilisis odio. Curabitur iaculis convallis felis ut iaculis. Etiam ut orci ullamcorper ligula elementum elementum vel at odio. Pellentesque feugiat lorem leo, non interdum nisl tristique nec. Suspendisse iaculis urna non convallis
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus congue porta felis non fringilla. Etiam nisl turpis, volutpat ut ipsum id, semper ornare velit. Aliquam non lectus rhoncus, laoreet nisl eget, elementum nisi. Nullam diam ligula, faucibus quis orci rhoncus, blandit facilisis odio. Curabitur iaculis convallis felis ut iaculis. Etiam ut orci ullamcorper ligula elementum elementum vel at odio. Pellentesque feugiat lorem leo, non interdum nisl tristique nec. Suspendisse iaculis urna non convallis
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus congue porta felis non fringilla. Etiam nisl turpis, volutpat ut ipsum id, semper ornare velit. Aliquam non lectus rhoncus, laoreet nisl eget, elementum nisi. Nullam diam ligula, faucibus quis orci rhoncus, blandit facilisis odio. Curabitur iaculis convallis felis ut iaculis. Etiam ut orci ullamcorper ligula elementum elementum vel at odio. Pellentesque feugiat lorem leo, non interdum nisl tristique nec. Suspendisse iaculis urna non convallis
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus congue porta felis non fringilla. Etiam nisl turpis, volutpat ut ipsum id, semper ornare velit. Aliquam non lectus rhoncus, laoreet nisl eget, elementum nisi. Nullam diam ligula, faucibus quis orci rhoncus, blandit facilisis odio. Curabitur iaculis convallis felis ut iaculis. Etiam ut orci ullamcorper ligula elementum elementum vel at odio. Pellentesque feugiat lorem leo, non interdum nisl tristique nec. Suspendisse iaculis urna non convallis
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus congue porta felis non fringilla. Etiam nisl turpis, volutpat ut ipsum id, semper ornare velit. Aliquam non lectus rhoncus, laoreet nisl eget, elementum nisi. Nullam diam ligula, faucibus quis orci rhoncus, blandit facilisis odio. Curabitur iaculis convallis felis ut iaculis. Etiam ut orci ullamcorper ligula elementum elementum vel at odio. Pellentesque feugiat lorem leo, non interdum nisl tristique nec. Suspendisse iaculis urna non convallis
</p>
<p><a href="http://cdn.ebaumsworld.com/mediaFiles/picture/664379/80470643.gif">Fin</a></p>
</div><!-- /.content -->
</div><!-- /.inner -->
</div><!-- /.container -->
<script>
$(function () {
ksl.assets.menu($('.menu-left')).addToggles(
$('.menu-left .head'),
$('.header .menu-left-toggle')
);
ksl.assets.menu($('.menu-right')).addToggles(
$('.menu-right .head'),
$('.header .menu-right-toggle')
);
});
</script>
<style>
/* decorative styles, irrelevant to menu */
*, *:before, *:after {
box-sizing: inherit;
box-sizing: inherit;
box-sizing: inherit;
}
html {
box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
body > .container {
padding: 0;
}
body > .container > .inner > .content {
padding: 0 15px;
}
.header > .inner {
position: absolute;
top: 0;
left: 0;
z-index: 100;
background-color: #0b162f;
color: #fff;
width: 100%;
padding: 0 20px;
height: 40px;
}
.header > .reserved {
height: 40px;
}
.header h1 {
display: inline-block;
font-size: 2em;
margin: 0;
margin-left: 15px;
line-height: 40px;
white-space: nowrap;
}
.menu {
background-color: #333;
color: #fff;
}
.menu .head {
background-color: #0b162f;
padding: 0 20px;
line-height: 40px;
font-size: 2em;
}
.menu .body {
padding-bottom: 20px;
}
.menu ul {
list-style-type: none;
padding: 0;
margin: 0;
}
.menu li {
padding: 10px 20px;
font-size: 1.5em;
border-bottom: 1px solid rgba(0,0,0,0.2);
}
.fa-ul {
position: relative;
}
.issues li i {
color: red;
}
.issues li i:before {
content: "\f00d"; /* .fa-times */
visibility: visible;
}
.issues li[x] {
text-decoration: line-through;
}
.issues li[x] i {
color: green;
}
.issues li[x] i:before {
content: "\f00c"; /* .fa-check */
}
.issues li[x='?'] {
text-decoration: none;
}
.issues li[x='?'] i:before {
content: "\f128"; /* fa-question */
color: blue;
}
.menu-right-toggle {
position: absolute;
right: 20px;
top: 7px;
}
.ksl-assets.container > .inner > .overlay {
background-color: rgba(0,0,0,.2);
}
</style>
</body>
</html>
var ksl = ksl || {};
ksl.assets = ksl.assets || {};
ksl.assets.menu = (function ($) {
/* fix minimal-ui landscape problem */
(function minimalUiFix() {
var fix = function () {
window.scrollTo(0,0);
};
$(fix);
$(window).on('resize.minimal-ui-fix', fix);
})();
/*= helpers =*/
var helpers = {};
helpers.scrollCap = function ($element) {
var getMinScrollTop = function () {
return 1;
};
var getMaxScrollTop = function () {
return $element.get(0).scrollHeight - $element.height() - 1;
};
var cap = function () {
var scrollTop = $element.scrollTop();
var minScrollTop = getMinScrollTop();
var maxScrollTop = getMaxScrollTop();
if (scrollTop < minScrollTop) {
$element.scrollTop(minScrollTop);
} else if (scrollTop > maxScrollTop) {
$element.scrollTop(maxScrollTop);
}
};
$element.on('touchstart.scroll-cap', cap);
cap();
};
helpers.transitionEnd = function (namespace) {
return $.map([
'webkitTransitionEnd',
'otransitionend',
'oTransitionEnd',
'msTransitionEnd',
'transitionend'
], function (event) {
return event + '.namespace';
}).join(' ');
};
helpers.styleSupported = (function () {
var supported = [];
var check = function (property) {
var body = document.body || document.documentElement;
var style = body.style;
// check for standard
if (typeof style[property] == 'string') { return true; }
// check for vendor specific
var vendors = ['Moz', 'webkit', 'Webkit', 'Khtml', 'O', 'ms'];
property = property.charAt(0).toUpperCase() + property.substr(1);
for (var i = 0; i < vendors.length; i++) {
var vendorProperty = vendors[i];
if (typeof style[vendorProperty] == 'string') { return true; }
}
return false;
};
return function (property) {
if (supported[property] === undefined) {
supported[property] = check(property);
}
return supported[property];
};
})();
/* Container constructor =*/
var Container = function ($element) {
/* private */
var container = this;
$element.addClass('ksl-assets container');
helpers.scrollCap($element.find('> .inner > .content'));
(function ensureOverlay($element) {
var $inner = $element.find('> .inner');
var $overlay = $inner.find('> .overlay');
if ($overlay.length !== 0) { return; }
$overlay = $('<div class="overlay"></div>');
$overlay.prependTo($inner);
$overlay.on('click', function (event) {
$('.ksl-assets.menu.menu-open').trigger('close');
});
})($element);
var lockScroll = function () {
$element.addClass('scroll-lock');
};
var unlockScroll = (function () {
var unlock = function () {
$element.removeClass('scroll-lock');
};
if (!helpers.styleSupported('transition')) { return unlock; }
var transitionEnd = helpers.transitionEnd('menu.container');
return function () {
$element.on(transitionEnd, function (event) {
unlock();
$element.off(transitionEnd);
});
};
})();
/* public */
this.open = function (openClass) {
$element.addClass(openClass);
lockScroll();
};
this.close = function (openClass) {
$element.removeClass(openClass);
unlockScroll();
};
};
/*= Menu constructor =*/
var Menu = function ($element, $container) {
/* private */
$element.addClass('ksl-assets menu');
var container = new Container($container);
var menu = this;
var containerClass = $element.hasClass('menu-right') ? 'menu-right-open' : 'menu-open';
/* public */
this.isOpen = function () {
return $element.hasClass('menu-open');
};
this.open = function () {
$element.trigger('open');
};
this.close = function () {
$element.trigger('close');
};
this.toggle = function () {
$element.trigger('toggle');
};
this.addToggles = function ($toggle1, $toggle2, $toggle3) {
var toggles = Array.prototype.slice.apply(arguments);
$.each(toggles, function (index, $toggle) {
$toggle.on('click', function () {
menu.toggle();
});
});
};
/*= events =*/
$element.on('open', function () {
$element.scrollTop(0);
$element.addClass('menu-open');
container.open(containerClass);
});
$element.on('close', function () {
$element.removeClass('menu-open');
container.close(containerClass);
});
$element.on('toggle', function () {
if (menu.isOpen()) {
$element.trigger('close');
} else {
$element.trigger('open');
}
});
$element.on('click', function (event) {
if (event.target === $element.get(0)) {
$element.trigger('close');
}
});
var transitionEnd = (helpers.styleSupported('transition')) ? helpers.transitionEnd('menu') : 'open close';
$element.on(transitionEnd, function (event) {
if (menu.isOpen()) {
$element.trigger('opened');
} else {
$element.trigger('closed');
}
});
helpers.scrollCap($element);
};
/*= menu function =*/
var menu = function ($element, $toggles) {
$element = $element.eq(0); // only handles one menu at a time
var api = $element.data('menu-api');
if (!api) {
var $container = $('body > .container');
api = new Menu($element, $container);
$element.data('menu-api');
}
return api;
};
/*= jquery plugin =*/
if (!$.fn.menu) {
$.fn.menu = function () { return menu(this); };
}
return menu;
})(jQuery);
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |