Files
edu/js/intro/init.js
T

267 lines
8.6 KiB
JavaScript

/**
* intro-init.js
* 인트로 페이지 초기화
* 공통 모듈 활용 (ErrorHandler, DOMUtils, Utils, EventManager)
*/
// 전역 의존성 (폴백 포함)
const _initDomUtils = typeof DOMUtils !== 'undefined' ? DOMUtils : null;
const _initErrorHandler = typeof ErrorHandler !== 'undefined' ? ErrorHandler : null;
const _initUtils = typeof Utils !== 'undefined' ? Utils : null;
const _initEventManager = typeof eventManager !== 'undefined' ? eventManager : null;
/**
* 에러 처리 헬퍼
* @private
*/
function _handleError(error, context, additionalInfo = {}) {
if (_initErrorHandler) {
_initErrorHandler.handle(error, {
context: `IntroInit.${context}`,
component: 'IntroInit',
...additionalInfo
}, false);
} else {
console.error(`[IntroInit] ${context}:`, error, additionalInfo);
}
}
/**
* 페이지 초기 설정
*/
function initializeIntroPage() {
try {
// DOM 요소 선택
const cardsContainer = _initDomUtils?.$("#cardsContainer") || document.getElementById("cardsContainer");
const ctaBtn = _initDomUtils?.$("#ctaBtn") || document.getElementById("ctaBtn");
const maskContainer = _initDomUtils?.$("#maskContainer") || document.getElementById("maskContainer");
const typedNameEl = _initDomUtils?.$("#typedName") || document.getElementById("typedName");
const cursorEl = _initDomUtils?.$("#cursor") || document.getElementById("cursor");
// 초기 요소 숨김 처리
if (cardsContainer) {
if (_initDomUtils && _initDomUtils.setStyles) {
_initDomUtils.setStyles(cardsContainer, { display: 'none' });
} else {
cardsContainer.style.display = "none";
}
} else {
console.warn('[IntroInit] cardsContainer 요소를 찾을 수 없습니다.');
}
if (ctaBtn) {
if (_initDomUtils && _initDomUtils.setStyles) {
_initDomUtils.setStyles(ctaBtn, { display: 'none' });
} else {
ctaBtn.style.display = "none";
}
} else {
console.warn('[IntroInit] ctaBtn 요소를 찾을 수 없습니다.');
}
if (maskContainer) {
maskContainer.style.setProperty("--size", "30px");
} else {
console.warn('[IntroInit] maskContainer 요소를 찾을 수 없습니다.');
}
// 이벤트 리스너 등록
if (typeof initEventListeners === 'function') {
try {
initEventListeners();
} catch (error) {
_handleError(error, 'initializeIntroPage.initEventListeners');
}
} else {
console.warn('[IntroInit] initEventListeners 함수를 찾을 수 없습니다.');
}
// typedIndex 초기화 및 typedName 요소 초기화
if (typeof INTRO_STATE !== 'undefined') {
INTRO_STATE.typedIndex = 0;
} else {
console.warn('[IntroInit] INTRO_STATE가 정의되지 않았습니다.');
}
if (typedNameEl) {
typedNameEl.textContent = "";
} else {
console.warn('[IntroInit] typedName 요소를 찾을 수 없습니다.');
}
if (cursorEl) {
if (_initDomUtils && _initDomUtils.setStyles) {
_initDomUtils.setStyles(cursorEl, { opacity: '1' });
} else {
cursorEl.style.opacity = "1";
}
} else {
console.warn('[IntroInit] cursor 요소를 찾을 수 없습니다.');
}
// 타이핑 애니메이션 시작 (INTRO_CONFIG가 준비된 후)
const animationDelay = 800;
const delayFn = _initUtils && _initUtils.delay ? _initUtils.delay : (ms) => new Promise(resolve => setTimeout(resolve, ms));
delayFn(animationDelay).then(() => {
try {
if (typeof INTRO_CONFIG !== 'undefined' && typeof INTRO_STATE !== 'undefined' && INTRO_CONFIG.fullName) {
// text-ani 섹션 표시 (CSS에서 display: none이므로 animating 클래스 추가)
const textAniSection = _initDomUtils?.$('.text-ani') || document.querySelector('.text-ani');
if (textAniSection) {
if (_initDomUtils && _initDomUtils.addClasses) {
_initDomUtils.addClasses(textAniSection, 'animating');
} else {
textAniSection.classList.add('animating');
}
}
INTRO_STATE.typedIndex = 0;
if (typeof typeName === 'function') {
typeName();
} else {
console.warn('[IntroInit] typeName 함수를 찾을 수 없습니다.');
}
} else {
console.warn('[IntroInit] INTRO_CONFIG 또는 INTRO_STATE가 준비되지 않았거나 fullName이 없습니다.');
}
} catch (error) {
_handleError(error, 'initializeIntroPage.animationStart');
}
});
} catch (error) {
_handleError(error, 'initializeIntroPage');
}
}
// DOM이 로드되면 초기화 실행
function setupInitialization() {
try {
if (document.readyState === "loading") {
// EventManager를 사용하여 이벤트 등록 (폴백 포함)
if (_initEventManager) {
_initEventManager.once(document, "DOMContentLoaded", initializeIntroPage);
} else {
document.addEventListener("DOMContentLoaded", initializeIntroPage, { once: true });
}
} else {
// DOMContentLoaded 이벤트가 이미 발생한 경우
initializeIntroPage();
}
} catch (error) {
_handleError(error, 'setupInitialization');
// 폴백: 에러가 발생해도 초기화 시도
if (document.readyState !== "loading") {
initializeIntroPage();
}
}
}
setupInitialization();
/**
* 외부에서 사용자 이름을 설정하고 다시 시작하는 함수
* @param {string} name - 사용자 이름
*/
function restartIntroWithName(name) {
try {
// 입력 검증
if (typeof name !== 'string' || name.trim() === '') {
_handleError(new Error('유효하지 않은 사용자 이름'), 'restartIntroWithName', { name });
return;
}
if (typeof INTRO_STATE === 'undefined') {
_handleError(new Error('INTRO_STATE가 정의되지 않았습니다'), 'restartIntroWithName');
return;
}
// 이름 설정
if (typeof setUserName === 'function') {
try {
setUserName(name);
} catch (error) {
_handleError(error, 'restartIntroWithName.setUserName');
}
} else {
console.warn('[IntroInit] setUserName 함수를 찾을 수 없습니다.');
}
// 상태 초기화
INTRO_STATE.currentSection = 0;
INTRO_STATE.typedIndex = 0;
INTRO_STATE.isScrolling = false;
INTRO_STATE.isAnimating = false;
INTRO_STATE.section2AnimDone = false;
clearTimeout(INTRO_STATE.autoScrollTimer);
INTRO_STATE.lastInteractionTime = Date.now();
// DOM 요소 선택
const typedNameEl = _initDomUtils?.$("#typedName") || document.getElementById("typedName");
const cursorEl = _initDomUtils?.$("#cursor") || document.getElementById("cursor");
const welcomeEl = _initDomUtils?.$("#welcome") || document.getElementById("welcome");
const textAniSection = _initDomUtils?.$('.text-ani') || document.querySelector('.text-ani');
// 화면 리셋
if (typedNameEl) {
typedNameEl.textContent = "";
} else {
console.warn('[IntroInit] typedName 요소를 찾을 수 없습니다.');
}
if (cursorEl) {
if (_initDomUtils && _initDomUtils.setStyles) {
_initDomUtils.setStyles(cursorEl, { opacity: '1' });
} else {
cursorEl.style.opacity = "1";
}
} else {
console.warn('[IntroInit] cursor 요소를 찾을 수 없습니다.');
}
if (welcomeEl) {
welcomeEl.innerHTML = "";
} else {
console.warn('[IntroInit] welcome 요소를 찾을 수 없습니다.');
}
// text-ani 섹션 표시
if (textAniSection) {
if (_initDomUtils && _initDomUtils.addClasses) {
_initDomUtils.addClasses(textAniSection, 'animating');
} else {
textAniSection.classList.add('animating');
}
}
// 섹션 1로 이동
if (typeof goToSection === 'function') {
try {
goToSection(0);
} catch (error) {
_handleError(error, 'restartIntroWithName.goToSection');
}
} else {
console.warn('[IntroInit] goToSection 함수를 찾을 수 없습니다.');
}
// 타이핑 재시작
const animationDelay = 800;
const delayFn = _initUtils && _initUtils.delay ? _initUtils.delay : (ms) => new Promise(resolve => setTimeout(resolve, ms));
delayFn(animationDelay).then(() => {
try {
if (typeof typeName === 'function') {
typeName();
} else {
console.warn('[IntroInit] typeName 함수를 찾을 수 없습니다.');
}
} catch (error) {
_handleError(error, 'restartIntroWithName.typeName');
}
});
} catch (error) {
_handleError(error, 'restartIntroWithName');
}
}