tui-drag.wxs 8.57 KB
var _st = {}

function isPC() {
	if (typeof navigator !== 'object') return false;
	var userAgentInfo = navigator.userAgent;
	var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
	var flag = true;
	for (var v = 0; v < Agents.length - 1; v++) {
		if (userAgentInfo.indexOf(Agents[v]) > 0) {
			flag = false;
			break;
		}
	}
	return flag;
}
var isH5 = false
if (typeof window === 'object') isH5 = true

var isOutRange = function(x1, y1, x2, y2, x3, y3) {
	return x1 < 0 || x1 >= y1 || x2 < 0 || x2 >= y2 || x3 < 0 || x3 >= y3
};
var isEdit = false;

function bool(str) {
	return str === 'true' || str == true ? true : false
}

var sortCore = function(sKey, eKey, st) {
	var _ = st.basedata;
	var excludeFix = function(cKey, type) {
		// fixed 元素位置不会变化, 这里直接用 cKey(sortKey) 获取, 更加快捷
		if (st.list[cKey].fixed) {
			var _cKey = type ? --cKey : ++cKey;
			return excludeFix(cKey, type);
		}
		return cKey;
	}

	// 先获取到 endKey 对应的 realKey, 防止下面排序过程中该 realKey 被修改
	var endRealKey = -1;
	st.list.forEach(function(item) {
		if (item.sortKey === eKey) endRealKey = item.realKey;
	});

	return st.list.map(function(item) {
		if (item.fixed) return item;
		var cKey = item.sortKey;
		var rKey = item.realKey;

		if (sKey < eKey) {
			// 正序拖动
			if (cKey > sKey && cKey <= eKey) {
				--rKey;
				cKey = excludeFix(--cKey, true);
			} else if (cKey === sKey) {
				rKey = endRealKey;
				cKey = eKey;
			}
		} else if (sKey > eKey) {
			// 倒序拖动
			if (cKey >= eKey && cKey < sKey) {
				++rKey
				cKey = excludeFix(++cKey, false);
			} else if (cKey === sKey) {
				rKey = endRealKey;
				cKey = eKey;
			}
		}

		if (item.sortKey !== cKey) {
			item.tranX = (cKey % _.columns) * 100 + "%";
			item.tranY = Math.floor(cKey / _.columns) * 100 + "%";
			item.sortKey = cKey;
			item.realKey = rKey;
		}
		return item;
	});
}

var triggerCustomEvent = function(list, type, ins) {
	if (!ins) return;
	var _list = [],
		listData = [];

	list.forEach(function(item) {
		_list[item.sortKey] = item;
	});

	_list.forEach(function(item) {
		listData.push(item.data);
	});

	//编译到小程序 funcName作为参数传递导致事件不执行
	if (type == "change") {
		ins.callMethod("change", {
			listData: listData
		});
	} else {
		ins.callMethod("sort_end", {
			listData: listData
		});
	}
}

var longPress = function(event, ownerInstance) {
	var ins = event.instance;
	var dataset = ins.getDataset()
	isEdit = bool(dataset.edit)
	if (!isEdit) return;
	var st = ins.getState();
	if (!st.basedata || st.basedata == 'undefined') {
		st.basedata = JSON.parse(dataset.basedata)
	}
	var _ = st.basedata;
	var sTouch = null;
	if (isH5 && isPC()) {
		sTouch = event;
	} else {
		sTouch = event.changedTouches ? event.changedTouches[0] : st.sTouch;
	}
	if (!sTouch) return;

	st.cur = +dataset.index;

	// 初始项是固定项则返回
	var item = st.list[st.cur];
	if (item && item.fixed) return;

	// 如果已经在 drag 中则返回, 防止多指触发 drag 动作, touchstart 事件中有效果
	if (st.dragging) return;

	// #ifdef MP-WEIXIN
	ownerInstance.callMethod("drag", {
		wxdrag: true
	});
	// #endif

	// 计算X,Y轴初始位移, 使 item 中心移动到点击处, 单列时候X轴初始不做位移
	st.tranX = _.columns === 1 ? 0 : sTouch.pageX - (_.itemWidth / 2 + _.wrapLeft);
	st.tranY = sTouch.pageY - (_.itemHeight / 2 + _.wrapTop);
	st.sId = sTouch.identifier;

	ins.setStyle({
		'transform': 'translate3d(' + st.tranX + 'px, ' + st.tranY + 'px, 0)'
	});
	st.itemsInstance.forEach(function(item, index) {
		item.removeClass("tui-drag__transition").removeClass("tui-drag__current");
		item.addClass(index == st.cur ? "tui-drag__current" : "tui-drag__transition");
	})

	ownerInstance.callMethod("vibrate");
	st.dragging = true;
};

var touchStart = function(event, ownerInstance) {
	var ins = event.instance;
	var state = ins.getState()
	state.list = _st.list
	state.itemsInstance = _st.itemsInstance
	state.basedata = _st.basedata
	if (isH5 && isPC()) {
		state.sTouch = event;
	} else {
		state.sTouch = event.changedTouches[0] || event.touches[0]
	}
	var dataset = ins.getDataset()
	isEdit = bool(dataset.edit)
	// #ifdef MP-WEIXIN
	ownerInstance.callMethod("drag", {
		wxdrag: false
	});
	// #endif
}

var touchMove = function(event, ownerInstance, pc_e) {
	var ins = null
	var st = {}
	var mTouch = null;
	if (isH5 && isPC()) {
		mTouch = event;
		st = pc_e.instance.getState()
		ins = pc_e.instance;
	} else {
		mTouch = event.changedTouches[0] || event.touches[0]
		ins = event.instance
		st = ins.getState()
	}
	if (event.preventDefault && st.dragging) {
		event.preventDefault()
	}
	var _ = st.basedata;

	if (!st.dragging || !isEdit || !mTouch) return;

	// 如果不是同一个触发点则返回
	if (st.sId !== mTouch.identifier) return;

	// 计算X,Y轴位移, 单列时候X轴初始不做位移
	var tranX = _.columns === 1 ? 0 : mTouch.pageX - (_.itemWidth / 2 + _.wrapLeft);
	var tranY = mTouch.pageY - (_.itemHeight / 2 + _.wrapTop);

	// 到顶到底自动滑动
	if (mTouch.clientY > _.windowHeight - _.itemHeight - _.realBottomSize) {
		// 当前触摸点pageY + item高度 - (屏幕高度 - 底部固定区域高度)
		ownerInstance.callMethod("pageScroll", {
			scrollTop: mTouch.pageY + _.itemHeight - (_.windowHeight - _.realBottomSize)
		});
	} else if (mTouch.clientY < _.itemHeight + _.realTopSize) {
		// 当前触摸点pageY - item高度 - 顶部固定区域高度
		ownerInstance.callMethod("pageScroll", {
			scrollTop: mTouch.pageY - _.itemHeight - _.realTopSize
		});
	}

	// 设置当前激活元素偏移量
	ins.setStyle({
		'transform': 'translate3d(' + tranX + 'px, ' + tranY + 'px, 0)'
	})

	var startKey = st.list[st.cur].sortKey;
	var curX = Math.round(tranX / _.itemWidth);
	var curY = Math.round(tranY / _.itemHeight);
	var endKey = curX + _.columns * curY;

	// 目标项是固定项则返回
	var item = st.list[endKey];
	if (item && item.fixed) return;

	// X轴或Y轴超出范围则返回
	if (isOutRange(curX, _.columns, curY, _.rows, endKey, st.list.length)) return;

	// 防止拖拽过程中发生乱序问题
	if (startKey === endKey || startKey === st.preStartKey) return;
	st.preStartKey = startKey;

	var list = sortCore(startKey, endKey, st);
	st.itemsInstance.forEach(function(itemIns, index) {
		var item = list[index];
		if (index !== st.cur) {
			itemIns.setStyle({
				'transform': 'translate3d(' + item.tranX + ',' + item.tranY + ', 0)'
			});
		}
	});

	ownerInstance.callMethod("vibrate");
	ownerInstance.callMethod("listChange", {
		list: list
	});
	triggerCustomEvent(list, "change", ownerInstance);
}

var touchEnd = function(event, ownerInstance, pc_e) {
	var ins = null
	var st = {}
	if (isH5 && isPC()) {
		ins = pc_e.instance
		st = pc_e.instance.getState()
	} else {
		st = event.instance.getState()
		ins = event.instance
	}

	if (!st.dragging || !isEdit) return;
	triggerCustomEvent(st.list, "sort_end", ownerInstance);

	ins.addClass("tui-drag__transition");
	ins.setStyle({
		'transform': 'translate3d(' + st.list[st.cur].tranX + ',' + st.list[st.cur].tranY + ', 0)'
	});
	st.itemsInstance.forEach(function(item, index) {
		item.removeClass("tui-drag__transition");
	})
	st.preStartKey = -1;
	st.dragging = false;
	// #ifdef MP-WEIXIN
	ownerInstance.callMethod("drag", {
		wxdrag: false
	});
	// #endif
	st.cur = -1;
	st.tranX = 0;
	st.tranY = 0;
}

var baseDataObserver = function(newVal, oldVal, ownerInstance, ins) {
	// var st = ownerInstance.getState();
	_st.basedata = newVal;
}

var listObserver = function(newVal, oldVal, ownerInstance, ins) {
	// var st = ownerInstance.getState();
	_st.itemsInstance = ownerInstance.selectAllComponents('.tui-drag__item');

	_st.list = newVal || [];
	if (!_st.itemsInstance || _st.itemsInstance.length === 0) return;
	_st.list.forEach(function(item, index) {
		var itemIns = _st.itemsInstance[index];
		if (item && itemIns) {
			itemIns.setStyle({
				'transform': 'translate3d(' + item.tranX + ',' + item.tranY + ', 0)'
			});
			if (item.fixed) itemIns.addClass("tui-drag__fixed");
		}
	})
}
var movable = false;

function mousedown(e, ins) {
	if (!isH5 || !isPC()) return
	touchStart(e, ins)
	longPress(e, ins)
	movable = true
	window.onmousemove = function(event) {
		if (!isH5 || !isPC() || !movable) return
		touchMove(event, ins, e)
	}
	window.onmouseup = function(event) {
		if (!isH5 || !isPC() || !movable) return
		touchEnd(event, ins, e)
		movable = false
	}
}

function stopMove() {
	return true
}

module.exports = {
	longPress: longPress,
	touchStart: touchStart,
	touchMove: touchMove,
	touchEnd: touchEnd,
	mousedown: mousedown,
	baseDataObserver: baseDataObserver,
	listObserver: listObserver,
	stopMove: stopMove
}