slider-js
Version:
a nice slider
503 lines (419 loc) • 16.7 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Items = undefined;
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; }; }();
exports.getTransformOffset = getTransformOffset;
exports.getTranslate = getTranslate;
require('gesturejs');
var _amfeCubicbezier = require('amfe-cubicbezier');
var cubicbezier = _interopRequireWildcard(_amfeCubicbezier);
var _animationJs = require('animation-js');
var _animationJs2 = _interopRequireDefault(_animationJs);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
if (typeof global.window === 'undefined') {
throw new Error('can not be running in non-browser');
}
var win = global.window;
var doc = win.document;
var ua = win.navigator.userAgent;
var Firefox = !!ua.match(/Firefox/i);
var IEMobile = !!ua.match(/IEMobile/i);
var stylePrefix = Firefox ? 'Moz' : IEMobile ? 'ms' : 'webkit';
function getTransformOffset(element) {
var offset = {
x: 0,
y: 0
};
var transform = getComputedStyle(element)[stylePrefix + 'Transform'];
var matched;
if (transform !== 'none') {
if (matched = transform.match(/^matrix3d\((?:[-\d.]+,\s*){12}([-\d.]+),\s*([-\d.]+)(?:,\s*[-\d.]+){2}\)/) || transform.match(/^matrix\((?:[-\d.]+,\s*){4}([-\d.]+),\s*([-\d.]+)\)$/)) {
offset.x = parseFloat(matched[1]) || 0;
offset.y = parseFloat(matched[2]) || 0;
}
}
return offset;
}
var CSSMatrix = IEMobile ? 'MSCSSMatrix' : 'WebKitCSSMatrix';
var has3d = !!Firefox || CSSMatrix in win && 'm11' in new win[CSSMatrix]();
function getTranslate(x, y) {
x = parseFloat(x);
y = parseFloat(y);
if (x !== 0) {
x += 'px';
}
if (y !== 0) {
y += 'px';
}
if (has3d) {
return 'translate3d(' + x + ', ' + y + ', 0)';
} else {
return 'translate(' + x + ', ' + y + ')';
}
}
function fireEvent(el, name, extra) {
var ev = doc.createEvent('HTMLEvents');
ev.initEvent(name, false, false);
if (extra) {
for (var key in extra) {
ev[key] = extra[key];
}
}
el.dispatchEvent(ev);
}
var Items = exports.Items = function () {
function Items(options) {
_classCallCheck(this, Items);
this.parentRoot = options.parentRoot;
this.parentElement = options.parentElement;
this.step = options.step;
this.length = 0;
this.index = 0;
this.transformOffset = 0;
}
_createClass(Items, [{
key: 'add',
value: function add(htmlElement) {
var itemElement = document.createElement('li');
if (typeof htmlElement === 'string') {
itemElement.innerHTML = htmlElement;
} else if (htmlElement.length > 1) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = htmlElement[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var el = _step.value;
itemElement.appendChild(el);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
} else if (htmlElement instanceof HTMLElement && htmlElement.tagName.toLowerCase() === 'li') {
itemElement = htmlElement;
} else {
itemElement.appendChild(htmlElement);
}
itemElement.style.display = 'none';
itemElement.style.position = 'absolute';
itemElement.index = this.length;
if (itemElement.parentNode !== this.parentElement) {
this.parentElement.appendChild(itemElement);
}
Object.defineProperty(this, String(this.length), {
get: function get() {
return itemElement;
}
});
this.length++;
return itemElement;
}
}, {
key: '_normalizeIndex',
value: function _normalizeIndex(index) {
while (index < 0) {
index += this.length;
}
while (index >= this.length) {
index -= this.length;
}
return index;
}
}, {
key: 'get',
value: function get(index) {
return this[String(this._normalizeIndex(index))];
}
}, {
key: '_getCloned',
value: function _getCloned(index) {
index = String(this._normalizeIndex(index));
var item = this.parentElement.querySelector('[cloned="cloned-' + index + '"]');
if (!item) {
item = this[index].cloneNode(true);
item.setAttribute('cloned', 'cloned-' + index);
item.index = index;
this.parentElement.appendChild(item);
}
return item;
}
}, {
key: '_activate',
value: function _activate(index) {
if (this.length === 0) {
return;
}
var curItem = this.get(index);
var prevItem = void 0;
var nextItem = void 0;
if (this.length > 1) {
prevItem = this.get(index - 1);
if (this.length === 2) {
nextItem = this._getCloned(index + 1);
fireEvent(this.parentRoot, 'clone', {
item: this.get(index + 1),
cloned: nextItem
});
} else {
nextItem = this.get(index + 1);
}
curItem.style.left = -this.transformOffset + 'px';
prevItem.style.left = -this.transformOffset - this.step + 'px';
prevItem.style.display = '';
nextItem.style.left = -this.transformOffset + this.step + 'px';
nextItem.style.display = '';
}
this.index = curItem.index;
curItem.style.display = '';
fireEvent(this.parentRoot, 'change', {
prevItem: prevItem,
curItem: curItem,
nextItem: nextItem
});
}
}, {
key: 'slide',
value: function slide(index) {
var _this = this;
if (this.length === 0) {
return;
}
if (this.length === 1) {
index = 0;
}
var startOffset = getTransformOffset(this.parentElement).x;
var endOffset = this.transformOffset + this.step * -index;
var interOffset = endOffset - startOffset;
if (interOffset === 0) {
return;
}
var anim = new _animationJs2.default(400, cubicbezier.ease, function (i1, i2) {
_this.parentElement.style[stylePrefix + 'Transform'] = getTranslate(startOffset + interOffset * i2, 0);
});
return anim.play().then(function () {
_this.transformOffset = endOffset;
_this.parentElement.style[stylePrefix + 'Transform'] = getTranslate(endOffset, 0);
index && _this._activate(_this.index + index);
});
}
}, {
key: 'next',
value: function next() {
this.slide(1);
}
}, {
key: 'prev',
value: function prev() {
this.slide(-1);
}
}]);
return Items;
}();
var incId = 0;
var Slider = function () {
function Slider() {
_classCallCheck(this, Slider);
this._initDom.apply(this, arguments);
this._initGestrue.apply(this, arguments);
this._isStarting = false;
this._isPlaying = false;
this._isSliding = false;
this._isPanning = false;
this._displacement;
this.playInterval = this.options.playInterval || 1500;
var autoplay = false;
var readyToPlay = false;
Object.defineProperty(this, 'autoplay', {
get: function get() {
return autoplay;
},
set: function set(v) {
var _this2 = this;
autoplay = !!v;
if (readyToPlay) {
clearTimeout(readyToPlay);
readyToPlay = false;
}
if (autoplay) {
readyToPlay = setTimeout(function () {
_this2.play();
}, 2000);
} else {
this.stop();
}
}
});
this.autoplay = !!this.options.autoplay;
}
_createClass(Slider, [{
key: '_initDom',
value: function _initDom() {
this.id = Date.now() + '-' + ++incId;
this.root = document.createDocumentFragment();
if (arguments.length === 1 && !((arguments.length <= 0 ? undefined : arguments[0]) instanceof HTMLElement)) {
this.element = null;
this.options = (arguments.length <= 0 ? undefined : arguments[0]) || {};
} else {
this.element = arguments.length <= 0 ? undefined : arguments[0];
this.options = (arguments.length <= 1 ? undefined : arguments[1]) || {};
}
if (!this.element) {
this.element = document.createElement('ul');
this.root.appendChild(this.element);
}
this.element.setAttribute('data-ctrl-name', 'slider');
this.element.setAttribute('data-ctrl-id', this.id);
this.element.style.position = 'relative';
this.element.style[stylePrefix + 'Transform'] = getTranslate(0, 0);
this.items = new Items({
parentRoot: this.root,
parentElement: this.element,
step: this.options.step || this.element.getBoundingClientRect().width
});
var itemElements = this.element.querySelectorAll('li');
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = itemElements[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var element = _step2.value;
this.items.add(element);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
}, {
key: '_initGestrue',
value: function _initGestrue() {
var _this3 = this;
if (this.options.useGesture) {
this.element.addEventListener('panstart', function (e) {
if (!e.isVertical && !(_this3._isPanning && _this3._isSliding)) {
e.preventDefault();
e.stopPropagation();
if (_this3.autoplay) {
_this3.stop();
}
_this3._displacement = 0;
_this3._isPanning = true;
}
});
this.element.addEventListener('panmove', function (e) {
if (!e.isVertical && _this3._isPanning) {
e.preventDefault();
e.stopPropagation();
_this3._displacement = e.displacementX;
_this3.element.style[stylePrefix + 'Transform'] = getTranslate(_this3.items.transformOffset + _this3._displacement, 0);
}
});
this.element.addEventListener('panend', function (e) {
if (!e.isVertical && _this3._isPanning) {
e.preventDefault();
e.stopPropagation();
_this3._isPanning = false;
if (e.isflick) {
if (_this3._displacement < 0) {
_this3.items.next();
} else {
_this3.items.prev();
}
} else {
if (Math.abs(_this3._displacement) < _this3.items.step / 2) {
_this3.items.slide(0);
} else {
_this3.items.slide(_this3._displacement < 0 ? 1 : -1);
}
}
if (_this3.autoplay) {
setTimeout(function () {
_this3.play();
}, 2000);
}
}
}, false);
this.element.addEventListener('flick', function (e) {
if (!e.isVertical) {
e.preventDefault();
e.stopPropagation();
}
});
}
}
}, {
key: 'play',
value: function play() {
var that = this;
if (!this._isStarting) {
this._isStarting = true;
return this.items._activate(0);
}
if (this._isPlaying) {
return;
}
function playing() {
that._isSliding = true;
that.items.next();
setTimeout(function () {
that._isSliding = false;
}, 500);
that._isPlaying = setTimeout(playing, 400 + that.playInterval);
}
this._isPlaying = setTimeout(playing, 400 + this.playInterval);
return this;
}
}, {
key: 'stop',
value: function stop() {
var _this4 = this;
if (!this._isPlaying) {
return;
}
clearTimeout(this._isPlaying);
setTimeout(function () {
_this4._isPlaying = false;
}, 500);
return this;
}
}, {
key: 'addEventListener',
value: function addEventListener(name, handler) {
this.root.addEventListener(name, handler, false);
return this;
}
}, {
key: 'removeEventListener',
value: function removeEventListener(name, handler) {
this.root.removeEventListener(name, handler, false);
return this;
}
}]);
return Slider;
}();
exports.default = Slider;