go-captcha-svelte
Version:
GoCaptcha for Svelte, which implements click mode, slider mode, drag-drop mode and rotation mode.
174 lines (173 loc) • 5.9 kB
JavaScript
/**
* @Author Awen
* @Date 2024/06/01
* @Email wengaolng@gmail.com
**/
import { checkTargetFather } from "../helper/helper";
import { writable, get } from 'svelte/store';
export function useHandler(data, event, config, clearCbs) {
let state = writable({ dragLeft: 0, thumbAngle: get(data).angle || 0, angle: get(data).angle });
let isFreeze = false;
let rootRef;
let dragBlockRef;
let dragBarRef;
const unsubscribe = data.subscribe(() => {
if (!isFreeze) {
state.set({ dragLeft: 0, thumbAngle: get(data).angle || 0, angle: get(data).angle || 0 });
}
});
const dragEvent = (e) => {
if (!checkTargetFather(dragBarRef, e)) {
return;
}
const touch = e.touches && e.touches[0];
const offsetLeft = dragBlockRef.offsetLeft;
const width = dragBarRef.offsetWidth;
const blockWidth = dragBlockRef.offsetWidth;
const maxWidth = width - blockWidth;
const maxAngle = 360;
const p = (maxAngle - get(state).angle) / maxWidth;
let angle = 0;
let isMoving = false;
let tmpLeaveDragEvent = null;
let startX = 0;
let currentAngle = 0;
if (touch) {
startX = touch.pageX - offsetLeft;
}
else {
startX = e.clientX - offsetLeft;
}
const moveEvent = (e) => {
isMoving = true;
const mTouche = e.touches && e.touches[0];
const curState = get(state);
let left = 0;
if (mTouche) {
left = mTouche.pageX - startX;
}
else {
left = e.clientX - startX;
}
angle = get(state).angle + (left * p);
if (left >= maxWidth) {
currentAngle = maxAngle;
state.set({ ...curState, dragLeft: maxWidth, thumbAngle: currentAngle });
return;
}
if (left <= 0) {
currentAngle = get(state).angle;
state.set({ ...curState, dragLeft: 0, thumbAngle: currentAngle });
return;
}
currentAngle = angle;
state.set({ ...curState, thumbAngle: angle, dragLeft: left });
const ec = get(event);
ec.rotate && ec.rotate(angle);
e.cancelBubble = true;
e.preventDefault();
};
const upEvent = (e) => {
if (!checkTargetFather(dragBarRef, e)) {
return;
}
clearEvent();
if (!isMoving) {
return;
}
isMoving = false;
if (currentAngle < 0) {
return;
}
const ec = get(event);
ec.confirm && ec.confirm(parseInt(currentAngle.toString()), () => {
resetData();
});
e.cancelBubble = true;
e.preventDefault();
};
const leaveDragBlockEvent = (e) => {
tmpLeaveDragEvent = e;
};
const enterDragBlockEvent = () => {
tmpLeaveDragEvent = null;
};
const leaveUpEvent = (_) => {
if (!tmpLeaveDragEvent) {
return;
}
upEvent(tmpLeaveDragEvent);
clearEvent();
};
const scope = get(config).scope;
const dragDom = scope ? rootRef : dragBarRef;
const scopeDom = scope ? rootRef : document.body;
const clearEvent = () => {
scopeDom.removeEventListener("mousemove", moveEvent, false);
// @ts-ignore
scopeDom.removeEventListener("touchmove", moveEvent, { passive: false });
dragDom.removeEventListener("mouseup", upEvent, false);
dragDom.removeEventListener("mouseenter", enterDragBlockEvent, false);
dragDom.removeEventListener("mouseleave", leaveDragBlockEvent, false);
dragDom.removeEventListener("touchend", upEvent, false);
scopeDom.removeEventListener("mouseleave", upEvent, false);
scopeDom.removeEventListener("mouseup", leaveUpEvent, false);
isFreeze = false;
};
isFreeze = true;
scopeDom.addEventListener("mousemove", moveEvent, false);
scopeDom.addEventListener("touchmove", moveEvent, { passive: false });
dragDom.addEventListener("mouseup", upEvent, false);
dragDom.addEventListener("mouseenter", enterDragBlockEvent, false);
dragDom.addEventListener("mouseleave", leaveDragBlockEvent, false);
dragDom.addEventListener("touchend", upEvent, false);
scopeDom.addEventListener("mouseleave", upEvent, false);
scopeDom.addEventListener("mouseup", leaveUpEvent, false);
};
const closeEvent = (e) => {
close();
e.cancelBubble = true;
e.preventDefault();
return false;
};
const refreshEvent = (e) => {
refresh();
e.cancelBubble = true;
e.preventDefault();
return false;
};
const resetData = () => {
state.set({ dragLeft: 0, thumbAngle: get(data).angle || 0, angle: get(data).angle || 0 });
};
const clearData = () => {
resetData();
clearCbs && clearCbs();
};
const close = () => {
const ec = get(event);
ec.close && ec.close();
resetData();
};
const refresh = () => {
const ec = get(event);
ec.refresh && ec.refresh();
resetData();
};
const initRefs = (root, dragBlock, dragBar) => {
rootRef = root;
dragBlockRef = dragBlock;
dragBarRef = dragBar;
};
return {
state,
initRefs,
unsubscribe,
dragEvent,
closeEvent,
refreshEvent,
resetData,
clearData,
close,
refresh,
};
}