JSFiddle - React, Tailwind, and code Playground
by tonyleeper
HTML
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<section data-bind="onDocumentClick: hideOverflowList">
<nav tabindex="0">
<ul class="tabs" data-bind="tabs: tabs">
<li data-bind="css: { active: active, fixed: fixed }">
<div data-bind="event: { mousedown: $root.activateTab.bind($root) }">
<span data-bind="text: name"></span>
</div>
</li>
</ul>
<div class="overflow" data-bind="visible: tabsOverflowing, event: { mousedown: toggleOverflowList }, preventEventBubbling: 'click'">
<i>...</i>
</div>
<ul class="overflow" data-bind="visible: overflowListActive, foreach: tabs">
<li data-bind="css: { active: active, fixed: fixed }">
<div data-bind="click: $root.activateTab.bind($root)"> <span data-bind="text: name"></span>
</div>
</li>
</ul>
</nav>
<!-- TODO: use nighthawk to data bind this article to the dashboard view -->
<!-- ko foreach: tabs -->
<article class="active" data-bind="visible: active"> <span class="dashboard-name" data-bind="text: name"></span>
</article>
<!-- /ko -->
</section>
CSS
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
}
body {
font-family: arial;
background-color: #5f6570;
padding: 15px;
}
section {
display: flex;
flex-direction: column;
height: 100%;
min-height: 400px;
min-width: 500px;
}
ul.tabs {
height: 70px;
list-style: none;
font-size: 0;
flex: 1 1;
padding-left: 10px;
-webkit-transform: translateZ(0); /* faster repaints */
}
ul.tabs > li {
display: inline-block;
vertical-align: top;
margin-right: 10px;
margin-bottom: 10px;
/* we don't want to see the overflowing tabs across the bottom */
}
ul.tabs > li > div {
font-family: arial;
font-weight: normal;
font-size: 16px;
color: #fff;
text-shadow: 0 1px #000;
display: inline-block;
height: 60px;
line-height: 60px;
text-align: center;
width: 100px;
background-color: #454a51;
border: 0;
border-radius: 3px;
padding: 0 10px;
}
ul.tabs > li.fixed > div {
width: 150px;
}
ul.tabs > li.fixed:not(.active) > div {
border: 1px solid black;
box-shadow: inset 0px 0px 0px 1px rgba(255,255,255,0.4)
}
ul > li > div > span {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
ul.tabs > li.active > div {
position: relative;
font-size: 18px;
color: #454b54;
text-shadow: 0 1px #fff;
background-color: #fff;
height: 70px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
ul.tabs > li.active > div:before {
content:"";
display: block;
position: absolute;
left: -6px;
bottom: 0;
width: 6px;
height: 6px;
background-color: #5f6570;
border-bottom-right-radius: 4px;
}
ul.tabs > li.active > div:after {
content:"";
display: block;
position: absolute;
right: -4px;
bottom: -1px;
width: 5px;
height: 5px;
background-color: #fff;
}
ul.tabs > li.active {
position:...
JavaScript
Array.prototype.swap = function (i, j) {
var temp = this[i];
this[i] = this[j];
this[j] = temp;
return this;
};
/**
carbon2 tabs
*/
/**
Prevents specific events from bubbling
Syntax: data-bind="preventEventBubbling: 'click'"
OR
data-bind="preventEventBubbling: ['click', 'onchange',.....]"
*/
ko.bindingHandlers.preventEventBubbling = {
stopPropagation: function (event) {
if (event.stopPropagation) {
event.stopPropagation();
} else { // Older IE.
event.cancelBubble = true;
}
},
init: function (element, valueAccessor) {
var $element = $(element);
var binding = ko.utils.unwrapObservable(valueAccessor());
if (typeof binding === "string") {
$element.on(binding, ko.bindingHandlers.preventEventBubbling.stopPropagation);
} else if (Array.isArray(binding)) {
for (var i = 0; i < binding.length; i++) {
$element.on(binding[i], ko.bindingHandlers.preventEventBubbling.stopPropagation);
}
}
}
};
/**
Custom binding handler that executes custom logic on document click
*/
ko.bindingHandlers.onDocumentClick = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
// First get the latest data that we're bound to
var allBindings = allBindingsAccessor();
$(document).on('click', function () {
allBindings.onDocumentClick.call(viewModel);
return true;
});
}
};
/**
sdl draggable plugin
*/
(function ($) {
var normalizeEvent = function (event) {
// "normalize" the event so that the passed in drag handler doesn't have to worry about
if (false) {
event.pageX = event.originalEvent.touches[0].pageX;
event.pageY = event.originalEvent.touches[0].pageY;
event.clientX = event.originalEvent.touches[0].clientX;
event.clientY =...