/** * Discshar.js * * 할인 공유 기능을 관리하는 모듈 * 할인 슬라이더, 공유 링크 생성, 공유 결과 확인 등의 기능 제공 */ const Discshar = (function() { // 모듈 내부 변수 선언 let $slider; // 슬라이더 컨테이너 (ul 요소) let $slides; // 슬라이드 아이템들 (li 요소들) let slideWidth; // 각 슬라이드 너비 (마진 포함) let currentSlide; // 현재 표시 중인 슬라이드 인덱스 let totalSlides; // 전체 슬라이드 개수 (복제 슬라이드 포함) let slideInterval; // 자동 슬라이드 간격 (밀리초) let autoSlideTimeout; // 자동 슬라이드 타이머 ID /** * 모듈 초기화 함수 * 슬라이더 초기화 및 이벤트 바인딩 */ function init() { initSlider(); // 슬라이더 요소 초기화 bindEvents(); // 이벤트 리스너 등록 } /** * 슬라이더 초기화 함수 * 슬라이더 요소 참조 가져오기, 크기 설정, 무한 루프를 위한 슬라이드 복제 */ function initSlider() { // 슬라이더 요소 참조 가져오기 $slider = $('.discountSlider ul'); $slides = $('.discountSlider li'); // 슬라이드 너비 계산 (요소 너비 + 마진) slideWidth = $slides.outerWidth() + parseInt($slides.css('margin-right')); // 초기 슬라이드 인덱스 및 총 개수 설정 currentSlide = 0; totalSlides = $slides.length; slideInterval = 3000; // 슬라이드 자동 전환 간격 (밀리초) // 무한 루프 슬라이드를 위한 복제 요소 추가 // 첫 번째 슬라이드 앞에 마지막 슬라이드 복제본 추가 $slides.first().before($slides.last().clone()); // 마지막 슬라이드 뒤에 첫 번째 슬라이드 복제본 추가 $slides.last().after($slides.first().clone()); // 복제된 슬라이드를 포함하여 총 슬라이드 수 업데이트 totalSlides += 2; // 모든 슬라이드를 포함할 수 있도록 컨테이너 너비 설정 $slider.width(totalSlides * slideWidth); // 초기 위치를 첫 번째 실제 슬라이드로 설정 (복제 슬라이드 건너뛰기) $slider.css('margin-left', -slideWidth); // 자동 슬라이드 시작 startAutoSlide(); } /** * 이벤트 리스너 등록 함수 * 슬라이더 조작을 위한 다양한 이벤트 핸들러 연결 */ function bindEvents() { // 슬라이더에 마우스 이벤트 및 터치 이벤트 바인딩 $slider.on('mouseenter', stopAutoSlide) // 마우스 진입 시 자동 슬라이드 정지 .on('mouseleave', startAutoSlide) // 마우스 이탈 시 자동 슬라이드 재시작 .on('mousedown touchstart', startDrag) // 드래그 시작 .on('mousemove touchmove', drag) // 드래그 중 .on('mouseup touchend', endDrag); // 드래그 종료 // 문서 전체에 마우스업/터치엔드 이벤트 리스너 추가 (드래그 도중 슬라이더 밖으로 나갔을 때 대비) $(document).on('mouseup touchend', endDrag); // 이미지 기본 드래그 방지 (브라우저의 기본 동작 차단) $('.discountSlider img').on('dragstart', function(event) { event.preventDefault(); }); } /** * 자동 슬라이드 시작 함수 * 일정 간격으로 다음 슬라이드로 자동 이동 */ function startAutoSlide() { autoSlideTimeout = setInterval(nextSlide, slideInterval); } /** * 자동 슬라이드 정지 함수 * 자동 슬라이드 타이머 중지 */ function stopAutoSlide() { clearInterval(autoSlideTimeout); } /** * 다음 슬라이드로 이동 함수 * 현재 슬라이드 인덱스 증가 후 슬라이드 이동 */ function nextSlide() { currentSlide++; moveSlide(); } /** * 슬라이드 이동 함수 * 현재 슬라이드 인덱스에 맞게 슬라이더 위치 애니메이션 * 무한 루프 슬라이딩을 위한 위치 보정 처리 포함 */ function moveSlide() { // 애니메이션으로 슬라이더 위치 이동 $slider.animate({'margin-left': -currentSlide * slideWidth}, 500, function() { // 애니메이션 완료 후 위치 보정 (무한 루프 구현) if (currentSlide >= totalSlides - 1) { // 마지막 슬라이드(복제본)에 도달하면 첫 번째 실제 슬라이드로 위치 즉시 이동 currentSlide = 1; $slider.css('margin-left', -slideWidth); } else if (currentSlide <= 0) { // 첫 번째 슬라이드(복제본)에 도달하면 마지막 실제 슬라이드로 위치 즉시 이동 currentSlide = totalSlides - 2; $slider.css('margin-left', -currentSlide * slideWidth); } }); } // 드래그 관련 상태 변수 let isDragging = false; // 드래그 중인지 여부 let startPos = 0; // 드래그 시작 위치 (X좌표) let currentPos = 0; // 현재 슬라이더 위치 /** * 드래그 시작 처리 함수 * 드래그 시작 위치와 현재 슬라이더 위치 기록 * @param {Event} e - 마우스 또는 터치 이벤트 */ function startDrag(e) { isDragging = true; // 마우스 또는 터치 이벤트의 X좌표 가져오기 startPos = e.pageX || e.originalEvent.touches[0].pageX; // 현재 슬라이더 위치 기록 currentPos = $slider.css('margin-left'); // 자동 슬라이드 정지 stopAutoSlide(); } /** * 드래그 중 처리 함수 * 마우스/터치 위치에 따라 슬라이더 위치 실시간 업데이트 * @param {Event} e - 마우스 또는 터치 이벤트 */ function drag(e) { if (!isDragging) return; // 드래그 중이 아니면 무시 // 현재 마우스/터치 위치 가져오기 let currentMousePos = e.pageX || e.originalEvent.touches[0].pageX; // 시작 위치와의 차이 계산 let diff = currentMousePos - startPos; // 슬라이더 위치 실시간 업데이트 $slider.css('margin-left', parseInt(currentPos) + diff); } /** * 드래그 종료 처리 함수 * 드래그 방향과 거리에 따라 슬라이드 이동 또는 원위치 * @param {Event} e - 마우스 또는 터치 이벤트 */ function endDrag(e) { if (!isDragging) return; // 드래그 중이 아니면 무시 isDragging = false; // 마우스/터치 종료 위치 가져오기 let endPos = e.pageX || e.originalEvent.changedTouches[0].pageX; // 시작 위치와의 차이 계산 let diff = endPos - startPos; // 슬라이드 전환을 위한 최소 드래그 거리(50px) 이상이면 슬라이드 전환 if (Math.abs(diff) > 50) { // 오른쪽으로 드래그: 이전 슬라이드, 왼쪽으로 드래그: 다음 슬라이드 currentSlide += (diff > 0) ? -1 : 1; moveSlide(); } else { // 최소 거리 미만이면 원래 위치로 되돌리기 $slider.animate({'margin-left': currentPos}, 200); } // 자동 슬라이드 재시작 startAutoSlide(); } /** * 공유 링크 생성 함수 * 할인 공유를 위한 고유 링크 생성 및 모달에 표시 * @param {number} bnfInnb - 혜택 고유 번호 */ function copyLink(bnfInnb) { $.ajax({ url: '/sopmal/bnft/copyDiscsharLink', // 공유 링크 생성 API method: 'POST', contentType: 'application/json', data: JSON.stringify({ bnfInnb: bnfInnb }), // 혜택 고유 번호 전달 success: function(response) { if (response.success && response.links && response.links.length > 0) { // 성공 시 첫 번째 링크 정보 사용 const link = response.links[0]; // 생성된 고유 URL을 입력 필드에 설정 $('#linkToCopy').val(link.uniqueUrl); // 링크 만료일 표시 형식 변환 const validDate = new Date(link.validDt); const formattedDate = validDate.toISOString().split('T')[0]; $('#linkExpiryDate').text(formattedDate); // 링크 복사 모달 표시 MicroModal.show('modal-1'); } else { // 링크 정보 없음 알림 alert('유효한 링크 정보가 없습니다.'); } }, error: function(xhr, status, error) { // 통신 오류 처리 console.error('서버 통신 오류:', error); alert('서버 통신 중 오류가 발생했습니다.'); } }); } /** * 공유 결과 확인 함수 * 사용자의 할인 공유 결과에 따라 적절한 모달 표시 */ function showShareResult() { $.ajax({ url: '/sopmal/bnft/checkDiscsharResult', // 공유 결과 확인 API method: 'POST', contentType: 'application/json', data: JSON.stringify({}), success: function(response) { // 공유 링크로 구매한 사람이 있는지 여부에 따라 다른 모달 표시 if (response.hasPurchase) { // 구매자가 있는 경우 (성공) MicroModal.show('modal-3'); } else { // 구매자가 없는 경우 (아직 공유 중) MicroModal.show('modal-2'); } }, error: function() { // 통신 오류 처리 alert('공유 결과를 확인하는데 실패했습니다.'); } }); } // 모듈의 공개 인터페이스 return { init: init, // 모듈 초기화 copyLink: copyLink, // 공유 링크 생성 showShareResult: showShareResult // 공유 결과 확인 }; })(); /** * 문서 로드 완료 시 실행 * Discshar 모듈 초기화 */ $(document).ready(function() { Discshar.init(); });