Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/bootstrap-rubygem.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGleb Mazovetskiy <glex.spb@gmail.com>2014-10-29 23:49:47 +0300
committerGleb Mazovetskiy <glex.spb@gmail.com>2014-10-29 23:49:47 +0300
commit37ea51e9ac2ea1e0f475f998f6df70fabf0996b7 (patch)
tree8ce3b8b2b581459a140813e329ebe06043e9ac09
parent9365af1399b518f1f1d1217e8f9dc56febdd7a93 (diff)
parentf675be933cd4d16e760f3dd8906e721a92973b71 (diff)
Merge branch 'next'
Conflicts: README.md lib/bootstrap-sass.rb
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml10
-rw-r--r--CHANGELOG.md5
-rw-r--r--README.md27
-rw-r--r--Rakefile7
-rw-r--r--assets/fonts/bootstrap/glyphicons-halflings-regular.svg2
-rw-r--r--assets/javascripts/bootstrap.js505
-rw-r--r--assets/javascripts/bootstrap/affix.js66
-rw-r--r--assets/javascripts/bootstrap/alert.js10
-rw-r--r--assets/javascripts/bootstrap/button.js26
-rw-r--r--assets/javascripts/bootstrap/carousel.js36
-rw-r--r--assets/javascripts/bootstrap/collapse.js97
-rw-r--r--assets/javascripts/bootstrap/dropdown.js30
-rw-r--r--assets/javascripts/bootstrap/modal.js43
-rw-r--r--assets/javascripts/bootstrap/popover.js20
-rw-r--r--assets/javascripts/bootstrap/scrollspy.js19
-rw-r--r--assets/javascripts/bootstrap/tab.js57
-rw-r--r--assets/javascripts/bootstrap/tooltip.js99
-rw-r--r--assets/javascripts/bootstrap/transition.js2
-rw-r--r--assets/stylesheets/bootstrap/_button-groups.scss29
-rw-r--r--assets/stylesheets/bootstrap/_buttons.scss13
-rw-r--r--assets/stylesheets/bootstrap/_carousel.scss26
-rw-r--r--assets/stylesheets/bootstrap/_code.scss1
-rw-r--r--assets/stylesheets/bootstrap/_component-animations.scss7
-rw-r--r--assets/stylesheets/bootstrap/_dropdowns.scss10
-rw-r--r--assets/stylesheets/bootstrap/_forms.scss79
-rw-r--r--assets/stylesheets/bootstrap/_glyphicons.scss7
-rw-r--r--assets/stylesheets/bootstrap/_grid.scss8
-rw-r--r--assets/stylesheets/bootstrap/_jumbotron.scss8
-rw-r--r--assets/stylesheets/bootstrap/_list-group.scss1
-rw-r--r--assets/stylesheets/bootstrap/_media.scss63
-rw-r--r--assets/stylesheets/bootstrap/_modals.scss7
-rw-r--r--assets/stylesheets/bootstrap/_navbar.scss68
-rw-r--r--assets/stylesheets/bootstrap/_navs.scss8
-rw-r--r--assets/stylesheets/bootstrap/_normalize.scss8
-rw-r--r--assets/stylesheets/bootstrap/_pager.scss5
-rw-r--r--assets/stylesheets/bootstrap/_pagination.scss2
-rw-r--r--assets/stylesheets/bootstrap/_panels.scss26
-rw-r--r--assets/stylesheets/bootstrap/_popovers.scss9
-rw-r--r--assets/stylesheets/bootstrap/_print.scss198
-rw-r--r--assets/stylesheets/bootstrap/_progress-bars.scss22
-rw-r--r--assets/stylesheets/bootstrap/_responsive-embed.scss3
-rw-r--r--assets/stylesheets/bootstrap/_scaffolding.scss6
-rw-r--r--assets/stylesheets/bootstrap/_tables.scss21
-rw-r--r--assets/stylesheets/bootstrap/_theme.scss30
-rw-r--r--assets/stylesheets/bootstrap/_thumbnails.scss4
-rw-r--r--assets/stylesheets/bootstrap/_type.scss26
-rw-r--r--assets/stylesheets/bootstrap/_utilities.scss7
-rw-r--r--assets/stylesheets/bootstrap/_variables.scss48
-rw-r--r--assets/stylesheets/bootstrap/mixins/_buttons.scss2
-rw-r--r--assets/stylesheets/bootstrap/mixins/_forms.scss6
-rw-r--r--assets/stylesheets/bootstrap/mixins/_grid.scss4
-rw-r--r--assets/stylesheets/bootstrap/mixins/_hide-text.scss2
-rw-r--r--assets/stylesheets/bootstrap/mixins/_image.scss1
-rw-r--r--assets/stylesheets/bootstrap/mixins/_labels.scss2
-rw-r--r--assets/stylesheets/bootstrap/mixins/_progress-bar.scss2
-rw-r--r--assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss9
-rw-r--r--lib/bootstrap-sass.rb2
-rw-r--r--lib/bootstrap-sass/engine.rb2
-rw-r--r--lib/bootstrap-sass/version.rb4
-rw-r--r--package.json6
-rw-r--r--tasks/converter/less_conversion.rb88
-rw-r--r--tasks/converter/network.rb18
-rw-r--r--templates/project/_bootstrap-variables.sass866
-rw-r--r--templates/project/_bootstrap-variables.sass.erb4
-rw-r--r--templates/project/manifest.rb16
-rwxr-xr-xtest/dummy_rails/bin/bundle3
-rwxr-xr-xtest/dummy_rails/bin/rails4
-rwxr-xr-xtest/dummy_rails/bin/rake4
-rw-r--r--test/dummy_rails/db/test.sqlite30
-rw-r--r--test/dummy_rails/lib/assets/.keep0
-rw-r--r--test/dummy_rails/log/production.log0
-rw-r--r--test/dummy_rails/public/404.html58
-rw-r--r--test/dummy_rails/public/422.html58
-rw-r--r--test/dummy_rails/public/500.html57
-rw-r--r--test/dummy_rails/public/favicon.ico0
-rwxr-xr-xtest/node_sass_compile_test.sh8
-rw-r--r--test/node_sass_test.rb16
-rw-r--r--test/support/integration_test.rb22
79 files changed, 2082 insertions, 995 deletions
diff --git a/.gitignore b/.gitignore
index 5772ce1..ec18253 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,6 @@ Gemfile.lock
tmp/
test/screenshots/
test/dummy_rails/log/*.log
-
+test/dummy_rails/public/assets/
.DS_Store
node_modules
diff --git a/.travis.yml b/.travis.yml
index 0223e8c..3087a94 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,12 @@
language: ruby
rvm:
- - 2.1.1
- - 2.0.0
+ - 2.1.2
- jruby
- rbx-2
gemfile:
- test/gemfiles/sass_3_2.gemfile
- test/gemfiles/sass_3_3.gemfile
+ - test/gemfiles/sass_3_4.gemfile
- test/gemfiles/sass_head.gemfile
before_install:
- "npm install"
@@ -17,3 +17,9 @@ matrix:
- gemfile: test/gemfiles/sass_head.gemfile
notifications:
slack: heybb:3n88HHilXn76ji9vV4gL819Y
+env:
+ global:
+ - VERBOSE=1
+script:
+ - bundle exec rake
+ - sh test/*.sh
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5446eca..3c6dbdd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 3.3.0
+
+* Improve libsass compatibility
+* Support using Bower package with Rails
+
## 3.2.0.2
Main bootstrap file is now a partial (_bootstrap.scss), for compatibility with Compass 1+.
diff --git a/README.md b/README.md
index 629c1b6..7244de5 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ Please see the appropriate guide for your environment of choice:
In your Gemfile you need to add the `bootstrap-sass` gem, and ensure that the `sass-rails` gem is present - it is added to new Rails applications by default.
```ruby
-gem 'bootstrap-sass', '~> 3.2.0'
+gem 'bootstrap-sass', '~> 3.3.0'
gem 'sass-rails', '>= 3.2'
```
@@ -33,6 +33,7 @@ gem 'autoprefixer-rails'
Import Bootstrap styles in `app/assets/stylesheets/application.css.scss`:
```scss
+// "bootstrap-sprockets" must be imported before "bootstrap" and "bootstrap/variables"
@import "bootstrap-sprockets";
@import "bootstrap";
```
@@ -57,13 +58,29 @@ Require Bootstrap Javascripts in `app/assets/javascripts/application.js`:
#### Bower with Rails
-When using [bootstrap-sass Bower package](#c-bower) in Rails, ensure [minimum Sass number precision](#sass-number-precision):
+When using [bootstrap-sass Bower package](#c-bower) instead of the gem in Rails, add Bootstrap asset paths:
```ruby
-# e.g. config/initializers/sass.rb
+# config/application.rb
+# bootstrap-sass asset paths
+root.join('vendor/assets/bower_components/bootstrap-sass/assets').tap do |path|
+ config.sass.load_paths << path.join('stylesheets')
+ config.assets.paths += %w(javascripts fonts images).map(&path.method(:join))
+end
+```
+
+Then, ensure [minimum Sass number precision](#sass-number-precision):
+
+```ruby
+# config/initializers/sass.rb
+# Minimum precision required by bootstrap-sass
::Sass::Script::Number.precision = [10, ::Sass::Script::Number.precision].max
```
+#### Rails 4.x
+
+Please make sure `sprockets-rails` is at least v2.1.4.
+
#### Rails 3.2.x
Rails 3.2 is [no longer maintained for bugfixes](http://guides.rubyonrails.org/maintenance_policy.html), and you should upgrade as soon as possible.
@@ -159,8 +176,8 @@ See also this [example manifest.js](/test/dummy_node_mincer/manifest.js) for min
By default all of Bootstrap is imported.
You can also import components explicitly. To start with a full list of modules copy
-[`bootstrap.scss`](assets/stylesheets/_bootstrap.scss) file into your assets as `bootstrap-custom.scss`.
-Then comment out components you do not want from `bootstrap-custom`.
+[`_bootstrap.scss`](assets/stylesheets/_bootstrap.scss) file into your assets as `_bootstrap-custom.scss`.
+Then comment out components you do not want from `_bootstrap-custom`.
In the application Sass file, replace `@import 'bootstrap'` with:
```scss
diff --git a/Rakefile b/Rakefile
index 92a3c4b..c90a305 100644
--- a/Rakefile
+++ b/Rakefile
@@ -4,10 +4,9 @@ $:.unshift(lib_path) unless $:.include?(lib_path)
load './tasks/bower.rake'
require 'rake/testtask'
-Rake::TestTask.new do |t|
- t.libs << "test"
- t.test_files = FileList['test/*_test.rb']
- t.verbose = true
+task :test do |t|
+ $: << File.expand_path('test/')
+ Dir.glob('./test/**/*_test.rb').each { |file| require file }
end
desc 'Dumps output to a CSS file for testing'
diff --git a/assets/fonts/bootstrap/glyphicons-halflings-regular.svg b/assets/fonts/bootstrap/glyphicons-halflings-regular.svg
index e3e2dc7..25691af 100644
--- a/assets/fonts/bootstrap/glyphicons-halflings-regular.svg
+++ b/assets/fonts/bootstrap/glyphicons-halflings-regular.svg
@@ -226,4 +226,4 @@
<glyph unicode="&#xe199;" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
<glyph unicode="&#xe200;" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
</font>
-</defs></svg> \ No newline at end of file
+</defs></svg> \ No newline at end of file
diff --git a/assets/javascripts/bootstrap.js b/assets/javascripts/bootstrap.js
index 30409f4..eac0ba4 100644
--- a/assets/javascripts/bootstrap.js
+++ b/assets/javascripts/bootstrap.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: affix.js v3.2.0
+ * Bootstrap: affix.js v3.3.0
* http://getbootstrap.com/javascript/#affix
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -28,7 +28,7 @@
this.checkPosition()
}
- Affix.VERSION = '3.2.0'
+ Affix.VERSION = '3.3.0'
Affix.RESET = 'affix affix-top affix-bottom'
@@ -37,6 +37,28 @@
target: window
}
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ var targetHeight = this.$target.height()
+
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+ if (this.affixed == 'bottom') {
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+ }
+
+ var initializing = this.affixed == null
+ var colliderTop = initializing ? scrollTop : position.top
+ var colliderHeight = initializing ? targetHeight : height
+
+ if (offsetTop != null && colliderTop <= offsetTop) return 'top'
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+ return false
+ }
+
Affix.prototype.getPinnedOffset = function () {
if (this.pinnedOffset) return this.pinnedOffset
this.$element.removeClass(Affix.RESET).addClass('affix')
@@ -52,42 +74,40 @@
Affix.prototype.checkPosition = function () {
if (!this.$element.is(':visible')) return
- var scrollHeight = $(document).height()
- var scrollTop = this.$target.scrollTop()
- var position = this.$element.offset()
+ var height = this.$element.height()
var offset = this.options.offset
var offsetTop = offset.top
var offsetBottom = offset.bottom
+ var scrollHeight = $('body').height()
if (typeof offset != 'object') offsetBottom = offsetTop = offset
if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
- var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
- offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
- offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
- if (this.affixed === affix) return
- if (this.unpin != null) this.$element.css('top', '')
+ if (this.affixed != affix) {
+ if (this.unpin != null) this.$element.css('top', '')
- var affixType = 'affix' + (affix ? '-' + affix : '')
- var e = $.Event(affixType + '.bs.affix')
+ var affixType = 'affix' + (affix ? '-' + affix : '')
+ var e = $.Event(affixType + '.bs.affix')
- this.$element.trigger(e)
+ this.$element.trigger(e)
- if (e.isDefaultPrevented()) return
+ if (e.isDefaultPrevented()) return
- this.affixed = affix
- this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
- this.$element
- .removeClass(Affix.RESET)
- .addClass(affixType)
- .trigger($.Event(affixType.replace('affix', 'affixed')))
+ this.$element
+ .removeClass(Affix.RESET)
+ .addClass(affixType)
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+ }
if (affix == 'bottom') {
this.$element.offset({
- top: scrollHeight - this.$element.height() - offsetBottom
+ top: scrollHeight - height - offsetBottom
})
}
}
@@ -132,8 +152,8 @@
data.offset = data.offset || {}
- if (data.offsetBottom) data.offset.bottom = data.offsetBottom
- if (data.offsetTop) data.offset.top = data.offsetTop
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
Plugin.call($spy, data)
})
@@ -142,7 +162,7 @@
}(jQuery);
/* ========================================================================
- * Bootstrap: alert.js v3.2.0
+ * Bootstrap: alert.js v3.3.0
* http://getbootstrap.com/javascript/#alerts
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -161,7 +181,9 @@
$(el).on('click', dismiss, this.close)
}
- Alert.VERSION = '3.2.0'
+ Alert.VERSION = '3.3.0'
+
+ Alert.TRANSITION_DURATION = 150
Alert.prototype.close = function (e) {
var $this = $(this)
@@ -177,7 +199,7 @@
if (e) e.preventDefault()
if (!$parent.length) {
- $parent = $this.hasClass('alert') ? $this : $this.parent()
+ $parent = $this.closest('.alert')
}
$parent.trigger(e = $.Event('close.bs.alert'))
@@ -194,7 +216,7 @@
$.support.transition && $parent.hasClass('fade') ?
$parent
.one('bsTransitionEnd', removeElement)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
removeElement()
}
@@ -235,7 +257,7 @@
}(jQuery);
/* ========================================================================
- * Bootstrap: button.js v3.2.0
+ * Bootstrap: button.js v3.3.0
* http://getbootstrap.com/javascript/#buttons
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -255,7 +277,7 @@
this.isLoading = false
}
- Button.VERSION = '3.2.0'
+ Button.VERSION = '3.3.0'
Button.DEFAULTS = {
loadingText: 'loading...'
@@ -271,10 +293,10 @@
if (data.resetText == null) $el.data('resetText', $el[val]())
- $el[val](data[state] == null ? this.options[state] : data[state])
-
// push to event loop to allow forms to submit
setTimeout($.proxy(function () {
+ $el[val](data[state] == null ? this.options[state] : data[state])
+
if (state == 'loadingText') {
this.isLoading = true
$el.addClass(d).attr(d, d)
@@ -296,6 +318,8 @@
else $parent.find('.active').removeClass('active')
}
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
+ } else {
+ this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
}
if (changed) this.$element.toggleClass('active')
@@ -336,17 +360,21 @@
// BUTTON DATA-API
// ===============
- $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
- var $btn = $(e.target)
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
- Plugin.call($btn, 'toggle')
- e.preventDefault()
- })
+ $(document)
+ .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ Plugin.call($btn, 'toggle')
+ e.preventDefault()
+ })
+ .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ $(e.target).closest('.btn').toggleClass('focus', e.type == 'focus')
+ })
}(jQuery);
/* ========================================================================
- * Bootstrap: carousel.js v3.2.0
+ * Bootstrap: carousel.js v3.3.0
* http://getbootstrap.com/javascript/#carousel
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -361,7 +389,7 @@
// =========================
var Carousel = function (element, options) {
- this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
+ this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
this.paused =
@@ -370,17 +398,22 @@
this.$active =
this.$items = null
- this.options.pause == 'hover' && this.$element
+ this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
+
+ this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
- Carousel.VERSION = '3.2.0'
+ Carousel.VERSION = '3.3.0'
+
+ Carousel.TRANSITION_DURATION = 600
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
- wrap: true
+ wrap: true,
+ keyboard: true
}
Carousel.prototype.keydown = function (e) {
@@ -410,6 +443,13 @@
return this.$items.index(item || this.$active)
}
+ Carousel.prototype.getItemForDirection = function (direction, active) {
+ var delta = direction == 'prev' ? -1 : 1
+ var activeIndex = this.getItemIndex(active)
+ var itemIndex = (activeIndex + delta) % this.$items.length
+ return this.$items.eq(itemIndex)
+ }
+
Carousel.prototype.to = function (pos) {
var that = this
var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
@@ -419,7 +459,7 @@
if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
if (activeIndex == pos) return this.pause().cycle()
- return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
}
Carousel.prototype.pause = function (e) {
@@ -447,7 +487,7 @@
Carousel.prototype.slide = function (type, next) {
var $active = this.$element.find('.item.active')
- var $next = next || $active[type]()
+ var $next = next || this.getItemForDirection(type, $active)
var isCycling = this.interval
var direction = type == 'next' ? 'left' : 'right'
var fallback = type == 'next' ? 'first' : 'last'
@@ -493,7 +533,7 @@
that.$element.trigger(slidEvent)
}, 0)
})
- .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
} else {
$active.removeClass('active')
$next.addClass('active')
@@ -542,7 +582,7 @@
// CAROUSEL DATA-API
// =================
- $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+ var clickHandler = function (e) {
var href
var $this = $(this)
var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
@@ -558,7 +598,11 @@
}
e.preventDefault()
- })
+ }
+
+ $(document)
+ .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
+ .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
$(window).on('load', function () {
$('[data-ride="carousel"]').each(function () {
@@ -570,7 +614,7 @@
}(jQuery);
/* ========================================================================
- * Bootstrap: collapse.js v3.2.0
+ * Bootstrap: collapse.js v3.3.0
* http://getbootstrap.com/javascript/#collapse
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -587,16 +631,25 @@
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
+ this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
this.transitioning = null
- if (this.options.parent) this.$parent = $(this.options.parent)
+ if (this.options.parent) {
+ this.$parent = this.getParent()
+ } else {
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
+ }
+
if (this.options.toggle) this.toggle()
}
- Collapse.VERSION = '3.2.0'
+ Collapse.VERSION = '3.3.0'
+
+ Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
- toggle: true
+ toggle: true,
+ trigger: '[data-toggle="collapse"]'
}
Collapse.prototype.dimension = function () {
@@ -607,17 +660,21 @@
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
+ var activesData
+ var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
+
+ if (actives && actives.length) {
+ activesData = actives.data('bs.collapse')
+ if (activesData && activesData.transitioning) return
+ }
+
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
- var actives = this.$parent && this.$parent.find('> .panel > .in')
-
if (actives && actives.length) {
- var hasData = actives.data('bs.collapse')
- if (hasData && hasData.transitioning) return
Plugin.call(actives, 'hide')
- hasData || actives.data('bs.collapse', null)
+ activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
@@ -625,6 +682,11 @@
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
+ .attr('aria-expanded', true)
+
+ this.$trigger
+ .removeClass('collapsed')
+ .attr('aria-expanded', true)
this.transitioning = 1
@@ -643,7 +705,7 @@
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
@@ -659,17 +721,21 @@
this.$element
.addClass('collapsing')
- .removeClass('collapse')
- .removeClass('in')
+ .removeClass('collapse in')
+ .attr('aria-expanded', false)
+
+ this.$trigger
+ .addClass('collapsed')
+ .attr('aria-expanded', false)
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
- .trigger('hidden.bs.collapse')
.removeClass('collapsing')
.addClass('collapse')
+ .trigger('hidden.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
@@ -677,13 +743,40 @@
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(350)
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
+ Collapse.prototype.getParent = function () {
+ return $(this.options.parent)
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
+ .each($.proxy(function (i, element) {
+ var $element = $(element)
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
+ }, this))
+ .end()
+ }
+
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
+ var isOpen = $element.hasClass('in')
+
+ $element.attr('aria-expanded', isOpen)
+ $trigger
+ .toggleClass('collapsed', !isOpen)
+ .attr('aria-expanded', isOpen)
+ }
+
+ function getTargetFromTrigger($trigger) {
+ var href
+ var target = $trigger.attr('data-target')
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+
+ return $(target)
+ }
+
// COLLAPSE PLUGIN DEFINITION
// ==========================
@@ -694,7 +787,7 @@
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
- if (!data && options.toggle && option == 'show') option = !option
+ if (!data && options.toggle && option == 'show') options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
@@ -719,21 +812,13 @@
// =================
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
- var href
var $this = $(this)
- var target = $this.attr('data-target')
- || e.preventDefault()
- || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
- var $target = $(target)
- var data = $target.data('bs.collapse')
- var option = data ? 'toggle' : $this.data()
- var parent = $this.attr('data-parent')
- var $parent = parent && $(parent)
- if (!data || !data.transitioning) {
- if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
- $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
- }
+ if (!$this.attr('data-target')) e.preventDefault()
+
+ var $target = getTargetFromTrigger($this)
+ var data = $target.data('bs.collapse')
+ var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
Plugin.call($target, option)
})
@@ -741,7 +826,7 @@
}(jQuery);
/* ========================================================================
- * Bootstrap: dropdown.js v3.2.0
+ * Bootstrap: dropdown.js v3.3.0
* http://getbootstrap.com/javascript/#dropdowns
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -761,7 +846,7 @@
$(element).on('click.bs.dropdown', this.toggle)
}
- Dropdown.VERSION = '3.2.0'
+ Dropdown.VERSION = '3.3.0'
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
@@ -784,7 +869,9 @@
if (e.isDefaultPrevented()) return
- $this.trigger('focus')
+ $this
+ .trigger('focus')
+ .attr('aria-expanded', 'true')
$parent
.toggleClass('open')
@@ -795,7 +882,7 @@
}
Dropdown.prototype.keydown = function (e) {
- if (!/(38|40|27)/.test(e.keyCode)) return
+ if (!/(38|40|27|32)/.test(e.which)) return
var $this = $(this)
@@ -807,7 +894,7 @@
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
- if (!isActive || (isActive && e.keyCode == 27)) {
+ if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
@@ -817,10 +904,10 @@
if (!$items.length) return
- var index = $items.index($items.filter(':focus'))
+ var index = $items.index(e.target)
- if (e.keyCode == 38 && index > 0) index-- // up
- if (e.keyCode == 40 && index < $items.length - 1) index++ // down
+ if (e.which == 38 && index > 0) index-- // up
+ if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')
@@ -830,11 +917,17 @@
if (e && e.which === 3) return
$(backdrop).remove()
$(toggle).each(function () {
- var $parent = getParent($(this))
+ var $this = $(this)
+ var $parent = getParent($this)
var relatedTarget = { relatedTarget: this }
+
if (!$parent.hasClass('open')) return
+
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
if (e.isDefaultPrevented()) return
+
+ $this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
})
}
@@ -888,12 +981,14 @@
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
- .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
}(jQuery);
/* ========================================================================
- * Bootstrap: tab.js v3.2.0
+ * Bootstrap: tab.js v3.3.0
* http://getbootstrap.com/javascript/#tabs
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -911,7 +1006,9 @@
this.element = $(element)
}
- Tab.VERSION = '3.2.0'
+ Tab.VERSION = '3.3.0'
+
+ Tab.TRANSITION_DURATION = 150
Tab.prototype.show = function () {
var $this = this.element
@@ -925,22 +1022,30 @@
if ($this.parent('li').hasClass('active')) return
- var previous = $ul.find('.active:last a')[0]
- var e = $.Event('show.bs.tab', {
- relatedTarget: previous
+ var $previous = $ul.find('.active:last a')
+ var hideEvent = $.Event('hide.bs.tab', {
+ relatedTarget: $this[0]
+ })
+ var showEvent = $.Event('show.bs.tab', {
+ relatedTarget: $previous[0]
})
- $this.trigger(e)
+ $previous.trigger(hideEvent)
+ $this.trigger(showEvent)
- if (e.isDefaultPrevented()) return
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.closest('li'), $ul)
this.activate($target, $target.parent(), function () {
+ $previous.trigger({
+ type: 'hidden.bs.tab',
+ relatedTarget: $this[0]
+ })
$this.trigger({
type: 'shown.bs.tab',
- relatedTarget: previous
+ relatedTarget: $previous[0]
})
})
}
@@ -949,15 +1054,21 @@
var $active = container.find('> .active')
var transition = callback
&& $.support.transition
- && $active.hasClass('fade')
+ && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
function next() {
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
- .removeClass('active')
+ .removeClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', false)
- element.addClass('active')
+ element
+ .addClass('active')
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
if (transition) {
element[0].offsetWidth // reflow for transition
@@ -967,16 +1078,21 @@
}
if (element.parent('.dropdown-menu')) {
- element.closest('li.dropdown').addClass('active')
+ element
+ .closest('li.dropdown')
+ .addClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
}
callback && callback()
}
- transition ?
+ $active.length && transition ?
$active
.one('bsTransitionEnd', next)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
next()
$active.removeClass('in')
@@ -1014,15 +1130,19 @@
// TAB DATA-API
// ============
- $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+ var clickHandler = function (e) {
e.preventDefault()
Plugin.call($(this), 'show')
- })
+ }
+
+ $(document)
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
}(jQuery);
/* ========================================================================
- * Bootstrap: transition.js v3.2.0
+ * Bootstrap: transition.js v3.3.0
* http://getbootstrap.com/javascript/#transitions
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -1082,7 +1202,7 @@
}(jQuery);
/* ========================================================================
- * Bootstrap: scrollspy.js v3.2.0
+ * Bootstrap: scrollspy.js v3.3.0
* http://getbootstrap.com/javascript/#scrollspy
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -1113,7 +1233,7 @@
this.process()
}
- ScrollSpy.VERSION = '3.2.0'
+ ScrollSpy.VERSION = '3.3.0'
ScrollSpy.DEFAULTS = {
offset: 10
@@ -1174,8 +1294,9 @@
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
- if (activeTarget && scrollTop <= offsets[0]) {
- return activeTarget != (i = targets[0]) && this.activate(i)
+ if (activeTarget && scrollTop < offsets[0]) {
+ this.activeTarget = null
+ return this.clear()
}
for (i = offsets.length; i--;) {
@@ -1189,9 +1310,7 @@
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
- $(this.selector)
- .parentsUntil(this.options.target, '.active')
- .removeClass('active')
+ this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
@@ -1210,6 +1329,12 @@
active.trigger('activate.bs.scrollspy')
}
+ ScrollSpy.prototype.clear = function () {
+ $(this.selector)
+ .parentsUntil(this.options.target, '.active')
+ .removeClass('active')
+ }
+
// SCROLLSPY PLUGIN DEFINITION
// ===========================
@@ -1253,7 +1378,7 @@
}(jQuery);
/* ========================================================================
- * Bootstrap: modal.js v3.2.0
+ * Bootstrap: modal.js v3.3.0
* http://getbootstrap.com/javascript/#modals
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -1284,7 +1409,10 @@
}
}
- Modal.VERSION = '3.2.0'
+ Modal.VERSION = '3.3.0'
+
+ Modal.TRANSITION_DURATION = 300
+ Modal.BACKDROP_TRANSITION_DURATION = 150
Modal.DEFAULTS = {
backdrop: true,
@@ -1342,7 +1470,7 @@
.one('bsTransitionEnd', function () {
that.$element.trigger('focus').trigger(e)
})
- .emulateTransitionEnd(300) :
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
})
}
@@ -1358,9 +1486,6 @@
this.isShown = false
- this.$body.removeClass('modal-open')
-
- this.resetScrollbar()
this.escape()
$(document).off('focusin.bs.modal')
@@ -1373,7 +1498,7 @@
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
- .emulateTransitionEnd(300) :
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()
}
@@ -1389,11 +1514,11 @@
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) {
- this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide()
}, this))
} else if (!this.isShown) {
- this.$element.off('keyup.dismiss.bs.modal')
+ this.$element.off('keydown.dismiss.bs.modal')
}
}
@@ -1401,6 +1526,8 @@
var that = this
this.$element.hide()
this.backdrop(function () {
+ that.$body.removeClass('modal-open')
+ that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
@@ -1418,14 +1545,13 @@
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
- .appendTo(this.$body)
-
- this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
- if (e.target !== e.currentTarget) return
- this.options.backdrop == 'static'
- ? this.$element[0].focus.call(this.$element[0])
- : this.hide.call(this)
- }, this))
+ .prependTo(this.$element)
+ .on('click.dismiss.bs.modal', $.proxy(function (e) {
+ if (e.target !== e.currentTarget) return
+ this.options.backdrop == 'static'
+ ? this.$element[0].focus.call(this.$element[0])
+ : this.hide.call(this)
+ }, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
@@ -1436,7 +1562,7 @@
doAnimate ?
this.$backdrop
.one('bsTransitionEnd', callback)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callback()
} else if (!this.isShown && this.$backdrop) {
@@ -1449,7 +1575,7 @@
$.support.transition && this.$element.hasClass('fade') ?
this.$backdrop
.one('bsTransitionEnd', callbackRemove)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callbackRemove()
} else if (callback) {
@@ -1458,8 +1584,7 @@
}
Modal.prototype.checkScrollbar = function () {
- if (document.body.clientWidth >= window.innerWidth) return
- this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
+ this.scrollbarWidth = this.measureScrollbar()
}
Modal.prototype.setScrollbar = function () {
@@ -1472,6 +1597,7 @@
}
Modal.prototype.measureScrollbar = function () { // thx walsh
+ if (document.body.clientWidth >= window.innerWidth) return 0
var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure'
this.$body.append(scrollDiv)
@@ -1534,7 +1660,7 @@
}(jQuery);
/* ========================================================================
- * Bootstrap: tooltip.js v3.2.0
+ * Bootstrap: tooltip.js v3.3.0
* http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
@@ -1560,7 +1686,9 @@
this.init('tooltip', element, options)
}
- Tooltip.VERSION = '3.2.0'
+ Tooltip.VERSION = '3.3.0'
+
+ Tooltip.TRANSITION_DURATION = 150
Tooltip.DEFAULTS = {
animation: true,
@@ -1638,6 +1766,11 @@
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
+ if (self && self.$tip && self.$tip.is(':visible')) {
+ self.hoverState = 'in'
+ return
+ }
+
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
@@ -1680,7 +1813,7 @@
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
- var inDom = $.contains(document.documentElement, this.$element[0])
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
var that = this
@@ -1716,13 +1849,13 @@
if (autoPlace) {
var orgPlacement = placement
- var $parent = this.$element.parent()
- var parentDim = this.getPosition($parent)
+ var $container = this.options.container ? $(this.options.container) : this.$element.parent()
+ var containerDim = this.getPosition($container)
- placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
- placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
- placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
- placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
+ placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
+ placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
+ placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
+ placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement
$tip
@@ -1735,14 +1868,17 @@
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
+ var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
+
+ if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
}
}
@@ -1789,16 +1925,18 @@
if (delta.left) offset.left += delta.left
else offset.top += delta.top
- var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
- var arrowPosition = delta.left ? 'left' : 'top'
- var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
+ var isVertical = /top|bottom/.test(placement)
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$tip.offset(offset)
- this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
}
- Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
- this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
+ this.arrow()
+ .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+ .css(isHorizontal ? 'top' : 'left', '')
}
Tooltip.prototype.setContent = function () {
@@ -1809,16 +1947,17 @@
$tip.removeClass('fade in top bottom left right')
}
- Tooltip.prototype.hide = function () {
+ Tooltip.prototype.hide = function (callback) {
var that = this
var $tip = this.tip()
var e = $.Event('hide.bs.' + this.type)
- this.$element.removeAttr('aria-describedby')
-
function complete() {
if (that.hoverState != 'in') $tip.detach()
- that.$element.trigger('hidden.bs.' + that.type)
+ that.$element
+ .removeAttr('aria-describedby')
+ .trigger('hidden.bs.' + that.type)
+ callback && callback()
}
this.$element.trigger(e)
@@ -1830,7 +1969,7 @@
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
this.hoverState = null
@@ -1851,13 +1990,20 @@
Tooltip.prototype.getPosition = function ($element) {
$element = $element || this.$element
+
var el = $element[0]
var isBody = el.tagName == 'BODY'
- return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
- scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
- width: isBody ? $(window).width() : $element.outerWidth(),
- height: isBody ? $(window).height() : $element.outerHeight()
- }, isBody ? { top: 0, left: 0 } : $element.offset())
+
+ var elRect = el.getBoundingClientRect()
+ if (elRect.width == null) {
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
+ }
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
+
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
@@ -1921,14 +2067,6 @@
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
}
- Tooltip.prototype.validate = function () {
- if (!this.$element[0].parentNode) {
- this.hide()
- this.$element = null
- this.options = null
- }
- }
-
Tooltip.prototype.enable = function () {
this.enabled = true
}
@@ -1955,8 +2093,11 @@
}
Tooltip.prototype.destroy = function () {
+ var that = this
clearTimeout(this.timeout)
- this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
+ this.hide(function () {
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
+ })
}
@@ -1965,12 +2106,18 @@
function Plugin(option) {
return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.tooltip')
- var options = typeof option == 'object' && option
+ var $this = $(this)
+ var data = $this.data('bs.tooltip')
+ var options = typeof option == 'object' && option
+ var selector = options && options.selector
if (!data && option == 'destroy') return
- if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ if (selector) {
+ if (!data) $this.data('bs.tooltip', (data = {}))
+ if (!data[selector]) data[selector] = new Tooltip(this, options)
+ } else {
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ }
if (typeof option == 'string') data[option]()
})
}
@@ -1992,7 +2139,7 @@
}(jQuery);
/* ========================================================================
- * Bootstrap: popover.js v3.2.0
+ * Bootstrap: popover.js v3.3.0
* http://getbootstrap.com/javascript/#popovers
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -2012,7 +2159,7 @@
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
- Popover.VERSION = '3.2.0'
+ Popover.VERSION = '3.3.0'
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right',
@@ -2039,7 +2186,7 @@
var content = this.getContent()
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
- $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
](content)
@@ -2079,12 +2226,18 @@
function Plugin(option) {
return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.popover')
- var options = typeof option == 'object' && option
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+ var selector = options && options.selector
if (!data && option == 'destroy') return
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (selector) {
+ if (!data) $this.data('bs.popover', (data = {}))
+ if (!data[selector]) data[selector] = new Popover(this, options)
+ } else {
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ }
if (typeof option == 'string') data[option]()
})
}
diff --git a/assets/javascripts/bootstrap/affix.js b/assets/javascripts/bootstrap/affix.js
index 7d404eb..e4efa20 100644
--- a/assets/javascripts/bootstrap/affix.js
+++ b/assets/javascripts/bootstrap/affix.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: affix.js v3.2.0
+ * Bootstrap: affix.js v3.3.0
* http://getbootstrap.com/javascript/#affix
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -28,7 +28,7 @@
this.checkPosition()
}
- Affix.VERSION = '3.2.0'
+ Affix.VERSION = '3.3.0'
Affix.RESET = 'affix affix-top affix-bottom'
@@ -37,6 +37,28 @@
target: window
}
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ var targetHeight = this.$target.height()
+
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+ if (this.affixed == 'bottom') {
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+ }
+
+ var initializing = this.affixed == null
+ var colliderTop = initializing ? scrollTop : position.top
+ var colliderHeight = initializing ? targetHeight : height
+
+ if (offsetTop != null && colliderTop <= offsetTop) return 'top'
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+ return false
+ }
+
Affix.prototype.getPinnedOffset = function () {
if (this.pinnedOffset) return this.pinnedOffset
this.$element.removeClass(Affix.RESET).addClass('affix')
@@ -52,42 +74,40 @@
Affix.prototype.checkPosition = function () {
if (!this.$element.is(':visible')) return
- var scrollHeight = $(document).height()
- var scrollTop = this.$target.scrollTop()
- var position = this.$element.offset()
+ var height = this.$element.height()
var offset = this.options.offset
var offsetTop = offset.top
var offsetBottom = offset.bottom
+ var scrollHeight = $('body').height()
if (typeof offset != 'object') offsetBottom = offsetTop = offset
if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
- var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
- offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
- offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
- if (this.affixed === affix) return
- if (this.unpin != null) this.$element.css('top', '')
+ if (this.affixed != affix) {
+ if (this.unpin != null) this.$element.css('top', '')
- var affixType = 'affix' + (affix ? '-' + affix : '')
- var e = $.Event(affixType + '.bs.affix')
+ var affixType = 'affix' + (affix ? '-' + affix : '')
+ var e = $.Event(affixType + '.bs.affix')
- this.$element.trigger(e)
+ this.$element.trigger(e)
- if (e.isDefaultPrevented()) return
+ if (e.isDefaultPrevented()) return
- this.affixed = affix
- this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
- this.$element
- .removeClass(Affix.RESET)
- .addClass(affixType)
- .trigger($.Event(affixType.replace('affix', 'affixed')))
+ this.$element
+ .removeClass(Affix.RESET)
+ .addClass(affixType)
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+ }
if (affix == 'bottom') {
this.$element.offset({
- top: scrollHeight - this.$element.height() - offsetBottom
+ top: scrollHeight - height - offsetBottom
})
}
}
@@ -132,8 +152,8 @@
data.offset = data.offset || {}
- if (data.offsetBottom) data.offset.bottom = data.offsetBottom
- if (data.offsetTop) data.offset.top = data.offsetTop
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
Plugin.call($spy, data)
})
diff --git a/assets/javascripts/bootstrap/alert.js b/assets/javascripts/bootstrap/alert.js
index 0efd92c..d47d85f 100644
--- a/assets/javascripts/bootstrap/alert.js
+++ b/assets/javascripts/bootstrap/alert.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: alert.js v3.2.0
+ * Bootstrap: alert.js v3.3.0
* http://getbootstrap.com/javascript/#alerts
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -18,7 +18,9 @@
$(el).on('click', dismiss, this.close)
}
- Alert.VERSION = '3.2.0'
+ Alert.VERSION = '3.3.0'
+
+ Alert.TRANSITION_DURATION = 150
Alert.prototype.close = function (e) {
var $this = $(this)
@@ -34,7 +36,7 @@
if (e) e.preventDefault()
if (!$parent.length) {
- $parent = $this.hasClass('alert') ? $this : $this.parent()
+ $parent = $this.closest('.alert')
}
$parent.trigger(e = $.Event('close.bs.alert'))
@@ -51,7 +53,7 @@
$.support.transition && $parent.hasClass('fade') ?
$parent
.one('bsTransitionEnd', removeElement)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
removeElement()
}
diff --git a/assets/javascripts/bootstrap/button.js b/assets/javascripts/bootstrap/button.js
index dc3164f..2be0234 100644
--- a/assets/javascripts/bootstrap/button.js
+++ b/assets/javascripts/bootstrap/button.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: button.js v3.2.0
+ * Bootstrap: button.js v3.3.0
* http://getbootstrap.com/javascript/#buttons
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -19,7 +19,7 @@
this.isLoading = false
}
- Button.VERSION = '3.2.0'
+ Button.VERSION = '3.3.0'
Button.DEFAULTS = {
loadingText: 'loading...'
@@ -35,10 +35,10 @@
if (data.resetText == null) $el.data('resetText', $el[val]())
- $el[val](data[state] == null ? this.options[state] : data[state])
-
// push to event loop to allow forms to submit
setTimeout($.proxy(function () {
+ $el[val](data[state] == null ? this.options[state] : data[state])
+
if (state == 'loadingText') {
this.isLoading = true
$el.addClass(d).attr(d, d)
@@ -60,6 +60,8 @@
else $parent.find('.active').removeClass('active')
}
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
+ } else {
+ this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
}
if (changed) this.$element.toggleClass('active')
@@ -100,11 +102,15 @@
// BUTTON DATA-API
// ===============
- $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
- var $btn = $(e.target)
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
- Plugin.call($btn, 'toggle')
- e.preventDefault()
- })
+ $(document)
+ .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ Plugin.call($btn, 'toggle')
+ e.preventDefault()
+ })
+ .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ $(e.target).closest('.btn').toggleClass('focus', e.type == 'focus')
+ })
}(jQuery);
diff --git a/assets/javascripts/bootstrap/carousel.js b/assets/javascripts/bootstrap/carousel.js
index b7da1ba..4e4e477 100644
--- a/assets/javascripts/bootstrap/carousel.js
+++ b/assets/javascripts/bootstrap/carousel.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: carousel.js v3.2.0
+ * Bootstrap: carousel.js v3.3.0
* http://getbootstrap.com/javascript/#carousel
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -14,7 +14,7 @@
// =========================
var Carousel = function (element, options) {
- this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
+ this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
this.paused =
@@ -23,17 +23,22 @@
this.$active =
this.$items = null
- this.options.pause == 'hover' && this.$element
+ this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
+
+ this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
- Carousel.VERSION = '3.2.0'
+ Carousel.VERSION = '3.3.0'
+
+ Carousel.TRANSITION_DURATION = 600
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
- wrap: true
+ wrap: true,
+ keyboard: true
}
Carousel.prototype.keydown = function (e) {
@@ -63,6 +68,13 @@
return this.$items.index(item || this.$active)
}
+ Carousel.prototype.getItemForDirection = function (direction, active) {
+ var delta = direction == 'prev' ? -1 : 1
+ var activeIndex = this.getItemIndex(active)
+ var itemIndex = (activeIndex + delta) % this.$items.length
+ return this.$items.eq(itemIndex)
+ }
+
Carousel.prototype.to = function (pos) {
var that = this
var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
@@ -72,7 +84,7 @@
if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
if (activeIndex == pos) return this.pause().cycle()
- return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
}
Carousel.prototype.pause = function (e) {
@@ -100,7 +112,7 @@
Carousel.prototype.slide = function (type, next) {
var $active = this.$element.find('.item.active')
- var $next = next || $active[type]()
+ var $next = next || this.getItemForDirection(type, $active)
var isCycling = this.interval
var direction = type == 'next' ? 'left' : 'right'
var fallback = type == 'next' ? 'first' : 'last'
@@ -146,7 +158,7 @@
that.$element.trigger(slidEvent)
}, 0)
})
- .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
} else {
$active.removeClass('active')
$next.addClass('active')
@@ -195,7 +207,7 @@
// CAROUSEL DATA-API
// =================
- $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+ var clickHandler = function (e) {
var href
var $this = $(this)
var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
@@ -211,7 +223,11 @@
}
e.preventDefault()
- })
+ }
+
+ $(document)
+ .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
+ .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
$(window).on('load', function () {
$('[data-ride="carousel"]').each(function () {
diff --git a/assets/javascripts/bootstrap/collapse.js b/assets/javascripts/bootstrap/collapse.js
index e4e6d79..4f85964 100644
--- a/assets/javascripts/bootstrap/collapse.js
+++ b/assets/javascripts/bootstrap/collapse.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: collapse.js v3.2.0
+ * Bootstrap: collapse.js v3.3.0
* http://getbootstrap.com/javascript/#collapse
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -16,16 +16,25 @@
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
+ this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
this.transitioning = null
- if (this.options.parent) this.$parent = $(this.options.parent)
+ if (this.options.parent) {
+ this.$parent = this.getParent()
+ } else {
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
+ }
+
if (this.options.toggle) this.toggle()
}
- Collapse.VERSION = '3.2.0'
+ Collapse.VERSION = '3.3.0'
+
+ Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
- toggle: true
+ toggle: true,
+ trigger: '[data-toggle="collapse"]'
}
Collapse.prototype.dimension = function () {
@@ -36,17 +45,21 @@
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
+ var activesData
+ var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
+
+ if (actives && actives.length) {
+ activesData = actives.data('bs.collapse')
+ if (activesData && activesData.transitioning) return
+ }
+
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
- var actives = this.$parent && this.$parent.find('> .panel > .in')
-
if (actives && actives.length) {
- var hasData = actives.data('bs.collapse')
- if (hasData && hasData.transitioning) return
Plugin.call(actives, 'hide')
- hasData || actives.data('bs.collapse', null)
+ activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
@@ -54,6 +67,11 @@
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
+ .attr('aria-expanded', true)
+
+ this.$trigger
+ .removeClass('collapsed')
+ .attr('aria-expanded', true)
this.transitioning = 1
@@ -72,7 +90,7 @@
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
@@ -88,17 +106,21 @@
this.$element
.addClass('collapsing')
- .removeClass('collapse')
- .removeClass('in')
+ .removeClass('collapse in')
+ .attr('aria-expanded', false)
+
+ this.$trigger
+ .addClass('collapsed')
+ .attr('aria-expanded', false)
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
- .trigger('hidden.bs.collapse')
.removeClass('collapsing')
.addClass('collapse')
+ .trigger('hidden.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
@@ -106,13 +128,40 @@
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(350)
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
+ Collapse.prototype.getParent = function () {
+ return $(this.options.parent)
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
+ .each($.proxy(function (i, element) {
+ var $element = $(element)
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
+ }, this))
+ .end()
+ }
+
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
+ var isOpen = $element.hasClass('in')
+
+ $element.attr('aria-expanded', isOpen)
+ $trigger
+ .toggleClass('collapsed', !isOpen)
+ .attr('aria-expanded', isOpen)
+ }
+
+ function getTargetFromTrigger($trigger) {
+ var href
+ var target = $trigger.attr('data-target')
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+
+ return $(target)
+ }
+
// COLLAPSE PLUGIN DEFINITION
// ==========================
@@ -123,7 +172,7 @@
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
- if (!data && options.toggle && option == 'show') option = !option
+ if (!data && options.toggle && option == 'show') options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
@@ -148,21 +197,13 @@
// =================
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
- var href
var $this = $(this)
- var target = $this.attr('data-target')
- || e.preventDefault()
- || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
- var $target = $(target)
- var data = $target.data('bs.collapse')
- var option = data ? 'toggle' : $this.data()
- var parent = $this.attr('data-parent')
- var $parent = parent && $(parent)
- if (!data || !data.transitioning) {
- if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
- $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
- }
+ if (!$this.attr('data-target')) e.preventDefault()
+
+ var $target = getTargetFromTrigger($this)
+ var data = $target.data('bs.collapse')
+ var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
Plugin.call($target, option)
})
diff --git a/assets/javascripts/bootstrap/dropdown.js b/assets/javascripts/bootstrap/dropdown.js
index 88f118c..ae192e5 100644
--- a/assets/javascripts/bootstrap/dropdown.js
+++ b/assets/javascripts/bootstrap/dropdown.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: dropdown.js v3.2.0
+ * Bootstrap: dropdown.js v3.3.0
* http://getbootstrap.com/javascript/#dropdowns
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -19,7 +19,7 @@
$(element).on('click.bs.dropdown', this.toggle)
}
- Dropdown.VERSION = '3.2.0'
+ Dropdown.VERSION = '3.3.0'
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
@@ -42,7 +42,9 @@
if (e.isDefaultPrevented()) return
- $this.trigger('focus')
+ $this
+ .trigger('focus')
+ .attr('aria-expanded', 'true')
$parent
.toggleClass('open')
@@ -53,7 +55,7 @@
}
Dropdown.prototype.keydown = function (e) {
- if (!/(38|40|27)/.test(e.keyCode)) return
+ if (!/(38|40|27|32)/.test(e.which)) return
var $this = $(this)
@@ -65,7 +67,7 @@
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
- if (!isActive || (isActive && e.keyCode == 27)) {
+ if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
@@ -75,10 +77,10 @@
if (!$items.length) return
- var index = $items.index($items.filter(':focus'))
+ var index = $items.index(e.target)
- if (e.keyCode == 38 && index > 0) index-- // up
- if (e.keyCode == 40 && index < $items.length - 1) index++ // down
+ if (e.which == 38 && index > 0) index-- // up
+ if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')
@@ -88,11 +90,17 @@
if (e && e.which === 3) return
$(backdrop).remove()
$(toggle).each(function () {
- var $parent = getParent($(this))
+ var $this = $(this)
+ var $parent = getParent($this)
var relatedTarget = { relatedTarget: this }
+
if (!$parent.hasClass('open')) return
+
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
if (e.isDefaultPrevented()) return
+
+ $this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
})
}
@@ -146,6 +154,8 @@
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
- .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
}(jQuery);
diff --git a/assets/javascripts/bootstrap/modal.js b/assets/javascripts/bootstrap/modal.js
index 29eedf1..8b0e269 100644
--- a/assets/javascripts/bootstrap/modal.js
+++ b/assets/javascripts/bootstrap/modal.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: modal.js v3.2.0
+ * Bootstrap: modal.js v3.3.0
* http://getbootstrap.com/javascript/#modals
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -30,7 +30,10 @@
}
}
- Modal.VERSION = '3.2.0'
+ Modal.VERSION = '3.3.0'
+
+ Modal.TRANSITION_DURATION = 300
+ Modal.BACKDROP_TRANSITION_DURATION = 150
Modal.DEFAULTS = {
backdrop: true,
@@ -88,7 +91,7 @@
.one('bsTransitionEnd', function () {
that.$element.trigger('focus').trigger(e)
})
- .emulateTransitionEnd(300) :
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
})
}
@@ -104,9 +107,6 @@
this.isShown = false
- this.$body.removeClass('modal-open')
-
- this.resetScrollbar()
this.escape()
$(document).off('focusin.bs.modal')
@@ -119,7 +119,7 @@
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
- .emulateTransitionEnd(300) :
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()
}
@@ -135,11 +135,11 @@
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) {
- this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide()
}, this))
} else if (!this.isShown) {
- this.$element.off('keyup.dismiss.bs.modal')
+ this.$element.off('keydown.dismiss.bs.modal')
}
}
@@ -147,6 +147,8 @@
var that = this
this.$element.hide()
this.backdrop(function () {
+ that.$body.removeClass('modal-open')
+ that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
@@ -164,14 +166,13 @@
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
- .appendTo(this.$body)
-
- this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
- if (e.target !== e.currentTarget) return
- this.options.backdrop == 'static'
- ? this.$element[0].focus.call(this.$element[0])
- : this.hide.call(this)
- }, this))
+ .prependTo(this.$element)
+ .on('click.dismiss.bs.modal', $.proxy(function (e) {
+ if (e.target !== e.currentTarget) return
+ this.options.backdrop == 'static'
+ ? this.$element[0].focus.call(this.$element[0])
+ : this.hide.call(this)
+ }, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
@@ -182,7 +183,7 @@
doAnimate ?
this.$backdrop
.one('bsTransitionEnd', callback)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callback()
} else if (!this.isShown && this.$backdrop) {
@@ -195,7 +196,7 @@
$.support.transition && this.$element.hasClass('fade') ?
this.$backdrop
.one('bsTransitionEnd', callbackRemove)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callbackRemove()
} else if (callback) {
@@ -204,8 +205,7 @@
}
Modal.prototype.checkScrollbar = function () {
- if (document.body.clientWidth >= window.innerWidth) return
- this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
+ this.scrollbarWidth = this.measureScrollbar()
}
Modal.prototype.setScrollbar = function () {
@@ -218,6 +218,7 @@
}
Modal.prototype.measureScrollbar = function () { // thx walsh
+ if (document.body.clientWidth >= window.innerWidth) return 0
var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure'
this.$body.append(scrollDiv)
diff --git a/assets/javascripts/bootstrap/popover.js b/assets/javascripts/bootstrap/popover.js
index 825e1b3..3548059 100644
--- a/assets/javascripts/bootstrap/popover.js
+++ b/assets/javascripts/bootstrap/popover.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: popover.js v3.2.0
+ * Bootstrap: popover.js v3.3.0
* http://getbootstrap.com/javascript/#popovers
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -19,7 +19,7 @@
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
- Popover.VERSION = '3.2.0'
+ Popover.VERSION = '3.3.0'
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right',
@@ -46,7 +46,7 @@
var content = this.getContent()
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
- $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
](content)
@@ -86,12 +86,18 @@
function Plugin(option) {
return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.popover')
- var options = typeof option == 'object' && option
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+ var selector = options && options.selector
if (!data && option == 'destroy') return
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (selector) {
+ if (!data) $this.data('bs.popover', (data = {}))
+ if (!data[selector]) data[selector] = new Popover(this, options)
+ } else {
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ }
if (typeof option == 'string') data[option]()
})
}
diff --git a/assets/javascripts/bootstrap/scrollspy.js b/assets/javascripts/bootstrap/scrollspy.js
index db23787..973021a 100644
--- a/assets/javascripts/bootstrap/scrollspy.js
+++ b/assets/javascripts/bootstrap/scrollspy.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: scrollspy.js v3.2.0
+ * Bootstrap: scrollspy.js v3.3.0
* http://getbootstrap.com/javascript/#scrollspy
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -30,7 +30,7 @@
this.process()
}
- ScrollSpy.VERSION = '3.2.0'
+ ScrollSpy.VERSION = '3.3.0'
ScrollSpy.DEFAULTS = {
offset: 10
@@ -91,8 +91,9 @@
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
- if (activeTarget && scrollTop <= offsets[0]) {
- return activeTarget != (i = targets[0]) && this.activate(i)
+ if (activeTarget && scrollTop < offsets[0]) {
+ this.activeTarget = null
+ return this.clear()
}
for (i = offsets.length; i--;) {
@@ -106,9 +107,7 @@
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
- $(this.selector)
- .parentsUntil(this.options.target, '.active')
- .removeClass('active')
+ this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
@@ -127,6 +126,12 @@
active.trigger('activate.bs.scrollspy')
}
+ ScrollSpy.prototype.clear = function () {
+ $(this.selector)
+ .parentsUntil(this.options.target, '.active')
+ .removeClass('active')
+ }
+
// SCROLLSPY PLUGIN DEFINITION
// ===========================
diff --git a/assets/javascripts/bootstrap/tab.js b/assets/javascripts/bootstrap/tab.js
index c0e1e46..7a68169 100644
--- a/assets/javascripts/bootstrap/tab.js
+++ b/assets/javascripts/bootstrap/tab.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: tab.js v3.2.0
+ * Bootstrap: tab.js v3.3.0
* http://getbootstrap.com/javascript/#tabs
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
@@ -17,7 +17,9 @@
this.element = $(element)
}
- Tab.VERSION = '3.2.0'
+ Tab.VERSION = '3.3.0'
+
+ Tab.TRANSITION_DURATION = 150
Tab.prototype.show = function () {
var $this = this.element
@@ -31,22 +33,30 @@
if ($this.parent('li').hasClass('active')) return
- var previous = $ul.find('.active:last a')[0]
- var e = $.Event('show.bs.tab', {
- relatedTarget: previous
+ var $previous = $ul.find('.active:last a')
+ var hideEvent = $.Event('hide.bs.tab', {
+ relatedTarget: $this[0]
+ })
+ var showEvent = $.Event('show.bs.tab', {
+ relatedTarget: $previous[0]
})
- $this.trigger(e)
+ $previous.trigger(hideEvent)
+ $this.trigger(showEvent)
- if (e.isDefaultPrevented()) return
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.closest('li'), $ul)
this.activate($target, $target.parent(), function () {
+ $previous.trigger({
+ type: 'hidden.bs.tab',
+ relatedTarget: $this[0]
+ })
$this.trigger({
type: 'shown.bs.tab',
- relatedTarget: previous
+ relatedTarget: $previous[0]
})
})
}
@@ -55,15 +65,21 @@
var $active = container.find('> .active')
var transition = callback
&& $.support.transition
- && $active.hasClass('fade')
+ && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
function next() {
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
- .removeClass('active')
+ .removeClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', false)
- element.addClass('active')
+ element
+ .addClass('active')
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
if (transition) {
element[0].offsetWidth // reflow for transition
@@ -73,16 +89,21 @@
}
if (element.parent('.dropdown-menu')) {
- element.closest('li.dropdown').addClass('active')
+ element
+ .closest('li.dropdown')
+ .addClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
}
callback && callback()
}
- transition ?
+ $active.length && transition ?
$active
.one('bsTransitionEnd', next)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
next()
$active.removeClass('in')
@@ -120,9 +141,13 @@
// TAB DATA-API
// ============
- $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+ var clickHandler = function (e) {
e.preventDefault()
Plugin.call($(this), 'show')
- })
+ }
+
+ $(document)
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
}(jQuery);
diff --git a/assets/javascripts/bootstrap/tooltip.js b/assets/javascripts/bootstrap/tooltip.js
index 9cdb6c9..68163c1 100644
--- a/assets/javascripts/bootstrap/tooltip.js
+++ b/assets/javascripts/bootstrap/tooltip.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: tooltip.js v3.2.0
+ * Bootstrap: tooltip.js v3.3.0
* http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
@@ -25,7 +25,9 @@
this.init('tooltip', element, options)
}
- Tooltip.VERSION = '3.2.0'
+ Tooltip.VERSION = '3.3.0'
+
+ Tooltip.TRANSITION_DURATION = 150
Tooltip.DEFAULTS = {
animation: true,
@@ -103,6 +105,11 @@
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
+ if (self && self.$tip && self.$tip.is(':visible')) {
+ self.hoverState = 'in'
+ return
+ }
+
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
@@ -145,7 +152,7 @@
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
- var inDom = $.contains(document.documentElement, this.$element[0])
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
var that = this
@@ -181,13 +188,13 @@
if (autoPlace) {
var orgPlacement = placement
- var $parent = this.$element.parent()
- var parentDim = this.getPosition($parent)
+ var $container = this.options.container ? $(this.options.container) : this.$element.parent()
+ var containerDim = this.getPosition($container)
- placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
- placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
- placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
- placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
+ placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
+ placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
+ placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
+ placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement
$tip
@@ -200,14 +207,17 @@
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
+ var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
+
+ if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
}
}
@@ -254,16 +264,18 @@
if (delta.left) offset.left += delta.left
else offset.top += delta.top
- var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
- var arrowPosition = delta.left ? 'left' : 'top'
- var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
+ var isVertical = /top|bottom/.test(placement)
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$tip.offset(offset)
- this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
}
- Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
- this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
+ this.arrow()
+ .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+ .css(isHorizontal ? 'top' : 'left', '')
}
Tooltip.prototype.setContent = function () {
@@ -274,16 +286,17 @@
$tip.removeClass('fade in top bottom left right')
}
- Tooltip.prototype.hide = function () {
+ Tooltip.prototype.hide = function (callback) {
var that = this
var $tip = this.tip()
var e = $.Event('hide.bs.' + this.type)
- this.$element.removeAttr('aria-describedby')
-
function complete() {
if (that.hoverState != 'in') $tip.detach()
- that.$element.trigger('hidden.bs.' + that.type)
+ that.$element
+ .removeAttr('aria-describedby')
+ .trigger('hidden.bs.' + that.type)
+ callback && callback()
}
this.$element.trigger(e)
@@ -295,7 +308,7 @@
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
- .emulateTransitionEnd(150) :
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
this.hoverState = null
@@ -316,13 +329,20 @@
Tooltip.prototype.getPosition = function ($element) {
$element = $element || this.$element
+
var el = $element[0]
var isBody = el.tagName == 'BODY'
- return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
- scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
- width: isBody ? $(window).width() : $element.outerWidth(),
- height: isBody ? $(window).height() : $element.outerHeight()
- }, isBody ? { top: 0, left: 0 } : $element.offset())
+
+ var elRect = el.getBoundingClientRect()
+ if (elRect.width == null) {
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
+ }
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
+
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
@@ -386,14 +406,6 @@
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
}
- Tooltip.prototype.validate = function () {
- if (!this.$element[0].parentNode) {
- this.hide()
- this.$element = null
- this.options = null
- }
- }
-
Tooltip.prototype.enable = function () {
this.enabled = true
}
@@ -420,8 +432,11 @@
}
Tooltip.prototype.destroy = function () {
+ var that = this
clearTimeout(this.timeout)
- this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
+ this.hide(function () {
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
+ })
}
@@ -430,12 +445,18 @@
function Plugin(option) {
return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.tooltip')
- var options = typeof option == 'object' && option
+ var $this = $(this)
+ var data = $this.data('bs.tooltip')
+ var options = typeof option == 'object' && option
+ var selector = options && options.selector
if (!data && option == 'destroy') return
- if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ if (selector) {
+ if (!data) $this.data('bs.tooltip', (data = {}))
+ if (!data[selector]) data[selector] = new Tooltip(this, options)
+ } else {
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ }
if (typeof option == 'string') data[option]()
})
}
diff --git a/assets/javascripts/bootstrap/transition.js b/assets/javascripts/bootstrap/transition.js
index 83f85bf..8199383 100644
--- a/assets/javascripts/bootstrap/transition.js
+++ b/assets/javascripts/bootstrap/transition.js
@@ -1,5 +1,5 @@
/* ========================================================================
- * Bootstrap: transition.js v3.2.0
+ * Bootstrap: transition.js v3.3.0
* http://getbootstrap.com/javascript/#transitions
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
diff --git a/assets/stylesheets/bootstrap/_button-groups.scss b/assets/stylesheets/bootstrap/_button-groups.scss
index 63ccd92..9bfa085 100644
--- a/assets/stylesheets/bootstrap/_button-groups.scss
+++ b/assets/stylesheets/bootstrap/_button-groups.scss
@@ -38,7 +38,7 @@
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
margin-left: -5px; // Offset the first child's margin
- @include clearfix();
+ @include clearfix;
.btn-group,
.input-group {
@@ -156,7 +156,7 @@
// Clear floats so dropdown menus can be properly placed
> .btn-group {
- @include clearfix();
+ @include clearfix;
> .btn {
float: none;
}
@@ -198,7 +198,6 @@
}
-
// Justified button groups
// ----------------------
@@ -226,15 +225,23 @@
// Checkbox and radio options
//
// In order to support the browser's form validation feedback, powered by the
-// `required` attribute, we have to "hide" the inputs via `opacity`. We cannot
-// use `display: none;` or `visibility: hidden;` as that also hides the popover.
+// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
+// `display: none;` or `visibility: hidden;` as that also hides the popover.
+// Simply visually hiding the inputs via `opacity` would leave them clickable in
+// certain cases which is prevented by using `clip` and `pointer-events`.
// This way, we ensure a DOM element is visible to position the popover from.
//
-// See https://github.com/twbs/bootstrap/pull/12794 for more.
+// See https://github.com/twbs/bootstrap/pull/12794 and
+// https://github.com/twbs/bootstrap/pull/14559 for more information.
-[data-toggle="buttons"] > .btn > input[type="radio"],
-[data-toggle="buttons"] > .btn > input[type="checkbox"] {
- position: absolute;
- z-index: -1;
- @include opacity(0);
+[data-toggle="buttons"] {
+ > .btn,
+ > .btn-group > .btn {
+ input[type="radio"],
+ input[type="checkbox"] {
+ position: absolute;
+ clip: rect(0,0,0,0);
+ pointer-events: none;
+ }
+ }
}
diff --git a/assets/stylesheets/bootstrap/_buttons.scss b/assets/stylesheets/bootstrap/_buttons.scss
index dae6ee3..37bf259 100644
--- a/assets/stylesheets/bootstrap/_buttons.scss
+++ b/assets/stylesheets/bootstrap/_buttons.scss
@@ -12,6 +12,7 @@
font-weight: $btn-font-weight;
text-align: center;
vertical-align: middle;
+ touch-action: manipulation;
cursor: pointer;
background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
border: 1px solid transparent;
@@ -22,13 +23,15 @@
&,
&:active,
&.active {
- &:focus {
- @include tab-focus();
+ &:focus,
+ &.focus {
+ @include tab-focus;
}
}
&:hover,
- &:focus {
+ &:focus,
+ &.focus {
color: $btn-default-color;
text-decoration: none;
}
@@ -43,7 +46,7 @@
&.disabled,
&[disabled],
fieldset[disabled] & {
- cursor: not-allowed;
+ cursor: $cursor-disabled;
pointer-events: none; // Future-proof disabling of clicks
@include opacity(.65);
@include box-shadow(none);
@@ -85,11 +88,11 @@
.btn-link {
color: $link-color;
font-weight: normal;
- cursor: pointer;
border-radius: 0;
&,
&:active,
+ &.active,
&[disabled],
fieldset[disabled] & {
background-color: transparent;
diff --git a/assets/stylesheets/bootstrap/_carousel.scss b/assets/stylesheets/bootstrap/_carousel.scss
index e9e2f7c..49db83f 100644
--- a/assets/stylesheets/bootstrap/_carousel.scss
+++ b/assets/stylesheets/bootstrap/_carousel.scss
@@ -21,9 +21,33 @@
// Account for jankitude on images
> img,
> a > img {
- @include img-responsive();
+ @include img-responsive;
line-height: 1;
}
+
+ // WebKit CSS3 transforms for supported devices
+ @media all and (transform-3d), (-webkit-transform-3d) {
+ transition: transform .6s ease-in-out;
+ backface-visibility: hidden;
+ perspective: 1000;
+
+ &.next,
+ &.active.right {
+ transform: translate3d(100%, 0, 0);
+ left: 0;
+ }
+ &.prev,
+ &.active.left {
+ transform: translate3d(-100%, 0, 0);
+ left: 0;
+ }
+ &.next.left,
+ &.prev.right,
+ &.active {
+ transform: translate3d(0, 0, 0);
+ left: 0;
+ }
+ }
}
> .active,
diff --git a/assets/stylesheets/bootstrap/_code.scss b/assets/stylesheets/bootstrap/_code.scss
index 8d83b14..caa5f06 100644
--- a/assets/stylesheets/bootstrap/_code.scss
+++ b/assets/stylesheets/bootstrap/_code.scss
@@ -32,6 +32,7 @@ kbd {
kbd {
padding: 0;
font-size: 100%;
+ font-weight: bold;
box-shadow: none;
}
}
diff --git a/assets/stylesheets/bootstrap/_component-animations.scss b/assets/stylesheets/bootstrap/_component-animations.scss
index 8c3fd07..1f76b8c 100644
--- a/assets/stylesheets/bootstrap/_component-animations.scss
+++ b/assets/stylesheets/bootstrap/_component-animations.scss
@@ -17,8 +17,9 @@
.collapse {
display: none;
+ visibility: hidden;
- &.in { display: block; }
+ &.in { display: block; visibility: visible; }
// [converter] extracted tr&.in to tr.collapse.in
// [converter] extracted tbody&.in to tbody.collapse.in
}
@@ -31,5 +32,7 @@ tbody.collapse.in { display: table-row-group; }
position: relative;
height: 0;
overflow: hidden;
- @include transition(height .35s ease);
+ @include transition-property(height, visibility);
+ @include transition-duration(.35s);
+ @include transition-timing-function(ease);
}
diff --git a/assets/stylesheets/bootstrap/_dropdowns.scss b/assets/stylesheets/bootstrap/_dropdowns.scss
index eb74be5..c7256e1 100644
--- a/assets/stylesheets/bootstrap/_dropdowns.scss
+++ b/assets/stylesheets/bootstrap/_dropdowns.scss
@@ -103,16 +103,15 @@
&:focus {
color: $dropdown-link-disabled-color;
}
-}
-// Nuke hover/focus effects
-.dropdown-menu > .disabled > a {
+
+ // Nuke hover/focus effects
&:hover,
&:focus {
text-decoration: none;
background-color: transparent;
background-image: none; // Remove CSS gradient
- @include reset-filter();
- cursor: not-allowed;
+ @include reset-filter;
+ cursor: $cursor-disabled;
}
}
@@ -212,4 +211,3 @@
}
}
}
-
diff --git a/assets/stylesheets/bootstrap/_forms.scss b/assets/stylesheets/bootstrap/_forms.scss
index 74bb67d..4e694b3 100644
--- a/assets/stylesheets/bootstrap/_forms.scss
+++ b/assets/stylesheets/bootstrap/_forms.scss
@@ -77,7 +77,7 @@ select[size] {
input[type="file"]:focus,
input[type="radio"]:focus,
input[type="checkbox"]:focus {
- @include tab-focus();
+ @include tab-focus;
}
// Adjust output element
@@ -128,10 +128,10 @@ output {
@include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
// Customize the `:focus` state to imitate native WebKit styles.
- @include form-control-focus();
+ @include form-control-focus;
// Placeholder
- @include placeholder();
+ @include placeholder;
// Disabled and read-only inputs
//
@@ -141,7 +141,7 @@ output {
&[disabled],
&[readonly],
fieldset[disabled] & {
- cursor: not-allowed;
+ cursor: $cursor-disabled;
background-color: $input-bg-disabled;
opacity: 1; // iOS fix for unreadable disabled content
}
@@ -185,9 +185,26 @@ input[type="month"] {
&.input-sm {
line-height: $input-height-small;
+ line-height: $line-height-small #{\0};
}
&.input-lg {
line-height: $input-height-large;
+ line-height: $line-height-large #{\0};
+ }
+}
+
+// IE 11 hack to reverse the iOS temporal input hack.
+_:-ms-fullscreen, :root input[type="date"],
+_:-ms-fullscreen, :root input[type="time"],
+_:-ms-fullscreen, :root input[type="datetime-local"],
+_:-ms-fullscreen, :root input[type="month"] {
+ line-height: $line-height-base;
+
+ &.input-sm {
+ line-height: $line-height-small;
+ }
+ &.input-lg {
+ line-height: $line-height-large;
}
}
@@ -210,11 +227,11 @@ input[type="month"] {
.checkbox {
position: relative;
display: block;
- min-height: $line-height-computed; // clear the floating input if there is no label text
margin-top: 10px;
margin-bottom: 10px;
label {
+ min-height: $line-height-computed; // Ensure the input doesn't jump when there is no text
padding-left: 20px;
margin-bottom: 0;
font-weight: normal;
@@ -260,7 +277,7 @@ input[type="checkbox"] {
&[disabled],
&.disabled,
fieldset[disabled] & {
- cursor: not-allowed;
+ cursor: $cursor-disabled;
}
}
// These classes are used directly on <label>s
@@ -268,7 +285,7 @@ input[type="checkbox"] {
.checkbox-inline {
&.disabled,
fieldset[disabled] & {
- cursor: not-allowed;
+ cursor: $cursor-disabled;
}
}
// These classes are used on elements with <label> descendants
@@ -277,7 +294,7 @@ input[type="checkbox"] {
&.disabled,
fieldset[disabled] & {
label {
- cursor: not-allowed;
+ cursor: $cursor-disabled;
}
}
}
@@ -308,9 +325,9 @@ input[type="checkbox"] {
// Build on `.form-control` with modifier classes to decrease or increase the
// height and font-size of form controls.
-@include input-size('.input-sm', $input-height-small, $padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small);
+@include input-size('.input-sm, .form-group-sm .form-control', $input-height-small, $padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $input-border-radius-small);
-@include input-size('.input-lg', $input-height-large, $padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large);
+@include input-size('.input-lg, .form-group-lg .form-control', $input-height-large, $padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $input-border-radius-large);
// Form control feedback states
@@ -329,7 +346,7 @@ input[type="checkbox"] {
// Feedback icon (requires .glyphicon classes)
.form-control-feedback {
position: absolute;
- top: ($line-height-computed + 5); // Height of the `label` and its margin
+ top: 0;
right: 0;
z-index: 2; // Ensure icon is above input groups
display: block;
@@ -337,6 +354,7 @@ input[type="checkbox"] {
height: $input-height-base;
line-height: $input-height-base;
text-align: center;
+ pointer-events: none;
}
.input-lg + .form-control-feedback {
width: $input-height-large;
@@ -360,10 +378,15 @@ input[type="checkbox"] {
@include form-control-validation($state-danger-text, $state-danger-text, $state-danger-bg);
}
+// Reposition feedback icon if input has visible label above
+.has-feedback label {
-// Reposition feedback icon if label is hidden with "screenreader only" state
-.has-feedback label.sr-only ~ .form-control-feedback {
- top: 0;
+ & ~ .form-control-feedback {
+ top: ($line-height-computed + 5); // Height of the `label` and its margin
+ }
+ &.sr-only ~ .form-control-feedback {
+ top: 0;
+ }
}
@@ -380,7 +403,6 @@ input[type="checkbox"] {
}
-
// Inline forms
//
// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
@@ -392,7 +414,8 @@ input[type="checkbox"] {
//
// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
-.form-inline {
+// [converter] extracted from `.form-inline` for libsass compatibility
+@mixin form-inline {
// Kick in the inline
@media (min-width: $screen-sm-min) {
@@ -410,6 +433,11 @@ input[type="checkbox"] {
vertical-align: middle;
}
+ // Make static controls behave like regular ones
+ .form-control-static {
+ display: inline-block;
+ }
+
.input-group {
display: inline-table;
vertical-align: middle;
@@ -451,15 +479,17 @@ input[type="checkbox"] {
margin-left: 0;
}
- // Validation states
- //
- // Reposition the icon because it's now within a grid column and columns have
- // `position: relative;` on them. Also accounts for the grid gutter padding.
+ // Re-override the feedback icon.
.has-feedback .form-control-feedback {
top: 0;
}
}
}
+// [converter] extracted as `@mixin form-inline` for libsass compatibility
+.form-inline {
+ @include form-inline;
+}
+
// Horizontal forms
@@ -489,7 +519,7 @@ input[type="checkbox"] {
// Make form groups behave like rows
.form-group {
- @include make-row();
+ @include make-row;
}
// Reset spacing and right align labels, but scope to media queries so that
@@ -507,7 +537,6 @@ input[type="checkbox"] {
// Reposition the icon because it's now within a grid column and columns have
// `position: relative;` on them. Also accounts for the grid gutter padding.
.has-feedback .form-control-feedback {
- top: 0;
right: ($grid-gutter-width / 2);
}
@@ -521,9 +550,6 @@ input[type="checkbox"] {
padding-top: (($padding-large-vertical * $line-height-large) + 1);
}
}
- .form-control {
- @extend .input-lg;
- }
}
.form-group-sm {
@media (min-width: $screen-sm-min) {
@@ -531,8 +557,5 @@ input[type="checkbox"] {
padding-top: ($padding-small-vertical + 1);
}
}
- .form-control {
- @extend .input-sm;
- }
}
}
diff --git a/assets/stylesheets/bootstrap/_glyphicons.scss b/assets/stylesheets/bootstrap/_glyphicons.scss
index 0f6ad34..5486eaa 100644
--- a/assets/stylesheets/bootstrap/_glyphicons.scss
+++ b/assets/stylesheets/bootstrap/_glyphicons.scss
@@ -1,7 +1,3 @@
-//= depend_on "bootstrap/glyphicons-halflings-regular.eot"
-//= depend_on "bootstrap/glyphicons-halflings-regular.svg"
-//= depend_on "bootstrap/glyphicons-halflings-regular.ttf"
-//= depend_on "bootstrap/glyphicons-halflings-regular.woff"
//
// Glyphicons for Bootstrap
//
@@ -37,7 +33,8 @@
// Individual icons
.glyphicon-asterisk { &:before { content: "\2a"; } }
.glyphicon-plus { &:before { content: "\2b"; } }
-.glyphicon-euro { &:before { content: "\20ac"; } }
+.glyphicon-euro,
+.glyphicon-eur { &:before { content: "\20ac"; } }
.glyphicon-minus { &:before { content: "\2212"; } }
.glyphicon-cloud { &:before { content: "\2601"; } }
.glyphicon-envelope { &:before { content: "\2709"; } }
diff --git a/assets/stylesheets/bootstrap/_grid.scss b/assets/stylesheets/bootstrap/_grid.scss
index f71f8b9..b15ca27 100644
--- a/assets/stylesheets/bootstrap/_grid.scss
+++ b/assets/stylesheets/bootstrap/_grid.scss
@@ -8,7 +8,7 @@
// Set the container width, and override it for fixed navbars in media queries.
.container {
- @include container-fixed();
+ @include container-fixed;
@media (min-width: $screen-sm-min) {
width: $container-sm;
@@ -28,7 +28,7 @@
// width for fluid, full width layouts.
.container-fluid {
- @include container-fixed();
+ @include container-fixed;
}
@@ -37,7 +37,7 @@
// Rows contain and clear the floats of your columns.
.row {
- @include make-row();
+ @include make-row;
}
@@ -45,7 +45,7 @@
//
// Common styles for small and large grid columns
-@include make-grid-columns();
+@include make-grid-columns;
// Extra small grid
diff --git a/assets/stylesheets/bootstrap/_jumbotron.scss b/assets/stylesheets/bootstrap/_jumbotron.scss
index 75efe64..f386213 100644
--- a/assets/stylesheets/bootstrap/_jumbotron.scss
+++ b/assets/stylesheets/bootstrap/_jumbotron.scss
@@ -4,7 +4,7 @@
.jumbotron {
- padding: $jumbotron-padding;
+ padding: $jumbotron-padding ($jumbotron-padding / 2);
margin-bottom: $jumbotron-padding;
color: $jumbotron-color;
background-color: $jumbotron-bg;
@@ -23,7 +23,8 @@
border-top-color: darken($jumbotron-bg, 10%);
}
- .container & {
+ .container &,
+ .container-fluid & {
border-radius: $border-radius-large; // Only round corners at higher resolutions if contained in a container
}
@@ -32,8 +33,7 @@
}
@media screen and (min-width: $screen-sm-min) {
- padding-top: ($jumbotron-padding * 1.6);
- padding-bottom: ($jumbotron-padding * 1.6);
+ padding: ($jumbotron-padding * 1.6) 0;
.container & {
padding-left: ($jumbotron-padding * 2);
diff --git a/assets/stylesheets/bootstrap/_list-group.scss b/assets/stylesheets/bootstrap/_list-group.scss
index 36c297c..14912b1 100644
--- a/assets/stylesheets/bootstrap/_list-group.scss
+++ b/assets/stylesheets/bootstrap/_list-group.scss
@@ -74,6 +74,7 @@ a.list-group-item {
&.disabled:focus {
background-color: $list-group-disabled-bg;
color: $list-group-disabled-color;
+ cursor: $cursor-disabled;
// Force color to inherit for custom content
.list-group-item-heading {
diff --git a/assets/stylesheets/bootstrap/_media.scss b/assets/stylesheets/bootstrap/_media.scss
index 5ad22cd..292e98d 100644
--- a/assets/stylesheets/bootstrap/_media.scss
+++ b/assets/stylesheets/bootstrap/_media.scss
@@ -1,54 +1,45 @@
-// Media objects
-// Source: http://stubbornella.org/content/?p=497
-// --------------------------------------------------
+.media {
+ // Proper spacing between instances of .media
+ margin-top: 15px;
+
+ &:first-child {
+ margin-top: 0;
+ }
+}
+.media-right,
+.media > .pull-right {
+ padding-left: 10px;
+}
-// Common styles
-// -------------------------
+.media-left,
+.media > .pull-left {
+ padding-right: 10px;
+}
-// Clear the floats
-.media,
+.media-left,
+.media-right,
.media-body {
- overflow: hidden;
- zoom: 1;
+ display: table-cell;
+ vertical-align: top;
}
-// Proper spacing between instances of .media
-.media,
-.media .media {
- margin-top: 15px;
-}
-.media:first-child {
- margin-top: 0;
+.media-middle {
+ vertical-align: middle;
}
-// For images and videos, set to block
-.media-object {
- display: block;
+.media-bottom {
+ vertical-align: bottom;
}
// Reset margins on headings for tighter default spacing
.media-heading {
- margin: 0 0 5px;
-}
-
-
-// Media image alignment
-// -------------------------
-
-.media {
- > .pull-left {
- margin-right: 10px;
- }
- > .pull-right {
- margin-left: 10px;
- }
+ margin-top: 0;
+ margin-bottom: 5px;
}
-
// Media list variation
-// -------------------------
-
+//
// Undo default ul/ol styles
.media-list {
padding-left: 0;
diff --git a/assets/stylesheets/bootstrap/_modals.scss b/assets/stylesheets/bootstrap/_modals.scss
index 785ca5c..fea4f36 100644
--- a/assets/stylesheets/bootstrap/_modals.scss
+++ b/assets/stylesheets/bootstrap/_modals.scss
@@ -30,10 +30,10 @@
// When fading in the modal, animate it to slide down
&.fade .modal-dialog {
- @include translate3d(0, -25%, 0);
+ @include translate(0, -25%);
@include transition-transform(0.3s ease-out);
}
- &.in .modal-dialog { @include translate3d(0, 0, 0) }
+ &.in .modal-dialog { @include translate(0, 0) }
}
.modal-open .modal {
overflow-x: hidden;
@@ -67,7 +67,6 @@
right: 0;
bottom: 0;
left: 0;
- z-index: $zindex-modal-background;
background-color: $modal-backdrop-bg;
// Fade for backdrop
&.fade { @include opacity(0); }
@@ -104,7 +103,7 @@
padding: $modal-inner-padding;
text-align: right; // right align buttons
border-top: 1px solid $modal-footer-border-color;
- @include clearfix(); // clear it in case folks use .pull-* classes on buttons
+ @include clearfix; // clear it in case folks use .pull-* classes on buttons
// Properly space out buttons
.btn + .btn {
diff --git a/assets/stylesheets/bootstrap/_navbar.scss b/assets/stylesheets/bootstrap/_navbar.scss
index 3b94d6f..8737ad3 100644
--- a/assets/stylesheets/bootstrap/_navbar.scss
+++ b/assets/stylesheets/bootstrap/_navbar.scss
@@ -15,7 +15,7 @@
border: 1px solid transparent;
// Prevent floats from breaking the navbar
- @include clearfix();
+ @include clearfix;
@media (min-width: $grid-float-breakpoint) {
border-radius: $navbar-border-radius;
@@ -29,7 +29,7 @@
// styling of responsive aspects.
.navbar-header {
- @include clearfix();
+ @include clearfix;
@media (min-width: $grid-float-breakpoint) {
float: left;
@@ -53,7 +53,7 @@
padding-left: $navbar-padding-horizontal;
border-top: 1px solid transparent;
box-shadow: inset 0 1px 0 rgba(255,255,255,.1);
- @include clearfix();
+ @include clearfix;
-webkit-overflow-scrolling: touch;
&.in {
@@ -67,6 +67,7 @@
&.collapse {
display: block !important;
+ visibility: visible !important;
height: auto !important;
padding-bottom: 0; // Override default setting
overflow: visible !important;
@@ -92,7 +93,7 @@
.navbar-collapse {
max-height: $navbar-collapse-max-height;
- @media (max-width: $screen-xs-min) and (orientation: landscape) {
+ @media (max-device-width: $screen-xs-min) and (orientation: landscape) {
max-height: 200px;
}
}
@@ -141,7 +142,6 @@
right: 0;
left: 0;
z-index: $zindex-navbar-fixed;
- @include translate3d(0, 0, 0);
// Undo the rounded corners
@media (min-width: $grid-float-breakpoint) {
@@ -173,6 +173,10 @@
text-decoration: none;
}
+ > img {
+ display: block;
+ }
+
@media (min-width: $grid-float-breakpoint) {
.navbar > .container &,
.navbar > .container-fluid & {
@@ -271,26 +275,6 @@
padding-bottom: $navbar-padding-vertical;
}
}
-
- &.navbar-right:last-child {
- margin-right: -$navbar-padding-horizontal;
- }
- }
-}
-
-
-// Component alignment
-//
-// Repurpose the pull utilities as their own navbar utilities to avoid specificity
-// issues with parents and chaining. Only do this when the navbar is uncollapsed
-// though so that navbar contents properly stack and align in mobile.
-
-@media (min-width: $grid-float-breakpoint) {
- .navbar-left {
- float: left !important;
- }
- .navbar-right {
- float: right !important;
}
}
@@ -310,11 +294,15 @@
@include box-shadow($shadow);
// Mixin behavior for optimum display
- @extend .form-inline;
+ @include form-inline;
.form-group {
@media (max-width: $grid-float-breakpoint-max) {
margin-bottom: 5px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
}
}
@@ -330,11 +318,6 @@
padding-top: 0;
padding-bottom: 0;
@include box-shadow(none);
-
- // Outdent the form if last child to line up with content down the page
- &.navbar-right:last-child {
- margin-right: -$navbar-padding-horizontal;
- }
}
}
@@ -379,14 +362,33 @@
float: left;
margin-left: $navbar-padding-horizontal;
margin-right: $navbar-padding-horizontal;
+ }
+}
+
+
+// Component alignment
+//
+// Repurpose the pull utilities as their own navbar utilities to avoid specificity
+// issues with parents and chaining. Only do this when the navbar is uncollapsed
+// though so that navbar contents properly stack and align in mobile.
+//
+// Declared after the navbar components to ensure more specificity on the margins.
- // Outdent the form if last child to line up with content down the page
- &.navbar-right:last-child {
+@media (min-width: $grid-float-breakpoint) {
+ .navbar-left {
+ float: left !important;
+ }
+ .navbar-right {
+ float: right !important;
+ margin-right: -$navbar-padding-horizontal;
+
+ ~ .navbar-right {
margin-right: 0;
}
}
}
+
// Alternate navbars
// --------------------------------------------------
diff --git a/assets/stylesheets/bootstrap/_navs.scss b/assets/stylesheets/bootstrap/_navs.scss
index 9016873..ce0b917 100644
--- a/assets/stylesheets/bootstrap/_navs.scss
+++ b/assets/stylesheets/bootstrap/_navs.scss
@@ -10,7 +10,7 @@
margin-bottom: 0;
padding-left: 0; // Override default ul/ol
list-style: none;
- @include clearfix();
+ @include clearfix;
> li {
position: relative;
@@ -36,7 +36,7 @@
color: $nav-disabled-link-hover-color;
text-decoration: none;
background-color: transparent;
- cursor: not-allowed;
+ cursor: $cursor-disabled;
}
}
}
@@ -57,7 +57,7 @@
// we missed it. We don't currently support this anywhere, but in the interest
// of maintaining backward compatibility in case you use it, it's deprecated.
.nav-divider {
- @include nav-divider();
+ @include nav-divider;
}
// Prevent IE8 from misplacing imgs
@@ -223,9 +223,11 @@
.tab-content {
> .tab-pane {
display: none;
+ visibility: hidden;
}
> .active {
display: block;
+ visibility: visible;
}
}
diff --git a/assets/stylesheets/bootstrap/_normalize.scss b/assets/stylesheets/bootstrap/_normalize.scss
index ce04b6a..62a085a 100644
--- a/assets/stylesheets/bootstrap/_normalize.scss
+++ b/assets/stylesheets/bootstrap/_normalize.scss
@@ -1,4 +1,4 @@
-/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
//
// 1. Set default font family to sans-serif.
@@ -25,7 +25,8 @@ body {
//
// Correct `block` display not defined for any HTML5 element in IE 8/9.
-// Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.
+// Correct `block` display not defined for `details` or `summary` in IE 10/11
+// and Firefox.
// Correct `block` display not defined for `main` in IE 11.
//
@@ -38,6 +39,7 @@ footer,
header,
hgroup,
main,
+menu,
nav,
section,
summary {
@@ -85,7 +87,7 @@ template {
//
a {
- background: transparent;
+ background-color: transparent;
}
//
diff --git a/assets/stylesheets/bootstrap/_pager.scss b/assets/stylesheets/bootstrap/_pager.scss
index 6531fe6..c234217 100644
--- a/assets/stylesheets/bootstrap/_pager.scss
+++ b/assets/stylesheets/bootstrap/_pager.scss
@@ -8,7 +8,7 @@
margin: $line-height-computed 0;
list-style: none;
text-align: center;
- @include clearfix();
+ @include clearfix;
li {
display: inline;
> a,
@@ -48,8 +48,7 @@
> span {
color: $pager-disabled-color;
background-color: $pager-bg;
- cursor: not-allowed;
+ cursor: $cursor-disabled;
}
}
-
}
diff --git a/assets/stylesheets/bootstrap/_pagination.scss b/assets/stylesheets/bootstrap/_pagination.scss
index 44c1222..323ec72 100644
--- a/assets/stylesheets/bootstrap/_pagination.scss
+++ b/assets/stylesheets/bootstrap/_pagination.scss
@@ -69,7 +69,7 @@
color: $pagination-disabled-color;
background-color: $pagination-disabled-bg;
border-color: $pagination-disabled-border;
- cursor: not-allowed;
+ cursor: $cursor-disabled;
}
}
}
diff --git a/assets/stylesheets/bootstrap/_panels.scss b/assets/stylesheets/bootstrap/_panels.scss
index 57cdcbc..6c323d9 100644
--- a/assets/stylesheets/bootstrap/_panels.scss
+++ b/assets/stylesheets/bootstrap/_panels.scss
@@ -15,7 +15,7 @@
// Panel contents
.panel-body {
padding: $panel-body-padding;
- @include clearfix();
+ @include clearfix;
}
// Optional heading
@@ -56,7 +56,8 @@
// any kind of custom content between the two.
.panel {
- > .list-group {
+ > .list-group,
+ > .panel-collapse > .list-group {
margin-bottom: 0;
.list-group-item {
@@ -100,6 +101,11 @@
> .table-responsive > .table,
> .panel-collapse > .table {
margin-bottom: 0;
+
+ caption {
+ padding-left: $panel-body-padding;
+ padding-right: $panel-body-padding;
+ }
}
// Add border top radius for first one
> .table:first-child,
@@ -109,6 +115,9 @@
> thead:first-child,
> tbody:first-child {
> tr:first-child {
+ border-top-left-radius: ($panel-border-radius - 1);
+ border-top-right-radius: ($panel-border-radius - 1);
+
td:first-child,
th:first-child {
border-top-left-radius: ($panel-border-radius - 1);
@@ -128,6 +137,9 @@
> tbody:last-child,
> tfoot:last-child {
> tr:last-child {
+ border-bottom-left-radius: ($panel-border-radius - 1);
+ border-bottom-right-radius: ($panel-border-radius - 1);
+
td:first-child,
th:first-child {
border-bottom-left-radius: ($panel-border-radius - 1);
@@ -140,7 +152,9 @@
}
}
> .panel-body + .table,
- > .panel-body + .table-responsive {
+ > .panel-body + .table-responsive,
+ > .table + .panel-body,
+ > .table-responsive + .panel-body {
border-top: 1px solid $table-border-color;
}
> .table > tbody:first-child > tr:first-child th,
@@ -202,6 +216,7 @@
.panel {
margin-bottom: 0;
border-radius: $panel-border-radius;
+
+ .panel {
margin-top: 5px;
}
@@ -209,10 +224,13 @@
.panel-heading {
border-bottom: 0;
- + .panel-collapse > .panel-body {
+
+ + .panel-collapse > .panel-body,
+ + .panel-collapse > .list-group {
border-top: 1px solid $panel-inner-border;
}
}
+
.panel-footer {
border-top: 0;
+ .panel-collapse .panel-body {
diff --git a/assets/stylesheets/bootstrap/_popovers.scss b/assets/stylesheets/bootstrap/_popovers.scss
index 1cf27ae..9e28c3c 100644
--- a/assets/stylesheets/bootstrap/_popovers.scss
+++ b/assets/stylesheets/bootstrap/_popovers.scss
@@ -11,7 +11,11 @@
display: none;
max-width: $popover-max-width;
padding: 1px;
- text-align: left; // Reset given new insertion method
+ // Reset font and text propertes given new insertion method
+ font-size: $font-size-base;
+ font-weight: normal;
+ line-height: $line-height-base;
+ text-align: left;
background-color: $popover-bg;
background-clip: padding-box;
border: 1px solid $popover-fallback-border-color;
@@ -33,8 +37,6 @@
margin: 0; // reset heading margin
padding: 8px 14px;
font-size: $font-size-base;
- font-weight: normal;
- line-height: 18px;
background-color: $popover-title-bg;
border-bottom: 1px solid darken($popover-title-bg, 5%);
border-radius: ($border-radius-large - 1) ($border-radius-large - 1) 0 0;
@@ -129,5 +131,4 @@
bottom: -$popover-arrow-width;
}
}
-
}
diff --git a/assets/stylesheets/bootstrap/_print.scss b/assets/stylesheets/bootstrap/_print.scss
index 3655d03..94ca58f 100644
--- a/assets/stylesheets/bootstrap/_print.scss
+++ b/assets/stylesheets/bootstrap/_print.scss
@@ -1,101 +1,107 @@
-//
-// Basic print styles
-// --------------------------------------------------
-// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css
+/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
+
+// ==========================================================================
+// Print styles.
+// Inlined to avoid the additional HTTP request: h5bp.com/r
+// ==========================================================================
@media print {
+ *,
+ *:before,
+ *:after {
+ background: transparent !important;
+ color: #000 !important; // Black prints faster: h5bp.com/s
+ box-shadow: none !important;
+ text-shadow: none !important;
+ }
+
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+
+ // Don't show links that are fragment identifiers,
+ // or use the `javascript:` pseudo protocol
+ a[href^="#"]:after,
+ a[href^="javascript:"]:after {
+ content: "";
+ }
+
+ pre,
+ blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid;
+ }
+
+ thead {
+ display: table-header-group; // h5bp.com/t
+ }
+
+ tr,
+ img {
+ page-break-inside: avoid;
+ }
- * {
- text-shadow: none !important;
- color: #000 !important; // Black prints faster: h5bp.com/s
- background: transparent !important;
- box-shadow: none !important;
- }
-
- a,
- a:visited {
- text-decoration: underline;
- }
-
- a[href]:after {
- content: " (" attr(href) ")";
- }
-
- abbr[title]:after {
- content: " (" attr(title) ")";
- }
-
- // Don't show links for images, or javascript/internal links
- a[href^="javascript:"]:after,
- a[href^="#"]:after {
- content: "";
- }
-
- pre,
- blockquote {
- border: 1px solid #999;
- page-break-inside: avoid;
- }
-
- thead {
- display: table-header-group; // h5bp.com/t
- }
-
- tr,
- img {
- page-break-inside: avoid;
- }
-
- img {
- max-width: 100% !important;
- }
-
- p,
- h2,
- h3 {
- orphans: 3;
- widows: 3;
- }
-
- h2,
- h3 {
- page-break-after: avoid;
- }
-
- // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245
- // Once fixed, we can just straight up remove this.
- select {
- background: #fff !important;
- }
-
- // Bootstrap components
- .navbar {
- display: none;
- }
- .table {
- td,
- th {
- background-color: #fff !important;
- }
- }
- .btn,
- .dropup > .btn {
- > .caret {
- border-top-color: #000 !important;
- }
- }
- .label {
- border: 1px solid #000;
- }
-
- .table {
- border-collapse: collapse !important;
- }
- .table-bordered {
- th,
- td {
- border: 1px solid #ddd !important;
- }
- }
+ img {
+ max-width: 100% !important;
+ }
+
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+
+ // Bootstrap specific changes start
+ //
+ // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245
+ // Once fixed, we can just straight up remove this.
+ select {
+ background: #fff !important;
+ }
+
+ // Bootstrap components
+ .navbar {
+ display: none;
+ }
+ .btn,
+ .dropup > .btn {
+ > .caret {
+ border-top-color: #000 !important;
+ }
+ }
+ .label {
+ border: 1px solid #000;
+ }
+
+ .table {
+ border-collapse: collapse !important;
+
+ td,
+ th {
+ background-color: #fff !important;
+ }
+ }
+ .table-bordered {
+ th,
+ td {
+ border: 1px solid #ddd !important;
+ }
+ }
+ // Bootstrap specific changes end
}
diff --git a/assets/stylesheets/bootstrap/_progress-bars.scss b/assets/stylesheets/bootstrap/_progress-bars.scss
index 6395ac2..343df63 100644
--- a/assets/stylesheets/bootstrap/_progress-bars.scss
+++ b/assets/stylesheets/bootstrap/_progress-bars.scss
@@ -19,7 +19,6 @@
}
-
// Bar itself
// -------------------------
@@ -29,7 +28,7 @@
height: $line-height-computed;
margin-bottom: $line-height-computed;
background-color: $progress-bg;
- border-radius: $border-radius-base;
+ border-radius: $progress-border-radius;
@include box-shadow(inset 0 1px 2px rgba(0,0,0,.1));
}
@@ -54,7 +53,7 @@
// `.progress-bar`.
.progress-striped .progress-bar,
.progress-bar-striped {
- @include gradient-striped();
+ @include gradient-striped;
background-size: 40px 40px;
}
@@ -67,23 +66,6 @@
@include animation(progress-bar-stripes 2s linear infinite);
}
-// Account for lower percentages
-.progress-bar {
- &[aria-valuenow="1"],
- &[aria-valuenow="2"] {
- min-width: 30px;
- }
-
- &[aria-valuenow="0"] {
- color: $gray-light;
- min-width: 30px;
- background-color: transparent;
- background-image: none;
- box-shadow: none;
- }
-}
-
-
// Variations
// -------------------------
diff --git a/assets/stylesheets/bootstrap/_responsive-embed.scss b/assets/stylesheets/bootstrap/_responsive-embed.scss
index a884d49..c1fa8f8 100644
--- a/assets/stylesheets/bootstrap/_responsive-embed.scss
+++ b/assets/stylesheets/bootstrap/_responsive-embed.scss
@@ -12,7 +12,8 @@
.embed-responsive-item,
iframe,
embed,
- object {
+ object,
+ video {
position: absolute;
top: 0;
left: 0;
diff --git a/assets/stylesheets/bootstrap/_scaffolding.scss b/assets/stylesheets/bootstrap/_scaffolding.scss
index 8cea4cd..626e5eb 100644
--- a/assets/stylesheets/bootstrap/_scaffolding.scss
+++ b/assets/stylesheets/bootstrap/_scaffolding.scss
@@ -52,11 +52,11 @@ a {
&:hover,
&:focus {
color: $link-hover-color;
- text-decoration: underline;
+ text-decoration: $link-hover-decoration;
}
&:focus {
- @include tab-focus();
+ @include tab-focus;
}
}
@@ -79,7 +79,7 @@ img {
// Responsive images (ensure images don't scale beyond their parents)
.img-responsive {
- @include img-responsive();
+ @include img-responsive;
}
// Rounded corners
diff --git a/assets/stylesheets/bootstrap/_tables.scss b/assets/stylesheets/bootstrap/_tables.scss
index 7c5d5bb..a575ff1 100644
--- a/assets/stylesheets/bootstrap/_tables.scss
+++ b/assets/stylesheets/bootstrap/_tables.scss
@@ -6,6 +6,12 @@
table {
background-color: $table-bg;
}
+caption {
+ padding-top: $table-cell-padding;
+ padding-bottom: $table-cell-padding;
+ color: $text-muted;
+ text-align: left;
+}
th {
text-align: left;
}
@@ -106,10 +112,7 @@ th {
.table-striped {
> tbody > tr:nth-child(odd) {
- > td,
- > th {
- background-color: $table-bg-accent;
- }
+ background-color: $table-bg-accent;
}
}
@@ -120,10 +123,7 @@ th {
.table-hover {
> tbody > tr:hover {
- > td,
- > th {
- background-color: $table-bg-hover;
- }
+ background-color: $table-bg-hover;
}
}
@@ -169,14 +169,15 @@ table {
// will display normally.
.table-responsive {
+ overflow-x: auto;
+ min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)
+
@media screen and (max-width: $screen-xs-max) {
width: 100%;
margin-bottom: ($line-height-computed * 0.75);
overflow-y: hidden;
- overflow-x: auto;
-ms-overflow-style: -ms-autohiding-scrollbar;
border: 1px solid $table-border-color;
- -webkit-overflow-scrolling: touch;
// Tighten up spacing
> .table {
diff --git a/assets/stylesheets/bootstrap/_theme.scss b/assets/stylesheets/bootstrap/_theme.scss
index 00386a2..05eb32a 100644
--- a/assets/stylesheets/bootstrap/_theme.scss
+++ b/assets/stylesheets/bootstrap/_theme.scss
@@ -7,7 +7,6 @@
@import "mixins";
-
//
// Buttons
// --------------------------------------------------
@@ -28,12 +27,16 @@
&.active {
@include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
}
+
+ .badge {
+ text-shadow: none;
+ }
}
// Mixin for generating new styles
@mixin btn-styles($btn-color: #555) {
@include gradient-vertical($start-color: $btn-color, $end-color: darken($btn-color, 12%));
- @include reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners
+ @include reset-filter; // Disable gradients for IE9 because filter bleeds through rounded corners
background-repeat: repeat-x;
border-color: darken($btn-color, 14%);
@@ -74,7 +77,6 @@
.btn-danger { @include btn-styles($btn-danger-bg); }
-
//
// Images
// --------------------------------------------------
@@ -85,7 +87,6 @@
}
-
//
// Dropdowns
// --------------------------------------------------
@@ -103,7 +104,6 @@
}
-
//
// Navbar
// --------------------------------------------------
@@ -111,13 +111,14 @@
// Default navbar
.navbar-default {
@include gradient-vertical($start-color: lighten($navbar-default-bg, 10%), $end-color: $navbar-default-bg);
- @include reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered
+ @include reset-filter; // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered
border-radius: $navbar-border-radius;
$shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);
@include box-shadow($shadow);
+ .navbar-nav > .open > a,
.navbar-nav > .active > a {
- @include gradient-vertical($start-color: darken($navbar-default-bg, 5%), $end-color: darken($navbar-default-bg, 2%));
+ @include gradient-vertical($start-color: darken($navbar-default-link-active-bg, 5%), $end-color: darken($navbar-default-link-active-bg, 2%));
@include box-shadow(inset 0 3px 9px rgba(0,0,0,.075));
}
}
@@ -129,10 +130,11 @@
// Inverted navbar
.navbar-inverse {
@include gradient-vertical($start-color: lighten($navbar-inverse-bg, 10%), $end-color: $navbar-inverse-bg);
- @include reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered
+ @include reset-filter; // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered
+ .navbar-nav > .open > a,
.navbar-nav > .active > a {
- @include gradient-vertical($start-color: $navbar-inverse-bg, $end-color: lighten($navbar-inverse-bg, 2.5%));
+ @include gradient-vertical($start-color: $navbar-inverse-link-active-bg, $end-color: lighten($navbar-inverse-link-active-bg, 2.5%));
@include box-shadow(inset 0 3px 9px rgba(0,0,0,.25));
}
@@ -150,7 +152,6 @@
}
-
//
// Alerts
// --------------------------------------------------
@@ -175,7 +176,6 @@
.alert-danger { @include alert-styles($alert-danger-bg); }
-
//
// Progress bars
// --------------------------------------------------
@@ -200,7 +200,7 @@
// Reset the striped class because our mixins don't do multiple gradients and
// the above custom styles override the new `.progress-bar-striped` in v3.2.0.
.progress-bar-striped {
- @include gradient-striped();
+ @include gradient-striped;
}
@@ -218,8 +218,11 @@
text-shadow: 0 -1px 0 darken($list-group-active-bg, 10%);
@include gradient-vertical($start-color: $list-group-active-bg, $end-color: darken($list-group-active-bg, 7.5%));
border-color: darken($list-group-active-border, 7.5%);
-}
+ .badge {
+ text-shadow: none;
+ }
+}
//
@@ -245,7 +248,6 @@
.panel-danger > .panel-heading { @include panel-heading-styles($panel-danger-heading-bg); }
-
//
// Wells
// --------------------------------------------------
diff --git a/assets/stylesheets/bootstrap/_thumbnails.scss b/assets/stylesheets/bootstrap/_thumbnails.scss
index 3d5ed86..da0e1e7 100644
--- a/assets/stylesheets/bootstrap/_thumbnails.scss
+++ b/assets/stylesheets/bootstrap/_thumbnails.scss
@@ -12,11 +12,11 @@
background-color: $thumbnail-bg;
border: 1px solid $thumbnail-border;
border-radius: $thumbnail-border-radius;
- @include transition(all .2s ease-in-out);
+ @include transition(border .2s ease-in-out);
> img,
a > img {
- @include img-responsive();
+ @include img-responsive;
margin-left: auto;
margin-right: auto;
}
diff --git a/assets/stylesheets/bootstrap/_type.scss b/assets/stylesheets/bootstrap/_type.scss
index 3f21b21..62d685c 100644
--- a/assets/stylesheets/bootstrap/_type.scss
+++ b/assets/stylesheets/bootstrap/_type.scss
@@ -80,11 +80,6 @@ small,
font-size: floor((100% * $font-size-small / $font-size-base));
}
-// Undo browser default styling
-cite {
- font-style: normal;
-}
-
mark,
.mark {
background-color: $state-warning-bg;
@@ -163,15 +158,20 @@ ol {
// List options
-// Unstyled keeps list items block level, just removes default browser padding and list-style
-.list-unstyled {
+// [converter] extracted from `.list-unstyled` for libsass compatibility
+@mixin list-unstyled {
padding-left: 0;
list-style: none;
}
+// [converter] extracted as `@mixin list-unstyled` for libsass compatibility
+.list-unstyled {
+ @include list-unstyled;
+}
+
// Inline turns list items into inline-block
.list-inline {
- @extend .list-unstyled;
+ @include list-unstyled;
margin-left: -5px;
> li {
@@ -204,7 +204,7 @@ dd {
.dl-horizontal {
dd {
- @include clearfix(); // Clear the floated `dt` if an empty `dd` is present
+ @include clearfix; // Clear the floated `dt` if an empty `dd` is present
}
@media (min-width: $grid-float-breakpoint) {
@@ -213,7 +213,7 @@ dd {
width: ($dl-horizontal-offset - 20);
clear: left;
text-align: right;
- @include text-overflow();
+ @include text-overflow;
}
dd {
margin-left: $dl-horizontal-offset;
@@ -290,12 +290,6 @@ blockquote.pull-right {
}
}
-// Quotes
-blockquote:before,
-blockquote:after {
- content: "";
-}
-
// Addresses
address {
margin-bottom: $line-height-computed;
diff --git a/assets/stylesheets/bootstrap/_utilities.scss b/assets/stylesheets/bootstrap/_utilities.scss
index 3ad5f2e..386c524 100644
--- a/assets/stylesheets/bootstrap/_utilities.scss
+++ b/assets/stylesheets/bootstrap/_utilities.scss
@@ -7,10 +7,10 @@
// -------------------------
.clearfix {
- @include clearfix();
+ @include clearfix;
}
.center-block {
- @include center-block();
+ @include center-block;
}
.pull-right {
float: right !important;
@@ -34,7 +34,7 @@
visibility: hidden;
}
.text-hide {
- @include text-hide();
+ @include text-hide;
}
@@ -53,5 +53,4 @@
.affix {
position: fixed;
- @include translate3d(0, 0, 0);
}
diff --git a/assets/stylesheets/bootstrap/_variables.scss b/assets/stylesheets/bootstrap/_variables.scss
index 2d17e0c..b4fba43 100644
--- a/assets/stylesheets/bootstrap/_variables.scss
+++ b/assets/stylesheets/bootstrap/_variables.scss
@@ -12,11 +12,12 @@ $bootstrap-sass-asset-helper: (twbs-font-path("") != unquote('twbs-font-path("")
//
//## Gray and brand colors for use across Bootstrap.
-$gray-darker: lighten(#000, 13.5%) !default; // #222
-$gray-dark: lighten(#000, 20%) !default; // #333
-$gray: lighten(#000, 33.5%) !default; // #555
-$gray-light: lighten(#000, 46.7%) !default; // #777
-$gray-lighter: lighten(#000, 93.5%) !default; // #eee
+$gray-base: #000 !default;
+$gray-darker: lighten($gray-base, 13.5%) !default; // #222
+$gray-dark: lighten($gray-base, 20%) !default; // #333
+$gray: lighten($gray-base, 33.5%) !default; // #555
+$gray-light: lighten($gray-base, 46.7%) !default; // #777
+$gray-lighter: lighten($gray-base, 93.5%) !default; // #eee
$brand-primary: #428bca !default;
$brand-success: #5cb85c !default;
@@ -38,6 +39,8 @@ $text-color: $gray-dark !default;
$link-color: $brand-primary !default;
//** Link hover color set via `darken()` function.
$link-hover-color: darken($link-color, 15%) !default;
+//** Link hover decoration.
+$link-hover-decoration: underline !default;
//== Typography
@@ -189,13 +192,20 @@ $input-bg-disabled: $gray-lighter !default;
$input-color: $gray !default;
//** `<input>` border color
$input-border: #ccc !default;
-//** `<input>` border radius
+
+// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
+//** Default `.form-control` border radius
$input-border-radius: $border-radius-base !default;
+//** Large `.form-control` border radius
+$input-border-radius-large: $border-radius-large !default;
+//** Small `.form-control` border radius
+$input-border-radius-small: $border-radius-small !default;
+
//** Border color for inputs on focus
$input-border-focus: #66afe9 !default;
//** Placeholder text color
-$input-color-placeholder: $gray-light !default;
+$input-color-placeholder: #999 !default;
//** Default `.form-control` height
$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
@@ -212,6 +222,9 @@ $input-group-addon-bg: $gray-lighter !default;
//** Border color for textual input addons
$input-group-addon-border-color: $input-border !default;
+//** Disabled cursor for form controls and buttons.
+$cursor-disabled: not-allowed !default;
+
//== Dropdowns
//
@@ -260,8 +273,7 @@ $zindex-dropdown: 1000 !default;
$zindex-popover: 1060 !default;
$zindex-tooltip: 1070 !default;
$zindex-navbar-fixed: 1030 !default;
-$zindex-modal-background: 1040 !default;
-$zindex-modal: 1050 !default;
+$zindex-modal: 1040 !default;
//== Media queries breakpoints
@@ -323,17 +335,17 @@ $grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
//## Define the maximum width of `.container` for different screen sizes.
// Small screen / tablet
-$container-tablet: ((720px + $grid-gutter-width)) !default;
+$container-tablet: (720px + $grid-gutter-width) !default;
//** For `$screen-sm-min` and up.
$container-sm: $container-tablet !default;
// Medium screen / desktop
-$container-desktop: ((940px + $grid-gutter-width)) !default;
+$container-desktop: (940px + $grid-gutter-width) !default;
//** For `$screen-md-min` and up.
$container-md: $container-desktop !default;
// Large screen / wide desktop
-$container-large-desktop: ((1140px + $grid-gutter-width)) !default;
+$container-large-desktop: (1140px + $grid-gutter-width) !default;
//** For `$screen-lg-min` and up.
$container-lg: $container-large-desktop !default;
@@ -376,12 +388,12 @@ $navbar-default-toggle-border-color: #ddd !default;
// Inverted navbar
// Reset inverted navbar basics
-$navbar-inverse-color: $gray-light !default;
+$navbar-inverse-color: lighten($gray-light, 15%) !default;
$navbar-inverse-bg: #222 !default;
$navbar-inverse-border: darken($navbar-inverse-bg, 10%) !default;
// Inverted navbar links
-$navbar-inverse-link-color: $gray-light !default;
+$navbar-inverse-link-color: lighten($gray-light, 15%) !default;
$navbar-inverse-link-hover-color: #fff !default;
$navbar-inverse-link-hover-bg: transparent !default;
$navbar-inverse-link-active-color: $navbar-inverse-link-hover-color !default;
@@ -411,8 +423,6 @@ $nav-link-hover-bg: $gray-lighter !default;
$nav-disabled-link-color: $gray-light !default;
$nav-disabled-link-hover-color: $gray-light !default;
-$nav-open-link-hover-color: #fff !default;
-
//== Tabs
$nav-tabs-border-color: #ddd !default;
@@ -537,7 +547,7 @@ $popover-title-bg: darken($popover-bg, 3%) !default;
//** Popover arrow width
$popover-arrow-width: 10px !default;
//** Popover arrow color
-$popover-arrow-color: #fff !default;
+$popover-arrow-color: $popover-bg !default;
//** Popover outer arrow width
$popover-arrow-outer-width: ($popover-arrow-width + 1) !default;
@@ -636,6 +646,8 @@ $alert-danger-border: $state-danger-border !default;
$progress-bg: #f5f5f5 !default;
//** Progress bar text color
$progress-bar-color: #fff !default;
+//** Variable for setting rounded corners on progress bar.
+$progress-border-radius: $border-radius-base !default;
//** Default progress bar color
$progress-bar-bg: $brand-primary !default;
@@ -850,5 +862,3 @@ $page-header-border-color: $gray-lighter !default;
$dl-horizontal-offset: $component-offset-horizontal !default;
//** Horizontal line color.
$hr-border: $gray-lighter !default;
-
-
diff --git a/assets/stylesheets/bootstrap/mixins/_buttons.scss b/assets/stylesheets/bootstrap/mixins/_buttons.scss
index 58ad13e..74a4ffc 100644
--- a/assets/stylesheets/bootstrap/mixins/_buttons.scss
+++ b/assets/stylesheets/bootstrap/mixins/_buttons.scss
@@ -10,6 +10,7 @@
&:hover,
&:focus,
+ &.focus,
&:active,
&.active,
.open > &.dropdown-toggle {
@@ -28,6 +29,7 @@
&,
&:hover,
&:focus,
+ &.focus,
&:active,
&.active {
background-color: $background;
diff --git a/assets/stylesheets/bootstrap/mixins/_forms.scss b/assets/stylesheets/bootstrap/mixins/_forms.scss
index ff72f0e..277aa5f 100644
--- a/assets/stylesheets/bootstrap/mixins/_forms.scss
+++ b/assets/stylesheets/bootstrap/mixins/_forms.scss
@@ -10,7 +10,11 @@
.radio,
.checkbox,
.radio-inline,
- .checkbox-inline {
+ .checkbox-inline,
+ &.radio label,
+ &.checkbox label,
+ &.radio-inline label,
+ &.checkbox-inline label {
color: $text-color;
}
// Set the border and box shadow on specific inputs to match
diff --git a/assets/stylesheets/bootstrap/mixins/_grid.scss b/assets/stylesheets/bootstrap/mixins/_grid.scss
index 1601f6a..ae16433 100644
--- a/assets/stylesheets/bootstrap/mixins/_grid.scss
+++ b/assets/stylesheets/bootstrap/mixins/_grid.scss
@@ -8,14 +8,14 @@
margin-left: auto;
padding-left: ($gutter / 2);
padding-right: ($gutter / 2);
- @include clearfix();
+ @include clearfix;
}
// Creates a wrapper for a series of columns
@mixin make-row($gutter: $grid-gutter-width) {
margin-left: ($gutter / -2);
margin-right: ($gutter / -2);
- @include clearfix();
+ @include clearfix;
}
// Generate the extra small columns
diff --git a/assets/stylesheets/bootstrap/mixins/_hide-text.scss b/assets/stylesheets/bootstrap/mixins/_hide-text.scss
index 5e06972..45db638 100644
--- a/assets/stylesheets/bootstrap/mixins/_hide-text.scss
+++ b/assets/stylesheets/bootstrap/mixins/_hide-text.scss
@@ -17,5 +17,5 @@
// New mixin to use as of v3.0.1
@mixin text-hide() {
- @include hide-text();
+ @include hide-text;
}
diff --git a/assets/stylesheets/bootstrap/mixins/_image.scss b/assets/stylesheets/bootstrap/mixins/_image.scss
index 57d60a3..c8dcf5e 100644
--- a/assets/stylesheets/bootstrap/mixins/_image.scss
+++ b/assets/stylesheets/bootstrap/mixins/_image.scss
@@ -8,7 +8,6 @@
// Keep images from scaling beyond the width of their parents.
@mixin img-responsive($display: block) {
display: $display;
- width: 100% \9; // Force IE10 and below to size SVG images correctly
max-width: 100%; // Part 1: Set a maximum relative to the parent
height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching
}
diff --git a/assets/stylesheets/bootstrap/mixins/_labels.scss b/assets/stylesheets/bootstrap/mixins/_labels.scss
index d99a653..eda6dfd 100644
--- a/assets/stylesheets/bootstrap/mixins/_labels.scss
+++ b/assets/stylesheets/bootstrap/mixins/_labels.scss
@@ -2,7 +2,7 @@
@mixin label-variant($color) {
background-color: $color;
-
+
&[href] {
&:hover,
&:focus {
diff --git a/assets/stylesheets/bootstrap/mixins/_progress-bar.scss b/assets/stylesheets/bootstrap/mixins/_progress-bar.scss
index 3275ea3..90a62af 100644
--- a/assets/stylesheets/bootstrap/mixins/_progress-bar.scss
+++ b/assets/stylesheets/bootstrap/mixins/_progress-bar.scss
@@ -5,6 +5,6 @@
// Deprecated parent class requirement as of v3.2.0
.progress-striped & {
- @include gradient-striped();
+ @include gradient-striped;
}
}
diff --git a/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss b/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss
index f91f576..a6b9ef4 100644
--- a/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss
+++ b/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss
@@ -99,9 +99,12 @@
// Placeholder text
@mixin placeholder($color: $input-color-placeholder) {
- &::-moz-placeholder { color: $color; // Firefox
- opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526
- &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+
+ // Firefox
+ &::-moz-placeholder {
+ color: $color;
+ opacity: 1; // See https://github.com/twbs/bootstrap/pull/11526
+ }
+ &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+
&::-webkit-input-placeholder { color: $color; } // Safari and Chrome
}
diff --git a/lib/bootstrap-sass.rb b/lib/bootstrap-sass.rb
index 019e284..2c6c1bc 100644
--- a/lib/bootstrap-sass.rb
+++ b/lib/bootstrap-sass.rb
@@ -4,7 +4,6 @@ module Bootstrap
def load!
register_compass_extension if compass?
register_rails_engine if rails?
-
configure_sass
end
@@ -56,6 +55,7 @@ module Bootstrap
def register_compass_extension
::Compass::Frameworks.register(
'bootstrap',
+ :version => Bootstrap::VERSION,
:path => gem_path,
:stylesheets_directory => stylesheets_path,
:templates_directory => File.join(gem_path, 'templates')
diff --git a/lib/bootstrap-sass/engine.rb b/lib/bootstrap-sass/engine.rb
index bd82137..2ebe261 100644
--- a/lib/bootstrap-sass/engine.rb
+++ b/lib/bootstrap-sass/engine.rb
@@ -3,7 +3,7 @@ module Bootstrap
class Engine < ::Rails::Engine
initializer 'bootstrap-sass.assets.precompile' do |app|
%w(stylesheets javascripts fonts images).each do |sub|
- app.config.assets.paths << root.join('assets', sub)
+ app.config.assets.paths << root.join('assets', sub).to_s
end
app.config.assets.precompile << %r(bootstrap/glyphicons-halflings-regular\.(?:eot|svg|ttf|woff)$)
end
diff --git a/lib/bootstrap-sass/version.rb b/lib/bootstrap-sass/version.rb
index dc78dde..89be577 100644
--- a/lib/bootstrap-sass/version.rb
+++ b/lib/bootstrap-sass/version.rb
@@ -1,4 +1,4 @@
module Bootstrap
- VERSION = '3.2.0.2'
- BOOTSTRAP_SHA = 'c068162161154a4b85110ea1e7dd3d7897ce2b72'
+ VERSION = '3.3.0.0'
+ BOOTSTRAP_SHA = '16dbdbd7a2c6cfa3be4e5dcc52249e577c02c84a'
end
diff --git a/package.json b/package.json
index 6085dd9..27e1bf2 100644
--- a/package.json
+++ b/package.json
@@ -23,8 +23,8 @@
"url": "https://github.com/twbs/bootstrap-sass/issues"
},
"devDependencies": {
- "node-sass": "*",
- "mincer": "*",
- "ejs": "*"
+ "node-sass": "~1.0",
+ "mincer": "~1.1",
+ "ejs": "~1.0"
}
}
diff --git a/tasks/converter/less_conversion.rb b/tasks/converter/less_conversion.rb
index a903aec..0d46ce9 100644
--- a/tasks/converter/less_conversion.rb
+++ b/tasks/converter/less_conversion.rb
@@ -22,7 +22,7 @@ class Converter
# match any brace that opens or closes a properties body
BRACE_RE = /#{RULE_OPEN_BRACE_RE}|#{RULE_CLOSE_BRACE_RE}/m
BRACE_RE_REVERSE = /#{RULE_OPEN_BRACE_RE_REVERSE}|#{RULE_CLOSE_BRACE_RE_REVERSE}/m
- # valid
+ # valid characters in mixin definitions
SCSS_MIXIN_DEF_ARGS_RE = /[\w\-,\s$:#%()]*/
LESS_MIXIN_DEF_ARGS_RE = /[\w\-,;.\s@:#%()]*/
@@ -31,27 +31,34 @@ class Converter
# These mixins will get vararg definitions in SCSS (not supported by LESS):
VARARG_MIXINS = %w(
- scale transition transition-duration transition-property transition-transform box-shadow
- )
+ scale transition transition-duration transition-property transition-transform box-shadow
+ )
+
+ # A list of classes that will be extracted into mixins
+ # Only the top-level selectors of form .CLASS { ... } are extracted. CLASS must not be used in any other rule definition.
+ # This is a work-around for libsass @extend issues
+ CLASSES_TO_MIXINS = %w(
+ list-unstyled form-inline
+ )
# Convert a snippet of bootstrap LESS to Scss
def convert_less(less)
- load_shared
less = convert_to_scss(less)
less = yield(less) if block_given?
less
end
- def load_shared
+ def shared_mixins
@shared_mixins ||= begin
log_status ' Reading shared mixins from mixins.less'
- read_mixins read_files('less', bootstrap_less_files.grep(/mixins\//)).values.join("\n"), nested: NESTED_MIXINS
+ CLASSES_TO_MIXINS + read_mixins(read_files('less', bootstrap_less_files.grep(/mixins\//)).values.join("\n"),
+ nested: NESTED_MIXINS)
end
end
def process_stylesheet_assets
log_status 'Processing stylesheets...'
- files = read_files('less', bootstrap_less_files)
+ files = read_files('less', bootstrap_less_files)
save_to = @save_to[:scss]
log_status ' Converting LESS files to Scss:'
@@ -94,7 +101,7 @@ class Converter
// NB: in Sass 3.3 there is a native function: function-exists(twbs-font-path)
$bootstrap-sass-asset-helper: #{sass_fn_exists('twbs-font-path')} !default;
SCSS
- file = replace_all file, %r{(\$icon-font-path): \s*"(.*)" (!default);}, "\n" + unindent(<<-SCSS, 14)
+ file = replace_all file, %r{(\$icon-font-path): \s*"(.*)" (!default);}, "\n" + unindent(<<-SCSS, 14)
// [converter] Asset helpers such as Sprockets and Node.js Mincer do not resolve relative paths
\\1: if($bootstrap-sass-asset-helper, "bootstrap/", "\\2bootstrap/") \\3;
SCSS
@@ -114,7 +121,6 @@ class Converter
when 'thumbnails.less', 'labels.less', 'badges.less'
file = extract_nested_rule file, 'a&'
when 'glyphicons.less'
- file = bootstrap_font_files.map { |p| %Q(//= depend_on "bootstrap/#{File.basename(p)}") } * "\n" + "\n" + file
file = replace_rules(file, '@font-face') { |rule|
rule = replace_all rule, /(\$icon-font(?:-\w+)+)/, '#{\1}'
replace_asset_url rule, :font
@@ -136,6 +142,11 @@ class Converter
main_to = File.expand_path("#{save_to}/../_bootstrap.scss")
save_file main_to, File.read(main_from).gsub(/ "/, ' "bootstrap/')
File.delete(main_from)
+
+ # generate variables template
+ save_file 'templates/project/_bootstrap-variables.sass',
+ "// Override Bootstrap variables here (defaults from bootstrap-sass v<%= Bootstrap::VERSION %>):\n\n" +
+ File.read("#{save_to}/_variables.scss").gsub(/^(?=\$)/, '// ').gsub(/ !default;/, '')
end
def bootstrap_less_files
@@ -147,10 +158,11 @@ class Converter
# apply general less to scss conversion
def convert_to_scss(file)
# get local mixin names before converting the definitions
- mixins = @shared_mixins + read_mixins(file)
+ mixins = shared_mixins + read_mixins(file)
file = replace_vars(file)
file = replace_mixin_definitions(file)
file = replace_mixins(file, mixins)
+ file = extract_mixins_from_selectors(file, CLASSES_TO_MIXINS.inject({}) { |h, cl| h.update(".#{cl}" => cl) })
file = replace_spin(file)
file = replace_fadein(file)
file = replace_image_urls(file)
@@ -371,7 +383,7 @@ SASS
sel = parent_sel + sel[1..-1]
end
# unwrap, and replace @include
- unindent unwrap_rule_block(rule).gsub(/(@include [\w-]+)\(([\$\w\-,\s]*)\)/) {
+ unindent unwrap_rule_block(rule).gsub(/(@include [\w-]+)\(?([\$\w\-,\s]*)\)?/) {
args = $2
"#{cmt}#{$1}('#{sel.gsub(/\s+/, ' ')}'#{', ' if args && !args.empty?}#{args})"
}
@@ -388,6 +400,25 @@ SASS
end
end
+ # .btn { ... } -> @mixin btn { ... }; .btn { @include btn }
+ def extract_mixins_from_selectors(file, selectors_to_mixins)
+ selectors_to_mixins.each do |selector, mixin|
+ file = replace_rules file, Regexp.escape(selector), prefix: false do |selector_css|
+ log_transform "#{selector} { ... } -> @mixin #{mixin} { ... }; #{selector} { @include #{mixin} } ", from: 'extract_mixins_from_selectors'
+ <<-SCSS
+// [converter] extracted from `#{selector}` for libsass compatibility
+@mixin #{mixin} {#{unwrap_rule_block(selector_css)}
+}
+// [converter] extracted as `@mixin #{mixin}` for libsass compatibility
+#{selector} {
+ @include #{mixin};
+}
+ SCSS
+ end
+ end
+ file
+ end
+
# @include and @extend from LESS:
# .mixin() -> @include mixin()
# #scope > .mixin() -> @include scope-mixin()
@@ -396,14 +427,11 @@ SASS
mixin_pattern = /(\s+)(([#|\.][\w-]+\s*>\s*)*)\.([\w-]+\(.*\))(?!\s\{)/
less = less.gsub(mixin_pattern) do |match|
- matches = match.scan(mixin_pattern).flatten
- scope = matches[1] || ''
- if scope != ''
- scope = scope.scan(/[\w-]+/).join('-') + '-'
- end
+ matches = match.scan(mixin_pattern).flatten
+ scope = matches[1] && matches[1] != '' ? matches[1].scan(/[\w-]+/).join('-') + '-' : ''
mixin_name = match.scan(/\.([\w-]+)\(.*\)\s?\{?/).first
if mixin_name && mixin_names.include?("#{scope}#{mixin_name.first}")
- "#{matches.first}@include #{scope}#{matches.last}".gsub(/; \$/, ", $").sub(/;\)$/, ')')
+ "#{matches.first}@include #{scope}#{matches.last.gsub(/;\s*\$/, ', $').sub(/;\)$/, ')').sub(/\(\)$/, '')}"
else
"#{matches.first}@extend .#{scope}#{matches.last.gsub(/\(\)/, '')}"
end
@@ -414,7 +442,7 @@ SASS
selector =~ /\.([\w-]+)/
mixin = $1
if mixin && mixin_names.include?(mixin)
- "@include #{mixin}()"
+ "@include #{mixin}"
else
"@extend #{selector}"
end
@@ -548,16 +576,20 @@ SASS
# option :comments -- include immediately preceding comments in rule_block
#
# replace_rules(".a{ \n .b{} }", '.b') { |rule, pos| ">#{rule}<" } #=> ".a{ \n >.b{}< }"
- def replace_rules(less, rule_prefix = SELECTOR_RE, options = {}, &block)
- options = {comments: true}.merge(options || {})
- less = less.dup
- s = CharStringScanner.new(less)
- rule_re = /(?:#{rule_prefix}[#{SELECTOR_CHAR})=(\s]*?#{RULE_OPEN_BRACE_RE})/
- if options[:comments]
- rule_start_re = /(?:#{COMMENT_RE}*)^#{rule_re}/
- else
- rule_start_re = /^#{rule_re}/
- end
+ def replace_rules(less, selector = SELECTOR_RE, options = {}, &block)
+ options = {prefix: true, comments: true}.merge(options || {})
+ less = less.dup
+ s = CharStringScanner.new(less)
+ rule_re = if options[:prefix]
+ /(?:#{selector}[#{SELECTOR_CHAR})=(\s]*?#{RULE_OPEN_BRACE_RE})/
+ else
+ /#{selector}[\s]*#{RULE_OPEN_BRACE_RE}/
+ end
+ rule_start_re = if options[:comments]
+ /(?:#{COMMENT_RE}*)^#{rule_re}/
+ else
+ /^#{rule_re}/
+ end
positions = []
while (rule_start = s.scan_next(rule_start_re))
diff --git a/tasks/converter/network.rb b/tasks/converter/network.rb
index a5ec956..848778a 100644
--- a/tasks/converter/network.rb
+++ b/tasks/converter/network.rb
@@ -1,3 +1,4 @@
+require 'shellwords'
class Converter
module Network
protected
@@ -58,12 +59,17 @@ class Converter
# get sha of the branch (= the latest commit)
def get_branch_sha
- return @branch if @branch =~ /\A[0-9a-f]+\z/
- cmd = "git ls-remote 'https://github.com/#@repo' | awk '/#@branch/ {print $1}'"
- log cmd
- @branch_sha ||= %x[#{cmd}].chomp
- raise 'Could not get branch sha!' unless $?.success?
- @branch_sha
+ @branch_sha ||= begin
+ if @branch + "\n" == %x[git rev-parse #@branch]
+ @branch
+ else
+ cmd = "git ls-remote #{Shellwords.escape "https://github.com/#@repo"} #@branch"
+ log cmd
+ result = %x[#{cmd}]
+ raise 'Could not get branch sha!' unless $?.success? && !result.empty?
+ result.split(/\s+/).first
+ end
+ end
end
# Get the sha of a dir
diff --git a/templates/project/_bootstrap-variables.sass b/templates/project/_bootstrap-variables.sass
new file mode 100644
index 0000000..917a457
--- /dev/null
+++ b/templates/project/_bootstrap-variables.sass
@@ -0,0 +1,866 @@
+// Override Bootstrap variables here (defaults from bootstrap-sass v<%= Bootstrap::VERSION %>):
+
+// When true, asset path helpers are used, otherwise the regular CSS `url()` is used.
+// When there no function is defined, `fn('')` is parsed as string that equals the right hand side
+// NB: in Sass 3.3 there is a native function: function-exists(twbs-font-path)
+// $bootstrap-sass-asset-helper: (twbs-font-path("") != unquote('twbs-font-path("")'))
+
+//
+// Variables
+// --------------------------------------------------
+
+
+//== Colors
+//
+//## Gray and brand colors for use across Bootstrap.
+
+// $gray-base: #000
+// $gray-darker: lighten($gray-base, 13.5%) // #222
+// $gray-dark: lighten($gray-base, 20%) // #333
+// $gray: lighten($gray-base, 33.5%) // #555
+// $gray-light: lighten($gray-base, 46.7%) // #777
+// $gray-lighter: lighten($gray-base, 93.5%) // #eee
+
+// $brand-primary: #428bca
+// $brand-success: #5cb85c
+// $brand-info: #5bc0de
+// $brand-warning: #f0ad4e
+// $brand-danger: #d9534f
+
+
+//== Scaffolding
+//
+//## Settings for some of the most global styles.
+
+//** Background color for `<body>`.
+// $body-bg: #fff
+//** Global text color on `<body>`.
+// $text-color: $gray-dark
+
+//** Global textual link color.
+// $link-color: $brand-primary
+//** Link hover color set via `darken()` function.
+// $link-hover-color: darken($link-color, 15%)
+//** Link hover decoration.
+// $link-hover-decoration: underline
+
+
+//== Typography
+//
+//## Font, line-height, and color for body text, headings, and more.
+
+// $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif
+// $font-family-serif: Georgia, "Times New Roman", Times, serif
+//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
+// $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace
+// $font-family-base: $font-family-sans-serif
+
+// $font-size-base: 14px
+// $font-size-large: ceil(($font-size-base * 1.25)) // ~18px
+// $font-size-small: ceil(($font-size-base * 0.85)) // ~12px
+
+// $font-size-h1: floor(($font-size-base * 2.6)) // ~36px
+// $font-size-h2: floor(($font-size-base * 2.15)) // ~30px
+// $font-size-h3: ceil(($font-size-base * 1.7)) // ~24px
+// $font-size-h4: ceil(($font-size-base * 1.25)) // ~18px
+// $font-size-h5: $font-size-base
+// $font-size-h6: ceil(($font-size-base * 0.85)) // ~12px
+
+//** Unit-less `line-height` for use in components like buttons.
+// $line-height-base: 1.428571429 // 20/14
+//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
+// $line-height-computed: floor(($font-size-base * $line-height-base)) // ~20px
+
+//** By default, this inherits from the `<body>`.
+// $headings-font-family: inherit
+// $headings-font-weight: 500
+// $headings-line-height: 1.1
+// $headings-color: inherit
+
+
+//== Iconography
+//
+//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
+
+//** Load fonts from this directory.
+
+// [converter] Asset helpers such as Sprockets and Node.js Mincer do not resolve relative paths
+// $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/")
+
+//** File name for all font files.
+// $icon-font-name: "glyphicons-halflings-regular"
+//** Element ID within SVG icon file.
+// $icon-font-svg-id: "glyphicons_halflingsregular"
+
+
+//== Components
+//
+//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
+
+// $padding-base-vertical: 6px
+// $padding-base-horizontal: 12px
+
+// $padding-large-vertical: 10px
+// $padding-large-horizontal: 16px
+
+// $padding-small-vertical: 5px
+// $padding-small-horizontal: 10px
+
+// $padding-xs-vertical: 1px
+// $padding-xs-horizontal: 5px
+
+// $line-height-large: 1.33
+// $line-height-small: 1.5
+
+// $border-radius-base: 4px
+// $border-radius-large: 6px
+// $border-radius-small: 3px
+
+//** Global color for active items (e.g., navs or dropdowns).
+// $component-active-color: #fff
+//** Global background color for active items (e.g., navs or dropdowns).
+// $component-active-bg: $brand-primary
+
+//** Width of the `border` for generating carets that indicator dropdowns.
+// $caret-width-base: 4px
+//** Carets increase slightly in size for larger components.
+// $caret-width-large: 5px
+
+
+//== Tables
+//
+//## Customizes the `.table` component with basic values, each used across all table variations.
+
+//** Padding for `<th>`s and `<td>`s.
+// $table-cell-padding: 8px
+//** Padding for cells in `.table-condensed`.
+// $table-condensed-cell-padding: 5px
+
+//** Default background color used for all tables.
+// $table-bg: transparent
+//** Background color used for `.table-striped`.
+// $table-bg-accent: #f9f9f9
+//** Background color used for `.table-hover`.
+// $table-bg-hover: #f5f5f5
+// $table-bg-active: $table-bg-hover
+
+//** Border color for table and cell borders.
+// $table-border-color: #ddd
+
+
+//== Buttons
+//
+//## For each of Bootstrap's buttons, define text, background and border color.
+
+// $btn-font-weight: normal
+
+// $btn-default-color: #333
+// $btn-default-bg: #fff
+// $btn-default-border: #ccc
+
+// $btn-primary-color: #fff
+// $btn-primary-bg: $brand-primary
+// $btn-primary-border: darken($btn-primary-bg, 5%)
+
+// $btn-success-color: #fff
+// $btn-success-bg: $brand-success
+// $btn-success-border: darken($btn-success-bg, 5%)
+
+// $btn-info-color: #fff
+// $btn-info-bg: $brand-info
+// $btn-info-border: darken($btn-info-bg, 5%)
+
+// $btn-warning-color: #fff
+// $btn-warning-bg: $brand-warning
+// $btn-warning-border: darken($btn-warning-bg, 5%)
+
+// $btn-danger-color: #fff
+// $btn-danger-bg: $brand-danger
+// $btn-danger-border: darken($btn-danger-bg, 5%)
+
+// $btn-link-disabled-color: $gray-light
+
+
+//== Forms
+//
+//##
+
+//** `<input>` background color
+// $input-bg: #fff
+//** `<input disabled>` background color
+// $input-bg-disabled: $gray-lighter
+
+//** Text color for `<input>`s
+// $input-color: $gray
+//** `<input>` border color
+// $input-border: #ccc
+
+// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
+//** Default `.form-control` border radius
+// $input-border-radius: $border-radius-base
+//** Large `.form-control` border radius
+// $input-border-radius-large: $border-radius-large
+//** Small `.form-control` border radius
+// $input-border-radius-small: $border-radius-small
+
+//** Border color for inputs on focus
+// $input-border-focus: #66afe9
+
+//** Placeholder text color
+// $input-color-placeholder: #999
+
+//** Default `.form-control` height
+// $input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2)
+//** Large `.form-control` height
+// $input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2)
+//** Small `.form-control` height
+// $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2)
+
+// $legend-color: $gray-dark
+// $legend-border-color: #e5e5e5
+
+//** Background color for textual input addons
+// $input-group-addon-bg: $gray-lighter
+//** Border color for textual input addons
+// $input-group-addon-border-color: $input-border
+
+//** Disabled cursor for form controls and buttons.
+// $cursor-disabled: not-allowed
+
+
+//== Dropdowns
+//
+//## Dropdown menu container and contents.
+
+//** Background for the dropdown menu.
+// $dropdown-bg: #fff
+//** Dropdown menu `border-color`.
+// $dropdown-border: rgba(0,0,0,.15)
+//** Dropdown menu `border-color` **for IE8**.
+// $dropdown-fallback-border: #ccc
+//** Divider color for between dropdown items.
+// $dropdown-divider-bg: #e5e5e5
+
+//** Dropdown link text color.
+// $dropdown-link-color: $gray-dark
+//** Hover color for dropdown links.
+// $dropdown-link-hover-color: darken($gray-dark, 5%)
+//** Hover background for dropdown links.
+// $dropdown-link-hover-bg: #f5f5f5
+
+//** Active dropdown menu item text color.
+// $dropdown-link-active-color: $component-active-color
+//** Active dropdown menu item background color.
+// $dropdown-link-active-bg: $component-active-bg
+
+//** Disabled dropdown menu item background color.
+// $dropdown-link-disabled-color: $gray-light
+
+//** Text color for headers within dropdown menus.
+// $dropdown-header-color: $gray-light
+
+//** Deprecated `$dropdown-caret-color` as of v3.1.0
+// $dropdown-caret-color: #000
+
+
+//-- Z-index master list
+//
+// Warning: Avoid customizing these values. They're used for a bird's eye view
+// of components dependent on the z-axis and are designed to all work together.
+//
+// Note: These variables are not generated into the Customizer.
+
+// $zindex-navbar: 1000
+// $zindex-dropdown: 1000
+// $zindex-popover: 1060
+// $zindex-tooltip: 1070
+// $zindex-navbar-fixed: 1030
+// $zindex-modal: 1040
+
+
+//== Media queries breakpoints
+//
+//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
+
+// Extra small screen / phone
+//** Deprecated `$screen-xs` as of v3.0.1
+// $screen-xs: 480px
+//** Deprecated `$screen-xs-min` as of v3.2.0
+// $screen-xs-min: $screen-xs
+//** Deprecated `$screen-phone` as of v3.0.1
+// $screen-phone: $screen-xs-min
+
+// Small screen / tablet
+//** Deprecated `$screen-sm` as of v3.0.1
+// $screen-sm: 768px
+// $screen-sm-min: $screen-sm
+//** Deprecated `$screen-tablet` as of v3.0.1
+// $screen-tablet: $screen-sm-min
+
+// Medium screen / desktop
+//** Deprecated `$screen-md` as of v3.0.1
+// $screen-md: 992px
+// $screen-md-min: $screen-md
+//** Deprecated `$screen-desktop` as of v3.0.1
+// $screen-desktop: $screen-md-min
+
+// Large screen / wide desktop
+//** Deprecated `$screen-lg` as of v3.0.1
+// $screen-lg: 1200px
+// $screen-lg-min: $screen-lg
+//** Deprecated `$screen-lg-desktop` as of v3.0.1
+// $screen-lg-desktop: $screen-lg-min
+
+// So media queries don't overlap when required, provide a maximum
+// $screen-xs-max: ($screen-sm-min - 1)
+// $screen-sm-max: ($screen-md-min - 1)
+// $screen-md-max: ($screen-lg-min - 1)
+
+
+//== Grid system
+//
+//## Define your custom responsive grid.
+
+//** Number of columns in the grid.
+// $grid-columns: 12
+//** Padding between columns. Gets divided in half for the left and right.
+// $grid-gutter-width: 30px
+// Navbar collapse
+//** Point at which the navbar becomes uncollapsed.
+// $grid-float-breakpoint: $screen-sm-min
+//** Point at which the navbar begins collapsing.
+// $grid-float-breakpoint-max: ($grid-float-breakpoint - 1)
+
+
+//== Container sizes
+//
+//## Define the maximum width of `.container` for different screen sizes.
+
+// Small screen / tablet
+// $container-tablet: (720px + $grid-gutter-width)
+//** For `$screen-sm-min` and up.
+// $container-sm: $container-tablet
+
+// Medium screen / desktop
+// $container-desktop: (940px + $grid-gutter-width)
+//** For `$screen-md-min` and up.
+// $container-md: $container-desktop
+
+// Large screen / wide desktop
+// $container-large-desktop: (1140px + $grid-gutter-width)
+//** For `$screen-lg-min` and up.
+// $container-lg: $container-large-desktop
+
+
+//== Navbar
+//
+//##
+
+// Basics of a navbar
+// $navbar-height: 50px
+// $navbar-margin-bottom: $line-height-computed
+// $navbar-border-radius: $border-radius-base
+// $navbar-padding-horizontal: floor(($grid-gutter-width / 2))
+// $navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2)
+// $navbar-collapse-max-height: 340px
+
+// $navbar-default-color: #777
+// $navbar-default-bg: #f8f8f8
+// $navbar-default-border: darken($navbar-default-bg, 6.5%)
+
+// Navbar links
+// $navbar-default-link-color: #777
+// $navbar-default-link-hover-color: #333
+// $navbar-default-link-hover-bg: transparent
+// $navbar-default-link-active-color: #555
+// $navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%)
+// $navbar-default-link-disabled-color: #ccc
+// $navbar-default-link-disabled-bg: transparent
+
+// Navbar brand label
+// $navbar-default-brand-color: $navbar-default-link-color
+// $navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%)
+// $navbar-default-brand-hover-bg: transparent
+
+// Navbar toggle
+// $navbar-default-toggle-hover-bg: #ddd
+// $navbar-default-toggle-icon-bar-bg: #888
+// $navbar-default-toggle-border-color: #ddd
+
+
+// Inverted navbar
+// Reset inverted navbar basics
+// $navbar-inverse-color: lighten($gray-light, 15%)
+// $navbar-inverse-bg: #222
+// $navbar-inverse-border: darken($navbar-inverse-bg, 10%)
+
+// Inverted navbar links
+// $navbar-inverse-link-color: lighten($gray-light, 15%)
+// $navbar-inverse-link-hover-color: #fff
+// $navbar-inverse-link-hover-bg: transparent
+// $navbar-inverse-link-active-color: $navbar-inverse-link-hover-color
+// $navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%)
+// $navbar-inverse-link-disabled-color: #444
+// $navbar-inverse-link-disabled-bg: transparent
+
+// Inverted navbar brand label
+// $navbar-inverse-brand-color: $navbar-inverse-link-color
+// $navbar-inverse-brand-hover-color: #fff
+// $navbar-inverse-brand-hover-bg: transparent
+
+// Inverted navbar toggle
+// $navbar-inverse-toggle-hover-bg: #333
+// $navbar-inverse-toggle-icon-bar-bg: #fff
+// $navbar-inverse-toggle-border-color: #333
+
+
+//== Navs
+//
+//##
+
+//=== Shared nav styles
+// $nav-link-padding: 10px 15px
+// $nav-link-hover-bg: $gray-lighter
+
+// $nav-disabled-link-color: $gray-light
+// $nav-disabled-link-hover-color: $gray-light
+
+//== Tabs
+// $nav-tabs-border-color: #ddd
+
+// $nav-tabs-link-hover-border-color: $gray-lighter
+
+// $nav-tabs-active-link-hover-bg: $body-bg
+// $nav-tabs-active-link-hover-color: $gray
+// $nav-tabs-active-link-hover-border-color: #ddd
+
+// $nav-tabs-justified-link-border-color: #ddd
+// $nav-tabs-justified-active-link-border-color: $body-bg
+
+//== Pills
+// $nav-pills-border-radius: $border-radius-base
+// $nav-pills-active-link-hover-bg: $component-active-bg
+// $nav-pills-active-link-hover-color: $component-active-color
+
+
+//== Pagination
+//
+//##
+
+// $pagination-color: $link-color
+// $pagination-bg: #fff
+// $pagination-border: #ddd
+
+// $pagination-hover-color: $link-hover-color
+// $pagination-hover-bg: $gray-lighter
+// $pagination-hover-border: #ddd
+
+// $pagination-active-color: #fff
+// $pagination-active-bg: $brand-primary
+// $pagination-active-border: $brand-primary
+
+// $pagination-disabled-color: $gray-light
+// $pagination-disabled-bg: #fff
+// $pagination-disabled-border: #ddd
+
+
+//== Pager
+//
+//##
+
+// $pager-bg: $pagination-bg
+// $pager-border: $pagination-border
+// $pager-border-radius: 15px
+
+// $pager-hover-bg: $pagination-hover-bg
+
+// $pager-active-bg: $pagination-active-bg
+// $pager-active-color: $pagination-active-color
+
+// $pager-disabled-color: $pagination-disabled-color
+
+
+//== Jumbotron
+//
+//##
+
+// $jumbotron-padding: 30px
+// $jumbotron-color: inherit
+// $jumbotron-bg: $gray-lighter
+// $jumbotron-heading-color: inherit
+// $jumbotron-font-size: ceil(($font-size-base * 1.5))
+
+
+//== Form states and alerts
+//
+//## Define colors for form feedback states and, by default, alerts.
+
+// $state-success-text: #3c763d
+// $state-success-bg: #dff0d8
+// $state-success-border: darken(adjust-hue($state-success-bg, -10), 5%)
+
+// $state-info-text: #31708f
+// $state-info-bg: #d9edf7
+// $state-info-border: darken(adjust-hue($state-info-bg, -10), 7%)
+
+// $state-warning-text: #8a6d3b
+// $state-warning-bg: #fcf8e3
+// $state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%)
+
+// $state-danger-text: #a94442
+// $state-danger-bg: #f2dede
+// $state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%)
+
+
+//== Tooltips
+//
+//##
+
+//** Tooltip max width
+// $tooltip-max-width: 200px
+//** Tooltip text color
+// $tooltip-color: #fff
+//** Tooltip background color
+// $tooltip-bg: #000
+// $tooltip-opacity: .9
+
+//** Tooltip arrow width
+// $tooltip-arrow-width: 5px
+//** Tooltip arrow color
+// $tooltip-arrow-color: $tooltip-bg
+
+
+//== Popovers
+//
+//##
+
+//** Popover body background color
+// $popover-bg: #fff
+//** Popover maximum width
+// $popover-max-width: 276px
+//** Popover border color
+// $popover-border-color: rgba(0,0,0,.2)
+//** Popover fallback border color
+// $popover-fallback-border-color: #ccc
+
+//** Popover title background color
+// $popover-title-bg: darken($popover-bg, 3%)
+
+//** Popover arrow width
+// $popover-arrow-width: 10px
+//** Popover arrow color
+// $popover-arrow-color: $popover-bg
+
+//** Popover outer arrow width
+// $popover-arrow-outer-width: ($popover-arrow-width + 1)
+//** Popover outer arrow color
+// $popover-arrow-outer-color: fade_in($popover-border-color, 0.05)
+//** Popover outer arrow fallback color
+// $popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%)
+
+
+//== Labels
+//
+//##
+
+//** Default label background color
+// $label-default-bg: $gray-light
+//** Primary label background color
+// $label-primary-bg: $brand-primary
+//** Success label background color
+// $label-success-bg: $brand-success
+//** Info label background color
+// $label-info-bg: $brand-info
+//** Warning label background color
+// $label-warning-bg: $brand-warning
+//** Danger label background color
+// $label-danger-bg: $brand-danger
+
+//** Default label text color
+// $label-color: #fff
+//** Default text color of a linked label
+// $label-link-hover-color: #fff
+
+
+//== Modals
+//
+//##
+
+//** Padding applied to the modal body
+// $modal-inner-padding: 15px
+
+//** Padding applied to the modal title
+// $modal-title-padding: 15px
+//** Modal title line-height
+// $modal-title-line-height: $line-height-base
+
+//** Background color of modal content area
+// $modal-content-bg: #fff
+//** Modal content border color
+// $modal-content-border-color: rgba(0,0,0,.2)
+//** Modal content border color **for IE8**
+// $modal-content-fallback-border-color: #999
+
+//** Modal backdrop background color
+// $modal-backdrop-bg: #000
+//** Modal backdrop opacity
+// $modal-backdrop-opacity: .5
+//** Modal header border color
+// $modal-header-border-color: #e5e5e5
+//** Modal footer border color
+// $modal-footer-border-color: $modal-header-border-color
+
+// $modal-lg: 900px
+// $modal-md: 600px
+// $modal-sm: 300px
+
+
+//== Alerts
+//
+//## Define alert colors, border radius, and padding.
+
+// $alert-padding: 15px
+// $alert-border-radius: $border-radius-base
+// $alert-link-font-weight: bold
+
+// $alert-success-bg: $state-success-bg
+// $alert-success-text: $state-success-text
+// $alert-success-border: $state-success-border
+
+// $alert-info-bg: $state-info-bg
+// $alert-info-text: $state-info-text
+// $alert-info-border: $state-info-border
+
+// $alert-warning-bg: $state-warning-bg
+// $alert-warning-text: $state-warning-text
+// $alert-warning-border: $state-warning-border
+
+// $alert-danger-bg: $state-danger-bg
+// $alert-danger-text: $state-danger-text
+// $alert-danger-border: $state-danger-border
+
+
+//== Progress bars
+//
+//##
+
+//** Background color of the whole progress component
+// $progress-bg: #f5f5f5
+//** Progress bar text color
+// $progress-bar-color: #fff
+//** Variable for setting rounded corners on progress bar.
+// $progress-border-radius: $border-radius-base
+
+//** Default progress bar color
+// $progress-bar-bg: $brand-primary
+//** Success progress bar color
+// $progress-bar-success-bg: $brand-success
+//** Warning progress bar color
+// $progress-bar-warning-bg: $brand-warning
+//** Danger progress bar color
+// $progress-bar-danger-bg: $brand-danger
+//** Info progress bar color
+// $progress-bar-info-bg: $brand-info
+
+
+//== List group
+//
+//##
+
+//** Background color on `.list-group-item`
+// $list-group-bg: #fff
+//** `.list-group-item` border color
+// $list-group-border: #ddd
+//** List group border radius
+// $list-group-border-radius: $border-radius-base
+
+//** Background color of single list items on hover
+// $list-group-hover-bg: #f5f5f5
+//** Text color of active list items
+// $list-group-active-color: $component-active-color
+//** Background color of active list items
+// $list-group-active-bg: $component-active-bg
+//** Border color of active list elements
+// $list-group-active-border: $list-group-active-bg
+//** Text color for content within active list items
+// $list-group-active-text-color: lighten($list-group-active-bg, 40%)
+
+//** Text color of disabled list items
+// $list-group-disabled-color: $gray-light
+//** Background color of disabled list items
+// $list-group-disabled-bg: $gray-lighter
+//** Text color for content within disabled list items
+// $list-group-disabled-text-color: $list-group-disabled-color
+
+// $list-group-link-color: #555
+// $list-group-link-hover-color: $list-group-link-color
+// $list-group-link-heading-color: #333
+
+
+//== Panels
+//
+//##
+
+// $panel-bg: #fff
+// $panel-body-padding: 15px
+// $panel-heading-padding: 10px 15px
+// $panel-footer-padding: $panel-heading-padding
+// $panel-border-radius: $border-radius-base
+
+//** Border color for elements within panels
+// $panel-inner-border: #ddd
+// $panel-footer-bg: #f5f5f5
+
+// $panel-default-text: $gray-dark
+// $panel-default-border: #ddd
+// $panel-default-heading-bg: #f5f5f5
+
+// $panel-primary-text: #fff
+// $panel-primary-border: $brand-primary
+// $panel-primary-heading-bg: $brand-primary
+
+// $panel-success-text: $state-success-text
+// $panel-success-border: $state-success-border
+// $panel-success-heading-bg: $state-success-bg
+
+// $panel-info-text: $state-info-text
+// $panel-info-border: $state-info-border
+// $panel-info-heading-bg: $state-info-bg
+
+// $panel-warning-text: $state-warning-text
+// $panel-warning-border: $state-warning-border
+// $panel-warning-heading-bg: $state-warning-bg
+
+// $panel-danger-text: $state-danger-text
+// $panel-danger-border: $state-danger-border
+// $panel-danger-heading-bg: $state-danger-bg
+
+
+//== Thumbnails
+//
+//##
+
+//** Padding around the thumbnail image
+// $thumbnail-padding: 4px
+//** Thumbnail background color
+// $thumbnail-bg: $body-bg
+//** Thumbnail border color
+// $thumbnail-border: #ddd
+//** Thumbnail border radius
+// $thumbnail-border-radius: $border-radius-base
+
+//** Custom text color for thumbnail captions
+// $thumbnail-caption-color: $text-color
+//** Padding around the thumbnail caption
+// $thumbnail-caption-padding: 9px
+
+
+//== Wells
+//
+//##
+
+// $well-bg: #f5f5f5
+// $well-border: darken($well-bg, 7%)
+
+
+//== Badges
+//
+//##
+
+// $badge-color: #fff
+//** Linked badge text color on hover
+// $badge-link-hover-color: #fff
+// $badge-bg: $gray-light
+
+//** Badge text color in active nav link
+// $badge-active-color: $link-color
+//** Badge background color in active nav link
+// $badge-active-bg: #fff
+
+// $badge-font-weight: bold
+// $badge-line-height: 1
+// $badge-border-radius: 10px
+
+
+//== Breadcrumbs
+//
+//##
+
+// $breadcrumb-padding-vertical: 8px
+// $breadcrumb-padding-horizontal: 15px
+//** Breadcrumb background color
+// $breadcrumb-bg: #f5f5f5
+//** Breadcrumb text color
+// $breadcrumb-color: #ccc
+//** Text color of current page in the breadcrumb
+// $breadcrumb-active-color: $gray-light
+//** Textual separator for between breadcrumb elements
+// $breadcrumb-separator: "/"
+
+
+//== Carousel
+//
+//##
+
+// $carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6)
+
+// $carousel-control-color: #fff
+// $carousel-control-width: 15%
+// $carousel-control-opacity: .5
+// $carousel-control-font-size: 20px
+
+// $carousel-indicator-active-bg: #fff
+// $carousel-indicator-border-color: #fff
+
+// $carousel-caption-color: #fff
+
+
+//== Close
+//
+//##
+
+// $close-font-weight: bold
+// $close-color: #000
+// $close-text-shadow: 0 1px 0 #fff
+
+
+//== Code
+//
+//##
+
+// $code-color: #c7254e
+// $code-bg: #f9f2f4
+
+// $kbd-color: #fff
+// $kbd-bg: #333
+
+// $pre-bg: #f5f5f5
+// $pre-color: $gray-dark
+// $pre-border-color: #ccc
+// $pre-scrollable-max-height: 340px
+
+
+//== Type
+//
+//##
+
+//** Horizontal offset for forms and lists.
+// $component-offset-horizontal: 180px
+//** Text muted color
+// $text-muted: $gray-light
+//** Abbreviations and acronyms border color
+// $abbr-border-color: $gray-light
+//** Headings small color
+// $headings-small-color: $gray-light
+//** Blockquote small color
+// $blockquote-small-color: $gray-light
+//** Blockquote font size
+// $blockquote-font-size: ($font-size-base * 1.25)
+//** Blockquote border color
+// $blockquote-border-color: $gray-lighter
+//** Page header border color
+// $page-header-border-color: $gray-lighter
+//** Width of horizontal description list titles
+// $dl-horizontal-offset: $component-offset-horizontal
+//** Horizontal line color.
+// $hr-border: $gray-lighter
diff --git a/templates/project/_bootstrap-variables.sass.erb b/templates/project/_bootstrap-variables.sass.erb
deleted file mode 100644
index d5265d3..0000000
--- a/templates/project/_bootstrap-variables.sass.erb
+++ /dev/null
@@ -1,4 +0,0 @@
-<% require 'bootstrap-sass/version' %>
-// Override Bootstrap variables here (defaults from bootstrap-sass v<%= Bootstrap::VERSION %>):
-
-<%= File.read(@template[:options][:bs_variables_path]).gsub(/^(?=\$)/, '// ').gsub(/ !default;/, '') %>
diff --git a/templates/project/manifest.rb b/templates/project/manifest.rb
index 20d6b63..93b4fac 100644
--- a/templates/project/manifest.rb
+++ b/templates/project/manifest.rb
@@ -3,24 +3,18 @@ description 'Bootstrap for Sass'
# Stylesheet importing bootstrap
stylesheet 'styles.sass'
-manifest = Pathname.new(File.dirname(__FILE__))
-assets = File.expand_path('../../assets', manifest)
-
-# Provide variables files
-bs_stylesheets = "#{assets}/stylesheets/bootstrap"
-stylesheet '_bootstrap-variables.sass.erb',
- :erb => true,
- :to => '_bootstrap-variables.sass',
- :bs_variables_path => File.expand_path("#{bs_stylesheets}/_variables.scss", manifest)
+# Bootstrap variable overrides file
+stylesheet '_bootstrap-variables.sass', :to => '_bootstrap-variables.sass'
# Copy JS and fonts
+manifest = Pathname.new(File.dirname(__FILE__))
+assets = File.expand_path('../../assets', manifest)
{:javascript => 'javascripts',
:font => 'fonts'
}.each do |method, dir|
root = Pathname.new(assets).join(dir)
Dir.glob root.join('**', '*.*') do |path|
path = Pathname.new(path)
- send method, path.relative_path_from(manifest).to_s,
- :to => path.relative_path_from(root).to_s
+ send method, path.relative_path_from(manifest).to_s, :to => path.relative_path_from(root).to_s
end
end
diff --git a/test/dummy_rails/bin/bundle b/test/dummy_rails/bin/bundle
deleted file mode 100755
index 66e9889..0000000
--- a/test/dummy_rails/bin/bundle
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env ruby
-ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
-load Gem.bin_path('bundler', 'bundle')
diff --git a/test/dummy_rails/bin/rails b/test/dummy_rails/bin/rails
deleted file mode 100755
index 728cd85..0000000
--- a/test/dummy_rails/bin/rails
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env ruby
-APP_PATH = File.expand_path('../../config/application', __FILE__)
-require_relative '../config/boot'
-require 'rails/commands'
diff --git a/test/dummy_rails/bin/rake b/test/dummy_rails/bin/rake
deleted file mode 100755
index 1724048..0000000
--- a/test/dummy_rails/bin/rake
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env ruby
-require_relative '../config/boot'
-require 'rake'
-Rake.application.run
diff --git a/test/dummy_rails/db/test.sqlite3 b/test/dummy_rails/db/test.sqlite3
deleted file mode 100644
index e69de29..0000000
--- a/test/dummy_rails/db/test.sqlite3
+++ /dev/null
diff --git a/test/dummy_rails/lib/assets/.keep b/test/dummy_rails/lib/assets/.keep
deleted file mode 100644
index e69de29..0000000
--- a/test/dummy_rails/lib/assets/.keep
+++ /dev/null
diff --git a/test/dummy_rails/log/production.log b/test/dummy_rails/log/production.log
deleted file mode 100644
index e69de29..0000000
--- a/test/dummy_rails/log/production.log
+++ /dev/null
diff --git a/test/dummy_rails/public/404.html b/test/dummy_rails/public/404.html
deleted file mode 100644
index a0daa0c..0000000
--- a/test/dummy_rails/public/404.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>The page you were looking for doesn't exist (404)</title>
- <style>
- body {
- background-color: #EFEFEF;
- color: #2E2F30;
- text-align: center;
- font-family: arial, sans-serif;
- }
-
- div.dialog {
- width: 25em;
- margin: 4em auto 0 auto;
- border: 1px solid #CCC;
- border-right-color: #999;
- border-left-color: #999;
- border-bottom-color: #BBB;
- border-top: #B00100 solid 4px;
- border-top-left-radius: 9px;
- border-top-right-radius: 9px;
- background-color: white;
- padding: 7px 4em 0 4em;
- }
-
- h1 {
- font-size: 100%;
- color: #730E15;
- line-height: 1.5em;
- }
-
- body > p {
- width: 33em;
- margin: 0 auto 1em;
- padding: 1em 0;
- background-color: #F7F7F7;
- border: 1px solid #CCC;
- border-right-color: #999;
- border-bottom-color: #999;
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px;
- border-top-color: #DADADA;
- color: #666;
- box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
- }
- </style>
-</head>
-
-<body>
- <!-- This file lives in public/404.html -->
- <div class="dialog">
- <h1>The page you were looking for doesn't exist.</h1>
- <p>You may have mistyped the address or the page may have moved.</p>
- </div>
- <p>If you are the application owner check the logs for more information.</p>
-</body>
-</html>
diff --git a/test/dummy_rails/public/422.html b/test/dummy_rails/public/422.html
deleted file mode 100644
index fbb4b84..0000000
--- a/test/dummy_rails/public/422.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>The change you wanted was rejected (422)</title>
- <style>
- body {
- background-color: #EFEFEF;
- color: #2E2F30;
- text-align: center;
- font-family: arial, sans-serif;
- }
-
- div.dialog {
- width: 25em;
- margin: 4em auto 0 auto;
- border: 1px solid #CCC;
- border-right-color: #999;
- border-left-color: #999;
- border-bottom-color: #BBB;
- border-top: #B00100 solid 4px;
- border-top-left-radius: 9px;
- border-top-right-radius: 9px;
- background-color: white;
- padding: 7px 4em 0 4em;
- }
-
- h1 {
- font-size: 100%;
- color: #730E15;
- line-height: 1.5em;
- }
-
- body > p {
- width: 33em;
- margin: 0 auto 1em;
- padding: 1em 0;
- background-color: #F7F7F7;
- border: 1px solid #CCC;
- border-right-color: #999;
- border-bottom-color: #999;
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px;
- border-top-color: #DADADA;
- color: #666;
- box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
- }
- </style>
-</head>
-
-<body>
- <!-- This file lives in public/422.html -->
- <div class="dialog">
- <h1>The change you wanted was rejected.</h1>
- <p>Maybe you tried to change something you didn't have access to.</p>
- </div>
- <p>If you are the application owner check the logs for more information.</p>
-</body>
-</html>
diff --git a/test/dummy_rails/public/500.html b/test/dummy_rails/public/500.html
deleted file mode 100644
index e9052d3..0000000
--- a/test/dummy_rails/public/500.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>We're sorry, but something went wrong (500)</title>
- <style>
- body {
- background-color: #EFEFEF;
- color: #2E2F30;
- text-align: center;
- font-family: arial, sans-serif;
- }
-
- div.dialog {
- width: 25em;
- margin: 4em auto 0 auto;
- border: 1px solid #CCC;
- border-right-color: #999;
- border-left-color: #999;
- border-bottom-color: #BBB;
- border-top: #B00100 solid 4px;
- border-top-left-radius: 9px;
- border-top-right-radius: 9px;
- background-color: white;
- padding: 7px 4em 0 4em;
- }
-
- h1 {
- font-size: 100%;
- color: #730E15;
- line-height: 1.5em;
- }
-
- body > p {
- width: 33em;
- margin: 0 auto 1em;
- padding: 1em 0;
- background-color: #F7F7F7;
- border: 1px solid #CCC;
- border-right-color: #999;
- border-bottom-color: #999;
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px;
- border-top-color: #DADADA;
- color: #666;
- box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
- }
- </style>
-</head>
-
-<body>
- <!-- This file lives in public/500.html -->
- <div class="dialog">
- <h1>We're sorry, but something went wrong.</h1>
- </div>
- <p>If you are the application owner check the logs for more information.</p>
-</body>
-</html>
diff --git a/test/dummy_rails/public/favicon.ico b/test/dummy_rails/public/favicon.ico
deleted file mode 100644
index e69de29..0000000
--- a/test/dummy_rails/public/favicon.ico
+++ /dev/null
diff --git a/test/node_sass_compile_test.sh b/test/node_sass_compile_test.sh
new file mode 100755
index 0000000..df6314a
--- /dev/null
+++ b/test/node_sass_compile_test.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Test compilation with node-sass binary
+
+mkdir -p tmp/node-sass
+node-sass assets/stylesheets/bootstrap -o tmp/node-sass/bootstrap.css && \
+node-sass assets/stylesheets/bootstrap/theme -o tmp/node-sass/bootstrap-theme.css || \
+(echo "node-sass compilation failed" && exit 1)
diff --git a/test/node_sass_test.rb b/test/node_sass_test.rb
deleted file mode 100644
index d1c68ec..0000000
--- a/test/node_sass_test.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'test_helper'
-require 'fileutils'
-
-class NodeSassTest < Minitest::Test
- def test_node_sass_compilation
- path = 'assets/stylesheets'
- %w(bootstrap bootstrap/_theme).each do |file|
- FileUtils.mkdir_p 'tmp/node-sass'
- command = "node-sass #{path}/#{file} -o tmp/node-sass/#{File.basename file}.css"
- success = silence_stderr_if !ENV['VERBOSE'] do
- system command
- end
- assert success, 'node-sass compilation failed'
- end
- end
-end
diff --git a/test/support/integration_test.rb b/test/support/integration_test.rb
deleted file mode 100644
index b49bb3a..0000000
--- a/test/support/integration_test.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'capybara'
-module IntegrationTest
- include Capybara::DSL
-
- def setup
- super
- %x[rm -rf test/dummy_rails/tmp/cache]
- end
-
- def teardown
- super
- Capybara.reset_sessions!
- Capybara.use_default_driver
- end
-
- def screenshot!
- screenshot_dir = File.expand_path('../../tmp/', File.dirname(__FILE__))
- page.driver.render(File.join(screenshot_dir, "#{name}.png"), :full => true)
- source = page.evaluate_script("document.getElementsByTagName('html')[0].outerHTML") rescue nil
- File.open(File.join(screenshot_dir, "#{name}.html"), 'w') { |f| f.write(source) } if source
- end
-end