123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- /**
- * 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);
|