/*!
* mobileSelect.js
* (c) 2017-present onlyhom
* Released under the MIT License.
*/
(function() {
function getClass(dom,string) {
return dom.getElementsByClassName(string);
}
//构造器
function MobileSelect(config) {
this.mobileSelect;
this.wheelsData = config.wheels;
this.jsonType = false;
this.cascadeJsonData = [];
this.displayJson = [];
this.cascade = false;
this.startY;
this.moveEndY;
this.moveY;
this.oldMoveY;
this.offset = 0;
this.offsetSum = 0;
this.oversizeBorder;
this.curDistance = [];
this.clickStatus = false;
this.isPC = true;
this.init(config);
}
MobileSelect.prototype = {
constructor: MobileSelect,
init: function(config){
var _this = this;
_this.keyMap = config.keyMap ? config.keyMap : {id:'id', value:'value', childs:'childs'};
_this.checkDataType();
_this.renderWheels(_this.wheelsData, config.cancelBtnText, config.ensureBtnText);
_this.trigger = document.querySelector(config.trigger);
if(!_this.trigger){
console.error('mobileSelect has been successfully installed, but no trigger found on your page.');
return false;
}
_this.wheel = getClass(_this.mobileSelect,'wheel');
_this.slider = getClass(_this.mobileSelect,'selectContainer');
_this.wheels = _this.mobileSelect.querySelector('.wheels');
_this.liHeight = _this.mobileSelect.querySelector('li').offsetHeight;
_this.ensureBtn = _this.mobileSelect.querySelector('.ensure');
_this.cancelBtn = _this.mobileSelect.querySelector('.cancel');
_this.grayLayer = _this.mobileSelect.querySelector('.grayLayer');
_this.popUp = _this.mobileSelect.querySelector('.content');
_this.callback = config.callback ? config.callback : function(){};
_this.transitionEnd = config.transitionEnd ? config.transitionEnd : function(){};
_this.initPosition = config.position ? config.position : [];
_this.titleText = config.title ? config.title : '';
_this.connector = config.connector ? config.connector : ' ';
_this.trigger.style.cursor='pointer';
_this.setStyle(config);
_this.setTitle(_this.titleText);
_this.checkIsPC();
_this.checkCascade();
if (_this.cascade) {
_this.initCascade();
}
//定位 初始位置
if(_this.initPosition.length < _this.slider.length){
var diff = _this.slider.length - _this.initPosition.length;
for(var i=0; i _this.initPosition.push(0); } } _this.setCurDistance(_this.initPosition); _this.addListenerAll(); //按钮监听 _this.cancelBtn.addEventListener('click',function(){ _this.mobileSelect.classList.remove('mobileSelect-show'); }); _this.ensureBtn.addEventListener('click',function(){ _this.mobileSelect.classList.remove('mobileSelect-show'); var tempValue =''; for(var i=0; i<_this.wheel.length; i++){ i==_this.wheel.length-1 ? tempValue += _this.getInnerHtml(i) : tempValue += _this.getInnerHtml(i) + _this.connector; } _this.trigger.innerHTML = tempValue; _this.callback(_this.getIndexArr(),_this.getValue()); }); _this.trigger.addEventListener('click',function(){ _this.mobileSelect.classList.add('mobileSelect-show'); }); _this.grayLayer.addEventListener('click',function(){ _this.mobileSelect.classList.remove('mobileSelect-show'); }); _this.popUp.addEventListener('click',function(){ event.stopPropagation(); }); _this.fixRowStyle(); //修正列数 }, setTitle: function(string){ var _this = this; _this.titleText = string; _this.mobileSelect.querySelector('.title').innerHTML = _this.titleText; }, setStyle: function(config){ var _this = this; if(config.ensureBtnColor){ _this.ensureBtn.style.color = config.ensureBtnColor; } if(config.cancelBtnColor){ _this.cancelBtn.style.color = config.cancelBtnColor; } if(config.titleColor){ _this.title = _this.mobileSelect.querySelector('.title'); _this.title.style.color = config.titleColor; } if(config.textColor){ _this.panel = _this.mobileSelect.querySelector('.panel'); _this.panel.style.color = config.textColor; } if(config.titleBgColor){ _this.btnBar = _this.mobileSelect.querySelector('.btnBar'); _this.btnBar.style.backgroundColor = config.titleBgColor; } if(config.bgColor){ _this.panel = _this.mobileSelect.querySelector('.panel'); _this.shadowMask = _this.mobileSelect.querySelector('.shadowMask'); _this.panel.style.backgroundColor = config.bgColor; _this.shadowMask.style.background = 'linear-gradient(to bottom, '+ config.bgColor + ', rgba(255, 255, 255, 0), '+ config.bgColor + ')'; } }, checkIsPC: function(){ var _this = this; var sUserAgent = navigator.userAgent.toLowerCase(); var bIsIpad = sUserAgent.match(/ipad/i) == "ipad"; var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os"; var bIsMidp = sUserAgent.match(/midp/i) == "midp"; var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4"; var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb"; var bIsAndroid = sUserAgent.match(/android/i) == "android"; var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce"; var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile"; if ((bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM)) { _this.isPC = false; } }, show: function(){ this.mobileSelect.classList.add('mobileSelect-show'); }, renderWheels: function(wheelsData, cancelBtnText, ensureBtnText){ var _this = this; var cancelText = cancelBtnText ? cancelBtnText : '取消'; var ensureText = ensureBtnText ? ensureBtnText : '确认'; _this.mobileSelect = document.createElement("div"); _this.mobileSelect.className = "mobileSelect"; _this.mobileSelect.innerHTML = '
'
'
'
'
'
'+'
'
'
'
'
'
'
'
'+'
'+'
'
'
document.body.appendChild(_this.mobileSelect);
//根据数据长度来渲染
var tempHTML='';
for(var i=0; i //列 tempHTML += ' if(_this.jsonType){ for(var j=0; j //行 tempHTML += ' } }else{ for(var j=0; j //行 tempHTML += ' } } tempHTML += '';
}
_this.mobileSelect.querySelector('.wheels').innerHTML = tempHTML;
},
addListenerAll: function(){
var _this = this;
for(var i=0; i<_this.slider.length; i++){
//手势监听
(function (i) {
_this.addListenerWheel(_this.wheel[i], i);
_this.addListenerLi(i);
})(i);
}
},
addListenerWheel: function(theWheel, index){
var _this = this;
theWheel.addEventListener('touchstart', function () {
_this.touch(event, this.firstChild, index);
},false);
theWheel.addEventListener('touchend', function () {
_this.touch(event, this.firstChild, index);
},false);
theWheel.addEventListener('touchmove', function () {
_this.touch(event, this.firstChild, index);
},false);
if(_this.isPC){
//如果是PC端则再增加拖拽监听 方便调试
theWheel.addEventListener('mousedown', function () {
_this.dragClick(event, this.firstChild, index);
},false);
theWheel.addEventListener('mousemove', function () {
_this.dragClick(event, this.firstChild, index);
},false);
theWheel.addEventListener('mouseup', function () {
_this.dragClick(event, this.firstChild, index);
},true);
}
},
addListenerLi:function(sliderIndex){
var _this = this;
var curWheelLi = _this.slider[sliderIndex].getElementsByTagName('li');
for(var j=0; j (function (j) { curWheelLi[j].addEventListener('click',function(){ _this.singleClick(this, j, sliderIndex); },false); })(j); } }, checkDataType: function(){ var _this = this; if(typeof(_this.wheelsData[0].data[0])=='object'){ _this.jsonType = true; } }, checkCascade: function(){ var _this = this; if(_this.jsonType){ var node = _this.wheelsData[0].data; for(var i=0; i if(_this.keyMap.childs in node[i] && node[i][_this.keyMap.childs].length > 0){ _this.cascade = true; _this.cascadeJsonData = _this.wheelsData[0].data; break; } } }else{ _this.cascade = false; } }, generateArrData: function (targetArr) { var tempArr = []; var keyMap_id = this.keyMap.id; var keyMap_value = this.keyMap.value; for(var i=0; i var tempObj = {}; tempObj[keyMap_id] = targetArr[i][this.keyMap.id]; tempObj[keyMap_value] = targetArr[i][this.keyMap.value]; tempArr.push(tempObj); } return tempArr; }, initCascade: function(){ var _this = this; _this.displayJson.push(_this.generateArrData(_this.cascadeJsonData)); if(_this.initPosition.length>0){ _this.initDeepCount = 0; _this.initCheckArrDeep(_this.cascadeJsonData[_this.initPosition[0]]); }else{ _this.checkArrDeep(_this.cascadeJsonData[0]); } _this.reRenderWheels(); }, initCheckArrDeep: function (parent) { var _this = this; if(parent){ if (_this.keyMap.childs in parent && parent[_this.keyMap.childs].length > 0) { _this.displayJson.push(_this.generateArrData(parent[_this.keyMap.childs])); _this.initDeepCount++; var nextNode = parent[_this.keyMap.childs][_this.initPosition[_this.initDeepCount]]; if(nextNode){ _this.initCheckArrDeep(nextNode); }else{ _this.checkArrDeep(parent[_this.keyMap.childs][0]); } } } }, checkArrDeep: function (parent) { //检测子节点深度 修改 displayJson var _this = this; if(parent){ if (_this.keyMap.childs in parent && parent[_this.keyMap.childs].length > 0) { _this.displayJson.push(_this.generateArrData(parent[_this.keyMap.childs])); //生成子节点数组 _this.checkArrDeep(parent[_this.keyMap.childs][0]);//检测下一个子节点 } } }, checkRange: function(index, posIndexArr){ var _this = this; var deleteNum = _this.displayJson.length-1-index; for(var i=0; i _this.displayJson.pop(); //修改 displayJson } var resultNode; for (var i = 0; i <= index; i++){ if (i == 0) resultNode = _this.cascadeJsonData[posIndexArr[0]]; else { resultNode = resultNode[_this.keyMap.childs][posIndexArr[i]]; } } _this.checkArrDeep(resultNode); //console.log(_this.displayJson); _this.reRenderWheels(); _this.fixRowStyle(); _this.setCurDistance(_this.resetPostion(index, posIndexArr)); }, resetPostion: function(index, posIndexArr){ var _this = this; var tempPosArr = posIndexArr; var tempCount; if(_this.slider.length > posIndexArr.length){ tempCount = _this.slider.length - posIndexArr.length; for(var i=0; i tempPosArr.push(0); } }else if(_this.slider.length < posIndexArr.length){ tempCount = posIndexArr.length - _this.slider.length; for(var i=0; i tempPosArr.pop(); } } for(var i=index+1; i< tempPosArr.length; i++){ tempPosArr[i] = 0; } return tempPosArr; }, reRenderWheels: function(){ var _this = this; //删除多余的wheel if(_this.wheel.length > _this.displayJson.length){ var count = _this.wheel.length - _this.displayJson.length; for(var i=0; i _this.wheels.removeChild(_this.wheel[_this.wheel.length-1]); } } for(var i=0; i<_this.displayJson.length; i++){ //列 (function (i) { var tempHTML=''; if(_this.wheel[i]){ //console.log('插入Li'); for(var j=0; j<_this.displayJson[i].length; j++){ //行 tempHTML += ' } _this.slider[i].innerHTML = tempHTML; }else{ var tempWheel = document.createElement("div"); tempWheel.className = "wheel"; tempHTML = ' for(var j=0; j<_this.displayJson[i].length; j++){ //行 tempHTML += ' } tempHTML += ''; tempWheel.innerHTML = tempHTML; _this.addListenerWheel(tempWheel, i); _this.wheels.appendChild(tempWheel); } _this.addListenerLi(i); })(i); } }, updateWheels:function(data){ var _this = this; if(_this.cascade){ _this.cascadeJsonData = data; _this.displayJson = []; _this.initCascade(); if(_this.initPosition.length < _this.slider.length){ var diff = _this.slider.length - _this.initPosition.length; for(var i=0; i _this.initPosition.push(0); } } _this.setCurDistance(_this.initPosition); _this.fixRowStyle(); } }, updateWheel: function(sliderIndex, data){ var _this = this; var tempHTML=''; if(_this.cascade){ console.error('级联格式不支持updateWheel(),请使用updateWheels()更新整个数据源'); return false; } else if(_this.jsonType){ for(var j=0; j tempHTML += ' } _this.wheelsData[sliderIndex] = {data: data}; }else{ for(var j=0; j tempHTML += ' } _this.wheelsData[sliderIndex] = data; } _this.slider[sliderIndex].innerHTML = tempHTML; _this.addListenerLi(sliderIndex); }, fixRowStyle: function(){ var _this = this; var width = (100/_this.wheel.length).toFixed(2); for(var i=0; i<_this.wheel.length; i++){ _this.wheel[i].style.width = width+'%'; } }, getIndex: function(distance){ return Math.round((2*this.liHeight-distance)/this.liHeight); }, getIndexArr: function(){ var _this = this; var temp = []; for(var i=0; i<_this.curDistance.length; i++){ temp.push(_this.getIndex(_this.curDistance[i])); } return temp; }, getValue: function(){ var _this = this; var temp = []; var positionArr = _this.getIndexArr(); if(_this.cascade){ for(var i=0; i<_this.wheel.length; i++){ temp.push(_this.displayJson[i][positionArr[i]]); } } else if(_this.jsonType){ for(var i=0; i<_this.curDistance.length; i++){ temp.push(_this.wheelsData[i].data[_this.getIndex(_this.curDistance[i])]); } }else{ for(var i=0; i<_this.curDistance.length; i++){ temp.push(_this.getInnerHtml(i)); } } return temp; }, calcDistance: function(index){ return 2*this.liHeight-index*this.liHeight; }, setCurDistance: function(indexArr){ var _this = this; var temp = []; for(var i=0; i<_this.slider.length; i++){ temp.push(_this.calcDistance(indexArr[i])); _this.movePosition(_this.slider[i],temp[i]); } _this.curDistance = temp; }, fixPosition: function(distance){ return -(this.getIndex(distance)-2)*this.liHeight; }, movePosition: function(theSlider, distance){ theSlider.style.webkitTransform = 'translate3d(0,' + distance + 'px, 0)'; theSlider.style.transform = 'translate3d(0,' + distance + 'px, 0)'; }, locatePostion: function(index, posIndex){ this.curDistance[index] = this.calcDistance(posIndex); this.movePosition(this.slider[index],this.curDistance[index]); }, updateCurDistance: function(theSlider, index){ this.curDistance[index] = parseInt(theSlider.style.transform.split(',')[1]); }, getDistance:function(theSlider){ return parseInt(theSlider.style.transform.split(',')[1]); }, getInnerHtml: function(sliderIndex){ var _this = this; var index = _this.getIndex(_this.curDistance[sliderIndex]); return _this.slider[sliderIndex].getElementsByTagName('li')[index].innerHTML; }, touch: function(event, theSlider, index){ var _this = this; event = event || window.event; switch(event.type){ case "touchstart": _this.startY = event.touches[0].clientY; _this.oldMoveY = _this.startY; break; case "touchend": _this.moveEndY = event.changedTouches[0].clientY; _this.offsetSum = _this.moveEndY - _this.startY; //修正位置 _this.updateCurDistance(theSlider, index); _this.curDistance[index] = _this.fixPosition(_this.curDistance[index]); _this.movePosition(theSlider, _this.curDistance[index]); _this.oversizeBorder = -(theSlider.getElementsByTagName('li').length-3)*_this.liHeight; //反弹 if(_this.curDistance[index] + _this.offsetSum > 2*_this.liHeight){ _this.curDistance[index] = 2*_this.liHeight; setTimeout(function(){ _this.movePosition(theSlider, _this.curDistance[index]); }, 100); }else if(_this.curDistance[index] + _this.offsetSum < _this.oversizeBorder){ _this.curDistance[index] = _this.oversizeBorder; setTimeout(function(){ _this.movePosition(theSlider, _this.curDistance[index]); }, 100); } _this.transitionEnd(_this.getIndexArr(),_this.getValue()); if(_this.cascade){ var tempPosArr = _this.getIndexArr(); tempPosArr[index] = _this.getIndex(_this.curDistance[index]); _this.checkRange(index, tempPosArr); } break; case "touchmove": event.preventDefault(); _this.moveY = event.touches[0].clientY; _this.offset = _this.moveY - _this.oldMoveY; _this.updateCurDistance(theSlider, index); _this.curDistance[index] = _this.curDistance[index] + _this.offset; _this.movePosition(theSlider, _this.curDistance[index]); _this.oldMoveY = _this.moveY; break; } }, dragClick: function(event, theSlider, index){ var _this = this; event = event || window.event; switch(event.type){ case "mousedown": _this.startY = event.clientY; _this.oldMoveY = _this.startY; _this.clickStatus = true; break; case "mouseup": _this.moveEndY = event.clientY; _this.offsetSum = _this.moveEndY - _this.startY; //修正位置 _this.updateCurDistance(theSlider, index); _this.curDistance[index] = _this.fixPosition(_this.curDistance[index]); _this.movePosition(theSlider, _this.curDistance[index]); _this.oversizeBorder = -(theSlider.getElementsByTagName('li').length-3)*_this.liHeight; //反弹 if(_this.curDistance[index] + _this.offsetSum > 2*_this.liHeight){ _this.curDistance[index] = 2*_this.liHeight; setTimeout(function(){ _this.movePosition(theSlider, _this.curDistance[index]); }, 100); }else if(_this.curDistance[index] + _this.offsetSum < _this.oversizeBorder){ _this.curDistance[index] = _this.oversizeBorder; setTimeout(function(){ _this.movePosition(theSlider, _this.curDistance[index]); }, 100); } _this.clickStatus = false; _this.transitionEnd(_this.getIndexArr(),_this.getValue()); if(_this.cascade){ var tempPosArr = _this.getIndexArr(); tempPosArr[index] = _this.getIndex(_this.curDistance[index]); _this.checkRange(index, tempPosArr); } break; case "mousemove": event.preventDefault(); if(_this.clickStatus){ _this.moveY = event.clientY; _this.offset = _this.moveY - _this.oldMoveY; _this.updateCurDistance(theSlider, index); _this.curDistance[index] = _this.curDistance[index] + _this.offset; _this.movePosition(theSlider, _this.curDistance[index]); _this.oldMoveY = _this.moveY; } break; } }, singleClick: function(theLi, index, sliderIndex){ var _this = this; if(_this.cascade){ var tempPosArr = _this.getIndexArr(); tempPosArr[sliderIndex] = index; _this.checkRange(sliderIndex, tempPosArr); }else{ _this.curDistance[sliderIndex] = (2-index)*_this.liHeight; _this.movePosition(theLi.parentNode, _this.curDistance[sliderIndex]); } } }; if (typeof exports == "object") { module.exports = MobileSelect; } else if (typeof define == "function" && define.amd) { define([], function () { return MobileSelect; }) } else { window.MobileSelect = MobileSelect; } })();';