bootstrap-sass 3.0.3.0 → 3.1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bootstrap-sass might be problematic. Click here for more details.

Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/CHANGELOG.md +4 -0
  4. data/CONTRIBUTING.md +2 -2
  5. data/Gemfile +1 -1
  6. data/LICENSE +17 -10
  7. data/README.md +17 -17
  8. data/Rakefile +7 -2
  9. data/bootstrap-sass.gemspec +9 -9
  10. data/bower.json +22 -0
  11. data/composer.json +35 -0
  12. data/lib/bootstrap-sass.rb +1 -3
  13. data/lib/bootstrap-sass/sass_functions.rb +4 -3
  14. data/lib/bootstrap-sass/version.rb +2 -2
  15. data/tasks/converter.rb +21 -15
  16. data/tasks/converter/fonts_conversion.rb +7 -3
  17. data/tasks/converter/js_conversion.rb +20 -3
  18. data/tasks/converter/less_conversion.rb +89 -60
  19. data/tasks/converter/logger.rb +6 -14
  20. data/tasks/converter/network.rb +7 -32
  21. data/test/compilation_test.rb +1 -1
  22. data/test/dummy/app/views/pages/root.html.slim +8 -2
  23. data/test/dummy/config/application.rb +2 -2
  24. data/test/gemfiles/sass_3_2.gemfile +1 -1
  25. data/test/gemfiles/sass_head.gemfile +2 -3
  26. data/test/sprockets_rails_test.rb +21 -0
  27. data/vendor/assets/javascripts/bootstrap/affix.js +34 -23
  28. data/vendor/assets/javascripts/bootstrap/alert.js +5 -15
  29. data/vendor/assets/javascripts/bootstrap/button.js +21 -29
  30. data/vendor/assets/javascripts/bootstrap/carousel.js +16 -28
  31. data/vendor/assets/javascripts/bootstrap/collapse.js +7 -16
  32. data/vendor/assets/javascripts/bootstrap/dropdown.js +19 -26
  33. data/vendor/assets/javascripts/bootstrap/modal.js +25 -28
  34. data/vendor/assets/javascripts/bootstrap/popover.js +14 -21
  35. data/vendor/assets/javascripts/bootstrap/scrollspy.js +16 -21
  36. data/vendor/assets/javascripts/bootstrap/tab.js +7 -17
  37. data/vendor/assets/javascripts/bootstrap/tooltip.js +52 -39
  38. data/vendor/assets/javascripts/bootstrap/transition.js +11 -19
  39. data/vendor/assets/stylesheets/bootstrap/_badges.scss +4 -0
  40. data/vendor/assets/stylesheets/bootstrap/_breadcrumbs.scss +4 -1
  41. data/vendor/assets/stylesheets/bootstrap/_button-groups.scss +8 -9
  42. data/vendor/assets/stylesheets/bootstrap/_buttons.scss +8 -8
  43. data/vendor/assets/stylesheets/bootstrap/_code.scss +10 -0
  44. data/vendor/assets/stylesheets/bootstrap/_dropdowns.scss +28 -3
  45. data/vendor/assets/stylesheets/bootstrap/_forms.scss +81 -38
  46. data/vendor/assets/stylesheets/bootstrap/_glyphicons.scss +1 -5
  47. data/vendor/assets/stylesheets/bootstrap/_grid.scss +26 -5
  48. data/vendor/assets/stylesheets/bootstrap/_input-groups.scss +39 -18
  49. data/vendor/assets/stylesheets/bootstrap/_jumbotron.scss +3 -5
  50. data/vendor/assets/stylesheets/bootstrap/_list-group.scss +25 -3
  51. data/vendor/assets/stylesheets/bootstrap/_mixins.scss +124 -41
  52. data/vendor/assets/stylesheets/bootstrap/_modals.scss +15 -6
  53. data/vendor/assets/stylesheets/bootstrap/_navbar.scss +21 -17
  54. data/vendor/assets/stylesheets/bootstrap/_navs.scss +1 -1
  55. data/vendor/assets/stylesheets/bootstrap/_normalize.scss +139 -122
  56. data/vendor/assets/stylesheets/bootstrap/_pager.scss +4 -4
  57. data/vendor/assets/stylesheets/bootstrap/_pagination.scss +6 -3
  58. data/vendor/assets/stylesheets/bootstrap/_panels.scss +63 -15
  59. data/vendor/assets/stylesheets/bootstrap/_print.scss +0 -4
  60. data/vendor/assets/stylesheets/bootstrap/_responsive-utilities.scss +6 -124
  61. data/vendor/assets/stylesheets/bootstrap/_scaffolding.scss +17 -2
  62. data/vendor/assets/stylesheets/bootstrap/_tables.scss +3 -1
  63. data/vendor/assets/stylesheets/bootstrap/_theme.scss +3 -3
  64. data/vendor/assets/stylesheets/bootstrap/_thumbnails.scss +4 -4
  65. data/vendor/assets/stylesheets/bootstrap/_tooltip.scss +1 -1
  66. data/vendor/assets/stylesheets/bootstrap/_type.scss +77 -62
  67. data/vendor/assets/stylesheets/bootstrap/_variables.scss +350 -163
  68. data/vendor/assets/stylesheets/bootstrap/_wells.scss +1 -1
  69. data/vendor/assets/stylesheets/bootstrap/bootstrap.scss +38 -38
  70. metadata +22 -4
@@ -2,16 +2,6 @@ class Converter
2
2
  class Logger
3
3
  include Term::ANSIColor
4
4
 
5
- def initialize(env)
6
- @env = env
7
- puts bold "Convert Bootstrap LESS to SASS"
8
- puts " repo : #{env[:repo]}"
9
- puts " branch : #{env[:branch]} #{dark "#{env[:repo]}/tree/#{env[:branch_sha]}"}"
10
- puts " save to: #{@env[:save_at].to_json}"
11
- puts " twbs cache: #{@env[:cache_path]}"
12
- puts dark "-" * 60
13
- end
14
-
15
5
  def log_status(status)
16
6
  puts bold status
17
7
  end
@@ -20,8 +10,8 @@ class Converter
20
10
  puts " #{magenta s}"
21
11
  end
22
12
 
23
- def log_transform(*args)
24
- puts "#{cyan " #{caller[1][/`.*'/][1..-2].sub(/^block in /, '')}"}#{cyan ": #{args * ', '}" unless args.empty?}"
13
+ def log_transform(*args, from: caller[1][/`.*'/][1..-2].sub(/^block in /, ''))
14
+ puts " #{cyan from}#{cyan ": #{args * ', '}" unless args.empty?}"
25
15
  end
26
16
 
27
17
  def log_processing(name)
@@ -51,9 +41,11 @@ class Converter
51
41
  end
52
42
 
53
43
  def puts(*args)
54
- STDOUT.puts *args unless @silence
44
+ STDERR.puts *args unless @silence
55
45
  end
56
46
 
47
+ alias log puts
48
+
57
49
  def silence_log
58
50
  @silence = true
59
51
  yield
@@ -61,4 +53,4 @@ class Converter
61
53
  @silence = false
62
54
  end
63
55
  end
64
- end
56
+ end
@@ -1,40 +1,14 @@
1
1
  class Converter
2
2
  module Network
3
-
4
- def bootstrap_font_files
5
- @bootstrap_font_files ||= get_paths_by_type('fonts', /\.(eot|svg|ttf|woff)$/)
6
- end
7
-
8
- def bootstrap_less_files
9
- @bootstrap_less_files ||= get_paths_by_type('less', /\.less$/)
10
- end
11
-
12
- def bootstrap_js_files
13
- @bootstrap_js_files ||= begin
14
- files = get_paths_by_type 'js', /\.js$/
15
- files.sort_by { |f|
16
- case f
17
- # tooltip depends on popover and must be loaded earlier
18
- when /tooltip/ then
19
- 1
20
- when /popover/ then
21
- 2
22
- else
23
- 0
24
- end
25
- }
26
- end
27
- end
28
-
29
3
  protected
30
4
 
31
5
  def get_paths_by_type(dir, file_re)
32
- files = get_json "#{@git_data_api_host}/#@repo/git/trees/#{get_tree_sha(dir)}"
6
+ files = get_json "https://api.github.com/repos/#@repo/git/trees/#{get_tree_sha(dir)}"
33
7
  files['tree'].select { |f| f['type'] == 'blob' && f['path'] =~ file_re }.map { |f| f['path'] }
34
8
  end
35
9
 
36
10
  def read_files(path, files)
37
- full_path = "#{@git_raw_host}/#@repo/#@branch_sha/#{path}"
11
+ full_path = "https://raw.github.com/#@repo/#@branch_sha/#{path}"
38
12
  if (contents = read_cached_files(path, files))
39
13
  log_http_get_files files, full_path, true
40
14
  else
@@ -87,8 +61,9 @@ class Converter
87
61
 
88
62
  # get sha of the branch (= the latest commit)
89
63
  def get_branch_sha
90
- cmd = "git ls-remote '#@repo_url' | awk '/#@branch/ {print $1}'"
91
- puts cmd
64
+ return @branch if @branch =~ /\A[0-9a-f]+\z/
65
+ cmd = "git ls-remote 'https://github.com/#@repo' | awk '/#@branch/ {print $1}'"
66
+ log cmd
92
67
  @branch_sha ||= %x[#{cmd}].chomp
93
68
  raise 'Could not get branch sha!' unless $?.success?
94
69
  @branch_sha
@@ -100,11 +75,11 @@ class Converter
100
75
  end
101
76
 
102
77
  def get_trees
103
- @trees ||= get_json("#{@git_data_api_host}/#@repo/git/trees/#@branch_sha")
78
+ @trees ||= get_json("https://api.github.com/repos/#@repo/git/trees/#@branch_sha")
104
79
  end
105
80
 
106
81
  def get_json(url)
107
82
  JSON.parse get_file(url)
108
83
  end
109
84
  end
110
- end
85
+ end
@@ -14,4 +14,4 @@ class CompilationTest < Test::Unit::TestCase
14
14
  end
15
15
  end
16
16
  end
17
- end
17
+ end
@@ -10,13 +10,19 @@
10
10
  li.list-group-item: a href='#three' Three
11
11
  .col-sm-3
12
12
  h2 3 columns
13
- button.btn.btn-primary type='button' Button
14
- button.btn.btn-primary type='button' Button
13
+ .btn-group
14
+ button.btn.btn-primary type='button' Button
15
+ button.btn.btn-primary type='button' Button
15
16
  h2 Icons
16
17
  ul.list-inline
17
18
  li: i.glyphicon.glyphicon-user
18
19
  li: i.glyphicon.glyphicon-bullhorn
19
20
  li: i.glyphicon.glyphicon-tint
21
+ table.table
22
+ caption Table
23
+ tr
24
+ td.danger Danger!
25
+ td.success Success!
20
26
  .col-sm-6
21
27
  h2 6 columns
22
28
  .panel.panel-primary: .panel-body
@@ -1,9 +1,9 @@
1
1
  require File.expand_path('../boot', __FILE__)
2
2
 
3
- require 'action_controller/railtie'
4
- require 'sprockets/railtie'
3
+ require 'rails'
5
4
 
6
5
  Bundler.require(*Rails.groups)
6
+
7
7
  require 'sass-rails'
8
8
  require 'jquery-rails'
9
9
  require 'slim-rails'
@@ -5,7 +5,7 @@ gem 'sass', '~> 3.2.0'
5
5
  platform :rbx do
6
6
  gem 'rubysl', '~> 2.0'
7
7
  gem 'rubysl-test-unit', '~> 2.0'
8
- gem 'rubysl-json', '~> 2.0'
8
+ gem 'json', '>= 1.8.1'
9
9
  gem 'racc'
10
10
  end
11
11
 
@@ -1,13 +1,12 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem 'sass', '~> 3.3.0.rc.2'
4
- gem 'compass', '~> 1.0.0.alpha.13'
5
-
4
+ gem 'compass', '~> 1.0.0.alpha.17'
6
5
 
7
6
  platform :rbx do
8
7
  gem 'rubysl', '~> 2.0'
9
8
  gem 'rubysl-test-unit', '~> 2.0'
10
- gem 'rubysl-json', '~> 2.0'
9
+ gem 'json', '>= 1.8.1'
11
10
  gem 'racc'
12
11
  end
13
12
 
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+ require 'fileutils'
3
+ require 'find'
4
+ require 'shellwords'
5
+
6
+ class SprocketsRailsTest < ActiveSupport::TestCase
7
+
8
+ def test_sprockets_digest_asset_refs
9
+ system "cd #{Shellwords.escape Rails.root.to_s} && bundle exec rake assets:precompile GEMFILE=#{Bootstrap.gem_path}/Gemfile RAILS_ENV=production"
10
+ Dir.glob(Rails.root.join('public', 'assets', 'app*.*')) do |path|
11
+ next unless path =~ /\.(css|js)$/
12
+ File.open(path, 'r') do |f|
13
+ f.read.scan /url\("?[^"]+\.(?:jpg|png|eot|woff|ttf|svg)[^"]*"?\)/ do |m|
14
+ assert_match /-[0-9a-f]{12,}\./, m
15
+ end
16
+ end
17
+ end
18
+ ensure
19
+ system "rm -rf #{Rails.root}/public/assets/ #{Rails.root}/tmp/cache/"
20
+ end
21
+ end
@@ -1,24 +1,14 @@
1
1
  /* ========================================================================
2
- * Bootstrap: affix.js v3.0.3
2
+ * Bootstrap: affix.js v3.1.0
3
3
  * http://getbootstrap.com/javascript/#affix
4
4
  * ========================================================================
5
- * Copyright 2013 Twitter, Inc.
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the "License");
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
5
+ * Copyright 2011-2014 Twitter, Inc.
6
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
18
7
  * ======================================================================== */
19
8
 
20
9
 
21
- +function ($) { "use strict";
10
+ +function ($) {
11
+ 'use strict';
22
12
 
23
13
  // AFFIX CLASS DEFINITION
24
14
  // ======================
@@ -29,9 +19,10 @@
29
19
  .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
30
20
  .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
31
21
 
32
- this.$element = $(element)
33
- this.affixed =
34
- this.unpin = null
22
+ this.$element = $(element)
23
+ this.affixed =
24
+ this.unpin =
25
+ this.pinnedOffset = null
35
26
 
36
27
  this.checkPosition()
37
28
  }
@@ -42,6 +33,14 @@
42
33
  offset: 0
43
34
  }
44
35
 
36
+ Affix.prototype.getPinnedOffset = function () {
37
+ if (this.pinnedOffset) return this.pinnedOffset
38
+ this.$element.removeClass(Affix.RESET).addClass('affix')
39
+ var scrollTop = this.$window.scrollTop()
40
+ var position = this.$element.offset()
41
+ return (this.pinnedOffset = position.top - scrollTop)
42
+ }
43
+
45
44
  Affix.prototype.checkPositionWithEventLoop = function () {
46
45
  setTimeout($.proxy(this.checkPosition, this), 1)
47
46
  }
@@ -56,9 +55,11 @@
56
55
  var offsetTop = offset.top
57
56
  var offsetBottom = offset.bottom
58
57
 
58
+ if (this.affixed == 'top') position.top += scrollTop
59
+
59
60
  if (typeof offset != 'object') offsetBottom = offsetTop = offset
60
- if (typeof offsetTop == 'function') offsetTop = offset.top()
61
- if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
61
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
62
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
62
63
 
63
64
  var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
64
65
  offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
@@ -67,13 +68,23 @@
67
68
  if (this.affixed === affix) return
68
69
  if (this.unpin) this.$element.css('top', '')
69
70
 
71
+ var affixType = 'affix' + (affix ? '-' + affix : '')
72
+ var e = $.Event(affixType + '.bs.affix')
73
+
74
+ this.$element.trigger(e)
75
+
76
+ if (e.isDefaultPrevented()) return
77
+
70
78
  this.affixed = affix
71
- this.unpin = affix == 'bottom' ? position.top - scrollTop : null
79
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
72
80
 
73
- this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))
81
+ this.$element
82
+ .removeClass(Affix.RESET)
83
+ .addClass(affixType)
84
+ .trigger($.Event(affixType.replace('affix', 'affixed')))
74
85
 
75
86
  if (affix == 'bottom') {
76
- this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })
87
+ this.$element.offset({ top: scrollHeight - offsetBottom - this.$element.height() })
77
88
  }
78
89
  }
79
90
 
@@ -1,24 +1,14 @@
1
1
  /* ========================================================================
2
- * Bootstrap: alert.js v3.0.3
2
+ * Bootstrap: alert.js v3.1.0
3
3
  * http://getbootstrap.com/javascript/#alerts
4
4
  * ========================================================================
5
- * Copyright 2013 Twitter, Inc.
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the "License");
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
5
+ * Copyright 2011-2014 Twitter, Inc.
6
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
18
7
  * ======================================================================== */
19
8
 
20
9
 
21
- +function ($) { "use strict";
10
+ +function ($) {
11
+ 'use strict';
22
12
 
23
13
  // ALERT CLASS DEFINITION
24
14
  // ======================
@@ -1,31 +1,22 @@
1
1
  /* ========================================================================
2
- * Bootstrap: button.js v3.0.3
2
+ * Bootstrap: button.js v3.1.0
3
3
  * http://getbootstrap.com/javascript/#buttons
4
4
  * ========================================================================
5
- * Copyright 2013 Twitter, Inc.
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the "License");
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
5
+ * Copyright 2011-2014 Twitter, Inc.
6
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
18
7
  * ======================================================================== */
19
8
 
20
9
 
21
- +function ($) { "use strict";
10
+ +function ($) {
11
+ 'use strict';
22
12
 
23
13
  // BUTTON PUBLIC CLASS DEFINITION
24
14
  // ==============================
25
15
 
26
16
  var Button = function (element, options) {
27
- this.$element = $(element)
28
- this.options = $.extend({}, Button.DEFAULTS, options)
17
+ this.$element = $(element)
18
+ this.options = $.extend({}, Button.DEFAULTS, options)
19
+ this.isLoading = false
29
20
  }
30
21
 
31
22
  Button.DEFAULTS = {
@@ -45,25 +36,26 @@
45
36
  $el[val](data[state] || this.options[state])
46
37
 
47
38
  // push to event loop to allow forms to submit
48
- setTimeout(function () {
49
- state == 'loadingText' ?
50
- $el.addClass(d).attr(d, d) :
51
- $el.removeClass(d).removeAttr(d);
52
- }, 0)
39
+ setTimeout($.proxy(function () {
40
+ if (state == 'loadingText') {
41
+ this.isLoading = true
42
+ $el.addClass(d).attr(d, d)
43
+ } else if (this.isLoading) {
44
+ this.isLoading = false
45
+ $el.removeClass(d).removeAttr(d)
46
+ }
47
+ }, this), 0)
53
48
  }
54
49
 
55
50
  Button.prototype.toggle = function () {
56
- var $parent = this.$element.closest('[data-toggle="buttons"]')
57
51
  var changed = true
52
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
58
53
 
59
54
  if ($parent.length) {
60
55
  var $input = this.$element.find('input')
61
- if ($input.prop('type') === 'radio') {
62
- // see if clicking on current one
63
- if ($input.prop('checked') && this.$element.hasClass('active'))
64
- changed = false
65
- else
66
- $parent.find('.active').removeClass('active')
56
+ if ($input.prop('type') == 'radio') {
57
+ if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
58
+ else $parent.find('.active').removeClass('active')
67
59
  }
68
60
  if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
69
61
  }
@@ -1,24 +1,14 @@
1
1
  /* ========================================================================
2
- * Bootstrap: carousel.js v3.0.3
2
+ * Bootstrap: carousel.js v3.1.0
3
3
  * http://getbootstrap.com/javascript/#carousel
4
4
  * ========================================================================
5
- * Copyright 2013 Twitter, Inc.
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the "License");
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
5
+ * Copyright 2011-2014 Twitter, Inc.
6
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
18
7
  * ======================================================================== */
19
8
 
20
9
 
21
- +function ($) { "use strict";
10
+ +function ($) {
11
+ 'use strict';
22
12
 
23
13
  // CAROUSEL CLASS DEFINITION
24
14
  // =========================
@@ -39,9 +29,9 @@
39
29
  }
40
30
 
41
31
  Carousel.DEFAULTS = {
42
- interval: 5000
43
- , pause: 'hover'
44
- , wrap: true
32
+ interval: 5000,
33
+ pause: 'hover',
34
+ wrap: true
45
35
  }
46
36
 
47
37
  Carousel.prototype.cycle = function (e) {
@@ -78,7 +68,7 @@
78
68
  Carousel.prototype.pause = function (e) {
79
69
  e || (this.paused = true)
80
70
 
81
- if (this.$element.find('.next, .prev').length && $.support.transition.end) {
71
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
82
72
  this.$element.trigger($.support.transition.end)
83
73
  this.cycle(true)
84
74
  }
@@ -111,13 +101,15 @@
111
101
  $next = this.$element.find('.item')[fallback]()
112
102
  }
113
103
 
114
- this.sliding = true
115
-
116
- isCycling && this.pause()
104
+ if ($next.hasClass('active')) return this.sliding = false
117
105
 
118
106
  var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })
107
+ this.$element.trigger(e)
108
+ if (e.isDefaultPrevented()) return
119
109
 
120
- if ($next.hasClass('active')) return
110
+ this.sliding = true
111
+
112
+ isCycling && this.pause()
121
113
 
122
114
  if (this.$indicators.length) {
123
115
  this.$indicators.find('.active').removeClass('active')
@@ -128,8 +120,6 @@
128
120
  }
129
121
 
130
122
  if ($.support.transition && this.$element.hasClass('slide')) {
131
- this.$element.trigger(e)
132
- if (e.isDefaultPrevented()) return
133
123
  $next.addClass(type)
134
124
  $next[0].offsetWidth // force reflow
135
125
  $active.addClass(direction)
@@ -141,10 +131,8 @@
141
131
  that.sliding = false
142
132
  setTimeout(function () { that.$element.trigger('slid.bs.carousel') }, 0)
143
133
  })
144
- .emulateTransitionEnd(600)
134
+ .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
145
135
  } else {
146
- this.$element.trigger(e)
147
- if (e.isDefaultPrevented()) return
148
136
  $active.removeClass('active')
149
137
  $next.addClass('active')
150
138
  this.sliding = false