Skip to content

Instantly share code, notes, and snippets.

@tagliala
Created October 27, 2012 23:46
Show Gist options
  • Save tagliala/3966892 to your computer and use it in GitHub Desktop.
Save tagliala/3966892 to your computer and use it in GitHub Desktop.
[W.I.P] Facebook-like sidebar for twitter bootstrap
/* =============================================================
* bootstrap-sidebar.js v2.1.2
* http://twitter.github.com/bootstrap/javascript.html#sidebar
* =============================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function ($) {
"use strict"; // jshint ;_;
/* SIDEBAR PUBLIC CLASS DEFINITION
* ================================ */
var Sidebar = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, $.fn.sidebar.defaults, options)
if (this.options.parent) {
this.$parent = $(this.options.parent)
}
this.options.toggle && this.toggle()
}
Sidebar.prototype = {
constructor: Sidebar
, dimension: function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
, show: function () {
var dimension
, scroll
, actives
, hasData
if (this.transitioning) return
dimension = this.dimension()
scroll = $.camelCase(['scroll', dimension].join('-'))
actives = this.$parent && this.$parent.find('> .accordion-group > .in')
if (actives && actives.length) {
hasData = actives.data('sidebar')
if (hasData && hasData.transitioning) return
actives.sidebar('hide')
hasData || actives.data('sidebar', null)
}
this.$element[dimension](0)
this.transition('addClass', $.Event('show'), 'shown')
$.support.transition && this.$element[dimension](this.$element[0][scroll])
}
, hide: function () {
var dimension
if (this.transitioning) return
dimension = this.dimension()
this.reset(this.$element[dimension]())
this.transition('removeClass', $.Event('shide'), 'hidden')
this.$element[dimension](0)
}
, reset: function (size) {
var dimension = this.dimension()
this.$element
.removeClass('sidebar')
[dimension](size || 'auto')
[0].offsetWidth
this.$element[size !== null ? 'addClass' : 'removeClass']('sidebar')
return this
}
, transition: function (method, startEvent, completeEvent) {
var that = this
, complete = function () {
if (startEvent.type == 'show') that.reset()
that.transitioning = 0
that.$element.trigger(completeEvent)
}
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
this.transitioning = 1
this.$element[method]('in')
$.support.transition && this.$element.hasClass('sidebar') ?
this.$element.one($.support.transition.end, complete) :
complete()
}
, toggle: function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
}
/* COLLAPSIBLE PLUGIN DEFINITION
* ============================== */
$.fn.sidebar = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('sidebar')
, options = typeof option == 'object' && option
if (!data) $this.data('sidebar', (data = new Sidebar(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.sidebar.defaults = {
toggle: true
}
$.fn.sidebar.Constructor = Sidebar
/* COLLAPSIBLE DATA-API
* ==================== */
$(document).on('click.sidebar.data-api', '[data-toggle=sidebar]', function (e) {
var $this = $(this), href
, target = 'html' /* $this.attr('data-target') */
|| e.preventDefault()
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
, option = $(target).data('sidebar') ? 'toggle' : $this.data()
$this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('sidebard')
$(target).sidebar(option)
})
}(window.jQuery);
@import "twitter/bootstrap/variables.less";
@import "twitter/bootstrap/mixins.less";
@sidebarBackground: desaturate(@linkColorHover, 75%);
@sidebarWidth: 260px;
.navbar .nav > li > a i[class^="icon-"],
.navbar .nav > li > a i[class*="icon-"] {
line-height: @baseLineHeight - 2px;
}
.navbar .btn-navbar.btn-sidebar {
float: left;
}
@media(max-width: 979px) {
.navbar .nav-sidebar {
position: absolute;
display: none;
overflow: hidden;
left: -@sidebarWidth;
top: 0;
width: @sidebarWidth;
height: 100%;
color: @grayLighter;
background: @sidebarBackground;
border-right: 1px solid fade(@black, 5%);
.box-shadow(1px 0 10px fade(@black, 10%));
.box-sizing(border-box);
.sidebar-footer {
margin-left: 15px;
}
.nav {
& > li {
display: block;
float: none;
width: @sidebarWidth;
.gradientBar(@sidebarBackground , darken(@sidebarBackground, 5));
border-top: 1px solid fade(@white, 15%);
border-bottom: 1px solid fade(@black, 30%);
& > a {
padding: 10px;
color: @white;
text-shadow: 0 -1px 0 fade(@black, 25%);
.text-ellipsis {
display: inline-block;
width: @sidebarWidth - 20px; /* padding */
overflow: hidden;
text-overflow: ellipsis;
white-space: pre;
}
.notification-label {
position: absolute;
display: block;
height: 18px;
right: 10px;
padding: 0 5px;
line-height: 18px;
font-size: 12px;
font-weight: bold;
background: lighten(@sidebarBackground, 15%);
color: @white;
text-shadow: 0 1px 0 fade(@black, 25%);
.border-radius(3px);
.box-shadow(0 1px 0 fade(@black, 25%));
}
}
}
& > li.divider {
display: block;
height: 20px;
padding-left: 15px;
.gradientBar(lighten(@sidebarBackground, 3%), @sidebarBackground);
color: fade(@white, 70%);
text-shadow: -1px -1px 0 fade(@black, 50%);
border-top: 1px solid fade(@white, 15%);
border-bottom: 1px solid fade(@black, 35%);
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
cursor: default;
}
}
}
html.in {
body {
.transition(left .2s linear);
}
}
html.sidebar {
body {
position: relative;
.transition(left .2s linear);
}
.nav-sidebar {
display: block;
}
&.in {
width: 100%;
max-width: 100%;
overflow-x: hidden;
body {
left: 260px;
}
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= content_for?(:title) ? yield(:title) : "BootstrapSidebar" %></title>
<%= csrf_meta_tags %>
<!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
<![endif]-->
<%= stylesheet_link_tag "application", :media => "all" %>
<!-- For third-generation iPad with high-resolution Retina display: -->
<!-- Size should be 144 x 144 pixels -->
<%= favicon_link_tag 'images/apple-touch-icon-144x144-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '144x144' %>
<!-- For iPhone with high-resolution Retina display: -->
<!-- Size should be 114 x 114 pixels -->
<%= favicon_link_tag 'images/apple-touch-icon-114x114-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '114x114' %>
<!-- For first- and second-generation iPad: -->
<!-- Size should be 72 x 72 pixels -->
<%= favicon_link_tag 'images/apple-touch-icon-72x72-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '72x72' %>
<!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->
<!-- Size should be 57 x 57 pixels -->
<%= favicon_link_tag 'images/apple-touch-icon-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png' %>
<!-- For all other devices -->
<!-- Size should be 32 x 32 pixels -->
<%= favicon_link_tag 'images/favicon.ico', :rel => 'shortcut icon' %>
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar btn-sidebar" data-toggle="sidebar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="#">BootstrapSidebar</a>
<div class="container nav-sidebar">
<ul class="nav">
<li><%= link_to "Link1", "/path1" %></li>
<li><%= link_to "/path2" do %>
<i class="icon-ok"></i>
Link 2
<% end %></li>
<li><%= link_to "/path3" do %>
<span class="text-ellipsis">Ellipsis (inside a span) Hoc erat in votis modus</span>
<% end %></li>
<li><%= link_to "/path3" do %>
<span class="notification-label">5</span>
<span class="text-ellipsis">With notification label and a very long text</span>
<% end %></li>
</ul>
</div><!--/.nav-sidebar -->
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span9">
<%= yield %>
</div>
<div class="span3">
<div class="well sidebar-nav">
<h3>Sidebar</h3>
<ul class="nav nav-list">
<li class="nav-header">Sidebar</li>
<li><%= link_to "Link1", "/path1" %></li>
<li><%= link_to "Link2", "/path2" %></li>
<li><%= link_to "Link3", "/path3" %></li>
</ul>
</div><!--/.well -->
</div><!--/span-->
</div><!--/row-->
<footer>
<p>&copy; Company 2012</p>
</footer>
</div> <!-- /container -->
<!-- Javascripts
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<%= javascript_include_tag "application" %>
</body>
</html>
@tagliala
Copy link
Author

http://jsfiddle.net/spMdg/

Note: the fiddle was built on bootstrap 2.1.1

Outside jsfiddle, it works good with chrome, firefox and ie9.

Based on bootstrap 2.1.2 w.i.p.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment