You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

406 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* snap 重构
* @param {Object} $
* @param {Object} window
*/
(function($, window) {
var CLASS_SLIDER = $.className('slider');
var CLASS_SLIDER_GROUP = $.className('slider-group');
var CLASS_SLIDER_LOOP = $.className('slider-loop');
var CLASS_SLIDER_INDICATOR = $.className('slider-indicator');
var CLASS_ACTION_PREVIOUS = $.className('action-previous');
var CLASS_ACTION_NEXT = $.className('action-next');
var CLASS_SLIDER_ITEM = $.className('slider-item');
var CLASS_ACTIVE = $.className('active');
var SELECTOR_SLIDER_ITEM = '.' + CLASS_SLIDER_ITEM;
var SELECTOR_SLIDER_INDICATOR = '.' + CLASS_SLIDER_INDICATOR;
var SELECTOR_SLIDER_PROGRESS_BAR = $.classSelector('.slider-progress-bar');
var Slider = $.Slider = $.Scroll.extend({
init: function(element, options) {
this._super(element, $.extend(true, {
fingers: 1,
interval: 0, //设置为0则不定时轮播
scrollY: false,
scrollX: true,
indicators: false,
scrollTime: 1000,
startX: false,
slideTime: 0, //滑动动画时间
snap: SELECTOR_SLIDER_ITEM
}, options));
if (this.options.startX) {
// $.trigger(this.wrapper, 'scrollend', this);
}
},
_init: function() {
this._reInit();
if (this.scroller) {
this.scrollerStyle = this.scroller.style;
this.progressBar = this.wrapper.querySelector(SELECTOR_SLIDER_PROGRESS_BAR);
if (this.progressBar) {
this.progressBarWidth = this.progressBar.offsetWidth;
this.progressBarStyle = this.progressBar.style;
}
//忘记这个代码是干什么的了?
// this.x = this._getScroll();
// if (this.options.startX === false) {
// this.options.startX = this.x;
// }
//根据active修正startX
this._super();
this._initTimer();
}
},
_triggerSlide: function() {
var self = this;
self.isInTransition = false;
var page = self.currentPage;
self.slideNumber = self._fixedSlideNumber();
if (self.loop) {
if (self.slideNumber === 0) {
self.setTranslate(self.pages[1][0].x, 0);
} else if (self.slideNumber === self.itemLength - 3) {
self.setTranslate(self.pages[self.itemLength - 2][0].x, 0);
}
}
if (self.lastSlideNumber != self.slideNumber) {
self.lastSlideNumber = self.slideNumber;
self.lastPage = self.currentPage;
$.trigger(self.wrapper, 'slide', {
slideNumber: self.slideNumber
});
}
self._initTimer();
},
_handleSlide: function(e) {
var self = this;
if (e.target !== self.wrapper) {
return;
}
var detail = e.detail;
detail.slideNumber = detail.slideNumber || 0;
var temps = self.scroller.querySelectorAll(SELECTOR_SLIDER_ITEM);
var items = [];
for (var i = 0, len = temps.length; i < len; i++) {
var item = temps[i];
if (item.parentNode === self.scroller) {
items.push(item);
}
}
var _slideNumber = detail.slideNumber;
if (self.loop) {
_slideNumber += 1;
}
if (!self.wrapper.classList.contains($.className('segmented-control'))) {
for (var i = 0, len = items.length; i < len; i++) {
var item = items[i];
if (item.parentNode === self.scroller) {
if (i === _slideNumber) {
item.classList.add(CLASS_ACTIVE);
} else {
item.classList.remove(CLASS_ACTIVE);
}
}
}
}
var indicatorWrap = self.wrapper.querySelector($.classSelector('.slider-indicator'));
if (indicatorWrap) {
if (indicatorWrap.getAttribute('data-scroll')) { //scroll
$(indicatorWrap).scroll().gotoPage(detail.slideNumber);
}
var indicators = indicatorWrap.querySelectorAll($.classSelector('.indicator'));
if (indicators.length > 0) { //图片轮播
for (var i = 0, len = indicators.length; i < len; i++) {
indicators[i].classList[i === detail.slideNumber ? 'add' : 'remove'](CLASS_ACTIVE);
}
} else {
var number = indicatorWrap.querySelector($.classSelector('.number span'));
if (number) { //图文表格
number.innerText = (detail.slideNumber + 1);
} else { //segmented controls
var controlItems = indicatorWrap.querySelectorAll($.classSelector('.control-item'));
for (var i = 0, len = controlItems.length; i < len; i++) {
controlItems[i].classList[i === detail.slideNumber ? 'add' : 'remove'](CLASS_ACTIVE);
}
}
}
}
e.stopPropagation();
},
_handleTabShow: function(e) {
var self = this;
self.gotoItem((e.detail.tabNumber || 0), self.options.slideTime);
},
_handleIndicatorTap: function(event) {
var self = this;
var target = event.target;
if (target.classList.contains(CLASS_ACTION_PREVIOUS) || target.classList.contains(CLASS_ACTION_NEXT)) {
self[target.classList.contains(CLASS_ACTION_PREVIOUS) ? 'prevItem' : 'nextItem']();
event.stopPropagation();
}
},
_initEvent: function(detach) {
var self = this;
self._super(detach);
var action = detach ? 'removeEventListener' : 'addEventListener';
self.wrapper[action]('slide', this);
self.wrapper[action]($.eventName('shown', 'tab'), this);
},
handleEvent: function(e) {
this._super(e);
switch (e.type) {
case 'slide':
this._handleSlide(e);
break;
case $.eventName('shown', 'tab'):
if (~this.snaps.indexOf(e.target)) { //避免嵌套监听错误的tab show
this._handleTabShow(e);
}
break;
}
},
_scrollend: function(e) {
this._super(e);
this._triggerSlide(e);
},
_drag: function(e) {
this._super(e);
var direction = e.detail.direction;
if (direction === 'left' || direction === 'right') {
//拖拽期间取消定时
var slidershowTimer = this.wrapper.getAttribute('data-slidershowTimer');
slidershowTimer && window.clearTimeout(slidershowTimer);
e.stopPropagation();
}
},
_initTimer: function() {
var self = this;
var slider = self.wrapper;
var interval = self.options.interval;
var slidershowTimer = slider.getAttribute('data-slidershowTimer');
slidershowTimer && window.clearTimeout(slidershowTimer);
if (interval) {
slidershowTimer = window.setTimeout(function() {
if (!slider) {
return;
}
//仅slider显示状态进行自动轮播
if (!!(slider.offsetWidth || slider.offsetHeight)) {
self.nextItem(true);
//下一个
}
self._initTimer();
}, interval);
slider.setAttribute('data-slidershowTimer', slidershowTimer);
}
},
_fixedSlideNumber: function(page) {
page = page || this.currentPage;
var slideNumber = page.pageX;
if (this.loop) {
if (page.pageX === 0) {
slideNumber = this.itemLength - 3;
} else if (page.pageX === (this.itemLength - 1)) {
slideNumber = 0;
} else {
slideNumber = page.pageX - 1;
}
}
return slideNumber;
},
_reLayout: function() {
this.hasHorizontalScroll = true;
this.loop = this.scroller.classList.contains(CLASS_SLIDER_LOOP);
this._super();
},
_getScroll: function() {
var result = $.parseTranslateMatrix($.getStyles(this.scroller, 'webkitTransform'));
return result ? result.x : 0;
},
_transitionEnd: function(e) {
if (e.target !== this.scroller || !this.isInTransition) {
return;
}
this._transitionTime();
this.isInTransition = false;
$.trigger(this.wrapper, 'scrollend', this);
},
_flick: function(e) {
if (!this.moved) { //无moved
return;
}
var detail = e.detail;
var direction = detail.direction;
this._clearRequestAnimationFrame();
this.isInTransition = true;
// if (direction === 'up' || direction === 'down') {
// this.resetPosition(this.options.bounceTime);
// return;
// }
if (e.type === 'flick') {
if (detail.deltaTime < 200) { //flick太容易触发额外校验一下deltaTime
this.x = this._getPage((this.slideNumber + (direction === 'right' ? -1 : 1)), true).x;
}
this.resetPosition(this.options.bounceTime);
} else if (e.type === 'dragend' && !detail.flick) {
this.resetPosition(this.options.bounceTime);
}
e.stopPropagation();
},
_initSnap: function() {
this.scrollerWidth = this.itemLength * this.scrollerWidth;
this.maxScrollX = Math.min(this.wrapperWidth - this.scrollerWidth, 0);
this._super();
if (!this.currentPage.x) {
//当slider处于隐藏状态时导致snap计算是错误的临时先这么判断一下后续要考虑解决所有scroll在隐藏状态下初始化属性不正确的问题
var currentPage = this.pages[this.loop ? 1 : 0];
currentPage = currentPage || this.pages[0];
if (!currentPage) {
return;
}
this.currentPage = currentPage[0];
this.slideNumber = 0;
this.lastSlideNumber = typeof this.lastSlideNumber === 'undefined' ? 0 : this.lastSlideNumber;
} else {
this.slideNumber = this._fixedSlideNumber();
this.lastSlideNumber = typeof this.lastSlideNumber === 'undefined' ? this.slideNumber : this.lastSlideNumber;
}
this.options.startX = this.currentPage.x || 0;
},
_getSnapX: function(offsetLeft) {
return Math.max(-offsetLeft, this.maxScrollX);
},
_getPage: function(slideNumber, isFlick) {
if (this.loop) {
if (slideNumber > (this.itemLength - (isFlick ? 2 : 3))) {
slideNumber = 1;
time = 0;
} else if (slideNumber < (isFlick ? -1 : 0)) {
slideNumber = this.itemLength - 2;
time = 0;
} else {
slideNumber += 1;
}
} else {
if (!isFlick) {
if (slideNumber > (this.itemLength - 1)) {
slideNumber = 0;
time = 0;
} else if (slideNumber < 0) {
slideNumber = this.itemLength - 1;
time = 0;
}
}
slideNumber = Math.min(Math.max(0, slideNumber), this.itemLength - 1);
}
return this.pages[slideNumber][0];
},
_gotoItem: function(slideNumber, time) {
this.currentPage = this._getPage(slideNumber, true); //此处传true。可保证程序切换时动画与人手操作一致(第一张,最后一张的切换动画)
this.scrollTo(this.currentPage.x, 0, time, this.options.scrollEasing);
if (time === 0) {
$.trigger(this.wrapper, 'scrollend', this);
}
},
//API
setTranslate: function(x, y) {
this._super(x, y);
var progressBar = this.progressBar;
if (progressBar) {
this.progressBarStyle.webkitTransform = this._getTranslateStr((-x * (this.progressBarWidth / this.wrapperWidth)), 0);
}
},
resetPosition: function(time) {
time = time || 0;
if (this.x > 0) {
this.x = 0;
} else if (this.x < this.maxScrollX) {
this.x = this.maxScrollX;
}
this.currentPage = this._nearestSnap(this.x);
this.scrollTo(this.currentPage.x, 0, time, this.options.scrollEasing);
return true;
},
gotoItem: function(slideNumber, time) {
this._gotoItem(slideNumber, typeof time === 'undefined' ? this.options.scrollTime : time);
},
nextItem: function() {
this._gotoItem(this.slideNumber + 1, this.options.scrollTime);
},
prevItem: function() {
this._gotoItem(this.slideNumber - 1, this.options.scrollTime);
},
getSlideNumber: function() {
return this.slideNumber || 0;
},
_reInit: function() {
var groups = this.wrapper.querySelectorAll('.' + CLASS_SLIDER_GROUP);
for (var i = 0, len = groups.length; i < len; i++) {
if (groups[i].parentNode === this.wrapper) {
this.scroller = groups[i];
break;
}
}
this.scrollerStyle = this.scroller && this.scroller.style;
if (this.progressBar) {
this.progressBarWidth = this.progressBar.offsetWidth;
this.progressBarStyle = this.progressBar.style;
}
},
refresh: function(options) {
if (options) {
$.extend(this.options, options);
this._super();
this._initTimer();
} else {
this._super();
}
},
destroy: function() {
this._initEvent(true); //detach
delete $.data[this.wrapper.getAttribute('data-slider')];
this.wrapper.setAttribute('data-slider', '');
}
});
$.fn.slider = function(options) {
var slider = null;
this.each(function() {
var sliderElement = this;
if (!this.classList.contains(CLASS_SLIDER)) {
sliderElement = this.querySelector('.' + CLASS_SLIDER);
}
if (sliderElement && sliderElement.querySelector(SELECTOR_SLIDER_ITEM)) {
var id = sliderElement.getAttribute('data-slider');
if (!id) {
id = ++$.uuid;
$.data[id] = slider = new Slider(sliderElement, options);
sliderElement.setAttribute('data-slider', id);
} else {
slider = $.data[id];
if (slider && options) {
slider.refresh(options);
}
}
}
});
return slider;
};
$.ready(function() {
// setTimeout(function() {
$($.classSelector('.slider')).slider();
$($.classSelector('.scroll-wrapper.slider-indicator.segmented-control')).scroll({
scrollY: false,
scrollX: true,
indicators: false,
snap: $.classSelector('.control-item')
});
// }, 500); //临时处理slider宽度计算不正确的问题(初步确认是scrollbar导致的)
});
})(mui, window);