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
Gemfile
... ... @@ -30,6 +30,7 @@ gem 'rack-contrib'
30 30 # asset pipeline
31 31 gem 'uglifier', '>= 1.0.3'
32 32 gem 'sass-rails'
  33 +gem 'sass', '~> 3.1.19'
33 34  
34 35 group :production do
35 36 gem 'dalli', '~> 2.7.0'
... ...
plugins/responsive/public/_bootstrap-compass.scss 0 → 100644
... ... @@ -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 @@
  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 5 @function twbs-image-path($path) {
6 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 @@
  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 18 // Specified for the h4 to prevent conflicts of changing $headings-color
19 19 color: inherit;
20 20 }
  21 +
21 22 // Provide class for links that match alerts
22 23 .alert-link {
23 24 font-weight: $alert-link-font-weight;
... ... @@ -28,6 +29,7 @@
28 29 > ul {
29 30 margin-bottom: 0;
30 31 }
  32 +
31 33 > p + p {
32 34 margin-top: 5px;
33 35 }
... ... @@ -57,12 +59,15 @@
57 59 .alert-success {
58 60 @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text);
59 61 }
  62 +
60 63 .alert-info {
61 64 @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text);
62 65 }
  66 +
63 67 .alert-warning {
64 68 @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text);
65 69 }
  70 +
66 71 .alert-danger {
67 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 12 font-weight: $badge-font-weight;
13 13 color: $badge-color;
14 14 line-height: $badge-line-height;
15   - vertical-align: baseline;
  15 + vertical-align: middle;
16 16 white-space: nowrap;
17 17 text-align: center;
18 18 background-color: $badge-bg;
... ... @@ -28,7 +28,9 @@
28 28 position: relative;
29 29 top: -1px;
30 30 }
31   - .btn-xs & {
  31 +
  32 + .btn-xs &,
  33 + .btn-group-xs > .btn & {
32 34 top: 0;
33 35 padding: 1px 5px;
34 36 }
... ... @@ -41,12 +43,15 @@
41 43 color: $badge-active-color;
42 44 background-color: $badge-active-bg;
43 45 }
  46 +
44 47 .list-group-item > & {
45 48 float: right;
46 49 }
  50 +
47 51 .list-group-item > & + & {
48 52 margin-right: 5px;
49 53 }
  54 +
50 55 .nav-pills > li > a > & {
51 56 margin-left: 3px;
52 57 }
... ...
plugins/responsive/public/bootstrap/_breadcrumbs.scss
... ... @@ -14,7 +14,9 @@
14 14 display: inline-block;
15 15  
16 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 20 padding: 0 5px;
19 21 color: $breadcrumb-color;
20 22 }
... ...
plugins/responsive/public/bootstrap/_button-groups.scss
... ... @@ -36,6 +36,7 @@
36 36 margin-left: -5px; // Offset the first child's margin
37 37 @include clearfix;
38 38  
  39 + .btn,
39 40 .btn-group,
40 41 .input-group {
41 42 float: left;
... ... @@ -71,13 +72,13 @@
71 72 .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
72 73 border-radius: 0;
73 74 }
74   -.btn-group > .btn-group:first-child {
  75 +.btn-group > .btn-group:first-child:not(:last-child) {
75 76 > .btn:last-child,
76 77 > .dropdown-toggle {
77 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 82 @include border-left-radius(0);
82 83 }
83 84  
... ... @@ -172,11 +173,11 @@
172 173 border-radius: 0;
173 174 }
174 175 &:first-child:not(:last-child) {
175   - border-top-right-radius: $border-radius-base;
  176 + border-top-right-radius: $btn-border-radius-base;
176 177 @include border-bottom-radius(0);
177 178 }
178 179 &:last-child:not(:first-child) {
179   - border-bottom-left-radius: $border-radius-base;
  180 + border-bottom-left-radius: $btn-border-radius-base;
180 181 @include border-top-radius(0);
181 182 }
182 183 }
... ...
plugins/responsive/public/bootstrap/_buttons.scss
... ... @@ -17,7 +17,7 @@
17 17 background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
18 18 border: 1px solid transparent;
19 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 21 @include user-select(none);
22 22  
23 23 &,
... ... @@ -47,10 +47,18 @@
47 47 &[disabled],
48 48 fieldset[disabled] & {
49 49 cursor: $cursor-disabled;
50   - pointer-events: none; // Future-proof disabling of clicks
51 50 @include opacity(.65);
52 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 115 &:hover,
108 116 &:focus {
109 117 color: $link-hover-color;
110   - text-decoration: underline;
  118 + text-decoration: $link-hover-decoration;
111 119 background-color: transparent;
112 120 }
113 121 &[disabled],
... ... @@ -126,14 +134,14 @@
126 134  
127 135 .btn-lg {
128 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 139 .btn-sm {
132 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 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 27  
28 28 // WebKit CSS3 transforms for supported devices
29 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 34 &.next,
35 35 &.active.right {
36   - transform: translate3d(100%, 0, 0);
  36 + @include translate3d(100%, 0, 0);
37 37 left: 0;
38 38 }
39 39 &.prev,
40 40 &.active.left {
41   - transform: translate3d(-100%, 0, 0);
  41 + @include translate3d(-100%, 0, 0);
42 42 left: 0;
43 43 }
44 44 &.next.left,
45 45 &.prev.right,
46 46 &.active {
47   - transform: translate3d(0, 0, 0);
  47 + @include translate3d(0, 0, 0);
48 48 left: 0;
49 49 }
50 50 }
... ... @@ -130,6 +130,7 @@
130 130 .glyphicon-chevron-right {
131 131 position: absolute;
132 132 top: 50%;
  133 + margin-top: -10px;
133 134 z-index: 5;
134 135 display: inline-block;
135 136 }
... ... @@ -147,7 +148,7 @@
147 148 .icon-next {
148 149 width: 20px;
149 150 height: 20px;
150   - margin-top: -10px;
  151 + line-height: 1;
151 152 font-family: serif;
152 153 }
153 154  
... ... @@ -195,6 +196,7 @@
195 196 // Internet Explorer 8-9 does not support clicks on elements without a set
196 197 // `background-color`. We cannot use `filter` since that's not viewed as a
197 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 201 // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we
200 202 // set alpha transparency for the best results possible.
... ...
plugins/responsive/public/bootstrap/_close.scss
... ... @@ -26,6 +26,7 @@
26 26 // Additional properties for button version
27 27 // iOS requires the button element instead of an anchor tag.
28 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 30 button.close {
30 31 padding: 0;
31 32 cursor: pointer;
... ...
plugins/responsive/public/bootstrap/_component-animations.scss
... ... @@ -17,9 +17,8 @@
17 17  
18 18 .collapse {
19 19 display: none;
20   - visibility: hidden;
21 20  
22   - &.in { display: block; visibility: visible; }
  21 + &.in { display: block; }
23 22 // [converter] extracted tr&.in to tr.collapse.in
24 23 // [converter] extracted tbody&.in to tbody.collapse.in
25 24 }
... ...
plugins/responsive/public/bootstrap/_dropdowns.scss
... ... @@ -10,12 +10,14 @@
10 10 height: 0;
11 11 margin-left: 2px;
12 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 15 border-right: $caret-width-base solid transparent;
15 16 border-left: $caret-width-base solid transparent;
16 17 }
17 18  
18 19 // The dropdown wrapper (div)
  20 +.dropup,
19 21 .dropdown {
20 22 position: relative;
21 23 }
... ... @@ -183,14 +185,15 @@
183 185 // Reverse the caret
184 186 .caret {
185 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 190 content: "";
188 191 }
189 192 // Different positioning for bottom up menu
190 193 .dropdown-menu {
191 194 top: auto;
192 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 56 line-height: normal;
57 57 }
58 58  
59   -// Set the height of file controls to match text inputs
60 59 input[type="file"] {
61 60 display: block;
62 61 }
... ... @@ -123,7 +122,7 @@ output {
123 122 background-color: $input-bg;
124 123 background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
125 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 126 @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
128 127 @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
129 128  
... ... @@ -141,9 +140,13 @@ output {
141 140 &[disabled],
142 141 &[readonly],
143 142 fieldset[disabled] & {
144   - cursor: $cursor-disabled;
145 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 152 // [converter] extracted textarea& to textarea.form-control
... ... @@ -172,26 +175,28 @@ input[type=&quot;search&quot;] {
172 175 // In Mobile Safari, setting `display: block` on temporal inputs causes the
173 176 // text within the input to become vertically misaligned. As a workaround, we
174 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 182 @media screen and (-webkit-min-device-pixel-ratio: 0) {
178 183 input[type="date"],
179 184 input[type="time"],
180 185 input[type="datetime-local"],
181 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 207 // horizontal forms, use the predefined grid classes.
203 208  
204 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 247 // Radios and checkboxes on same line
243 248 .radio-inline,
244 249 .checkbox-inline {
  250 + position: relative;
245 251 display: inline-block;
246 252 padding-left: 20px;
247 253 margin-bottom: 0;
... ... @@ -298,6 +304,7 @@ input[type=&quot;checkbox&quot;] {
298 304 padding-bottom: ($padding-base-vertical + 1);
299 305 // Remove default margin from `p`
300 306 margin-bottom: 0;
  307 + min-height: ($line-height-computed + $font-size-base);
301 308  
302 309 &.input-lg,
303 310 &.input-sm {
... ... @@ -311,10 +318,61 @@ input[type=&quot;checkbox&quot;] {
311 318 //
312 319 // Build on `.form-control` with modifier classes to decrease or increase the
313 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 378 // Form control feedback states
... ... @@ -343,12 +401,16 @@ input[type=&quot;checkbox&quot;] {
343 401 text-align: center;
344 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 407 width: $input-height-large;
348 408 height: $input-height-large;
349 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 414 width: $input-height-small;
353 415 height: $input-height-small;
354 416 line-height: $input-height-small;
... ... @@ -447,8 +509,7 @@ input[type=&quot;checkbox&quot;] {
447 509 }
448 510  
449 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 513 .radio,
453 514 .checkbox {
454 515 display: inline-block;
... ... @@ -524,7 +585,7 @@ input[type=&quot;checkbox&quot;] {
524 585 // Reposition the icon because it's now within a grid column and columns have
525 586 // `position: relative;` on them. Also accounts for the grid gutter padding.
526 587 .has-feedback .form-control-feedback {
527   - right: ($grid-gutter-width / 2);
  588 + right: floor(($grid-gutter-width / 2));
528 589 }
529 590  
530 591 // Form group sizes
... ... @@ -535,6 +596,7 @@ input[type=&quot;checkbox&quot;] {
535 596 @media (min-width: $screen-sm-min) {
536 597 .control-label {
537 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 604 @media (min-width: $screen-sm-min) {
543 605 .control-label {
544 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 7 //
8 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 23 // Catchall baseclass
... ... @@ -232,3 +235,73 @@
232 235 .glyphicon-cloud-upload { &:before { content: "\e198"; } }
233 236 .glyphicon-tree-conifer { &:before { content: "\e199"; } }
234 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 160 &:last-child {
161 161 > .btn,
162 162 > .btn-group {
  163 + z-index: 2;
163 164 margin-left: -1px;
164 165 }
165 166 }
... ...
plugins/responsive/public/bootstrap/_jumbotron.scss
... ... @@ -4,7 +4,8 @@
4 4  
5 5  
6 6 .jumbotron {
7   - padding: $jumbotron-padding ($jumbotron-padding / 2);
  7 + padding-top: $jumbotron-padding;
  8 + padding-bottom: $jumbotron-padding;
8 9 margin-bottom: $jumbotron-padding;
9 10 color: $jumbotron-color;
10 11 background-color: $jumbotron-bg;
... ... @@ -13,6 +14,7 @@
13 14 .h1 {
14 15 color: $jumbotron-heading-color;
15 16 }
  17 +
16 18 p {
17 19 margin-bottom: ($jumbotron-padding / 2);
18 20 font-size: $jumbotron-font-size;
... ... @@ -33,7 +35,8 @@
33 35 }
34 36  
35 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 41 .container &,
39 42 .container-fluid & {
... ... @@ -43,7 +46,7 @@
43 46  
44 47 h1,
45 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 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 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 48 color: $list-group-link-color;
48 49  
49 50 .list-group-item-heading {
... ... @@ -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 68 .list-group-item {
63 69 // Disabled state
64 70 &.disabled,
... ...
plugins/responsive/public/bootstrap/_media.scss
... ... @@ -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 29 .media-right,
11 30 .media > .pull-right {
12 31 padding-left: 10px;
... ...
plugins/responsive/public/bootstrap/_mixins.scss
... ... @@ -2,38 +2,39 @@
2 2 // --------------------------------------------------
3 3  
4 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 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 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 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 62  
63 63 // Modal background
64 64 .modal-backdrop {
65   - position: absolute;
  65 + position: fixed;
66 66 top: 0;
67 67 right: 0;
  68 + bottom: 0;
68 69 left: 0;
  70 + z-index: $zindex-modal-background;
69 71 background-color: $modal-backdrop-bg;
70 72 // Fade for backdrop
71 73 &.fade { @include opacity(0); }
... ...
plugins/responsive/public/bootstrap/_navbar.scss
... ... @@ -67,7 +67,6 @@
67 67  
68 68 &.collapse {
69 69 display: block !important;
70   - visibility: visible !important;
71 70 height: auto !important;
72 71 padding-bottom: 0; // Override default setting
73 72 overflow: visible !important;
... ... @@ -331,6 +330,7 @@
331 330 }
332 331 // Menu position and menu caret support for dropups via extra dropup class
333 332 .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
  333 + margin-bottom: 0;
334 334 @include border-top-radius($navbar-border-radius);
335 335 @include border-bottom-radius(0);
336 336 }
... ...
plugins/responsive/public/bootstrap/_navs.scss
... ... @@ -223,11 +223,9 @@
223 223 .tab-content {
224 224 > .tab-pane {
225 225 display: none;
226   - visibility: hidden;
227 226 }
228 227 > .active {
229 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 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 9 html {
... ... @@ -71,7 +71,7 @@ audio:not([controls]) {
71 71  
72 72 //
73 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 77 [hidden],
... ... @@ -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 98 a:active,
... ... @@ -209,7 +210,6 @@ figure {
209 210 //
210 211  
211 212 hr {
212   - -moz-box-sizing: content-box;
213 213 box-sizing: content-box;
214 214 height: 0;
215 215 }
... ... @@ -350,15 +350,12 @@ input[type=&quot;number&quot;]::-webkit-outer-spin-button {
350 350  
351 351 //
352 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 356 input[type="search"] {
358 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 40 > li > span {
41 41 &:hover,
42 42 &:focus {
  43 + z-index: 3;
43 44 color: $pagination-hover-color;
44 45 background-color: $pagination-hover-bg;
45 46 border-color: $pagination-hover-border;
... ... @@ -79,10 +80,10 @@
79 80  
80 81 // Large
81 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 86 // Small
86 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 36 font-size: ceil(($font-size-base * 1.125));
37 37 color: inherit;
38 38  
39   - > a {
  39 + > a,
  40 + > small,
  41 + > .small,
  42 + > small > a,
  43 + > .small > a {
40 44 color: inherit;
41 45 }
42 46 }
... ... @@ -72,6 +76,7 @@
72 76 @include border-top-radius(($panel-border-radius - 1));
73 77 }
74 78 }
  79 +
75 80 // Add border bottom radius for last one
76 81 &:last-child {
77 82 .list-group-item:last-child {
... ... @@ -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 94 // Collapse space between when there's no additional content.
85 95 .panel-heading + .list-group {
... ...
plugins/responsive/public/bootstrap/_popovers.scss
... ... @@ -11,12 +11,11 @@
11 11 display: none;
12 12 max-width: $popover-max-width;
13 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 17 font-size: $font-size-base;
17   - font-weight: normal;
18   - line-height: $line-height-base;
19   - text-align: left;
  18 +
20 19 background-color: $popover-bg;
21 20 background-clip: padding-box;
22 21 border: 1px solid $popover-fallback-border-color;
... ... @@ -24,9 +23,6 @@
24 23 border-radius: $border-radius-large;
25 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 26 // Offset the popover to account for the popover arrow
31 27 &.top { margin-top: -$popover-arrow-width; }
32 28 &.right { margin-left: $popover-arrow-width; }
... ...
plugins/responsive/public/bootstrap/_print.scss
... ... @@ -67,12 +67,6 @@
67 67 }
68 68  
69 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 71 // Bootstrap components
78 72 .navbar {
... ...
plugins/responsive/public/bootstrap/_responsive-embed.scss
... ... @@ -22,14 +22,14 @@
22 22 width: 100%;
23 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 18 // Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/
19 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 28 // Visibility utilities
27 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 36 .visible-xs-block,
32 37 .visible-xs-inline,
... ...
plugins/responsive/public/bootstrap/_scaffolding.scss
... ... @@ -148,3 +148,14 @@ hr {
148 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 111 // Default zebra-stripe styles (alternating gray and transparent backgrounds)
112 112  
113 113 .table-striped {
114   - > tbody > tr:nth-child(odd) {
  114 + > tbody > tr:nth-of-type(odd) {
115 115 background-color: $table-bg-accent;
116 116 }
117 117 }
... ... @@ -133,7 +133,7 @@ th {
133 133 // Reset default table behavior
134 134  
135 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 137 float: none;
138 138 display: table-column;
139 139 }
... ... @@ -141,7 +141,7 @@ table {
141 141 td,
142 142 th {
143 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 145 float: none;
146 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 8 // Load core variables and mixins
... ... @@ -28,6 +33,12 @@
28 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 42 .badge {
32 43 text-shadow: none;
33 44 }
... ... @@ -36,7 +47,7 @@
36 47 // Mixin for generating new styles
37 48 @mixin btn-styles($btn-color: #555) {
38 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 51 background-repeat: repeat-x;
41 52 border-color: darken($btn-color, 14%);
42 53  
... ... @@ -52,10 +63,18 @@
52 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 149 // Inverted navbar
131 150 .navbar-inverse {
132 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 154 .navbar-nav > .open > a,
136 155 .navbar-nav > .active > a {
137 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 8 position: absolute;
9 9 z-index: $zindex-tooltip;
10 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 14 font-size: $font-size-small;
15   - font-weight: normal;
16   - line-height: 1.4;
  15 +
17 16 @include opacity(0);
18 17  
19 18 &.in { @include opacity($tooltip-opacity); }
... ... @@ -29,7 +28,6 @@
29 28 padding: 3px 8px;
30 29 color: $tooltip-color;
31 30 text-align: center;
32   - text-decoration: none;
33 31 background-color: $tooltip-bg;
34 32 border-radius: $border-radius-base;
35 33 }
... ...
plugins/responsive/public/bootstrap/_type.scss
... ... @@ -234,7 +234,7 @@ abbr[data-original-title] {
234 234 }
235 235 .initialism {
236 236 font-size: 90%;
237   - text-transform: uppercase;
  237 + @extend .text-uppercase;
238 238 }
239 239  
240 240 // Blockquotes
... ...
plugins/responsive/public/bootstrap/_utilities.scss
... ... @@ -44,7 +44,6 @@
44 44  
45 45 .hidden {
46 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 3 // Variables
8 4 // --------------------------------------------------
... ... @@ -19,7 +15,7 @@ $gray: lighten($gray-base, 33.5%) !default; // #555
19 15 $gray-light: lighten($gray-base, 46.7%) !default; // #777
20 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 19 $brand-success: #5cb85c !default;
24 20 $brand-info: #5bc0de !default;
25 21 $brand-warning: #f0ad4e !default;
... ... @@ -82,7 +78,8 @@ $headings-color: inherit !default;
82 78  
83 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 83 $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
87 84  
88 85 //** File name for all font files.
... ... @@ -107,7 +104,7 @@ $padding-small-horizontal: 10px !default;
107 104 $padding-xs-vertical: 1px !default;
108 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 108 $line-height-small: 1.5 !default;
112 109  
113 110 $border-radius-base: 4px !default;
... ... @@ -178,6 +175,11 @@ $btn-danger-border: darken($btn-danger-bg, 5%) !default;
178 175  
179 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 184 //== Forms
183 185 //
... ... @@ -195,6 +197,7 @@ $input-border: #ccc !default;
195 197  
196 198 // TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
197 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 201 $input-border-radius: $border-radius-base !default;
199 202 //** Large `.form-control` border radius
200 203 $input-border-radius-large: $border-radius-large !default;
... ... @@ -214,6 +217,9 @@ $input-height-large: (ceil($font-size-large * $line-height-large) +
214 217 //** Small `.form-control` height
215 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 223 $legend-color: $gray-dark !default;
218 224 $legend-border-color: #e5e5e5 !default;
219 225  
... ... @@ -273,7 +279,8 @@ $zindex-dropdown: 1000 !default;
273 279 $zindex-popover: 1060 !default;
274 280 $zindex-tooltip: 1070 !default;
275 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 286 //== Media queries breakpoints
... ... @@ -386,7 +393,7 @@ $navbar-default-toggle-icon-bar-bg: #888 !default;
386 393 $navbar-default-toggle-border-color: #ddd !default;
387 394  
388 395  
389   -// Inverted navbar
  396 +//=== Inverted navbar
390 397 // Reset inverted navbar basics
391 398 $navbar-inverse-color: lighten($gray-light, 15%) !default;
392 399 $navbar-inverse-bg: #222 !default;
... ... @@ -487,6 +494,7 @@ $jumbotron-color: inherit !default;
487 494 $jumbotron-bg: $gray-lighter !default;
488 495 $jumbotron-heading-color: inherit !default;
489 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 500 //== Form states and alerts
... ...
plugins/responsive/public/bootstrap/mixins/_background-variant.scss
... ... @@ -5,7 +5,8 @@
5 5 #{$parent} {
6 6 background-color: $color;
7 7 }
8   - a#{$parent}:hover {
  8 + a#{$parent}:hover,
  9 + a#{$parent}:focus {
9 10 background-color: darken($color, 10%);
10 11 }
11 12 }
... ...
plugins/responsive/public/bootstrap/mixins/_buttons.scss
... ... @@ -8,15 +8,31 @@
8 8 background-color: $background;
9 9 border-color: $border;
10 10  
11   - &:hover,
12 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 22 &:active,
15 23 &.active,
16 24 .open > &.dropdown-toggle {
17 25 color: $color;
18 26 background-color: darken($background, 10%);
19 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 37 &:active,
22 38 &.active,
... ...
plugins/responsive/public/bootstrap/mixins/_grid-framework.scss
... ... @@ -13,8 +13,8 @@
13 13 // Prevent columns from collapsing when empty
14 14 min-height: 1px;
15 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 13  
14 14 // Creates a wrapper for a series of columns
15 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 18 @include clearfix;
19 19 }
20 20  
... ...
plugins/responsive/public/bootstrap/mixins/_hide-text.scss
1 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 4 // mixins being reused as classes with the same name, this doesn't hold up. As
5 5 // of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.
6 6 //
... ... @@ -8,7 +8,7 @@
8 8  
9 9 // Deprecated as of v3.0.1 (will be removed in v4)
10 10 @mixin hide-text() {
11   - font: #{0/0} a;
  11 + font: 0/0 a;
12 12 color: transparent;
13 13 text-shadow: none;
14 14 background-color: transparent;
... ...
plugins/responsive/public/bootstrap/mixins/_list-group.scss
... ... @@ -5,10 +5,11 @@
5 5 color: $color;
6 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 13 color: $color;
13 14  
14 15 .list-group-item-heading {
... ...
plugins/responsive/public/bootstrap/mixins/_opacity.scss
... ... @@ -4,5 +4,5 @@
4 4 opacity: $opacity;
5 5 // IE8 filter
6 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 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 4 > li {
5 5 > a,
6 6 > span {
7 7 padding: $padding-vertical $padding-horizontal;
8 8 font-size: $font-size;
  9 + line-height: $line-height;
9 10 }
10 11 &:first-child {
11 12 > a,
... ...
plugins/responsive/public/bootstrap/mixins/_reset-text.scss 0 → 100644
... ... @@ -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 #{$parent} {
8 8 display: block !important;
9 9 }
10   - table#{$parent} { display: table; }
  10 + table#{$parent} { display: table !important; }
11 11 tr#{$parent} { display: table-row !important; }
12 12 th#{$parent},
13 13 td#{$parent} { display: table-cell !important; }
... ...
plugins/responsive/public/bootstrap/mixins/_text-emphasis.scss
... ... @@ -5,7 +5,8 @@
5 5 #{$parent} {
6 6 color: $color;
7 7 }
8   - a#{$parent}:hover {
  8 + a#{$parent}:hover,
  9 + a#{$parent}:focus {
9 10 color: darken($color, 10%);
10 11 }
11 12 }
... ...
plugins/responsive/public/bootstrap/mixins/_vendor-prefixes.scss
... ... @@ -102,7 +102,7 @@
102 102 // Firefox
103 103 &::-moz-placeholder {
104 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 107 &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+
108 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 21 * http://getbootstrap.com/javascript/#transitions
12 22 * ========================================================================
13   - * Copyright 2011-2014 Twitter, Inc.
  23 + * Copyright 2011-2015 Twitter, Inc.
14 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 77 }(jQuery);
68 78  
69 79 /* ========================================================================
70   - * Bootstrap: alert.js v3.2.0
  80 + * Bootstrap: alert.js v3.3.5
71 81 * http://getbootstrap.com/javascript/#alerts
72 82 * ========================================================================
73   - * Copyright 2011-2014 Twitter, Inc.
  83 + * Copyright 2011-2015 Twitter, Inc.
74 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 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 103 Alert.prototype.close = function (e) {
92 104 var $this = $(this)
... ... @@ -102,7 +114,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
102 114 if (e) e.preventDefault()
103 115  
104 116 if (!$parent.length) {
105   - $parent = $this.hasClass('alert') ? $this : $this.parent()
  117 + $parent = $this.closest('.alert')
106 118 }
107 119  
108 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 131 $.support.transition && $parent.hasClass('fade') ?
120 132 $parent
121 133 .one('bsTransitionEnd', removeElement)
122   - .emulateTransitionEnd(150) :
  134 + .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
123 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 172 }(jQuery);
161 173  
162 174 /* ========================================================================
163   - * Bootstrap: button.js v3.2.0
  175 + * Bootstrap: button.js v3.3.5
164 176 * http://getbootstrap.com/javascript/#buttons
165 177 * ========================================================================
166   - * Copyright 2011-2014 Twitter, Inc.
  178 + * Copyright 2011-2015 Twitter, Inc.
167 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 192 this.isLoading = false
181 193 }
182 194  
183   - Button.VERSION = '3.2.0'
  195 + Button.VERSION = '3.3.5'
184 196  
185 197 Button.DEFAULTS = {
186 198 loadingText: 'loading...'
... ... @@ -192,14 +204,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
192 204 var val = $el.is('input') ? 'val' : 'html'
193 205 var data = $el.data()
194 206  
195   - state = state + 'Text'
  207 + state += 'Text'
196 208  
197 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 211 // push to event loop to allow forms to submit
202 212 setTimeout($.proxy(function () {
  213 + $el[val](data[state] == null ? this.options[state] : data[state])
  214 +
203 215 if (state == 'loadingText') {
204 216 this.isLoading = true
205 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 229 if ($parent.length) {
218 230 var $input = this.$element.find('input')
219 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 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 293 }(jQuery);
272 294  
273 295 /* ========================================================================
274   - * Bootstrap: carousel.js v3.2.0
  296 + * Bootstrap: carousel.js v3.3.5
275 297 * http://getbootstrap.com/javascript/#carousel
276 298 * ========================================================================
277   - * Copyright 2011-2014 Twitter, Inc.
  299 + * Copyright 2011-2015 Twitter, Inc.
278 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 308 // =========================
287 309  
288 310 var Carousel = function (element, options) {
289   - this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
  311 + this.$element = $(element)
290 312 this.$indicators = this.$element.find('.carousel-indicators')
291 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 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 323 .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
300 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 331 Carousel.DEFAULTS = {
306 332 interval: 5000,
307 333 pause: 'hover',
308   - wrap: true
  334 + wrap: true,
  335 + keyboard: true
309 336 }
310 337  
311 338 Carousel.prototype.keydown = function (e) {
  339 + if (/input|textarea/i.test(e.target.tagName)) return
312 340 switch (e.which) {
313 341 case 37: this.prev(); break
314 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 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 376 Carousel.prototype.to = function (pos) {
339 377 var that = this
340 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 382 if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
345 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 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 410  
373 411 Carousel.prototype.slide = function (type, next) {
374 412 var $active = this.$element.find('.item.active')
375   - var $next = next || $active[type]()
  413 + var $next = next || this.getItemForDirection(type, $active)
376 414 var isCycling = this.interval
377 415 var direction = type == 'next' ? 'left' : 'right'
378   - var fallback = type == 'next' ? 'first' : 'last'
379 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 418 if ($next.hasClass('active')) return (this.sliding = false)
387 419  
388 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 450 that.$element.trigger(slidEvent)
419 451 }, 0)
420 452 })
421   - .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
  453 + .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
422 454 } else {
423 455 $active.removeClass('active')
424 456 $next.addClass('active')
... ... @@ -467,7 +499,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
467 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 503 var href
472 504 var $this = $(this)
473 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 515 }
484 516  
485 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 524 $(window).on('load', function () {
489 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 531 }(jQuery);
496 532  
497 533 /* ========================================================================
498   - * Bootstrap: collapse.js v3.2.0
  534 + * Bootstrap: collapse.js v3.3.5
499 535 * http://getbootstrap.com/javascript/#collapse
500 536 * ========================================================================
501   - * Copyright 2011-2014 Twitter, Inc.
  537 + * Copyright 2011-2015 Twitter, Inc.
502 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 548 var Collapse = function (element, options) {
513 549 this.$element = $(element)
514 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 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 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 568 Collapse.DEFAULTS = {
524 569 toggle: true
... ... @@ -532,17 +577,21 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
532 577 Collapse.prototype.show = function () {
533 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 588 var startEvent = $.Event('show.bs.collapse')
536 589 this.$element.trigger(startEvent)
537 590 if (startEvent.isDefaultPrevented()) return
538 591  
539   - var actives = this.$parent && this.$parent.find('> .panel > .in')
540   -
541 592 if (actives && actives.length) {
542   - var hasData = actives.data('bs.collapse')
543   - if (hasData && hasData.transitioning) return
544 593 Plugin.call(actives, 'hide')
545   - hasData || actives.data('bs.collapse', null)
  594 + activesData || actives.data('bs.collapse', null)
546 595 }
547 596  
548 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 599 this.$element
551 600 .removeClass('collapse')
552 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 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 622  
569 623 this.$element
570 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 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 638  
585 639 this.$element
586 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 648 this.transitioning = 1
591 649  
592 650 var complete = function () {
593 651 this.transitioning = 0
594 652 this.$element
595   - .trigger('hidden.bs.collapse')
596 653 .removeClass('collapsing')
597 654 .addClass('collapse')
  655 + .trigger('hidden.bs.collapse')
598 656 }
599 657  
600 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 660 this.$element
603 661 [dimension](0)
604 662 .one('bsTransitionEnd', $.proxy(complete, this))
605   - .emulateTransitionEnd(350)
  663 + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
606 664 }
607 665  
608 666 Collapse.prototype.toggle = function () {
609 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 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 704 var data = $this.data('bs.collapse')
620 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 708 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
624 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 729 // =================
645 730  
646 731 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
647   - var href
648 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 737 var data = $target.data('bs.collapse')
654 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 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 743 }(jQuery);
667 744  
668 745 /* ========================================================================
669   - * Bootstrap: dropdown.js v3.2.0
  746 + * Bootstrap: dropdown.js v3.3.5
670 747 * http://getbootstrap.com/javascript/#dropdowns
671 748 * ========================================================================
672   - * Copyright 2011-2014 Twitter, Inc.
  749 + * Copyright 2011-2015 Twitter, Inc.
673 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 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 802 Dropdown.prototype.toggle = function (e) {
692 803 var $this = $(this)
... ... @@ -701,7 +812,10 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
701 812 if (!isActive) {
702 813 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
703 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 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 823  
710 824 if (e.isDefaultPrevented()) return
711 825  
712   - $this.trigger('focus')
  826 + $this
  827 + .trigger('focus')
  828 + .attr('aria-expanded', 'true')
713 829  
714 830 $parent
715 831 .toggleClass('open')
... ... @@ -720,7 +836,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
720 836 }
721 837  
722 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 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 848 var $parent = getParent($this)
733 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 852 if (e.which == 27) $parent.find(toggle).trigger('focus')
737 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 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 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 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 903 .on('click.bs.dropdown.data-api', clearMenus)
814 904 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
815 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 909 }(jQuery);
819 910  
820 911 /* ========================================================================
821   - * Bootstrap: modal.js v3.2.0
  912 + * Bootstrap: modal.js v3.3.5
822 913 * http://getbootstrap.com/javascript/#modals
823 914 * ========================================================================
824   - * Copyright 2011-2014 Twitter, Inc.
  915 + * Copyright 2011-2015 Twitter, Inc.
825 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 924 // ======================
834 925  
835 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 937 if (this.options.remote) {
844 938 this.$element
... ... @@ -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 951 Modal.DEFAULTS = {
855 952 backdrop: true,
... ... @@ -872,13 +969,20 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
872 969 this.isShown = true
873 970  
874 971 this.checkScrollbar()
  972 + this.setScrollbar()
875 973 this.$body.addClass('modal-open')
876 974  
877   - this.setScrollbar()
878 975 this.escape()
  976 + this.resize()
879 977  
880 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 986 this.backdrop(function () {
883 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 994 .show()
891 995 .scrollTop(0)
892 996  
  997 + that.adjustDialog()
  998 +
893 999 if (transition) {
894 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 1005 that.enforceFocus()
902 1006  
903 1007 var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
904 1008  
905 1009 transition ?
906   - that.$element.find('.modal-dialog') // wait for modal to slide in
  1010 + that.$dialog // wait for modal to slide in
907 1011 .one('bsTransitionEnd', function () {
908 1012 that.$element.trigger('focus').trigger(e)
909 1013 })
910   - .emulateTransitionEnd(300) :
  1014 + .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
911 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 1027  
924 1028 this.isShown = false
925 1029  
926   - this.$body.removeClass('modal-open')
927   -
928   - this.resetScrollbar()
929 1030 this.escape()
  1031 + this.resize()
930 1032  
931 1033 $(document).off('focusin.bs.modal')
932 1034  
933 1035 this.$element
934 1036 .removeClass('in')
935   - .attr('aria-hidden', true)
936 1037 .off('click.dismiss.bs.modal')
  1038 + .off('mouseup.dismiss.bs.modal')
  1039 +
  1040 + this.$dialog.off('mousedown.dismiss.bs.modal')
937 1041  
938 1042 $.support.transition && this.$element.hasClass('fade') ?
939 1043 this.$element
940 1044 .one('bsTransitionEnd', $.proxy(this.hideModal, this))
941   - .emulateTransitionEnd(300) :
  1045 + .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
942 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 1058  
955 1059 Modal.prototype.escape = function () {
956 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 1062 e.which == 27 && this.hide()
959 1063 }, this))
960 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 1078 var that = this
967 1079 this.$element.hide()
968 1080 this.backdrop(function () {
  1081 + that.$body.removeClass('modal-open')
  1082 + that.resetAdjustments()
  1083 + that.resetScrollbar()
969 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 1097 if (this.isShown && this.options.backdrop) {
983 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 1102 .appendTo(this.$body)
987 1103  
988 1104 this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
  1105 + if (this.ignoreBackdropClick) {
  1106 + this.ignoreBackdropClick = false
  1107 + return
  1108 + }
989 1109 if (e.target !== e.currentTarget) return
990 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 1113 }, this))
994 1114  
995 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 1121 doAnimate ?
1002 1122 this.$backdrop
1003 1123 .one('bsTransitionEnd', callback)
1004   - .emulateTransitionEnd(150) :
  1124 + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1005 1125 callback()
1006 1126  
1007 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 1134 $.support.transition && this.$element.hasClass('fade') ?
1015 1135 this.$backdrop
1016 1136 .one('bsTransitionEnd', callbackRemove)
1017   - .emulateTransitionEnd(150) :
  1137 + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1018 1138 callbackRemove()
1019 1139  
1020 1140 } else if (callback) {
... ... @@ -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 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 1177 Modal.prototype.setScrollbar = function () {
1031 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 1183 Modal.prototype.resetScrollbar = function () {
1036   - this.$body.css('padding-right', '')
  1184 + this.$body.css('padding-right', this.originalBodyPad)
1037 1185 }
1038 1186  
1039 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 1247 }(jQuery);
1100 1248  
1101 1249 /* ========================================================================
1102   - * Bootstrap: tooltip.js v3.2.0
  1250 + * Bootstrap: tooltip.js v3.3.5
1103 1251 * http://getbootstrap.com/javascript/#tooltip
1104 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 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 1263 // ===============================
1116 1264  
1117 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 1271 this.$element = null
  1272 + this.inState = null
1124 1273  
1125 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 1281 Tooltip.DEFAULTS = {
1131 1282 animation: true,
... ... @@ -1148,7 +1299,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1148 1299 this.type = type
1149 1300 this.$element = $(element)
1150 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 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 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 1376 clearTimeout(self.timeout)
1212 1377  
1213 1378 self.hoverState = 'in'
... ... @@ -1219,6 +1384,14 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1219 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 1395 Tooltip.prototype.leave = function (obj) {
1223 1396 var self = obj instanceof this.constructor ?
1224 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 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 1410 clearTimeout(self.timeout)
1232 1411  
1233 1412 self.hoverState = 'out'
... ... @@ -1245,7 +1424,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1245 1424 if (this.hasContent() && this.enabled) {
1246 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 1428 if (e.isDefaultPrevented() || !inDom) return
1250 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 1453 .data('bs.' + this.type, this)
1275 1454  
1276 1455 this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
  1456 + this.$element.trigger('inserted.bs.' + this.type)
1277 1457  
1278 1458 var pos = this.getPosition()
1279 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 1461  
1282 1462 if (autoPlace) {
1283 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 1470 placement
1292 1471  
1293 1472 $tip
... ... @@ -1300,14 +1479,17 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1300 1479 this.applyPlacement(calculatedOffset, placement)
1301 1480  
1302 1481 var complete = function () {
  1482 + var prevHoverState = that.hoverState
1303 1483 that.$element.trigger('shown.bs.' + that.type)
1304 1484 that.hoverState = null
  1485 +
  1486 + if (prevHoverState == 'out') that.leave(that)
1305 1487 }
1306 1488  
1307 1489 $.support.transition && this.$tip.hasClass('fade') ?
1308 1490 $tip
1309 1491 .one('bsTransitionEnd', complete)
1310   - .emulateTransitionEnd(150) :
  1492 + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1311 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 1507 if (isNaN(marginTop)) marginTop = 0
1326 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 1513 // $.fn.offset doesn't round pixel values
1332 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 1536 if (delta.left) offset.left += delta.left
1355 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 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 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 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 1562 var that = this
1379   - var $tip = this.tip()
  1563 + var $tip = $(this.$tip)
1380 1564 var e = $.Event('hide.bs.' + this.type)
1381 1565  
1382   - this.$element.removeAttr('aria-describedby')
1383   -
1384 1566 function complete() {
1385 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 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 1577  
1393 1578 $tip.removeClass('in')
1394 1579  
1395   - $.support.transition && this.$tip.hasClass('fade') ?
  1580 + $.support.transition && $tip.hasClass('fade') ?
1396 1581 $tip
1397 1582 .one('bsTransitionEnd', complete)
1398   - .emulateTransitionEnd(150) :
  1583 + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1399 1584 complete()
1400 1585  
1401 1586 this.hoverState = null
... ... @@ -1405,7 +1590,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1405 1590  
1406 1591 Tooltip.prototype.fixTitle = function () {
1407 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 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 1601  
1417 1602 Tooltip.prototype.getPosition = function ($element) {
1418 1603 $element = $element || this.$element
  1604 +
1419 1605 var el = $element[0]
1420 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 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 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 1645 var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1454 1646 if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1455 1647 delta.left = viewportDimensions.left - leftEdgeOffset
1456   - } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
  1648 + } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
1457 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 1671 }
1480 1672  
1481 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 1683 Tooltip.prototype.arrow = function () {
1486 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 1687 Tooltip.prototype.enable = function () {
1498 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 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 1718 Tooltip.prototype.destroy = function () {
  1719 + var that = this
1523 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 1739 var data = $this.data('bs.tooltip')
1535 1740 var options = typeof option == 'object' && option
1536 1741  
1537   - if (!data && option == 'destroy') return
  1742 + if (!data && /destroy|hide/.test(option)) return
1538 1743 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1539 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 1762 }(jQuery);
1558 1763  
1559 1764 /* ========================================================================
1560   - * Bootstrap: popover.js v3.2.0
  1765 + * Bootstrap: popover.js v3.3.5
1561 1766 * http://getbootstrap.com/javascript/#popovers
1562 1767 * ========================================================================
1563   - * Copyright 2011-2014 Twitter, Inc.
  1768 + * Copyright 2011-2015 Twitter, Inc.
1564 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 1782  
1578 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 1787 Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1583 1788 placement: 'right',
... ... @@ -1604,7 +1809,7 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1604 1809 var content = this.getContent()
1605 1810  
1606 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 1813 this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1609 1814 ](content)
1610 1815  
... ... @@ -1633,11 +1838,6 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1633 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 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 1848 var data = $this.data('bs.popover')
1649 1849 var options = typeof option == 'object' && option
1650 1850  
1651   - if (!data && option == 'destroy') return
  1851 + if (!data && /destroy|hide/.test(option)) return
1652 1852 if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1653 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 1871 }(jQuery);
1672 1872  
1673 1873 /* ========================================================================
1674   - * Bootstrap: scrollspy.js v3.2.0
  1874 + * Bootstrap: scrollspy.js v3.3.5
1675 1875 * http://getbootstrap.com/javascript/#scrollspy
1676 1876 * ========================================================================
1677   - * Copyright 2011-2014 Twitter, Inc.
  1877 + * Copyright 2011-2015 Twitter, Inc.
1678 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 1886 // ==========================
1687 1887  
1688 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 1891 this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1694 1892 this.selector = (this.options.target || '') + ' .nav li > a'
1695 1893 this.offsets = []
... ... @@ -1697,12 +1895,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1697 1895 this.activeTarget = null
1698 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 1899 this.refresh()
1702 1900 this.process()
1703 1901 }
1704 1902  
1705   - ScrollSpy.VERSION = '3.2.0'
  1903 + ScrollSpy.VERSION = '3.3.5'
1706 1904  
1707 1905 ScrollSpy.DEFAULTS = {
1708 1906 offset: 10
... ... @@ -1713,20 +1911,19 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1713 1911 }
1714 1912  
1715 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 1922 if (!$.isWindow(this.$scrollElement[0])) {
1720 1923 offsetMethod = 'position'
1721 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 1927 this.$body
1731 1928 .find(this.selector)
1732 1929 .map(function () {
... ... @@ -1741,8 +1938,8 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1741 1938 })
1742 1939 .sort(function (a, b) { return a[0] - b[0] })
1743 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 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 1968 for (i = offsets.length; i--;) {
1771 1969 activeTarget != targets[i]
1772 1970 && scrollTop >= offsets[i]
1773   - && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
  1971 + && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
1774 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 1976 ScrollSpy.prototype.activate = function (target) {
1779 1977 this.activeTarget = target
1780 1978  
1781   - $(this.selector)
1782   - .parentsUntil(this.options.target, '.active')
1783   - .removeClass('active')
  1979 + this.clear()
1784 1980  
1785 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 1985 var active = $(selector)
1790 1986 .parents('li')
... ... @@ -1799,6 +1995,12 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1799 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 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 2044 }(jQuery);
1843 2045  
1844 2046 /* ========================================================================
1845   - * Bootstrap: tab.js v3.2.0
  2047 + * Bootstrap: tab.js v3.3.5
1846 2048 * http://getbootstrap.com/javascript/#tabs
1847 2049 * ========================================================================
1848   - * Copyright 2011-2014 Twitter, Inc.
  2050 + * Copyright 2011-2015 Twitter, Inc.
1849 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 2059 // ====================
1858 2060  
1859 2061 var Tab = function (element) {
  2062 + // jscs:disable requireDollarBeforejQueryAssignment
1860 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 2071 Tab.prototype.show = function () {
1866 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 2080  
1875 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 2096 var $target = $(selector)
1887 2097  
1888 2098 this.activate($this.closest('li'), $ul)
1889 2099 this.activate($target, $target.parent(), function () {
  2100 + $previous.trigger({
  2101 + type: 'hidden.bs.tab',
  2102 + relatedTarget: $this[0]
  2103 + })
1890 2104 $this.trigger({
1891 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 2112 var $active = container.find('> .active')
1899 2113 var transition = callback
1900 2114 && $.support.transition
1901   - && $active.hasClass('fade')
  2115 + && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
1902 2116  
1903 2117 function next() {
1904 2118 $active
1905 2119 .removeClass('active')
1906 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 2131 if (transition) {
1912 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 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 2147 callback && callback()
1923 2148 }
1924 2149  
1925   - transition ?
  2150 + $active.length && transition ?
1926 2151 $active
1927 2152 .one('bsTransitionEnd', next)
1928   - .emulateTransitionEnd(150) :
  2153 + .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
1929 2154 next()
1930 2155  
1931 2156 $active.removeClass('in')
... ... @@ -1963,18 +2188,22 @@ if (typeof jQuery === &#39;undefined&#39;) { throw new Error(&#39;Bootstrap\&#39;s JavaScript re
1963 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 2192 e.preventDefault()
1968 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 2200 }(jQuery);
1972 2201  
1973 2202 /* ========================================================================
1974   - * Bootstrap: affix.js v3.2.0
  2203 + * Bootstrap: affix.js v3.3.5
1975 2204 * http://getbootstrap.com/javascript/#affix
1976 2205 * ========================================================================
1977   - * Copyright 2011-2014 Twitter, Inc.
  2206 + * Copyright 2011-2015 Twitter, Inc.
1978 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 2222 .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
1994 2223  
1995 2224 this.$element = $(element)
1996   - this.affixed =
1997   - this.unpin =
  2225 + this.affixed = null
  2226 + this.unpin = null
1998 2227 this.pinnedOffset = null
1999 2228  
2000 2229 this.checkPosition()
2001 2230 }
2002 2231  
2003   - Affix.VERSION = '3.2.0'
  2232 + Affix.VERSION = '3.3.5'
2004 2233  
2005 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 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 2263 Affix.prototype.getPinnedOffset = function () {
2013 2264 if (this.pinnedOffset) return this.pinnedOffset
2014 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 2275 Affix.prototype.checkPosition = function () {
2025 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 2279 var offset = this.options.offset
2031 2280 var offsetTop = offset.top
2032 2281 var offsetBottom = offset.bottom
  2282 + var scrollHeight = Math.max($(document).height(), $(document.body).height())
2033 2283  
2034 2284 if (typeof offset != 'object') offsetBottom = offsetTop = offset
2035 2285 if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
2036 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 2309 if (affix == 'bottom') {
2061 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 2353  
2105 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 2359 Plugin.call($spy, data)
2111 2360 })
... ...