mobileSelect.js

/*!

* 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 =

    '

'+

        '

'+

            '

'+

                '

'+

                    '

'+ cancelText +'
'+

                    '

'+

                    '

'+ ensureText +'
'+

                '

'+

            '

'+

            '

'+

                '

'+

                '

'+

                '

'+

                    '

'+

                    '

'+

                '

'+

            '

'+

        '

';

    document.body.appendChild(_this.mobileSelect);

//根据数据长度来渲染

var tempHTML='';

for(var i=0; i

//列

tempHTML += '

    ';

    if(_this.jsonType){

    for(var j=0; j

    //行

    tempHTML += '

  • '+wheelsData[i].data[j][_this.keyMap.value]+'
  • ';

    }

    }else{

    for(var j=0; j

    //行

    tempHTML += '

  • '+wheelsData[i].data[j]+'
  • ';

    }

    }

    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.displayJson[i][j][_this.keyMap.value]+'
  • ';

    }

    _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 += '

    • '+_this.displayJson[i][j][_this.keyMap.value]+'
    • ';

      }

      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 += '

  • '+data[j][_this.keyMap.value]+'
  • ';

    }

    _this.wheelsData[sliderIndex] = {data: data};

        }else{

    for(var j=0; j

    tempHTML += '

  • '+data[j]+'
  • ';

    }

    _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;

    }

    })();

    你可能感兴趣的:(mobileSelect.js)