vue-weui-expand
Version:
WeUI 的轻量级 js 封装
266 lines (223 loc) • 9.44 kB
JavaScript
//picker已经写vue版本的,觉得很不方便调用,故重写了js版本的
import {_Substitute} from '../comm/comm.js'
function show ({data,setValue=[],level,yes,no,shadeClose=true}={}){
let items=[];
let options=[];
for(let i=0; i<level;i++){
options=[...options,{
init_location: 102,
pull_location_y: 0,
styleObject: 'transform:translate3d(0px, 102px, 0px);transition:all 0s ease 0s'
}];
}
//初始化数据
let recursive=function(d,l,f,de){
let items=[];
let child=undefined;
let tp=102;
let find=false;
d.forEach((el,index)=>{
items=[...items,{text:el.text,value:el.value}];
if(f>de.length-1){
if(index==0){
child=el.child;
}
}
else if(de[f]!=undefined && de[f]==el.value&&f<level){
//给默认项设置当前位置
options[f].init_location=tp;
options[f].styleObject='transform:translate3d(0px, '+tp+'px, 0px);transition:all 0s ease 0s';
find=true;
child=el.child;
}else if(de[f]!=undefined&&find==false){
tp-=34;//未找到位置当前位置向前排
}
});
l=[...l,items];
if(child!=undefined&&f<level){
//继续查找子项数据
l= recursive(child,l,(f+1),de);
}
return l;
}
let areaData=recursive.call(this,data,[],0,setValue);
items=areaData;//滚动数据实初始化,如果没有默认,显示第一个项数据
let tpl_itemBaseHtml=`
<div class="weui-picker__group" data-index="{index}">
<div class="weui-picker__mask" ></div>
<div class="weui-picker__indicator"></div>
<div class="weui-picker__content" style="{styleObject}">{items}</div>
</div>
`;
let tpl_itemHtml='<div class="weui-picker__item" >{text}</div>';
let r_itemHtml='';
for(let i=0; i<level;i++){
let itemsHtml='';
if(items[i]!=undefined){
items[i].forEach(el=>{
itemsHtml+=_Substitute(tpl_itemHtml,{text:el.text});
});
}
let html=_Substitute(tpl_itemBaseHtml,{styleObject:options[i].styleObject,items:itemsHtml,index:i});
r_itemHtml+=html;
}
var innerHtml=`
<div class="weui-mask weui-animate-fade-in" ></div>
<div class="weui-picker weui-animate-slide-up">
<div class="weui-picker__hd">
<a data-action="cancel" class="weui-picker__action" >取消</a>
<a data-action="select" class="weui-picker__action" >确定</a>
</div>
<div class="weui-picker__bd">
${r_itemHtml}
</div>
</div>
`;
let newNode = window.document.createElement("div");
newNode.id=Number(Math.random().toString().substr(3,length) + Date.now()).toString(36);
newNode.innerHTML = innerHtml;
window.document.getElementsByTagName('body')[0].appendChild(newNode);
//动态生成document后,给相关的document注册事件
let group= newNode.getElementsByClassName('weui-picker__group');
for(let i=0;i<group.length;i++){
group[i].addEventListener('touchstart',()=>{
let index=event.currentTarget.dataset.index;
options[index].pull_location_y=event.touches[0].clientY;
},false);
group[i].addEventListener('touchmove',()=>{
let index=event.currentTarget.dataset.index;
let tp=event.touches[0].clientY-options[index].pull_location_y+options[index].init_location;
//下/上拉动的时候,超出列表范围,最多空白34px
if(tp>136){
tp=136;
}
let len= data[index].length;
if(len>4){
if(tp<-((len-4+1)*34)){
tp=-((len-4+1)*34);
}
}else{
if(tp<102-((len)*34)){
tp=102-((len)*34);
}
}
options[index].styleObject='transform:translate3d(0px, '+tp+'px, 0px);transition:all 0s ease 0s';
newNode.getElementsByClassName('weui-picker__group')[index].getElementsByClassName('weui-picker__content')[0].style=options[index].styleObject;
},false);
group[i].addEventListener('touchend',()=>{
let index=event.currentTarget.dataset.index;
let tp=event.changedTouches[0].clientY-options[index].pull_location_y+options[index].init_location;
//下/上拉超同列表范围不得超过34px
if(tp>102){
tp=102;
}
let len= items[index].length;
if(len>4){
if(tp<-((len-4)*34)){
tp=-((len-4)*34);
}
}else{
if(tp<102-((len-1)*34)){
tp=102-((len-1)*34);
}
}
//处理必须选中一项
if(tp%34!=0)
{
if(tp%34>17)
{
tp=(parseInt(tp/34+1))*34;
}else{
tp=parseInt(tp/34)*34;
}
}
let oldpostion=options[index].init_location;//记录原来的位置
options[index].init_location=tp;//记录最后的位置,也是下一次的起始位置
//设置选项
options[index].styleObject='transform:translate3d(0px, '+tp+'px, 0px);transition:all 0.3s ease 0s';
newNode.getElementsByClassName('weui-picker__group')[index].getElementsByClassName('weui-picker__content')[0].style=options[index].styleObject;
//拖动时如果当前选项不变,即数据不需要变化
if(oldpostion!=tp){
//重置子项数据
let child=undefined;
options.forEach((el,f)=>{
if(f>index){
el.init_location=102;
el.styleObject='transform:translate3d(0px, 102px, 0px);transition:all 0.3s ease 0s';
}
let dataIndex=Math.abs((el.init_location-102))/34;
if(f>0){
if(child!=undefined){
if(child[dataIndex]!=undefined){
child=child[dataIndex].child;
}else{
child=[];
}
}
}else{
child=data[dataIndex].child;
}
if(child!=undefined){
items[f+1]=child.map(item=>{
return {text:item.text,value:item.value};
});
}else{
items[f+1]=[];
}
});
}
//chnage 到元素
for(let i=parseInt(index) +1;i<level;i++){
let itemsHtml='';
if(items[i].forEach){
items[i].forEach(el=>{
itemsHtml+=_Substitute(tpl_itemHtml,{text:el.text});
});
}
let currerNode=newNode.getElementsByClassName('weui-picker__content')[i];
currerNode.innerHTML=itemsHtml;
currerNode.style=options[i].styleObject;
}
},false);
}
let remove=function(){
let up= newNode.getElementsByClassName('weui-animate-fade-in');
if(up.length>0){
up[0].setAttribute('class','weui-mask weui-animate-fade-out');
}
let down= newNode.getElementsByClassName('weui-animate-slide-up');
if(down.length>0){
down[0].setAttribute('class','weui-picker weui-animate-slide-down');
}
setTimeout(function(){ window.document.getElementsByTagName('body')[0].removeChild(newNode);},300);
}
//回调事件注册
newNode.getElementsByClassName('weui-picker__action')[0].addEventListener('click',()=>{
remove();
if(no!=undefined)no();
},false);
newNode.getElementsByClassName('weui-mask')[0].addEventListener('click',()=>{
if(shadeClose){
remove();
if(no!=undefined)no();
}
},false);
newNode.getElementsByClassName('weui-picker__action')[1].addEventListener('click',()=>{
let r=[];
options.forEach((el,index)=>{
if(index<level){
let elindex= Math.abs((options[index].init_location-102))/34;
if(items[index]!=undefined&&items[index].length>0){
let item= items[index][elindex];
r=[...r,item];
}
}
});
remove();
if(yes!=undefined)yes(r);
},false);
}
function install(Vue){
Vue.prototype.picker={show};
}
export {show,install}