diff --git a/backend/app/assets/javascripts/spree/backend.js b/backend/app/assets/javascripts/spree/backend.js index 5beba64ea54..0847d535536 100644 --- a/backend/app/assets/javascripts/spree/backend.js +++ b/backend/app/assets/javascripts/spree/backend.js @@ -10,7 +10,7 @@ //= require solidus_admin/underscore //= require solidus_admin/backbone //= require solidus_admin/backbone-nested-models -//= require solidus_admin/tether +//= require solidus_admin/popover //= require solidus_admin/bootstrap //= require prism //= require spree diff --git a/backend/app/assets/stylesheets/spree/backend/_bootstrap_custom.scss b/backend/app/assets/stylesheets/spree/backend/_bootstrap_custom.scss index 97e8980c5af..4c064b00845 100644 --- a/backend/app/assets/stylesheets/spree/backend/_bootstrap_custom.scss +++ b/backend/app/assets/stylesheets/spree/backend/_bootstrap_custom.scss @@ -7,10 +7,10 @@ // // Grayscale and brand colors for use across Bootstrap. -$brand-primary: $color-3 !default; -$brand-success: $color-2 !default; -$brand-warning: $color-6 !default; -$brand-danger: $color-5 !default; +$blue: $color-3 !default; +$red: $color-5 !default; +$orange: $color-6 !default; +$green: $color-2 !default; // Body // @@ -23,10 +23,9 @@ $body-color: $color-4 !default; // // Style anchor elements. -$link-color: $color-3 !default; -$link-decoration: none !default; -$link-hover-color: $color-2 !default; -$link-hover-decoration: none !default; +$link-decoration: none !default; +$link-hover-color: $color-2 !default; +$link-hover-decoration: none !default; // Grid columns // @@ -47,12 +46,12 @@ $font-size-root: 13px !default; $font-weight-normal: 400 !default; $font-weight-bold: 600 !default; -$font-size-h1: $font-size-root + 12 !default; -$font-size-h2: $font-size-root + 10 !default; -$font-size-h3: $font-size-root + 8 !default; -$font-size-h4: $font-size-root + 6 !default; -$font-size-h5: $font-size-root + 4 !default; -$font-size-h6: $font-size-root + 2 !default; +$h1-font-size: $font-size-root + 12 !default; +$h2-font-size: $font-size-root + 10 !default; +$h3-font-size: $font-size-root + 8 !default; +$h4-font-size: $font-size-root + 6 !default; +$h5-font-size: $font-size-root + 4 !default; +$h6-font-size: $font-size-root + 2 !default; $headings-font-weight: $font-weight-bold !default; $headings-color: $color-4 !default; @@ -67,9 +66,9 @@ $border-radius: 3px !default; $input-color: $color-3 !default; $input-border-color: $color-border !default; -$input-border-focus: $color-2 !default; +$input-focus-border-color: $color-2 !default; -$custom-select-focus-border-color: $input-border-focus !default; +$custom-select-focus-border-color: $input-focus-border-color !default; // Dropdowns // @@ -78,10 +77,6 @@ $custom-select-focus-border-color: $input-border-focus !default; $dropdown-link-hover-color: #fff !default; $dropdown-link-hover-bg: $color-3 !default; -// Badges - -$badge-default-bg: $color-7 !default; - // Breadcrumbs $breadcrumb-bg: transparent !default; diff --git a/backend/app/assets/stylesheets/spree/backend/components/_date-picker.scss b/backend/app/assets/stylesheets/spree/backend/components/_date-picker.scss index 5da4054b89b..ae951848a8d 100644 --- a/backend/app/assets/stylesheets/spree/backend/components/_date-picker.scss +++ b/backend/app/assets/stylesheets/spree/backend/components/_date-picker.scss @@ -1,6 +1,6 @@ .date-range-filter { .range-divider { - color: $gray; + color: $gray-800; } } diff --git a/backend/app/assets/stylesheets/spree/backend/components/_messages.scss b/backend/app/assets/stylesheets/spree/backend/components/_messages.scss index b4c644a2cce..1f45e2361c7 100644 --- a/backend/app/assets/stylesheets/spree/backend/components/_messages.scss +++ b/backend/app/assets/stylesheets/spree/backend/components/_messages.scss @@ -1,14 +1,14 @@ .errorExplanation { padding: 5px; - border: 1px solid very-light($brand-danger, 12); - background-color: very-light($brand-danger, 6); + border: 1px solid very-light(theme-color("danger"), 12); + background-color: very-light(theme-color("danger"), 6); border-radius: 3px; - color: very-light($brand-danger, 30); + color: very-light(theme-color("danger"), 30); margin-bottom: 15px; h2 { font-size: 140%; - color: very-light($brand-danger, 30); + color: very-light(theme-color("danger"), 30); margin-bottom: 5px; } @@ -37,9 +37,9 @@ color: $color-1; font-weight: $font-weight-bold; - &.notice { background-color: rgba($brand-warning, 0.8) } - &.success { background-color: rgba($brand-success, 0.8) } - &.error { background-color: rgba($brand-danger, 0.8) } + &.notice { background-color: rgba(theme-color("warning"), 0.8) } + &.success { background-color: rgba(theme-color("success"), 0.8) } + &.error { background-color: rgba(theme-color("danger"), 0.8) } } .alert { @@ -50,5 +50,5 @@ text-decoration: underline; } - &.error a { color: very-light($brand-danger, 10) } + &.error a { color: very-light(theme-color("danger"), 10) } } diff --git a/backend/app/assets/stylesheets/spree/backend/components/_navigation.scss b/backend/app/assets/stylesheets/spree/backend/components/_navigation.scss index 524ac5b0637..2556efca89d 100644 --- a/backend/app/assets/stylesheets/spree/backend/components/_navigation.scss +++ b/backend/app/assets/stylesheets/spree/backend/components/_navigation.scss @@ -28,7 +28,7 @@ nav.menu { .admin-nav { border-right: $border-sidebar; background: $color-sidebar-bg; - z-index: $zindex-navbar; + z-index: $zindex-sticky; } .admin-nav-header { diff --git a/backend/app/assets/stylesheets/spree/backend/components/_number_with_currency.scss b/backend/app/assets/stylesheets/spree/backend/components/_number_with_currency.scss index da3417c553d..aa5a7ed991e 100644 --- a/backend/app/assets/stylesheets/spree/backend/components/_number_with_currency.scss +++ b/backend/app/assets/stylesheets/spree/backend/components/_number_with_currency.scss @@ -17,7 +17,7 @@ border-right: 0; &:focus + .number-with-currency-select { - border-left-color: $input-border-focus; + border-left-color: $input-focus-border-color; } } diff --git a/backend/app/assets/stylesheets/spree/backend/plugins/_bootstrap_tooltip.scss b/backend/app/assets/stylesheets/spree/backend/plugins/_bootstrap_tooltip.scss index 98c8f3b5ee6..4dc9abfd4d2 100644 --- a/backend/app/assets/stylesheets/spree/backend/plugins/_bootstrap_tooltip.scss +++ b/backend/app/assets/stylesheets/spree/backend/plugins/_bootstrap_tooltip.scss @@ -3,30 +3,26 @@ background-color: $color; } - &.tooltip-top, - &.bs-tether-element-attached-bottom { - .tooltip-inner::before { + &.bs-tooltip-top { + .arrow::before { border-top-color: $color; } } - &.tooltip-right, - &.bs-tether-element-attached-left { - .tooltip-inner::before { + &.bs-tooltip-right { + .arrow::before { border-right-color: $color; } } - &.tooltip-bottom, - &.bs-tether-element-attached-top { - .tooltip-inner::before { + &.bs-tooltip-bottom { + .arrow::before { border-bottom-color: $color; } } - &.tooltip-left, - &.bs-tether-element-attached-right { - .tooltip-inner::before { + &.bs-tooltip-left { + .arrow::before { border-left-color: $color; } } @@ -36,12 +32,12 @@ pointer-events: none; &.action-edit, &.action-save, &.action-capture, &.action-add { - @include bootstrap-tooltip-color($brand-success); + @include bootstrap-tooltip-color(theme-color("success")); } &.action-clone, &.action-cancel { - @include bootstrap-tooltip-color($brand-warning); + @include bootstrap-tooltip-color(theme-color("warning")); } &.action-void, &.action-failure, &.action-remove { - @include bootstrap-tooltip-color($brand-danger); + @include bootstrap-tooltip-color(theme-color("danger")); } } diff --git a/backend/app/assets/stylesheets/spree/backend/plugins/_select2.scss b/backend/app/assets/stylesheets/spree/backend/plugins/_select2.scss index c85ebb5985a..3e2ebdbc4ed 100644 --- a/backend/app/assets/stylesheets/spree/backend/plugins/_select2.scss +++ b/backend/app/assets/stylesheets/spree/backend/plugins/_select2.scss @@ -3,7 +3,8 @@ border: $input-btn-border-width solid $input-border-color; @include border-radius($input-border-radius); background: $input-bg; - height: calc(#{$input-height} + #{2*$input-btn-border-width}); + height: $input-height; + padding: 0; .select2-arrow { background: transparent; @@ -17,7 +18,8 @@ } >.select2-chosen { - line-height: $input-height; + padding: $input-btn-padding-y $input-btn-padding-x; + line-height: $input-btn-line-height; color: $input-color; } } @@ -39,7 +41,7 @@ .select2-choices.select2-choices, /* Needs extra specificity */ .select2-choice { box-shadow: none; /* Remove default outline */ - border-color: $input-border-focus; + border-color: $input-focus-border-color; } } @@ -49,7 +51,7 @@ } .select2-search-choice { - background: $badge-default-bg; + background: $gray-200; border: 0; margin: 2px 0 3px 5px; // adjust the margin to respect the adjusted line height } @@ -72,7 +74,7 @@ } .select2-drop-active { - border: $input-btn-border-width solid $input-border-focus; + border: $input-btn-border-width solid $input-focus-border-color; border-top: 0; } diff --git a/backend/app/assets/stylesheets/spree/backend/sections/_orders.scss b/backend/app/assets/stylesheets/spree/backend/sections/_orders.scss index d4c98128b47..5076a42a7bf 100644 --- a/backend/app/assets/stylesheets/spree/backend/sections/_orders.scss +++ b/backend/app/assets/stylesheets/spree/backend/sections/_orders.scss @@ -17,7 +17,7 @@ .order-total { font-size: 35px; font-weight: $font-weight-bold; - color: $brand-success; + color: theme-color("success"); } } @@ -28,7 +28,7 @@ .customer { font-size: 20px; font-weight: $font-weight-bold; - color: $brand-success; + color: theme-color("success"); } } @@ -37,10 +37,10 @@ color: $body-color; .shipment-number { - color: $brand-success; + color: theme-color("success"); } .stock-location-name { - color: $brand-success; + color: theme-color("success"); } } } @@ -83,11 +83,11 @@ form.admin-ship-shipment { table.line-items { input.error { - border-color: $brand-danger; + border-color: theme-color("danger"); } .select2-container.error { border-radius: 4px; - border: 1px solid $brand-danger; + border: 1px solid theme-color("danger"); } } diff --git a/backend/app/assets/stylesheets/spree/backend/sections/_products.scss b/backend/app/assets/stylesheets/spree/backend/sections/_products.scss index bc060bed102..42982ba7c99 100644 --- a/backend/app/assets/stylesheets/spree/backend/sections/_products.scss +++ b/backend/app/assets/stylesheets/spree/backend/sections/_products.scss @@ -48,7 +48,7 @@ div[data-hook="admin_products_index_search_buttons"] { } &.with-images { - border-color: $brand-success; + border-color: theme-color("success"); } } diff --git a/backend/app/assets/stylesheets/spree/backend/sections/_promotions.scss b/backend/app/assets/stylesheets/spree/backend/sections/_promotions.scss index 0c045e8177b..bb6ee05d565 100644 --- a/backend/app/assets/stylesheets/spree/backend/sections/_promotions.scss +++ b/backend/app/assets/stylesheets/spree/backend/sections/_promotions.scss @@ -121,7 +121,7 @@ cursor: pointer; &:hover { - color: $brand-danger; + color: theme-color("danger"); } } } diff --git a/backend/app/assets/stylesheets/spree/backend/sections/_stock_management.scss b/backend/app/assets/stylesheets/spree/backend/sections/_stock_management.scss index 4f057c8430d..5f155691596 100644 --- a/backend/app/assets/stylesheets/spree/backend/sections/_stock_management.scss +++ b/backend/app/assets/stylesheets/spree/backend/sections/_stock_management.scss @@ -31,12 +31,12 @@ } input.error { - border-color: $brand-danger; + border-color: theme-color("danger"); } .select2-container.error { border-radius: 4px; - border: 1px solid $brand-danger; + border: 1px solid theme-color("danger"); } } diff --git a/backend/app/assets/stylesheets/spree/backend/shared/_forms.scss b/backend/app/assets/stylesheets/spree/backend/shared/_forms.scss index d7d496016a1..4abaf6ad7c1 100644 --- a/backend/app/assets/stylesheets/spree/backend/shared/_forms.scss +++ b/backend/app/assets/stylesheets/spree/backend/shared/_forms.scss @@ -8,25 +8,25 @@ input[type="url"], input[type="number"], input[type="tel"], textarea { - padding: $input-padding-y $input-padding-x; + padding: $input-btn-padding-y $input-btn-padding-x; color: $input-color; border: $input-btn-border-width solid $input-border-color; border-radius: $input-border-radius; background: $input-bg; font-size: $font-size-base; - line-height: $input-line-height; + line-height: $input-btn-line-height; &:focus { - border-color: $input-border-focus; + border-color: $input-focus-border-color; outline: 0; } &:disabled { - background: $input-bg-disabled; + background: $input-disabled-bg; } &::placeholder { - color: $input-color-placeholder; + color: $input-placeholder-color; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526. opacity: 1; } @@ -68,7 +68,7 @@ button, .button { &:not(.close) { @extend .btn; - @include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border); + @include button-variant(theme-color("primary"), theme-color("primary")); } &:before { @@ -134,21 +134,21 @@ span.info { &.withError { .field_with_errors { label { - color: very-light($brand-danger, 30); + color: very-light(theme-color("danger"), 30); } input { - border-color: very-light($brand-danger, 15); + border-color: very-light(theme-color("danger"), 15); } } .formError { - color: very-light($brand-danger, 30); + color: very-light(theme-color("danger"), 30); font-style: italic; font-size: 85%; } .select2-container { border-radius: 4px; - border: 1px solid very-light($brand-danger, 15); + border: 1px solid very-light(theme-color("danger"), 15); } } } diff --git a/backend/app/assets/stylesheets/spree/backend/shared/_header.scss b/backend/app/assets/stylesheets/spree/backend/shared/_header.scss index d2943177bc6..e6144fdddbb 100644 --- a/backend/app/assets/stylesheets/spree/backend/shared/_header.scss +++ b/backend/app/assets/stylesheets/spree/backend/shared/_header.scss @@ -1,7 +1,7 @@ .main-header { display: flex; align-items: center; - padding: 15px map-get($grid-gutter-widths, "xl"); + padding: 15px $grid-gutter-width; background-color: very-light($color-3, 4); border-bottom: 1px solid $color-border; height: $main-header-height; diff --git a/backend/app/assets/stylesheets/spree/backend/shared/_layout.scss b/backend/app/assets/stylesheets/spree/backend/shared/_layout.scss index 3c60c2ee307..8d8ab3cc72a 100644 --- a/backend/app/assets/stylesheets/spree/backend/shared/_layout.scss +++ b/backend/app/assets/stylesheets/spree/backend/shared/_layout.scss @@ -15,7 +15,7 @@ body { } .content-wrapper { - @include padding(1rem map-get($grid-gutter-widths, "xl") null); + @include padding(1rem $grid-gutter-width null); &:not(.full-width) { @include margin(null auto); diff --git a/backend/app/assets/stylesheets/spree/backend/shared/_tables.scss b/backend/app/assets/stylesheets/spree/backend/shared/_tables.scss index de3d6a8ff44..25228a18c6b 100644 --- a/backend/app/assets/stylesheets/spree/backend/shared/_tables.scss +++ b/backend/app/assets/stylesheets/spree/backend/shared/_tables.scss @@ -74,27 +74,27 @@ table { } .fa-trash:hover, .fa-void:hover, .fa-failure:hover { - color: $brand-danger; + color: theme-color("danger"); } .fa-cancel:hover { - color: $brand-warning; + color: theme-color("warning"); } .fa-edit:hover, .fa-capture:hover, .fa-ok:hover, .fa-plus:hover, .fa-save:hover { - color: $brand-success; + color: theme-color("success"); } .fa-copy:hover { - color: $brand-warning; + color: theme-color("warning"); } .fa-thumbs-up:hover { - color: $brand-success; + color: theme-color("success"); } .fa-thumbs-down:hover { - color: $brand-danger; + color: theme-color("danger"); } } @@ -159,8 +159,8 @@ table { } &.deleted td { - background-color: very-light($brand-danger, 6); - border-color: very-light($brand-danger, 15); + background-color: very-light(theme-color("danger"), 6); + border-color: very-light(theme-color("danger"), 15); } &.ui-sortable-placeholder td { diff --git a/backend/app/assets/stylesheets/spree/backend/shared/_typography.scss b/backend/app/assets/stylesheets/spree/backend/shared/_typography.scss index bde43997137..3ecd2ec3479 100644 --- a/backend/app/assets/stylesheets/spree/backend/shared/_typography.scss +++ b/backend/app/assets/stylesheets/spree/backend/shared/_typography.scss @@ -20,12 +20,12 @@ hr { // Headings //-------------------------------------------------------------- -h1 { line-height: $font-size-h1 + 6 } -h2 { line-height: $font-size-h1 + 4 } -h3 { line-height: $font-size-h1 + 2 } -h4 { line-height: $font-size-h1 } -h5 { line-height: $font-size-h1 } -h6 { line-height: $font-size-h1 } +h1 { line-height: $h1-font-size + 6 } +h2 { line-height: $h1-font-size + 4 } +h3 { line-height: $h1-font-size + 2 } +h4 { line-height: $h1-font-size } +h5 { line-height: $h1-font-size } +h6 { line-height: $h1-font-size } // Lists diff --git a/backend/lib/spree/backend.rb b/backend/lib/spree/backend.rb index ab59e90ef0f..25da78fd501 100644 --- a/backend/lib/spree/backend.rb +++ b/backend/lib/spree/backend.rb @@ -6,6 +6,7 @@ require 'bourbon' require 'handlebars_assets' require 'font-awesome-rails' +require 'autoprefixer-rails' require 'jbuilder' require 'spree_core' diff --git a/backend/solidus_backend.gemspec b/backend/solidus_backend.gemspec index 1c24c789d9d..852faab1c63 100644 --- a/backend/solidus_backend.gemspec +++ b/backend/solidus_backend.gemspec @@ -34,4 +34,5 @@ Gem::Specification.new do |s| s.add_dependency 'jbuilder', '~> 2.6' s.add_dependency 'handlebars_assets', '~> 0.23' + s.add_dependency 'autoprefixer-rails', '~> 7.1' end diff --git a/backend/vendor/assets/javascripts/solidus_admin/bootstrap.js b/backend/vendor/assets/javascripts/solidus_admin/bootstrap.js index 25687733265..7597fb3280b 100644 --- a/backend/vendor/assets/javascripts/solidus_admin/bootstrap.js +++ b/backend/vendor/assets/javascripts/solidus_admin/bootstrap.js @@ -1,5 +1,5 @@ /*! - * Bootstrap v4.0.0-alpha.6 (https://getbootstrap.com) + * Bootstrap v4.0.0-beta (https://getbootstrap.com) * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ @@ -8,16 +8,14 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.') } -+function ($) { +(function ($) { var version = $.fn.jquery.split(' ')[0].split('.') if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) { throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0') } -}(jQuery); - - -+function () { +})(jQuery); +(function () { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); @@ -30,7 +28,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.6): util.js + * Bootstrap (v4.0.0-beta): util.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -52,10 +50,9 @@ var Util = function ($) { MozTransition: 'transitionend', OTransition: 'oTransitionEnd otransitionend', transition: 'transitionend' - }; - // shoutout AngusCroll (https://goo.gl/pxwQGp) - function toType(obj) { + // shoutout AngusCroll (https://goo.gl/pxwQGp) + };function toType(obj) { return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } @@ -141,13 +138,16 @@ var Util = function ($) { }, getSelectorFromElement: function getSelectorFromElement(element) { var selector = element.getAttribute('data-target'); - - if (!selector) { + if (!selector || selector === '#') { selector = element.getAttribute('href') || ''; - selector = /^#[a-z]/i.test(selector) ? selector : null; } - return selector; + try { + var $selector = $(selector); + return $selector.length > 0 ? selector : null; + } catch (error) { + return null; + } }, reflow: function reflow(element) { return element.offsetHeight; @@ -180,7 +180,7 @@ var Util = function ($) { /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.6): alert.js + * Bootstrap (v4.0.0-beta): alert.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -194,7 +194,7 @@ var Alert = function ($) { */ var NAME = 'alert'; - var VERSION = '4.0.0-alpha.6'; + var VERSION = '4.0.0-beta'; var DATA_KEY = 'bs.alert'; var EVENT_KEY = '.' + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -215,14 +215,14 @@ var Alert = function ($) { ALERT: 'alert', FADE: 'fade', SHOW: 'show' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + }; var Alert = function () { function Alert(element) { _classCallCheck(this, Alert); @@ -359,7 +359,7 @@ var Alert = function ($) { /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.6): button.js + * Bootstrap (v4.0.0-beta): button.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -373,7 +373,7 @@ var Button = function ($) { */ var NAME = 'button'; - var VERSION = '4.0.0-alpha.6'; + var VERSION = '4.0.0-beta'; var DATA_KEY = 'bs.button'; var EVENT_KEY = '.' + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -396,14 +396,14 @@ var Button = function ($) { var Event = { CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY, FOCUS_BLUR_DATA_API: 'focus' + EVENT_KEY + DATA_API_KEY + ' ' + ('blur' + EVENT_KEY + DATA_API_KEY) - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + }; var Button = function () { function Button(element) { _classCallCheck(this, Button); @@ -417,6 +417,7 @@ var Button = function ($) { Button.prototype.toggle = function toggle() { var triggerChangeEvent = true; + var addAriaPressed = true; var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0]; if (rootElement) { @@ -436,15 +437,21 @@ var Button = function ($) { } if (triggerChangeEvent) { + if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) { + return; + } input.checked = !$(this._element).hasClass(ClassName.ACTIVE); $(input).trigger('change'); } input.focus(); + addAriaPressed = false; } } - this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE)); + if (addAriaPressed) { + this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE)); + } if (triggerChangeEvent) { $(this._element).toggleClass(ClassName.ACTIVE); @@ -522,7 +529,7 @@ var Button = function ($) { /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.6): carousel.js + * Bootstrap (v4.0.0-beta): carousel.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -536,7 +543,7 @@ var Carousel = function ($) { */ var NAME = 'carousel'; - var VERSION = '4.0.0-alpha.6'; + var VERSION = '4.0.0-beta'; var DATA_KEY = 'bs.carousel'; var EVENT_KEY = '.' + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -544,6 +551,7 @@ var Carousel = function ($) { var TRANSITION_DURATION = 600; var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key + var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch var Default = { interval: 5000, @@ -574,6 +582,7 @@ var Carousel = function ($) { KEYDOWN: 'keydown' + EVENT_KEY, MOUSEENTER: 'mouseenter' + EVENT_KEY, MOUSELEAVE: 'mouseleave' + EVENT_KEY, + TOUCHEND: 'touchend' + EVENT_KEY, LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY, CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY }; @@ -597,14 +606,14 @@ var Carousel = function ($) { INDICATORS: '.carousel-indicators', DATA_SLIDE: '[data-slide], [data-slide-to]', DATA_RIDE: '[data-ride="carousel"]' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + }; var Carousel = function () { function Carousel(element, config) { _classCallCheck(this, Carousel); @@ -616,6 +625,8 @@ var Carousel = function ($) { this._isPaused = false; this._isSliding = false; + this.touchTimeout = null; + this._config = this._getConfig(config); this._element = $(element)[0]; this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0]; @@ -628,10 +639,9 @@ var Carousel = function ($) { // public Carousel.prototype.next = function next() { - if (this._isSliding) { - throw new Error('Carousel is sliding'); + if (!this._isSliding) { + this._slide(Direction.NEXT); } - this._slide(Direction.NEXT); }; Carousel.prototype.nextWhenVisible = function nextWhenVisible() { @@ -642,10 +652,9 @@ var Carousel = function ($) { }; Carousel.prototype.prev = function prev() { - if (this._isSliding) { - throw new Error('Carousel is sliding'); + if (!this._isSliding) { + this._slide(Direction.PREV); } - this._slide(Direction.PREVIOUS); }; Carousel.prototype.pause = function pause(event) { @@ -701,7 +710,7 @@ var Carousel = function ($) { return; } - var direction = index > activeIndex ? Direction.NEXT : Direction.PREVIOUS; + var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; this._slide(direction, this._items[index]); }; @@ -737,12 +746,30 @@ var Carousel = function ($) { }); } - if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) { + if (this._config.pause === 'hover') { $(this._element).on(Event.MOUSEENTER, function (event) { return _this4.pause(event); }).on(Event.MOUSELEAVE, function (event) { return _this4.cycle(event); }); + if ('ontouchstart' in document.documentElement) { + // if it's a touch-enabled device, mouseenter/leave are fired as + // part of the mouse compatibility events on first tap - the carousel + // would stop cycling until user tapped out of it; + // here, we listen for touchend, explicitly pause the carousel + // (as if it's the second time we tap on it, mouseenter compat event + // is NOT fired) and after a timeout (to allow for mouse compatibility + // events to fire) we explicitly restart cycling + $(this._element).on(Event.TOUCHEND, function () { + _this4.pause(); + if (_this4.touchTimeout) { + clearTimeout(_this4.touchTimeout); + } + _this4.touchTimeout = setTimeout(function (event) { + return _this4.cycle(event); + }, TOUCHEVENT_COMPAT_WAIT + _this4._config.interval); + }); + } } }; @@ -772,7 +799,7 @@ var Carousel = function ($) { Carousel.prototype._getItemByDirection = function _getItemByDirection(direction, activeElement) { var isNextDirection = direction === Direction.NEXT; - var isPrevDirection = direction === Direction.PREVIOUS; + var isPrevDirection = direction === Direction.PREV; var activeIndex = this._getItemIndex(activeElement); var lastItemIndex = this._items.length - 1; var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex; @@ -781,16 +808,20 @@ var Carousel = function ($) { return activeElement; } - var delta = direction === Direction.PREVIOUS ? -1 : 1; + var delta = direction === Direction.PREV ? -1 : 1; var itemIndex = (activeIndex + delta) % this._items.length; return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex]; }; Carousel.prototype._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { + var targetIndex = this._getItemIndex(relatedTarget); + var fromIndex = this._getItemIndex($(this._element).find(Selector.ACTIVE_ITEM)[0]); var slideEvent = $.Event(Event.SLIDE, { relatedTarget: relatedTarget, - direction: eventDirectionName + direction: eventDirectionName, + from: fromIndex, + to: targetIndex }); $(this._element).trigger(slideEvent); @@ -814,8 +845,9 @@ var Carousel = function ($) { var _this5 = this; var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0]; + var activeElementIndex = this._getItemIndex(activeElement); var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement); - + var nextElementIndex = this._getItemIndex(nextElement); var isCycling = Boolean(this._interval); var directionalClassName = void 0; @@ -857,7 +889,9 @@ var Carousel = function ($) { var slidEvent = $.Event(Event.SLID, { relatedTarget: nextElement, - direction: eventDirectionName + direction: eventDirectionName, + from: activeElementIndex, + to: nextElementIndex }); if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) { @@ -1002,7 +1036,7 @@ var Carousel = function ($) { /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.6): collapse.js + * Bootstrap (v4.0.0-beta): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -1016,7 +1050,7 @@ var Collapse = function ($) { */ var NAME = 'collapse'; - var VERSION = '4.0.0-alpha.6'; + var VERSION = '4.0.0-beta'; var DATA_KEY = 'bs.collapse'; var EVENT_KEY = '.' + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -1054,16 +1088,16 @@ var Collapse = function ($) { }; var Selector = { - ACTIVES: '.card > .show, .card > .collapsing', + ACTIVES: '.show, .collapsing', DATA_TOGGLE: '[data-toggle="collapse"]' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + }; var Collapse = function () { function Collapse(element, config) { _classCallCheck(this, Collapse); @@ -1072,6 +1106,14 @@ var Collapse = function ($) { this._element = element; this._config = this._getConfig(config); this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]'))); + var tabToggles = $(Selector.DATA_TOGGLE); + for (var i = 0; i < tabToggles.length; i++) { + var elem = tabToggles[i]; + var selector = Util.getSelectorFromElement(elem); + if (selector !== null && $(selector).filter(element).length > 0) { + this._triggerArray.push(elem); + } + } this._parent = this._config.parent ? this._getParent() : null; @@ -1099,11 +1141,7 @@ var Collapse = function ($) { Collapse.prototype.show = function show() { var _this6 = this; - if (this._isTransitioning) { - throw new Error('Collapse is transitioning'); - } - - if ($(this._element).hasClass(ClassName.SHOW)) { + if (this._isTransitioning || $(this._element).hasClass(ClassName.SHOW)) { return; } @@ -1111,7 +1149,7 @@ var Collapse = function ($) { var activesData = void 0; if (this._parent) { - actives = $.makeArray($(this._parent).find(Selector.ACTIVES)); + actives = $.makeArray($(this._parent).children().children(Selector.ACTIVES)); if (!actives.length) { actives = null; } @@ -1142,7 +1180,6 @@ var Collapse = function ($) { $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); this._element.style[dimension] = 0; - this._element.setAttribute('aria-expanded', true); if (this._triggerArray.length) { $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); @@ -1176,11 +1213,7 @@ var Collapse = function ($) { Collapse.prototype.hide = function hide() { var _this7 = this; - if (this._isTransitioning) { - throw new Error('Collapse is transitioning'); - } - - if (!$(this._element).hasClass(ClassName.SHOW)) { + if (this._isTransitioning || !$(this._element).hasClass(ClassName.SHOW)) { return; } @@ -1191,18 +1224,24 @@ var Collapse = function ($) { } var dimension = this._getDimension(); - var offsetDimension = dimension === Dimension.WIDTH ? 'offsetWidth' : 'offsetHeight'; - this._element.style[dimension] = this._element[offsetDimension] + 'px'; + this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + 'px'; Util.reflow(this._element); $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); - this._element.setAttribute('aria-expanded', false); - if (this._triggerArray.length) { - $(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); + for (var i = 0; i < this._triggerArray.length; i++) { + var trigger = this._triggerArray[i]; + var selector = Util.getSelectorFromElement(trigger); + if (selector !== null) { + var $elem = $(selector); + if (!$elem.hasClass(ClassName.SHOW)) { + $(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); + } + } + } } this.setTransitioning(true); @@ -1266,7 +1305,6 @@ var Collapse = function ($) { Collapse.prototype._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) { if (element) { var isOpen = $(element).hasClass(ClassName.SHOW); - element.setAttribute('aria-expanded', isOpen); if (triggerArray.length) { $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); @@ -1327,13 +1365,18 @@ var Collapse = function ($) { */ $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { - event.preventDefault(); - - var target = Collapse._getTargetFromElement(this); - var data = $(target).data(DATA_KEY); - var config = data ? 'toggle' : $(this).data(); + if (!/input|textarea/i.test(event.target.tagName)) { + event.preventDefault(); + } - Collapse._jQueryInterface.call($(target), config); + var $trigger = $(this); + var selector = Util.getSelectorFromElement(this); + $(selector).each(function () { + var $target = $(this); + var data = $target.data(DATA_KEY); + var config = data ? 'toggle' : $trigger.data(); + Collapse._jQueryInterface.call($target, config); + }); }); /** @@ -1352,15 +1395,25 @@ var Collapse = function ($) { return Collapse; }(jQuery); +/* global Popper */ + /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.6): dropdown.js + * Bootstrap (v4.0.0-beta): dropdown.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Dropdown = function ($) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)'); + } + /** * ------------------------------------------------------------------------ * Constants @@ -1368,15 +1421,18 @@ var Dropdown = function ($) { */ var NAME = 'dropdown'; - var VERSION = '4.0.0-alpha.6'; + var VERSION = '4.0.0-beta'; var DATA_KEY = 'bs.dropdown'; var EVENT_KEY = '.' + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $.fn[NAME]; var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key + var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) + var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + '|' + ARROW_DOWN_KEYCODE + '|' + ESCAPE_KEYCODE); var Event = { HIDE: 'hide' + EVENT_KEY, @@ -1385,37 +1441,60 @@ var Dropdown = function ($) { SHOWN: 'shown' + EVENT_KEY, CLICK: 'click' + EVENT_KEY, CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY, - FOCUSIN_DATA_API: 'focusin' + EVENT_KEY + DATA_API_KEY, - KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY + KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY, + KEYUP_DATA_API: 'keyup' + EVENT_KEY + DATA_API_KEY }; var ClassName = { - BACKDROP: 'dropdown-backdrop', DISABLED: 'disabled', - SHOW: 'show' + SHOW: 'show', + DROPUP: 'dropup', + MENURIGHT: 'dropdown-menu-right', + MENULEFT: 'dropdown-menu-left' }; var Selector = { - BACKDROP: '.dropdown-backdrop', DATA_TOGGLE: '[data-toggle="dropdown"]', FORM_CHILD: '.dropdown form', - ROLE_MENU: '[role="menu"]', - ROLE_LISTBOX: '[role="listbox"]', + MENU: '.dropdown-menu', NAVBAR_NAV: '.navbar-nav', - VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a' + VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled)' }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + var AttachmentMap = { + TOP: 'top-start', + TOPEND: 'top-end', + BOTTOM: 'bottom-start', + BOTTOMEND: 'bottom-end' + }; + + var Default = { + placement: AttachmentMap.BOTTOM, + offset: 0, + flip: true + }; + + var DefaultType = { + placement: 'string', + offset: '(number|string)', + flip: 'boolean' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; var Dropdown = function () { - function Dropdown(element) { + function Dropdown(element, config) { _classCallCheck(this, Dropdown); this._element = element; + this._popper = null; + this._config = this._getConfig(config); + this._menu = this._getMenuElement(); + this._inNavbar = this._detectNavbar(); this._addEventListeners(); } @@ -1425,58 +1504,144 @@ var Dropdown = function ($) { // public Dropdown.prototype.toggle = function toggle() { - if (this.disabled || $(this).hasClass(ClassName.DISABLED)) { - return false; + if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) { + return; } - var parent = Dropdown._getParentFromElement(this); - var isActive = $(parent).hasClass(ClassName.SHOW); + var parent = Dropdown._getParentFromElement(this._element); + var isActive = $(this._menu).hasClass(ClassName.SHOW); Dropdown._clearMenus(); if (isActive) { - return false; - } - - if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) { - - // if mobile we use a backdrop because click events don't delegate - var dropdown = document.createElement('div'); - dropdown.className = ClassName.BACKDROP; - $(dropdown).insertBefore(this); - $(dropdown).on('click', Dropdown._clearMenus); + return; } var relatedTarget = { - relatedTarget: this + relatedTarget: this._element }; var showEvent = $.Event(Event.SHOW, relatedTarget); $(parent).trigger(showEvent); if (showEvent.isDefaultPrevented()) { - return false; + return; } - this.focus(); - this.setAttribute('aria-expanded', true); + var element = this._element; + // for dropup with alignment we use the parent as popper container + if ($(parent).hasClass(ClassName.DROPUP)) { + if ($(this._menu).hasClass(ClassName.MENULEFT) || $(this._menu).hasClass(ClassName.MENURIGHT)) { + element = parent; + } + } + this._popper = new Popper(element, this._menu, this._getPopperConfig()); + + // if this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) { + $('body').children().on('mouseover', null, $.noop); + } - $(parent).toggleClass(ClassName.SHOW); - $(parent).trigger($.Event(Event.SHOWN, relatedTarget)); + this._element.focus(); + this._element.setAttribute('aria-expanded', true); - return false; + $(this._menu).toggleClass(ClassName.SHOW); + $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget)); }; Dropdown.prototype.dispose = function dispose() { $.removeData(this._element, DATA_KEY); $(this._element).off(EVENT_KEY); this._element = null; + this._menu = null; + if (this._popper !== null) { + this._popper.destroy(); + } + this._popper = null; + }; + + Dropdown.prototype.update = function update() { + this._inNavbar = this._detectNavbar(); + if (this._popper !== null) { + this._popper.scheduleUpdate(); + } }; // private Dropdown.prototype._addEventListeners = function _addEventListeners() { - $(this._element).on(Event.CLICK, this.toggle); + var _this9 = this; + + $(this._element).on(Event.CLICK, function (event) { + event.preventDefault(); + event.stopPropagation(); + _this9.toggle(); + }); + }; + + Dropdown.prototype._getConfig = function _getConfig(config) { + var elementData = $(this._element).data(); + if (elementData.placement !== undefined) { + elementData.placement = AttachmentMap[elementData.placement.toUpperCase()]; + } + + config = $.extend({}, this.constructor.Default, $(this._element).data(), config); + + Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); + + return config; + }; + + Dropdown.prototype._getMenuElement = function _getMenuElement() { + if (!this._menu) { + var parent = Dropdown._getParentFromElement(this._element); + this._menu = $(parent).find(Selector.MENU)[0]; + } + return this._menu; + }; + + Dropdown.prototype._getPlacement = function _getPlacement() { + var $parentDropdown = $(this._element).parent(); + var placement = this._config.placement; + + // Handle dropup + if ($parentDropdown.hasClass(ClassName.DROPUP) || this._config.placement === AttachmentMap.TOP) { + placement = AttachmentMap.TOP; + if ($(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.TOPEND; + } + } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.BOTTOMEND; + } + return placement; + }; + + Dropdown.prototype._detectNavbar = function _detectNavbar() { + return $(this._element).closest('.navbar').length > 0; + }; + + Dropdown.prototype._getPopperConfig = function _getPopperConfig() { + var popperConfig = { + placement: this._getPlacement(), + modifiers: { + offset: { + offset: this._config.offset + }, + flip: { + enabled: this._config.flip + } + } + + // Disable Popper.js for Dropdown in Navbar + };if (this._inNavbar) { + popperConfig.modifiers.applyStyle = { + enabled: !this._inNavbar + }; + } + return popperConfig; }; // static @@ -1484,9 +1649,10 @@ var Dropdown = function ($) { Dropdown._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $(this).data(DATA_KEY); + var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null; if (!data) { - data = new Dropdown(this); + data = new Dropdown(this, _config); $(this).data(DATA_KEY, data); } @@ -1494,34 +1660,34 @@ var Dropdown = function ($) { if (data[config] === undefined) { throw new Error('No method named "' + config + '"'); } - data[config].call(this); + data[config](); } }); }; Dropdown._clearMenus = function _clearMenus(event) { - if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) { + if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { return; } - var backdrop = $(Selector.BACKDROP)[0]; - if (backdrop) { - backdrop.parentNode.removeChild(backdrop); - } - var toggles = $.makeArray($(Selector.DATA_TOGGLE)); - for (var i = 0; i < toggles.length; i++) { var parent = Dropdown._getParentFromElement(toggles[i]); + var context = $(toggles[i]).data(DATA_KEY); var relatedTarget = { relatedTarget: toggles[i] }; + if (!context) { + continue; + } + + var dropdownMenu = context._menu; if (!$(parent).hasClass(ClassName.SHOW)) { continue; } - if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'focusin') && $.contains(parent, event.target)) { + if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) { continue; } @@ -1531,8 +1697,15 @@ var Dropdown = function ($) { continue; } + // if this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + if ('ontouchstart' in document.documentElement) { + $('body').children().off('mouseover', null, $.noop); + } + toggles[i].setAttribute('aria-expanded', 'false'); + $(dropdownMenu).removeClass(ClassName.SHOW); $(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget)); } }; @@ -1549,7 +1722,7 @@ var Dropdown = function ($) { }; Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { - if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) { + if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE || /input|textarea/i.test(event.target.tagName)) { return; } @@ -1563,7 +1736,7 @@ var Dropdown = function ($) { var parent = Dropdown._getParentFromElement(this); var isActive = $(parent).hasClass(ClassName.SHOW); - if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) { + if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { if (event.which === ESCAPE_KEYCODE) { var toggle = $(parent).find(Selector.DATA_TOGGLE)[0]; @@ -1604,6 +1777,16 @@ var Dropdown = function ($) { get: function get() { return VERSION; } + }, { + key: 'Default', + get: function get() { + return Default; + } + }, { + key: 'DefaultType', + get: function get() { + return DefaultType; + } }]); return Dropdown; @@ -1615,7 +1798,11 @@ var Dropdown = function ($) { * ------------------------------------------------------------------------ */ - $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + ' ' + Event.FOCUSIN_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) { + $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + ' ' + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + event.preventDefault(); + event.stopPropagation(); + Dropdown._jQueryInterface.call($(this), 'toggle'); + }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) { e.stopPropagation(); }); @@ -1637,7 +1824,7 @@ var Dropdown = function ($) { /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.6): modal.js + * Bootstrap (v4.0.0-beta): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -1651,7 +1838,7 @@ var Modal = function ($) { */ var NAME = 'modal'; - var VERSION = '4.0.0-alpha.6'; + var VERSION = '4.0.0-beta'; var DATA_KEY = 'bs.modal'; var EVENT_KEY = '.' + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -1700,15 +1887,16 @@ var Modal = function ($) { DIALOG: '.modal-dialog', DATA_TOGGLE: '[data-toggle="modal"]', DATA_DISMISS: '[data-dismiss="modal"]', - FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top' - }; + FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', + NAVBAR_TOGGLER: '.navbar-toggler' - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + }; var Modal = function () { function Modal(element, config) { _classCallCheck(this, Modal); @@ -1720,7 +1908,6 @@ var Modal = function ($) { this._isShown = false; this._isBodyOverflowing = false; this._ignoreBackdropClick = false; - this._isTransitioning = false; this._originalBodyPadding = 0; this._scrollbarWidth = 0; } @@ -1734,15 +1921,16 @@ var Modal = function ($) { }; Modal.prototype.show = function show(relatedTarget) { - var _this9 = this; + var _this10 = this; if (this._isTransitioning) { - throw new Error('Modal is transitioning'); + return; } if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) { this._isTransitioning = true; } + var showEvent = $.Event(Event.SHOW, { relatedTarget: relatedTarget }); @@ -1764,39 +1952,41 @@ var Modal = function ($) { this._setResizeEvent(); $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) { - return _this9.hide(event); + return _this10.hide(event); }); $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () { - $(_this9._element).one(Event.MOUSEUP_DISMISS, function (event) { - if ($(event.target).is(_this9._element)) { - _this9._ignoreBackdropClick = true; + $(_this10._element).one(Event.MOUSEUP_DISMISS, function (event) { + if ($(event.target).is(_this10._element)) { + _this10._ignoreBackdropClick = true; } }); }); this._showBackdrop(function () { - return _this9._showElement(relatedTarget); + return _this10._showElement(relatedTarget); }); }; Modal.prototype.hide = function hide(event) { - var _this10 = this; + var _this11 = this; if (event) { event.preventDefault(); } - if (this._isTransitioning) { - throw new Error('Modal is transitioning'); + if (this._isTransitioning || !this._isShown) { + return; } var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE); + if (transition) { this._isTransitioning = true; } var hideEvent = $.Event(Event.HIDE); + $(this._element).trigger(hideEvent); if (!this._isShown || hideEvent.isDefaultPrevented()) { @@ -1816,8 +2006,9 @@ var Modal = function ($) { $(this._dialog).off(Event.MOUSEDOWN_DISMISS); if (transition) { + $(this._element).one(Util.TRANSITION_END, function (event) { - return _this10._hideModal(event); + return _this11._hideModal(event); }).emulateTransitionEnd(TRANSITION_DURATION); } else { this._hideModal(); @@ -1836,10 +2027,13 @@ var Modal = function ($) { this._isShown = null; this._isBodyOverflowing = null; this._ignoreBackdropClick = null; - this._originalBodyPadding = null; this._scrollbarWidth = null; }; + Modal.prototype.handleUpdate = function handleUpdate() { + this._adjustDialog(); + }; + // private Modal.prototype._getConfig = function _getConfig(config) { @@ -1849,7 +2043,7 @@ var Modal = function ($) { }; Modal.prototype._showElement = function _showElement(relatedTarget) { - var _this11 = this; + var _this12 = this; var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE); @@ -1877,11 +2071,11 @@ var Modal = function ($) { }); var transitionComplete = function transitionComplete() { - if (_this11._config.focus) { - _this11._element.focus(); + if (_this12._config.focus) { + _this12._element.focus(); } - _this11._isTransitioning = false; - $(_this11._element).trigger(shownEvent); + _this12._isTransitioning = false; + $(_this12._element).trigger(shownEvent); }; if (transition) { @@ -1892,23 +2086,24 @@ var Modal = function ($) { }; Modal.prototype._enforceFocus = function _enforceFocus() { - var _this12 = this; + var _this13 = this; $(document).off(Event.FOCUSIN) // guard against infinite focus loop .on(Event.FOCUSIN, function (event) { - if (document !== event.target && _this12._element !== event.target && !$(_this12._element).has(event.target).length) { - _this12._element.focus(); + if (document !== event.target && _this13._element !== event.target && !$(_this13._element).has(event.target).length) { + _this13._element.focus(); } }); }; Modal.prototype._setEscapeEvent = function _setEscapeEvent() { - var _this13 = this; + var _this14 = this; if (this._isShown && this._config.keyboard) { $(this._element).on(Event.KEYDOWN_DISMISS, function (event) { if (event.which === ESCAPE_KEYCODE) { - _this13.hide(); + event.preventDefault(); + _this14.hide(); } }); } else if (!this._isShown) { @@ -1917,11 +2112,11 @@ var Modal = function ($) { }; Modal.prototype._setResizeEvent = function _setResizeEvent() { - var _this14 = this; + var _this15 = this; if (this._isShown) { $(window).on(Event.RESIZE, function (event) { - return _this14._handleUpdate(event); + return _this15.handleUpdate(event); }); } else { $(window).off(Event.RESIZE); @@ -1929,16 +2124,16 @@ var Modal = function ($) { }; Modal.prototype._hideModal = function _hideModal() { - var _this15 = this; + var _this16 = this; this._element.style.display = 'none'; - this._element.setAttribute('aria-hidden', 'true'); + this._element.setAttribute('aria-hidden', true); this._isTransitioning = false; this._showBackdrop(function () { $(document.body).removeClass(ClassName.OPEN); - _this15._resetAdjustments(); - _this15._resetScrollbar(); - $(_this15._element).trigger(Event.HIDDEN); + _this16._resetAdjustments(); + _this16._resetScrollbar(); + $(_this16._element).trigger(Event.HIDDEN); }); }; @@ -1950,7 +2145,7 @@ var Modal = function ($) { }; Modal.prototype._showBackdrop = function _showBackdrop(callback) { - var _this16 = this; + var _this17 = this; var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : ''; @@ -1967,17 +2162,17 @@ var Modal = function ($) { $(this._backdrop).appendTo(document.body); $(this._element).on(Event.CLICK_DISMISS, function (event) { - if (_this16._ignoreBackdropClick) { - _this16._ignoreBackdropClick = false; + if (_this17._ignoreBackdropClick) { + _this17._ignoreBackdropClick = false; return; } if (event.target !== event.currentTarget) { return; } - if (_this16._config.backdrop === 'static') { - _this16._element.focus(); + if (_this17._config.backdrop === 'static') { + _this17._element.focus(); } else { - _this16.hide(); + _this17.hide(); } }); @@ -2001,7 +2196,7 @@ var Modal = function ($) { $(this._backdrop).removeClass(ClassName.SHOW); var callbackRemove = function callbackRemove() { - _this16._removeBackdrop(); + _this17._removeBackdrop(); if (callback) { callback(); } @@ -2022,10 +2217,6 @@ var Modal = function ($) { // todo (fat): these should probably be refactored out of modal.js // ---------------------------------------------------------------------- - Modal.prototype._handleUpdate = function _handleUpdate() { - this._adjustDialog(); - }; - Modal.prototype._adjustDialog = function _adjustDialog() { var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; @@ -2049,17 +2240,55 @@ var Modal = function ($) { }; Modal.prototype._setScrollbar = function _setScrollbar() { - var bodyPadding = parseInt($(Selector.FIXED_CONTENT).css('padding-right') || 0, 10); - - this._originalBodyPadding = document.body.style.paddingRight || ''; + var _this18 = this; if (this._isBodyOverflowing) { - document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px'; + // Note: DOMNode.style.paddingRight returns the actual value or '' if not set + // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set + + // Adjust fixed content padding + $(Selector.FIXED_CONTENT).each(function (index, element) { + var actualPadding = $(element)[0].style.paddingRight; + var calculatedPadding = $(element).css('padding-right'); + $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this18._scrollbarWidth + 'px'); + }); + + // Adjust navbar-toggler margin + $(Selector.NAVBAR_TOGGLER).each(function (index, element) { + var actualMargin = $(element)[0].style.marginRight; + var calculatedMargin = $(element).css('margin-right'); + $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) + _this18._scrollbarWidth + 'px'); + }); + + // Adjust body padding + var actualPadding = document.body.style.paddingRight; + var calculatedPadding = $('body').css('padding-right'); + $('body').data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + 'px'); } }; Modal.prototype._resetScrollbar = function _resetScrollbar() { - document.body.style.paddingRight = this._originalBodyPadding; + // Restore fixed content padding + $(Selector.FIXED_CONTENT).each(function (index, element) { + var padding = $(element).data('padding-right'); + if (typeof padding !== 'undefined') { + $(element).css('padding-right', padding).removeData('padding-right'); + } + }); + + // Restore navbar-toggler margin + $(Selector.NAVBAR_TOGGLER).each(function (index, element) { + var margin = $(element).data('margin-right'); + if (typeof margin !== 'undefined') { + $(element).css('margin-right', margin).removeData('margin-right'); + } + }); + + // Restore body padding + var padding = $('body').data('padding-right'); + if (typeof padding !== 'undefined') { + $('body').css('padding-right', padding).removeData('padding-right'); + } }; Modal.prototype._getScrollbarWidth = function _getScrollbarWidth() { @@ -2067,7 +2296,7 @@ var Modal = function ($) { var scrollDiv = document.createElement('div'); scrollDiv.className = ClassName.SCROLLBAR_MEASURER; document.body.appendChild(scrollDiv); - var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; document.body.removeChild(scrollDiv); return scrollbarWidth; }; @@ -2117,7 +2346,7 @@ var Modal = function ($) { */ $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { - var _this17 = this; + var _this19 = this; var target = void 0; var selector = Util.getSelectorFromElement(this); @@ -2139,8 +2368,8 @@ var Modal = function ($) { } $target.one(Event.HIDDEN, function () { - if ($(_this17).is(':visible')) { - _this17.focus(); + if ($(_this19).is(':visible')) { + _this19.focus(); } }); }); @@ -2166,7 +2395,7 @@ var Modal = function ($) { /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.6): scrollspy.js + * Bootstrap (v4.0.0-beta): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -2180,7 +2409,7 @@ var ScrollSpy = function ($) { */ var NAME = 'scrollspy'; - var VERSION = '4.0.0-alpha.6'; + var VERSION = '4.0.0-beta'; var DATA_KEY = 'bs.scrollspy'; var EVENT_KEY = '.' + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -2207,18 +2436,15 @@ var ScrollSpy = function ($) { var ClassName = { DROPDOWN_ITEM: 'dropdown-item', DROPDOWN_MENU: 'dropdown-menu', - NAV_LINK: 'nav-link', - NAV: 'nav', ACTIVE: 'active' }; var Selector = { DATA_SPY: '[data-spy="scroll"]', ACTIVE: '.active', - LIST_ITEM: '.list-item', - LI: 'li', - LI_DROPDOWN: 'li.dropdown', + NAV_LIST_GROUP: '.nav, .list-group', NAV_LINKS: '.nav-link', + LIST_ITEMS: '.list-group-item', DROPDOWN: '.dropdown', DROPDOWN_ITEMS: '.dropdown-item', DROPDOWN_TOGGLE: '.dropdown-toggle' @@ -2227,31 +2453,31 @@ var ScrollSpy = function ($) { var OffsetMethod = { OFFSET: 'offset', POSITION: 'position' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + }; var ScrollSpy = function () { function ScrollSpy(element, config) { - var _this18 = this; + var _this20 = this; _classCallCheck(this, ScrollSpy); this._element = element; this._scrollElement = element.tagName === 'BODY' ? window : element; this._config = this._getConfig(config); - this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS); + this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.LIST_ITEMS + ',') + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS); this._offsets = []; this._targets = []; this._activeTarget = null; this._scrollHeight = 0; $(this._scrollElement).on(Event.SCROLL, function (event) { - return _this18._process(event); + return _this20._process(event); }); this.refresh(); @@ -2263,7 +2489,7 @@ var ScrollSpy = function ($) { // public ScrollSpy.prototype.refresh = function refresh() { - var _this19 = this; + var _this21 = this; var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET; @@ -2286,9 +2512,12 @@ var ScrollSpy = function ($) { target = $(targetSelector)[0]; } - if (target && (target.offsetWidth || target.offsetHeight)) { - // todo (fat): remove sketch reliance on jQuery position/offset - return [$(target)[offsetMethod]().top + offsetBase, targetSelector]; + if (target) { + var targetBCR = target.getBoundingClientRect(); + if (targetBCR.width || targetBCR.height) { + // todo (fat): remove sketch reliance on jQuery position/offset + return [$(target)[offsetMethod]().top + offsetBase, targetSelector]; + } } return null; }).filter(function (item) { @@ -2296,8 +2525,8 @@ var ScrollSpy = function ($) { }).sort(function (a, b) { return a[0] - b[0]; }).forEach(function (item) { - _this19._offsets.push(item[0]); - _this19._targets.push(item[1]); + _this21._offsets.push(item[0]); + _this21._targets.push(item[1]); }); }; @@ -2343,7 +2572,7 @@ var ScrollSpy = function ($) { }; ScrollSpy.prototype._getOffsetHeight = function _getOffsetHeight() { - return this._scrollElement === window ? window.innerHeight : this._scrollElement.offsetHeight; + return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; }; ScrollSpy.prototype._process = function _process() { @@ -2395,9 +2624,11 @@ var ScrollSpy = function ($) { $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); $link.addClass(ClassName.ACTIVE); } else { - // todo (fat) this is kinda sus... - // recursively add actives to tested nav-links - $link.parents(Selector.LI).find('> ' + Selector.NAV_LINKS).addClass(ClassName.ACTIVE); + // Set triggered link as active + $link.addClass(ClassName.ACTIVE); + // Set triggered links parents as active + // With both