drip-ui
Version:
Lightweight Mobile UI Components built on Vue
399 lines (302 loc) • 10.4 kB
JavaScript
import objectAssign from 'object-assign';
var arrayFrom = function arrayFrom(nodeList) {
return Array.prototype.slice.call(nodeList);
};
var Swiper =
/*#__PURE__*/
function () {
function Swiper(options) {
this._default = {
container: '.drip-swiper',
item: '.drip-swiper-item',
direction: 'vertical',
activeClass: 'active',
threshold: 50,
duration: 300,
auto: false,
loop: false,
interval: 3000,
height: 'auto',
minMovingDistance: 0
};
this._options = objectAssign(this._default, options);
this._options.height = this._options.height.replace('px', '');
this._start = {};
this._move = {};
this._end = {};
this._eventHandlers = {};
this._prev = this._current = this._goto = 0;
this._width = this._height = this._distance = 0;
this._offset = [];
this.$box = this._options.container;
this.$container = this._options.container.querySelector('.drip-swiper');
this.$items = this.$container.querySelectorAll(this._options.item);
this.count = this.$items.length;
this.realCount = this.$items.length; // real items length
this._position = []; // used by go event
this._firstItemIndex = 0;
if (!this.count) {
return;
}
this._init();
this._auto();
this._bind();
this._onResize();
return this;
}
var _proto = Swiper.prototype;
_proto._auto = function _auto() {
var me = this;
me.stop();
if (me._options.auto) {
me.timer = setTimeout(function () {
me.next();
}, me._options.interval);
}
};
_proto.updateItemWidth = function updateItemWidth() {
this._width = this.$box.offsetWidth || document.documentElement.offsetWidth;
this._distance = this._options.direction === 'horizontal' ? this._width : this._height;
};
_proto.stop = function stop() {
this.timer && clearTimeout(this.timer);
};
_proto._loop = function _loop() {
return this._options.loop && this.realCount >= 3;
};
_proto._onResize = function _onResize() {
var me = this;
this.resizeHandler = function () {
setTimeout(function () {
me.updateItemWidth();
me._setOffset();
me._setTransform();
}, 100);
};
window.addEventListener('orientationchange', this.resizeHandler, false);
};
_proto._init = function _init() {
this._height = this._options.height === 'auto' ? 'auto' : this._options.height - 0;
this.updateItemWidth();
this._initPosition();
this._activate(this._current);
this._setOffset();
this._setTransform();
if (this._loop()) {
this._loopRender();
}
};
_proto._initPosition = function _initPosition() {
for (var i = 0; i < this.realCount; i++) {
this._position.push(i);
}
};
_proto._movePosition = function _movePosition(position) {
var me = this;
if (position > 0) {
var firstIndex = me._position.splice(0, 1);
me._position.push(firstIndex[0]);
} else if (position < 0) {
var lastIndex = me._position.pop();
me._position.unshift(lastIndex);
}
};
_proto._setOffset = function _setOffset() {
var me = this;
var index = me._position.indexOf(me._current);
me._offset = [];
arrayFrom(me.$items).forEach(function ($item, key) {
me._offset.push((key - index) * me._distance);
});
};
_proto._setTransition = function _setTransition(duration) {
duration = duration || this._options.duration || 'none';
var transition = duration === 'none' ? 'none' : duration + 'ms';
arrayFrom(this.$items).forEach(function ($item, key) {
$item.style.webkitTransition = transition;
$item.style.transition = transition;
});
};
_proto._setTransform = function _setTransform(offset) {
var me = this;
offset = offset || 0;
arrayFrom(me.$items).forEach(function ($item, key) {
var distance = me._offset[key] + offset;
var transform = "translate3d(" + distance + "px, 0, 0)";
if (me._options.direction === 'vertical') {
transform = "translate3d(0, " + distance + "px, 0)";
}
$item.style.webkitTransform = transform;
$item.style.transform = transform;
});
};
_proto._bind = function _bind() {
var _this = this;
var me = this;
me.touchstartHandler = function (e) {
me.stop();
me._start.x = e.changedTouches[0].pageX;
me._start.y = e.changedTouches[0].pageY;
me._setTransition('none');
};
me.touchmoveHandler = function (e) {
me._move.x = e.changedTouches[0].pageX;
me._move.y = e.changedTouches[0].pageY;
var distanceX = me._move.x - me._start.x;
var distanceY = me._move.y - me._start.y;
var distance = distanceY;
var noScrollerY = Math.abs(distanceX) > Math.abs(distanceY);
if (me._options.direction === 'horizontal' && noScrollerY) {
distance = distanceX;
}
/* set shorter distance for first and last item for better experience */
if (!_this._options.loop && (_this._current === _this.count - 1 || _this._current === 0)) {
distance = distance / 3;
}
if ((me._options.minMovingDistance && Math.abs(distance) >= me._options.minMovingDistance || !me._options.minMovingDistance) && noScrollerY) {
me._setTransform(distance);
}
noScrollerY && e.preventDefault();
};
me.touchendHandler = function (e) {
me._end.x = e.changedTouches[0].pageX;
me._end.y = e.changedTouches[0].pageY;
var distance = me._end.y - me._start.y;
if (me._options.direction === 'horizontal') {
distance = me._end.x - me._start.x;
}
distance = me.getDistance(distance);
if (distance !== 0 && me._options.minMovingDistance && Math.abs(distance) < me._options.minMovingDistance) {
return;
}
if (distance > me._options.threshold) {
me.move(-1);
} else if (distance < -me._options.threshold) {
me.move(1);
} else {
me.move(0);
}
me._loopRender();
};
me.transitionEndHandler = function (e) {
me._activate(me._current);
var cb = me._eventHandlers.swiped;
cb && cb.apply(me, [me._prev % me.count, me._current % me.count]);
me._auto();
me._loopRender();
e.preventDefault();
};
me.$container.addEventListener('touchstart', me.touchstartHandler, false);
me.$container.addEventListener('touchmove', me.touchmoveHandler, false);
me.$container.addEventListener('touchend', me.touchendHandler, false);
me.$items[1] && me.$items[1].addEventListener('webkitTransitionEnd', me.transitionEndHandler, false);
};
_proto._loopRender = function _loopRender() {
var me = this;
if (me._loop()) {
// issue #507 (delete cloneNode)
if (me._offset[me._offset.length - 1] === 0) {
me.$container.appendChild(me.$items[0]);
me._loopEvent(1);
} else if (me._offset[0] === 0) {
me.$container.insertBefore(me.$items[me.$items.length - 1], me.$container.firstChild);
me._loopEvent(-1);
}
}
};
_proto._loopEvent = function _loopEvent(num) {
var me = this;
me._itemDestoy();
me.$items = me.$container.querySelectorAll(me._options.item);
me.$items[1] && me.$items[1].addEventListener('webkitTransitionEnd', me.transitionEndHandler, false);
me._movePosition(num);
me._setOffset();
me._setTransform();
};
_proto.getDistance = function getDistance(distance) {
if (this._loop()) {
return distance;
} else {
if (distance > 0 && this._current === 0) {
return 0;
} else if (distance < 0 && this._current === this.realCount - 1) {
return 0;
} else {
return distance;
}
}
};
_proto._moveIndex = function _moveIndex(num) {
if (num !== 0) {
this._prev = this._current;
this._current += this.realCount;
this._current += num;
this._current %= this.realCount;
}
};
_proto._activate = function _activate(index) {
var clazz = this._options.activeClass;
Array.prototype.forEach.call(this.$items, function ($item, key) {
$item.classList.remove(clazz);
if (index === Number($item.dataset.index)) {
$item.classList.add(clazz);
}
});
};
_proto.go = function go(index) {
var me = this;
me.stop();
index = index || 0;
index += this.realCount;
index = index % this.realCount;
index = this._position.indexOf(index) - this._position.indexOf(this._current);
me._moveIndex(index);
me._setOffset();
me._setTransition();
me._setTransform();
me._auto();
return this;
};
_proto.next = function next() {
this.move(1);
return this;
};
_proto.move = function move(num) {
this.go(this._current + num);
return this;
};
_proto.on = function on(event, callback) {
if (this._eventHandlers[event]) {
console.error("[swiper] event " + event + " is already register");
}
if (typeof callback !== 'function') {
console.error('[swiper] parameter callback must be a function');
}
this._eventHandlers[event] = callback;
return this;
};
_proto._itemDestoy = function _itemDestoy() {
var _this2 = this;
this.$items.length && arrayFrom(this.$items).forEach(function (item) {
item.removeEventListener('webkitTransitionEnd', _this2.transitionEndHandler, false);
});
};
_proto.destroy = function destroy() {
this.stop();
this._current = 0;
this._setTransform(0);
window.removeEventListener('orientationchange', this.resizeHandler, false);
this.$container.removeEventListener('touchstart', this.touchstartHandler, false);
this.$container.removeEventListener('touchmove', this.touchmoveHandler, false);
this.$container.removeEventListener('touchend', this.touchendHandler, false);
this._itemDestoy(); // remove clone item (used by loop only 2)
if (this._options.loop && this.count === 2) {
var $item = this.$container.querySelector(this._options.item + "-clone");
$item && this.$container.removeChild($item);
$item = this.$container.querySelector(this._options.item + "-clone");
$item && this.$container.removeChild($item);
}
};
return Swiper;
}();
export default Swiper;