Commit af618249467f8344fb9023797ac941db66e3f546

Authored by Braulio Bhavamitra
1 parent c108f292

responsive: update bootstrap to make it compatible with sass 3.1 (Fix #140)

Showing 51 changed files with 1066 additions and 462 deletions   Show diff stats
@@ -30,6 +30,7 @@ gem 'rack-contrib' @@ -30,6 +30,7 @@ gem 'rack-contrib'
30 # asset pipeline 30 # asset pipeline
31 gem 'uglifier', '>= 1.0.3' 31 gem 'uglifier', '>= 1.0.3'
32 gem 'sass-rails' 32 gem 'sass-rails'
  33 +gem 'sass', '~> 3.1.19'
33 34
34 group :production do 35 group :production do
35 gem 'dalli', '~> 2.7.0' 36 gem 'dalli', '~> 2.7.0'
plugins/responsive/public/_bootstrap-compass.scss 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +@function twbs-font-path($path) {
  2 + @return font-url($path, true);
  3 +}
  4 +
  5 +@function twbs-image-path($path) {
  6 + @return image-url($path, true);
  7 +}
  8 +
  9 +$bootstrap-sass-asset-helper: true;
plugins/responsive/public/_bootstrap-mincer.scss 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +// Mincer asset helper functions
  2 +//
  3 +// This must be imported into a .css.ejs.scss file.
  4 +// Then, <% %>-interpolations will be parsed as strings by Sass, and evaluated by EJS after Sass compilation.
  5 +
  6 +
  7 +@function twbs-font-path($path) {
  8 + // do something like following
  9 + // from "path/to/font.ext#suffix" to "<%- asset_path(path/to/font.ext)) + #suffix %>"
  10 + // from "path/to/font.ext?#suffix" to "<%- asset_path(path/to/font.ext)) + ?#suffix %>"
  11 + // or from "path/to/font.ext" just "<%- asset_path(path/to/font.ext)) %>"
  12 + @return "<%- asset_path("#{$path}".replace(/[#?].*$/, '')) + "#{$path}".replace(/(^[^#?]*)([#?]?.*$)/, '$2') %>";
  13 +}
  14 +
  15 +@function twbs-image-path($file) {
  16 + @return "<%- asset_path("#{$file}") %>";
  17 +}
  18 +
  19 +$bootstrap-sass-asset-helper: true;
plugins/responsive/public/_bootstrap-sprockets.scss
@@ -5,3 +5,5 @@ @@ -5,3 +5,5 @@
5 @function twbs-image-path($path) { 5 @function twbs-image-path($path) {
6 @return image-path($path); 6 @return image-path($path);
7 } 7 }
  8 +
  9 +$bootstrap-sass-asset-helper: true;
plugins/responsive/public/_bootstrap.scss 0 → 100644
@@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
  1 +/*!
  2 + * Bootstrap v3.3.5 (http://getbootstrap.com)
  3 + * Copyright 2011-2015 Twitter, Inc.
  4 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5 + */
  6 +
  7 +// Core variables and mixins
  8 +@import "bootstrap/variables";
  9 +@import "bootstrap/mixins";
  10 +
  11 +// Reset and dependencies
  12 +@import "bootstrap/normalize";
  13 +@import "bootstrap/print";
  14 +@import "bootstrap/glyphicons";
  15 +
  16 +// Core CSS
  17 +@import "bootstrap/scaffolding";
  18 +@import "bootstrap/type";
  19 +@import "bootstrap/code";
  20 +@import "bootstrap/grid";
  21 +@import "bootstrap/tables";
  22 +@import "bootstrap/forms";
  23 +@import "bootstrap/buttons";
  24 +
  25 +// Components
  26 +@import "bootstrap/component-animations";
  27 +@import "bootstrap/dropdowns";
  28 +@import "bootstrap/button-groups";
  29 +@import "bootstrap/input-groups";
  30 +@import "bootstrap/navs";
  31 +@import "bootstrap/navbar";
  32 +@import "bootstrap/breadcrumbs";
  33 +@import "bootstrap/pagination";
  34 +@import "bootstrap/pager";
  35 +@import "bootstrap/labels";
  36 +@import "bootstrap/badges";
  37 +@import "bootstrap/jumbotron";
  38 +@import "bootstrap/thumbnails";
  39 +@import "bootstrap/alerts";
  40 +@import "bootstrap/progress-bars";
  41 +@import "bootstrap/media";
  42 +@import "bootstrap/list-group";
  43 +@import "bootstrap/panels";
  44 +@import "bootstrap/responsive-embed";
  45 +@import "bootstrap/wells";
  46 +@import "bootstrap/close";
  47 +
  48 +// Components w/ JavaScript
  49 +@import "bootstrap/modals";
  50 +@import "bootstrap/tooltip";
  51 +@import "bootstrap/popovers";
  52 +@import "bootstrap/carousel";
  53 +
  54 +// Utility classes
  55 +@import "bootstrap/utilities";
  56 +@import "bootstrap/responsive-utilities";
plugins/responsive/public/bootstrap/_alerts.scss
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 // Specified for the h4 to prevent conflicts of changing $headings-color 18 // Specified for the h4 to prevent conflicts of changing $headings-color
19 color: inherit; 19 color: inherit;
20 } 20 }
  21 +
21 // Provide class for links that match alerts 22 // Provide class for links that match alerts
22 .alert-link { 23 .alert-link {
23 font-weight: $alert-link-font-weight; 24 font-weight: $alert-link-font-weight;
@@ -28,6 +29,7 @@ @@ -28,6 +29,7 @@
28 > ul { 29 > ul {
29 margin-bottom: 0; 30 margin-bottom: 0;
30 } 31 }
  32 +
31 > p + p { 33 > p + p {
32 margin-top: 5px; 34 margin-top: 5px;
33 } 35 }
@@ -57,12 +59,15 @@ @@ -57,12 +59,15 @@
57 .alert-success { 59 .alert-success {
58 @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text); 60 @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text);
59 } 61 }
  62 +
60 .alert-info { 63 .alert-info {
61 @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text); 64 @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text);
62 } 65 }
  66 +
63 .alert-warning { 67 .alert-warning {
64 @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text); 68 @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text);
65 } 69 }
  70 +
66 .alert-danger { 71 .alert-danger {
67 @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text); 72 @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text);
68 } 73 }
plugins/responsive/public/bootstrap/_badges.scss
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 font-weight: $badge-font-weight; 12 font-weight: $badge-font-weight;
13 color: $badge-color; 13 color: $badge-color;
14 line-height: $badge-line-height; 14 line-height: $badge-line-height;
15 - vertical-align: baseline; 15 + vertical-align: middle;
16 white-space: nowrap; 16 white-space: nowrap;
17 text-align: center; 17 text-align: center;
18 background-color: $badge-bg; 18 background-color: $badge-bg;
@@ -28,7 +28,9 @@ @@ -28,7 +28,9 @@
28 position: relative; 28 position: relative;
29 top: -1px; 29 top: -1px;
30 } 30 }
31 - .btn-xs & { 31 +
  32 + .btn-xs &,
  33 + .btn-group-xs > .btn & {
32 top: 0; 34 top: 0;
33 padding: 1px 5px; 35 padding: 1px 5px;
34 } 36 }
@@ -41,12 +43,15 @@ @@ -41,12 +43,15 @@
41 color: $badge-active-color; 43 color: $badge-active-color;
42 background-color: $badge-active-bg; 44 background-color: $badge-active-bg;
43 } 45 }
  46 +
44 .list-group-item > & { 47 .list-group-item > & {
45 float: right; 48 float: right;
46 } 49 }
  50 +
47 .list-group-item > & + & { 51 .list-group-item > & + & {
48 margin-right: 5px; 52 margin-right: 5px;
49 } 53 }
  54 +
50 .nav-pills > li > a > & { 55 .nav-pills > li > a > & {
51 margin-left: 3px; 56 margin-left: 3px;
52 } 57 }
plugins/responsive/public/bootstrap/_breadcrumbs.scss
@@ -14,7 +14,9 @@ @@ -14,7 +14,9 @@
14 display: inline-block; 14 display: inline-block;
15 15
16 + li:before { 16 + li:before {
17 - content: "#{$breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space 17 + // [converter] Workaround for https://github.com/sass/libsass/issues/1115
  18 + $nbsp: "\00a0";
  19 + content: "#{$breadcrumb-separator}#{$nbsp}"; // Unicode space added since inline-block means non-collapsing white-space
18 padding: 0 5px; 20 padding: 0 5px;
19 color: $breadcrumb-color; 21 color: $breadcrumb-color;
20 } 22 }
plugins/responsive/public/bootstrap/_button-groups.scss
@@ -36,6 +36,7 @@ @@ -36,6 +36,7 @@
36 margin-left: -5px; // Offset the first child's margin 36 margin-left: -5px; // Offset the first child's margin
37 @include clearfix; 37 @include clearfix;
38 38
  39 + .btn,
39 .btn-group, 40 .btn-group,
40 .input-group { 41 .input-group {
41 float: left; 42 float: left;
@@ -71,13 +72,13 @@ @@ -71,13 +72,13 @@
71 .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { 72 .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
72 border-radius: 0; 73 border-radius: 0;
73 } 74 }
74 -.btn-group > .btn-group:first-child { 75 +.btn-group > .btn-group:first-child:not(:last-child) {
75 > .btn:last-child, 76 > .btn:last-child,
76 > .dropdown-toggle { 77 > .dropdown-toggle {
77 @include border-right-radius(0); 78 @include border-right-radius(0);
78 } 79 }
79 } 80 }
80 -.btn-group > .btn-group:last-child > .btn:first-child { 81 +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
81 @include border-left-radius(0); 82 @include border-left-radius(0);
82 } 83 }
83 84
@@ -172,11 +173,11 @@ @@ -172,11 +173,11 @@
172 border-radius: 0; 173 border-radius: 0;
173 } 174 }
174 &:first-child:not(:last-child) { 175 &:first-child:not(:last-child) {
175 - border-top-right-radius: $border-radius-base; 176 + border-top-right-radius: $btn-border-radius-base;
176 @include border-bottom-radius(0); 177 @include border-bottom-radius(0);
177 } 178 }
178 &:last-child:not(:first-child) { 179 &:last-child:not(:first-child) {
179 - border-bottom-left-radius: $border-radius-base; 180 + border-bottom-left-radius: $btn-border-radius-base;
180 @include border-top-radius(0); 181 @include border-top-radius(0);
181 } 182 }
182 } 183 }
plugins/responsive/public/bootstrap/_buttons.scss
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 17 background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
18 border: 1px solid transparent; 18 border: 1px solid transparent;
19 white-space: nowrap; 19 white-space: nowrap;
20 - @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $border-radius-base); 20 + @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $btn-border-radius-base);
21 @include user-select(none); 21 @include user-select(none);
22 22
23 &, 23 &,
@@ -47,10 +47,18 @@ @@ -47,10 +47,18 @@
47 &[disabled], 47 &[disabled],
48 fieldset[disabled] & { 48 fieldset[disabled] & {
49 cursor: $cursor-disabled; 49 cursor: $cursor-disabled;
50 - pointer-events: none; // Future-proof disabling of clicks  
51 @include opacity(.65); 50 @include opacity(.65);
52 @include box-shadow(none); 51 @include box-shadow(none);
53 } 52 }
  53 +
  54 + // [converter] extracted a& to a.btn
  55 +}
  56 +
  57 +a.btn {
  58 + &.disabled,
  59 + fieldset[disabled] & {
  60 + pointer-events: none; // Future-proof disabling of clicks on `<a>` elements
  61 + }
54 } 62 }
55 63
56 64
@@ -107,7 +115,7 @@ @@ -107,7 +115,7 @@
107 &:hover, 115 &:hover,
108 &:focus { 116 &:focus {
109 color: $link-hover-color; 117 color: $link-hover-color;
110 - text-decoration: underline; 118 + text-decoration: $link-hover-decoration;
111 background-color: transparent; 119 background-color: transparent;
112 } 120 }
113 &[disabled], 121 &[disabled],
@@ -126,14 +134,14 @@ @@ -126,14 +134,14 @@
126 134
127 .btn-lg { 135 .btn-lg {
128 // line-height: ensure even-numbered height of button next to large input 136 // line-height: ensure even-numbered height of button next to large input
129 - @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large); 137 + @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $btn-border-radius-large);
130 } 138 }
131 .btn-sm { 139 .btn-sm {
132 // line-height: ensure proper height of button next to small input 140 // line-height: ensure proper height of button next to small input
133 - @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small); 141 + @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $btn-border-radius-small);
134 } 142 }
135 .btn-xs { 143 .btn-xs {
136 - @include button-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $line-height-small, $border-radius-small); 144 + @include button-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $line-height-small, $btn-border-radius-small);
137 } 145 }
138 146
139 147
plugins/responsive/public/bootstrap/_carousel.scss
@@ -27,24 +27,24 @@ @@ -27,24 +27,24 @@
27 27
28 // WebKit CSS3 transforms for supported devices 28 // WebKit CSS3 transforms for supported devices
29 @media all and (transform-3d), (-webkit-transform-3d) { 29 @media all and (transform-3d), (-webkit-transform-3d) {
30 - transition: transform .6s ease-in-out;  
31 - backface-visibility: hidden;  
32 - perspective: 1000; 30 + @include transition-transform(0.6s ease-in-out);
  31 + @include backface-visibility(hidden);
  32 + @include perspective(1000px);
33 33
34 &.next, 34 &.next,
35 &.active.right { 35 &.active.right {
36 - transform: translate3d(100%, 0, 0); 36 + @include translate3d(100%, 0, 0);
37 left: 0; 37 left: 0;
38 } 38 }
39 &.prev, 39 &.prev,
40 &.active.left { 40 &.active.left {
41 - transform: translate3d(-100%, 0, 0); 41 + @include translate3d(-100%, 0, 0);
42 left: 0; 42 left: 0;
43 } 43 }
44 &.next.left, 44 &.next.left,
45 &.prev.right, 45 &.prev.right,
46 &.active { 46 &.active {
47 - transform: translate3d(0, 0, 0); 47 + @include translate3d(0, 0, 0);
48 left: 0; 48 left: 0;
49 } 49 }
50 } 50 }
@@ -130,6 +130,7 @@ @@ -130,6 +130,7 @@
130 .glyphicon-chevron-right { 130 .glyphicon-chevron-right {
131 position: absolute; 131 position: absolute;
132 top: 50%; 132 top: 50%;
  133 + margin-top: -10px;
133 z-index: 5; 134 z-index: 5;
134 display: inline-block; 135 display: inline-block;
135 } 136 }
@@ -147,7 +148,7 @@ @@ -147,7 +148,7 @@
147 .icon-next { 148 .icon-next {
148 width: 20px; 149 width: 20px;
149 height: 20px; 150 height: 20px;
150 - margin-top: -10px; 151 + line-height: 1;
151 font-family: serif; 152 font-family: serif;
152 } 153 }
153 154
@@ -195,6 +196,7 @@ @@ -195,6 +196,7 @@
195 // Internet Explorer 8-9 does not support clicks on elements without a set 196 // Internet Explorer 8-9 does not support clicks on elements without a set
196 // `background-color`. We cannot use `filter` since that's not viewed as a 197 // `background-color`. We cannot use `filter` since that's not viewed as a
197 // background color by the browser. Thus, a hack is needed. 198 // background color by the browser. Thus, a hack is needed.
  199 + // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer
198 // 200 //
199 // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we 201 // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we
200 // set alpha transparency for the best results possible. 202 // set alpha transparency for the best results possible.
plugins/responsive/public/bootstrap/_close.scss
@@ -26,6 +26,7 @@ @@ -26,6 +26,7 @@
26 // Additional properties for button version 26 // Additional properties for button version
27 // iOS requires the button element instead of an anchor tag. 27 // iOS requires the button element instead of an anchor tag.
28 // If you want the anchor version, it requires `href="#"`. 28 // If you want the anchor version, it requires `href="#"`.
  29 +// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
29 button.close { 30 button.close {
30 padding: 0; 31 padding: 0;
31 cursor: pointer; 32 cursor: pointer;
plugins/responsive/public/bootstrap/_component-animations.scss
@@ -17,9 +17,8 @@ @@ -17,9 +17,8 @@
17 17
18 .collapse { 18 .collapse {
19 display: none; 19 display: none;
20 - visibility: hidden;  
21 20
22 - &.in { display: block; visibility: visible; } 21 + &.in { display: block; }
23 // [converter] extracted tr&.in to tr.collapse.in 22 // [converter] extracted tr&.in to tr.collapse.in
24 // [converter] extracted tbody&.in to tbody.collapse.in 23 // [converter] extracted tbody&.in to tbody.collapse.in
25 } 24 }
plugins/responsive/public/bootstrap/_dropdowns.scss
@@ -10,12 +10,14 @@ @@ -10,12 +10,14 @@
10 height: 0; 10 height: 0;
11 margin-left: 2px; 11 margin-left: 2px;
12 vertical-align: middle; 12 vertical-align: middle;
13 - border-top: $caret-width-base solid; 13 + border-top: $caret-width-base dashed;
  14 + border-top: $caret-width-base solid \9; // IE8
14 border-right: $caret-width-base solid transparent; 15 border-right: $caret-width-base solid transparent;
15 border-left: $caret-width-base solid transparent; 16 border-left: $caret-width-base solid transparent;
16 } 17 }
17 18
18 // The dropdown wrapper (div) 19 // The dropdown wrapper (div)
  20 +.dropup,
19 .dropdown { 21 .dropdown {
20 position: relative; 22 position: relative;
21 } 23 }
@@ -183,14 +185,15 @@ @@ -183,14 +185,15 @@
183 // Reverse the caret 185 // Reverse the caret
184 .caret { 186 .caret {
185 border-top: 0; 187 border-top: 0;
186 - border-bottom: $caret-width-base solid; 188 + border-bottom: $caret-width-base dashed;
  189 + border-bottom: $caret-width-base solid \9; // IE8
187 content: ""; 190 content: "";
188 } 191 }
189 // Different positioning for bottom up menu 192 // Different positioning for bottom up menu
190 .dropdown-menu { 193 .dropdown-menu {
191 top: auto; 194 top: auto;
192 bottom: 100%; 195 bottom: 100%;
193 - margin-bottom: 1px; 196 + margin-bottom: 2px;
194 } 197 }
195 } 198 }
196 199
plugins/responsive/public/bootstrap/_forms.scss
@@ -56,7 +56,6 @@ input[type=&quot;checkbox&quot;] { @@ -56,7 +56,6 @@ input[type=&quot;checkbox&quot;] {
56 line-height: normal; 56 line-height: normal;
57 } 57 }
58 58
59 -// Set the height of file controls to match text inputs  
60 input[type="file"] { 59 input[type="file"] {
61 display: block; 60 display: block;
62 } 61 }
@@ -123,7 +122,7 @@ output { @@ -123,7 +122,7 @@ output {
123 background-color: $input-bg; 122 background-color: $input-bg;
124 background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 123 background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
125 border: 1px solid $input-border; 124 border: 1px solid $input-border;
126 - border-radius: $input-border-radius; 125 + border-radius: $input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS.
127 @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); 126 @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
128 @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s); 127 @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
129 128
@@ -141,9 +140,13 @@ output { @@ -141,9 +140,13 @@ output {
141 &[disabled], 140 &[disabled],
142 &[readonly], 141 &[readonly],
143 fieldset[disabled] & { 142 fieldset[disabled] & {
144 - cursor: $cursor-disabled;  
145 background-color: $input-bg-disabled; 143 background-color: $input-bg-disabled;
146 - opacity: 1; // iOS fix for unreadable disabled content 144 + opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655
  145 + }
  146 +
  147 + &[disabled],
  148 + fieldset[disabled] & {
  149 + cursor: $cursor-disabled;
147 } 150 }
148 151
149 // [converter] extracted textarea& to textarea.form-control 152 // [converter] extracted textarea& to textarea.form-control
@@ -172,26 +175,28 @@ input[type=&quot;search&quot;] { @@ -172,26 +175,28 @@ input[type=&quot;search&quot;] {
172 // In Mobile Safari, setting `display: block` on temporal inputs causes the 175 // In Mobile Safari, setting `display: block` on temporal inputs causes the
173 // text within the input to become vertically misaligned. As a workaround, we 176 // text within the input to become vertically misaligned. As a workaround, we
174 // set a pixel line-height that matches the given height of the input, but only 177 // set a pixel line-height that matches the given height of the input, but only
175 -// for Safari. 178 +// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848
  179 +//
  180 +// Note that as of 8.3, iOS doesn't support `datetime` or `week`.
176 181
177 @media screen and (-webkit-min-device-pixel-ratio: 0) { 182 @media screen and (-webkit-min-device-pixel-ratio: 0) {
178 input[type="date"], 183 input[type="date"],
179 input[type="time"], 184 input[type="time"],
180 input[type="datetime-local"], 185 input[type="datetime-local"],
181 input[type="month"] { 186 input[type="month"] {
182 - line-height: $input-height-base;  
183 - }  
184 - input[type="date"].input-sm,  
185 - input[type="time"].input-sm,  
186 - input[type="datetime-local"].input-sm,  
187 - input[type="month"].input-sm {  
188 - line-height: $input-height-small;  
189 - }  
190 - input[type="date"].input-lg,  
191 - input[type="time"].input-lg,  
192 - input[type="datetime-local"].input-lg,  
193 - input[type="month"].input-lg {  
194 - line-height: $input-height-large; 187 + &.form-control {
  188 + line-height: $input-height-base;
  189 + }
  190 +
  191 + &.input-sm,
  192 + .input-group-sm & {
  193 + line-height: $input-height-small;
  194 + }
  195 +
  196 + &.input-lg,
  197 + .input-group-lg & {
  198 + line-height: $input-height-large;
  199 + }
195 } 200 }
196 } 201 }
197 202
@@ -202,7 +207,7 @@ input[type=&quot;search&quot;] { @@ -202,7 +207,7 @@ input[type=&quot;search&quot;] {
202 // horizontal forms, use the predefined grid classes. 207 // horizontal forms, use the predefined grid classes.
203 208
204 .form-group { 209 .form-group {
205 - margin-bottom: 15px; 210 + margin-bottom: $form-group-margin-bottom;
206 } 211 }
207 212
208 213
@@ -242,6 +247,7 @@ input[type=&quot;search&quot;] { @@ -242,6 +247,7 @@ input[type=&quot;search&quot;] {
242 // Radios and checkboxes on same line 247 // Radios and checkboxes on same line
243 .radio-inline, 248 .radio-inline,
244 .checkbox-inline { 249 .checkbox-inline {
  250 + position: relative;
245 display: inline-block; 251 display: inline-block;
246 padding-left: 20px; 252 padding-left: 20px;
247 margin-bottom: 0; 253 margin-bottom: 0;
@@ -298,6 +304,7 @@ input[type=&quot;checkbox&quot;] { @@ -298,6 +304,7 @@ input[type=&quot;checkbox&quot;] {
298 padding-bottom: ($padding-base-vertical + 1); 304 padding-bottom: ($padding-base-vertical + 1);
299 // Remove default margin from `p` 305 // Remove default margin from `p`
300 margin-bottom: 0; 306 margin-bottom: 0;
  307 + min-height: ($line-height-computed + $font-size-base);
301 308
302 &.input-lg, 309 &.input-lg,
303 &.input-sm { 310 &.input-sm {
@@ -311,10 +318,61 @@ input[type=&quot;checkbox&quot;] { @@ -311,10 +318,61 @@ input[type=&quot;checkbox&quot;] {
311 // 318 //
312 // Build on `.form-control` with modifier classes to decrease or increase the 319 // Build on `.form-control` with modifier classes to decrease or increase the
313 // height and font-size of form controls. 320 // height and font-size of form controls.
  321 +//
  322 +// The `.form-group-* form-control` variations are sadly duplicated to avoid the
  323 +// issue documented in https://github.com/twbs/bootstrap/issues/15074.
314 324
315 -@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); 325 +@include input-size('.input-sm', $input-height-small, $padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $input-border-radius-small);
  326 +.form-group-sm {
  327 + .form-control {
  328 + height: $input-height-small;
  329 + padding: $padding-small-vertical $padding-small-horizontal;
  330 + font-size: $font-size-small;
  331 + line-height: $line-height-small;
  332 + border-radius: $input-border-radius-small;
  333 + }
  334 + select.form-control {
  335 + height: $input-height-small;
  336 + line-height: $input-height-small;
  337 + }
  338 + textarea.form-control,
  339 + select[multiple].form-control {
  340 + height: auto;
  341 + }
  342 + .form-control-static {
  343 + height: $input-height-small;
  344 + min-height: ($line-height-computed + $font-size-small);
  345 + padding: ($padding-small-vertical + 1) $padding-small-horizontal;
  346 + font-size: $font-size-small;
  347 + line-height: $line-height-small;
  348 + }
  349 +}
316 350
317 -@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); 351 +@include input-size('.input-lg', $input-height-large, $padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $input-border-radius-large);
  352 +.form-group-lg {
  353 + .form-control {
  354 + height: $input-height-large;
  355 + padding: $padding-large-vertical $padding-large-horizontal;
  356 + font-size: $font-size-large;
  357 + line-height: $line-height-large;
  358 + border-radius: $input-border-radius-large;
  359 + }
  360 + select.form-control {
  361 + height: $input-height-large;
  362 + line-height: $input-height-large;
  363 + }
  364 + textarea.form-control,
  365 + select[multiple].form-control {
  366 + height: auto;
  367 + }
  368 + .form-control-static {
  369 + height: $input-height-large;
  370 + min-height: ($line-height-computed + $font-size-large);
  371 + padding: ($padding-large-vertical + 1) $padding-large-horizontal;
  372 + font-size: $font-size-large;
  373 + line-height: $line-height-large;
  374 + }
  375 +}
318 376
319 377
320 // Form control feedback states 378 // Form control feedback states
@@ -343,12 +401,16 @@ input[type=&quot;checkbox&quot;] { @@ -343,12 +401,16 @@ input[type=&quot;checkbox&quot;] {
343 text-align: center; 401 text-align: center;
344 pointer-events: none; 402 pointer-events: none;
345 } 403 }
346 -.input-lg + .form-control-feedback { 404 +.input-lg + .form-control-feedback,
  405 +.input-group-lg + .form-control-feedback,
  406 +.form-group-lg .form-control + .form-control-feedback {
347 width: $input-height-large; 407 width: $input-height-large;
348 height: $input-height-large; 408 height: $input-height-large;
349 line-height: $input-height-large; 409 line-height: $input-height-large;
350 } 410 }
351 -.input-sm + .form-control-feedback { 411 +.input-sm + .form-control-feedback,
  412 +.input-group-sm + .form-control-feedback,
  413 +.form-group-sm .form-control + .form-control-feedback {
352 width: $input-height-small; 414 width: $input-height-small;
353 height: $input-height-small; 415 height: $input-height-small;
354 line-height: $input-height-small; 416 line-height: $input-height-small;
@@ -447,8 +509,7 @@ input[type=&quot;checkbox&quot;] { @@ -447,8 +509,7 @@ input[type=&quot;checkbox&quot;] {
447 } 509 }
448 510
449 // Remove default margin on radios/checkboxes that were used for stacking, and 511 // Remove default margin on radios/checkboxes that were used for stacking, and
450 - // then undo the floating of radios and checkboxes to match (which also avoids  
451 - // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969). 512 + // then undo the floating of radios and checkboxes to match.
452 .radio, 513 .radio,
453 .checkbox { 514 .checkbox {
454 display: inline-block; 515 display: inline-block;
@@ -524,7 +585,7 @@ input[type=&quot;checkbox&quot;] { @@ -524,7 +585,7 @@ input[type=&quot;checkbox&quot;] {
524 // Reposition the icon because it's now within a grid column and columns have 585 // Reposition the icon because it's now within a grid column and columns have
525 // `position: relative;` on them. Also accounts for the grid gutter padding. 586 // `position: relative;` on them. Also accounts for the grid gutter padding.
526 .has-feedback .form-control-feedback { 587 .has-feedback .form-control-feedback {
527 - right: ($grid-gutter-width / 2); 588 + right: floor(($grid-gutter-width / 2));
528 } 589 }
529 590
530 // Form group sizes 591 // Form group sizes
@@ -535,6 +596,7 @@ input[type=&quot;checkbox&quot;] { @@ -535,6 +596,7 @@ input[type=&quot;checkbox&quot;] {
535 @media (min-width: $screen-sm-min) { 596 @media (min-width: $screen-sm-min) {
536 .control-label { 597 .control-label {
537 padding-top: (($padding-large-vertical * $line-height-large) + 1); 598 padding-top: (($padding-large-vertical * $line-height-large) + 1);
  599 + font-size: $font-size-large;
538 } 600 }
539 } 601 }
540 } 602 }
@@ -542,6 +604,7 @@ input[type=&quot;checkbox&quot;] { @@ -542,6 +604,7 @@ input[type=&quot;checkbox&quot;] {
542 @media (min-width: $screen-sm-min) { 604 @media (min-width: $screen-sm-min) {
543 .control-label { 605 .control-label {
544 padding-top: ($padding-small-vertical + 1); 606 padding-top: ($padding-small-vertical + 1);
  607 + font-size: $font-size-small;
545 } 608 }
546 } 609 }
547 } 610 }
plugins/responsive/public/bootstrap/_glyphicons.scss
@@ -7,14 +7,17 @@ @@ -7,14 +7,17 @@
7 // 7 //
8 // <a href="#"><span class="glyphicon glyphicon-star"></span> Star</a> 8 // <a href="#"><span class="glyphicon glyphicon-star"></span> Star</a>
9 9
10 -// Import the fonts  
11 -@font-face {  
12 - font-family: 'Glyphicons Halflings';  
13 - src: url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.eot'), '#{$icon-font-path}#{$icon-font-name}.eot'));  
14 - src: url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.eot?#iefix'), '#{$icon-font-path}#{$icon-font-name}.eot?#iefix')) format('embedded-opentype'),  
15 - url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.woff'), '#{$icon-font-path}#{$icon-font-name}.woff')) format('woff'),  
16 - url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.ttf'), '#{$icon-font-path}#{$icon-font-name}.ttf')) format('truetype'),  
17 - url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}'), '#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}')) format('svg'); 10 +@at-root {
  11 + // Import the fonts
  12 + @font-face {
  13 + font-family: 'Glyphicons Halflings';
  14 + src: url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.eot'), '#{$icon-font-path}#{$icon-font-name}.eot'));
  15 + src: url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.eot?#iefix'), '#{$icon-font-path}#{$icon-font-name}.eot?#iefix')) format('embedded-opentype'),
  16 + url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.woff2'), '#{$icon-font-path}#{$icon-font-name}.woff2')) format('woff2'),
  17 + url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.woff'), '#{$icon-font-path}#{$icon-font-name}.woff')) format('woff'),
  18 + url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.ttf'), '#{$icon-font-path}#{$icon-font-name}.ttf')) format('truetype'),
  19 + url(if($bootstrap-sass-asset-helper, twbs-font-path('#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}'), '#{$icon-font-path}#{$icon-font-name}.svg##{$icon-font-svg-id}')) format('svg');
  20 + }
18 } 21 }
19 22
20 // Catchall baseclass 23 // Catchall baseclass
@@ -232,3 +235,73 @@ @@ -232,3 +235,73 @@
232 .glyphicon-cloud-upload { &:before { content: "\e198"; } } 235 .glyphicon-cloud-upload { &:before { content: "\e198"; } }
233 .glyphicon-tree-conifer { &:before { content: "\e199"; } } 236 .glyphicon-tree-conifer { &:before { content: "\e199"; } }
234 .glyphicon-tree-deciduous { &:before { content: "\e200"; } } 237 .glyphicon-tree-deciduous { &:before { content: "\e200"; } }
  238 +.glyphicon-cd { &:before { content: "\e201"; } }
  239 +.glyphicon-save-file { &:before { content: "\e202"; } }
  240 +.glyphicon-open-file { &:before { content: "\e203"; } }
  241 +.glyphicon-level-up { &:before { content: "\e204"; } }
  242 +.glyphicon-copy { &:before { content: "\e205"; } }
  243 +.glyphicon-paste { &:before { content: "\e206"; } }
  244 +// The following 2 Glyphicons are omitted for the time being because
  245 +// they currently use Unicode codepoints that are outside the
  246 +// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle
  247 +// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.
  248 +// Notably, the bug affects some older versions of the Android Browser.
  249 +// More info: https://github.com/twbs/bootstrap/issues/10106
  250 +// .glyphicon-door { &:before { content: "\1f6aa"; } }
  251 +// .glyphicon-key { &:before { content: "\1f511"; } }
  252 +.glyphicon-alert { &:before { content: "\e209"; } }
  253 +.glyphicon-equalizer { &:before { content: "\e210"; } }
  254 +.glyphicon-king { &:before { content: "\e211"; } }
  255 +.glyphicon-queen { &:before { content: "\e212"; } }
  256 +.glyphicon-pawn { &:before { content: "\e213"; } }
  257 +.glyphicon-bishop { &:before { content: "\e214"; } }
  258 +.glyphicon-knight { &:before { content: "\e215"; } }
  259 +.glyphicon-baby-formula { &:before { content: "\e216"; } }
  260 +.glyphicon-tent { &:before { content: "\26fa"; } }
  261 +.glyphicon-blackboard { &:before { content: "\e218"; } }
  262 +.glyphicon-bed { &:before { content: "\e219"; } }
  263 +.glyphicon-apple { &:before { content: "\f8ff"; } }
  264 +.glyphicon-erase { &:before { content: "\e221"; } }
  265 +.glyphicon-hourglass { &:before { content: "\231b"; } }
  266 +.glyphicon-lamp { &:before { content: "\e223"; } }
  267 +.glyphicon-duplicate { &:before { content: "\e224"; } }
  268 +.glyphicon-piggy-bank { &:before { content: "\e225"; } }
  269 +.glyphicon-scissors { &:before { content: "\e226"; } }
  270 +.glyphicon-bitcoin { &:before { content: "\e227"; } }
  271 +.glyphicon-btc { &:before { content: "\e227"; } }
  272 +.glyphicon-xbt { &:before { content: "\e227"; } }
  273 +.glyphicon-yen { &:before { content: "\00a5"; } }
  274 +.glyphicon-jpy { &:before { content: "\00a5"; } }
  275 +.glyphicon-ruble { &:before { content: "\20bd"; } }
  276 +.glyphicon-rub { &:before { content: "\20bd"; } }
  277 +.glyphicon-scale { &:before { content: "\e230"; } }
  278 +.glyphicon-ice-lolly { &:before { content: "\e231"; } }
  279 +.glyphicon-ice-lolly-tasted { &:before { content: "\e232"; } }
  280 +.glyphicon-education { &:before { content: "\e233"; } }
  281 +.glyphicon-option-horizontal { &:before { content: "\e234"; } }
  282 +.glyphicon-option-vertical { &:before { content: "\e235"; } }
  283 +.glyphicon-menu-hamburger { &:before { content: "\e236"; } }
  284 +.glyphicon-modal-window { &:before { content: "\e237"; } }
  285 +.glyphicon-oil { &:before { content: "\e238"; } }
  286 +.glyphicon-grain { &:before { content: "\e239"; } }
  287 +.glyphicon-sunglasses { &:before { content: "\e240"; } }
  288 +.glyphicon-text-size { &:before { content: "\e241"; } }
  289 +.glyphicon-text-color { &:before { content: "\e242"; } }
  290 +.glyphicon-text-background { &:before { content: "\e243"; } }
  291 +.glyphicon-object-align-top { &:before { content: "\e244"; } }
  292 +.glyphicon-object-align-bottom { &:before { content: "\e245"; } }
  293 +.glyphicon-object-align-horizontal{ &:before { content: "\e246"; } }
  294 +.glyphicon-object-align-left { &:before { content: "\e247"; } }
  295 +.glyphicon-object-align-vertical { &:before { content: "\e248"; } }
  296 +.glyphicon-object-align-right { &:before { content: "\e249"; } }
  297 +.glyphicon-triangle-right { &:before { content: "\e250"; } }
  298 +.glyphicon-triangle-left { &:before { content: "\e251"; } }
  299 +.glyphicon-triangle-bottom { &:before { content: "\e252"; } }
  300 +.glyphicon-triangle-top { &:before { content: "\e253"; } }
  301 +.glyphicon-console { &:before { content: "\e254"; } }
  302 +.glyphicon-superscript { &:before { content: "\e255"; } }
  303 +.glyphicon-subscript { &:before { content: "\e256"; } }
  304 +.glyphicon-menu-left { &:before { content: "\e257"; } }
  305 +.glyphicon-menu-right { &:before { content: "\e258"; } }
  306 +.glyphicon-menu-down { &:before { content: "\e259"; } }
  307 +.glyphicon-menu-up { &:before { content: "\e260"; } }
plugins/responsive/public/bootstrap/_input-groups.scss
@@ -160,6 +160,7 @@ @@ -160,6 +160,7 @@
160 &:last-child { 160 &:last-child {
161 > .btn, 161 > .btn,
162 > .btn-group { 162 > .btn-group {
  163 + z-index: 2;
163 margin-left: -1px; 164 margin-left: -1px;
164 } 165 }
165 } 166 }
plugins/responsive/public/bootstrap/_jumbotron.scss
@@ -4,7 +4,8 @@ @@ -4,7 +4,8 @@
4 4
5 5
6 .jumbotron { 6 .jumbotron {
7 - padding: $jumbotron-padding ($jumbotron-padding / 2); 7 + padding-top: $jumbotron-padding;
  8 + padding-bottom: $jumbotron-padding;
8 margin-bottom: $jumbotron-padding; 9 margin-bottom: $jumbotron-padding;
9 color: $jumbotron-color; 10 color: $jumbotron-color;
10 background-color: $jumbotron-bg; 11 background-color: $jumbotron-bg;
@@ -13,6 +14,7 @@ @@ -13,6 +14,7 @@
13 .h1 { 14 .h1 {
14 color: $jumbotron-heading-color; 15 color: $jumbotron-heading-color;
15 } 16 }
  17 +
16 p { 18 p {
17 margin-bottom: ($jumbotron-padding / 2); 19 margin-bottom: ($jumbotron-padding / 2);
18 font-size: $jumbotron-font-size; 20 font-size: $jumbotron-font-size;
@@ -33,7 +35,8 @@ @@ -33,7 +35,8 @@
33 } 35 }
34 36
35 @media screen and (min-width: $screen-sm-min) { 37 @media screen and (min-width: $screen-sm-min) {
36 - padding: ($jumbotron-padding * 1.6) 0; 38 + padding-top: ($jumbotron-padding * 1.6);
  39 + padding-bottom: ($jumbotron-padding * 1.6);
37 40
38 .container &, 41 .container &,
39 .container-fluid & { 42 .container-fluid & {
@@ -43,7 +46,7 @@ @@ -43,7 +46,7 @@
43 46
44 h1, 47 h1,
45 .h1 { 48 .h1 {
46 - font-size: ($font-size-base * 4.5); 49 + font-size: $jumbotron-heading-font-size;
47 } 50 }
48 } 51 }
49 } 52 }
plugins/responsive/public/bootstrap/_list-group.scss
@@ -38,12 +38,13 @@ @@ -38,12 +38,13 @@
38 } 38 }
39 39
40 40
41 -// Linked list items 41 +// Interactive list items
42 // 42 //
43 -// Use anchor elements instead of `li`s or `div`s to create linked list items. 43 +// Use anchor or button elements instead of `li`s or `div`s to create interactive items.
44 // Includes an extra `.active` modifier class for showing selected items. 44 // Includes an extra `.active` modifier class for showing selected items.
45 45
46 -a.list-group-item { 46 +a.list-group-item,
  47 +button.list-group-item {
47 color: $list-group-link-color; 48 color: $list-group-link-color;
48 49
49 .list-group-item-heading { 50 .list-group-item-heading {
@@ -59,6 +60,11 @@ a.list-group-item { @@ -59,6 +60,11 @@ a.list-group-item {
59 } 60 }
60 } 61 }
61 62
  63 +button.list-group-item {
  64 + width: 100%;
  65 + text-align: left;
  66 +}
  67 +
62 .list-group-item { 68 .list-group-item {
63 // Disabled state 69 // Disabled state
64 &.disabled, 70 &.disabled,
plugins/responsive/public/bootstrap/_media.scss
@@ -7,6 +7,25 @@ @@ -7,6 +7,25 @@
7 } 7 }
8 } 8 }
9 9
  10 +.media,
  11 +.media-body {
  12 + zoom: 1;
  13 + overflow: hidden;
  14 +}
  15 +
  16 +.media-body {
  17 + width: 10000px;
  18 +}
  19 +
  20 +.media-object {
  21 + display: block;
  22 +
  23 + // Fix collapse in webkit from max-width: 100% and display: table-cell.
  24 + &.img-thumbnail {
  25 + max-width: none;
  26 + }
  27 +}
  28 +
10 .media-right, 29 .media-right,
11 .media > .pull-right { 30 .media > .pull-right {
12 padding-left: 10px; 31 padding-left: 10px;
plugins/responsive/public/bootstrap/_mixins.scss
@@ -2,38 +2,39 @@ @@ -2,38 +2,39 @@
2 // -------------------------------------------------- 2 // --------------------------------------------------
3 3
4 // Utilities 4 // Utilities
5 -@import "bootstrap/mixins/hide-text";  
6 -@import "bootstrap/mixins/opacity";  
7 -@import "bootstrap/mixins/image";  
8 -@import "bootstrap/mixins/labels";  
9 -@import "bootstrap/mixins/reset-filter";  
10 -@import "bootstrap/mixins/resize";  
11 -@import "bootstrap/mixins/responsive-visibility";  
12 -@import "bootstrap/mixins/size";  
13 -@import "bootstrap/mixins/tab-focus";  
14 -@import "bootstrap/mixins/text-emphasis";  
15 -@import "bootstrap/mixins/text-overflow";  
16 -@import "bootstrap/mixins/vendor-prefixes"; 5 +@import "mixins/hide-text";
  6 +@import "mixins/opacity";
  7 +@import "mixins/image";
  8 +@import "mixins/labels";
  9 +@import "mixins/reset-filter";
  10 +@import "mixins/resize";
  11 +@import "mixins/responsive-visibility";
  12 +@import "mixins/size";
  13 +@import "mixins/tab-focus";
  14 +@import "mixins/reset-text";
  15 +@import "mixins/text-emphasis";
  16 +@import "mixins/text-overflow";
  17 +@import "mixins/vendor-prefixes";
17 18
18 // Components 19 // Components
19 -@import "bootstrap/mixins/alerts";  
20 -@import "bootstrap/mixins/buttons";  
21 -@import "bootstrap/mixins/panels";  
22 -@import "bootstrap/mixins/pagination";  
23 -@import "bootstrap/mixins/list-group";  
24 -@import "bootstrap/mixins/nav-divider";  
25 -@import "bootstrap/mixins/forms";  
26 -@import "bootstrap/mixins/progress-bar";  
27 -@import "bootstrap/mixins/table-row"; 20 +@import "mixins/alerts";
  21 +@import "mixins/buttons";
  22 +@import "mixins/panels";
  23 +@import "mixins/pagination";
  24 +@import "mixins/list-group";
  25 +@import "mixins/nav-divider";
  26 +@import "mixins/forms";
  27 +@import "mixins/progress-bar";
  28 +@import "mixins/table-row";
28 29
29 // Skins 30 // Skins
30 -@import "bootstrap/mixins/background-variant";  
31 -@import "bootstrap/mixins/border-radius";  
32 -@import "bootstrap/mixins/gradients"; 31 +@import "mixins/background-variant";
  32 +@import "mixins/border-radius";
  33 +@import "mixins/gradients";
33 34
34 // Layout 35 // Layout
35 -@import "bootstrap/mixins/clearfix";  
36 -@import "bootstrap/mixins/center-block";  
37 -@import "bootstrap/mixins/nav-vertical-align";  
38 -@import "bootstrap/mixins/grid-framework";  
39 -@import "bootstrap/mixins/grid"; 36 +@import "mixins/clearfix";
  37 +@import "mixins/center-block";
  38 +@import "mixins/nav-vertical-align";
  39 +@import "mixins/grid-framework";
  40 +@import "mixins/grid";
plugins/responsive/public/bootstrap/_modals.scss
@@ -62,10 +62,12 @@ @@ -62,10 +62,12 @@
62 62
63 // Modal background 63 // Modal background
64 .modal-backdrop { 64 .modal-backdrop {
65 - position: absolute; 65 + position: fixed;
66 top: 0; 66 top: 0;
67 right: 0; 67 right: 0;
  68 + bottom: 0;
68 left: 0; 69 left: 0;
  70 + z-index: $zindex-modal-background;
69 background-color: $modal-backdrop-bg; 71 background-color: $modal-backdrop-bg;
70 // Fade for backdrop 72 // Fade for backdrop
71 &.fade { @include opacity(0); } 73 &.fade { @include opacity(0); }
plugins/responsive/public/bootstrap/_navbar.scss
@@ -67,7 +67,6 @@ @@ -67,7 +67,6 @@
67 67
68 &.collapse { 68 &.collapse {
69 display: block !important; 69 display: block !important;
70 - visibility: visible !important;  
71 height: auto !important; 70 height: auto !important;
72 padding-bottom: 0; // Override default setting 71 padding-bottom: 0; // Override default setting
73 overflow: visible !important; 72 overflow: visible !important;
@@ -331,6 +330,7 @@ @@ -331,6 +330,7 @@
331 } 330 }
332 // Menu position and menu caret support for dropups via extra dropup class 331 // Menu position and menu caret support for dropups via extra dropup class
333 .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { 332 .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
  333 + margin-bottom: 0;
334 @include border-top-radius($navbar-border-radius); 334 @include border-top-radius($navbar-border-radius);
335 @include border-bottom-radius(0); 335 @include border-bottom-radius(0);
336 } 336 }
plugins/responsive/public/bootstrap/_navs.scss
@@ -223,11 +223,9 @@ @@ -223,11 +223,9 @@
223 .tab-content { 223 .tab-content {
224 > .tab-pane { 224 > .tab-pane {
225 display: none; 225 display: none;
226 - visibility: hidden;  
227 } 226 }
228 > .active { 227 > .active {
229 display: block; 228 display: block;
230 - visibility: visible;  
231 } 229 }
232 } 230 }
233 231
plugins/responsive/public/bootstrap/_normalize.scss
1 -/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 1 +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
2 2
3 // 3 //
4 // 1. Set default font family to sans-serif. 4 // 1. Set default font family to sans-serif.
5 -// 2. Prevent iOS text size adjust after orientation change, without disabling  
6 -// user zoom. 5 +// 2. Prevent iOS and IE text size adjust after device orientation change,
  6 +// without disabling user zoom.
7 // 7 //
8 8
9 html { 9 html {
@@ -71,7 +71,7 @@ audio:not([controls]) { @@ -71,7 +71,7 @@ audio:not([controls]) {
71 71
72 // 72 //
73 // Address `[hidden]` styling not present in IE 8/9/10. 73 // Address `[hidden]` styling not present in IE 8/9/10.
74 -// Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 74 +// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
75 // 75 //
76 76
77 [hidden], 77 [hidden],
@@ -91,7 +91,8 @@ a { @@ -91,7 +91,8 @@ a {
91 } 91 }
92 92
93 // 93 //
94 -// Improve readability when focused and also mouse hovered in all browsers. 94 +// Improve readability of focused elements when they are also in an
  95 +// active/hover state.
95 // 96 //
96 97
97 a:active, 98 a:active,
@@ -209,7 +210,6 @@ figure { @@ -209,7 +210,6 @@ figure {
209 // 210 //
210 211
211 hr { 212 hr {
212 - -moz-box-sizing: content-box;  
213 box-sizing: content-box; 213 box-sizing: content-box;
214 height: 0; 214 height: 0;
215 } 215 }
@@ -350,15 +350,12 @@ input[type=&quot;number&quot;]::-webkit-outer-spin-button { @@ -350,15 +350,12 @@ input[type=&quot;number&quot;]::-webkit-outer-spin-button {
350 350
351 // 351 //
352 // 1. Address `appearance` set to `searchfield` in Safari and Chrome. 352 // 1. Address `appearance` set to `searchfield` in Safari and Chrome.
353 -// 2. Address `box-sizing` set to `border-box` in Safari and Chrome  
354 -// (include `-moz` to future-proof). 353 +// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
355 // 354 //
356 355
357 input[type="search"] { 356 input[type="search"] {
358 -webkit-appearance: textfield; // 1 357 -webkit-appearance: textfield; // 1
359 - -moz-box-sizing: content-box;  
360 - -webkit-box-sizing: content-box; // 2  
361 - box-sizing: content-box; 358 + box-sizing: content-box; //2
362 } 359 }
363 360
364 // 361 //
plugins/responsive/public/bootstrap/_pagination.scss
@@ -40,6 +40,7 @@ @@ -40,6 +40,7 @@
40 > li > span { 40 > li > span {
41 &:hover, 41 &:hover,
42 &:focus { 42 &:focus {
  43 + z-index: 3;
43 color: $pagination-hover-color; 44 color: $pagination-hover-color;
44 background-color: $pagination-hover-bg; 45 background-color: $pagination-hover-bg;
45 border-color: $pagination-hover-border; 46 border-color: $pagination-hover-border;
@@ -79,10 +80,10 @@ @@ -79,10 +80,10 @@
79 80
80 // Large 81 // Large
81 .pagination-lg { 82 .pagination-lg {
82 - @include pagination-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $border-radius-large); 83 + @include pagination-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large);
83 } 84 }
84 85
85 // Small 86 // Small
86 .pagination-sm { 87 .pagination-sm {
87 - @include pagination-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $border-radius-small); 88 + @include pagination-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small);
88 } 89 }
plugins/responsive/public/bootstrap/_panels.scss
@@ -36,7 +36,11 @@ @@ -36,7 +36,11 @@
36 font-size: ceil(($font-size-base * 1.125)); 36 font-size: ceil(($font-size-base * 1.125));
37 color: inherit; 37 color: inherit;
38 38
39 - > a { 39 + > a,
  40 + > small,
  41 + > .small,
  42 + > small > a,
  43 + > .small > a {
40 color: inherit; 44 color: inherit;
41 } 45 }
42 } 46 }
@@ -72,6 +76,7 @@ @@ -72,6 +76,7 @@
72 @include border-top-radius(($panel-border-radius - 1)); 76 @include border-top-radius(($panel-border-radius - 1));
73 } 77 }
74 } 78 }
  79 +
75 // Add border bottom radius for last one 80 // Add border bottom radius for last one
76 &:last-child { 81 &:last-child {
77 .list-group-item:last-child { 82 .list-group-item:last-child {
@@ -80,6 +85,11 @@ @@ -80,6 +85,11 @@
80 } 85 }
81 } 86 }
82 } 87 }
  88 + > .panel-heading + .panel-collapse > .list-group {
  89 + .list-group-item:first-child {
  90 + @include border-top-radius(0);
  91 + }
  92 + }
83 } 93 }
84 // Collapse space between when there's no additional content. 94 // Collapse space between when there's no additional content.
85 .panel-heading + .list-group { 95 .panel-heading + .list-group {
plugins/responsive/public/bootstrap/_popovers.scss
@@ -11,12 +11,11 @@ @@ -11,12 +11,11 @@
11 display: none; 11 display: none;
12 max-width: $popover-max-width; 12 max-width: $popover-max-width;
13 padding: 1px; 13 padding: 1px;
14 - // Reset font and text propertes given new insertion method  
15 - font-family: $font-family-base; 14 + // Our parent element can be arbitrary since popovers are by default inserted as a sibling of their target element.
  15 + // So reset our font and text properties to avoid inheriting weird values.
  16 + @include reset-text;
16 font-size: $font-size-base; 17 font-size: $font-size-base;
17 - font-weight: normal;  
18 - line-height: $line-height-base;  
19 - text-align: left; 18 +
20 background-color: $popover-bg; 19 background-color: $popover-bg;
21 background-clip: padding-box; 20 background-clip: padding-box;
22 border: 1px solid $popover-fallback-border-color; 21 border: 1px solid $popover-fallback-border-color;
@@ -24,9 +23,6 @@ @@ -24,9 +23,6 @@
24 border-radius: $border-radius-large; 23 border-radius: $border-radius-large;
25 @include box-shadow(0 5px 10px rgba(0,0,0,.2)); 24 @include box-shadow(0 5px 10px rgba(0,0,0,.2));
26 25
27 - // Overrides for proper insertion  
28 - white-space: normal;  
29 -  
30 // Offset the popover to account for the popover arrow 26 // Offset the popover to account for the popover arrow
31 &.top { margin-top: -$popover-arrow-width; } 27 &.top { margin-top: -$popover-arrow-width; }
32 &.right { margin-left: $popover-arrow-width; } 28 &.right { margin-left: $popover-arrow-width; }
plugins/responsive/public/bootstrap/_print.scss
@@ -67,12 +67,6 @@ @@ -67,12 +67,6 @@
67 } 67 }
68 68
69 // Bootstrap specific changes start 69 // Bootstrap specific changes start
70 - //  
71 - // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245  
72 - // Once fixed, we can just straight up remove this.  
73 - select {  
74 - background: #fff !important;  
75 - }  
76 70
77 // Bootstrap components 71 // Bootstrap components
78 .navbar { 72 .navbar {
plugins/responsive/public/bootstrap/_responsive-embed.scss
@@ -22,14 +22,14 @@ @@ -22,14 +22,14 @@
22 width: 100%; 22 width: 100%;
23 border: 0; 23 border: 0;
24 } 24 }
  25 +}
25 26
26 - // Modifier class for 16:9 aspect ratio  
27 - &.embed-responsive-16by9 {  
28 - padding-bottom: 56.25%;  
29 - } 27 +// Modifier class for 16:9 aspect ratio
  28 +.embed-responsive-16by9 {
  29 + padding-bottom: 56.25%;
  30 +}
30 31
31 - // Modifier class for 4:3 aspect ratio  
32 - &.embed-responsive-4by3 {  
33 - padding-bottom: 75%;  
34 - } 32 +// Modifier class for 4:3 aspect ratio
  33 +.embed-responsive-4by3 {
  34 + padding-bottom: 75%;
35 } 35 }
plugins/responsive/public/bootstrap/_responsive-utilities.scss
@@ -18,15 +18,20 @@ @@ -18,15 +18,20 @@
18 // Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/ 18 // Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/
19 // Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ 19 // Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/
20 20
21 -@-ms-viewport {  
22 - width: device-width; 21 +@at-root {
  22 + @-ms-viewport {
  23 + width: device-width;
  24 + }
23 } 25 }
24 26
25 27
26 // Visibility utilities 28 // Visibility utilities
27 // Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0 29 // Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0
28 30
29 -@include responsive-invisibility('.visible-xs, .visible-sm, .visible-md, .visible-lg'); 31 +@include responsive-invisibility('.visible-xs');
  32 +@include responsive-invisibility('.visible-sm');
  33 +@include responsive-invisibility('.visible-md');
  34 +@include responsive-invisibility('.visible-lg');
30 35
31 .visible-xs-block, 36 .visible-xs-block,
32 .visible-xs-inline, 37 .visible-xs-inline,
plugins/responsive/public/bootstrap/_scaffolding.scss
@@ -148,3 +148,14 @@ hr { @@ -148,3 +148,14 @@ hr {
148 clip: auto; 148 clip: auto;
149 } 149 }
150 } 150 }
  151 +
  152 +
  153 +// iOS "clickable elements" fix for role="button"
  154 +//
  155 +// Fixes "clickability" issue (and more generally, the firing of events such as focus as well)
  156 +// for traditionally non-focusable elements with role="button"
  157 +// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
  158 +
  159 +[role="button"] {
  160 + cursor: pointer;
  161 +}
plugins/responsive/public/bootstrap/_tables.scss
@@ -111,7 +111,7 @@ th { @@ -111,7 +111,7 @@ th {
111 // Default zebra-stripe styles (alternating gray and transparent backgrounds) 111 // Default zebra-stripe styles (alternating gray and transparent backgrounds)
112 112
113 .table-striped { 113 .table-striped {
114 - > tbody > tr:nth-child(odd) { 114 + > tbody > tr:nth-of-type(odd) {
115 background-color: $table-bg-accent; 115 background-color: $table-bg-accent;
116 } 116 }
117 } 117 }
@@ -133,7 +133,7 @@ th { @@ -133,7 +133,7 @@ th {
133 // Reset default table behavior 133 // Reset default table behavior
134 134
135 table col[class*="col-"] { 135 table col[class*="col-"] {
136 - position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623) 136 + position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)
137 float: none; 137 float: none;
138 display: table-column; 138 display: table-column;
139 } 139 }
@@ -141,7 +141,7 @@ table { @@ -141,7 +141,7 @@ table {
141 td, 141 td,
142 th { 142 th {
143 &[class*="col-"] { 143 &[class*="col-"] {
144 - position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623) 144 + position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)
145 float: none; 145 float: none;
146 display: table-cell; 146 display: table-cell;
147 } 147 }
plugins/responsive/public/bootstrap/_theme.scss
  1 +/*!
  2 + * Bootstrap v3.3.5 (http://getbootstrap.com)
  3 + * Copyright 2011-2015 Twitter, Inc.
  4 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5 + */
1 6
2 // 7 //
3 // Load core variables and mixins 8 // Load core variables and mixins
@@ -28,6 +33,12 @@ @@ -28,6 +33,12 @@
28 @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); 33 @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
29 } 34 }
30 35
  36 + &.disabled,
  37 + &[disabled],
  38 + fieldset[disabled] & {
  39 + @include box-shadow(none);
  40 + }
  41 +
31 .badge { 42 .badge {
32 text-shadow: none; 43 text-shadow: none;
33 } 44 }
@@ -36,7 +47,7 @@ @@ -36,7 +47,7 @@
36 // Mixin for generating new styles 47 // Mixin for generating new styles
37 @mixin btn-styles($btn-color: #555) { 48 @mixin btn-styles($btn-color: #555) {
38 @include gradient-vertical($start-color: $btn-color, $end-color: darken($btn-color, 12%)); 49 @include gradient-vertical($start-color: $btn-color, $end-color: darken($btn-color, 12%));
39 - @include reset-filter; // Disable gradients for IE9 because filter bleeds through rounded corners 50 + @include reset-filter; // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620
40 background-repeat: repeat-x; 51 background-repeat: repeat-x;
41 border-color: darken($btn-color, 14%); 52 border-color: darken($btn-color, 14%);
42 53
@@ -52,10 +63,18 @@ @@ -52,10 +63,18 @@
52 border-color: darken($btn-color, 14%); 63 border-color: darken($btn-color, 14%);
53 } 64 }
54 65
55 - &:disabled,  
56 - &[disabled] {  
57 - background-color: darken($btn-color, 12%);  
58 - background-image: none; 66 + &.disabled,
  67 + &[disabled],
  68 + fieldset[disabled] & {
  69 + &,
  70 + &:hover,
  71 + &:focus,
  72 + &.focus,
  73 + &:active,
  74 + &.active {
  75 + background-color: darken($btn-color, 12%);
  76 + background-image: none;
  77 + }
59 } 78 }
60 } 79 }
61 80
@@ -130,8 +149,8 @@ @@ -130,8 +149,8 @@
130 // Inverted navbar 149 // Inverted navbar
131 .navbar-inverse { 150 .navbar-inverse {
132 @include gradient-vertical($start-color: lighten($navbar-inverse-bg, 10%), $end-color: $navbar-inverse-bg); 151 @include gradient-vertical($start-color: lighten($navbar-inverse-bg, 10%), $end-color: $navbar-inverse-bg);
133 - @include reset-filter; // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered  
134 - 152 + @include reset-filter; // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257
  153 + border-radius: $navbar-border-radius;
135 .navbar-nav > .open > a, 154 .navbar-nav > .open > a,
136 .navbar-nav > .active > a { 155 .navbar-nav > .active > a {
137 @include gradient-vertical($start-color: $navbar-inverse-link-active-bg, $end-color: lighten($navbar-inverse-link-active-bg, 2.5%)); 156 @include gradient-vertical($start-color: $navbar-inverse-link-active-bg, $end-color: lighten($navbar-inverse-link-active-bg, 2.5%));
plugins/responsive/public/bootstrap/_tooltip.scss
@@ -8,12 +8,11 @@ @@ -8,12 +8,11 @@
8 position: absolute; 8 position: absolute;
9 z-index: $zindex-tooltip; 9 z-index: $zindex-tooltip;
10 display: block; 10 display: block;
11 - visibility: visible;  
12 - // Reset font and text propertes given new insertion method  
13 - font-family: $font-family-base; 11 + // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
  12 + // So reset our font and text properties to avoid inheriting weird values.
  13 + @include reset-text;
14 font-size: $font-size-small; 14 font-size: $font-size-small;
15 - font-weight: normal;  
16 - line-height: 1.4; 15 +
17 @include opacity(0); 16 @include opacity(0);
18 17
19 &.in { @include opacity($tooltip-opacity); } 18 &.in { @include opacity($tooltip-opacity); }
@@ -29,7 +28,6 @@ @@ -29,7 +28,6 @@
29 padding: 3px 8px; 28 padding: 3px 8px;
30 color: $tooltip-color; 29 color: $tooltip-color;
31 text-align: center; 30 text-align: center;
32 - text-decoration: none;  
33 background-color: $tooltip-bg; 31 background-color: $tooltip-bg;
34 border-radius: $border-radius-base; 32 border-radius: $border-radius-base;
35 } 33 }
plugins/responsive/public/bootstrap/_type.scss
@@ -234,7 +234,7 @@ abbr[data-original-title] { @@ -234,7 +234,7 @@ abbr[data-original-title] {
234 } 234 }
235 .initialism { 235 .initialism {
236 font-size: 90%; 236 font-size: 90%;
237 - text-transform: uppercase; 237 + @extend .text-uppercase;
238 } 238 }
239 239
240 // Blockquotes 240 // Blockquotes
plugins/responsive/public/bootstrap/_utilities.scss
@@ -44,7 +44,6 @@ @@ -44,7 +44,6 @@
44 44
45 .hidden { 45 .hidden {
46 display: none !important; 46 display: none !important;
47 - visibility: hidden !important;  
48 } 47 }
49 48
50 49
plugins/responsive/public/bootstrap/_variables.scss
1 -// When true, asset path helpers are used, otherwise the regular CSS `url()` is used.  
2 -// When there no function is defined, `fn('')` is parsed as string that equals the right hand side  
3 -// NB: in Sass 3.3 there is a native function: function-exists(twbs-font-path)  
4 -$bootstrap-sass-asset-helper: (twbs-font-path("") != unquote('twbs-font-path("")')) !default;  
5 - 1 +$bootstrap-sass-asset-helper: false !default;
6 // 2 //
7 // Variables 3 // Variables
8 // -------------------------------------------------- 4 // --------------------------------------------------
@@ -19,7 +15,7 @@ $gray: lighten($gray-base, 33.5%) !default; // #555 @@ -19,7 +15,7 @@ $gray: lighten($gray-base, 33.5%) !default; // #555
19 $gray-light: lighten($gray-base, 46.7%) !default; // #777 15 $gray-light: lighten($gray-base, 46.7%) !default; // #777
20 $gray-lighter: lighten($gray-base, 93.5%) !default; // #eee 16 $gray-lighter: lighten($gray-base, 93.5%) !default; // #eee
21 17
22 -$brand-primary: darken(#428bca, 6.5%) !default; 18 +$brand-primary: darken(#428bca, 6.5%) !default; // #337ab7
23 $brand-success: #5cb85c !default; 19 $brand-success: #5cb85c !default;
24 $brand-info: #5bc0de !default; 20 $brand-info: #5bc0de !default;
25 $brand-warning: #f0ad4e !default; 21 $brand-warning: #f0ad4e !default;
@@ -82,7 +78,8 @@ $headings-color: inherit !default; @@ -82,7 +78,8 @@ $headings-color: inherit !default;
82 78
83 //** Load fonts from this directory. 79 //** Load fonts from this directory.
84 80
85 -// [converter] Asset helpers such as Sprockets and Node.js Mincer do not resolve relative paths 81 +// [converter] If $bootstrap-sass-asset-helper if used, provide path relative to the assets load path.
  82 +// [converter] This is because some asset helpers, such as Sprockets, do not work with file-relative paths.
86 $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default; 83 $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
87 84
88 //** File name for all font files. 85 //** File name for all font files.
@@ -107,7 +104,7 @@ $padding-small-horizontal: 10px !default; @@ -107,7 +104,7 @@ $padding-small-horizontal: 10px !default;
107 $padding-xs-vertical: 1px !default; 104 $padding-xs-vertical: 1px !default;
108 $padding-xs-horizontal: 5px !default; 105 $padding-xs-horizontal: 5px !default;
109 106
110 -$line-height-large: 1.33 !default; 107 +$line-height-large: 1.3333333 !default; // extra decimals for Win 8.1 Chrome
111 $line-height-small: 1.5 !default; 108 $line-height-small: 1.5 !default;
112 109
113 $border-radius-base: 4px !default; 110 $border-radius-base: 4px !default;
@@ -178,6 +175,11 @@ $btn-danger-border: darken($btn-danger-bg, 5%) !default; @@ -178,6 +175,11 @@ $btn-danger-border: darken($btn-danger-bg, 5%) !default;
178 175
179 $btn-link-disabled-color: $gray-light !default; 176 $btn-link-disabled-color: $gray-light !default;
180 177
  178 +// Allows for customizing button radius independently from global border radius
  179 +$btn-border-radius-base: $border-radius-base !default;
  180 +$btn-border-radius-large: $border-radius-large !default;
  181 +$btn-border-radius-small: $border-radius-small !default;
  182 +
181 183
182 //== Forms 184 //== Forms
183 // 185 //
@@ -195,6 +197,7 @@ $input-border: #ccc !default; @@ -195,6 +197,7 @@ $input-border: #ccc !default;
195 197
196 // TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4 198 // TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
197 //** Default `.form-control` border radius 199 //** Default `.form-control` border radius
  200 +// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS.
198 $input-border-radius: $border-radius-base !default; 201 $input-border-radius: $border-radius-base !default;
199 //** Large `.form-control` border radius 202 //** Large `.form-control` border radius
200 $input-border-radius-large: $border-radius-large !default; 203 $input-border-radius-large: $border-radius-large !default;
@@ -214,6 +217,9 @@ $input-height-large: (ceil($font-size-large * $line-height-large) + @@ -214,6 +217,9 @@ $input-height-large: (ceil($font-size-large * $line-height-large) +
214 //** Small `.form-control` height 217 //** Small `.form-control` height
215 $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default; 218 $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
216 219
  220 +//** `.form-group` margin
  221 +$form-group-margin-bottom: 15px !default;
  222 +
217 $legend-color: $gray-dark !default; 223 $legend-color: $gray-dark !default;
218 $legend-border-color: #e5e5e5 !default; 224 $legend-border-color: #e5e5e5 !default;
219 225
@@ -273,7 +279,8 @@ $zindex-dropdown: 1000 !default; @@ -273,7 +279,8 @@ $zindex-dropdown: 1000 !default;
273 $zindex-popover: 1060 !default; 279 $zindex-popover: 1060 !default;
274 $zindex-tooltip: 1070 !default; 280 $zindex-tooltip: 1070 !default;
275 $zindex-navbar-fixed: 1030 !default; 281 $zindex-navbar-fixed: 1030 !default;
276 -$zindex-modal: 1040 !default; 282 +$zindex-modal-background: 1040 !default;
  283 +$zindex-modal: 1050 !default;
277 284
278 285
279 //== Media queries breakpoints 286 //== Media queries breakpoints
@@ -386,7 +393,7 @@ $navbar-default-toggle-icon-bar-bg: #888 !default; @@ -386,7 +393,7 @@ $navbar-default-toggle-icon-bar-bg: #888 !default;
386 $navbar-default-toggle-border-color: #ddd !default; 393 $navbar-default-toggle-border-color: #ddd !default;
387 394
388 395
389 -// Inverted navbar 396 +//=== Inverted navbar
390 // Reset inverted navbar basics 397 // Reset inverted navbar basics
391 $navbar-inverse-color: lighten($gray-light, 15%) !default; 398 $navbar-inverse-color: lighten($gray-light, 15%) !default;
392 $navbar-inverse-bg: #222 !default; 399 $navbar-inverse-bg: #222 !default;
@@ -487,6 +494,7 @@ $jumbotron-color: inherit !default; @@ -487,6 +494,7 @@ $jumbotron-color: inherit !default;
487 $jumbotron-bg: $gray-lighter !default; 494 $jumbotron-bg: $gray-lighter !default;
488 $jumbotron-heading-color: inherit !default; 495 $jumbotron-heading-color: inherit !default;
489 $jumbotron-font-size: ceil(($font-size-base * 1.5)) !default; 496 $jumbotron-font-size: ceil(($font-size-base * 1.5)) !default;
  497 +$jumbotron-heading-font-size: ceil(($font-size-base * 4.5)) !default;
490 498
491 499
492 //== Form states and alerts 500 //== Form states and alerts
plugins/responsive/public/bootstrap/mixins/_background-variant.scss
@@ -5,7 +5,8 @@ @@ -5,7 +5,8 @@
5 #{$parent} { 5 #{$parent} {
6 background-color: $color; 6 background-color: $color;
7 } 7 }
8 - a#{$parent}:hover { 8 + a#{$parent}:hover,
  9 + a#{$parent}:focus {
9 background-color: darken($color, 10%); 10 background-color: darken($color, 10%);
10 } 11 }
11 } 12 }
plugins/responsive/public/bootstrap/mixins/_buttons.scss
@@ -8,15 +8,31 @@ @@ -8,15 +8,31 @@
8 background-color: $background; 8 background-color: $background;
9 border-color: $border; 9 border-color: $border;
10 10
11 - &:hover,  
12 &:focus, 11 &:focus,
13 - &.focus, 12 + &.focus {
  13 + color: $color;
  14 + background-color: darken($background, 10%);
  15 + border-color: darken($border, 25%);
  16 + }
  17 + &:hover {
  18 + color: $color;
  19 + background-color: darken($background, 10%);
  20 + border-color: darken($border, 12%);
  21 + }
14 &:active, 22 &:active,
15 &.active, 23 &.active,
16 .open > &.dropdown-toggle { 24 .open > &.dropdown-toggle {
17 color: $color; 25 color: $color;
18 background-color: darken($background, 10%); 26 background-color: darken($background, 10%);
19 border-color: darken($border, 12%); 27 border-color: darken($border, 12%);
  28 +
  29 + &:hover,
  30 + &:focus,
  31 + &.focus {
  32 + color: $color;
  33 + background-color: darken($background, 17%);
  34 + border-color: darken($border, 25%);
  35 + }
20 } 36 }
21 &:active, 37 &:active,
22 &.active, 38 &.active,
plugins/responsive/public/bootstrap/mixins/_grid-framework.scss
@@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
13 // Prevent columns from collapsing when empty 13 // Prevent columns from collapsing when empty
14 min-height: 1px; 14 min-height: 1px;
15 // Inner gutter via padding 15 // Inner gutter via padding
16 - padding-left: ($grid-gutter-width / 2);  
17 - padding-right: ($grid-gutter-width / 2); 16 + padding-left: ceil(($grid-gutter-width / 2));
  17 + padding-right: floor(($grid-gutter-width / 2));
18 } 18 }
19 } 19 }
20 20
plugins/responsive/public/bootstrap/mixins/_grid.scss
@@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
13 13
14 // Creates a wrapper for a series of columns 14 // Creates a wrapper for a series of columns
15 @mixin make-row($gutter: $grid-gutter-width) { 15 @mixin make-row($gutter: $grid-gutter-width) {
16 - margin-left: ($gutter / -2);  
17 - margin-right: ($gutter / -2); 16 + margin-left: ceil(($gutter / -2));
  17 + margin-right: floor(($gutter / -2));
18 @include clearfix; 18 @include clearfix;
19 } 19 }
20 20
plugins/responsive/public/bootstrap/mixins/_hide-text.scss
1 // CSS image replacement 1 // CSS image replacement
2 // 2 //
3 -// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for 3 +// Heads up! v3 launched with only `.hide-text()`, but per our pattern for
4 // mixins being reused as classes with the same name, this doesn't hold up. As 4 // mixins being reused as classes with the same name, this doesn't hold up. As
5 // of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. 5 // of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.
6 // 6 //
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 8
9 // Deprecated as of v3.0.1 (will be removed in v4) 9 // Deprecated as of v3.0.1 (will be removed in v4)
10 @mixin hide-text() { 10 @mixin hide-text() {
11 - font: #{0/0} a; 11 + font: 0/0 a;
12 color: transparent; 12 color: transparent;
13 text-shadow: none; 13 text-shadow: none;
14 background-color: transparent; 14 background-color: transparent;
plugins/responsive/public/bootstrap/mixins/_list-group.scss
@@ -5,10 +5,11 @@ @@ -5,10 +5,11 @@
5 color: $color; 5 color: $color;
6 background-color: $background; 6 background-color: $background;
7 7
8 - // [converter] extracted a& to a.list-group-item-#{$state} 8 + // [converter] extracted a&, button& to a.list-group-item-#{$state}, button.list-group-item-#{$state}
9 } 9 }
10 10
11 - a.list-group-item-#{$state} { 11 + a.list-group-item-#{$state},
  12 + button.list-group-item-#{$state} {
12 color: $color; 13 color: $color;
13 14
14 .list-group-item-heading { 15 .list-group-item-heading {
plugins/responsive/public/bootstrap/mixins/_opacity.scss
@@ -4,5 +4,5 @@ @@ -4,5 +4,5 @@
4 opacity: $opacity; 4 opacity: $opacity;
5 // IE8 filter 5 // IE8 filter
6 $opacity-ie: ($opacity * 100); 6 $opacity-ie: ($opacity * 100);
7 - filter: #{alpha(opacity=$opacity-ie)}; 7 + filter: alpha(opacity=$opacity-ie);
8 } 8 }
plugins/responsive/public/bootstrap/mixins/_pagination.scss
1 // Pagination 1 // Pagination
2 2
3 -@mixin pagination-size($padding-vertical, $padding-horizontal, $font-size, $border-radius) { 3 +@mixin pagination-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {
4 > li { 4 > li {
5 > a, 5 > a,
6 > span { 6 > span {
7 padding: $padding-vertical $padding-horizontal; 7 padding: $padding-vertical $padding-horizontal;
8 font-size: $font-size; 8 font-size: $font-size;
  9 + line-height: $line-height;
9 } 10 }
10 &:first-child { 11 &:first-child {
11 > a, 12 > a,
plugins/responsive/public/bootstrap/mixins/_reset-text.scss 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +@mixin reset-text() {
  2 + font-family: $font-family-base;
  3 + // We deliberately do NOT reset font-size.
  4 + font-style: normal;
  5 + font-weight: normal;
  6 + letter-spacing: normal;
  7 + line-break: auto;
  8 + line-height: $line-height-base;
  9 + text-align: left; // Fallback for where `start` is not supported
  10 + text-align: start;
  11 + text-decoration: none;
  12 + text-shadow: none;
  13 + text-transform: none;
  14 + white-space: normal;
  15 + word-break: normal;
  16 + word-spacing: normal;
  17 + word-wrap: normal;
  18 +}
plugins/responsive/public/bootstrap/mixins/_responsive-visibility.scss
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 #{$parent} { 7 #{$parent} {
8 display: block !important; 8 display: block !important;
9 } 9 }
10 - table#{$parent} { display: table; } 10 + table#{$parent} { display: table !important; }
11 tr#{$parent} { display: table-row !important; } 11 tr#{$parent} { display: table-row !important; }
12 th#{$parent}, 12 th#{$parent},
13 td#{$parent} { display: table-cell !important; } 13 td#{$parent} { display: table-cell !important; }
plugins/responsive/public/bootstrap/mixins/_text-emphasis.scss
@@ -5,7 +5,8 @@ @@ -5,7 +5,8 @@
5 #{$parent} { 5 #{$parent} {
6 color: $color; 6 color: $color;
7 } 7 }
8 - a#{$parent}:hover { 8 + a#{$parent}:hover,
  9 + a#{$parent}:focus {
9 color: darken($color, 10%); 10 color: darken($color, 10%);
10 } 11 }
11 } 12 }
plugins/responsive/public/bootstrap/mixins/_vendor-prefixes.scss
@@ -102,7 +102,7 @@ @@ -102,7 +102,7 @@
102 // Firefox 102 // Firefox
103 &::-moz-placeholder { 103 &::-moz-placeholder {
104 color: $color; 104 color: $color;
105 - opacity: 1; // See https://github.com/twbs/bootstrap/pull/11526 105 + opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526
106 } 106 }
107 &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+ 107 &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+
108 &::-webkit-input-placeholder { color: $color; } // Safari and Chrome 108 &::-webkit-input-placeholder { color: $color; } // Safari and Chrome
plugins/responsive/public/javascripts/bootstrap.js
1 /*! 1 /*!
2 - * Bootstrap v3.2.0 (http://getbootstrap.com)  
3 - * Copyright 2011-2014 Twitter, Inc.  
4 - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 2 + * Bootstrap v3.3.5 (http://getbootstrap.com)
  3 + * Copyright 2011-2015 Twitter, Inc.
  4 + * Licensed under the MIT license
5 */ 5 */
6 6
7 -if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } 7 +if (typeof jQuery === 'undefined') {
  8 + throw new Error('Bootstrap\'s JavaScript requires jQuery')
  9 +}
  10 +
  11 ++function ($) {
  12 + 'use strict';
  13 + var version = $.fn.jquery.split(' ')[0].split('.')
  14 + if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
  15 + throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
  16 + }
  17 +}(jQuery);
8 18
9 /* ======================================================================== 19 /* ========================================================================
10 - * Bootstrap: transition.js v3.2.0 20 + * Bootstrap: transition.js v3.3.5
11 * http://getbootstrap.com/javascript/#transitions 21 * http://getbootstrap.com/javascript/#transitions
12 * ======================================================================== 22 * ========================================================================
13 - * Copyright 2011-2014 Twitter, Inc. 23 + * Copyright 2011-2015 Twitter, Inc.
14 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 24 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15 * ======================================================================== */ 25 * ======================================================================== */
16 26
@@ -67,10 +77,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -67,10 +77,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
67 }(jQuery); 77 }(jQuery);
68 78
69 /* ======================================================================== 79 /* ========================================================================
70 - * Bootstrap: alert.js v3.2.0 80 + * Bootstrap: alert.js v3.3.5
71 * http://getbootstrap.com/javascript/#alerts 81 * http://getbootstrap.com/javascript/#alerts
72 * ======================================================================== 82 * ========================================================================
73 - * Copyright 2011-2014 Twitter, Inc. 83 + * Copyright 2011-2015 Twitter, Inc.
74 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 84 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
75 * ======================================================================== */ 85 * ======================================================================== */
76 86
@@ -86,7 +96,9 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -86,7 +96,9 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
86 $(el).on('click', dismiss, this.close) 96 $(el).on('click', dismiss, this.close)
87 } 97 }
88 98
89 - Alert.VERSION = '3.2.0' 99 + Alert.VERSION = '3.3.5'
  100 +
  101 + Alert.TRANSITION_DURATION = 150
90 102
91 Alert.prototype.close = function (e) { 103 Alert.prototype.close = function (e) {
92 var $this = $(this) 104 var $this = $(this)
@@ -102,7 +114,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -102,7 +114,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
102 if (e) e.preventDefault() 114 if (e) e.preventDefault()
103 115
104 if (!$parent.length) { 116 if (!$parent.length) {
105 - $parent = $this.hasClass('alert') ? $this : $this.parent() 117 + $parent = $this.closest('.alert')
106 } 118 }
107 119
108 $parent.trigger(e = $.Event('close.bs.alert')) 120 $parent.trigger(e = $.Event('close.bs.alert'))
@@ -119,7 +131,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -119,7 +131,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
119 $.support.transition && $parent.hasClass('fade') ? 131 $.support.transition && $parent.hasClass('fade') ?
120 $parent 132 $parent
121 .one('bsTransitionEnd', removeElement) 133 .one('bsTransitionEnd', removeElement)
122 - .emulateTransitionEnd(150) : 134 + .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
123 removeElement() 135 removeElement()
124 } 136 }
125 137
@@ -160,10 +172,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -160,10 +172,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
160 }(jQuery); 172 }(jQuery);
161 173
162 /* ======================================================================== 174 /* ========================================================================
163 - * Bootstrap: button.js v3.2.0 175 + * Bootstrap: button.js v3.3.5
164 * http://getbootstrap.com/javascript/#buttons 176 * http://getbootstrap.com/javascript/#buttons
165 * ======================================================================== 177 * ========================================================================
166 - * Copyright 2011-2014 Twitter, Inc. 178 + * Copyright 2011-2015 Twitter, Inc.
167 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 179 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
168 * ======================================================================== */ 180 * ======================================================================== */
169 181
@@ -180,7 +192,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -180,7 +192,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
180 this.isLoading = false 192 this.isLoading = false
181 } 193 }
182 194
183 - Button.VERSION = '3.2.0' 195 + Button.VERSION = '3.3.5'
184 196
185 Button.DEFAULTS = { 197 Button.DEFAULTS = {
186 loadingText: 'loading...' 198 loadingText: 'loading...'
@@ -192,14 +204,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -192,14 +204,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
192 var val = $el.is('input') ? 'val' : 'html' 204 var val = $el.is('input') ? 'val' : 'html'
193 var data = $el.data() 205 var data = $el.data()
194 206
195 - state = state + 'Text' 207 + state += 'Text'
196 208
197 if (data.resetText == null) $el.data('resetText', $el[val]()) 209 if (data.resetText == null) $el.data('resetText', $el[val]())
198 210
199 - $el[val](data[state] == null ? this.options[state] : data[state])  
200 -  
201 // push to event loop to allow forms to submit 211 // push to event loop to allow forms to submit
202 setTimeout($.proxy(function () { 212 setTimeout($.proxy(function () {
  213 + $el[val](data[state] == null ? this.options[state] : data[state])
  214 +
203 if (state == 'loadingText') { 215 if (state == 'loadingText') {
204 this.isLoading = true 216 this.isLoading = true
205 $el.addClass(d).attr(d, d) 217 $el.addClass(d).attr(d, d)
@@ -217,13 +229,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -217,13 +229,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
217 if ($parent.length) { 229 if ($parent.length) {
218 var $input = this.$element.find('input') 230 var $input = this.$element.find('input')
219 if ($input.prop('type') == 'radio') { 231 if ($input.prop('type') == 'radio') {
220 - if ($input.prop('checked') && this.$element.hasClass('active')) changed = false  
221 - else $parent.find('.active').removeClass('active') 232 + if ($input.prop('checked')) changed = false
  233 + $parent.find('.active').removeClass('active')
  234 + this.$element.addClass('active')
  235 + } else if ($input.prop('type') == 'checkbox') {
  236 + if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
  237 + this.$element.toggleClass('active')
222 } 238 }
223 - if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') 239 + $input.prop('checked', this.$element.hasClass('active'))
  240 + if (changed) $input.trigger('change')
  241 + } else {
  242 + this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
  243 + this.$element.toggleClass('active')
224 } 244 }
225 -  
226 - if (changed) this.$element.toggleClass('active')  
227 } 245 }
228 246
229 247
@@ -261,20 +279,24 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -261,20 +279,24 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
261 // BUTTON DATA-API 279 // BUTTON DATA-API
262 // =============== 280 // ===============
263 281
264 - $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {  
265 - var $btn = $(e.target)  
266 - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')  
267 - Plugin.call($btn, 'toggle')  
268 - e.preventDefault()  
269 - }) 282 + $(document)
  283 + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
  284 + var $btn = $(e.target)
  285 + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
  286 + Plugin.call($btn, 'toggle')
  287 + if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
  288 + })
  289 + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
  290 + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
  291 + })
270 292
271 }(jQuery); 293 }(jQuery);
272 294
273 /* ======================================================================== 295 /* ========================================================================
274 - * Bootstrap: carousel.js v3.2.0 296 + * Bootstrap: carousel.js v3.3.5
275 * http://getbootstrap.com/javascript/#carousel 297 * http://getbootstrap.com/javascript/#carousel
276 * ======================================================================== 298 * ========================================================================
277 - * Copyright 2011-2014 Twitter, Inc. 299 + * Copyright 2011-2015 Twitter, Inc.
278 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 300 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
279 * ======================================================================== */ 301 * ======================================================================== */
280 302
@@ -286,29 +308,35 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -286,29 +308,35 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
286 // ========================= 308 // =========================
287 309
288 var Carousel = function (element, options) { 310 var Carousel = function (element, options) {
289 - this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this)) 311 + this.$element = $(element)
290 this.$indicators = this.$element.find('.carousel-indicators') 312 this.$indicators = this.$element.find('.carousel-indicators')
291 this.options = options 313 this.options = options
292 - this.paused =  
293 - this.sliding =  
294 - this.interval =  
295 - this.$active = 314 + this.paused = null
  315 + this.sliding = null
  316 + this.interval = null
  317 + this.$active = null
296 this.$items = null 318 this.$items = null
297 319
298 - this.options.pause == 'hover' && this.$element 320 + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
  321 +
  322 + this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
299 .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) 323 .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
300 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) 324 .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
301 } 325 }
302 326
303 - Carousel.VERSION = '3.2.0' 327 + Carousel.VERSION = '3.3.5'
  328 +
  329 + Carousel.TRANSITION_DURATION = 600
304 330
305 Carousel.DEFAULTS = { 331 Carousel.DEFAULTS = {
306 interval: 5000, 332 interval: 5000,
307 pause: 'hover', 333 pause: 'hover',
308 - wrap: true 334 + wrap: true,
  335 + keyboard: true
309 } 336 }
310 337
311 Carousel.prototype.keydown = function (e) { 338 Carousel.prototype.keydown = function (e) {
  339 + if (/input|textarea/i.test(e.target.tagName)) return
312 switch (e.which) { 340 switch (e.which) {
313 case 37: this.prev(); break 341 case 37: this.prev(); break
314 case 39: this.next(); break 342 case 39: this.next(); break
@@ -335,6 +363,16 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -335,6 +363,16 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
335 return this.$items.index(item || this.$active) 363 return this.$items.index(item || this.$active)
336 } 364 }
337 365
  366 + Carousel.prototype.getItemForDirection = function (direction, active) {
  367 + var activeIndex = this.getItemIndex(active)
  368 + var willWrap = (direction == 'prev' && activeIndex === 0)
  369 + || (direction == 'next' && activeIndex == (this.$items.length - 1))
  370 + if (willWrap && !this.options.wrap) return active
  371 + var delta = direction == 'prev' ? -1 : 1
  372 + var itemIndex = (activeIndex + delta) % this.$items.length
  373 + return this.$items.eq(itemIndex)
  374 + }
  375 +
338 Carousel.prototype.to = function (pos) { 376 Carousel.prototype.to = function (pos) {
339 var that = this 377 var that = this
340 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) 378 var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
@@ -344,7 +382,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -344,7 +382,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
344 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" 382 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
345 if (activeIndex == pos) return this.pause().cycle() 383 if (activeIndex == pos) return this.pause().cycle()
346 384
347 - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) 385 + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
348 } 386 }
349 387
350 Carousel.prototype.pause = function (e) { 388 Carousel.prototype.pause = function (e) {
@@ -372,17 +410,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -372,17 +410,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
372 410
373 Carousel.prototype.slide = function (type, next) { 411 Carousel.prototype.slide = function (type, next) {
374 var $active = this.$element.find('.item.active') 412 var $active = this.$element.find('.item.active')
375 - var $next = next || $active[type]() 413 + var $next = next || this.getItemForDirection(type, $active)
376 var isCycling = this.interval 414 var isCycling = this.interval
377 var direction = type == 'next' ? 'left' : 'right' 415 var direction = type == 'next' ? 'left' : 'right'
378 - var fallback = type == 'next' ? 'first' : 'last'  
379 var that = this 416 var that = this
380 417
381 - if (!$next.length) {  
382 - if (!this.options.wrap) return  
383 - $next = this.$element.find('.item')[fallback]()  
384 - }  
385 -  
386 if ($next.hasClass('active')) return (this.sliding = false) 418 if ($next.hasClass('active')) return (this.sliding = false)
387 419
388 var relatedTarget = $next[0] 420 var relatedTarget = $next[0]
@@ -418,7 +450,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -418,7 +450,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
418 that.$element.trigger(slidEvent) 450 that.$element.trigger(slidEvent)
419 }, 0) 451 }, 0)
420 }) 452 })
421 - .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) 453 + .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
422 } else { 454 } else {
423 $active.removeClass('active') 455 $active.removeClass('active')
424 $next.addClass('active') 456 $next.addClass('active')
@@ -467,7 +499,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -467,7 +499,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
467 // CAROUSEL DATA-API 499 // CAROUSEL DATA-API
468 // ================= 500 // =================
469 501
470 - $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { 502 + var clickHandler = function (e) {
471 var href 503 var href
472 var $this = $(this) 504 var $this = $(this)
473 var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 505 var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
@@ -483,7 +515,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -483,7 +515,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
483 } 515 }
484 516
485 e.preventDefault() 517 e.preventDefault()
486 - }) 518 + }
  519 +
  520 + $(document)
  521 + .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
  522 + .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
487 523
488 $(window).on('load', function () { 524 $(window).on('load', function () {
489 $('[data-ride="carousel"]').each(function () { 525 $('[data-ride="carousel"]').each(function () {
@@ -495,10 +531,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -495,10 +531,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
495 }(jQuery); 531 }(jQuery);
496 532
497 /* ======================================================================== 533 /* ========================================================================
498 - * Bootstrap: collapse.js v3.2.0 534 + * Bootstrap: collapse.js v3.3.5
499 * http://getbootstrap.com/javascript/#collapse 535 * http://getbootstrap.com/javascript/#collapse
500 * ======================================================================== 536 * ========================================================================
501 - * Copyright 2011-2014 Twitter, Inc. 537 + * Copyright 2011-2015 Twitter, Inc.
502 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 538 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
503 * ======================================================================== */ 539 * ======================================================================== */
504 540
@@ -512,13 +548,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -512,13 +548,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
512 var Collapse = function (element, options) { 548 var Collapse = function (element, options) {
513 this.$element = $(element) 549 this.$element = $(element)
514 this.options = $.extend({}, Collapse.DEFAULTS, options) 550 this.options = $.extend({}, Collapse.DEFAULTS, options)
  551 + this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
  552 + '[data-toggle="collapse"][data-target="#' + element.id + '"]')
515 this.transitioning = null 553 this.transitioning = null
516 554
517 - if (this.options.parent) this.$parent = $(this.options.parent) 555 + if (this.options.parent) {
  556 + this.$parent = this.getParent()
  557 + } else {
  558 + this.addAriaAndCollapsedClass(this.$element, this.$trigger)
  559 + }
  560 +
518 if (this.options.toggle) this.toggle() 561 if (this.options.toggle) this.toggle()
519 } 562 }
520 563
521 - Collapse.VERSION = '3.2.0' 564 + Collapse.VERSION = '3.3.5'
  565 +
  566 + Collapse.TRANSITION_DURATION = 350
522 567
523 Collapse.DEFAULTS = { 568 Collapse.DEFAULTS = {
524 toggle: true 569 toggle: true
@@ -532,17 +577,21 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -532,17 +577,21 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
532 Collapse.prototype.show = function () { 577 Collapse.prototype.show = function () {
533 if (this.transitioning || this.$element.hasClass('in')) return 578 if (this.transitioning || this.$element.hasClass('in')) return
534 579
  580 + var activesData
  581 + var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
  582 +
  583 + if (actives && actives.length) {
  584 + activesData = actives.data('bs.collapse')
  585 + if (activesData && activesData.transitioning) return
  586 + }
  587 +
535 var startEvent = $.Event('show.bs.collapse') 588 var startEvent = $.Event('show.bs.collapse')
536 this.$element.trigger(startEvent) 589 this.$element.trigger(startEvent)
537 if (startEvent.isDefaultPrevented()) return 590 if (startEvent.isDefaultPrevented()) return
538 591
539 - var actives = this.$parent && this.$parent.find('> .panel > .in')  
540 -  
541 if (actives && actives.length) { 592 if (actives && actives.length) {
542 - var hasData = actives.data('bs.collapse')  
543 - if (hasData && hasData.transitioning) return  
544 Plugin.call(actives, 'hide') 593 Plugin.call(actives, 'hide')
545 - hasData || actives.data('bs.collapse', null) 594 + activesData || actives.data('bs.collapse', null)
546 } 595 }
547 596
548 var dimension = this.dimension() 597 var dimension = this.dimension()
@@ -550,6 +599,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -550,6 +599,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
550 this.$element 599 this.$element
551 .removeClass('collapse') 600 .removeClass('collapse')
552 .addClass('collapsing')[dimension](0) 601 .addClass('collapsing')[dimension](0)
  602 + .attr('aria-expanded', true)
  603 +
  604 + this.$trigger
  605 + .removeClass('collapsed')
  606 + .attr('aria-expanded', true)
553 607
554 this.transitioning = 1 608 this.transitioning = 1
555 609
@@ -568,7 +622,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -568,7 +622,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
568 622
569 this.$element 623 this.$element
570 .one('bsTransitionEnd', $.proxy(complete, this)) 624 .one('bsTransitionEnd', $.proxy(complete, this))
571 - .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 625 + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
572 } 626 }
573 627
574 Collapse.prototype.hide = function () { 628 Collapse.prototype.hide = function () {
@@ -584,17 +638,21 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -584,17 +638,21 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
584 638
585 this.$element 639 this.$element
586 .addClass('collapsing') 640 .addClass('collapsing')
587 - .removeClass('collapse')  
588 - .removeClass('in') 641 + .removeClass('collapse in')
  642 + .attr('aria-expanded', false)
  643 +
  644 + this.$trigger
  645 + .addClass('collapsed')
  646 + .attr('aria-expanded', false)
589 647
590 this.transitioning = 1 648 this.transitioning = 1
591 649
592 var complete = function () { 650 var complete = function () {
593 this.transitioning = 0 651 this.transitioning = 0
594 this.$element 652 this.$element
595 - .trigger('hidden.bs.collapse')  
596 .removeClass('collapsing') 653 .removeClass('collapsing')
597 .addClass('collapse') 654 .addClass('collapse')
  655 + .trigger('hidden.bs.collapse')
598 } 656 }
599 657
600 if (!$.support.transition) return complete.call(this) 658 if (!$.support.transition) return complete.call(this)
@@ -602,13 +660,40 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -602,13 +660,40 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
602 this.$element 660 this.$element
603 [dimension](0) 661 [dimension](0)
604 .one('bsTransitionEnd', $.proxy(complete, this)) 662 .one('bsTransitionEnd', $.proxy(complete, this))
605 - .emulateTransitionEnd(350) 663 + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
606 } 664 }
607 665
608 Collapse.prototype.toggle = function () { 666 Collapse.prototype.toggle = function () {
609 this[this.$element.hasClass('in') ? 'hide' : 'show']() 667 this[this.$element.hasClass('in') ? 'hide' : 'show']()
610 } 668 }
611 669
  670 + Collapse.prototype.getParent = function () {
  671 + return $(this.options.parent)
  672 + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
  673 + .each($.proxy(function (i, element) {
  674 + var $element = $(element)
  675 + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
  676 + }, this))
  677 + .end()
  678 + }
  679 +
  680 + Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
  681 + var isOpen = $element.hasClass('in')
  682 +
  683 + $element.attr('aria-expanded', isOpen)
  684 + $trigger
  685 + .toggleClass('collapsed', !isOpen)
  686 + .attr('aria-expanded', isOpen)
  687 + }
  688 +
  689 + function getTargetFromTrigger($trigger) {
  690 + var href
  691 + var target = $trigger.attr('data-target')
  692 + || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
  693 +
  694 + return $(target)
  695 + }
  696 +
612 697
613 // COLLAPSE PLUGIN DEFINITION 698 // COLLAPSE PLUGIN DEFINITION
614 // ========================== 699 // ==========================
@@ -619,7 +704,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -619,7 +704,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
619 var data = $this.data('bs.collapse') 704 var data = $this.data('bs.collapse')
620 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 705 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
621 706
622 - if (!data && options.toggle && option == 'show') option = !option 707 + if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
623 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 708 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
624 if (typeof option == 'string') data[option]() 709 if (typeof option == 'string') data[option]()
625 }) 710 })
@@ -644,21 +729,13 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -644,21 +729,13 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
644 // ================= 729 // =================
645 730
646 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 731 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
647 - var href  
648 var $this = $(this) 732 var $this = $(this)
649 - var target = $this.attr('data-target')  
650 - || e.preventDefault()  
651 - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7  
652 - var $target = $(target) 733 +
  734 + if (!$this.attr('data-target')) e.preventDefault()
  735 +
  736 + var $target = getTargetFromTrigger($this)
653 var data = $target.data('bs.collapse') 737 var data = $target.data('bs.collapse')
654 var option = data ? 'toggle' : $this.data() 738 var option = data ? 'toggle' : $this.data()
655 - var parent = $this.attr('data-parent')  
656 - var $parent = parent && $(parent)  
657 -  
658 - if (!data || !data.transitioning) {  
659 - if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')  
660 - $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')  
661 - }  
662 739
663 Plugin.call($target, option) 740 Plugin.call($target, option)
664 }) 741 })
@@ -666,10 +743,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -666,10 +743,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
666 }(jQuery); 743 }(jQuery);
667 744
668 /* ======================================================================== 745 /* ========================================================================
669 - * Bootstrap: dropdown.js v3.2.0 746 + * Bootstrap: dropdown.js v3.3.5
670 * http://getbootstrap.com/javascript/#dropdowns 747 * http://getbootstrap.com/javascript/#dropdowns
671 * ======================================================================== 748 * ========================================================================
672 - * Copyright 2011-2014 Twitter, Inc. 749 + * Copyright 2011-2015 Twitter, Inc.
673 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 750 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
674 * ======================================================================== */ 751 * ======================================================================== */
675 752
@@ -686,7 +763,41 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -686,7 +763,41 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
686 $(element).on('click.bs.dropdown', this.toggle) 763 $(element).on('click.bs.dropdown', this.toggle)
687 } 764 }
688 765
689 - Dropdown.VERSION = '3.2.0' 766 + Dropdown.VERSION = '3.3.5'
  767 +
  768 + function getParent($this) {
  769 + var selector = $this.attr('data-target')
  770 +
  771 + if (!selector) {
  772 + selector = $this.attr('href')
  773 + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  774 + }
  775 +
  776 + var $parent = selector && $(selector)
  777 +
  778 + return $parent && $parent.length ? $parent : $this.parent()
  779 + }
  780 +
  781 + function clearMenus(e) {
  782 + if (e && e.which === 3) return
  783 + $(backdrop).remove()
  784 + $(toggle).each(function () {
  785 + var $this = $(this)
  786 + var $parent = getParent($this)
  787 + var relatedTarget = { relatedTarget: this }
  788 +
  789 + if (!$parent.hasClass('open')) return
  790 +
  791 + if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
  792 +
  793 + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
  794 +
  795 + if (e.isDefaultPrevented()) return
  796 +
  797 + $this.attr('aria-expanded', 'false')
  798 + $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
  799 + })
  800 + }
690 801
691 Dropdown.prototype.toggle = function (e) { 802 Dropdown.prototype.toggle = function (e) {
692 var $this = $(this) 803 var $this = $(this)
@@ -701,7 +812,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -701,7 +812,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
701 if (!isActive) { 812 if (!isActive) {
702 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 813 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
703 // if mobile we use a backdrop because click events don't delegate 814 // if mobile we use a backdrop because click events don't delegate
704 - $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) 815 + $(document.createElement('div'))
  816 + .addClass('dropdown-backdrop')
  817 + .insertAfter($(this))
  818 + .on('click', clearMenus)
705 } 819 }
706 820
707 var relatedTarget = { relatedTarget: this } 821 var relatedTarget = { relatedTarget: this }
@@ -709,7 +823,9 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -709,7 +823,9 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
709 823
710 if (e.isDefaultPrevented()) return 824 if (e.isDefaultPrevented()) return
711 825
712 - $this.trigger('focus') 826 + $this
  827 + .trigger('focus')
  828 + .attr('aria-expanded', 'true')
713 829
714 $parent 830 $parent
715 .toggleClass('open') 831 .toggleClass('open')
@@ -720,7 +836,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -720,7 +836,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
720 } 836 }
721 837
722 Dropdown.prototype.keydown = function (e) { 838 Dropdown.prototype.keydown = function (e) {
723 - if (!/(38|40|27)/.test(e.keyCode)) return 839 + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
724 840
725 var $this = $(this) 841 var $this = $(this)
726 842
@@ -732,51 +848,25 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -732,51 +848,25 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
732 var $parent = getParent($this) 848 var $parent = getParent($this)
733 var isActive = $parent.hasClass('open') 849 var isActive = $parent.hasClass('open')
734 850
735 - if (!isActive || (isActive && e.keyCode == 27)) { 851 + if (!isActive && e.which != 27 || isActive && e.which == 27) {
736 if (e.which == 27) $parent.find(toggle).trigger('focus') 852 if (e.which == 27) $parent.find(toggle).trigger('focus')
737 return $this.trigger('click') 853 return $this.trigger('click')
738 } 854 }
739 855
740 - var desc = ' li:not(.divider):visible a'  
741 - var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc) 856 + var desc = ' li:not(.disabled):visible a'
  857 + var $items = $parent.find('.dropdown-menu' + desc)
742 858
743 if (!$items.length) return 859 if (!$items.length) return
744 860
745 - var index = $items.index($items.filter(':focus')) 861 + var index = $items.index(e.target)
746 862
747 - if (e.keyCode == 38 && index > 0) index-- // up  
748 - if (e.keyCode == 40 && index < $items.length - 1) index++ // down  
749 - if (!~index) index = 0 863 + if (e.which == 38 && index > 0) index-- // up
  864 + if (e.which == 40 && index < $items.length - 1) index++ // down
  865 + if (!~index) index = 0
750 866
751 $items.eq(index).trigger('focus') 867 $items.eq(index).trigger('focus')
752 } 868 }
753 869
754 - function clearMenus(e) {  
755 - if (e && e.which === 3) return  
756 - $(backdrop).remove()  
757 - $(toggle).each(function () {  
758 - var $parent = getParent($(this))  
759 - var relatedTarget = { relatedTarget: this }  
760 - if (!$parent.hasClass('open')) return  
761 - $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))  
762 - if (e.isDefaultPrevented()) return  
763 - $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)  
764 - })  
765 - }  
766 -  
767 - function getParent($this) {  
768 - var selector = $this.attr('data-target')  
769 -  
770 - if (!selector) {  
771 - selector = $this.attr('href')  
772 - selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7  
773 - }  
774 -  
775 - var $parent = selector && $(selector)  
776 -  
777 - return $parent && $parent.length ? $parent : $this.parent()  
778 - }  
779 -  
780 870
781 // DROPDOWN PLUGIN DEFINITION 871 // DROPDOWN PLUGIN DEFINITION
782 // ========================== 872 // ==========================
@@ -813,15 +903,16 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -813,15 +903,16 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
813 .on('click.bs.dropdown.data-api', clearMenus) 903 .on('click.bs.dropdown.data-api', clearMenus)
814 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 904 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
815 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) 905 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
816 - .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown) 906 + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
  907 + .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
817 908
818 }(jQuery); 909 }(jQuery);
819 910
820 /* ======================================================================== 911 /* ========================================================================
821 - * Bootstrap: modal.js v3.2.0 912 + * Bootstrap: modal.js v3.3.5
822 * http://getbootstrap.com/javascript/#modals 913 * http://getbootstrap.com/javascript/#modals
823 * ======================================================================== 914 * ========================================================================
824 - * Copyright 2011-2014 Twitter, Inc. 915 + * Copyright 2011-2015 Twitter, Inc.
825 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 916 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
826 * ======================================================================== */ 917 * ======================================================================== */
827 918
@@ -833,12 +924,15 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -833,12 +924,15 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
833 // ====================== 924 // ======================
834 925
835 var Modal = function (element, options) { 926 var Modal = function (element, options) {
836 - this.options = options  
837 - this.$body = $(document.body)  
838 - this.$element = $(element)  
839 - this.$backdrop =  
840 - this.isShown = null  
841 - this.scrollbarWidth = 0 927 + this.options = options
  928 + this.$body = $(document.body)
  929 + this.$element = $(element)
  930 + this.$dialog = this.$element.find('.modal-dialog')
  931 + this.$backdrop = null
  932 + this.isShown = null
  933 + this.originalBodyPad = null
  934 + this.scrollbarWidth = 0
  935 + this.ignoreBackdropClick = false
842 936
843 if (this.options.remote) { 937 if (this.options.remote) {
844 this.$element 938 this.$element
@@ -849,7 +943,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -849,7 +943,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
849 } 943 }
850 } 944 }
851 945
852 - Modal.VERSION = '3.2.0' 946 + Modal.VERSION = '3.3.5'
  947 +
  948 + Modal.TRANSITION_DURATION = 300
  949 + Modal.BACKDROP_TRANSITION_DURATION = 150
853 950
854 Modal.DEFAULTS = { 951 Modal.DEFAULTS = {
855 backdrop: true, 952 backdrop: true,
@@ -872,13 +969,20 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -872,13 +969,20 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
872 this.isShown = true 969 this.isShown = true
873 970
874 this.checkScrollbar() 971 this.checkScrollbar()
  972 + this.setScrollbar()
875 this.$body.addClass('modal-open') 973 this.$body.addClass('modal-open')
876 974
877 - this.setScrollbar()  
878 this.escape() 975 this.escape()
  976 + this.resize()
879 977
880 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) 978 this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
881 979
  980 + this.$dialog.on('mousedown.dismiss.bs.modal', function () {
  981 + that.$element.one('mouseup.dismiss.bs.modal', function (e) {
  982 + if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
  983 + })
  984 + })
  985 +
882 this.backdrop(function () { 986 this.backdrop(function () {
883 var transition = $.support.transition && that.$element.hasClass('fade') 987 var transition = $.support.transition && that.$element.hasClass('fade')
884 988
@@ -890,24 +994,24 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -890,24 +994,24 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
890 .show() 994 .show()
891 .scrollTop(0) 995 .scrollTop(0)
892 996
  997 + that.adjustDialog()
  998 +
893 if (transition) { 999 if (transition) {
894 that.$element[0].offsetWidth // force reflow 1000 that.$element[0].offsetWidth // force reflow
895 } 1001 }
896 1002
897 - that.$element  
898 - .addClass('in')  
899 - .attr('aria-hidden', false) 1003 + that.$element.addClass('in')
900 1004
901 that.enforceFocus() 1005 that.enforceFocus()
902 1006
903 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) 1007 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
904 1008
905 transition ? 1009 transition ?
906 - that.$element.find('.modal-dialog') // wait for modal to slide in 1010 + that.$dialog // wait for modal to slide in
907 .one('bsTransitionEnd', function () { 1011 .one('bsTransitionEnd', function () {
908 that.$element.trigger('focus').trigger(e) 1012 that.$element.trigger('focus').trigger(e)
909 }) 1013 })
910 - .emulateTransitionEnd(300) : 1014 + .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
911 that.$element.trigger('focus').trigger(e) 1015 that.$element.trigger('focus').trigger(e)
912 }) 1016 })
913 } 1017 }
@@ -923,22 +1027,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -923,22 +1027,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
923 1027
924 this.isShown = false 1028 this.isShown = false
925 1029
926 - this.$body.removeClass('modal-open')  
927 -  
928 - this.resetScrollbar()  
929 this.escape() 1030 this.escape()
  1031 + this.resize()
930 1032
931 $(document).off('focusin.bs.modal') 1033 $(document).off('focusin.bs.modal')
932 1034
933 this.$element 1035 this.$element
934 .removeClass('in') 1036 .removeClass('in')
935 - .attr('aria-hidden', true)  
936 .off('click.dismiss.bs.modal') 1037 .off('click.dismiss.bs.modal')
  1038 + .off('mouseup.dismiss.bs.modal')
  1039 +
  1040 + this.$dialog.off('mousedown.dismiss.bs.modal')
937 1041
938 $.support.transition && this.$element.hasClass('fade') ? 1042 $.support.transition && this.$element.hasClass('fade') ?
939 this.$element 1043 this.$element
940 .one('bsTransitionEnd', $.proxy(this.hideModal, this)) 1044 .one('bsTransitionEnd', $.proxy(this.hideModal, this))
941 - .emulateTransitionEnd(300) : 1045 + .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
942 this.hideModal() 1046 this.hideModal()
943 } 1047 }
944 1048
@@ -954,11 +1058,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -954,11 +1058,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
954 1058
955 Modal.prototype.escape = function () { 1059 Modal.prototype.escape = function () {
956 if (this.isShown && this.options.keyboard) { 1060 if (this.isShown && this.options.keyboard) {
957 - this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) { 1061 + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
958 e.which == 27 && this.hide() 1062 e.which == 27 && this.hide()
959 }, this)) 1063 }, this))
960 } else if (!this.isShown) { 1064 } else if (!this.isShown) {
961 - this.$element.off('keyup.dismiss.bs.modal') 1065 + this.$element.off('keydown.dismiss.bs.modal')
  1066 + }
  1067 + }
  1068 +
  1069 + Modal.prototype.resize = function () {
  1070 + if (this.isShown) {
  1071 + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
  1072 + } else {
  1073 + $(window).off('resize.bs.modal')
962 } 1074 }
963 } 1075 }
964 1076
@@ -966,6 +1078,9 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -966,6 +1078,9 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
966 var that = this 1078 var that = this
967 this.$element.hide() 1079 this.$element.hide()
968 this.backdrop(function () { 1080 this.backdrop(function () {
  1081 + that.$body.removeClass('modal-open')
  1082 + that.resetAdjustments()
  1083 + that.resetScrollbar()
969 that.$element.trigger('hidden.bs.modal') 1084 that.$element.trigger('hidden.bs.modal')
970 }) 1085 })
971 } 1086 }
@@ -982,14 +1097,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -982,14 +1097,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
982 if (this.isShown && this.options.backdrop) { 1097 if (this.isShown && this.options.backdrop) {
983 var doAnimate = $.support.transition && animate 1098 var doAnimate = $.support.transition && animate
984 1099
985 - this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') 1100 + this.$backdrop = $(document.createElement('div'))
  1101 + .addClass('modal-backdrop ' + animate)
986 .appendTo(this.$body) 1102 .appendTo(this.$body)
987 1103
988 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { 1104 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
  1105 + if (this.ignoreBackdropClick) {
  1106 + this.ignoreBackdropClick = false
  1107 + return
  1108 + }
989 if (e.target !== e.currentTarget) return 1109 if (e.target !== e.currentTarget) return
990 this.options.backdrop == 'static' 1110 this.options.backdrop == 'static'
991 - ? this.$element[0].focus.call(this.$element[0])  
992 - : this.hide.call(this) 1111 + ? this.$element[0].focus()
  1112 + : this.hide()
993 }, this)) 1113 }, this))
994 1114
995 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow 1115 if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
@@ -1001,7 +1121,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1001,7 +1121,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1001 doAnimate ? 1121 doAnimate ?
1002 this.$backdrop 1122 this.$backdrop
1003 .one('bsTransitionEnd', callback) 1123 .one('bsTransitionEnd', callback)
1004 - .emulateTransitionEnd(150) : 1124 + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1005 callback() 1125 callback()
1006 1126
1007 } else if (!this.isShown && this.$backdrop) { 1127 } else if (!this.isShown && this.$backdrop) {
@@ -1014,7 +1134,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1014,7 +1134,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1014 $.support.transition && this.$element.hasClass('fade') ? 1134 $.support.transition && this.$element.hasClass('fade') ?
1015 this.$backdrop 1135 this.$backdrop
1016 .one('bsTransitionEnd', callbackRemove) 1136 .one('bsTransitionEnd', callbackRemove)
1017 - .emulateTransitionEnd(150) : 1137 + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1018 callbackRemove() 1138 callbackRemove()
1019 1139
1020 } else if (callback) { 1140 } else if (callback) {
@@ -1022,18 +1142,46 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1022,18 +1142,46 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1022 } 1142 }
1023 } 1143 }
1024 1144
  1145 + // these following methods are used to handle overflowing modals
  1146 +
  1147 + Modal.prototype.handleUpdate = function () {
  1148 + this.adjustDialog()
  1149 + }
  1150 +
  1151 + Modal.prototype.adjustDialog = function () {
  1152 + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
  1153 +
  1154 + this.$element.css({
  1155 + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
  1156 + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
  1157 + })
  1158 + }
  1159 +
  1160 + Modal.prototype.resetAdjustments = function () {
  1161 + this.$element.css({
  1162 + paddingLeft: '',
  1163 + paddingRight: ''
  1164 + })
  1165 + }
  1166 +
1025 Modal.prototype.checkScrollbar = function () { 1167 Modal.prototype.checkScrollbar = function () {
1026 - if (document.body.clientWidth >= window.innerWidth) return  
1027 - this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar() 1168 + var fullWindowWidth = window.innerWidth
  1169 + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
  1170 + var documentElementRect = document.documentElement.getBoundingClientRect()
  1171 + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
  1172 + }
  1173 + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
  1174 + this.scrollbarWidth = this.measureScrollbar()
1028 } 1175 }
1029 1176
1030 Modal.prototype.setScrollbar = function () { 1177 Modal.prototype.setScrollbar = function () {
1031 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) 1178 var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
1032 - if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) 1179 + this.originalBodyPad = document.body.style.paddingRight || ''
  1180 + if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1033 } 1181 }
1034 1182
1035 Modal.prototype.resetScrollbar = function () { 1183 Modal.prototype.resetScrollbar = function () {
1036 - this.$body.css('padding-right', '') 1184 + this.$body.css('padding-right', this.originalBodyPad)
1037 } 1185 }
1038 1186
1039 Modal.prototype.measureScrollbar = function () { // thx walsh 1187 Modal.prototype.measureScrollbar = function () { // thx walsh
@@ -1099,11 +1247,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1099,11 +1247,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1099 }(jQuery); 1247 }(jQuery);
1100 1248
1101 /* ======================================================================== 1249 /* ========================================================================
1102 - * Bootstrap: tooltip.js v3.2.0 1250 + * Bootstrap: tooltip.js v3.3.5
1103 * http://getbootstrap.com/javascript/#tooltip 1251 * http://getbootstrap.com/javascript/#tooltip
1104 * Inspired by the original jQuery.tipsy by Jason Frame 1252 * Inspired by the original jQuery.tipsy by Jason Frame
1105 * ======================================================================== 1253 * ========================================================================
1106 - * Copyright 2011-2014 Twitter, Inc. 1254 + * Copyright 2011-2015 Twitter, Inc.
1107 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1255 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1108 * ======================================================================== */ 1256 * ======================================================================== */
1109 1257
@@ -1115,17 +1263,20 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1115,17 +1263,20 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1115 // =============================== 1263 // ===============================
1116 1264
1117 var Tooltip = function (element, options) { 1265 var Tooltip = function (element, options) {
1118 - this.type =  
1119 - this.options =  
1120 - this.enabled =  
1121 - this.timeout =  
1122 - this.hoverState = 1266 + this.type = null
  1267 + this.options = null
  1268 + this.enabled = null
  1269 + this.timeout = null
  1270 + this.hoverState = null
1123 this.$element = null 1271 this.$element = null
  1272 + this.inState = null
1124 1273
1125 this.init('tooltip', element, options) 1274 this.init('tooltip', element, options)
1126 } 1275 }
1127 1276
1128 - Tooltip.VERSION = '3.2.0' 1277 + Tooltip.VERSION = '3.3.5'
  1278 +
  1279 + Tooltip.TRANSITION_DURATION = 150
1129 1280
1130 Tooltip.DEFAULTS = { 1281 Tooltip.DEFAULTS = {
1131 animation: true, 1282 animation: true,
@@ -1148,7 +1299,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1148,7 +1299,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1148 this.type = type 1299 this.type = type
1149 this.$element = $(element) 1300 this.$element = $(element)
1150 this.options = this.getOptions(options) 1301 this.options = this.getOptions(options)
1151 - this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 1302 + this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
  1303 + this.inState = { click: false, hover: false, focus: false }
  1304 +
  1305 + if (this.$element[0] instanceof document.constructor && !this.options.selector) {
  1306 + throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
  1307 + }
1152 1308
1153 var triggers = this.options.trigger.split(' ') 1309 var triggers = this.options.trigger.split(' ')
1154 1310
@@ -1208,6 +1364,15 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1208,6 +1364,15 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1208 $(obj.currentTarget).data('bs.' + this.type, self) 1364 $(obj.currentTarget).data('bs.' + this.type, self)
1209 } 1365 }
1210 1366
  1367 + if (obj instanceof $.Event) {
  1368 + self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
  1369 + }
  1370 +
  1371 + if (self.tip().hasClass('in') || self.hoverState == 'in') {
  1372 + self.hoverState = 'in'
  1373 + return
  1374 + }
  1375 +
1211 clearTimeout(self.timeout) 1376 clearTimeout(self.timeout)
1212 1377
1213 self.hoverState = 'in' 1378 self.hoverState = 'in'
@@ -1219,6 +1384,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1219,6 +1384,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1219 }, self.options.delay.show) 1384 }, self.options.delay.show)
1220 } 1385 }
1221 1386
  1387 + Tooltip.prototype.isInStateTrue = function () {
  1388 + for (var key in this.inState) {
  1389 + if (this.inState[key]) return true
  1390 + }
  1391 +
  1392 + return false
  1393 + }
  1394 +
1222 Tooltip.prototype.leave = function (obj) { 1395 Tooltip.prototype.leave = function (obj) {
1223 var self = obj instanceof this.constructor ? 1396 var self = obj instanceof this.constructor ?
1224 obj : $(obj.currentTarget).data('bs.' + this.type) 1397 obj : $(obj.currentTarget).data('bs.' + this.type)
@@ -1228,6 +1401,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1228,6 +1401,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1228 $(obj.currentTarget).data('bs.' + this.type, self) 1401 $(obj.currentTarget).data('bs.' + this.type, self)
1229 } 1402 }
1230 1403
  1404 + if (obj instanceof $.Event) {
  1405 + self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
  1406 + }
  1407 +
  1408 + if (self.isInStateTrue()) return
  1409 +
1231 clearTimeout(self.timeout) 1410 clearTimeout(self.timeout)
1232 1411
1233 self.hoverState = 'out' 1412 self.hoverState = 'out'
@@ -1245,7 +1424,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1245,7 +1424,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1245 if (this.hasContent() && this.enabled) { 1424 if (this.hasContent() && this.enabled) {
1246 this.$element.trigger(e) 1425 this.$element.trigger(e)
1247 1426
1248 - var inDom = $.contains(document.documentElement, this.$element[0]) 1427 + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1249 if (e.isDefaultPrevented() || !inDom) return 1428 if (e.isDefaultPrevented() || !inDom) return
1250 var that = this 1429 var that = this
1251 1430
@@ -1274,6 +1453,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1274,6 +1453,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1274 .data('bs.' + this.type, this) 1453 .data('bs.' + this.type, this)
1275 1454
1276 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) 1455 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
  1456 + this.$element.trigger('inserted.bs.' + this.type)
1277 1457
1278 var pos = this.getPosition() 1458 var pos = this.getPosition()
1279 var actualWidth = $tip[0].offsetWidth 1459 var actualWidth = $tip[0].offsetWidth
@@ -1281,13 +1461,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1281,13 +1461,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1281 1461
1282 if (autoPlace) { 1462 if (autoPlace) {
1283 var orgPlacement = placement 1463 var orgPlacement = placement
1284 - var $parent = this.$element.parent()  
1285 - var parentDim = this.getPosition($parent) 1464 + var viewportDim = this.getPosition(this.$viewport)
1286 1465
1287 - placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :  
1288 - placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :  
1289 - placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :  
1290 - placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 1466 + placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
  1467 + placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
  1468 + placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
  1469 + placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
1291 placement 1470 placement
1292 1471
1293 $tip 1472 $tip
@@ -1300,14 +1479,17 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1300,14 +1479,17 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1300 this.applyPlacement(calculatedOffset, placement) 1479 this.applyPlacement(calculatedOffset, placement)
1301 1480
1302 var complete = function () { 1481 var complete = function () {
  1482 + var prevHoverState = that.hoverState
1303 that.$element.trigger('shown.bs.' + that.type) 1483 that.$element.trigger('shown.bs.' + that.type)
1304 that.hoverState = null 1484 that.hoverState = null
  1485 +
  1486 + if (prevHoverState == 'out') that.leave(that)
1305 } 1487 }
1306 1488
1307 $.support.transition && this.$tip.hasClass('fade') ? 1489 $.support.transition && this.$tip.hasClass('fade') ?
1308 $tip 1490 $tip
1309 .one('bsTransitionEnd', complete) 1491 .one('bsTransitionEnd', complete)
1310 - .emulateTransitionEnd(150) : 1492 + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1311 complete() 1493 complete()
1312 } 1494 }
1313 } 1495 }
@@ -1325,8 +1507,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1325,8 +1507,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1325 if (isNaN(marginTop)) marginTop = 0 1507 if (isNaN(marginTop)) marginTop = 0
1326 if (isNaN(marginLeft)) marginLeft = 0 1508 if (isNaN(marginLeft)) marginLeft = 0
1327 1509
1328 - offset.top = offset.top + marginTop  
1329 - offset.left = offset.left + marginLeft 1510 + offset.top += marginTop
  1511 + offset.left += marginLeft
1330 1512
1331 // $.fn.offset doesn't round pixel values 1513 // $.fn.offset doesn't round pixel values
1332 // so we use setOffset directly with our own function B-0 1514 // so we use setOffset directly with our own function B-0
@@ -1354,16 +1536,18 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1354,16 +1536,18 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1354 if (delta.left) offset.left += delta.left 1536 if (delta.left) offset.left += delta.left
1355 else offset.top += delta.top 1537 else offset.top += delta.top
1356 1538
1357 - var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight  
1358 - var arrowPosition = delta.left ? 'left' : 'top'  
1359 - var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 1539 + var isVertical = /top|bottom/.test(placement)
  1540 + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
  1541 + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1360 1542
1361 $tip.offset(offset) 1543 $tip.offset(offset)
1362 - this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 1544 + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1363 } 1545 }
1364 1546
1365 - Tooltip.prototype.replaceArrow = function (delta, dimension, position) {  
1366 - this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 1547 + Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
  1548 + this.arrow()
  1549 + .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
  1550 + .css(isVertical ? 'top' : 'left', '')
1367 } 1551 }
1368 1552
1369 Tooltip.prototype.setContent = function () { 1553 Tooltip.prototype.setContent = function () {
@@ -1374,16 +1558,17 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1374,16 +1558,17 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1374 $tip.removeClass('fade in top bottom left right') 1558 $tip.removeClass('fade in top bottom left right')
1375 } 1559 }
1376 1560
1377 - Tooltip.prototype.hide = function () { 1561 + Tooltip.prototype.hide = function (callback) {
1378 var that = this 1562 var that = this
1379 - var $tip = this.tip() 1563 + var $tip = $(this.$tip)
1380 var e = $.Event('hide.bs.' + this.type) 1564 var e = $.Event('hide.bs.' + this.type)
1381 1565
1382 - this.$element.removeAttr('aria-describedby')  
1383 -  
1384 function complete() { 1566 function complete() {
1385 if (that.hoverState != 'in') $tip.detach() 1567 if (that.hoverState != 'in') $tip.detach()
1386 - that.$element.trigger('hidden.bs.' + that.type) 1568 + that.$element
  1569 + .removeAttr('aria-describedby')
  1570 + .trigger('hidden.bs.' + that.type)
  1571 + callback && callback()
1387 } 1572 }
1388 1573
1389 this.$element.trigger(e) 1574 this.$element.trigger(e)
@@ -1392,10 +1577,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1392,10 +1577,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1392 1577
1393 $tip.removeClass('in') 1578 $tip.removeClass('in')
1394 1579
1395 - $.support.transition && this.$tip.hasClass('fade') ? 1580 + $.support.transition && $tip.hasClass('fade') ?
1396 $tip 1581 $tip
1397 .one('bsTransitionEnd', complete) 1582 .one('bsTransitionEnd', complete)
1398 - .emulateTransitionEnd(150) : 1583 + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1399 complete() 1584 complete()
1400 1585
1401 this.hoverState = null 1586 this.hoverState = null
@@ -1405,7 +1590,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1405,7 +1590,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1405 1590
1406 Tooltip.prototype.fixTitle = function () { 1591 Tooltip.prototype.fixTitle = function () {
1407 var $e = this.$element 1592 var $e = this.$element
1408 - if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') { 1593 + if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
1409 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 1594 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1410 } 1595 }
1411 } 1596 }
@@ -1416,20 +1601,27 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1416,20 +1601,27 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1416 1601
1417 Tooltip.prototype.getPosition = function ($element) { 1602 Tooltip.prototype.getPosition = function ($element) {
1418 $element = $element || this.$element 1603 $element = $element || this.$element
  1604 +
1419 var el = $element[0] 1605 var el = $element[0]
1420 var isBody = el.tagName == 'BODY' 1606 var isBody = el.tagName == 'BODY'
1421 - return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {  
1422 - scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),  
1423 - width: isBody ? $(window).width() : $element.outerWidth(),  
1424 - height: isBody ? $(window).height() : $element.outerHeight()  
1425 - }, isBody ? { top: 0, left: 0 } : $element.offset()) 1607 +
  1608 + var elRect = el.getBoundingClientRect()
  1609 + if (elRect.width == null) {
  1610 + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
  1611 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
  1612 + }
  1613 + var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
  1614 + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
  1615 + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
  1616 +
  1617 + return $.extend({}, elRect, scroll, outerDims, elOffset)
1426 } 1618 }
1427 1619
1428 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 1620 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1429 - return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :  
1430 - placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 1621 + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
  1622 + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1431 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 1623 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1432 - /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 1624 + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1433 1625
1434 } 1626 }
1435 1627
@@ -1453,7 +1645,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1453,7 +1645,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1453 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 1645 var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1454 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 1646 if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1455 delta.left = viewportDimensions.left - leftEdgeOffset 1647 delta.left = viewportDimensions.left - leftEdgeOffset
1456 - } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 1648 + } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
1457 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 1649 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1458 } 1650 }
1459 } 1651 }
@@ -1479,21 +1671,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1479,21 +1671,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1479 } 1671 }
1480 1672
1481 Tooltip.prototype.tip = function () { 1673 Tooltip.prototype.tip = function () {
1482 - return (this.$tip = this.$tip || $(this.options.template)) 1674 + if (!this.$tip) {
  1675 + this.$tip = $(this.options.template)
  1676 + if (this.$tip.length != 1) {
  1677 + throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
  1678 + }
  1679 + }
  1680 + return this.$tip
1483 } 1681 }
1484 1682
1485 Tooltip.prototype.arrow = function () { 1683 Tooltip.prototype.arrow = function () {
1486 return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) 1684 return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1487 } 1685 }
1488 1686
1489 - Tooltip.prototype.validate = function () {  
1490 - if (!this.$element[0].parentNode) {  
1491 - this.hide()  
1492 - this.$element = null  
1493 - this.options = null  
1494 - }  
1495 - }  
1496 -  
1497 Tooltip.prototype.enable = function () { 1687 Tooltip.prototype.enable = function () {
1498 this.enabled = true 1688 this.enabled = true
1499 } 1689 }
@@ -1516,12 +1706,27 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1516,12 +1706,27 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1516 } 1706 }
1517 } 1707 }
1518 1708
1519 - self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 1709 + if (e) {
  1710 + self.inState.click = !self.inState.click
  1711 + if (self.isInStateTrue()) self.enter(self)
  1712 + else self.leave(self)
  1713 + } else {
  1714 + self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  1715 + }
1520 } 1716 }
1521 1717
1522 Tooltip.prototype.destroy = function () { 1718 Tooltip.prototype.destroy = function () {
  1719 + var that = this
1523 clearTimeout(this.timeout) 1720 clearTimeout(this.timeout)
1524 - this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 1721 + this.hide(function () {
  1722 + that.$element.off('.' + that.type).removeData('bs.' + that.type)
  1723 + if (that.$tip) {
  1724 + that.$tip.detach()
  1725 + }
  1726 + that.$tip = null
  1727 + that.$arrow = null
  1728 + that.$viewport = null
  1729 + })
1525 } 1730 }
1526 1731
1527 1732
@@ -1534,7 +1739,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1534,7 +1739,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1534 var data = $this.data('bs.tooltip') 1739 var data = $this.data('bs.tooltip')
1535 var options = typeof option == 'object' && option 1740 var options = typeof option == 'object' && option
1536 1741
1537 - if (!data && option == 'destroy') return 1742 + if (!data && /destroy|hide/.test(option)) return
1538 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 1743 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1539 if (typeof option == 'string') data[option]() 1744 if (typeof option == 'string') data[option]()
1540 }) 1745 })
@@ -1557,10 +1762,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1557,10 +1762,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1557 }(jQuery); 1762 }(jQuery);
1558 1763
1559 /* ======================================================================== 1764 /* ========================================================================
1560 - * Bootstrap: popover.js v3.2.0 1765 + * Bootstrap: popover.js v3.3.5
1561 * http://getbootstrap.com/javascript/#popovers 1766 * http://getbootstrap.com/javascript/#popovers
1562 * ======================================================================== 1767 * ========================================================================
1563 - * Copyright 2011-2014 Twitter, Inc. 1768 + * Copyright 2011-2015 Twitter, Inc.
1564 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1769 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1565 * ======================================================================== */ 1770 * ======================================================================== */
1566 1771
@@ -1577,7 +1782,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1577,7 +1782,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1577 1782
1578 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') 1783 if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1579 1784
1580 - Popover.VERSION = '3.2.0' 1785 + Popover.VERSION = '3.3.5'
1581 1786
1582 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { 1787 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1583 placement: 'right', 1788 placement: 'right',
@@ -1604,7 +1809,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1604,7 +1809,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1604 var content = this.getContent() 1809 var content = this.getContent()
1605 1810
1606 $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) 1811 $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1607 - $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events 1812 + $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1608 this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' 1813 this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1609 ](content) 1814 ](content)
1610 1815
@@ -1633,11 +1838,6 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1633,11 +1838,6 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1633 return (this.$arrow = this.$arrow || this.tip().find('.arrow')) 1838 return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1634 } 1839 }
1635 1840
1636 - Popover.prototype.tip = function () {  
1637 - if (!this.$tip) this.$tip = $(this.options.template)  
1638 - return this.$tip  
1639 - }  
1640 -  
1641 1841
1642 // POPOVER PLUGIN DEFINITION 1842 // POPOVER PLUGIN DEFINITION
1643 // ========================= 1843 // =========================
@@ -1648,7 +1848,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1648,7 +1848,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1648 var data = $this.data('bs.popover') 1848 var data = $this.data('bs.popover')
1649 var options = typeof option == 'object' && option 1849 var options = typeof option == 'object' && option
1650 1850
1651 - if (!data && option == 'destroy') return 1851 + if (!data && /destroy|hide/.test(option)) return
1652 if (!data) $this.data('bs.popover', (data = new Popover(this, options))) 1852 if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1653 if (typeof option == 'string') data[option]() 1853 if (typeof option == 'string') data[option]()
1654 }) 1854 })
@@ -1671,10 +1871,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1671,10 +1871,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1671 }(jQuery); 1871 }(jQuery);
1672 1872
1673 /* ======================================================================== 1873 /* ========================================================================
1674 - * Bootstrap: scrollspy.js v3.2.0 1874 + * Bootstrap: scrollspy.js v3.3.5
1675 * http://getbootstrap.com/javascript/#scrollspy 1875 * http://getbootstrap.com/javascript/#scrollspy
1676 * ======================================================================== 1876 * ========================================================================
1677 - * Copyright 2011-2014 Twitter, Inc. 1877 + * Copyright 2011-2015 Twitter, Inc.
1678 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1878 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1679 * ======================================================================== */ 1879 * ======================================================================== */
1680 1880
@@ -1686,10 +1886,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1686,10 +1886,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1686 // ========================== 1886 // ==========================
1687 1887
1688 function ScrollSpy(element, options) { 1888 function ScrollSpy(element, options) {
1689 - var process = $.proxy(this.process, this)  
1690 -  
1691 - this.$body = $('body')  
1692 - this.$scrollElement = $(element).is('body') ? $(window) : $(element) 1889 + this.$body = $(document.body)
  1890 + this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
1693 this.options = $.extend({}, ScrollSpy.DEFAULTS, options) 1891 this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1694 this.selector = (this.options.target || '') + ' .nav li > a' 1892 this.selector = (this.options.target || '') + ' .nav li > a'
1695 this.offsets = [] 1893 this.offsets = []
@@ -1697,12 +1895,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1697,12 +1895,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1697 this.activeTarget = null 1895 this.activeTarget = null
1698 this.scrollHeight = 0 1896 this.scrollHeight = 0
1699 1897
1700 - this.$scrollElement.on('scroll.bs.scrollspy', process) 1898 + this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
1701 this.refresh() 1899 this.refresh()
1702 this.process() 1900 this.process()
1703 } 1901 }
1704 1902
1705 - ScrollSpy.VERSION = '3.2.0' 1903 + ScrollSpy.VERSION = '3.3.5'
1706 1904
1707 ScrollSpy.DEFAULTS = { 1905 ScrollSpy.DEFAULTS = {
1708 offset: 10 1906 offset: 10
@@ -1713,20 +1911,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1713,20 +1911,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1713 } 1911 }
1714 1912
1715 ScrollSpy.prototype.refresh = function () { 1913 ScrollSpy.prototype.refresh = function () {
1716 - var offsetMethod = 'offset'  
1717 - var offsetBase = 0 1914 + var that = this
  1915 + var offsetMethod = 'offset'
  1916 + var offsetBase = 0
  1917 +
  1918 + this.offsets = []
  1919 + this.targets = []
  1920 + this.scrollHeight = this.getScrollHeight()
1718 1921
1719 if (!$.isWindow(this.$scrollElement[0])) { 1922 if (!$.isWindow(this.$scrollElement[0])) {
1720 offsetMethod = 'position' 1923 offsetMethod = 'position'
1721 offsetBase = this.$scrollElement.scrollTop() 1924 offsetBase = this.$scrollElement.scrollTop()
1722 } 1925 }
1723 1926
1724 - this.offsets = []  
1725 - this.targets = []  
1726 - this.scrollHeight = this.getScrollHeight()  
1727 -  
1728 - var self = this  
1729 -  
1730 this.$body 1927 this.$body
1731 .find(this.selector) 1928 .find(this.selector)
1732 .map(function () { 1929 .map(function () {
@@ -1741,8 +1938,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1741,8 +1938,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1741 }) 1938 })
1742 .sort(function (a, b) { return a[0] - b[0] }) 1939 .sort(function (a, b) { return a[0] - b[0] })
1743 .each(function () { 1940 .each(function () {
1744 - self.offsets.push(this[0])  
1745 - self.targets.push(this[1]) 1941 + that.offsets.push(this[0])
  1942 + that.targets.push(this[1])
1746 }) 1943 })
1747 } 1944 }
1748 1945
@@ -1763,14 +1960,15 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1763,14 +1960,15 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1763 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) 1960 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
1764 } 1961 }
1765 1962
1766 - if (activeTarget && scrollTop <= offsets[0]) {  
1767 - return activeTarget != (i = targets[0]) && this.activate(i) 1963 + if (activeTarget && scrollTop < offsets[0]) {
  1964 + this.activeTarget = null
  1965 + return this.clear()
1768 } 1966 }
1769 1967
1770 for (i = offsets.length; i--;) { 1968 for (i = offsets.length; i--;) {
1771 activeTarget != targets[i] 1969 activeTarget != targets[i]
1772 && scrollTop >= offsets[i] 1970 && scrollTop >= offsets[i]
1773 - && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) 1971 + && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
1774 && this.activate(targets[i]) 1972 && this.activate(targets[i])
1775 } 1973 }
1776 } 1974 }
@@ -1778,13 +1976,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1778,13 +1976,11 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1778 ScrollSpy.prototype.activate = function (target) { 1976 ScrollSpy.prototype.activate = function (target) {
1779 this.activeTarget = target 1977 this.activeTarget = target
1780 1978
1781 - $(this.selector)  
1782 - .parentsUntil(this.options.target, '.active')  
1783 - .removeClass('active') 1979 + this.clear()
1784 1980
1785 var selector = this.selector + 1981 var selector = this.selector +
1786 - '[data-target="' + target + '"],' +  
1787 - this.selector + '[href="' + target + '"]' 1982 + '[data-target="' + target + '"],' +
  1983 + this.selector + '[href="' + target + '"]'
1788 1984
1789 var active = $(selector) 1985 var active = $(selector)
1790 .parents('li') 1986 .parents('li')
@@ -1799,6 +1995,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1799,6 +1995,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1799 active.trigger('activate.bs.scrollspy') 1995 active.trigger('activate.bs.scrollspy')
1800 } 1996 }
1801 1997
  1998 + ScrollSpy.prototype.clear = function () {
  1999 + $(this.selector)
  2000 + .parentsUntil(this.options.target, '.active')
  2001 + .removeClass('active')
  2002 + }
  2003 +
1802 2004
1803 // SCROLLSPY PLUGIN DEFINITION 2005 // SCROLLSPY PLUGIN DEFINITION
1804 // =========================== 2006 // ===========================
@@ -1842,10 +2044,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1842,10 +2044,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1842 }(jQuery); 2044 }(jQuery);
1843 2045
1844 /* ======================================================================== 2046 /* ========================================================================
1845 - * Bootstrap: tab.js v3.2.0 2047 + * Bootstrap: tab.js v3.3.5
1846 * http://getbootstrap.com/javascript/#tabs 2048 * http://getbootstrap.com/javascript/#tabs
1847 * ======================================================================== 2049 * ========================================================================
1848 - * Copyright 2011-2014 Twitter, Inc. 2050 + * Copyright 2011-2015 Twitter, Inc.
1849 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 2051 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1850 * ======================================================================== */ 2052 * ======================================================================== */
1851 2053
@@ -1857,10 +2059,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1857,10 +2059,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1857 // ==================== 2059 // ====================
1858 2060
1859 var Tab = function (element) { 2061 var Tab = function (element) {
  2062 + // jscs:disable requireDollarBeforejQueryAssignment
1860 this.element = $(element) 2063 this.element = $(element)
  2064 + // jscs:enable requireDollarBeforejQueryAssignment
1861 } 2065 }
1862 2066
1863 - Tab.VERSION = '3.2.0' 2067 + Tab.VERSION = '3.3.5'
  2068 +
  2069 + Tab.TRANSITION_DURATION = 150
1864 2070
1865 Tab.prototype.show = function () { 2071 Tab.prototype.show = function () {
1866 var $this = this.element 2072 var $this = this.element
@@ -1874,22 +2080,30 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1874,22 +2080,30 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1874 2080
1875 if ($this.parent('li').hasClass('active')) return 2081 if ($this.parent('li').hasClass('active')) return
1876 2082
1877 - var previous = $ul.find('.active:last a')[0]  
1878 - var e = $.Event('show.bs.tab', {  
1879 - relatedTarget: previous 2083 + var $previous = $ul.find('.active:last a')
  2084 + var hideEvent = $.Event('hide.bs.tab', {
  2085 + relatedTarget: $this[0]
  2086 + })
  2087 + var showEvent = $.Event('show.bs.tab', {
  2088 + relatedTarget: $previous[0]
1880 }) 2089 })
1881 2090
1882 - $this.trigger(e) 2091 + $previous.trigger(hideEvent)
  2092 + $this.trigger(showEvent)
1883 2093
1884 - if (e.isDefaultPrevented()) return 2094 + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
1885 2095
1886 var $target = $(selector) 2096 var $target = $(selector)
1887 2097
1888 this.activate($this.closest('li'), $ul) 2098 this.activate($this.closest('li'), $ul)
1889 this.activate($target, $target.parent(), function () { 2099 this.activate($target, $target.parent(), function () {
  2100 + $previous.trigger({
  2101 + type: 'hidden.bs.tab',
  2102 + relatedTarget: $this[0]
  2103 + })
1890 $this.trigger({ 2104 $this.trigger({
1891 type: 'shown.bs.tab', 2105 type: 'shown.bs.tab',
1892 - relatedTarget: previous 2106 + relatedTarget: $previous[0]
1893 }) 2107 })
1894 }) 2108 })
1895 } 2109 }
@@ -1898,15 +2112,21 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1898,15 +2112,21 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1898 var $active = container.find('> .active') 2112 var $active = container.find('> .active')
1899 var transition = callback 2113 var transition = callback
1900 && $.support.transition 2114 && $.support.transition
1901 - && $active.hasClass('fade') 2115 + && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
1902 2116
1903 function next() { 2117 function next() {
1904 $active 2118 $active
1905 .removeClass('active') 2119 .removeClass('active')
1906 .find('> .dropdown-menu > .active') 2120 .find('> .dropdown-menu > .active')
1907 - .removeClass('active') 2121 + .removeClass('active')
  2122 + .end()
  2123 + .find('[data-toggle="tab"]')
  2124 + .attr('aria-expanded', false)
1908 2125
1909 - element.addClass('active') 2126 + element
  2127 + .addClass('active')
  2128 + .find('[data-toggle="tab"]')
  2129 + .attr('aria-expanded', true)
1910 2130
1911 if (transition) { 2131 if (transition) {
1912 element[0].offsetWidth // reflow for transition 2132 element[0].offsetWidth // reflow for transition
@@ -1915,17 +2135,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1915,17 +2135,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1915 element.removeClass('fade') 2135 element.removeClass('fade')
1916 } 2136 }
1917 2137
1918 - if (element.parent('.dropdown-menu')) {  
1919 - element.closest('li.dropdown').addClass('active') 2138 + if (element.parent('.dropdown-menu').length) {
  2139 + element
  2140 + .closest('li.dropdown')
  2141 + .addClass('active')
  2142 + .end()
  2143 + .find('[data-toggle="tab"]')
  2144 + .attr('aria-expanded', true)
1920 } 2145 }
1921 2146
1922 callback && callback() 2147 callback && callback()
1923 } 2148 }
1924 2149
1925 - transition ? 2150 + $active.length && transition ?
1926 $active 2151 $active
1927 .one('bsTransitionEnd', next) 2152 .one('bsTransitionEnd', next)
1928 - .emulateTransitionEnd(150) : 2153 + .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
1929 next() 2154 next()
1930 2155
1931 $active.removeClass('in') 2156 $active.removeClass('in')
@@ -1963,18 +2188,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1963,18 +2188,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1963 // TAB DATA-API 2188 // TAB DATA-API
1964 // ============ 2189 // ============
1965 2190
1966 - $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 2191 + var clickHandler = function (e) {
1967 e.preventDefault() 2192 e.preventDefault()
1968 Plugin.call($(this), 'show') 2193 Plugin.call($(this), 'show')
1969 - }) 2194 + }
  2195 +
  2196 + $(document)
  2197 + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
  2198 + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
1970 2199
1971 }(jQuery); 2200 }(jQuery);
1972 2201
1973 /* ======================================================================== 2202 /* ========================================================================
1974 - * Bootstrap: affix.js v3.2.0 2203 + * Bootstrap: affix.js v3.3.5
1975 * http://getbootstrap.com/javascript/#affix 2204 * http://getbootstrap.com/javascript/#affix
1976 * ======================================================================== 2205 * ========================================================================
1977 - * Copyright 2011-2014 Twitter, Inc. 2206 + * Copyright 2011-2015 Twitter, Inc.
1978 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 2207 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1979 * ======================================================================== */ 2208 * ======================================================================== */
1980 2209
@@ -1993,14 +2222,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -1993,14 +2222,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1993 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) 2222 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
1994 2223
1995 this.$element = $(element) 2224 this.$element = $(element)
1996 - this.affixed =  
1997 - this.unpin = 2225 + this.affixed = null
  2226 + this.unpin = null
1998 this.pinnedOffset = null 2227 this.pinnedOffset = null
1999 2228
2000 this.checkPosition() 2229 this.checkPosition()
2001 } 2230 }
2002 2231
2003 - Affix.VERSION = '3.2.0' 2232 + Affix.VERSION = '3.3.5'
2004 2233
2005 Affix.RESET = 'affix affix-top affix-bottom' 2234 Affix.RESET = 'affix affix-top affix-bottom'
2006 2235
@@ -2009,6 +2238,28 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -2009,6 +2238,28 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
2009 target: window 2238 target: window
2010 } 2239 }
2011 2240
  2241 + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
  2242 + var scrollTop = this.$target.scrollTop()
  2243 + var position = this.$element.offset()
  2244 + var targetHeight = this.$target.height()
  2245 +
  2246 + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
  2247 +
  2248 + if (this.affixed == 'bottom') {
  2249 + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
  2250 + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
  2251 + }
  2252 +
  2253 + var initializing = this.affixed == null
  2254 + var colliderTop = initializing ? scrollTop : position.top
  2255 + var colliderHeight = initializing ? targetHeight : height
  2256 +
  2257 + if (offsetTop != null && scrollTop <= offsetTop) return 'top'
  2258 + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
  2259 +
  2260 + return false
  2261 + }
  2262 +
2012 Affix.prototype.getPinnedOffset = function () { 2263 Affix.prototype.getPinnedOffset = function () {
2013 if (this.pinnedOffset) return this.pinnedOffset 2264 if (this.pinnedOffset) return this.pinnedOffset
2014 this.$element.removeClass(Affix.RESET).addClass('affix') 2265 this.$element.removeClass(Affix.RESET).addClass('affix')
@@ -2024,42 +2275,40 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -2024,42 +2275,40 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
2024 Affix.prototype.checkPosition = function () { 2275 Affix.prototype.checkPosition = function () {
2025 if (!this.$element.is(':visible')) return 2276 if (!this.$element.is(':visible')) return
2026 2277
2027 - var scrollHeight = $(document).height()  
2028 - var scrollTop = this.$target.scrollTop()  
2029 - var position = this.$element.offset() 2278 + var height = this.$element.height()
2030 var offset = this.options.offset 2279 var offset = this.options.offset
2031 var offsetTop = offset.top 2280 var offsetTop = offset.top
2032 var offsetBottom = offset.bottom 2281 var offsetBottom = offset.bottom
  2282 + var scrollHeight = Math.max($(document).height(), $(document.body).height())
2033 2283
2034 if (typeof offset != 'object') offsetBottom = offsetTop = offset 2284 if (typeof offset != 'object') offsetBottom = offsetTop = offset
2035 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) 2285 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
2036 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) 2286 if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
2037 2287
2038 - var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :  
2039 - offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :  
2040 - offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false 2288 + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
2041 2289
2042 - if (this.affixed === affix) return  
2043 - if (this.unpin != null) this.$element.css('top', '') 2290 + if (this.affixed != affix) {
  2291 + if (this.unpin != null) this.$element.css('top', '')
2044 2292
2045 - var affixType = 'affix' + (affix ? '-' + affix : '')  
2046 - var e = $.Event(affixType + '.bs.affix') 2293 + var affixType = 'affix' + (affix ? '-' + affix : '')
  2294 + var e = $.Event(affixType + '.bs.affix')
2047 2295
2048 - this.$element.trigger(e) 2296 + this.$element.trigger(e)
2049 2297
2050 - if (e.isDefaultPrevented()) return 2298 + if (e.isDefaultPrevented()) return
2051 2299
2052 - this.affixed = affix  
2053 - this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null 2300 + this.affixed = affix
  2301 + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
2054 2302
2055 - this.$element  
2056 - .removeClass(Affix.RESET)  
2057 - .addClass(affixType)  
2058 - .trigger($.Event(affixType.replace('affix', 'affixed'))) 2303 + this.$element
  2304 + .removeClass(Affix.RESET)
  2305 + .addClass(affixType)
  2306 + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
  2307 + }
2059 2308
2060 if (affix == 'bottom') { 2309 if (affix == 'bottom') {
2061 this.$element.offset({ 2310 this.$element.offset({
2062 - top: scrollHeight - this.$element.height() - offsetBottom 2311 + top: scrollHeight - height - offsetBottom
2063 }) 2312 })
2064 } 2313 }
2065 } 2314 }
@@ -2104,8 +2353,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re @@ -2104,8 +2353,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
2104 2353
2105 data.offset = data.offset || {} 2354 data.offset = data.offset || {}
2106 2355
2107 - if (data.offsetBottom) data.offset.bottom = data.offsetBottom  
2108 - if (data.offsetTop) data.offset.top = data.offsetTop 2356 + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
  2357 + if (data.offsetTop != null) data.offset.top = data.offsetTop
2109 2358
2110 Plugin.call($spy, data) 2359 Plugin.call($spy, data)
2111 }) 2360 })