@wiajs/ui
Version:
wia app ui packages
490 lines (489 loc) • 22.4 kB
JavaScript
// @ts-nocheck
import { Utils, Event, Support as support } from '@wiajs/core';
const { nextFrame, bindMethods } = Utils;
const def = {
actionsNoFold: false,
noFollow: false,
removeElements: true,
removeElementsWithTimeout: false,
removeElementsTimeout: 0,
overswipeRatio: 1.2
};
/**
* Swipeout Class
* _ 代替 this,表示类实例
*
*/ export default class Swipeout extends Event {
/**
* 构造函数
* @param {*} page Page 实例
* @param {*} opts
*/ constructor(page, opts = {}){
super(opts, [
page
]), this.allow = true;
const m = this;
const opt = {
...def,
...opts
};
m.opt = opt;
this.init();
}
/**
* 初始化
*/ init() {
const _ = this;
const opt = _;
const touchesStart = {};
let isTouched;
let isMoved;
let isScrolling;
let touchStartTime;
let touchesDiff;
let $swipeoutEl;
let $swipeoutContent;
let $actionsRight;
let $actionsLeft;
let actionsLeftWidth;
let actionsRightWidth;
let translate;
let opened;
let openedActionsSide;
let $leftButtons;
let $rightButtons;
let direction;
let $overswipeLeftButton;
let $overswipeRightButton;
let overswipeLeft;
let overswipeRight;
function handleTouchStart(e) {
if (!_.allow) return;
isMoved = false;
isTouched = true;
isScrolling = undefined;
touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
touchStartTime = new Date().getTime();
$swipeoutEl = $(this);
}
function handleTouchMove(e) {
if (!isTouched) return;
const pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
const pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (typeof isScrolling === 'undefined') {
isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
}
if (isScrolling) {
isTouched = false;
return;
}
if (!isMoved) {
if ($('.list.sortable-opened').length > 0) return;
$swipeoutContent = $swipeoutEl.find('.swipeout-content');
$actionsRight = $swipeoutEl.find('.swipeout-actions-right');
$actionsLeft = $swipeoutEl.find('.swipeout-actions-left');
actionsLeftWidth = null;
actionsRightWidth = null;
$leftButtons = null;
$rightButtons = null;
$overswipeRightButton = null;
$overswipeLeftButton = null;
if ($actionsLeft.length > 0) {
actionsLeftWidth = $actionsLeft.outerWidth();
$leftButtons = $actionsLeft.children('a');
$overswipeLeftButton = $actionsLeft.find('.swipeout-overswipe');
}
if ($actionsRight.length > 0) {
actionsRightWidth = $actionsRight.outerWidth();
$rightButtons = $actionsRight.children('a');
$overswipeRightButton = $actionsRight.find('.swipeout-overswipe');
}
opened = $swipeoutEl.hasClass('swipeout-opened');
if (opened) {
openedActionsSide = $swipeoutEl.find('.swipeout-actions-left.swipeout-actions-opened').length > 0 ? 'left' : 'right';
}
$swipeoutEl.removeClass('swipeout-transitioning');
if (!opt.noFollow) {
$swipeoutEl.find('.swipeout-actions-opened').removeClass('swipeout-actions-opened');
$swipeoutEl.removeClass('swipeout-opened');
}
}
isMoved = true;
if (e.cancelable) {
e.preventDefault();
}
touchesDiff = pageX - touchesStart.x;
translate = touchesDiff;
if (opened) {
if (openedActionsSide === 'right') translate -= actionsRightWidth;
else translate += actionsLeftWidth;
}
if (translate > 0 && $actionsLeft.length === 0 || translate < 0 && $actionsRight.length === 0) {
if (!opened) {
isTouched = false;
isMoved = false;
$swipeoutContent.transform('');
if ($rightButtons && $rightButtons.length > 0) {
$rightButtons.transform('');
}
if ($leftButtons && $leftButtons.length > 0) {
$leftButtons.transform('');
}
return;
}
translate = 0;
}
if (translate < 0) direction = 'to-left';
else if (translate > 0) direction = 'to-right';
else if (!direction) direction = 'to-left';
let buttonOffset;
let progress;
e.f7PreventSwipePanel = true;
if (opt.noFollow) {
if (opened) {
if (openedActionsSide === 'right' && touchesDiff > 0) {
_.swipeout.close($swipeoutEl);
}
if (openedActionsSide === 'left' && touchesDiff < 0) {
_.swipeout.close($swipeoutEl);
}
} else {
if (touchesDiff < 0 && $actionsRight.length > 0) {
_.swipeout.open($swipeoutEl, 'right');
}
if (touchesDiff > 0 && $actionsLeft.length > 0) {
_.swipeout.open($swipeoutEl, 'left');
}
}
isTouched = false;
isMoved = false;
return;
}
overswipeLeft = false;
overswipeRight = false;
if ($actionsRight.length > 0) {
// Show right actions
let buttonTranslate = translate;
progress = buttonTranslate / actionsRightWidth;
if (buttonTranslate < -actionsRightWidth) {
const ratio = buttonTranslate / -actionsRightWidth;
buttonTranslate = -actionsRightWidth - (-buttonTranslate - actionsRightWidth) ** 0.8;
translate = buttonTranslate;
if ($overswipeRightButton.length > 0 && ratio > opt.overswipeRatio) {
overswipeRight = true;
}
}
if (direction !== 'to-left') {
progress = 0;
buttonTranslate = 0;
}
$rightButtons.forEach((buttonEl)=>{
const $buttonEl = $(buttonEl);
if (typeof buttonEl.f7SwipeoutButtonOffset === 'undefined') {
$buttonEl[0].f7SwipeoutButtonOffset = buttonEl.offsetLeft;
}
buttonOffset = buttonEl.f7SwipeoutButtonOffset;
if ($overswipeRightButton.length > 0 && $buttonEl.hasClass('swipeout-overswipe') && direction === 'to-left') {
$buttonEl.css({
left: `${overswipeRight ? -buttonOffset : 0}px`
});
if (overswipeRight) {
if (!$buttonEl.hasClass('swipeout-overswipe-active')) {
_.emit('local::overswipeEnter swipeoutOverswipeEnter', $swipeoutEl[0]);
}
$buttonEl.addClass('swipeout-overswipe-active');
} else {
if ($buttonEl.hasClass('swipeout-overswipe-active')) {
_.emit('local::overswipeExit swipeoutOverswipeExit', $swipeoutEl[0]);
}
$buttonEl.removeClass('swipeout-overswipe-active');
}
}
$buttonEl.transform(`translate3d(${buttonTranslate - buttonOffset * (1 + Math.max(progress, -1))}px,0,0)`);
});
}
if ($actionsLeft.length > 0) {
// Show left actions
let buttonTranslate = translate;
progress = buttonTranslate / actionsLeftWidth;
if (buttonTranslate > actionsLeftWidth) {
const ratio = buttonTranslate / actionsRightWidth;
buttonTranslate = actionsLeftWidth + (buttonTranslate - actionsLeftWidth) ** 0.8;
translate = buttonTranslate;
if ($overswipeLeftButton.length > 0 && ratio > opt.overswipeRatio) {
overswipeLeft = true;
}
}
if (direction !== 'to-right') {
buttonTranslate = 0;
progress = 0;
}
$leftButtons.forEach((buttonEl, index)=>{
const $buttonEl = $(buttonEl);
if (typeof buttonEl.f7SwipeoutButtonOffset === 'undefined') {
$buttonEl[0].f7SwipeoutButtonOffset = actionsLeftWidth - buttonEl.offsetLeft - buttonEl.offsetWidth;
}
buttonOffset = buttonEl.f7SwipeoutButtonOffset;
if ($overswipeLeftButton.length > 0 && $buttonEl.hasClass('swipeout-overswipe') && direction === 'to-right') {
$buttonEl.css({
left: `${overswipeLeft ? buttonOffset : 0}px`
});
if (overswipeLeft) {
if (!$buttonEl.hasClass('swipeout-overswipe-active')) {
_.emit('local::overswipeEnter swipeoutOverswipeEnter', $swipeoutEl[0]);
}
$buttonEl.addClass('swipeout-overswipe-active');
} else {
if ($buttonEl.hasClass('swipeout-overswipe-active')) {
_.emit('local::overswipeExit swipeoutOverswipeExit', $swipeoutEl[0]);
}
$buttonEl.removeClass('swipeout-overswipe-active');
}
}
if ($leftButtons.length > 1) {
$buttonEl.css('z-index', $leftButtons.length - index);
}
$buttonEl.transform(`translate3d(${buttonTranslate + buttonOffset * (1 - Math.min(progress, 1))}px,0,0)`);
});
}
_.emit('local::init swipeoutInit', $swipeoutEl[0], progress);
$swipeoutContent.transform(`translate3d(${translate}px,0,0)`);
}
function handleTouchEnd() {
if (!isTouched || !isMoved) {
isTouched = false;
isMoved = false;
return;
}
isTouched = false;
isMoved = false;
const timeDiff = new Date().getTime() - touchStartTime;
const $actions = direction === 'to-left' ? $actionsRight : $actionsLeft;
const actionsWidth = direction === 'to-left' ? actionsRightWidth : actionsLeftWidth;
let action;
let $buttons;
let i;
if (timeDiff < 300 && (touchesDiff < -10 && direction === 'to-left' || touchesDiff > 10 && direction === 'to-right') || timeDiff >= 300 && Math.abs(translate) > actionsWidth / 2) {
action = 'open';
} else {
action = 'close';
}
if (timeDiff < 300) {
if (Math.abs(translate) === 0) action = 'close';
if (Math.abs(translate) === actionsWidth) action = 'open';
}
if (action === 'open') {
[_.el] = $swipeoutEl;
_.emit('local::open swipeoutOpen', $swipeoutEl[0]);
$swipeoutEl.addClass('swipeout-opened swipeout-transitioning');
const newTranslate = direction === 'to-left' ? -actionsWidth : actionsWidth;
$swipeoutContent.transform(`translate3d(${newTranslate}px,0,0)`);
$actions.addClass('swipeout-actions-opened');
$buttons = direction === 'to-left' ? $rightButtons : $leftButtons;
if ($buttons) {
for(i = 0; i < $buttons.length; i += 1){
$($buttons[i]).transform(`translate3d(${newTranslate}px,0,0)`);
}
}
if (overswipeRight) {
$actionsRight.find('.swipeout-overswipe').trigger('click', 'f7Overswipe');
}
if (overswipeLeft) {
$actionsLeft.find('.swipeout-overswipe').trigger('click', 'f7Overswipe');
}
} else {
_.emit('local::close swipeoutClose', $swipeoutEl[0]);
_.el = undefined;
$swipeoutEl.addClass('swipeout-transitioning').removeClass('swipeout-opened');
$swipeoutContent.transform('');
$actions.removeClass('swipeout-actions-opened');
}
let buttonOffset;
if ($leftButtons && $leftButtons.length > 0 && $leftButtons !== $buttons) {
$leftButtons.forEach((buttonEl)=>{
const $buttonEl = $(buttonEl);
buttonOffset = buttonEl.f7SwipeoutButtonOffset;
if (typeof buttonOffset === 'undefined') {
$buttonEl[0].f7SwipeoutButtonOffset = actionsLeftWidth - buttonEl.offsetLeft - buttonEl.offsetWidth;
}
$buttonEl.transform(`translate3d(${buttonOffset}px,0,0)`);
});
}
if ($rightButtons && $rightButtons.length > 0 && $rightButtons !== $buttons) {
$rightButtons.forEach((buttonEl)=>{
const $buttonEl = $(buttonEl);
buttonOffset = buttonEl.f7SwipeoutButtonOffset;
if (typeof buttonOffset === 'undefined') {
$buttonEl[0].f7SwipeoutButtonOffset = buttonEl.offsetLeft;
}
$buttonEl.transform(`translate3d(${-buttonOffset}px,0,0)`);
});
}
$swipeoutContent.transitionEnd(()=>{
if (opened && action === 'open' || !opened && action === 'close') return;
_.emit(action === 'open' ? 'local::opened swipeoutOpened' : 'local::closed swipeoutClosed', $swipeoutEl[0]);
$swipeoutEl.removeClass('swipeout-transitioning');
if (opened && action === 'close') {
if ($actionsRight.length > 0) {
$rightButtons.transform('');
}
if ($actionsLeft.length > 0) {
$leftButtons.transform('');
}
}
});
}
const passiveListener = support.passiveListener ? {
passive: true
} : false;
_.on('touchstart', (e)=>{
if (_.el) {
const $targetEl = $(e.target);
if (!($(_.el).is($targetEl[0]) || $targetEl.parents('.swipeout').is(_.el) || $targetEl.hasClass('modal-in') || ($targetEl.attr('class') || '').indexOf('-backdrop') > 0 || $targetEl.hasClass('actions-modal') || $targetEl.parents('.actions-modal.modal-in, .dialog.modal-in').length > 0)) {
_.close(_.el);
}
}
});
$(document).on(_.touchEvents.start, 'li.swipeout', handleTouchStart, passiveListener);
_.on('touchmove:active', handleTouchMove);
_.on('touchend:passive', handleTouchEnd);
}
open(...args) {
const _ = this;
let [el, side, callback] = args;
if (typeof args[1] === 'function') {
[el, callback, side] = args;
}
const $el = $(el).eq(0);
if ($el.length === 0) return;
if (!$el.hasClass('swipeout') || $el.hasClass('swipeout-opened')) return;
if (!side) {
if ($el.find('.swipeout-actions-right').length > 0) side = 'right';
else side = 'left';
}
const $swipeoutActions = $el.find(`.swipeout-actions-${side}`);
const $swipeoutContent = $el.find('.swipeout-content');
if ($swipeoutActions.length === 0) return;
$el.trigger('swipeout:open').addClass('swipeout-opened').removeClass('swipeout-transitioning');
_.emit('local::open swipeoutOpen', $el[0]);
$swipeoutActions.addClass('swipeout-actions-opened');
const $buttons = $swipeoutActions.children('a');
const swipeoutActionsWidth = $swipeoutActions.outerWidth();
const translate = side === 'right' ? -swipeoutActionsWidth : swipeoutActionsWidth;
if ($buttons.length > 1) {
$buttons.forEach((buttonEl, buttonIndex)=>{
const $buttonEl = $(buttonEl);
if (side === 'right') {
$buttonEl.transform(`translate3d(${-buttonEl.offsetLeft}px,0,0)`);
} else {
$buttonEl.css('z-index', $buttons.length - buttonIndex).transform(`translate3d(${swipeoutActionsWidth - buttonEl.offsetWidth - buttonEl.offsetLeft}px,0,0)`);
}
});
}
$el.addClass('swipeout-transitioning');
$swipeoutContent.transitionEnd(()=>{
_.emit('local::opened swipeoutOpened', $el[0]);
if (callback) callback.call($el[0]);
});
nextFrame(()=>{
$buttons.transform(`translate3d(${translate}px,0,0)`);
$swipeoutContent.transform(`translate3d(${translate}px,0,0)`);
});
[_.el] = $el;
}
close(el, callback) {
const _ = this;
const $el = $(el).eq(0);
if ($el.length === 0) return;
if (!$el.hasClass('swipeout-opened')) return;
const side = $el.find('.swipeout-actions-opened').hasClass('swipeout-actions-right') ? 'right' : 'left';
const $swipeoutActions = $el.find('.swipeout-actions-opened').removeClass('swipeout-actions-opened');
const $buttons = $swipeoutActions.children('a');
const swipeoutActionsWidth = $swipeoutActions.outerWidth();
_.allow = false;
_.emit('local::close swipeoutClose', $el[0]);
$el.removeClass('swipeout-opened').addClass('swipeout-transitioning');
let closeTimeout;
function onSwipeoutClose() {
_.allow = true;
if ($el.hasClass('swipeout-opened')) return;
$el.removeClass('swipeout-transitioning');
$buttons.transform('');
_.emit('local::closed swipeoutClosed', $el[0]);
if (callback) callback.call($el[0]);
if (closeTimeout) clearTimeout(closeTimeout);
}
$el.find('.swipeout-content').transform('').transitionEnd(onSwipeoutClose);
closeTimeout = setTimeout(onSwipeoutClose, 500);
$buttons.forEach((buttonEl)=>{
const $buttonEl = $(buttonEl);
if (side === 'right') {
$buttonEl.transform(`translate3d(${-buttonEl.offsetLeft}px,0,0)`);
} else {
$buttonEl.transform(`translate3d(${swipeoutActionsWidth - buttonEl.offsetWidth - buttonEl.offsetLeft}px,0,0)`);
}
$buttonEl.css({
left: '0px'
}).removeClass('swipeout-overswipe-active');
});
if (_.el && _.el === $el[0]) _.el = undefined;
}
delete(el, callback) {
const _ = this;
const { opt } = _;
const $el = $(el).eq(0);
if ($el.length === 0) return;
_.el = undefined;
// 触发Event事件,使用 on 接收
_.emit('local::delete swipeoutDelete', $el[0]);
$el.css({
height: `${$el.outerHeight()}px`
});
$el.transitionEnd(()=>{
_.emit('local::deleted swipeoutDeleted', $el[0]);
if (callback) callback.call($el[0]);
if ($el.parents('.virtual-list').length > 0) {
const virtualList = $el.parents('.virtual-list')[0].f7VirtualList;
const virtualIndex = $el[0].f7VirtualListIndex;
if (virtualList && typeof virtualIndex !== 'undefined') virtualList.deleteItem(virtualIndex);
} else if (opt.removeElements) {
if (opt.removeElementsWithTimeout) {
setTimeout(()=>{
$el.remove();
}, opt.removeElementsTimeout);
} else {
$el.remove();
}
} else {
$el.removeClass('swipeout-deleting swipeout-transitioning');
}
});
// eslint-disable-next-line
// $el[0]._clientLeft = $el[0].clientLeft;
nextFrame(()=>{
$el.addClass('swipeout-deleting swipeout-transitioning').css({
height: '0px'
}).find('.swipeout-content').transform('translate3d(-100%,0,0)');
});
}
bind() {
const _ = this;
$('.swipeout-open').click((ev, src, data = {})=>this.open(data.swipeout, data.side));
$('.swipeout-close').click((ev, src)=>{
const $el = $(ev).closest('.swipeout');
if ($el.length) this.close($el);
});
$('.swipeout-delete').click((ev, src, data = {})=>{
const $el = $(ev).closest('.swipeout');
if ($el.length) {
const { confirm, confirmTitle } = data;
if (data.confirm) {
$.app.dialog.confirm(confirm, confirmTitle, ()=>{
_.delete($el);
});
} else _.delete($el);
}
});
}
}