hybridstart
Version:
A hybrid application development framework
308 lines (291 loc) • 13.6 kB
JavaScript
define(function(require, exports, module) {
"use strict";
seajs.importStyle('.multi-picker-locked{height:100%!important;overflow:hidden!important}.multi-picker-bg-delay{z-index:999!important}.multi-picker-bg{position:fixed;top:0;left:0;background:rgba(75,75,75,0);height:100%;width:100%;overflow:hidden;transition:all .3s ease;-webkit-transition:all .3s ease;z-index:-1}.multi-picker-bg-up{z-index:999!important;background:rgba(75,75,75,.65)!important}.multi-picker-container{width:100%;height:250px;position:absolute;bottom:0;transform:translate3d(0,101%,0);-webkit-transform:translate3d(0,101%,0);left:0;background-color:#FFF;transition:transform .3s ease;-webkit-transition:-webkit-transform .3s ease;z-index:-1}.multi-picker-container-up{transform:translate3d(0,0,0)!important;-webkit-transform:translate3d(0,0,0)!important}.multi-picker-btn-box{display:block;position:absolute;text-align:center;width:100%;height:50px;line-height:50px;background:rgba(218,218,218,.7);z-index:10}.multi-picker-btn-box .multi-picker-btn{position:absolute;display:inline-block;margin:0 20px;right:0}.multi-picker-btn-box .multi-picker-btn:nth-child(1){left:0;right:initial}.multi-picker-content{position:absolute;width:100%;background:#fff;font-size:0;top:50px;z-index:10;transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transition:transform .3s ease;-webkit-transition:-webkit-transform .3s ease}.multi-picker-content .multi-picker{display:inline-block;height:200px;overflow:hidden;position:relative;z-index:-1;transition:width .3s ease;vertical-align:top;top:0}.multi-picker-content ul::-webkit-scrollbar{display:none}.multi-picker-content li{height:40px;text-align:center;font-size:16px;line-height:40px;list-style:none;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.multi-picker-content .multi-picker-down-shadow,.multi-picker-content .multi-picker-up-shadow{position:absolute;width:100%;height:80px;pointer-events:none}.multi-picker-content .multi-picker-up-shadow{top:0;background-image:linear-gradient(to bottom,#FFF,rgba(255,255,255,0));z-index:50}.multi-picker-content .multi-picker-down-shadow{bottom:-200px;z-index:50;background-image:linear-gradient(to top,#FFF,rgba(255,255,255,0))}.multi-picker-content .multi-picker-line{width:95%;height:40px;position:absolute;top:80px;left:50%;pointer-events:none;box-sizing:border-box;border-top:1px solid #DCDCDC;border-bottom:1px solid #DCDCDC;transform:translate3d(-50%,0,0);-webkit-transform:translate3d(-50%,0,0)}',
module.uri);
/**
* Created by appian on 2016/11/4.
*/
var wid = window;
var doc = document;
function $id(id) {
return doc.getElementById(id);
}
function $class(name) {
return doc.getElementsByClassName(name);
}
function loop(begin, length, fuc) {
for ( var i = begin; i < length; i++ ) {
if (fuc(i)) break;
}
}
function on(action, selector, callback) {
doc.addEventListener(action, function (e) {
if (selector == e.target.tagName.toLowerCase() || selector == e.target.className || selector == e.target.id) {
callback(e);
}
})
}
function MultiPicker(config) {
this.input = config.input;
this.container = config.container;
this.jsonData = config.jsonData;
this.success = config.success;
this.ulCount = 0;
this.ulIdx = 0;
this.ulDomArr = [];
this.idxArr = [];
this.jsonArr = [];
this.liHeight = wid.lib ? parseInt(doc.getElementsByTagName('HTML')[0].style.fontSize) * 1 : 40;
this.maxHeight = [];
this.distance = [];
this.start = {
Y: 0,
time: ''
};
this.move = {
Y: 0,
speed: []
};
this.end = {
Y: 0,
status: true,
};
this.resultArr = [];
this.initDomFuc();
this.initReady(0, this.jsonData[0]);
this.initBinding();
}
MultiPicker.prototype = {
constructor: MultiPicker,
generateArrData: function (targetArr) {
var tempArr = [];
loop(0, targetArr.length, function (i) {
tempArr.push({
"id": targetArr[i].id,
"value": targetArr[i].value
})
});
return tempArr;
},
checkArrDeep: function (parent) {
var _this = this;
if ('child' in parent && parent.child.length > 0) {
_this.jsonArr.push(_this.generateArrData(parent.child));
_this.checkArrDeep(parent.child[0]);
}
_this.idxArr.push(this.ulIdx++);
},
insertLiArr: function (targetUl, arr) {
var html = '';
var nullObj = {
id: '-99',
value: '',
};
arr.unshift(nullObj, nullObj);
arr.push(nullObj, nullObj);
loop(0, arr.length, function (i) {
html += '<li data-id="' + arr[i].id + '">' + arr[i].value + '</li>';
});
targetUl.innerHTML = html;
},
initDomFuc: function () {
var _this = this;
var html = '';
html += '<div class="multi-picker-bg" id="multi-picker-bg-' + _this.container + '">'
+ '<div class="multi-picker-container" id="multi-picker-container-' + _this.container + '">'
+ '<div class="multi-picker-btn-box">'
+ '<div class="multi-picker-btn text-primary" id="multi-picker-btn-cancel">返回</div>'
+ '<div class="multi-picker-btn text-primary" id="multi-picker-btn-save-' + _this.container + '">确定</div>'
+ '</div>'
+ '<div class="multi-picker-content">'
+ '<div class="multi-picker-up-shadow"></div>'
+ '<div class="multi-picker-down-shadow"></div>'
+ '<div class="multi-picker-line"></div>'
+ '</div></div></div>';
$id(_this.container).innerHTML = html;
_this.jsonArr.push(_this.generateArrData(_this.jsonData));
},
initReady: function (idx, target) {
var _this = this;
this.ulIdx = 0;
this.idxArr.length = idx;
_this.jsonArr.length = idx + 1;
_this.checkArrDeep(target);
var parentNode = $id('multi-picker-container-' + _this.container).children[1];
var tempMax = _this.ulCount <= _this.idxArr.length ? _this.ulCount : _this.idxArr.length;
loop(idx + 1, tempMax, function (i) {
var $picker = $id('multi-picker-' + _this.container + '-' + i);
_this.insertLiArr($picker, _this.jsonArr[i]);
_this.distance[i] = 0;
$picker.style.transform = 'translate3d(0, 0, 0)';
$picker.style.webkitTransform = 'translate3d(0, 0, 0)';
});
if (_this.ulCount <= _this.idxArr.length) {
loop(_this.ulCount, _this.idxArr.length, function (i) {
var newPickerDiv = document.createElement('div');
newPickerDiv.setAttribute('class', 'multi-picker');
newPickerDiv.innerHTML = '<ul id="multi-picker-' + _this.container + '-' + i + '"></ul>';
parentNode.insertBefore(newPickerDiv, parentNode.children[parentNode.children.length - 3]);
var tempDomUl = $id('multi-picker-' + _this.container + '-' + i);
_this.ulDomArr.push(tempDomUl);
_this.distance.push(0);
_this.insertLiArr(tempDomUl, _this.jsonArr[i]);
var tempArray = _this.jsonArr[i];
tempDomUl.addEventListener('touchstart', function () {
_this.touch(event, _this, tempDomUl, tempArray, i);
}, false);
tempDomUl.addEventListener('touchmove', function () {
_this.touch(event, _this, tempDomUl, tempArray, i);
}, false);
tempDomUl.addEventListener('touchend', function () {
_this.touch(event, _this, tempDomUl, tempArray, i);
}, true);
});
} else {
for ( var j = _this.ulCount - 1; j > _this.idxArr.length - 1; j-- ) {
var oldPicker = $id(_this.container).querySelectorAll('.multi-picker')[j];
oldPicker.parentNode.removeChild(oldPicker);
_this.ulDomArr.pop();
_this.distance.pop();
}
}
_this.maxHeight.length = 0;
_this.resultArr.length = 0;
loop(0, _this.idxArr.length, function (i) {
$id(_this.container).querySelectorAll('.multi-picker')[i].style.width = 100 / _this.idxArr.length + '%';
_this.maxHeight.push($id('multi-picker-' + _this.container + '-' + i).childNodes.length * _this.liHeight);
_this.resultArr.push({
"id": _this.jsonArr[i][_this.distance[i] / _this.liHeight + 2].id,
"value": _this.jsonArr[i][_this.distance[i] / _this.liHeight + 2].value,
"index": _this.distance[i] / _this.liHeight
});
});
_this.ulCount = _this.idxArr.length;
},
initBinding: function () {
var _this = this;
var bg = $id('multi-picker-bg-' + _this.container);
var container = $id('multi-picker-container-' + _this.container);
var body = doc.body;
on('touchstart', _this.input, function () {
bg.classList.add('multi-picker-bg-up', 'multi-picker-bg-delay');
container.classList.add('multi-picker-container-up');
body.classList.add('multi-picker-locked');
}, false);
on('touchstart', 'multi-picker-btn-save-' + _this.container, function () {
_this.success(_this.resultArr);
bg.classList.remove('multi-picker-bg-up');
container.classList.remove('multi-picker-container-up');
setTimeout(function () {
bg.classList.remove('multi-picker-bg-delay');
}, 350);
body.classList.remove('multi-picker-locked');
}, false);
on('touchstart', 'multi-picker-bg-' + _this.container, function () {
bg.classList.remove('multi-picker-bg-up');
container.classList.remove('multi-picker-container-up');
setTimeout(function () {
bg.classList.remove('multi-picker-bg-delay');
}, 350);
body.classList.remove('multi-picker-locked');
}, false);
on('touchstart', 'multi-picker-btn-cancel', function () {
bg.classList.remove('multi-picker-bg-up');
container.classList.remove('multi-picker-container-up');
setTimeout(function () {
bg.classList.remove('multi-picker-bg-delay');
}, 350);
body.classList.remove('multi-picker-locked');
}, false);
},
checkRange: function (idx) {
var _this = this;
var tempObj = _this.jsonData;
var targetIdx = 0;
loop(0, idx + 1, function (i) {
targetIdx = _this.distance[i] / _this.liHeight;
tempObj = i == 0 ? tempObj[targetIdx] : tempObj.child[targetIdx];
});
_this.initReady(idx, tempObj);
},
initPosition: function (dis, max, idx) {
dis = dis < 0 ? 0 : dis;
dis = dis > max ? max : dis;
var sub = dis % this.liHeight;
if (sub < this.liHeight / 2) {
this.distance[idx] = dis - sub;
} else {
this.distance[idx] = dis + (this.liHeight - sub);
}
return this;
},
initSpeed: function (arr, dir, max, idx) {
var variance = 0;
var sum = 0;
var rate = 0;
for ( var i in arr ) {
sum += arr[i] - 0;
}
for ( var j in arr ) {
variance += (arr[j] - (sum / arr.length)) * (arr[j] - (sum / arr.length));
}
if ((variance / arr.length).toFixed(2) > .1) {
rate = max > this.liHeight * 15 ? dir * 2 : 0;
this.initPosition(this.distance[idx] + rate, max - this.liHeight * 5, idx);
this.move.speed[0] = .2;
} else {
this.initPosition(this.distance[idx], max, idx);
this.move.speed[0] = this.move.speed[0] > 0.2 ? .2 : this.move.speed[0];
}
},
touch: function (event, that, $picker, array, idx) {
event = event || window.event;
event.preventDefault();
switch (event.type) {
case "touchstart":
if (that.end.status) {
that.end.status = !that.end.status;
event.preventDefault();
that.move.speed = [];
that.start.Y = event.touches[0].clientY;
that.start.time = Date.now();
}
break;
case "touchend":
that.end.Y = Math.abs(event.changedTouches[0].clientY);
var tempDis = that.distance[idx] + (that.start.Y - that.end.Y);
var temp = that.distance[idx];
that.distance[idx] = tempDis < 0 ? 0 : (tempDis < that.maxHeight[idx] - this.liHeight * 5 ? tempDis : that.maxHeight[idx] - this.liHeight * 5);
that.initSpeed(that.move.speed, that.start.Y - that.end.Y, that.maxHeight[idx], idx);
$picker.style.transform = 'translate3d(0,-' + that.distance[idx] + 'px, 0)';
$picker.style.webkitTransform = 'translate3d(0,-' + that.distance[idx] + 'px, 0)';
$picker.style.transition = 'transform ' + that.move.speed[0] + 's ease-out';
$picker.style.webkitTransition = '-webkit-transform ' + that.move.speed[0] + 's ease-out';
if (temp != that.distance[idx]) that.checkRange(idx);
setTimeout(function () {
that.end.status = true;
}, that.move.speed[0] * 1000);
break;
case "touchmove":
event.preventDefault();
that.move.Y = event.touches[0].clientY;
var offset = that.start.Y - that.move.Y;
if (that.distance[idx] == 0 && offset < 0) {
$picker.style.transform = 'translate3d(0,' + 1.5 * that.liHeight + 'px, 0)';
$picker.style.webkitTransform = 'translate3d(0,' + 1.5 * that.liHeight + 'px, 0)';
$picker.style.transition = 'transform 0.2s ease-out';
$picker.style.webkitTransition = '-webkit-transform 0.2s ease-out';
} else {
$picker.style.transform = 'translate3d(0,-' + (offset + that.distance[idx]) + 'px, 0)';
$picker.style.webkitTransform = 'translate3d(0,-' + (offset + that.distance[idx]) + 'px, 0)';
}
if (Math.abs(offset).toFixed(0) % 5 === 0) {
var time = Date.now();
that.move.speed.push((Math.abs(offset) / (time - that.start.time)).toFixed(2));
}
break;
}
}
};
module.exports = MultiPicker;
});