123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- /**
- * 选择列表插件
- * 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 = "<li>...</li>";
- 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('<div class="mui-listpicker-rule"> </div>')[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("<li data-value='" + item.value + "' data-item='" + itemJson + "'>" + item.text + "</li>");
- };
- 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);
|