mirror of
https://github.com/twbs/bootstrap.git
synced 2025-08-08 14:46:34 +02:00
swipe left/right without hammerjs
This commit is contained in:
@@ -1,7 +1,3 @@
|
||||
import $ from 'jquery'
|
||||
import Hammer from 'hammerjs'
|
||||
import Util from './util'
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
* Bootstrap (v4.1.3): carousel.js
|
||||
@@ -9,6 +5,9 @@ import Util from './util'
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import $ from 'jquery'
|
||||
import Util from './util'
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------------------
|
||||
* Constants
|
||||
@@ -24,7 +23,7 @@ const JQUERY_NO_CONFLICT = $.fn[NAME]
|
||||
const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key
|
||||
const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key
|
||||
const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch
|
||||
const HAMMER_ENABLED = typeof Hammer !== 'undefined'
|
||||
const SWIPE_THRESHOLD = 40
|
||||
|
||||
const Default = {
|
||||
interval : 5000,
|
||||
@@ -58,10 +57,10 @@ const Event = {
|
||||
MOUSEENTER : `mouseenter${EVENT_KEY}`,
|
||||
MOUSELEAVE : `mouseleave${EVENT_KEY}`,
|
||||
TOUCHEND : `touchend${EVENT_KEY}`,
|
||||
TOUCHSTART : `touchstart${EVENT_KEY}`,
|
||||
TOUCHMOVE : `touchmove${EVENT_KEY}`,
|
||||
LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,
|
||||
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,
|
||||
SWIPELEFT : 'swipeleft',
|
||||
SWIPERIGHT : 'swiperight'
|
||||
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
|
||||
}
|
||||
|
||||
const ClassName = {
|
||||
@@ -98,22 +97,13 @@ class Carousel {
|
||||
this._isPaused = false
|
||||
this._isSliding = false
|
||||
this.touchTimeout = null
|
||||
this.hammer = null
|
||||
this.touchStartX = 0
|
||||
this.touchDeltaX = 0
|
||||
|
||||
this._config = this._getConfig(config)
|
||||
this._element = element
|
||||
this._indicatorsElement = this._element.querySelector(Selector.INDICATORS)
|
||||
this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
|
||||
|
||||
if (HAMMER_ENABLED && this._touchSupported && this._config.touch) {
|
||||
this.hammer = new Hammer(this._element, {
|
||||
recognizers: [[
|
||||
Hammer.Swipe, {
|
||||
direction: Hammer.DIRECTION_HORIZONTAL
|
||||
}
|
||||
]]
|
||||
})
|
||||
}
|
||||
this._touchSupported = 'ontouchstart' in document.documentElement
|
||||
|
||||
this._addEventListeners()
|
||||
}
|
||||
@@ -235,22 +225,65 @@ class Carousel {
|
||||
return config
|
||||
}
|
||||
|
||||
_handleSwipe() {
|
||||
const absDeltax = Math.abs(this.touchDeltaX)
|
||||
|
||||
if (absDeltax <= SWIPE_THRESHOLD) {
|
||||
return
|
||||
}
|
||||
|
||||
const direction = absDeltax / this.touchDeltaX
|
||||
|
||||
// swipe left
|
||||
if (direction > 0) {
|
||||
this.prev()
|
||||
}
|
||||
|
||||
// swipe right
|
||||
if (direction < 0) {
|
||||
this.next()
|
||||
}
|
||||
}
|
||||
|
||||
_addEventListeners() {
|
||||
if (this._config.keyboard) {
|
||||
$(this._element)
|
||||
.on(Event.KEYDOWN, (event) => this._keydown(event))
|
||||
}
|
||||
|
||||
if (this.hammer) {
|
||||
this.hammer.on(Event.SWIPELEFT, () => this.next())
|
||||
this.hammer.on(Event.SWIPERIGHT, () => this.prev())
|
||||
}
|
||||
|
||||
if (this._config.pause === 'hover') {
|
||||
$(this._element)
|
||||
.on(Event.MOUSEENTER, (event) => this.pause(event))
|
||||
.on(Event.MOUSELEAVE, (event) => this.cycle(event))
|
||||
if (this._touchSupported) {
|
||||
}
|
||||
|
||||
this._addTouchEventListeners()
|
||||
}
|
||||
|
||||
_addTouchEventListeners() {
|
||||
if (!this._touchSupported) {
|
||||
return
|
||||
}
|
||||
|
||||
$(this._element).on(Event.TOUCHSTART, (event) => {
|
||||
this.touchStartX = event.originalEvent.touches[0].pageX
|
||||
})
|
||||
|
||||
$(this._element).on(Event.TOUCHMOVE, (event) => {
|
||||
event.preventDefault()
|
||||
|
||||
// ensure swiping with one touch and not pinching
|
||||
if (event.originalEvent.touches.length > 1) {
|
||||
return
|
||||
}
|
||||
|
||||
this.touchDeltaX = event.originalEvent.touches[0].pageX - this.touchStartX
|
||||
})
|
||||
|
||||
$(this._element).on(Event.TOUCHEND, () => {
|
||||
this._handleSwipe()
|
||||
|
||||
if (this._config.pause === 'hover') {
|
||||
// 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;
|
||||
@@ -258,15 +291,14 @@ class 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, () => {
|
||||
this.pause()
|
||||
if (this.touchTimeout) {
|
||||
clearTimeout(this.touchTimeout)
|
||||
}
|
||||
this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)
|
||||
})
|
||||
|
||||
this.pause()
|
||||
if (this.touchTimeout) {
|
||||
clearTimeout(this.touchTimeout)
|
||||
}
|
||||
this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_keydown(event) {
|
||||
|
@@ -20,7 +20,6 @@
|
||||
}())
|
||||
</script>
|
||||
<script src="../../node_modules/popper.js/dist/umd/popper.min.js"></script>
|
||||
<script src="../../node_modules/hammerjs/hammer.min.js"></script>
|
||||
|
||||
<!-- QUnit -->
|
||||
<link rel="stylesheet" href="../../node_modules/qunit/qunit/qunit.css" media="screen">
|
||||
|
@@ -12,16 +12,16 @@ const jqueryFile = process.env.USE_OLD_JQUERY ? 'https://code.jquery.com/jquery-
|
||||
const bundle = process.env.BUNDLE === 'true'
|
||||
const browserStack = process.env.BROWSER === 'true'
|
||||
|
||||
const plugins = [
|
||||
'karma-qunit',
|
||||
'karma-sinon'
|
||||
]
|
||||
|
||||
const frameworks = [
|
||||
'qunit',
|
||||
'sinon'
|
||||
]
|
||||
|
||||
const plugins = [
|
||||
'karma-qunit',
|
||||
'karma-sinon'
|
||||
]
|
||||
|
||||
const reporters = ['dots']
|
||||
|
||||
const detectBrowsers = {
|
||||
@@ -48,7 +48,6 @@ const customLaunchers = {
|
||||
|
||||
let files = [
|
||||
'node_modules/popper.js/dist/umd/popper.min.js',
|
||||
'node_modules/hammerjs/hammer.min.js',
|
||||
'node_modules/hammer-simulator/index.js'
|
||||
]
|
||||
|
||||
|
@@ -3,8 +3,6 @@ $(function () {
|
||||
|
||||
window.Carousel = typeof bootstrap !== 'undefined' ? bootstrap.Carousel : Carousel
|
||||
|
||||
var touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
|
||||
|
||||
QUnit.module('carousel plugin')
|
||||
|
||||
QUnit.test('should be defined on jQuery object', function (assert) {
|
||||
@@ -1009,13 +1007,8 @@ $(function () {
|
||||
})
|
||||
|
||||
QUnit.test('should allow swiperight and call prev', function (assert) {
|
||||
if (!touchSupported) {
|
||||
assert.expect(0)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
assert.expect(2)
|
||||
Simulator.setType('touch')
|
||||
assert.expect(3)
|
||||
var done = assert.async()
|
||||
document.documentElement.ontouchstart = $.noop
|
||||
|
||||
@@ -1035,10 +1028,13 @@ $(function () {
|
||||
$carousel.appendTo('#qunit-fixture')
|
||||
var $item = $('#item')
|
||||
$carousel.bootstrapCarousel()
|
||||
var carousel = $carousel.data('bs.carousel')
|
||||
var spy = sinon.spy(carousel, 'prev')
|
||||
|
||||
$carousel.one('slid.bs.carousel', function () {
|
||||
assert.ok(true, 'slid event fired')
|
||||
assert.ok($item.hasClass('active'))
|
||||
assert.ok(spy.called)
|
||||
delete document.documentElement.ontouchstart
|
||||
done()
|
||||
})
|
||||
@@ -1049,40 +1045,10 @@ $(function () {
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.test('should not use HammerJS when touch option is false', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
var $carousel = $('<div></div>').appendTo('#qunit-fixture')
|
||||
$carousel.bootstrapCarousel({
|
||||
touch: false
|
||||
})
|
||||
|
||||
var carousel = $carousel.data('bs.carousel')
|
||||
|
||||
assert.strictEqual(carousel.hammer, null)
|
||||
})
|
||||
|
||||
QUnit.test('should use HammerJS when touch option is true', function (assert) {
|
||||
assert.expect(1)
|
||||
|
||||
document.documentElement.ontouchstart = $.noop
|
||||
|
||||
var $carousel = $('<div></div>').appendTo('#qunit-fixture')
|
||||
$carousel.bootstrapCarousel()
|
||||
|
||||
var carousel = $carousel.data('bs.carousel')
|
||||
|
||||
assert.ok(carousel.hammer !== null)
|
||||
})
|
||||
|
||||
QUnit.test('should allow swipeleft and call next', function (assert) {
|
||||
if (!touchSupported) {
|
||||
assert.expect(0)
|
||||
assert.expect(3)
|
||||
Simulator.setType('touch')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
assert.expect(2)
|
||||
var done = assert.async()
|
||||
document.documentElement.ontouchstart = $.noop
|
||||
|
||||
@@ -1102,11 +1068,13 @@ $(function () {
|
||||
$carousel.appendTo('#qunit-fixture')
|
||||
var $item = $('#item')
|
||||
$carousel.bootstrapCarousel()
|
||||
var carousel = $carousel.data('bs.carousel')
|
||||
var spy = sinon.spy(carousel, 'next')
|
||||
|
||||
$carousel.one('slid.bs.carousel', function () {
|
||||
assert.ok(true, 'slid event fired')
|
||||
assert.ok(!$item.hasClass('active'))
|
||||
delete document.documentElement.ontouchstart
|
||||
assert.ok(spy.called)
|
||||
done()
|
||||
})
|
||||
|
||||
@@ -1116,4 +1084,25 @@ $(function () {
|
||||
deltaY: 0
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.test('should not allow pinch', function (assert) {
|
||||
assert.expect(0)
|
||||
Simulator.setType('touch')
|
||||
var done = assert.async()
|
||||
document.documentElement.ontouchstart = $.noop
|
||||
|
||||
var carouselHTML = '<div class="carousel" data-interval="false"></div>'
|
||||
var $carousel = $(carouselHTML)
|
||||
$carousel.appendTo('#qunit-fixture')
|
||||
$carousel.bootstrapCarousel()
|
||||
|
||||
Simulator.gestures.swipe($carousel[0], {
|
||||
pos: [300, 10],
|
||||
deltaX: -300,
|
||||
deltaY: 0,
|
||||
touches: 2
|
||||
}, function () {
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -46,7 +46,6 @@
|
||||
</div>
|
||||
|
||||
<script src="../../../site/docs/4.1/assets/js/vendor/jquery-slim.min.js"></script>
|
||||
<script src="../../../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../../dist/util.js"></script>
|
||||
<script src="../../dist/carousel.js"></script>
|
||||
<script>
|
||||
|
Reference in New Issue
Block a user