feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
This commit is contained in:
0
f_scripts/shared/swiper/modules/autoplay/autoplay-element.min.css
vendored
Normal file
0
f_scripts/shared/swiper/modules/autoplay/autoplay-element.min.css
vendored
Normal file
279
f_scripts/shared/swiper/modules/autoplay/autoplay.js
Normal file
279
f_scripts/shared/swiper/modules/autoplay/autoplay.js
Normal file
@@ -0,0 +1,279 @@
|
||||
/* eslint no-underscore-dangle: "off" */
|
||||
/* eslint no-use-before-define: "off" */
|
||||
import { getDocument } from 'ssr-window';
|
||||
export default function Autoplay({
|
||||
swiper,
|
||||
extendParams,
|
||||
on,
|
||||
emit,
|
||||
params
|
||||
}) {
|
||||
swiper.autoplay = {
|
||||
running: false,
|
||||
paused: false,
|
||||
timeLeft: 0
|
||||
};
|
||||
extendParams({
|
||||
autoplay: {
|
||||
enabled: false,
|
||||
delay: 3000,
|
||||
waitForTransition: true,
|
||||
disableOnInteraction: true,
|
||||
stopOnLastSlide: false,
|
||||
reverseDirection: false,
|
||||
pauseOnMouseEnter: false
|
||||
}
|
||||
});
|
||||
let timeout;
|
||||
let raf;
|
||||
let autoplayDelayTotal = params && params.autoplay ? params.autoplay.delay : 3000;
|
||||
let autoplayDelayCurrent = params && params.autoplay ? params.autoplay.delay : 3000;
|
||||
let autoplayTimeLeft;
|
||||
let autoplayStartTime = new Date().getTime;
|
||||
let wasPaused;
|
||||
let isTouched;
|
||||
let pausedByTouch;
|
||||
let touchStartTimeout;
|
||||
let slideChanged;
|
||||
let pausedByInteraction;
|
||||
function onTransitionEnd(e) {
|
||||
if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;
|
||||
if (e.target !== swiper.wrapperEl) return;
|
||||
swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);
|
||||
resume();
|
||||
}
|
||||
const calcTimeLeft = () => {
|
||||
if (swiper.destroyed || !swiper.autoplay.running) return;
|
||||
if (swiper.autoplay.paused) {
|
||||
wasPaused = true;
|
||||
} else if (wasPaused) {
|
||||
autoplayDelayCurrent = autoplayTimeLeft;
|
||||
wasPaused = false;
|
||||
}
|
||||
const timeLeft = swiper.autoplay.paused ? autoplayTimeLeft : autoplayStartTime + autoplayDelayCurrent - new Date().getTime();
|
||||
swiper.autoplay.timeLeft = timeLeft;
|
||||
emit('autoplayTimeLeft', timeLeft, timeLeft / autoplayDelayTotal);
|
||||
raf = requestAnimationFrame(() => {
|
||||
calcTimeLeft();
|
||||
});
|
||||
};
|
||||
const getSlideDelay = () => {
|
||||
let activeSlideEl;
|
||||
if (swiper.virtual && swiper.params.virtual.enabled) {
|
||||
activeSlideEl = swiper.slides.filter(slideEl => slideEl.classList.contains('swiper-slide-active'))[0];
|
||||
} else {
|
||||
activeSlideEl = swiper.slides[swiper.activeIndex];
|
||||
}
|
||||
if (!activeSlideEl) return undefined;
|
||||
const currentSlideDelay = parseInt(activeSlideEl.getAttribute('data-swiper-autoplay'), 10);
|
||||
return currentSlideDelay;
|
||||
};
|
||||
const run = delayForce => {
|
||||
if (swiper.destroyed || !swiper.autoplay.running) return;
|
||||
cancelAnimationFrame(raf);
|
||||
calcTimeLeft();
|
||||
let delay = typeof delayForce === 'undefined' ? swiper.params.autoplay.delay : delayForce;
|
||||
autoplayDelayTotal = swiper.params.autoplay.delay;
|
||||
autoplayDelayCurrent = swiper.params.autoplay.delay;
|
||||
const currentSlideDelay = getSlideDelay();
|
||||
if (!Number.isNaN(currentSlideDelay) && currentSlideDelay > 0 && typeof delayForce === 'undefined') {
|
||||
delay = currentSlideDelay;
|
||||
autoplayDelayTotal = currentSlideDelay;
|
||||
autoplayDelayCurrent = currentSlideDelay;
|
||||
}
|
||||
autoplayTimeLeft = delay;
|
||||
const speed = swiper.params.speed;
|
||||
const proceed = () => {
|
||||
if (!swiper || swiper.destroyed) return;
|
||||
if (swiper.params.autoplay.reverseDirection) {
|
||||
if (!swiper.isBeginning || swiper.params.loop || swiper.params.rewind) {
|
||||
swiper.slidePrev(speed, true, true);
|
||||
emit('autoplay');
|
||||
} else if (!swiper.params.autoplay.stopOnLastSlide) {
|
||||
swiper.slideTo(swiper.slides.length - 1, speed, true, true);
|
||||
emit('autoplay');
|
||||
}
|
||||
} else {
|
||||
if (!swiper.isEnd || swiper.params.loop || swiper.params.rewind) {
|
||||
swiper.slideNext(speed, true, true);
|
||||
emit('autoplay');
|
||||
} else if (!swiper.params.autoplay.stopOnLastSlide) {
|
||||
swiper.slideTo(0, speed, true, true);
|
||||
emit('autoplay');
|
||||
}
|
||||
}
|
||||
if (swiper.params.cssMode) {
|
||||
autoplayStartTime = new Date().getTime();
|
||||
requestAnimationFrame(() => {
|
||||
run();
|
||||
});
|
||||
}
|
||||
};
|
||||
if (delay > 0) {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
proceed();
|
||||
}, delay);
|
||||
} else {
|
||||
requestAnimationFrame(() => {
|
||||
proceed();
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
return delay;
|
||||
};
|
||||
const start = () => {
|
||||
swiper.autoplay.running = true;
|
||||
run();
|
||||
emit('autoplayStart');
|
||||
};
|
||||
const stop = () => {
|
||||
swiper.autoplay.running = false;
|
||||
clearTimeout(timeout);
|
||||
cancelAnimationFrame(raf);
|
||||
emit('autoplayStop');
|
||||
};
|
||||
const pause = (internal, reset) => {
|
||||
if (swiper.destroyed || !swiper.autoplay.running) return;
|
||||
clearTimeout(timeout);
|
||||
if (!internal) {
|
||||
pausedByInteraction = true;
|
||||
}
|
||||
const proceed = () => {
|
||||
emit('autoplayPause');
|
||||
if (swiper.params.autoplay.waitForTransition) {
|
||||
swiper.wrapperEl.addEventListener('transitionend', onTransitionEnd);
|
||||
} else {
|
||||
resume();
|
||||
}
|
||||
};
|
||||
swiper.autoplay.paused = true;
|
||||
if (reset) {
|
||||
if (slideChanged) {
|
||||
autoplayTimeLeft = swiper.params.autoplay.delay;
|
||||
}
|
||||
slideChanged = false;
|
||||
proceed();
|
||||
return;
|
||||
}
|
||||
const delay = autoplayTimeLeft || swiper.params.autoplay.delay;
|
||||
autoplayTimeLeft = delay - (new Date().getTime() - autoplayStartTime);
|
||||
if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop) return;
|
||||
if (autoplayTimeLeft < 0) autoplayTimeLeft = 0;
|
||||
proceed();
|
||||
};
|
||||
const resume = () => {
|
||||
if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop || swiper.destroyed || !swiper.autoplay.running) return;
|
||||
autoplayStartTime = new Date().getTime();
|
||||
if (pausedByInteraction) {
|
||||
pausedByInteraction = false;
|
||||
run(autoplayTimeLeft);
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
swiper.autoplay.paused = false;
|
||||
emit('autoplayResume');
|
||||
};
|
||||
const onVisibilityChange = () => {
|
||||
if (swiper.destroyed || !swiper.autoplay.running) return;
|
||||
const document = getDocument();
|
||||
if (document.visibilityState === 'hidden') {
|
||||
pausedByInteraction = true;
|
||||
pause(true);
|
||||
}
|
||||
if (document.visibilityState === 'visible') {
|
||||
resume();
|
||||
}
|
||||
};
|
||||
const onPointerEnter = e => {
|
||||
if (e.pointerType !== 'mouse') return;
|
||||
pausedByInteraction = true;
|
||||
pause(true);
|
||||
};
|
||||
const onPointerLeave = e => {
|
||||
if (e.pointerType !== 'mouse') return;
|
||||
if (swiper.autoplay.paused) {
|
||||
resume();
|
||||
}
|
||||
};
|
||||
const attachMouseEvents = () => {
|
||||
if (swiper.params.autoplay.pauseOnMouseEnter) {
|
||||
swiper.el.addEventListener('pointerenter', onPointerEnter);
|
||||
swiper.el.addEventListener('pointerleave', onPointerLeave);
|
||||
}
|
||||
};
|
||||
const detachMouseEvents = () => {
|
||||
swiper.el.removeEventListener('pointerenter', onPointerEnter);
|
||||
swiper.el.removeEventListener('pointerleave', onPointerLeave);
|
||||
};
|
||||
const attachDocumentEvents = () => {
|
||||
const document = getDocument();
|
||||
document.addEventListener('visibilitychange', onVisibilityChange);
|
||||
};
|
||||
const detachDocumentEvents = () => {
|
||||
const document = getDocument();
|
||||
document.removeEventListener('visibilitychange', onVisibilityChange);
|
||||
};
|
||||
on('init', () => {
|
||||
if (swiper.params.autoplay.enabled) {
|
||||
attachMouseEvents();
|
||||
attachDocumentEvents();
|
||||
autoplayStartTime = new Date().getTime();
|
||||
start();
|
||||
}
|
||||
});
|
||||
on('destroy', () => {
|
||||
detachMouseEvents();
|
||||
detachDocumentEvents();
|
||||
if (swiper.autoplay.running) {
|
||||
stop();
|
||||
}
|
||||
});
|
||||
on('beforeTransitionStart', (_s, speed, internal) => {
|
||||
if (swiper.destroyed || !swiper.autoplay.running) return;
|
||||
if (internal || !swiper.params.autoplay.disableOnInteraction) {
|
||||
pause(true, true);
|
||||
} else {
|
||||
stop();
|
||||
}
|
||||
});
|
||||
on('sliderFirstMove', () => {
|
||||
if (swiper.destroyed || !swiper.autoplay.running) return;
|
||||
if (swiper.params.autoplay.disableOnInteraction) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
isTouched = true;
|
||||
pausedByTouch = false;
|
||||
pausedByInteraction = false;
|
||||
touchStartTimeout = setTimeout(() => {
|
||||
pausedByInteraction = true;
|
||||
pausedByTouch = true;
|
||||
pause(true);
|
||||
}, 200);
|
||||
});
|
||||
on('touchEnd', () => {
|
||||
if (swiper.destroyed || !swiper.autoplay.running || !isTouched) return;
|
||||
clearTimeout(touchStartTimeout);
|
||||
clearTimeout(timeout);
|
||||
if (swiper.params.autoplay.disableOnInteraction) {
|
||||
pausedByTouch = false;
|
||||
isTouched = false;
|
||||
return;
|
||||
}
|
||||
if (pausedByTouch && swiper.params.cssMode) resume();
|
||||
pausedByTouch = false;
|
||||
isTouched = false;
|
||||
});
|
||||
on('slideChange', () => {
|
||||
if (swiper.destroyed || !swiper.autoplay.running) return;
|
||||
slideChanged = true;
|
||||
});
|
||||
Object.assign(swiper.autoplay, {
|
||||
start,
|
||||
stop,
|
||||
pause,
|
||||
resume
|
||||
});
|
||||
}
|
||||
0
f_scripts/shared/swiper/modules/autoplay/autoplay.min.css
vendored
Normal file
0
f_scripts/shared/swiper/modules/autoplay/autoplay.min.css
vendored
Normal file
Reference in New Issue
Block a user