/** * 选择列表插件 * varstion 1.0.1 * by Houfeng * Houfeng@DCloud.io */ (function($, document) { //创建 DOM $.dom = function(str) { if (typeof(str) !== 'string') { if ((str instanceof Array) || (str[0] && str.length)) { return [].slice.call(str); } else { return [str]; } } if (!$.__create_dom_div__) { $.__create_dom_div__ = document.createElement('div'); } $.__create_dom_div__.innerHTML = str; return [].slice.call($.__create_dom_div__.childNodes); }; var _listpickerId = 0; var ListPicker = $.ListPicker = $.Class.extend({ init: function(box, options) { var self = this; if (!box) { throw "构造 ListPicker 时找不到元素"; } self.box = box; //避免重复初始化开始 if (self.box.listpickerId) return; self.listpickerId = self.box.listpickerId = "listpicker-" + (++_listpickerId); //避免重复初始化结束 self.box.setAttribute('data-listpicker-id', self.box.listpickerId); //处理 options options = options || {}; options.fiexdDur = options.fiexdDur || 150; options.highlightStyle = options.highlightStyle || 'color: green;'; //在 ios 上启用 h5 模式, if ($.os.ios) { options.enabledH5 = true; } //如果没有设定 enabled3d,将默认用 3d 模式 if (options.enabled3d === null || typeof options.enabled3d === 'undefined') { options.enabled3d = $.os.ios; } // self.options = options; self._create(); self._handleShim(); self._bindEvent(); self._applyToBox(); self._handleHighlight(); }, _create: function() { var self = this; self.boxInner = $('.mui-listpicker-inner', self.box)[0]; self.boxHeight = self.box.offsetHeight; self.list = $('ul', self.boxInner)[0]; //refresh 中会执行 self.itemElementArray = [].slice.call($('li', self.list)); self.refresh(); var firstItem = self.itemElementArray[0]; self.itemHeight = 0; if (firstItem) { self.itemHeight = firstItem.offsetHeight; } else { self.list.innerHTML = "
  • ...
  • "; firstItem = $('li', self.list)[0]; self.itemHeight = firstItem.offsetHeight; self.list.innerHTML = ''; } self.list.style.paddingTop = self.list.style.paddingBottom = (self.boxHeight / 2 - self.itemHeight / 2) + 'px'; //创建中间选中项的高亮行 self.rule = $.dom('
    ')[0]; self.rule.style.height = self.itemHeight + 'px'; self.rule.style.marginTop = -(self.itemHeight / 2) + 'px'; self.box.appendChild(self.rule); self.middle = self.boxInner.offsetHeight / 2; self.showLine = parseInt((self.boxInner.offsetHeight / self.itemHeight).toFixed(0)); //是否启用 3d 效果 if (self.options.enabled3d) { self.box.classList.add('three-dimensional'); } }, //根据 options 处理不同平台兼容问题 _handleShim: function() { var self = this; if (self.options.enabledH5) { self.options.fiexdDur *= 2; self.boxInner.classList.add($.className('scroll-wrapper')); self.list.classList.add($.className('scroll')); self._scrollerApi = $(self.boxInner).scroll({ deceleration: 0.002 }); //增加惯性滚动时的 scroll 触发处理 //shimTetTranslate(self._scrollerApi); //-- self.setScrollTop = function(y, dur, callback) { self._scrollerApi.scrollTo(0, -y, dur); }; self.getScrollTop = function() { var self = this; if (self._scrollerApi.lastY > 0) { return 0 } else { return Math.abs(self._scrollerApi.lastY); } }; } else { //alert(0); //为 boxInner 增加 scrollend 事件 (没有原生 scrollend 事件) self.boxInner.addEventListener('scroll', function(event) { if (self.disabledScroll) return; self.isScrolling = true; if (self.scrollTimer) { clearTimeout(self.scrollTimer); } self.scrollTimer = setTimeout(function() { self.isScrolling = false; if (!self.isTouchDown || !$.os.ios) { $.trigger(self.boxInner, 'scrollend'); } }, 150); }, false); self.aniScrollTop = function(y, dur, callback) { self.disabledScroll = true; var stepNum = dur > 0 ? dur / 10 : 1; var stepSize = (y - self.boxInner.scrollTop) / stepNum; self._lastScrollTop = self.boxInner.scrollTop; //记录最后的位置 self._aniScrollTop(y, 0, stepNum, stepSize, callback); }; self._aniScrollTop = function(y, stepIndex, stepNum, stepSize, callback) { self.boxInner.scrollTop = self._lastScrollTop + stepSize * stepIndex; if (stepIndex < stepNum) { setTimeout(function() { self._aniScrollTop(y, ++stepIndex, stepNum, stepSize); }, 10); } else { //self.boxInner.scrollTop = y; self.disabledScroll = false; if (callback) callback(); } }; self.setScrollTop = function(y, dur, callback) { self.aniScrollTop(y, dur); }; self.getScrollTop = function() { var self = this; return self.boxInner.scrollTop; }; //在 ios 上手指不弹起时,防止定位抖动开始 if ($.os.ios) { self.boxInner.addEventListener('touchstart', function(event) { var self = this; self.isTouchDown = true; }, false); self.boxInner.addEventListener('touchend', function(event) { self.isTouchDown = false; if (!self.isScrolling) { setTimeout(function() { $.trigger(self.boxInner, 'scrollend'); }, 0); } }, false); } //在 ios 上手指不弹起时,防止定位抖动结束 } }, _handleHighlight: function() { var self = this; var scrollTop = self.getScrollTop(); var fiexd = parseInt((scrollTop / self.itemHeight).toFixed(0)); var lastIndex = self.itemElementArray.length - 1; var displayRange = parseInt((self.showLine / 2).toFixed(0)); var displayBegin = fiexd - displayRange; var displayEnd = fiexd + displayRange; if (displayBegin < 0) { displayBegin = 0; } if (displayEnd > lastIndex) { displayEnd = lastIndex; } //高亮选中行开始 for (var index = displayBegin; index <= displayEnd; index++) { var itemElement = self.itemElementArray[index]; if (index == fiexd) { itemElement.classList.add($.className('listpicker-item-selected')); //itemElement.classList.remove($.className('listpicker-item-before')); //itemElement.classList.remove($.className('listpicker-item-after')); } else { //itemElement.classList.add($.className('listpicker-item-' + (fiexd > index ? 'before' : 'after'))); itemElement.classList.remove($.className('listpicker-item-selected')); } if (self.options.enabled3d) { //3d 处理开始 var itemOffset = self.middle - (itemElement.offsetTop - scrollTop + self.itemHeight / 2) + 1; var percentage = itemOffset / self.itemHeight; var angle = (18 * percentage); //if (angle > 180) angle = 180; //if (angle < -180) angle = -180; itemElement.style.webkitTransform = 'rotateX(' + angle + 'deg) translate3d(0px,0px,' + (0 - Math.abs(percentage * 12)) + 'px)'; //3d 处理结束 } } }, _triggerChange: function() { var self = this; $.trigger(self.box, 'change', { index: self.getSelectedIndex(), value: self.getSelectedValue(), text: self.getSelectedText(), item: self.getSelectedItem(), element: self.getSelectedElement() }); }, _scrollEndHandle: function() { var self = this; var scrollTop = self.getScrollTop(); var fiexd = (scrollTop / self.itemHeight).toFixed(0); self.disabledScrollEnd = true; self.setSelectedIndex(fiexd); self._triggerChange(); self._handleHighlight(); setTimeout(function() { self.disabledScrollEnd = false; self._handleHighlight(); }, self.options.fiexdDur); }, _bindEvent: function() { var self = this; //滚动处理高亮 self.boxInner.addEventListener('scroll', function(event) { self._handleHighlight(event); }, false); //处理滚动结束 self.disabledScrollEnd = false; self.boxInner.addEventListener('scrollend', function(event) { if (self.disabledScrollEnd) return; self.disabledScrollEnd = true; self._scrollEndHandle(); }, false); //绑定项 tap 事件 $(self.boxInner).on('tap', 'li', function(event) { var tapItem = this; var items = [].slice.call($('li', self.list)); for (var i in items) { var item = items[i]; if (item == tapItem) { self.setSelectedIndex(i); return; } }; }); }, getSelectedIndex: function() { var self = this; return (self.getScrollTop() / self.itemHeight).toFixed(0); }, setSelectedIndex: function(index, noAni) { var self = this; index = (index || 0); self.setScrollTop(self.itemHeight * index, noAni ? 0 : self.options.fiexdDur); }, getSelectedElement: function() { var self = this; var index = self.getSelectedIndex(); return $('li', self.list)[index]; }, getSelectedItem: function() { var self = this; var itemElement = self.getSelectedElement(); if (!itemElement) return null; var itemJson = itemElement.getAttribute('data-item'); return itemJson ? JSON.parse(itemJson) : { text: itemElement.innerText, value: itemElement.getAttribute('data-value') }; }, refresh: function() { var self = this; self.itemElementArray = [].slice.call($('li', self.list)); }, setItems: function(items) { var self = this; var buffer = []; for (index in items) { var item = items[index] || { text: 'null', value: 'null' + index }; var itemJson = JSON.stringify(item); buffer.push("
  • " + item.text + "
  • "); }; self.list.innerHTML = buffer.join(''); if (self._scrollerApi && self._scrollerApi.refresh) { self._scrollerApi.refresh(); } self.refresh(); self._handleHighlight(); self._triggerChange(); }, getItems: function() { var self = this; var items = []; var itemElements = $('li', self.list); for (index in itemElements) { var itemElement = itemElements[index]; var itemJson = itemElement.getAttribute('data-item'); items.push(itemJson ? JSON.parse(itemJson) : { text: itemElement.innerText, value: itemElement.getAttribute('data-value') }); } return items; }, getSelectedValue: function() { var self = this; var item = self.getSelectedItem(); if (!item) return null; return item.value; }, getSelectedText: function() { var self = this; var item = self.getSelectedItem(); if (!item) return null; return item.text; }, setSelectedValue: function(value, noAni) { var self = this; var itemElements = $('li', self.list); for (index in itemElements) { var itemElement = itemElements[index]; if (!itemElement || !itemElement.getAttribute) { continue; } if (itemElement.getAttribute('data-value') == value) { self.setSelectedIndex(index, noAni); return; } } }, _applyToBox: function() { var self = this; var memberArray = [ "getSelectedIndex", "setSelectedIndex", "getSelectedElement", "getSelectedItem", "setItems", "getItems", "getSelectedValue", "getSelectedText", "setSelectedValue" ]; var _clone = function(name) { if (typeof self[name] === 'function') { self.box[name] = function() { return self[name].apply(self, arguments); }; } else { self.box[name] = self[name]; } }; for (var i in memberArray) { var name = memberArray[i]; _clone(name); } } }); //添加 locker 插件 $.fn.listpicker = function(options) { //遍历选择的元素 this.each(function(i, element) { if (options) { new ListPicker(element, options); } else { var optionsText = element.getAttribute('data-listpicker-options'); var _options = optionsText ? JSON.parse(optionsText) : {}; _options.enabledH5 = element.getAttribute('data-listpicker-enabledh5') || _options.enabledH5; _options.enabled3d = element.getAttribute('data-listpicker-enabled3d') || _options.enabled3d; _options.fixedDur = element.getAttribute('data-listpicker-fixddur') || _options.fixedDur; new ListPicker(element, _options); } }); return this; }; //自动初始化 $.ready(function() { $('.mui-listpicker').listpicker(); }); })(mui, document);