bootstrap-sass 3.0.3.0 → 3.1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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