commit
This commit is contained in:
commit
21b6332c9c
459 files changed
+190743
No files matched your search
+406
@@ -0,0 +1,406 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert } from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
import { setUserGridMode, loadData } from './adm_comp.js'
|
||||
|
||||
export function destroyGrid(name) {
|
||||
if (w2ui[name]) {
|
||||
w2ui[name].destroy()
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------
|
||||
Super Admin Grid 생성 (상단)
|
||||
---------------------------------------- */
|
||||
export function createSuperAdminGrid(boxId) {
|
||||
|
||||
destroyGrid('superGrid')
|
||||
userGrid
|
||||
const grid = new w2grid({
|
||||
name: 'superGrid',
|
||||
box: boxId,
|
||||
|
||||
show: {
|
||||
// toolbar: true,
|
||||
footer: true,
|
||||
// toolbarReload: true,
|
||||
// toolbarColumns: true,
|
||||
// toolbarSearch: true
|
||||
},
|
||||
|
||||
// multiSearch: true,
|
||||
|
||||
// searches: [
|
||||
// { field: 'member_id', text: 'ID', type: 'text' },
|
||||
// { field: 'user_nm', text: '회원명', type: 'text' },
|
||||
// { field: 'co_nm', text: '회사명', type: 'text' },
|
||||
// {
|
||||
// field: 'stat_bc',
|
||||
// text: '회원상태',
|
||||
// type: 'list',
|
||||
// options: {
|
||||
// items: [
|
||||
// { id: 'Y', text: '사용' },
|
||||
// { id: 'N', text: '미사용' }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
|
||||
columns: [
|
||||
{ field: 'recid', text: '#', size: '50px', attr: 'align=center', editable: false, resizable: true, sortable: true },
|
||||
{ field: 'member_id', text: 'ID', size: '90px', editable: false, resizable: true, sortable: true },
|
||||
{ field: 'user_nm', text: '회원명', size: '90px', editable: false, resizable: true, sortable: true },
|
||||
{ field: 'tel_no', text: '연락처', size: '120px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{ field: 'email', text: 'E-mail', size: '180px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{ field: 'co_nm', text: '회사명', size: '120px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'bs_no',
|
||||
text: '사업자번호',
|
||||
size: '120px',
|
||||
editable: { type: 'text' },
|
||||
resizable: true,
|
||||
sortable: true
|
||||
},
|
||||
{ field: 'join_dt', text: '가입일', size: '100px', editable: false, resizable: true, sortable: true },
|
||||
{ field: 'user_y', text: '사용자수', size: '80px', attr: 'align=right', editable: false, resizable: true, sortable: true },
|
||||
{ field: 'buy_area', text: '제공면적', size: '100px', attr: 'align=right', editable: false, resizable: true, sortable: true },
|
||||
{ field: 'use_area', text: '사용면적', size: '100px', attr: 'align=right', editable: false, resizable: true, sortable: true },
|
||||
{ field: 'rem_area', text: '잔여면적', size: '100px', attr: 'align=right', editable: false, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'stat_bc',
|
||||
text: '회원상태',
|
||||
size: '80px',
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
editable: false,
|
||||
render(record) {
|
||||
switch (record.stat_bc) {
|
||||
case 'SA100100':
|
||||
return '사용중'
|
||||
case 'SA100200':
|
||||
return '탈퇴'
|
||||
default:
|
||||
return record.stat_bc || ''
|
||||
}
|
||||
}
|
||||
},
|
||||
{ field: 'memo', text: '메모', size: '100px', attr: 'align=right', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
|
||||
],
|
||||
|
||||
records: [],
|
||||
|
||||
/* --------------------------------
|
||||
상단 회사 클릭 → 하단 사용자 Grid 갱신
|
||||
-------------------------------- */
|
||||
onClick(event) {
|
||||
if (!event.detail.recid) return
|
||||
|
||||
const record = this.get(event.detail.recid)
|
||||
if (!record) return
|
||||
|
||||
// 하단 영역 표시
|
||||
document.getElementById('detailCard').style.display = 'block'
|
||||
|
||||
// 하단 사용자 로드
|
||||
// fetch(`/kngil/bbs/adm.php?action=user_list&member_id=${record.member_id}`)
|
||||
// .then(res => res.json())
|
||||
// .then(d => {
|
||||
// if (d.status !== 'success') {
|
||||
// w2alert('사용자 조회 실패')
|
||||
// return
|
||||
// }
|
||||
|
||||
// const g = w2ui.detailGrid
|
||||
// g.clear()
|
||||
// g.add(d.records || [])
|
||||
// })
|
||||
import('./adm_comp.js').then(m => {
|
||||
m.loadUsersByMember(record.member_id)
|
||||
})
|
||||
},
|
||||
onSelect(event) {
|
||||
event.onComplete = () => {
|
||||
const btn = document.getElementById('btnServiceRegister')
|
||||
if (btn) btn.disabled = false
|
||||
}
|
||||
},
|
||||
|
||||
onUnselect(event) {
|
||||
event.onComplete = () => {
|
||||
const btn = document.getElementById('btnServiceRegister')
|
||||
if (btn && !this.getSelection().length) {
|
||||
btn.disabled = true
|
||||
}
|
||||
}
|
||||
},
|
||||
// onEditField(event) {
|
||||
// if (event.field !== 'bs_no') return
|
||||
|
||||
// event.onComplete = () => {
|
||||
// const input = event.input
|
||||
// if (!input) return
|
||||
|
||||
// input.addEventListener('input', () => {
|
||||
// let v = input.value.replace(/\D/g, '').slice(0, 10)
|
||||
|
||||
// if (v.length >= 6) {
|
||||
// v = `${v.slice(0, 3)}-${v.slice(3, 5)}-${v.slice(5)}`
|
||||
// } else if (v.length >= 4) {
|
||||
// v = `${v.slice(0, 3)}-${v.slice(3)}`
|
||||
// }
|
||||
|
||||
// input.value = v
|
||||
// })
|
||||
// }
|
||||
// },
|
||||
onChange(event) {
|
||||
event.onComplete = function (ev) {
|
||||
let rec = grid.get(ev.recid);
|
||||
if (!rec) return;
|
||||
|
||||
let field = grid.columns[ev.column].field;
|
||||
let val = ev.value_new;
|
||||
|
||||
/* ===============================
|
||||
🔴 사업자번호(bs_no) 전용 처리
|
||||
=============================== */
|
||||
if (field === 'bs_no') {
|
||||
|
||||
// 숫자만 추출
|
||||
let digits = String(val || '').replace(/\D/g, '');
|
||||
|
||||
// 🔥 입력 중에는 아무 것도 안 건드린다
|
||||
if (digits.length < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 10자리 초과 방지
|
||||
digits = digits.slice(0, 10);
|
||||
|
||||
// 최종 포맷
|
||||
let formatted = `${digits.slice(0, 3)}-${digits.slice(3, 5)}-${digits.slice(5)}`;
|
||||
|
||||
// 🔥 여기서만 set
|
||||
grid.set(ev.recid, { bs_no: formatted });
|
||||
grid.refreshRow(ev.recid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
🔵 기존 공통 로직
|
||||
=============================== */
|
||||
|
||||
if (typeof val === "object" && val !== null) {
|
||||
val = val.text;
|
||||
}
|
||||
|
||||
grid.set(ev.recid, { [field]: val });
|
||||
|
||||
if (field === 'quantity' || field === 'unit_price' || field === 'discount') {
|
||||
let qty = parseInt(rec.quantity) || 0;
|
||||
let unit = parseInt(rec.unit_price) || 0;
|
||||
let dc = parseInt(rec.discount) || 0;
|
||||
let total = Math.max(0, qty * unit - dc);
|
||||
|
||||
grid.set(ev.recid, { total_amount: total });
|
||||
}
|
||||
|
||||
grid.refresh();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// onDblClick(event) {
|
||||
// if (!event.detail.recid) return
|
||||
// const record = this.get(event.detail.recid)
|
||||
// if (!record) return
|
||||
|
||||
// import('./adm_service.js').then(m => {
|
||||
// m.openServiceRegisterPopup({
|
||||
// memberId: record.member_id,
|
||||
// memberName: record.user_nm,
|
||||
// company: record.co_nm,
|
||||
// bizNo: record.bs_no
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
})
|
||||
|
||||
loadCompanies()
|
||||
return grid
|
||||
}
|
||||
|
||||
//사업자 번호 포맷
|
||||
function formatBizNo(value) {
|
||||
const digits = String(value || '').replace(/\D/g, '');
|
||||
if (digits.length !== 10) return null;
|
||||
return `${digits.slice(0, 3)}-${digits.slice(3, 5)}-${digits.slice(5)}`;
|
||||
}
|
||||
|
||||
/* ----------------------------------------
|
||||
상단 회사 목록 로드
|
||||
---------------------------------------- */
|
||||
function loadCompanies() {
|
||||
fetch('/kngil/bbs/adm.php')
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
if (!json.records) return
|
||||
|
||||
w2ui.superGrid.clear()
|
||||
w2ui.superGrid.add(json.records)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('회사 목록 로드 실패:', err)
|
||||
})
|
||||
}
|
||||
|
||||
// =========================
|
||||
// 서비스등록 버튼
|
||||
// =========================
|
||||
document.getElementById('btnServiceRegister')
|
||||
.addEventListener('click', () => {
|
||||
|
||||
const g = w2ui.superGrid
|
||||
if (!g) return
|
||||
|
||||
const sel = g.getSelection()
|
||||
if (!sel.length) {
|
||||
w2alert('서비스를 등록할 회원을 선택하세요.')
|
||||
return
|
||||
}
|
||||
|
||||
const r = g.get(sel[0])
|
||||
|
||||
// 신규 행 방지
|
||||
if (!r.member_id || String(r.member_id).startsWith('new_')) {
|
||||
w2alert('저장된 회원만 서비스 등록이 가능합니다.')
|
||||
return
|
||||
}
|
||||
|
||||
import('/kngil/js/adm_service.js').then(m => {
|
||||
m.openServiceRegisterPopup({
|
||||
memberId: r.member_id,
|
||||
memberName: r.user_nm,
|
||||
company: r.co_nm,
|
||||
bizNo: r.bs_no
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
//저장
|
||||
let isSaveBound = false
|
||||
|
||||
export function bindSaveButton() {
|
||||
if (isSaveBound) return
|
||||
isSaveBound = true
|
||||
|
||||
const btn = document.getElementById('btnSave')
|
||||
if (!btn) return
|
||||
|
||||
btn.addEventListener('click', () => {
|
||||
const g = w2ui.superGrid
|
||||
if (!g) return
|
||||
|
||||
document.activeElement?.blur()
|
||||
g.finishEditing?.()
|
||||
|
||||
const changes = g.getChanges()
|
||||
|
||||
changes.forEach(ch => {
|
||||
// bs_no가 변경 대상이면
|
||||
if ('bs_no' in ch) {
|
||||
const formatted = formatBizNo(ch.bs_no);
|
||||
|
||||
if (!formatted) {
|
||||
w2alert('사업자번호는 숫자 10자리여야 합니다.\n예: 123-45-67890');
|
||||
throw new Error('invalid bs_no');
|
||||
}
|
||||
|
||||
// 🔥 changes 객체를 직접 수정
|
||||
ch.bs_no = formatted;
|
||||
}
|
||||
});
|
||||
|
||||
if (!changes.length) {
|
||||
w2alert('변경된 내용이 없습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
// 🔥 recid 기준으로 원본 record + 변경값 병합
|
||||
const updates = changes.map(c => {
|
||||
const r = g.get(c.recid)
|
||||
return { ...r, ...c }
|
||||
})
|
||||
|
||||
// 🔥 member_id 필수 체크
|
||||
if (!updates[0]?.member_id) {
|
||||
w2alert('member_id가 없습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
fetch('/kngil/bbs/adm.php?action=save', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
member_id: updates[0].member_id, // ✅ 핵심
|
||||
updates
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
if (json.status !== 'success') {
|
||||
throw new Error(json.message)
|
||||
}
|
||||
|
||||
updates.forEach(u => {
|
||||
const r = g.get(u.recid);
|
||||
if (r && u.bs_no) {
|
||||
r.bs_no = u.bs_no; // 하이픈 포함 값
|
||||
g.refreshRow(u.recid);
|
||||
}
|
||||
});
|
||||
|
||||
// g.mergeChanges()
|
||||
// changes 강제 제거
|
||||
g.changes = [];
|
||||
|
||||
// 수정 상태 플래그 제거
|
||||
g.records.forEach(r => {
|
||||
if (r.w2ui) delete r.w2ui.changes;
|
||||
});
|
||||
|
||||
// 화면 다시 그리기
|
||||
g.refresh();
|
||||
w2alert('저장되었습니다.')
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
w2alert(err.message || '저장 실패')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function createDetailGrid(boxId) {
|
||||
|
||||
if (w2ui.detailGrid) w2ui.detailGrid.destroy()
|
||||
|
||||
new w2grid({
|
||||
name: 'detailGrid',
|
||||
box: boxId,
|
||||
show: {
|
||||
footer: true
|
||||
},
|
||||
columns: [
|
||||
{ field: 'recid', text: '#', size: '50px' },
|
||||
{ field: 'user_id', text: 'ID', size: '120px' },
|
||||
{ field: 'user_nm', text: '이름', size: '120px' },
|
||||
{ field: 'dept_nm', text: '부서', size: '120px' },
|
||||
{ field: 'email', text: 'E-mail', size: '200px' },
|
||||
{ field: 'use_yn', text: '사용', size: '80px' }
|
||||
],
|
||||
records: []
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert , w2confirm} from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
export function bindProductPopupEvents() {
|
||||
|
||||
const g = w2ui.productGrid
|
||||
//행 추가
|
||||
document.getElementById('prodAdd').onclick = () => {
|
||||
g.add({
|
||||
recid: g.records.length + 1,
|
||||
name: '',
|
||||
volume: 0,
|
||||
price: 0,
|
||||
use_yn: 'Y'
|
||||
})
|
||||
}
|
||||
//행 삭제
|
||||
document.getElementById('prodRemove').onclick = () => {
|
||||
const sel = g.getSelection()
|
||||
if (!sel.length) {
|
||||
w2alert('삭제할 항목을 선택하세요.')
|
||||
return
|
||||
}
|
||||
g.remove(...sel)
|
||||
}
|
||||
//저장
|
||||
document.getElementById('prodSave').onclick = () => {
|
||||
console.log('상품 저장', g.records)
|
||||
w2alert('저장 처리 예정')
|
||||
}
|
||||
}
|
||||
|
||||
// [추가] 공통 함수
|
||||
export function commonAdd(gridName, defaultData = {}) {
|
||||
const grid = w2ui[gridName];
|
||||
if (!grid) return;
|
||||
|
||||
// 중복되지 않는 recid 생성 (신규 행 식별용)
|
||||
const newRecid = 'new_' + Date.now();
|
||||
|
||||
grid.add({
|
||||
recid: newRecid,
|
||||
is_new: true, // ★ 핵심: 이 플래그가 있어야 commonSave에서 검색됨
|
||||
...defaultData // 아래 2번 단계에서 전달받은 초기값들이 여기에 들어감
|
||||
});
|
||||
|
||||
grid.scrollIntoView(newRecid);
|
||||
}
|
||||
|
||||
// [행 삭제] 공통 함수 (체크박스 선택 기준)
|
||||
export function commonRemove(gridName) {
|
||||
// 인자가 문자열이 아닌 객체로 들어오는지 확인용
|
||||
if (typeof gridName !== 'string') {
|
||||
console.error("그리드 이름은 반드시 문자열이어야 합니다. 전달된 값:", gridName);
|
||||
return;
|
||||
}
|
||||
|
||||
const grid = w2ui[gridName];
|
||||
if (!grid) {
|
||||
console.error(`그리드 '${gridName}'을 찾을 수 없습니다.`, Object.keys(w2ui));
|
||||
return;
|
||||
}
|
||||
|
||||
const sel = grid.getSelection();
|
||||
if (sel.length === 0) {
|
||||
w2alert('삭제할 항목을 선택하세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
w2confirm(`${sel.length}건을 삭제하시겠습니까?`).yes(() => {
|
||||
grid.remove(...sel);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// /js/adm_common.js
|
||||
export async function commonRemoveWithParams(gridName, deleteUrl) {
|
||||
const grid = w2ui[gridName];
|
||||
|
||||
// 1. 그리드 존재 확인 (문자열로 잘 들어왔는지 체크)
|
||||
if (!grid) {
|
||||
console.error(`[삭제실패] ${gridName} 그리드를 찾을 수 없습니다.`, Object.keys(w2ui));
|
||||
return;
|
||||
}
|
||||
|
||||
const sel = grid.getSelection();
|
||||
if (sel.length === 0) {
|
||||
w2alert('삭제할 항목을 선택하세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
w2confirm(`${sel.length}건을 삭제하시겠습니까?`).yes(async () => {
|
||||
try {
|
||||
grid.lock('삭제 중...', true);
|
||||
|
||||
// 2. 프로시저에 필요한 데이터(member_id, sq_no) 추출
|
||||
const selectedRows = sel.map(id => grid.get(id));
|
||||
|
||||
const response = await fetch(deleteUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ items: selectedRows }) // 통째로 전달
|
||||
});
|
||||
|
||||
const responseText = await response.text(); // JSON 변환 전에 텍스트로 먼저 받음
|
||||
console.log("서버 실제 응답 원문:", responseText); // 여기서 HTML 에러 내용 확인 가능
|
||||
|
||||
const result = await response.json();
|
||||
if (result.status === 'success') {
|
||||
grid.remove(...sel);
|
||||
w2alert('성공적으로 삭제되었습니다.');
|
||||
} else {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
} catch (e) {
|
||||
w2alert('삭제 오류: ' + e.message);
|
||||
console.error("서버 응답이 JSON이 아닙니다:", responseText);
|
||||
w2alert("서버 오류가 발생했습니다. 콘솔을 확인하세요.");
|
||||
} finally {
|
||||
grid.unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// [수정 및 저장] 공통 함수
|
||||
export async function commonSave(gridName, saveUrl) {
|
||||
const grid = w2ui[gridName];
|
||||
if (!grid) {
|
||||
console.error(`[저장 실패] '${gridName}' 그리드를 찾을 수 없습니다.`);
|
||||
return;
|
||||
}
|
||||
|
||||
grid.save(); // 에디터에서 입력 중인 값 확정
|
||||
|
||||
// 변경된 내용이 있는지 확인
|
||||
if (grid.getChanges().length === 0) {
|
||||
w2alert('변경사항이 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
grid.lock('저장 중...', true);
|
||||
const response = await fetch(saveUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ items: grid.records }) // 전체 데이터를 보낼지 changes만 보낼지 선택
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
if (result.status === 'success') {
|
||||
w2alert('저장되었습니다.');
|
||||
grid.mergeChanges(); // 그리드의 변경 표시(빨간색) 제거
|
||||
} else {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
} catch (e) {
|
||||
w2alert('저장 오류: ' + e.message);
|
||||
} finally {
|
||||
grid.unlock();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,506 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert, w2confirm } from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
/* -------------------------------------------------
|
||||
공통 유틸
|
||||
------------------------------------------------- */
|
||||
function destroyGrid(name) {
|
||||
if (w2ui[name]) {
|
||||
w2ui[name].destroy()
|
||||
}
|
||||
}
|
||||
|
||||
function loadBaseCode(mainCd) {
|
||||
return fetch(`/kngil/bbs/adm_comp.php?action=base_code&main_cd=${mainCd}`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
if (json.status !== 'success') {
|
||||
throw new Error(json.message || '공통코드 로딩 실패')
|
||||
}
|
||||
return json.items
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
기업 관리자 페이지 Grid
|
||||
------------------------------------------------- */
|
||||
export async function createUserGrid(boxId, options = {}) {
|
||||
// 🔥 DB에서 권한 코드 로딩
|
||||
const authItems = await loadBaseCode('BS100')
|
||||
const { loadSummary = true, memberId = null } = options
|
||||
|
||||
destroyGrid('userGrid')
|
||||
|
||||
const grid = new w2grid({
|
||||
name: boxId === '#detailGrid' ? 'detailGrid' : 'userGrid',
|
||||
box: boxId,
|
||||
|
||||
show: {
|
||||
footer: true,
|
||||
selectColumn: true,
|
||||
},
|
||||
|
||||
columns: [
|
||||
{ field: 'recid', text: '#', size: '50px', attr: 'align=center', editable: false, resizable: true, sortable: true },
|
||||
{ field: 'user_id', text: 'ID', size: '90px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'user_pw',
|
||||
text: 'PW',
|
||||
size: '90px',
|
||||
resizable: true,
|
||||
sortable: false,
|
||||
|
||||
editable: {
|
||||
type: 'password' // ✅ 입력 시 ●●●●
|
||||
},
|
||||
|
||||
render() {
|
||||
return '********' // ✅ 항상 마스킹
|
||||
}
|
||||
},
|
||||
{ field: 'user_nm', text: '이름', size: '90px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{ field: 'tel_no', text: '연락처', size: '120px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{ field: 'email', text: 'E-mail', size: '180px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{ field: 'dept_nm', text: '부서', size: '120px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'use_area',
|
||||
text: '사용량(㎡)',
|
||||
size: '120px',
|
||||
attr: 'align=right',
|
||||
editable: false,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
|
||||
render(record) {
|
||||
const v = Number(record.use_area) || 0
|
||||
return v.toLocaleString() // ✅ 1,000단위 콤마
|
||||
}
|
||||
},
|
||||
{ field: 'reg_date', text: '등록일', size: '100px', editable: false, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'use_yn',
|
||||
text: '사용',
|
||||
size: '80px',
|
||||
attr: 'align=center',
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
|
||||
editable: {
|
||||
type: 'list',
|
||||
items: [
|
||||
{ id: 'Y', text: 'Y' },
|
||||
{ id: 'N', text: 'N' }
|
||||
]
|
||||
},
|
||||
|
||||
render(record) {
|
||||
return record.use_yn === 'Y' ? 'Y' : 'N'
|
||||
}
|
||||
},
|
||||
/* ✅ 권한 콤보 (DB 연동) */
|
||||
{
|
||||
field: 'auth_bc',
|
||||
text: '권한',
|
||||
size: '120px',
|
||||
editable: {
|
||||
type: 'list',
|
||||
items: authItems
|
||||
},
|
||||
render(record) {
|
||||
const item = authItems.find(i => i.id === record.auth_bc)
|
||||
return item ? item.text : record.auth_bc
|
||||
}
|
||||
},
|
||||
{ field: 'rmks', text: '비고', size: '120px', editable: { type: 'text' }, resizable: true, sortable: true }
|
||||
],
|
||||
|
||||
onEditField(event) {
|
||||
|
||||
const pwColIndex = this.getColumn('user_pw').index
|
||||
|
||||
// 🔥 PW 컬럼일 때만 처리
|
||||
if (event.column !== pwColIndex) return
|
||||
|
||||
event.onComplete = function () {
|
||||
|
||||
// 🔥 현재 편집 세션의 input만 정확히 집기
|
||||
const box = event.box
|
||||
if (!box) return
|
||||
|
||||
const input = box.querySelector('input[type="password"]')
|
||||
if (!input) return
|
||||
|
||||
// PW만 초기화
|
||||
input.value = ''
|
||||
input.placeholder = '변경 시에만 입력'
|
||||
}
|
||||
},
|
||||
|
||||
records: [],
|
||||
})
|
||||
|
||||
loadData({
|
||||
loadSummary,
|
||||
memberId
|
||||
})
|
||||
}
|
||||
|
||||
function loadUsers() {
|
||||
fetch('/kngil/bbs/adm_comp.php')
|
||||
.then(res => res.text()) // 🔥 먼저 text로 확인
|
||||
.then(text => {
|
||||
try {
|
||||
const json = JSON.parse(text)
|
||||
w2ui.userGrid.clear()
|
||||
w2ui.userGrid.add(json.records)
|
||||
} catch (e) {
|
||||
console.error('JSON 파싱 실패:', text)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function loadUsersByMember(member_id) {
|
||||
|
||||
if (!member_id) return
|
||||
|
||||
// 🔥 실제 존재하는 grid 찾기
|
||||
const g = w2ui.detailGrid || w2ui.userGrid
|
||||
if (!g) {
|
||||
console.error('사용자 grid가 없습니다')
|
||||
return
|
||||
}
|
||||
|
||||
fetch('/kngil/bbs/adm_comp.php')
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
g.clear()
|
||||
g.add(json.records || [])
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('사용자 로드 실패', err)
|
||||
})
|
||||
}
|
||||
|
||||
export function setUserGridMode(mode = 'view') {
|
||||
const g = w2ui.userGrid
|
||||
if (!g) return
|
||||
|
||||
if (mode === 'view') {
|
||||
g.show.toolbar = false
|
||||
g.show.selectColumn = false
|
||||
g.show.toolbarSave = false
|
||||
} else {
|
||||
g.show.toolbar = true
|
||||
g.show.selectColumn = true
|
||||
g.show.toolbarSave = true
|
||||
}
|
||||
|
||||
g.refresh()
|
||||
}
|
||||
|
||||
export function loadData({ loadSummary = true } = {}) {
|
||||
|
||||
fetch('/kngil/bbs/adm_comp.php')
|
||||
.then(res => res.json())
|
||||
.then(async d => {
|
||||
|
||||
if (d.status !== 'success') {
|
||||
w2alert('데이터 로딩 실패')
|
||||
return
|
||||
}
|
||||
|
||||
const records = d.records || []
|
||||
const memberId = d.member_id // ⭐ 여기서 확정
|
||||
|
||||
if (loadSummary && memberId) {
|
||||
const totalArea = await loadTotalArea(memberId)
|
||||
|
||||
renderSummaryFromRecords({
|
||||
memberId,
|
||||
records,
|
||||
totalArea
|
||||
})
|
||||
}
|
||||
|
||||
const gridName = w2ui.detailGrid ? 'detailGrid' : 'userGrid'
|
||||
w2ui[gridName].clear()
|
||||
w2ui[gridName].add(records)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
w2alert('서버 통신 오류')
|
||||
})
|
||||
}
|
||||
|
||||
function renderSummaryFromRecords({ memberId, records, totalArea }) {
|
||||
|
||||
if (!records.length) return
|
||||
|
||||
const first = records[0]
|
||||
|
||||
const issuedCnt = Number(first.users_tot) || 0
|
||||
const usedCnt = Number(first.users_y) || 0
|
||||
const term = first.term || ''
|
||||
|
||||
// 사용 중 면적 합계
|
||||
let usedArea = 0
|
||||
records.forEach(r => {
|
||||
if (r.use_yn === 'Y') {
|
||||
usedArea += Number(r.use_area || 0)
|
||||
}
|
||||
})
|
||||
|
||||
const percent = totalArea > 0
|
||||
? Math.floor((usedArea / totalArea) * 100)
|
||||
: 0
|
||||
|
||||
/* -------- 화면 바인딩 -------- */
|
||||
document.getElementById('memberId').textContent = memberId
|
||||
document.getElementById('planName').textContent = 'Silver'
|
||||
document.getElementById('dateRange').textContent = term
|
||||
|
||||
document.getElementById('issuedCnt').textContent = issuedCnt
|
||||
document.getElementById('usedCnt').textContent = usedCnt
|
||||
|
||||
document.getElementById('usedArea').textContent =
|
||||
usedArea.toLocaleString() + '㎡'
|
||||
|
||||
document.getElementById('totalArea').textContent =
|
||||
totalArea.toLocaleString() + '㎡'
|
||||
|
||||
document.getElementById('usedBar').style.width = percent + '%'
|
||||
document.getElementById('usedBar').textContent = percent + '%'
|
||||
document.getElementById('remainBar').style.width =
|
||||
(100 - percent) + '%'
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ===============================
|
||||
// 저장 버튼
|
||||
// ===============================
|
||||
document.getElementById('btnSave_comp')?.addEventListener('click', () => {
|
||||
|
||||
// 현재 사용 중인 grid
|
||||
const g = w2ui.detailGrid || w2ui.userGrid
|
||||
if (!g) return
|
||||
|
||||
const changes = g.getChanges()
|
||||
|
||||
if (!changes.length) {
|
||||
w2alert('변경된 내용이 없습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
const inserts = []
|
||||
const updates = []
|
||||
|
||||
changes.forEach(c => {
|
||||
const rec = g.get(c.recid)
|
||||
if (!rec) return
|
||||
|
||||
// 🔥 핵심: 원본 rec + 변경값 c 병합
|
||||
const merged = { ...rec, ...c }
|
||||
|
||||
if (rec.__isNew) {
|
||||
// INSERT → 전체 row 필요
|
||||
inserts.push(merged)
|
||||
} else {
|
||||
// UPDATE → PK + 변경 컬럼
|
||||
updates.push({
|
||||
member_id : merged.member_id,
|
||||
user_id : merged.user_id,
|
||||
|
||||
user_nm : merged.user_nm,
|
||||
dept_nm : merged.dept_nm,
|
||||
tel_no : merged.tel_no,
|
||||
email : merged.email,
|
||||
use_yn : merged.use_yn,
|
||||
auth_bc : merged.auth_bc,
|
||||
rmks : (merged.memo !== undefined ? merged.memo : '')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
console.log('INSERTS', inserts)
|
||||
console.log('UPDATES', updates)
|
||||
|
||||
fetch('/kngil/bbs/adm_comp.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'save',
|
||||
member_id: g.records[0]?.member_id,
|
||||
inserts,
|
||||
updates
|
||||
})
|
||||
})
|
||||
.then(res => res.text())
|
||||
.then(text => {
|
||||
try {
|
||||
const json = JSON.parse(text)
|
||||
if (json.status === 'success') {
|
||||
w2alert('저장 완료')
|
||||
loadUsersByMember(g.records[0].member_id)
|
||||
} else {
|
||||
w2alert(json.message || '저장 실패')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(text)
|
||||
w2alert('서버 응답 오류 (JSON 아님)')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
//추가(insert)
|
||||
document.getElementById('btnAdd')?.addEventListener('click', () => {
|
||||
|
||||
const g = w2ui.userGrid || w2ui.detailGrid
|
||||
if (!g) return
|
||||
|
||||
// 신규 row용 recid (음수로 충돌 방지)
|
||||
const newRecid = -Date.now()
|
||||
|
||||
g.add({
|
||||
recid: newRecid,
|
||||
__isNew: true, // ⭐ 신규 플래그
|
||||
user_id: '',
|
||||
user_pw: '',
|
||||
user_nm: '',
|
||||
tel_no: '',
|
||||
email: '',
|
||||
dept_nm: '',
|
||||
use_area: 0,
|
||||
use_yn: 'Y',
|
||||
auth_bc: 'BS100400',
|
||||
memo: ''
|
||||
}, true)
|
||||
|
||||
g.select(newRecid)
|
||||
g.scrollIntoView(newRecid)
|
||||
})
|
||||
|
||||
//삭제
|
||||
document.getElementById('btnDelete')?.addEventListener('click', () => {
|
||||
|
||||
const g = w2ui.detailGrid || w2ui.userGrid
|
||||
if (!g) return
|
||||
|
||||
const sel = g.getSelection()
|
||||
|
||||
if (!sel.length) {
|
||||
w2alert('삭제할 사용자를 선택하세요.')
|
||||
return
|
||||
}
|
||||
|
||||
// 선택된 user_id 수집
|
||||
const ids = sel
|
||||
.map(recid => {
|
||||
const r = g.get(recid)
|
||||
return r?.user_id
|
||||
})
|
||||
.filter(Boolean)
|
||||
|
||||
if (!ids.length) {
|
||||
w2alert('삭제 가능한 항목이 없습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
w2confirm(`선택한 ${ids.length}명의 사용자를 삭제하시겠습니까?`)
|
||||
.yes(() => {
|
||||
|
||||
fetch('/kngil/bbs/adm_comp.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'delete',
|
||||
member_id: g.records[0]?.member_id,
|
||||
ids
|
||||
})
|
||||
})
|
||||
.then(res => res.text())
|
||||
.then(text => {
|
||||
try {
|
||||
const json = JSON.parse(text)
|
||||
if (json.status === 'success') {
|
||||
w2alert('삭제 완료')
|
||||
loadUsersByMember(g.records[0].member_id)
|
||||
} else {
|
||||
w2alert(json.message || '삭제 실패')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(text)
|
||||
w2alert('서버 응답 오류 (JSON 아님)')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function loadTotalArea(memberId) {
|
||||
return fetch(`/kngil/bbs/adm_comp.php?action=total_area&member_id=${memberId}`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
if (json.status !== 'success') {
|
||||
throw new Error('총 구매면적 로딩 실패')
|
||||
}
|
||||
return Number(json.total_area || 0)
|
||||
})
|
||||
}
|
||||
|
||||
function doSearch() {
|
||||
|
||||
const keyword = document.getElementById('schKeyword').value.trim()
|
||||
const type = document.getElementById('schType').value
|
||||
const useYn = document.getElementById('schUseYn').value
|
||||
|
||||
let p_user_nm = ''
|
||||
let p_dept_nm = ''
|
||||
|
||||
// DB로 보낼 검색 조건
|
||||
if (type === 'name') {
|
||||
p_user_nm = keyword
|
||||
} else if (type === 'dept') {
|
||||
p_dept_nm = keyword
|
||||
} else if (type === '') {
|
||||
// 전체 검색 → 이름 OR 부서
|
||||
p_user_nm = keyword
|
||||
p_dept_nm = keyword
|
||||
}
|
||||
// ⚠️ type === 'id' 는 DB로 안 보냄
|
||||
|
||||
fetch(`/kngil/bbs/adm_comp.php?action=list`
|
||||
+ `&user_nm=${encodeURIComponent(p_user_nm)}`
|
||||
+ `&dept_nm=${encodeURIComponent(p_dept_nm)}`
|
||||
+ `&use_yn=${useYn}`
|
||||
)
|
||||
.then(res => res.json())
|
||||
.then(d => {
|
||||
|
||||
if (d.status !== 'success') {
|
||||
w2alert('검색 실패')
|
||||
return
|
||||
}
|
||||
|
||||
let records = d.records || []
|
||||
|
||||
// 🔥 ID 검색은 프론트 필터
|
||||
if (type === 'id' && keyword) {
|
||||
records = records.filter(r =>
|
||||
(r.user_id || '').toLowerCase()
|
||||
.includes(keyword.toLowerCase())
|
||||
)
|
||||
}
|
||||
|
||||
const g = w2ui.detailGrid || w2ui.userGrid
|
||||
g.clear()
|
||||
g.add(records)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('btnSearch')
|
||||
?.addEventListener('click', doSearch)
|
||||
|
||||
document.getElementById('schKeyword')
|
||||
?.addEventListener('keydown', e => {
|
||||
if (e.key === 'Enter') doSearch()
|
||||
})
|
||||
@@ -0,0 +1,798 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert, w2confirm } from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
let AUTH_ITEMS = []
|
||||
let CURRENT_MEMBER_ID = null;
|
||||
|
||||
const USE_ITEMS = [
|
||||
{ id: 'Y', text: '사용' },
|
||||
{ id: 'N', text: '미사용' }
|
||||
]
|
||||
/* -------------------------------------------------
|
||||
공통 유틸
|
||||
------------------------------------------------- */
|
||||
|
||||
function getTargetMemberId() {
|
||||
return document.getElementById('targetMemberId')?.value?.trim()
|
||||
}
|
||||
|
||||
function destroyGrid(name) {
|
||||
if (w2ui[name]) {
|
||||
w2ui[name].destroy()
|
||||
}
|
||||
}
|
||||
|
||||
function loadBaseCode(mainCd) {
|
||||
return fetch(`/kngil/bbs/adm_comp.php?action=base_code&main_cd=${mainCd}`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
if (json.status !== 'success') {
|
||||
throw new Error(json.message || '공통코드 로딩 실패')
|
||||
}
|
||||
return json.items
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeAuth(records) {
|
||||
return records.map(r => {
|
||||
const item = AUTH_ITEMS.find(a => a.id === r.auth_bc)
|
||||
return {
|
||||
...r,
|
||||
auth_bc: item || null //객체 복사
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeUseYn(records) {
|
||||
return records.map(r => {
|
||||
const item = USE_ITEMS.find(u => u.id === r.use_yn)
|
||||
return {
|
||||
...r,
|
||||
use_yn: item || null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------
|
||||
기업 관리자 페이지 Grid
|
||||
------------------------------------------------- */
|
||||
export async function createUserGrid(boxId, options = {}) {
|
||||
console.log('🔥 createUserGrid 호출됨:', boxId)
|
||||
// 🔥 DB에서 권한 코드 로딩
|
||||
AUTH_ITEMS = (await loadBaseCode('BS100')).map(r => ({
|
||||
id: r.id,
|
||||
text: r.text
|
||||
}))
|
||||
const { loadSummary = true, memberId = null } = options
|
||||
|
||||
destroyGrid('userGrid')
|
||||
|
||||
const grid = new w2grid({
|
||||
name: boxId === '#detailGrid' ? 'detailGrid' : 'userGrid',
|
||||
box: boxId,
|
||||
|
||||
show: {
|
||||
footer: true,
|
||||
lineNumbers: true,
|
||||
selectColumn: true,
|
||||
},
|
||||
|
||||
columns: [
|
||||
// {
|
||||
// field: 'recid',
|
||||
// text: '#',
|
||||
// size: '50px',
|
||||
// attr: 'align=center',
|
||||
// sortable: true,
|
||||
// },
|
||||
{ field: 'user_id', text: 'ID', size: '90px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'user_pw',
|
||||
text: 'PW',
|
||||
size: '90px',
|
||||
resizable: true,
|
||||
sortable: false,
|
||||
|
||||
editable: {
|
||||
type: 'password' // ✅ 입력 시 ●●●●
|
||||
},
|
||||
|
||||
render() {
|
||||
return '********' // ✅ 항상 마스킹
|
||||
}
|
||||
},
|
||||
{ field: 'user_nm', text: '이름', size: '90px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'tel_no',
|
||||
text: '연락처',
|
||||
size: '120px',
|
||||
editable: { type: 'text' },
|
||||
resizable: true,
|
||||
sortable: true
|
||||
},
|
||||
{ field: 'email', text: 'E-mail', size: '180px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{ field: 'dept_nm', text: '부서', size: '120px', editable: {type : 'text'}, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'use_area',
|
||||
text: '사용량(㎡)',
|
||||
size: '120px',
|
||||
attr: 'align=right',
|
||||
editable: false,
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
|
||||
render(record) {
|
||||
const v = Number(record.use_area) || 0
|
||||
return v.toLocaleString() // ✅ 1,000단위 콤마
|
||||
}
|
||||
},
|
||||
{ field: 'cdt', text: '등록일', size: '100px', editable: false, resizable: true, sortable: true },
|
||||
{
|
||||
field: 'use_yn',
|
||||
text: '사용',
|
||||
size: '90px',
|
||||
attr: 'align=center',
|
||||
sortable: true,
|
||||
editable: {
|
||||
type: 'list',
|
||||
items: USE_ITEMS,
|
||||
showAll: true,
|
||||
openOnFocus: true
|
||||
},
|
||||
|
||||
render(record, extra) {
|
||||
return extra?.value?.text || ''
|
||||
}
|
||||
},
|
||||
/* ✅ 권한 콤보 (DB 연동) */
|
||||
{
|
||||
field: 'auth_bc',
|
||||
text: '권한',
|
||||
size: '120px',
|
||||
sortable: true,
|
||||
editable: {
|
||||
type: 'list',
|
||||
items: AUTH_ITEMS,
|
||||
showAll: true,
|
||||
openOnFocus: true
|
||||
},
|
||||
render(record, extra) {
|
||||
return extra?.value?.text || ''
|
||||
}
|
||||
},
|
||||
{ field: 'rmks', text: '비고', size: '120px', editable: { type: 'text' }, resizable: true, sortable: true }
|
||||
],
|
||||
onEditField(event) {
|
||||
|
||||
const pwColIndex = this.getColumn('user_pw').index
|
||||
|
||||
// 🔥 PW 컬럼일 때만 처리
|
||||
if (event.column !== pwColIndex) return
|
||||
|
||||
event.onComplete = function () {
|
||||
|
||||
// 🔥 현재 편집 세션의 input만 정확히 집기
|
||||
const box = event.box
|
||||
if (!box) return
|
||||
|
||||
const input = box.querySelector('input[type="password"]')
|
||||
if (!input) return
|
||||
|
||||
// PW만 초기화
|
||||
input.value = ''
|
||||
input.placeholder = '변경 시에만 입력'
|
||||
}
|
||||
},
|
||||
onChange(event) {
|
||||
event.onComplete = function (ev) {
|
||||
|
||||
const rec = grid.get(ev.recid);
|
||||
if (!rec) return;
|
||||
|
||||
const field = grid.columns[ev.column].field;
|
||||
let val = ev.value_new;
|
||||
|
||||
/* ===============================
|
||||
📞 전화번호(tel_no) 자동 하이픈
|
||||
=============================== */
|
||||
if (field === 'tel_no') {
|
||||
|
||||
let digits = String(val || '').replace(/\D/g, '');
|
||||
|
||||
// 입력 중이면 건드리지 않음
|
||||
if (digits.length < 9) return;
|
||||
|
||||
let formatted = digits;
|
||||
|
||||
if (digits.length === 11) {
|
||||
formatted =
|
||||
`${digits.slice(0,3)}-${digits.slice(3,7)}-${digits.slice(7)}`;
|
||||
} else if (digits.length === 10) {
|
||||
formatted =
|
||||
`${digits.slice(0,3)}-${digits.slice(3,6)}-${digits.slice(6)}`;
|
||||
}
|
||||
|
||||
// ✅ 화면 값
|
||||
grid.set(ev.recid, { tel_no: formatted });
|
||||
|
||||
// ✅ 변경사항으로 "확정" (이게 핵심)
|
||||
grid.mergeChanges(ev.recid, { tel_no: formatted });
|
||||
|
||||
grid.refreshRow(ev.recid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
공통 처리
|
||||
=============================== */
|
||||
if (typeof val === 'object' && val !== null) {
|
||||
val = val.text;
|
||||
}
|
||||
|
||||
grid.set(ev.recid, { [field]: val });
|
||||
grid.mergeChanges(ev.recid, { [field]: val });
|
||||
};
|
||||
},
|
||||
records: [],
|
||||
})
|
||||
|
||||
loadData({
|
||||
loadSummary,
|
||||
memberId
|
||||
})
|
||||
}
|
||||
|
||||
export function loadUsersByMember(memberId) {
|
||||
|
||||
if (!memberId) return
|
||||
|
||||
const g = w2ui.detailGrid
|
||||
if (!g) {
|
||||
console.error('detailGrid 없음')
|
||||
return
|
||||
}
|
||||
|
||||
fetch(`/kngil/bbs/adm_comp.php?action=list&member_id=${memberId}`)
|
||||
.then(res => res.json())
|
||||
.then(d => {
|
||||
|
||||
if (d.status !== 'success') {
|
||||
w2alert('사용자 조회 실패')
|
||||
return
|
||||
}
|
||||
const records = normalizeAuth(d.records || [])
|
||||
records = normalizeUseYn(records)
|
||||
g.clear()
|
||||
g.add(d.records)
|
||||
})
|
||||
.catch(err => console.error(err))
|
||||
}
|
||||
|
||||
export function setUserGridMode(mode = 'view') {
|
||||
const g = w2ui.userGrid
|
||||
if (!g) return
|
||||
|
||||
if (mode === 'view') {
|
||||
g.show.toolbar = false
|
||||
g.show.selectColumn = false
|
||||
g.show.toolbarSave = false
|
||||
} else {
|
||||
g.show.toolbar = true
|
||||
g.show.selectColumn = true
|
||||
g.show.toolbarSave = true
|
||||
}
|
||||
|
||||
g.refresh()
|
||||
}
|
||||
|
||||
export function loadData({ loadSummary = true } = {}) {
|
||||
fetch('/kngil/bbs/adm_comp.php?action=list')
|
||||
.then(res => res.json())
|
||||
.then(async d => {
|
||||
|
||||
if (d.status !== 'success') return
|
||||
|
||||
let records = normalizeAuth(d.records || [])
|
||||
records = normalizeUseYn(records)
|
||||
const gridName = w2ui.detailGrid ? 'detailGrid' : 'userGrid'
|
||||
|
||||
w2ui[gridName].clear()
|
||||
w2ui[gridName].add(records)
|
||||
|
||||
if (loadSummary && d.member_id) {
|
||||
const totalArea = await loadTotalArea()
|
||||
renderSummaryFromRecords({
|
||||
memberId: d.member_id,
|
||||
records,
|
||||
totalArea
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function renderSummaryFromRecords({ memberId, records, totalArea }) {
|
||||
|
||||
if (!records.length) return
|
||||
|
||||
const first = records[0]
|
||||
|
||||
const issuedCnt = Number(first.users_tot) || 0
|
||||
const usedCnt = Number(first.users_y) || 0
|
||||
const term = first.term || ''
|
||||
|
||||
// 사용 중 면적 합계
|
||||
let usedArea = 0
|
||||
records.forEach(r => {
|
||||
if (r.use_yn?.id === 'Y') {
|
||||
usedArea += Number(r.use_area || 0)
|
||||
}
|
||||
})
|
||||
|
||||
const percent = totalArea > 0
|
||||
? Math.floor((usedArea / totalArea) * 100)
|
||||
: 0
|
||||
|
||||
/* -------- 화면 바인딩 -------- */
|
||||
document.getElementById('memberId').textContent = memberId
|
||||
document.getElementById('planName').textContent = first.itm_nm || '-'
|
||||
document.getElementById('dateRange').textContent = term
|
||||
|
||||
document.getElementById('issuedCnt').textContent = issuedCnt
|
||||
document.getElementById('usedCnt').textContent = usedCnt
|
||||
|
||||
document.getElementById('usedArea').textContent =
|
||||
usedArea.toLocaleString() + '㎡'
|
||||
|
||||
document.getElementById('totalArea').textContent =
|
||||
totalArea.toLocaleString() + '㎡'
|
||||
|
||||
/* -------- 사용량 바 -------- */
|
||||
const bar = document.getElementById('usedBar')
|
||||
bar.style.width = percent + '%'
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ===============================
|
||||
// 저장 버튼
|
||||
// ===============================
|
||||
document.getElementById('btnSave_comp')?.addEventListener('click', () => {
|
||||
|
||||
// 현재 사용 중인 grid
|
||||
const g = w2ui.detailGrid || w2ui.userGrid
|
||||
if (!g) return
|
||||
|
||||
const changes = g.getChanges()
|
||||
|
||||
if (!changes.length) {
|
||||
w2alert('변경된 내용이 없습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
const inserts = []
|
||||
const updates = []
|
||||
|
||||
changes.forEach(c => {
|
||||
const rec = g.get(c.recid)
|
||||
if (!rec) return
|
||||
|
||||
// 🔥 핵심: 원본 rec + 변경값 c 병합
|
||||
const merged = { ...rec, ...c }
|
||||
|
||||
if (rec.__isNew) {
|
||||
// INSERT → 전체 row 필요
|
||||
inserts.push(merged)
|
||||
} else {
|
||||
// UPDATE → PK + 변경 컬럼
|
||||
updates.push({
|
||||
member_id : merged.member_id,
|
||||
user_id : merged.user_id,
|
||||
|
||||
user_nm : merged.user_nm,
|
||||
dept_nm : merged.dept_nm,
|
||||
tel_no : merged.tel_no,
|
||||
email : merged.email,
|
||||
use_yn : merged.use_yn?.id || merged.use_yn,
|
||||
auth_bc : merged.auth_bc?.id || merged.auth_bc,
|
||||
rmks : (merged.memo !== undefined ? merged.memo : '')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
console.log('INSERTS', inserts)
|
||||
console.log('UPDATES', updates)
|
||||
|
||||
fetch('/kngil/bbs/adm_comp.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'save',
|
||||
// member_id: g.records[0]?.member_id,
|
||||
inserts,
|
||||
updates
|
||||
})
|
||||
})
|
||||
.then(res => res.text())
|
||||
.then(text => {
|
||||
try {
|
||||
const json = JSON.parse(text)
|
||||
if (json.status === 'success') {
|
||||
w2alert('저장 완료')
|
||||
loadData()
|
||||
} else {
|
||||
w2alert(json.message || '저장 실패')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(text)
|
||||
w2alert('서버 응답 오류 (JSON 아님)')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
//추가(insert)
|
||||
document.getElementById('btnAdd')?.addEventListener('click', () => {
|
||||
|
||||
const g = w2ui.userGrid || w2ui.detailGrid
|
||||
if (!g) return
|
||||
const defaultAuth = AUTH_ITEMS.find(a => a.id === 'BS100500') // 일반
|
||||
// 신규 row용 recid (음수로 충돌 방지)
|
||||
const newRecid = -Date.now()
|
||||
|
||||
g.add({
|
||||
recid: newRecid,
|
||||
__isNew: true,
|
||||
user_id: '',
|
||||
user_pw: '',
|
||||
user_nm: '',
|
||||
tel_no: '',
|
||||
email: '',
|
||||
dept_nm: '',
|
||||
use_area: 0,
|
||||
use_yn: USE_ITEMS[0],
|
||||
auth_bc: defaultAuth || null,
|
||||
memo: ''
|
||||
}, true)
|
||||
|
||||
g.select(newRecid)
|
||||
g.scrollIntoView(newRecid)
|
||||
})
|
||||
|
||||
//삭제
|
||||
document.getElementById('btnDelete')?.addEventListener('click', () => {
|
||||
|
||||
const g = w2ui.detailGrid || w2ui.userGrid
|
||||
if (!g) return
|
||||
|
||||
const sel = g.getSelection()
|
||||
|
||||
if (!sel.length) {
|
||||
w2alert('삭제할 사용자를 선택하세요.')
|
||||
return
|
||||
}
|
||||
|
||||
// 선택된 user_id 수집
|
||||
const ids = sel
|
||||
.map(recid => {
|
||||
const r = g.get(recid)
|
||||
return r?.user_id
|
||||
})
|
||||
.filter(Boolean)
|
||||
|
||||
if (!ids.length) {
|
||||
w2alert('삭제 가능한 항목이 없습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
w2confirm(`선택한 ${ids.length}명의 사용자를 삭제하시겠습니까?`)
|
||||
.yes(() => {
|
||||
|
||||
fetch('/kngil/bbs/adm_comp.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'delete',
|
||||
// member_id: g.records[0]?.member_id,
|
||||
ids
|
||||
})
|
||||
})
|
||||
.then(res => res.text())
|
||||
.then(text => {
|
||||
try {
|
||||
const json = JSON.parse(text)
|
||||
if (json.status === 'success') {
|
||||
w2alert('삭제 완료')
|
||||
loadData()
|
||||
} else {
|
||||
w2alert(json.message || '삭제 실패')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(text)
|
||||
w2alert('서버 응답 오류 (JSON 아님)')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function loadTotalArea(memberId) {
|
||||
return fetch(`/kngil/bbs/adm_comp.php?action=total_area`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
if (json.status !== 'success') {
|
||||
throw new Error('총 구매면적 로딩 실패')
|
||||
}
|
||||
return Number(json.total_area || 0)
|
||||
})
|
||||
}
|
||||
|
||||
function doSearch() {
|
||||
|
||||
const keyword = document.getElementById('schKeyword').value.trim()
|
||||
const type = document.getElementById('schType').value
|
||||
const useYn = document.getElementById('schUseYn').value
|
||||
|
||||
let p_user_nm = ''
|
||||
let p_dept_nm = ''
|
||||
|
||||
// DB로 보낼 검색 조건
|
||||
if (type === 'name') {
|
||||
p_user_nm = keyword
|
||||
} else if (type === 'dept') {
|
||||
p_dept_nm = keyword
|
||||
} else if (type === '') {
|
||||
// 전체 검색 → 이름 OR 부서
|
||||
p_user_nm = keyword
|
||||
p_dept_nm = keyword
|
||||
}
|
||||
// ⚠️ type === 'id' 는 DB로 안 보냄
|
||||
|
||||
fetch(`/kngil/bbs/adm_comp.php?action=list`
|
||||
+ `&user_nm=${encodeURIComponent(p_user_nm)}`
|
||||
+ `&dept_nm=${encodeURIComponent(p_dept_nm)}`
|
||||
+ `&use_yn=${useYn}`
|
||||
)
|
||||
.then(res => res.json())
|
||||
.then(d => {
|
||||
|
||||
if (d.status !== 'success') {
|
||||
w2alert('검색 실패')
|
||||
return
|
||||
}
|
||||
|
||||
let records = d.records || []
|
||||
|
||||
// ID 검색은 프론트 필터
|
||||
if (type === 'id' && keyword) {
|
||||
records = records.filter(r =>
|
||||
(r.user_id || '').toLowerCase()
|
||||
.includes(keyword.toLowerCase())
|
||||
)
|
||||
}
|
||||
|
||||
const g = w2ui.detailGrid || w2ui.userGrid
|
||||
records = normalizeAuth(records)
|
||||
records = normalizeUseYn(records)
|
||||
g.clear()
|
||||
g.add(records)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('btnSearch')
|
||||
?.addEventListener('click', () => {
|
||||
|
||||
const memberInput = document.getElementById('targetMemberId');
|
||||
const memberId = memberInput ? memberInput.value.trim() : '';
|
||||
|
||||
if (memberInput && memberInput.style.display !== 'none') {
|
||||
CURRENT_MEMBER_ID = memberId; // ⭐ 저장
|
||||
loadDataByMemberId(memberId);
|
||||
return;
|
||||
}
|
||||
|
||||
doSearch();
|
||||
});
|
||||
|
||||
document.getElementById('schKeyword')
|
||||
?.addEventListener('keydown', e => {
|
||||
if (e.key === 'Enter') doSearch()
|
||||
})
|
||||
|
||||
document.getElementById('btnBulkCreate')
|
||||
?.addEventListener('click', () => {
|
||||
|
||||
const memberId = getTargetMemberId()
|
||||
|
||||
if (!memberId) {
|
||||
w2alert('회원ID를 입력하세요.')
|
||||
return
|
||||
}
|
||||
|
||||
// 🔥 여기서 CSV URL 팝업 띄움
|
||||
openBulkCreatePopup(memberId)
|
||||
})
|
||||
|
||||
function openBulkCreatePopup(memberId) {
|
||||
|
||||
// ⭐ 방어: 객체면 member_id만 사용
|
||||
if (typeof memberId === 'object' && memberId !== null) {
|
||||
memberId = memberId.member_id || '';
|
||||
}
|
||||
|
||||
if (!memberId) {
|
||||
w2alert('회원ID가 올바르지 않습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
w2popup.open({
|
||||
title: '사용자 일괄 생성 (CSV)',
|
||||
width: 520,
|
||||
height: 220,
|
||||
modal: true,
|
||||
body: `
|
||||
<div style="padding:20px">
|
||||
<p style="margin-bottom:8px">
|
||||
대상 회원ID: <b>${memberId}</b>
|
||||
</p>
|
||||
|
||||
<input type="text"
|
||||
id="csvUrl"
|
||||
placeholder="CSV URL 입력"
|
||||
style="width:100%; padding:6px" />
|
||||
|
||||
<div style="margin-top:15px; text-align:right">
|
||||
<button class="w2ui-btn" id="btnCsvRun">실행</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
onOpen(event) {
|
||||
event.onComplete = () => {
|
||||
document
|
||||
.getElementById('btnCsvRun')
|
||||
.addEventListener('click', () => {
|
||||
|
||||
const url =
|
||||
document.getElementById('csvUrl').value.trim()
|
||||
|
||||
if (!url) {
|
||||
w2alert('CSV URL을 입력하세요.')
|
||||
return
|
||||
}
|
||||
|
||||
runBulkCreate(memberId, url)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function runBulkCreate(memberId, csvUrl) {
|
||||
|
||||
fetch('/kngil/bbs/adm_comp.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'bulk_create',
|
||||
member_id: memberId,
|
||||
csv_url: csvUrl
|
||||
})
|
||||
})
|
||||
.then(res => res.text())
|
||||
.then(text => {
|
||||
|
||||
let d;
|
||||
try {
|
||||
d = JSON.parse(text);
|
||||
} catch (e) {
|
||||
w2alert({
|
||||
title: '서버 오류',
|
||||
text: `<pre style="white-space:pre-wrap; text-align:left;">${text}</pre>`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const successCnt = Number(d.success_cnt || 0);
|
||||
const failCnt = Number(d.fail_cnt || 0);
|
||||
|
||||
let errors = d.errors || [];
|
||||
// 배열이지만 요소가 객체일 수 있음 → 문자열로 강제
|
||||
errors = errors.map(e => {
|
||||
if (typeof e === 'string') return e;
|
||||
try {
|
||||
return JSON.stringify(e);
|
||||
} catch {
|
||||
return String(e);
|
||||
}
|
||||
});
|
||||
|
||||
// // ⭐ 핵심: object → array 변환
|
||||
// if (!Array.isArray(errors) && typeof errors === 'object') {
|
||||
// errors = Object.values(errors);
|
||||
// }
|
||||
console.log('errors raw =', d.errors);
|
||||
// ❌ 전부 실패
|
||||
if (successCnt === 0) {
|
||||
w2popup.close(); // ⭐ 먼저 CSV 팝업 닫기
|
||||
|
||||
w2alert(`
|
||||
<div style="
|
||||
text-align:center;
|
||||
line-height:1.6;
|
||||
padding:10px;
|
||||
font-size:16px;
|
||||
">
|
||||
<b>일괄 생성 실패</b><br><br>
|
||||
${errors.map(e => `• ${e}`).join('<br>')}
|
||||
</div>
|
||||
`);
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ 성공 or 부분 성공
|
||||
let msg = '';
|
||||
msg += `✔ 성공: ${successCnt}명<br>`;
|
||||
msg += `❌ 실패: ${failCnt}명`;
|
||||
|
||||
if (errors.length > 0) {
|
||||
msg += '<hr style="margin:8px 0">';
|
||||
msg += '<div style="text-align:left; max-height:200px; overflow:auto;">';
|
||||
errors.forEach(err => {
|
||||
msg += `• ${err}<br>`;
|
||||
});
|
||||
msg += '</div>';
|
||||
}
|
||||
|
||||
w2alert({
|
||||
title: '일괄 생성 결과',
|
||||
msg: msg
|
||||
});
|
||||
|
||||
if (CURRENT_MEMBER_ID) {
|
||||
loadDataByMemberId(CURRENT_MEMBER_ID);
|
||||
} else {
|
||||
loadData();
|
||||
}
|
||||
w2popup.close();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
w2alert('서버 통신 중 오류가 발생했습니다.');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function loadDataByMemberId(memberId) {
|
||||
|
||||
if (!memberId) {
|
||||
w2alert('회원ID를 입력하세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`/kngil/bbs/adm_comp.php?action=list&member_id=${encodeURIComponent(memberId)}`)
|
||||
.then(res => res.json())
|
||||
.then(async d => {
|
||||
|
||||
if (d.status !== 'success') {
|
||||
w2alert(d.message || '조회 실패');
|
||||
return;
|
||||
}
|
||||
|
||||
let records = normalizeAuth(d.records || []);
|
||||
records = normalizeUseYn(records);
|
||||
|
||||
const gridName = w2ui.detailGrid ? 'detailGrid' : 'userGrid';
|
||||
w2ui[gridName].clear();
|
||||
w2ui[gridName].add(records);
|
||||
|
||||
// ✅ 상단 요약 갱신
|
||||
const totalArea = await loadTotalArea(memberId);
|
||||
renderSummaryFromRecords({
|
||||
memberId,
|
||||
records,
|
||||
totalArea
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert } from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
|
||||
|
||||
/* -------------------------------------------------
|
||||
공통 유틸
|
||||
------------------------------------------------- */
|
||||
function destroyGrid(name) {
|
||||
if (w2ui[name]) {
|
||||
w2ui[name].destroy()
|
||||
}
|
||||
}
|
||||
|
||||
function loadBaseCode(mainCd) {
|
||||
return fetch(`/kngil/bbs/adm_comp.php?action=base_code&main_cd=${mainCd}`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
if (json.status !== 'success') {
|
||||
throw new Error(json.message || '공통코드 로딩 실패')
|
||||
}
|
||||
return json.items
|
||||
})
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
faq 팝업 (슈퍼관리자 전용)
|
||||
================================================= */
|
||||
export function openfaqPopup() {
|
||||
|
||||
if (w2ui.faqGrid) {
|
||||
w2ui.faqGrid.destroy()
|
||||
}
|
||||
w2popup.open({
|
||||
title: 'FAQ 내용등록',
|
||||
width: 900,
|
||||
height: 600,
|
||||
modal: true,
|
||||
|
||||
body: `
|
||||
<div class="faq-popup">
|
||||
|
||||
<div style="display: flex; justify-content: flex-end; padding: 10px; gap: 5px;">
|
||||
<button id="faqAdd">추가</button>
|
||||
<button id="faqRemove">삭제</button>
|
||||
<button id="faqSave" class="btn-faq">저장</button>
|
||||
</div>
|
||||
|
||||
<div id="faqGrid" style="height:460px;"></div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
|
||||
onOpen(event) {
|
||||
event.onComplete = () => {
|
||||
// 1. 그리드를 생성합니다.
|
||||
createfaqGrid('#faqGrid');
|
||||
|
||||
|
||||
// 1. 추가 버튼
|
||||
document.getElementById('faqAdd').onclick = () => {
|
||||
const g = w2ui.faqGrid
|
||||
if (!g) return
|
||||
// 신규 row용 recid (음수로 충돌 방지)
|
||||
const newRecid = -Date.now()
|
||||
g.add({
|
||||
fa_subject: '',
|
||||
recid: newRecid,
|
||||
__isNew: true, // ⭐ 신규 플래그
|
||||
fa_content: ''
|
||||
}, true)
|
||||
g.select(newRecid)
|
||||
g.scrollIntoView(newRecid)
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 삭제 버튼 이벤트 연결
|
||||
const removeBtn = document.getElementById('faqRemove');
|
||||
if (removeBtn) {
|
||||
removeBtn.onclick = () => {
|
||||
const g = w2ui.faqGrid;
|
||||
if (!g) return;
|
||||
|
||||
// 1. 선택된 행 가져오기
|
||||
const sel = g.getSelection();
|
||||
if (!sel.length) {
|
||||
alert('삭제할 항목을 선택하세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. faq 추출
|
||||
const ids = sel
|
||||
.map(recid => g.get(recid)?.fa_id)
|
||||
.filter(Boolean);
|
||||
|
||||
if (!ids.length) {
|
||||
alert('삭제 가능한 항목이 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 브라우저 기본 확인창 사용 (가장 확실함)
|
||||
if (confirm(`선택한 ${ids.length}개의 상품을 삭제하시겠습니까?`)) {
|
||||
fetch('/kngil/bbs/adm_faq_popup_delete.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'delete', ids: ids })
|
||||
})
|
||||
.then(res => {
|
||||
// 서버 응답이 오면 일단 텍스트로 받아서 확인
|
||||
return res.text();
|
||||
})
|
||||
.then(text => {
|
||||
try {
|
||||
const json = JSON.parse(text);
|
||||
if (json.status === 'success') {
|
||||
alert('삭제 완료');
|
||||
loadfaqData(); // 목록 새로고침
|
||||
} else {
|
||||
alert(json.message || '삭제 실패');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('응답 파싱 에러:', text);
|
||||
alert('서버 응답 처리 중 오류가 발생했습니다.');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('통신 에러:', err);
|
||||
alert('서버와 통신할 수 없습니다.');
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// 3. 저장 버튼
|
||||
document.getElementById('faqSave').onclick = () => {
|
||||
|
||||
// 현재 사용 중인 grid
|
||||
const g = w2ui.faqGrid
|
||||
if (!g) return
|
||||
const changes = g.getChanges()
|
||||
if (!changes.length) {
|
||||
w2alert('변경된 내용이 없습니다.')
|
||||
return
|
||||
}
|
||||
const inserts = []
|
||||
const updates = []
|
||||
|
||||
changes.forEach(c => {
|
||||
const rec = g.get(c.recid)
|
||||
if (!rec) return
|
||||
// 🔥 핵심: 원본 rec + 변경값 c 병합
|
||||
const merged = { ...rec, ...c }
|
||||
if (rec.__isNew) {
|
||||
// INSERT → 전체 row 필요
|
||||
inserts.push(merged)
|
||||
} else {
|
||||
// UPDATE → PK + 변경 컬럼
|
||||
updates.push({
|
||||
fa_id : merged.fa_id,
|
||||
fa_subject : merged.fa_subject ,
|
||||
fa_content : merged.fa_content ,
|
||||
use_yn : merged.use_yn,
|
||||
sq_no : merged.sq_no
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
console.log('INSERTS', inserts)
|
||||
console.log('UPDATES', updates)
|
||||
|
||||
fetch('/kngil/bbs/adm_faq_popup_save.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'save',
|
||||
inserts,
|
||||
updates
|
||||
})
|
||||
})
|
||||
|
||||
.then(res => {
|
||||
// 서버가 준 응답이 괜찮은지 확인
|
||||
if (!res.ok) throw new Error('서버 응답 오류');
|
||||
return res.json(); // 처음부터 깔끔하게 데이터로 읽기
|
||||
})
|
||||
|
||||
.then(json => {
|
||||
// 이제 json.status를 바로 쓸 수 있습니다.
|
||||
if (json.status === 'success') {
|
||||
w2alert('저장 완료');
|
||||
w2ui.faqGrid.save(); // 빨간 삼각형 없애기
|
||||
loadfaqData(); // 목록 새로고침
|
||||
} else {
|
||||
w2alert(json.message || '저장 실패');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('에러 발생:', err);
|
||||
w2alert('처리 중 오류가 발생했습니다.');
|
||||
});
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
//faq 그리드
|
||||
export async function createfaqGrid(boxId) {
|
||||
if (w2ui.faqGrid) w2ui.faqGrid.destroy();
|
||||
destroyGrid('faqGrid')
|
||||
|
||||
const authItems = await loadBaseCode('BS210')
|
||||
|
||||
const grid = new w2grid({
|
||||
|
||||
name: 'faqGrid',
|
||||
box: boxId,
|
||||
recordHeight: 80, // ⭐ 행 높이를 80px로 설정 (3줄 정도 높이)
|
||||
show: {
|
||||
footer: true,
|
||||
selectColumn: true,
|
||||
lineNumbers: true // 행 번호를 표시하면 디버깅이 편합니다.
|
||||
},
|
||||
columns: [
|
||||
/*
|
||||
{ field: 'row_status', text: ' ', size: '30px', attr: 'align=center',
|
||||
render: function (record) {
|
||||
// 1. 신규 추가된 행 (recid가 임시값이거나 DB에 없는 경우)
|
||||
if (record.is_new) return '<span style="color: green;">I</span>';
|
||||
|
||||
// 2. 수정된 데이터 (w2ui.changes 객체가 존재하는 경우)
|
||||
if (record.w2ui && record.w2ui.changes) return '<span style="color: blue;">U</span>';
|
||||
// 3. 일반 상태
|
||||
return '<span style="color: gray;"> </span>';
|
||||
}
|
||||
},
|
||||
*/
|
||||
{ field: 'fa_id', text: 'FAID', size: '60',attr: 'align=center',style: 'text-align: center', attr: 'align=center' ,hidden: true,sortable: true}, // name 아님!
|
||||
{ field: 'fa_subject', text: '질문', size: '300', editable: { type: 'text' }
|
||||
,render: function(record) {
|
||||
if (!record.fa_content) return '';
|
||||
// 엔터값(\n)을 브라우저가 인식하는 <br>로 바꿔서 리턴
|
||||
return record.fa_content.replace(/\n/g, '<br>');
|
||||
}
|
||||
}, // name 아님!
|
||||
{ field: 'fa_content', text: '답글', size: '300', editable: { type: 'text' } }, // volume 아님!
|
||||
{ field: 'sq_no', text: '순번', size: '60', attr: 'align=center',style: 'text-align: center',render: 'number:0', editable: { type: 'int' } ,sortable: true}, //
|
||||
{ field: 'use_yn', text: '사용여부', size: '80px',attr: 'align=center',style: 'text-align: center', attr: 'align=center',
|
||||
editable: { type: 'list', items: authItems, filter: false ,showAll: true } ,
|
||||
render(record) {
|
||||
const item = authItems.find(i => i.id === record.use_yn)
|
||||
return item ? item.text : record.use_yn
|
||||
},sortable: true
|
||||
},
|
||||
{ field: 'rmks', text: '비고', size: '200px', attr: 'align=center', editable: { type: 'text' } } // memo 아님!
|
||||
],
|
||||
records: [] // 처음엔 비워둠
|
||||
});
|
||||
|
||||
// 데이터 호출 함수 실행
|
||||
loadfaqData();
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
|
||||
// 데이터를 서버에서 불러오는 함수
|
||||
async function loadfaqData() {
|
||||
try {
|
||||
w2ui.faqGrid.lock('조회 중...', true);
|
||||
|
||||
const response = await fetch('/kngil/bbs/adm_faq_popup.php'); // PHP 파일 호출
|
||||
const data = await response.json();
|
||||
|
||||
w2ui.faqGrid.clear();
|
||||
w2ui.faqGrid.add(data);
|
||||
w2ui.faqGrid.unlock();
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
w2ui.faqGrid.unlock();
|
||||
w2alert('데이터 로드 실패');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert } from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
|
||||
|
||||
/* -------------------------------------------------
|
||||
공통 유틸
|
||||
------------------------------------------------- */
|
||||
function destroyGrid(name) {
|
||||
if (w2ui[name]) {
|
||||
w2ui[name].destroy()
|
||||
}
|
||||
}
|
||||
|
||||
function loadBaseCode(mainCd) {
|
||||
return fetch(`/kngil/bbs/adm_comp.php?action=base_code&main_cd=${mainCd}`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
if (json.status !== 'success') {
|
||||
throw new Error(json.message || '공통코드 로딩 실패')
|
||||
}
|
||||
return json.items
|
||||
})
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
상품등록 팝업 (슈퍼관리자 전용)
|
||||
================================================= */
|
||||
export function openProductPopup() {
|
||||
|
||||
if (w2ui.productGrid) {
|
||||
w2ui.productGrid.destroy()
|
||||
}
|
||||
w2popup.open({
|
||||
title: '상품등록',
|
||||
width: 900,
|
||||
height: 600,
|
||||
modal: true,
|
||||
|
||||
body: `
|
||||
<div class="product-popup">
|
||||
|
||||
<div style="display: flex; justify-content: flex-end; padding: 1S0px; gap: 5px;">
|
||||
<button id="prodAdd">추가</button>
|
||||
<button id="prodRemove">삭제</button>
|
||||
<button id="prodSave" class="btn-product">저장</button>
|
||||
</div>
|
||||
|
||||
<div id="productGrid" style="height:460px;"></div>
|
||||
</div>
|
||||
`,
|
||||
|
||||
|
||||
onOpen(event) {
|
||||
event.onComplete = () => {
|
||||
// 1. 그리드를 생성합니다.
|
||||
createProductGrid('#productGrid');
|
||||
|
||||
|
||||
// 1. 추가 버튼
|
||||
document.getElementById('prodAdd').onclick = () => {
|
||||
const g = w2ui.productGrid
|
||||
if (!g) return
|
||||
// 신규 row용 recid (음수로 충돌 방지)
|
||||
const newRecid = -Date.now()
|
||||
g.add({
|
||||
row_status: 'I',
|
||||
recid: newRecid,
|
||||
__isNew: true, // ⭐ 신규 플래그
|
||||
use_yn: 'Y'
|
||||
}, true)
|
||||
g.select(newRecid)
|
||||
g.scrollIntoView(newRecid)
|
||||
|
||||
// commonAdd('productGrid', { use_yn: 'Y', itm_amt: 0, area: 0 });
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 삭제 버튼 이벤트 연결
|
||||
const removeBtn = document.getElementById('prodRemove');
|
||||
if (removeBtn) {
|
||||
removeBtn.onclick = () => {
|
||||
const g = w2ui.productGrid;
|
||||
if (!g) return;
|
||||
|
||||
// 1. 선택된 행 가져오기
|
||||
const sel = g.getSelection();
|
||||
if (!sel.length) {
|
||||
alert('삭제할 상품을 선택하세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 상품코드 추출
|
||||
const ids = sel
|
||||
.map(recid => g.get(recid)?.itm_cd)
|
||||
.filter(Boolean);
|
||||
|
||||
if (!ids.length) {
|
||||
alert('삭제 가능한 항목이 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 브라우저 기본 확인창 사용 (가장 확실함)
|
||||
if (confirm(`선택한 ${ids.length}개의 상품을 삭제하시겠습니까?`)) {
|
||||
fetch('/kngil/bbs/adm_product_popup_delete.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'delete', ids: ids })
|
||||
})
|
||||
.then(res => {
|
||||
// 서버 응답이 오면 일단 텍스트로 받아서 확인
|
||||
return res.text();
|
||||
})
|
||||
.then(text => {
|
||||
try {
|
||||
const json = JSON.parse(text);
|
||||
if (json.status === 'success') {
|
||||
alert('삭제 완료');
|
||||
loadProductData(); // 목록 새로고침
|
||||
} else {
|
||||
alert(json.message || '삭제 실패');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('응답 파싱 에러:', text);
|
||||
alert('서버 응답 처리 중 오류가 발생했습니다.');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('통신 에러:', err);
|
||||
alert('서버와 통신할 수 없습니다.');
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// 3. 저장 버튼
|
||||
document.getElementById('prodSave').onclick = () => {
|
||||
|
||||
// 현재 사용 중인 grid
|
||||
const g = w2ui.productGrid
|
||||
if (!g) return
|
||||
const changes = g.getChanges()
|
||||
if (!changes.length) {
|
||||
w2alert('변경된 내용이 없습니다.')
|
||||
return
|
||||
}
|
||||
const inserts = []
|
||||
const updates = []
|
||||
|
||||
changes.forEach(c => {
|
||||
const rec = g.get(c.recid)
|
||||
if (!rec) return
|
||||
// 🔥 핵심: 원본 rec + 변경값 c 병합
|
||||
const merged = { ...rec, ...c }
|
||||
if (rec.__isNew) {
|
||||
// INSERT → 전체 row 필요
|
||||
inserts.push(merged)
|
||||
} else {
|
||||
// UPDATE → PK + 변경 컬럼
|
||||
updates.push({
|
||||
itm_cd : merged.itm_cd,
|
||||
itm_nm : merged.itm_nm,
|
||||
area : merged.area,
|
||||
itm_amt: merged.itm_amt,
|
||||
use_yn : merged.use_yn,
|
||||
rmks : merged.rmks
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
console.log('INSERTS', inserts)
|
||||
console.log('UPDATES', updates)
|
||||
|
||||
fetch('/kngil/bbs/adm_product_popup_save.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'save',
|
||||
inserts,
|
||||
updates
|
||||
})
|
||||
})
|
||||
|
||||
.then(res => {
|
||||
// 서버가 준 응답이 괜찮은지 확인
|
||||
if (!res.ok) throw new Error('서버 응답 오류');
|
||||
return res.json(); // 처음부터 깔끔하게 데이터로 읽기
|
||||
})
|
||||
|
||||
.then(json => {
|
||||
// 이제 json.status를 바로 쓸 수 있습니다.
|
||||
if (json.status === 'success') {
|
||||
w2alert('저장 완료');
|
||||
w2ui.productGrid.save(); // 빨간 삼각형 없애기
|
||||
loadProductData(); // 목록 새로고침
|
||||
} else {
|
||||
w2alert(json.message || '저장 실패');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('에러 발생:', err);
|
||||
w2alert('처리 중 오류가 발생했습니다.');
|
||||
});
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
//상품등록 그리드
|
||||
export async function createProductGrid(boxId) {
|
||||
if (w2ui.productGrid) w2ui.productGrid.destroy();
|
||||
destroyGrid('productGrid')
|
||||
|
||||
const authItems = await loadBaseCode('BS210')
|
||||
|
||||
const grid = new w2grid({
|
||||
|
||||
name: 'productGrid',
|
||||
box: boxId,
|
||||
show: {
|
||||
footer: true,
|
||||
selectColumn: true,
|
||||
lineNumbers: true // 행 번호를 표시하면 디버깅이 편합니다.
|
||||
},
|
||||
columns: [
|
||||
/*
|
||||
{ field: 'row_status', text: ' ', size: '30px', attr: 'align=center',
|
||||
render: function (record) {
|
||||
// 1. 신규 추가된 행 (recid가 임시값이거나 DB에 없는 경우)
|
||||
if (record.is_new) return '<span style="color: green;">I</span>';
|
||||
|
||||
// 2. 수정된 데이터 (w2ui.changes 객체가 존재하는 경우)
|
||||
if (record.w2ui && record.w2ui.changes) return '<span style="color: blue;">U</span>';
|
||||
// 3. 일반 상태
|
||||
return '<span style="color: gray;"> </span>';
|
||||
}
|
||||
},
|
||||
*/
|
||||
{ field: 'itm_cd', text: '상품코드', size: '80px',attr: 'align=center',style: 'text-align: center', attr: 'align=center', editable: { type: 'text' } ,sortable: true}, // name 아님!
|
||||
{ field: 'itm_nm', text: '상품명', size: '120px', attr: 'align=center',style: 'text-align: center', editable: { type: 'text' } ,sortable: true}, // name 아님!
|
||||
{ field: 'area', text: '제공량', size: '100px', attr: 'align=center',render: 'number:0' , editable: { type: 'float' } ,sortable: true}, // volume 아님!
|
||||
{ field: 'itm_amt', text: '단가', size: '120px', attr: 'align=center',render: 'number:0', editable: { type: 'int' } ,sortable: true}, //
|
||||
{ field: 'use_yn', text: '사용여부', size: '80px',attr: 'align=center',style: 'text-align: center', attr: 'align=center',
|
||||
editable: { type: 'list', items: authItems, filter: false ,showAll: true } ,
|
||||
render(record) {
|
||||
const item = authItems.find(i => i.id === record.use_yn)
|
||||
return item ? item.text : record.use_yn
|
||||
},sortable: true
|
||||
},
|
||||
{ field: 'rmks', text: '비고', size: '200px', attr: 'align=center', editable: { type: 'text' } ,sortable: true} // memo 아님!
|
||||
],
|
||||
records: [] // 처음엔 비워둠
|
||||
});
|
||||
|
||||
// 데이터 호출 함수 실행
|
||||
loadProductData();
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
|
||||
// 데이터를 서버에서 불러오는 함수
|
||||
async function loadProductData() {
|
||||
try {
|
||||
w2ui.productGrid.lock('조회 중...', true);
|
||||
|
||||
const response = await fetch('/kngil/bbs/adm_product_popup.php'); // PHP 파일 호출
|
||||
const data = await response.json();
|
||||
|
||||
w2ui.productGrid.clear();
|
||||
w2ui.productGrid.add(data);
|
||||
w2ui.productGrid.unlock();
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
w2ui.productGrid.unlock();
|
||||
w2alert('데이터 로드 실패');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert } from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
// 파일이 실제 존재하는지 확인 필수! 존재하지 않으면 아래 코드가 모두 멈춥니다.
|
||||
import { bindProductPopupEvents } from '/kngil/js/adm_common.js'
|
||||
|
||||
|
||||
|
||||
export function openPurchaseHistoryPopup(memberId = '',isSuperAdmin='') {
|
||||
// 기존 그리드 안전하게 제거
|
||||
if (w2ui.purchaseHistoryGrid) {
|
||||
w2ui.purchaseHistoryGrid.destroy();
|
||||
}
|
||||
|
||||
w2popup.open({
|
||||
title: '서비스 구매 이력',
|
||||
width: 1100,
|
||||
height: 600,
|
||||
modal: true,
|
||||
body:
|
||||
/*
|
||||
`
|
||||
<div style="padding:8px">
|
||||
<div id="purchaseHistoryGrid" style="height:520px;"></div>
|
||||
</div>
|
||||
*/
|
||||
`
|
||||
<div id="popupMainContainer" style="display: flex; flex-direction: column; height: 100%; padding: 10px; gap: 10px; box-sizing: border-box;">
|
||||
|
||||
<div id="searchFormArea" style="display: flex; align-items: center; gap: 10px; padding: 15px; background: #f9f9f9; border: 1px solid #ddd; border-radius: 4px;">
|
||||
<span style="font-weight: bold; color: #333;">회원 ID</span>
|
||||
<input type="text" id="searchMemberId" value="${memberId}"
|
||||
${!isSuperAdmin ? 'disabled' : ''}
|
||||
style="width: 150px; padding: 6px; border: 1px solid #ccc; border-radius: 4px;"
|
||||
placeholder="아이디 입력">
|
||||
|
||||
<button id="btnSearchHistory"
|
||||
style="padding: 6px 20px; background: #1565c0; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold;">
|
||||
검색
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="purchaseHistoryGrid" style="flex: 1; min-height: 450px; border: 1px solid #ddd;"></div>
|
||||
</div>
|
||||
|
||||
`,
|
||||
onOpen(event) {
|
||||
event.onComplete = () => {
|
||||
const searchBtn = document.getElementById('btnSearchHistory');
|
||||
const searchInput = document.getElementById('searchMemberId');
|
||||
|
||||
// 조회 버튼 클릭 시 동작
|
||||
if (searchBtn) {
|
||||
searchBtn.onclick = () => {
|
||||
loadPurchaseHistoryData(searchInput.value);
|
||||
};
|
||||
}
|
||||
|
||||
// 엔터키 지원
|
||||
if (searchInput) {
|
||||
searchInput.onkeydown = (e) => {
|
||||
if (e.key === 'Enter') searchBtn.click();
|
||||
};
|
||||
}
|
||||
|
||||
createPurchaseHistoryGrid(memberId);
|
||||
loadPurchaseHistoryData(memberId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createPurchaseHistoryGrid(memberId) {
|
||||
new w2grid({
|
||||
name: 'purchaseHistoryGrid',
|
||||
box: '#purchaseHistoryGrid',
|
||||
show: {
|
||||
//toolbar: true,
|
||||
footer: true,
|
||||
lineNumbers: true // 행 번호를 표시하면 디버깅이 편합니다.
|
||||
},
|
||||
columns: [
|
||||
// field 이름이 PHP에서 내려주는 JSON 키값과 정확히 일치해야 함!
|
||||
{ field: 'member_id', text: '회원ID', size: '80px',style: 'text-align: center', attr: 'align=center',sortable: true }, // name 아님!
|
||||
{ field: 'sq_no', text: '순번', size: '50px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'user_nm', text: '구매자', size: '80px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'co_nm', text: '회사명', size: '100px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'bs_no', text: '사업자번호', size: '100px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'buy_dt', text: '구입일자', size: '80px',style: 'text-align: center', attr: 'align=center',sortable: true }, // name 아님!
|
||||
{ field: 'itm_nm', text: '상품명', size: '80px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'area', text: '상품면적', size: '80px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'itm_qty', text: '수량', size: '80px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'itm_area', text: '면적', size: '100px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'add_area', text: '추가면적', size: '100px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'sum_area', text: '합계면적', size: '100px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'itm_amt', text: '단가', size: '100px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'dis_rt', text: '할인율', size: '80px', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'buy_amt', text: '공급금액', size: '100px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'vat_amt', text: '부가세', size: '100px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'sum_amt', text: '합계', size: '100px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'end_dt', text: '종료일', size: '80px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'ok_yn', text: '승인여부', size: '80px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'rmks', text: '비고', size: '150px',style: 'text-align: center', attr: 'align=center' ,sortable: true} // name 아님!
|
||||
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async function loadPurchaseHistoryData(memberId) {
|
||||
try {
|
||||
const grid = w2ui.purchaseHistoryGrid;
|
||||
if (!grid) return;
|
||||
|
||||
grid.lock('조회 중...', true);
|
||||
|
||||
const searchParams = new URLSearchParams();
|
||||
searchParams.append('member_id', memberId);
|
||||
searchParams.append('member_nm', '');
|
||||
searchParams.append('fbuy_dt', '');
|
||||
searchParams.append('tbuy_dt', '');
|
||||
|
||||
const response = await fetch('/kngil/bbs/adm_purch_popup.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: searchParams
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error(`서버 응답 오류: ${response.status}`);
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!Array.isArray(data)) {
|
||||
throw new Error('응답 데이터 형식 오류');
|
||||
}
|
||||
|
||||
grid.clear();
|
||||
grid.add(data);
|
||||
grid.unlock();
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (w2ui.purchaseHistoryGrid) w2ui.purchaseHistoryGrid.unlock();
|
||||
w2alert('구매이력 조회 실패: ' + e.message);
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,237 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert }
|
||||
from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
|
||||
/* -------------------------------------------------
|
||||
공통 유틸
|
||||
------------------------------------------------- */
|
||||
function destroyGrid(name) {
|
||||
if (w2ui[name]) w2ui[name].destroy()
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
서비스 등록 팝업
|
||||
------------------------------------------------- */
|
||||
export function openServiceRegisterPopup(ctx) {
|
||||
|
||||
destroyGrid('serviceGrid')
|
||||
destroyGrid('productList')
|
||||
|
||||
w2popup.open({
|
||||
title: '서비스 등록',
|
||||
width: 1300,
|
||||
height: 720,
|
||||
modal: true,
|
||||
body: `
|
||||
<div class="service-popup">
|
||||
|
||||
<!-- 상단 -->
|
||||
<div class="service-top">
|
||||
|
||||
<!-- 좌측 : 회원정보 + 구매일 -->
|
||||
<div class="service-member">
|
||||
<div><b>회원ID</b> : ${ctx.memberId}</div>
|
||||
<div><b>회원명</b> : ${ctx.memberName}</div>
|
||||
<div><b>회사명</b> : ${ctx.company}</div>
|
||||
<div><b>사업자번호</b> : ${ctx.bizNo}</div>
|
||||
|
||||
<div class="purchase-date">
|
||||
<label>구매일</label>
|
||||
<input type="date" id="buyDate">
|
||||
<button id="btnSearchBuy">조회</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 우측 : 상품 선택 -->
|
||||
<div class="service-product">
|
||||
<div class="title">상품 선택 (더블클릭)</div>
|
||||
<div id="productList" style="height:160px;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 중단 -->
|
||||
<div class="service-grid">
|
||||
<div id="serviceGrid" style="height:260px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- 하단 -->
|
||||
<div class="service-summary">
|
||||
<div>공급가액 <span id="sumSupply">0</span></div>
|
||||
<div>부가세 <span id="sumVat">0</span></div>
|
||||
<div>결제금액 <span id="sumTotal">0</span></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
onOpen(event) {
|
||||
event.onComplete = () => {
|
||||
createServiceGrid()
|
||||
createProductList()
|
||||
|
||||
// ✅ 구매일 조회 버튼 바인딩 (여기서!)
|
||||
document.getElementById('btnSearchBuy').addEventListener('click', () => {
|
||||
const buyDate = document.getElementById('buyDate').value
|
||||
if (!buyDate) {
|
||||
w2alert('구매일을 선택하세요')
|
||||
return
|
||||
}
|
||||
loadExistingPurchase(ctx.memberId, buyDate)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
서비스 Grid
|
||||
------------------------------------------------- */
|
||||
function createServiceGrid() {
|
||||
|
||||
new w2grid({
|
||||
name: 'serviceGrid',
|
||||
box: '#serviceGrid',
|
||||
show: {
|
||||
footer: true,
|
||||
// selectColumn: true
|
||||
},
|
||||
columns: [
|
||||
{ field: 'recid', text: 'NO', size: '50px', attr: 'align=center' },
|
||||
{ field: 'itm_cd', text: '상품명', size: '100px' },
|
||||
{ field: 'itm_area', text: '면적(m²)', size: '100px', editable: { type: 'int' } },
|
||||
{ field: 'itm_amt', text: '금액', size: '100px', attr: 'align=right' },
|
||||
{ field: 'itm_qty', text: '수량', size: '80px', editable: { type: 'int' } },
|
||||
{ field: 'dis_rt', text: '할인율', size: '80px', editable: { type: 'int' } },
|
||||
{ field: 'supply', text: '공급가액', size: '120px', attr: 'align=right' },
|
||||
{ field: 'vat_amt', text: '부가세', size: '100px', attr: 'align=right' },
|
||||
{ field: 'sum_amt', text: '결제금액', size: '120px', attr: 'align=right' },
|
||||
{ field: 'end_dt', text: '만료일자', size: '110px', editable: { type: 'date' } },
|
||||
{ field: 'rmks', text: '비고', size: '150px', editable: { type: 'text' } }
|
||||
],
|
||||
records: [],
|
||||
onChange() {
|
||||
calcSummary()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
상품 목록
|
||||
------------------------------------------------- */
|
||||
function createProductList() {
|
||||
|
||||
new w2grid({
|
||||
name: 'productList',
|
||||
box: '#productList',
|
||||
columns: [
|
||||
{ field: 'name', text: '상품명', size: '120px' },
|
||||
{ field: 'area', text: '제공량', size: '100px', attr: 'align=right' },
|
||||
{ field: 'price', text: '단가', size: '100px', attr: 'align=right' }
|
||||
],
|
||||
records: [
|
||||
{ recid: 1, name: '다이아', area: 10000000, price: 10000000 },
|
||||
{ recid: 2, name: '골드', area: 1000000, price: 5000000 },
|
||||
{ recid: 3, name: '실버', area: 100000, price: 1000000 }
|
||||
],
|
||||
onDblClick(event) {
|
||||
const rec = this.get(event.recid)
|
||||
addServiceFromProduct(rec)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
상품 → 서비스 Grid 추가
|
||||
------------------------------------------------- */
|
||||
function addServiceFromProduct(p) {
|
||||
|
||||
const g = w2ui.serviceGrid
|
||||
const recid = g.records.length + 1
|
||||
|
||||
const supply = p.price
|
||||
const vat = Math.floor(supply * 0.1)
|
||||
const total = supply + vat
|
||||
|
||||
g.add({
|
||||
recid,
|
||||
itm_cd: p.name,
|
||||
itm_area: p.area,
|
||||
itm_amt: p.price,
|
||||
itm_qty: 1,
|
||||
dis_rt: 0,
|
||||
supply,
|
||||
vat_amt: vat,
|
||||
sum_amt: total,
|
||||
end_dt: '',
|
||||
rmks: ''
|
||||
})
|
||||
|
||||
calcSummary()
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
기존 구매 불러오기
|
||||
------------------------------------------------- */
|
||||
function loadExistingPurchase(memberId, buyDate) {
|
||||
|
||||
fetch(`/kngil/bbs/adm_service.php?member_id=${memberId}&buy_date=${buyDate}`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
|
||||
if (json.status !== 'success') {
|
||||
w2alert(json.message || '조회 실패')
|
||||
return
|
||||
}
|
||||
|
||||
const g = w2ui.serviceGrid
|
||||
g.clear()
|
||||
|
||||
json.records.forEach((r, i) => {
|
||||
g.add({
|
||||
recid: i + 1,
|
||||
itm_cd: r.itm_cd,
|
||||
itm_area: Number(r.itm_area),
|
||||
itm_amt: Number(r.itm_amt),
|
||||
itm_qty: Number(r.itm_qty),
|
||||
dis_rt: Number(r.dis_rt),
|
||||
supply: Number(r.supply),
|
||||
vat_amt: Number(r.vat_amt),
|
||||
sum_amt: Number(r.sum_amt),
|
||||
end_dt: r.end_dt,
|
||||
rmks: r.rmks,
|
||||
_existing: true
|
||||
})
|
||||
|
||||
// 🔒 기존 구매 회색 처리
|
||||
g.set(i + 1, {
|
||||
w2ui: { style: 'background:#f3f3f3;color:#555' }
|
||||
})
|
||||
})
|
||||
|
||||
g.refresh()
|
||||
calcSummary()
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
w2alert('서버 오류')
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
합계 계산
|
||||
------------------------------------------------- */
|
||||
function calcSummary() {
|
||||
|
||||
let supply = 0
|
||||
let vat = 0
|
||||
let total = 0
|
||||
|
||||
w2ui.serviceGrid.records.forEach(r => {
|
||||
supply += Number(r.supply || 0)
|
||||
vat += Number(r.vat_amt || 0)
|
||||
total += Number(r.sum_amt || 0)
|
||||
})
|
||||
|
||||
document.getElementById('sumSupply').innerText = supply.toLocaleString()
|
||||
document.getElementById('sumVat').innerText = vat.toLocaleString()
|
||||
document.getElementById('sumTotal').innerText = total.toLocaleString()
|
||||
}
|
||||
@@ -0,0 +1,678 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert, w2confirm }
|
||||
from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
|
||||
/* -------------------------------------------------
|
||||
공통 유틸
|
||||
------------------------------------------------- */
|
||||
function destroyGrid(name) {
|
||||
if (w2ui[name]) w2ui[name].destroy()
|
||||
}
|
||||
|
||||
function fmtNum(val) {
|
||||
return Number(val || 0).toLocaleString()
|
||||
}
|
||||
|
||||
function fmtPrice(val) {
|
||||
const v = Number(val || 0)
|
||||
return Number.isInteger(v)
|
||||
? v.toLocaleString()
|
||||
: v.toLocaleString(undefined, { minimumFractionDigits: 2 })
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
서비스 등록 팝업
|
||||
------------------------------------------------- */
|
||||
export function openServiceRegisterPopup(ctx) {
|
||||
|
||||
destroyGrid('serviceGrid')
|
||||
destroyGrid('productList')
|
||||
|
||||
w2popup.open({
|
||||
title: '서비스 등록',
|
||||
width: 1300,
|
||||
height: 720,
|
||||
modal: true,
|
||||
body: `
|
||||
<div class="service-popup">
|
||||
|
||||
<!-- 상단 -->
|
||||
<div class="service-top">
|
||||
|
||||
<!-- 좌측 : 회원정보 -->
|
||||
<div class="service-member">
|
||||
<div><b>회원ID</b> : ${ctx.memberId}</div>
|
||||
<div><b>회원명</b> : ${ctx.memberName}</div>
|
||||
<div><b>회사명</b> : ${ctx.company}</div>
|
||||
<div><b>사업자번호</b> : ${ctx.bizNo}</div>
|
||||
|
||||
<div class="purchase-date">
|
||||
<label>구매일</label>
|
||||
<input type="date" id="buyDate">
|
||||
<button id="btnSearchBuy">조회</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 우측 : 상품 선택 -->
|
||||
<div class="service-product">
|
||||
<div class="title">상품 선택 (더블클릭)</div>
|
||||
<div id="productList" style="height:160px;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 중단 -->
|
||||
<div class="service-save-bar">
|
||||
<div class="right-actions">
|
||||
<button id="btnDeleteRow" class="btn-delete">삭제</button>
|
||||
<button id="btnSaveService" class="btn-save">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-grid">
|
||||
<div id="serviceGrid" style="height:260px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- 하단 합계 -->
|
||||
<div class="service-summary">
|
||||
<div>공급가액 <span id="sumSupply">0</span></div>
|
||||
<div>부가세 <span id="sumVat">0</span></div>
|
||||
<div>결제금액 <span id="sumTotal">0</span></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
onOpen(event) {
|
||||
event.onComplete = () => {
|
||||
|
||||
createServiceGrid()
|
||||
createProductList()
|
||||
|
||||
const buyDateInput = document.getElementById('buyDate')
|
||||
const today = new Date().toISOString().slice(0, 10)
|
||||
|
||||
// 기본 구매일 = 오늘
|
||||
buyDateInput.value = today
|
||||
|
||||
// 자동 조회
|
||||
loadExistingPurchase(ctx.memberId, today)
|
||||
|
||||
// 수동 조회 버튼
|
||||
document.getElementById('btnSearchBuy').addEventListener('click', () => {
|
||||
const buyDate = buyDateInput.value
|
||||
if (!buyDate) {
|
||||
w2alert('구매일을 선택하세요')
|
||||
return
|
||||
}
|
||||
loadExistingPurchase(ctx.memberId, buyDate)
|
||||
})
|
||||
|
||||
document.getElementById('btnDeleteRow')
|
||||
.addEventListener('click', deleteSelectedRows)
|
||||
|
||||
document.getElementById('btnSaveService')
|
||||
.addEventListener('click', () => saveService(ctx))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
서비스 Grid
|
||||
------------------------------------------------- */
|
||||
function createServiceGrid() {
|
||||
|
||||
new w2grid({
|
||||
name: 'serviceGrid',
|
||||
box: '#serviceGrid',
|
||||
show: {
|
||||
footer: true,
|
||||
selectColumn: true
|
||||
},
|
||||
multiSelect: false,
|
||||
|
||||
columns: [
|
||||
{ field: 'recid', text: 'NO', size: '50px', attr: 'align=center' },
|
||||
{ field: 'itm_nm', text: '상품명', size: '120px', editable: { type: 'text' } },
|
||||
{ field: 'area', text: '제공량', size: '120px', editable: { type: 'text' } },
|
||||
{ field: 'itm_cd', text: '상품코드', hidden: true },
|
||||
{
|
||||
field: 'itm_amt',
|
||||
text: '단가',
|
||||
size: '100px',
|
||||
attr: 'align=right',
|
||||
render: r => fmtPrice(r.itm_amt)
|
||||
},
|
||||
{
|
||||
field: 'itm_qty',
|
||||
text: '수량',
|
||||
size: '80px',
|
||||
attr: 'align=right',
|
||||
editable: { type: 'int' },
|
||||
render: r => fmtNum(r.itm_qty)
|
||||
},
|
||||
{
|
||||
field: 'dis_rt',
|
||||
text: '할인율',
|
||||
size: '80px',
|
||||
editable: { type: 'int' }
|
||||
},
|
||||
{
|
||||
field: 'supply',
|
||||
text: '공급가액',
|
||||
size: '120px',
|
||||
attr: 'align=right',
|
||||
render: r => fmtNum(r.supply)
|
||||
},
|
||||
{
|
||||
field: 'vat_amt',
|
||||
text: '부가세',
|
||||
size: '100px',
|
||||
attr: 'align=right',
|
||||
render: r => fmtNum(r.vat_amt)
|
||||
},
|
||||
{
|
||||
field: 'sum_amt',
|
||||
text: '결제금액',
|
||||
size: '120px',
|
||||
attr: 'align=right',
|
||||
render: r => fmtNum(r.sum_amt)
|
||||
},
|
||||
{
|
||||
field: 'itm_area',
|
||||
text: '적용면적(m²)',
|
||||
size: '100px',
|
||||
attr: 'align=right',
|
||||
editable: { type: 'int' },
|
||||
render: r => fmtNum(r.itm_area)
|
||||
},
|
||||
{
|
||||
field: 'add_area',
|
||||
text: '추가면적(m²)',
|
||||
size: '110px',
|
||||
attr: 'align=right',
|
||||
editable: { type: 'int' },
|
||||
render: r => fmtNum(r.add_area)
|
||||
},
|
||||
{
|
||||
field: 'sum_area',
|
||||
text: '합계면적(m²)',
|
||||
size: '110px',
|
||||
attr: 'align=right',
|
||||
editable: { type: 'int' },
|
||||
render: r => fmtNum(r.sum_area)
|
||||
},
|
||||
{
|
||||
field: 'end_dt',
|
||||
text: '만료일자',
|
||||
size: '110px',
|
||||
editable: { type: 'date' }
|
||||
},
|
||||
{
|
||||
field: 'ok_yn',
|
||||
text: '승인여부',
|
||||
size: '80px',
|
||||
attr: 'align=center',
|
||||
editable: {
|
||||
type: 'combo',
|
||||
items: [
|
||||
{ id: 'N', text: '미승인' },
|
||||
{ id: 'Y', text: '승인' }
|
||||
],
|
||||
openOnFocus: true
|
||||
},
|
||||
render(record) {
|
||||
if (record.ok_yn === 'Y') return '승인'
|
||||
return '미승인'
|
||||
}
|
||||
},
|
||||
{ field: 'rmks', text: '비고', size: '150px', editable: { type: 'text' } }
|
||||
],
|
||||
|
||||
records: [],
|
||||
|
||||
/* -----------------------------
|
||||
일반 필드 처리 (date 제외)
|
||||
----------------------------- */
|
||||
onChange(event) {
|
||||
event.onComplete = (ev) => {
|
||||
const g = w2ui.serviceGrid
|
||||
const field = g.columns[ev.column].field
|
||||
|
||||
let val = ev.value_new
|
||||
if (typeof val === 'object' && val !== null) val = val.id
|
||||
|
||||
g.set(ev.recid, { [field]: val })
|
||||
|
||||
if (['itm_qty','dis_rt','add_area'].includes(field)) {
|
||||
recalcRow(ev.recid)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* -----------------------------
|
||||
날짜 전용 처리 (핵심)
|
||||
----------------------------- */
|
||||
onEditField(event) {
|
||||
if (event.field !== 'end_dt') return;
|
||||
|
||||
event.onComplete = () => {
|
||||
const g = w2ui.serviceGrid;
|
||||
const recid = event.recid;
|
||||
|
||||
const input = document.querySelector(
|
||||
`#grid_${g.name}_edit input`
|
||||
);
|
||||
if (!input) return;
|
||||
|
||||
input.addEventListener('change', () => {
|
||||
|
||||
// 🔥 날짜는 문자열 그대로 즉시 확정
|
||||
g.set(recid, {
|
||||
end_dt: input.value // YYYY-MM-DD
|
||||
});
|
||||
|
||||
// 🔥 w2ui 방식으로 edit 종료
|
||||
input.blur();
|
||||
|
||||
g.refreshRow(recid);
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------
|
||||
상품 목록
|
||||
------------------------------------------------- */
|
||||
function createProductList() {
|
||||
|
||||
new w2grid({
|
||||
name: 'productList',
|
||||
box: '#productList',
|
||||
url: '/kngil/bbs/adm_product_popup.php',
|
||||
columns: [
|
||||
{ field: 'itm_nm', text: '상품명', size: '120px' },
|
||||
{
|
||||
field: 'area',
|
||||
text: '제공량',
|
||||
size: '100px',
|
||||
attr: 'align=right',
|
||||
render(record) {
|
||||
return Number(record.area || 0).toLocaleString()
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'itm_amt',
|
||||
text: '단가',
|
||||
size: '120px',
|
||||
attr: 'align=right',
|
||||
render(record) {
|
||||
const v = Number(record.itm_amt || 0)
|
||||
// 정수면 소수점 제거
|
||||
return Number.isInteger(v)
|
||||
? v.toLocaleString()
|
||||
: v.toLocaleString(undefined, { minimumFractionDigits: 2 })
|
||||
}
|
||||
}
|
||||
],
|
||||
onDblClick(event) {
|
||||
event.onComplete = () => {
|
||||
const recid = event.detail?.recid
|
||||
if (!recid) return
|
||||
|
||||
const rec = this.get(recid)
|
||||
if (!rec) return
|
||||
|
||||
addServiceFromProduct(rec)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------
|
||||
상품 → 서비스 Grid 추가
|
||||
------------------------------------------------- */
|
||||
function addServiceFromProduct(p) {
|
||||
|
||||
const g = w2ui.serviceGrid
|
||||
const recid = g.records.length + 1
|
||||
|
||||
const qty = 1
|
||||
const area = Number(p.area || 0)
|
||||
const unit = Number(p.itm_amt || 0)
|
||||
|
||||
const today = new Date()
|
||||
const endDt = `${today.getFullYear()}-12-31`
|
||||
|
||||
g.add({
|
||||
recid,
|
||||
itm_cd: p.itm_cd,
|
||||
itm_nm: p.itm_nm,
|
||||
|
||||
area: area, // 제공량
|
||||
itm_qty: qty,
|
||||
itm_amt: unit,
|
||||
dis_rt: 0,
|
||||
|
||||
itm_area: area * qty,
|
||||
add_area: 0,
|
||||
sum_area: area * qty,
|
||||
|
||||
supply: unit * qty,
|
||||
vat_amt: Math.floor(unit * qty * 0.1),
|
||||
sum_amt: Math.floor(unit * qty * 1.1),
|
||||
|
||||
end_dt: endDt,
|
||||
ok_yn: 'N',
|
||||
rmks: '',
|
||||
|
||||
_new: true
|
||||
})
|
||||
|
||||
recalcRow(recid)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------
|
||||
행 삭제
|
||||
------------------------------------------------- */
|
||||
function deleteSelectedRows() {
|
||||
|
||||
const g = w2ui.serviceGrid
|
||||
const sel = g.getSelection()
|
||||
|
||||
if (!sel.length) {
|
||||
w2alert('삭제할 서비스를 선택하세요')
|
||||
return
|
||||
}
|
||||
|
||||
const recid = sel[0]
|
||||
const row = g.get(recid)
|
||||
|
||||
if (!row || !row.sq_no) {
|
||||
w2alert('삭제할 수 없는 항목입니다.')
|
||||
return
|
||||
}
|
||||
|
||||
if (row.ok_yn === 'Y') {
|
||||
w2alert('승인된 항목은 삭제할 수 없습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
w2confirm('선택한 서비스를 삭제하시겠습니까?')
|
||||
.yes(() => {
|
||||
deleteServiceImmediately(row)
|
||||
})
|
||||
}
|
||||
|
||||
function deleteServiceImmediately(row) {
|
||||
console.log({
|
||||
action: 'delete',
|
||||
member_id: row.member_id,
|
||||
sq_no: row.sq_no
|
||||
})
|
||||
|
||||
fetch('/kngil/bbs/adm_service.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'delete',
|
||||
member_id: row.member_id, // ✅ 여기 중요
|
||||
sq_no: row.sq_no
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (res.status === 'success') {
|
||||
w2alert('삭제되었습니다.')
|
||||
w2ui.serviceGrid.remove(row.recid)
|
||||
calcSummary()
|
||||
} else {
|
||||
w2alert(res.message || '삭제 실패')
|
||||
}
|
||||
})
|
||||
.catch(() => w2alert('서버 오류'))
|
||||
}
|
||||
|
||||
|
||||
function isServiceItem(r) {
|
||||
return r.itm_cd && r.itm_cd.startsWith('ZET01')
|
||||
|| r.itm_nm === '서비스'
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
기존 구매 불러오기
|
||||
------------------------------------------------- */
|
||||
function loadExistingPurchase(memberId, buyDate) {
|
||||
|
||||
fetch('/kngil/bbs/adm_service.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'list',
|
||||
member_id: memberId,
|
||||
buy_date: buyDate
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
|
||||
if (json.status !== 'success') {
|
||||
w2alert(json.message || '조회 실패')
|
||||
return
|
||||
}
|
||||
|
||||
const g = w2ui.serviceGrid
|
||||
g.clear()
|
||||
|
||||
json.records.forEach((r, i) => {
|
||||
g.add({
|
||||
recid: i + 1,
|
||||
member_id: memberId,
|
||||
sq_no: r.sq_no,
|
||||
|
||||
itm_cd: r.itm_cd,
|
||||
itm_nm: r.itm_nm,
|
||||
itm_area: Number(r.itm_area || 0),
|
||||
add_area: Number(r.add_area || 0),
|
||||
itm_amt: Number(r.itm_amt),
|
||||
itm_qty: Number(r.itm_qty),
|
||||
|
||||
// area
|
||||
area: isServiceItem(r)
|
||||
? 1
|
||||
: (r.itm_qty ? Number(r.itm_area) / Number(r.itm_qty) : 0),
|
||||
|
||||
dis_rt: Number(r.dis_rt || 0), // 문자열 → 숫자
|
||||
supply: Number(r.buy_amt),
|
||||
vat_amt: Number(r.vat_amt),
|
||||
sum_amt: Number(r.sum_amt),
|
||||
|
||||
end_dt: r.end_dt || '',
|
||||
ok_yn: r.ok_yn || 'N',
|
||||
rmks: r.rmks ?? '', // undefined 방지
|
||||
|
||||
_existing: true
|
||||
})
|
||||
|
||||
g.set(i + 1, {
|
||||
w2ui: { style: 'background:#f3f3f3;color:#555' }
|
||||
})
|
||||
})
|
||||
|
||||
g.refresh()
|
||||
// 🔥 모든 행 재계산
|
||||
g.records.forEach(r => {
|
||||
if (!r._deleted) {
|
||||
recalcRow(r.recid)
|
||||
}
|
||||
})
|
||||
calcSummary()
|
||||
})
|
||||
.catch(() => w2alert('서버 오류'))
|
||||
}
|
||||
|
||||
/* -------------------------------------------------
|
||||
행 단위 재계산
|
||||
------------------------------------------------- */
|
||||
function recalcRow(recid) {
|
||||
|
||||
const g = w2ui.serviceGrid
|
||||
const r = g.get(recid)
|
||||
if (!r) return
|
||||
|
||||
const qty = Number(r.itm_qty || 0)
|
||||
const unit = Number(r.itm_amt || 0)
|
||||
const rate = Number(r.dis_rt || 0)
|
||||
const area = Number(r.area || 0)
|
||||
const add = Number(r.add_area || 0)
|
||||
|
||||
// 🔥 적용면적 = 제공량 * 수량
|
||||
r.itm_area = area * qty
|
||||
|
||||
// 🔥 공급가액 = 단가 * 수량 * (1 - 할인율)
|
||||
const base = unit * qty
|
||||
const discount = Math.floor(base * (rate / 100))
|
||||
r.supply = base - discount
|
||||
|
||||
// 🔥 부가세 / 결제금액
|
||||
r.vat_amt = Math.floor(r.supply * 0.1)
|
||||
r.sum_amt = r.supply + r.vat_amt
|
||||
|
||||
// 🔥 합계면적
|
||||
r.sum_area = r.itm_area + add
|
||||
|
||||
g.refreshRow(recid)
|
||||
calcSummary()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------
|
||||
합계 계산
|
||||
------------------------------------------------- */
|
||||
function calcSummary() {
|
||||
|
||||
let supply = 0
|
||||
let vat = 0
|
||||
let total = 0
|
||||
|
||||
w2ui.serviceGrid.records.forEach(r => {
|
||||
if (r._deleted) return
|
||||
supply += Number(r.supply || 0)
|
||||
vat += Number(r.vat_amt || 0)
|
||||
total += Number(r.sum_amt || 0)
|
||||
})
|
||||
|
||||
document.getElementById('sumSupply').innerText = supply.toLocaleString()
|
||||
document.getElementById('sumVat').innerText = vat.toLocaleString()
|
||||
document.getElementById('sumTotal').innerText = total.toLocaleString()
|
||||
}
|
||||
|
||||
function saveService(ctx) {
|
||||
|
||||
const buyDate = document.getElementById('buyDate').value
|
||||
if (!buyDate) {
|
||||
w2alert('구매일을 선택하세요')
|
||||
return
|
||||
}
|
||||
|
||||
const g = w2ui.serviceGrid
|
||||
|
||||
// 🔥🔥🔥 핵심: 현재 편집중인 셀 강제 반영
|
||||
g.save()
|
||||
|
||||
const items = g.records.map(r => ({
|
||||
sq_no: r.sq_no || null,
|
||||
itm_cd: r.itm_cd,
|
||||
itm_area: r.itm_area,
|
||||
add_area: r.add_area || 0,
|
||||
itm_amt: r.itm_amt,
|
||||
itm_qty: r.itm_qty,
|
||||
|
||||
dis_rt: r.dis_rt,
|
||||
buy_amt: r.supply,
|
||||
vat_amt: r.vat_amt,
|
||||
sum_amt: r.sum_amt,
|
||||
end_dt: dateToYMD(r.end_dt),
|
||||
ok_yn: r.ok_yn || 'N',
|
||||
rmks: r.rmks,
|
||||
|
||||
_new: r._new || false,
|
||||
_existing: r._existing || false,
|
||||
_deleted: r._deleted || false
|
||||
}))
|
||||
|
||||
fetch('/kngil/bbs/adm_service.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'save',
|
||||
member_id: ctx.memberId,
|
||||
buy_date: buyDate,
|
||||
items
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (res.status === 'success') {
|
||||
w2alert('저장되었습니다.')
|
||||
loadExistingPurchase(ctx.memberId, buyDate)
|
||||
} else {
|
||||
w2alert(res.message || '저장 실패')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeDate(val) {
|
||||
if (!val) return null
|
||||
|
||||
// 이미 YYYY-MM-DD면 그대로
|
||||
if (/^\d{4}-\d{2}-\d{2}$/.test(val)) {
|
||||
return val
|
||||
}
|
||||
|
||||
// MM/DD/YYYY → YYYY-MM-DD
|
||||
const d = new Date(val)
|
||||
if (isNaN(d)) return null
|
||||
|
||||
return d.toISOString().slice(0, 10)
|
||||
}
|
||||
|
||||
|
||||
function dateToYMD(val) {
|
||||
if (!val) return null
|
||||
|
||||
// Date 객체
|
||||
if (val instanceof Date) {
|
||||
return [
|
||||
val.getFullYear(),
|
||||
String(val.getMonth() + 1).padStart(2, '0'),
|
||||
String(val.getDate()).padStart(2, '0')
|
||||
].join('-')
|
||||
}
|
||||
|
||||
// 문자열 (MM/DD/YYYY or YYYY-MM-DD)
|
||||
if (typeof val === 'string') {
|
||||
|
||||
// 이미 YYYY-MM-DD
|
||||
if (/^\d{4}-\d{2}-\d{2}$/.test(val)) {
|
||||
return val
|
||||
}
|
||||
|
||||
// MM/DD/YYYY
|
||||
const d = new Date(val)
|
||||
if (!isNaN(d)) {
|
||||
return [
|
||||
d.getFullYear(),
|
||||
String(d.getMonth() + 1).padStart(2, '0'),
|
||||
String(d.getDate()).padStart(2, '0')
|
||||
].join('-')
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
import { w2grid, w2ui, w2popup, w2alert } from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js'
|
||||
// 파일이 실제 존재하는지 확인 필수! 존재하지 않으면 아래 코드가 모두 멈춥니다.
|
||||
import { bindProductPopupEvents } from '/kngil/js/adm_common.js'
|
||||
|
||||
|
||||
|
||||
export function openuseHistoryPopup(memberId = '',isSuperAdmin='') {
|
||||
// 기존 그리드 안전하게 제거
|
||||
if (w2ui.UseHistoryGrid) {
|
||||
w2ui.UseHistoryGrid.destroy();
|
||||
}
|
||||
|
||||
w2popup.open({
|
||||
title: '서비스 사용 이력',
|
||||
width: 1100,
|
||||
height: 600,
|
||||
modal: true,
|
||||
body:
|
||||
/*
|
||||
`
|
||||
<div style="padding:8px">
|
||||
<div id="UseHistoryGrid" style="height:520px;"></div>
|
||||
</div>
|
||||
*/
|
||||
`
|
||||
<div id="popupMainContainer" style="display: flex; flex-direction: column; height: 100%; padding: 10px; gap: 10px; box-sizing: border-box;">
|
||||
|
||||
<div id="searchFormArea" style="display: flex; align-items: center; gap: 20px; padding: 15px; background: #f9f9f9; border: 1px solid #ddd; border-radius: 4px;">
|
||||
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<span style="font-weight: bold; color: #333; white-space: nowrap;">회원 ID</span>
|
||||
<input type="text" id="searchMemberId" value="${memberId}"
|
||||
${!isSuperAdmin ? 'disabled' : ''}
|
||||
style="width: 120px; padding: 6px; border: 1px solid #ccc; border-radius: 4px;"
|
||||
placeholder="아이디">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<span style="font-weight: bold; color: #333; white-space: nowrap;">성명</span>
|
||||
<input type="text" id="searchUserNm"
|
||||
style="width: 120px; padding: 6px; border: 1px solid #ccc; border-radius: 4px;"
|
||||
placeholder="성명 입력">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<span style="font-weight: bold; color: #333; white-space: nowrap;">부서</span>
|
||||
<input type="text" id="searchDeptNm"
|
||||
style="width: 150px; padding: 6px; border: 1px solid #ccc; border-radius: 4px;"
|
||||
placeholder="부서명 입력">
|
||||
</div>
|
||||
|
||||
<button id="btnSearchHistory"
|
||||
style="padding: 6px 20px; background: #1565c0; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; margin-left: auto;">
|
||||
검색
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="UseHistoryGrid" style="flex: 1; min-height: 450px; border: 1px solid #ddd;"></div>
|
||||
</div>
|
||||
|
||||
`,
|
||||
onOpen(event) {
|
||||
event.onComplete = () => {
|
||||
const searchBtn = document.getElementById('btnSearchHistory');
|
||||
const searchInput = document.getElementById('searchMemberId');
|
||||
const inputUnm = document.getElementById('searchUserNm');
|
||||
const inputDnm = document.getElementById('searchDeptNm');
|
||||
|
||||
// 조회 버튼 클릭 시 동작
|
||||
if (searchBtn) {
|
||||
searchBtn.onclick = () => {
|
||||
loadUseHistoryData(searchInput.value,inputUnm,inputDnm);
|
||||
};
|
||||
}
|
||||
|
||||
// 엔터키 지원
|
||||
if (searchInput,inputUnm,inputDnm) {
|
||||
searchInput.onkeydown = (e) => {
|
||||
if (e.key === 'Enter') searchBtn.click();
|
||||
};
|
||||
}
|
||||
|
||||
createUseHistoryGrid(memberId);
|
||||
loadUseHistoryData(memberId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createUseHistoryGrid(memberId) {
|
||||
new w2grid({
|
||||
name: 'UseHistoryGrid',
|
||||
box: '#UseHistoryGrid',
|
||||
show: {
|
||||
//toolbar: true,
|
||||
footer: true,
|
||||
lineNumbers: true // 행 번호를 표시하면 디버깅이 편합니다.
|
||||
},
|
||||
columns: [
|
||||
// field 이름이 PHP에서 내려주는 JSON 키값과 정확히 일치해야 함!
|
||||
{ field: 'member_id', text: '회원ID', size: '100px',style: 'text-align: center', attr: 'align=center',hidden: true }, // name 아님!
|
||||
{ field: 'use_dt', text: '사용일자', size: '100px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'user_id', text: '사용자ID', size: '100px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'sq_no', text: '순번', size: '100px',style: 'text-align: center', attr: 'align=center' ,hidden: true}, // name 아님!
|
||||
{ field: 'user_nm', text: '성명', size: '100px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'dept_nm', text: '부서', size: '100px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'posit_nm', text: '직위', size: '100px',style: 'text-align: center', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'use_yn', text: '사용여부', size: '80px', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'use_area', text: '사용면적', size: '100px',render: 'number:0' , attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
{ field: 'ser_bc', text: '서비스구분', size: '150px', attr: 'align=center' ,sortable: true}, // name 아님!
|
||||
|
||||
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async function loadUseHistoryData(memberId = ''){
|
||||
try {
|
||||
const grid = w2ui.UseHistoryGrid;
|
||||
if (!grid) return;
|
||||
|
||||
// DOM에서 현재 입력된 값을 실시간으로 읽어옴
|
||||
const sMid = document.getElementById('searchMemberId')?.value || '';
|
||||
const sUnm = document.getElementById('searchUserNm')?.value || '';
|
||||
const sDnm = document.getElementById('searchDeptNm')?.value || '';
|
||||
|
||||
grid.lock('조회 중...', true);
|
||||
|
||||
const searchParams = new URLSearchParams();
|
||||
searchParams.append('member_id', sMid);
|
||||
searchParams.append('user_nm', sUnm);
|
||||
searchParams.append('dept_nm', sDnm);
|
||||
|
||||
const response = await fetch('/kngil/bbs/adm_use_history.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: searchParams
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error(`서버 응답 오류: ${response.status}`);
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!Array.isArray(data)) {
|
||||
throw new Error('응답 데이터 형식 오류');
|
||||
}
|
||||
|
||||
grid.clear();
|
||||
grid.add(data);
|
||||
grid.unlock();
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (w2ui.UseHistoryGrid) w2ui.UseHistoryGrid.unlock();
|
||||
w2alert('사용이력 조회 실패: ' + e.message);
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
+4289
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,256 @@
|
||||
window.onload = function() {
|
||||
$.ajax({
|
||||
url: "some_api_endpoint",
|
||||
success: function(response) {
|
||||
},
|
||||
complete: function() {
|
||||
|
||||
// 팝업 닫기버튼
|
||||
$(document).ready(function() {
|
||||
$('.btn_close').click(function() {
|
||||
$('.popup_wrap').hide();
|
||||
$('body').css('overflow', ''); // 기본 스크롤 상태로 복귀
|
||||
lenis.start();
|
||||
console.log('lenis 재시작')
|
||||
});
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$('.btn_map_close').click(function() {
|
||||
$('.popup_sitemap').hide();
|
||||
$('body').css('overflow', ''); // 기본 스크롤 상태로 복귀
|
||||
lenis.start();
|
||||
console.log('lenis 재시작')
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 이메일 직접입력
|
||||
$(document).ready(function() {
|
||||
$('#domain-list').change(function() {
|
||||
if ($(this).val() === 'type') {
|
||||
$('#custom-domain').show().focus();
|
||||
} else {
|
||||
$('#custom-domain').hide().val('');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 인증번호 타이머
|
||||
$(document).ready(function() {
|
||||
// 인증번호 버튼 클릭 시
|
||||
$('.cert_number').click(function() {
|
||||
$('.code').show();
|
||||
});
|
||||
|
||||
// 확인 버튼 클릭 시
|
||||
$('.check').click(function() {
|
||||
$(this).hide();
|
||||
$('.check.complete').show();
|
||||
clearInterval(interval); // 타이머 멈춤
|
||||
$('.timer').remove(); // 타이머 요소 삭제
|
||||
});
|
||||
|
||||
// 타이머 함수
|
||||
var interval;
|
||||
function startTimer(duration, display) {
|
||||
clearInterval(interval);
|
||||
var timer = duration, minutes, seconds;
|
||||
|
||||
function updateTimer() {
|
||||
minutes = parseInt(timer / 60, 10);
|
||||
seconds = parseInt(timer % 60, 10);
|
||||
|
||||
minutes = minutes < 10 ? "0" + minutes : minutes;
|
||||
seconds = seconds < 10 ? "0" + seconds : seconds;
|
||||
|
||||
display.text(minutes + ":" + seconds);
|
||||
|
||||
if (--timer < 0) {
|
||||
clearInterval(interval);
|
||||
display.text("00:00");
|
||||
}
|
||||
}
|
||||
|
||||
updateTimer();
|
||||
interval = setInterval(updateTimer, 1000);
|
||||
}
|
||||
|
||||
var threeMinutes = 60 * 3,
|
||||
display = $('.timer');
|
||||
|
||||
startTimer(threeMinutes, display);
|
||||
|
||||
$('.cert_number').click(function() {
|
||||
startTimer(threeMinutes, display);
|
||||
});
|
||||
});
|
||||
|
||||
// 아이디찾기
|
||||
$(document).ready(function(){
|
||||
$('.find_email').click(function(){
|
||||
$('.find_ph').removeClass('on').prop('checked', false);
|
||||
$(this).addClass('on').prop('checked', true);
|
||||
$('.ph').hide();
|
||||
$('.email').show();
|
||||
});
|
||||
|
||||
$('.find_ph').click(function(){
|
||||
$('.find_email').removeClass('on').prop('checked', false);
|
||||
$(this).addClass('on').prop('checked', true);
|
||||
$('.email').hide();
|
||||
$('.ph').show();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.btn_id').on('click', function() {
|
||||
$('.btn_id').addClass('on');
|
||||
$('.btn_pw').removeClass('on');
|
||||
$('.content.id').show();
|
||||
$('.content.pw').hide();
|
||||
});
|
||||
|
||||
$('.btn_pw').on('click', function() {
|
||||
$('.btn_pw').addClass('on');
|
||||
$('.btn_id').removeClass('on');
|
||||
$('.content.pw').show();
|
||||
$('.content.id').hide();
|
||||
});
|
||||
|
||||
$('#domain-list').on('change', function() {
|
||||
if ($(this).val() === 'type') {
|
||||
$('#custom-domain').show();
|
||||
} else {
|
||||
$('#custom-domain').hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 전체약관동의
|
||||
// $(document).ready(function() {
|
||||
// function toggleJoinButton() {
|
||||
// // 모든 개별 체크박스가 체크되었는지 확인
|
||||
// var allChecked = $('.terms_wrap input[type="checkbox"]').length === $('.terms_wrap input[type="checkbox"]:checked').length;
|
||||
|
||||
// // '약관에 모두 동의합니다' 체크박스 상태에 따라 조정
|
||||
// $('.checkbox_wrap.all input[type="checkbox"]').prop('checked', allChecked);
|
||||
|
||||
// // 모든 체크박스가 체크되지 않은 경우 버튼에 'none' 클래스 추가하고 disabled 속성 추가
|
||||
// if (allChecked) {
|
||||
// $('.join_btn_wrap').removeClass('none');
|
||||
// $('.join_btn_wrap button').prop('disabled', false);
|
||||
// } else {
|
||||
// $('.join_btn_wrap').addClass('none');
|
||||
// $('.join_btn_wrap button').prop('disabled', true);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // '약관에 모두 동의합니다' 체크박스의 변경 이벤트
|
||||
// $('.checkbox_wrap.all input[type="checkbox"]').on('change', function() {
|
||||
// var isChecked = $(this).is(':checked');
|
||||
// $('.terms_wrap input[type="checkbox"]').prop('checked', isChecked);
|
||||
// toggleJoinButton(); // 버튼 상태 업데이트
|
||||
// });
|
||||
|
||||
// // 각 terms_wrap의 개별 체크박스 변경 이벤트
|
||||
// $('.terms_wrap input[type="checkbox"]').on('change', function() {
|
||||
// toggleJoinButton(); // 버튼 상태 업데이트
|
||||
// });
|
||||
|
||||
// // 초기 상태 설정
|
||||
// toggleJoinButton();
|
||||
// });
|
||||
|
||||
// 전체약관동의 수정 250813
|
||||
(function ($) {
|
||||
if (window.__agreeBound) return; // 중복 바인딩 방지
|
||||
window.__agreeBound = true;
|
||||
|
||||
const $container = $('#pop_agreement');
|
||||
const $items = $container.find('.terms_wrap input[type="checkbox"]'); // agree11, agree21
|
||||
const $all = $container.find('.checkbox_wrap.all input[type="checkbox"]');
|
||||
const $btn = $container.find('#btn_agree');
|
||||
|
||||
function syncAll() {
|
||||
const allChecked = $items.length > 0 && $items.filter(':checked').length === $items.length;
|
||||
$all.prop('checked', allChecked);
|
||||
// 버튼은 disable 하지 않음 (스타일만 조정하고 싶다면 클래스만 토글)
|
||||
// $('.join_btn_wrap').toggleClass('none', !allChecked); <-- 필요 없으면 제거
|
||||
}
|
||||
|
||||
// 전체동의 → 개별
|
||||
$all.on('change', function () {
|
||||
const on = $(this).is(':checked');
|
||||
$items.prop('checked', on);
|
||||
syncAll();
|
||||
});
|
||||
|
||||
// 개별 → 전체동의 동기화
|
||||
$items.on('change', syncAll);
|
||||
|
||||
// 동의 버튼 클릭 시에만 검사
|
||||
$btn.off('click.agree').on('click.agree', function (e) {
|
||||
e.preventDefault();
|
||||
const allChecked = $items.filter(':checked').length === $items.length;
|
||||
if (!allChecked) {
|
||||
alert('약관에 모두 동의해주세요.');
|
||||
return false;
|
||||
}
|
||||
// 통과 시 다음 단계로 진행(필요 시 주석 해제)
|
||||
// $('#pop_agreement').hide();
|
||||
// $('#pop_register_form').show();
|
||||
// $('body').css('overflow','hidden');
|
||||
});
|
||||
|
||||
// 외부에서 팝업 열 때 상태 초기화가 필요하면 이 함수 호출
|
||||
window.resetAgreementUI = function () {
|
||||
$items.prop('checked', false);
|
||||
$all.prop('checked', false);
|
||||
syncAll();
|
||||
// 버튼은 항상 활성
|
||||
$('#btn_agree, #fregister button[type=submit]')
|
||||
.prop('disabled', false)
|
||||
.css('pointer-events', 'auto');
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
|
||||
// 가입완료
|
||||
$(document).ready(function() {
|
||||
$('.join.completion .join_btn_wrap button').click(function() {
|
||||
$('.pop_input_wrap form').children().not('.messages').hide();
|
||||
$('.messages').show();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.join.completion .join_btn_wrap button').click(function() {
|
||||
$('.pop_input_wrap form').children().not('.messages').hide();
|
||||
$('.messages').show();
|
||||
|
||||
// 세 번째 단계에 'on' 클래스 추가하고, 다른 단계에서 'on' 클래스 제거
|
||||
$('.join_progress .join_step').removeClass('on');
|
||||
$('.join_progress .join_step').eq(2).addClass('on');
|
||||
});
|
||||
});
|
||||
|
||||
// 개인정보 보호정책 스크립트
|
||||
$(document).ready(function() {
|
||||
$('.tab_privacy').on('click', function() {
|
||||
$(this).addClass('on');
|
||||
$('.tab_agreement').removeClass('on');
|
||||
$('.content.pri').addClass('show').removeClass('hide');
|
||||
$('.content.agr').removeClass('show').addClass('hide');
|
||||
});
|
||||
$('.tab_agreement').on('click', function() {
|
||||
$(this).addClass('on');
|
||||
$('.tab_privacy').removeClass('on');
|
||||
$('.content.agr').addClass('show').removeClass('hide');
|
||||
$('.content.pri').removeClass('show').addClass('hide');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */
|
||||
!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|Line truncated
|
||||
}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&U.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var Y=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)Y(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFraLine truncated
|
||||
marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},gb.propHooks.scrollTop=gb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:hb||lb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]Line truncated
|
||||
padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return Y(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n});
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */
|
||||
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=y.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:v}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,y,s,c,v,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),j=function(e,t){return e===t&&(l=!0),0},D={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^Line truncated
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
/*! jQuery Migrate v1.4.1 | (c) jQuery Foundation and other contributors | jquery.org/license */
|
||||
"undefined"==typeof jQuery.migrateMute&&(jQuery.migrateMute=!0),function(a,b,c){function d(c){var d=b.console;f[c]||(f[c]=!0,a.migrateWarnings.push(c),d&&d.warn&&!a.migrateMute&&(d.warn("JQMIGRATE: "+c),a.migrateTrace&&d.trace&&d.trace()))}function e(b,c,e,f){if(Object.defineProperty)try{return void Object.defineProperty(b,c,{configurable:!0,enumerable:!0,get:function(){return d(f),e},set:function(a){d(f),e=a}})}catch(g){}a._definePropertyBroken=!0,b[c]=e}a.migrateVersion="1.4.1";var f={};a.migrateWarnings=[],b.console&&b.console.log&&b.console.log("JQMIGRATE: Migrate is installed"+(a.migrateMute?"":" with logging active")+", version "+a.migrateVersion),a.migrateTrace===c&&(a.migrateTrace=!0),a.migrateReset=function(){f={},a.migrateWarnings.length=0},"BackCompat"===document.compatMode&&d("jQuery is not compatible with Quirks Mode");var g=a("<input/>",{size:1}).attr("size")&&a.attrFn,h=a.attr,i=a.attrHooks.value&&a.attrHooks.value.get||function(){return null},j=a.attrHooks.value&&a.attrHooks.value.set||function(){return c},k=/^(?:input|button)$/i,l=/^[238]$/,m=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,n=/^(?:checked|selected)$/i;e(a,"attrFn",g||{},"jQuery.attrFn is deprecated"),a.attr=function(b,e,f,i){var j=e.toLowerCase(),o=b&&b.nodeType;return i&&(h.length<4&&d("jQuery.fn.attr( props, pass ) is deprecated"),b&&!l.test(o)&&(g?e in g:a.isFunction(a.fn[e])))?a(b)[e](f):("type"===e&&f!==c&&k.test(b.nodeName)&&b.parentNode&&d("Can't change the 'type' of an input or button in IE 6/7/8"),!a.attrHooks[j]&&m.test(j)&&(a.attrHooks[j]={get:function(b,d){var e,f=a.prop(b,d);return f===!0||"boolean"!=typeof f&&(e=b.getAttributeNode(d))&&e.nodeValue!==!1?d.toLowerCase():c},set:function(b,c,d){var e;return c===!1?a.removeAttr(b,d):(e=a.propFix[d]||d,e in b&&(b[e]=!0),b.setAttribute(d,d.toLowerCase())),d}},n.test(j)&&d("jQuery.fn.attr('"+j+"') might use property instead of attribute")),h.call(a,b,e,f))},a.attrHooks.value={get:function(a,b){var c=(a.nodeName||"").toLowerCase();return"button"===c?i.apply(this,arguments):("input"!==c&&"option"!==c&&d("jQuery.fn.attr('value') no longer gets properties"),b in a?a.value:null)},set:function(a,b){var c=(a.nodeName||"").toLowerCase();return"button"===c?j.apply(this,arguments):("input"!==c&&"option"!==c&&d("jQuery.fn.attr('value', val) no longer sets properties"),void(a.value=b))}};var o,p,q=a.fn.init,r=a.find,s=a.parseJSON,t=/^\s*</,u=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,v=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g,w=/^([^<]*)(<[\w\W]+>)([^>]*)$/;a.fn.init=function(b,e,f){var g,h;return b&&"string"==typeof b&&!a.isPlainObject(e)&&(g=w.exec(a.trim(b)))&&g[0]&&(t.test(b)||d("$(html) HTML strings must start with '<' character"),g[3]&&d("$(html) HTML text after last tag is ignored"),"#"===g[0].charAt(0)&&(d("HTML string cannot start with a '#' character"),a.error("JQMIGRATE: Invalid selector string (XSS)")),e&&e.context&&e.context.nodeType&&(e=e.context),a.parseHTML)?q.call(this,a.parseHTML(g[2],e&&e.ownerDocument||e||document,!0),e,f):(h=q.apply(this,arguments),b&&b.selector!==c?(h.selector=b.selector,h.context=b.context):(h.selector="string"==typeof b?b:"",b&&(h.context=b.nodeType?b:e||document)),h)},a.fn.init.prototype=a.fn,a.find=function(a){var b=Array.prototype.slice.call(arguments);if("string"==typeof a&&u.test(a))try{document.querySelector(a)}catch(c){a=a.replace(v,function(a,b,c,d){return"["+b+c+'"'+d+'"]'});try{document.querySelector(a),d("Attribute selector with '#' must be quoted: "+b[0]),b[0]=a}catch(e){d("Attribute selector with '#' was not fixed: "+b[0])}}return r.apply(this,b)};var x;for(x in r)Object.prototype.hasOwnProperty.call(r,x)&&(a.find[x]=r[x]);a.parseJSON=function(a){return a?s.apply(this,arguments):(d("jQuery.parseJSON requires a valid JSON string"),null)},a.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a.browser||(o=a.uaMatch(navigator.userAgent),p={},o.browser&&(p[o.browser]=!0,p.version=o.version),p.chrome?p.webkit=!0:p.webkit&&(p.safari=!0),a.browser=p),e(a,"browser",a.browser,"jQuery.browser is deprecated"),a.boxModel=a.support.boxModel="CSS1Compat"===document.compatMode,e(a,"boxModel",a.boxModel,"jQuery.boxModel is deprecated"),e(a.support,"boxModel",a.support.boxModel,"jQuery.support.boxModel is deprecated"),a.sub=function(){function b(a,c){return new b.fn.init(a,c)}a.extend(!0,b,this),b.superclass=this,b.fn=b.prototype=this(),b.fn.constructor=b,b.sub=this.sub,b.fn.init=function(d,e){var f=a.fn.init.call(this,d,e,c);return f instanceof b?f:b(f)},b.fn.init.prototype=b.fn;var c=b(document);return d("jQuery.sub() is deprecated"),b},a.fn.size=function(){return d("jQuery.fn.size() is deprecatLine truncated
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,109 @@
|
||||
$(function(){
|
||||
var hide_menu = false;
|
||||
var mouse_event = false;
|
||||
var oldX = oldY = 0;
|
||||
|
||||
$(document).mousemove(function(e) {
|
||||
if(oldX == 0) {
|
||||
oldX = e.pageX;
|
||||
oldY = e.pageY;
|
||||
}
|
||||
|
||||
if(oldX != e.pageX || oldY != e.pageY) {
|
||||
mouse_event = true;
|
||||
}
|
||||
});
|
||||
|
||||
// 주메뉴
|
||||
var $gnb = $(".gnb_1dli > a");
|
||||
$gnb.mouseover(function() {
|
||||
if(mouse_event) {
|
||||
$("#hd").addClass("hd_zindex");
|
||||
$(".gnb_1dli").removeClass("gnb_1dli_over gnb_1dli_over2 gnb_1dli_on");
|
||||
$(this).parent().addClass("gnb_1dli_over gnb_1dli_on");
|
||||
menu_rearrange($(this).parent());
|
||||
hide_menu = false;
|
||||
}
|
||||
});
|
||||
|
||||
$gnb.mouseout(function() {
|
||||
hide_menu = true;
|
||||
});
|
||||
|
||||
$(".gnb_2dli").mouseover(function() {
|
||||
hide_menu = false;
|
||||
});
|
||||
|
||||
$(".gnb_2dli").mouseout(function() {
|
||||
hide_menu = true;
|
||||
});
|
||||
|
||||
$gnb.focusin(function() {
|
||||
$("#hd").addClass("hd_zindex");
|
||||
$(".gnb_1dli").removeClass("gnb_1dli_over gnb_1dli_over2 gnb_1dli_on");
|
||||
$(this).parent().addClass("gnb_1dli_over gnb_1dli_on");
|
||||
menu_rearrange($(this).parent());
|
||||
hide_menu = false;
|
||||
});
|
||||
|
||||
$gnb.focusout(function() {
|
||||
hide_menu = true;
|
||||
});
|
||||
|
||||
$(".gnb_2da").focusin(function() {
|
||||
$(".gnb_1dli").removeClass("gnb_1dli_over gnb_1dli_over2 gnb_1dli_on");
|
||||
var $gnb_li = $(this).closest(".gnb_1dli").addClass("gnb_1dli_over gnb_1dli_on");
|
||||
menu_rearrange($(this).closest(".gnb_1dli"));
|
||||
hide_menu = false;
|
||||
});
|
||||
|
||||
$(".gnb_2da").focusout(function() {
|
||||
hide_menu = true;
|
||||
});
|
||||
|
||||
$('#gnb_1dul>li').bind('mouseleave',function(){
|
||||
submenu_hide();
|
||||
});
|
||||
|
||||
$(document).bind('click focusin',function(){
|
||||
if(hide_menu) {
|
||||
submenu_hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function submenu_hide() {
|
||||
$("#hd").removeClass("hd_zindex");
|
||||
$(".gnb_1dli").removeClass("gnb_1dli_over gnb_1dli_over2 gnb_1dli_on");
|
||||
}
|
||||
|
||||
function menu_rearrange(el)
|
||||
{
|
||||
var width = $("#gnb_1dul").width();
|
||||
var left = w1 = w2 = 0;
|
||||
var idx = $(".gnb_1dli").index(el);
|
||||
var max_menu_count = 0;
|
||||
var $gnb_1dli;
|
||||
|
||||
for(i=0; i<=idx; i++) {
|
||||
$gnb_1dli = $(".gnb_1dli:eq("+i+")");
|
||||
w1 = $gnb_1dli.outerWidth();
|
||||
|
||||
if($gnb_1dli.find(".gnb_2dul").length)
|
||||
w2 = $gnb_1dli.find(".gnb_2dli > a").outerWidth(true);
|
||||
else
|
||||
w2 = w1;
|
||||
|
||||
if((left + w2) > width) {
|
||||
if(max_menu_count == 0)
|
||||
max_menu_count = i + 1;
|
||||
}
|
||||
|
||||
if(max_menu_count > 0 && (idx + 1) % max_menu_count == 0) {
|
||||
el.removeClass("gnb_1dli_over").addClass("gnb_1dli_over2");
|
||||
left = 0;
|
||||
} else {
|
||||
left += w1;
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* jQuery Mousewheel 3.1.13
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
*/
|
||||
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?module.exports=e:e(jQuery)}(function(a){var u,r,e=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],t="onwheel"in window.document||9<=window.document.documentMode?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],f=Array.prototype.slice;if(a.event.fixHooks)for(var n=e.length;n;)a.event.fixHooks[e[--n]]=a.event.mouseHooks;var d=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var e=t.length;e;)this.addEventListener(t[--e],i,!1);else this.onmousewheel=i;a.data(this,"mousewheel-line-height",d.getLineHeight(this)),a.data(this,"mousewheel-page-height",d.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var e=t.length;e;)this.removeEventListener(t[--e],i,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(e){var t=a(e),e=t["offsetParent"in a.fn?"offsetParent":"parent"]();return e.length||(e=a("body")),parseInt(e.css("fontSize"),10)||parseInt(t.css("fontSize"),10)||16},getPageHeight:function(e){return a(e).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};function i(e){var t,n=e||window.event,i=f.call(arguments,1),o=0,l=0,s=0,h=0;if((e=a.event.fix(n)).type="mousewheel","detail"in n&&(s=-1*n.detail),"wheelDelta"in n&&(s=n.wheelDelta),"wheelDeltaY"in n&&(s=n.wheelDeltaY),"wheelDeltaX"in n&&(l=-1*n.wheelDeltaX),"axis"in n&&n.axis===n.HORIZONTAL_AXIS&&(l=-1*s,s=0),o=0===s?l:s,"deltaY"in n&&(o=s=-1*n.deltaY),"deltaX"in n&&(l=n.deltaX,0===s&&(o=-1*l)),0!==s||0!==l)return 1===n.deltaMode?(o*=t=a.data(this,"mousewheel-line-height"),s*=t,l*=t):2===n.deltaMode&&(o*=t=a.data(this,"mousewheel-page-height"),s*=t,l*=t),h=Math.max(Math.abs(s),Math.abs(l)),(!r||h<r)&&c(n,r=h)&&(r/=40),c(n,h)&&(o/=40,l/=40,s/=40),o=Math[1<=o?"floor":"ceil"](o/r),l=Math[1<=l?"floor":"ceil"](l/r),s=Math[1<=s?"floor":"ceil"](s/r),d.settings.normalizeOffset&&this.getBoundingClientRect&&(h=this.getBoundingClientRect(),e.offsetX=e.clientX-h.left,e.offsetY=e.clientY-h.top),e.deltaX=l,e.deltaY=s,e.deltaFactor=r,e.deltaMode=0,i.unshift(e,o,l,s),u&&window.clearTimeout(u),u=window.setTimeout(w,200),(a.event.dispatch||a.event.handle).apply(this,i)}function w(){r=null}function c(e,t){return d.settings.adjustOldDeltas&&"mousewheel"===e.type&&t%120==0}a.fn.extend({mousewheel:function(e){return e?this.on("mousewheel",e):this.trigger("mousewheel")},unmousewheel:function(e){return this.off("mousewheel",e)}})});
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Owl Carousel v2.3.4
|
||||
* Copyright 2013-2018 David Deutsch
|
||||
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
|
||||
*/
|
||||
!function(a,b,c,d){function e(b,c){this.settings=null,this.options=a.extend({},e.Defaults,c),this.$element=a(b),this._handlers={},this._plugins={},this._supress={},this._current=null,this._speed=null,this._coordinates=[],this._breakpoint=null,this._width=null,this._items=[],this._clones=[],this._mergers=[],this._widths=[],this._invalidated={},this._pipe=[],this._drag={time:null,target:null,pointer:null,stage:{start:null,current:null},direction:null},this._states={current:{},tags:{initializing:["busy"],animating:["busy"],dragging:["interacting"]}},a.each(["onResize","onThrottledResize"],a.proxy(function(b,c){this._handlers[c]=a.proxy(this[c],this)},this)),a.each(e.Plugins,a.proxy(function(a,b){this._plugins[a.charAt(0).toLowerCase()+a.slice(1)]=new b(this)},this)),a.each(e.Workers,a.proxy(function(b,c){this._pipe.push({filter:c.filter,run:a.proxy(c.run,this)})},this)),this.setup(),this.initialize()}e.Defaults={items:3,loop:!1,center:!1,rewind:!1,checkVisibility:!0,mouseDrag:!0,touchDrag:!0,pullDrag:!0,freeDrag:!1,margin:0,stagePadding:0,merge:!1,mergeFit:!0,autoWidth:!1,startPosition:0,rtl:!1,smartSpeed:250,fluidSpeed:!1,dragEndSpeed:!1,responsive:{},responsiveRefreshRate:200,responsiveBaseElement:b,fallbackEasing:"swing",slideTransition:"",info:!1,nestedItemSelector:!1,itemElement:"div",stageElement:"div",refreshClass:"owl-refresh",loadedClass:"owl-loaded",loadingClass:"owl-loading",rtlClass:"owl-rtl",responsiveClass:"owl-responsive",dragClass:"owl-drag",itemClass:"owl-item",stageClass:"owl-stage",stageOuterClass:"owl-stage-outer",grabClass:"owl-grab"},e.Width={Default:"default",Inner:"inner",Outer:"outer"},e.Type={Event:"event",State:"state"},e.Plugins={},e.Workers=[{filter:["width","settings"],run:function(){this._width=this.$element.width()}},{filter:["width","items","settings"],run:function(a){a.current=this._items&&this._items[this.relative(this._current)]}},{filter:["items","settings"],run:function(){this.$stage.children(".cloned").remove()}},{filter:["width","items","settings"],run:function(a){var b=this.settings.margin||"",c=!this.settings.autoWidth,d=this.settings.rtl,e={width:"auto","margin-left":d?b:"","margin-right":d?"":b};!c&&this.$stage.children().css(e),a.css=e}},{filter:["width","items","settings"],run:function(a){var b=(this.width()/this.settings.items).toFixed(3)-this.settings.margin,c=null,d=this._items.length,e=!this.settings.autoWidth,f=[];for(a.items={merge:!1,width:b};d--;)c=this._mergers[d],c=this.settings.mergeFit&&Math.min(c,this.settings.items)||c,a.items.merge=c>1||a.items.merge,f[d]=e?b*c:this._items[d].width();this._widths=f}},{filter:["items","settings"],run:function(){var b=[],c=this._items,d=this.settings,e=Math.max(2*d.items,4),f=2*Math.ceil(c.length/2),g=d.loop&&c.length?d.rewind?e:Math.max(e,f):0,h="",i="";for(g/=2;g>0;)b.push(this.normalize(b.length/2,!0)),h+=c[b[b.length-1]][0].outerHTML,b.push(this.normalize(c.length-1-(b.length-1)/2,!0)),i=c[b[b.length-1]][0].outerHTML+i,g-=1;this._clones=b,a(h).addClass("cloned").appendTo(this.$stage),a(i).addClass("cloned").prependTo(this.$stage)}},{filter:["width","items","settings"],run:function(){for(var a=this.settings.rtl?1:-1,b=this._clones.length+this._items.length,c=-1,d=0,e=0,f=[];++c<b;)d=f[c-1]||0,e=this._widths[this.relative(c)]+this.settings.margin,f.push(d+e*a);this._coordinates=f}},{filter:["width","items","settings"],run:function(){var a=this.settings.stagePadding,b=this._coordinates,c={width:Math.ceil(Math.abs(b[b.length-1]))+2*a,"padding-left":a||"","padding-right":a||""};this.$stage.css(c)}},{filter:["width","items","settings"],run:function(a){var b=this._coordinates.length,c=!this.settings.autoWidth,d=this.$stage.children();if(c&&a.items.merge)for(;b--;)a.css.width=this._widths[this.relative(b)],d.eq(b).css(a.css);else c&&(a.css.width=a.items.width,d.css(a.css))}},{filter:["items"],run:function(){this._coordinates.length<1&&this.$stage.removeAttr("style")}},{filter:["width","items","settings"],run:function(a){a.current=a.current?this.$stage.children().index(a.current):0,a.current=Math.max(this.minimum(),Math.min(this.maximum(),a.current)),this.reset(a.current)}},{filter:["position"],run:function(){this.animate(this.coordinates(this._current))}},{filter:["width","position","items","settings"],run:function(){var a,b,c,d,e=this.settings.rtl?1:-1,f=2*this.settings.stagePadding,g=this.coordinates(this.current())+f,h=g+this.width()*e,i=[];for(c=0,d=this._coordinates.length;c<d;c++)a=this._coordinates[c-1]||0,b=Math.abs(this._coordinates[c])+f*e,(this.op(a,"<=",g)&&this.op(a,">",h)||this.op(b,"<",g)&&this.op(b,">",h))&&i.push(c);this.$stage.children(".active").removeClass("active"),this.$stage.children(":eq("+i.join("), :eq(")+")").addClass("active"),this.$stage.children(".center").removeClass("center"),this.settings.center&&this.$stage.children().eq(this.current()).addClass("center")}}],e.prototype.initializeStage=function(){this.$stage=this.$element.find("."+this.settings.stageClass),this.$stage.length||(this.$elemeLine truncated
|
||||
animateIn:!1},e.prototype.swap=function(){if(1===this.core.settings.items&&a.support.animation&&a.support.transition){this.core.speed(0);var b,c=a.proxy(this.clear,this),d=this.core.$stage.children().eq(this.previous),e=this.core.$stage.children().eq(this.next),f=this.core.settings.animateIn,g=this.core.settings.animateOut;this.core.current()!==this.previous&&(g&&(b=this.core.coordinates(this.previous)-this.core.coordinates(this.next),d.one(a.support.animation.end,c).css({left:b+"px"}).addClass("animated owl-animated-out").addClass(g)),f&&e.one(a.support.animation.end,c).addClass("animated owl-animated-in").addClass(f))}},e.prototype.clear=function(b){a(b.target).css({left:""}).removeClass("animated owl-animated-out owl-animated-in").removeClass(this.core.settings.animateIn).removeClass(this.core.settings.animateOut),this.core.onTransitionEnd()},e.prototype.destroy=function(){var a,b;for(a in this.handlers)this.core.$element.off(a,this.handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.Animate=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){var e=function(b){this._core=b,this._call=null,this._time=0,this._timeout=0,this._paused=!0,this._handlers={"changed.owl.carousel":a.proxy(function(a){a.namespace&&"settings"===a.property.name?this._core.settings.autoplay?this.play():this.stop():a.namespace&&"position"===a.property.name&&this._paused&&(this._time=0)},this),"initialized.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.autoplay&&this.play()},this),"play.owl.autoplay":a.proxy(function(a,b,c){a.namespace&&this.play(b,c)},this),"stop.owl.autoplay":a.proxy(function(a){a.namespace&&this.stop()},this),"mouseover.owl.autoplay":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.pause()},this),"mouseleave.owl.autoplay":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.play()},this),"touchstart.owl.core":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.pause()},this),"touchend.owl.core":a.proxy(function(){this._core.settings.autoplayHoverPause&&this.play()},this)},this._core.$element.on(this._handlers),this._core.options=a.extend({},e.Defaults,this._core.options)};e.Defaults={autoplay:!1,autoplayTimeout:5e3,autoplayHoverPause:!1,autoplaySpeed:!1},e.prototype._next=function(d){this._call=b.setTimeout(a.proxy(this._next,this,d),this._timeout*(Math.round(this.read()/this._timeout)+1)-this.read()),this._core.is("interacting")||c.hidden||this._core.next(d||this._core.settings.autoplaySpeed)},e.prototype.read=function(){return(new Date).getTime()-this._time},e.prototype.play=function(c,d){var e;this._core.is("rotating")||this._core.enter("rotating"),c=c||this._core.settings.autoplayTimeout,e=Math.min(this._time%(this._timeout||c),c),this._paused?(this._time=this.read(),this._paused=!1):b.clearTimeout(this._call),this._time+=this.read()%c-e,this._timeout=c,this._call=b.setTimeout(a.proxy(this._next,this,d),c-e)},e.prototype.stop=function(){this._core.is("rotating")&&(this._time=0,this._paused=!0,b.clearTimeout(this._call),this._core.leave("rotating"))},e.prototype.pause=function(){this._core.is("rotating")&&!this._paused&&(this._time=this.read(),this._paused=!0,b.clearTimeout(this._call))},e.prototype.destroy=function(){var a,b;this.stop();for(a in this._handlers)this._core.$element.off(a,this._handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.autoplay=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){"use strict";var e=function(b){this._core=b,this._initialized=!1,this._pages=[],this._controls={},this._templates=[],this.$element=this._core.$element,this._overrides={next:this._core.next,prev:this._core.prev,to:this._core.to},this._handlers={"prepared.owl.carousel":a.proxy(function(b){b.namespace&&this._core.settings.dotsData&&this._templates.push('<div class="'+this._core.settings.dotClass+'">'+a(b.content).find("[data-dot]").addBack("[data-dot]").attr("data-dot")+"</div>")},this),"added.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.dotsData&&this._templates.splice(a.position,0,this._templates.pop())},this),"remove.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.dotsData&&this._templates.splice(a.position,1)},this),"changed.owl.carousel":a.proxy(function(a){a.namespace&&"position"==a.property.name&&this.draw()},this),"initialized.owl.carousel":a.proxy(function(a){a.namespace&&!this._initialized&&(this._core.trigger("initialize",null,"navigation"),this.initialize(),this.update(),this.draw(),this._initialized=!0,this._core.trigger("initialized",null,"navigation"))},this),"refreshed.owl.carousel":a.proxy(function(a){a.namespace&&this._initialized&&(this._core.trigger("refresh",null,"navigation"),this.update(),this.draw(),this._core.trigger("refreLine truncated
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Owl Carousel v2.3.4
|
||||
* Copyright 2013-2018 David Deutsch
|
||||
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
|
||||
*/
|
||||
/*
|
||||
* Owl Carousel - Core
|
||||
*/
|
||||
.owl-carousel {
|
||||
display: none;
|
||||
width: 100%;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
/* position relative and z-index fix webkit rendering fonts issue */
|
||||
position: relative;
|
||||
z-index: 1; }
|
||||
.owl-carousel .owl-stage {
|
||||
position: relative;
|
||||
-ms-touch-action: pan-Y;
|
||||
touch-action: manipulation;
|
||||
-moz-backface-visibility: hidden;
|
||||
/* fix firefox animation glitch */ }
|
||||
.owl-carousel .owl-stage:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
line-height: 0;
|
||||
height: 0; }
|
||||
.owl-carousel .owl-stage-outer {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* fix for flashing background */
|
||||
-webkit-transform: translate3d(0px, 0px, 0px); }
|
||||
.owl-carousel .owl-wrapper,
|
||||
.owl-carousel .owl-item {
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
-moz-transform: translate3d(0, 0, 0);
|
||||
-ms-transform: translate3d(0, 0, 0); }
|
||||
.owl-carousel .owl-item {
|
||||
position: relative;
|
||||
min-height: 1px;
|
||||
float: left;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-touch-callout: none; }
|
||||
.owl-carousel .owl-item img {
|
||||
display: block;
|
||||
width: 100%; }
|
||||
.owl-carousel .owl-nav.disabled,
|
||||
.owl-carousel .owl-dots.disabled {
|
||||
display: none; }
|
||||
.owl-carousel .owl-nav .owl-prev,
|
||||
.owl-carousel .owl-nav .owl-next,
|
||||
.owl-carousel .owl-dot {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none; }
|
||||
.owl-carousel .owl-nav button.owl-prev,
|
||||
.owl-carousel .owl-nav button.owl-next,
|
||||
.owl-carousel button.owl-dot {
|
||||
background: none;
|
||||
color: inherit;
|
||||
border: none;
|
||||
padding: 0 !important;
|
||||
font: inherit; }
|
||||
.owl-carousel.owl-loaded {
|
||||
display: block; }
|
||||
.owl-carousel.owl-loading {
|
||||
opacity: 0;
|
||||
display: block; }
|
||||
.owl-carousel.owl-hidden {
|
||||
opacity: 0; }
|
||||
.owl-carousel.owl-refresh .owl-item {
|
||||
visibility: hidden; }
|
||||
.owl-carousel.owl-drag .owl-item {
|
||||
-ms-touch-action: pan-y;
|
||||
touch-action: pan-y;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none; }
|
||||
.owl-carousel.owl-grab {
|
||||
cursor: move;
|
||||
cursor: grab; }
|
||||
.owl-carousel.owl-rtl {
|
||||
direction: rtl; }
|
||||
.owl-carousel.owl-rtl .owl-item {
|
||||
float: right; }
|
||||
|
||||
/* No Js */
|
||||
.no-js .owl-carousel {
|
||||
display: block; }
|
||||
|
||||
/*
|
||||
* Owl Carousel - Animate Plugin
|
||||
*/
|
||||
.owl-carousel .animated {
|
||||
animation-duration: 1000ms;
|
||||
animation-fill-mode: both; }
|
||||
|
||||
.owl-carousel .owl-animated-in {
|
||||
z-index: 0; }
|
||||
|
||||
.owl-carousel .owl-animated-out {
|
||||
z-index: 1; }
|
||||
|
||||
.owl-carousel .fadeOut {
|
||||
animation-name: fadeOut; }
|
||||
|
||||
@keyframes fadeOut {
|
||||
0% {
|
||||
opacity: 1; }
|
||||
100% {
|
||||
opacity: 0; } }
|
||||
|
||||
/*
|
||||
* Owl Carousel - Auto Height Plugin
|
||||
*/
|
||||
.owl-height {
|
||||
transition: height 500ms ease-in-out; }
|
||||
|
||||
/*
|
||||
* Owl Carousel - Lazy Load Plugin
|
||||
*/
|
||||
.owl-carousel .owl-item {
|
||||
/**
|
||||
This is introduced due to a bug in IE11 where lazy loading combined with autoheight plugin causes a wrong
|
||||
calculation of the height of the owl-item that breaks page layouts
|
||||
*/ }
|
||||
.owl-carousel .owl-item .owl-lazy {
|
||||
opacity: 0;
|
||||
transition: opacity 400ms ease; }
|
||||
.owl-carousel .owl-item .owl-lazy[src^=""], .owl-carousel .owl-item .owl-lazy:not([src]) {
|
||||
max-height: 0; }
|
||||
.owl-carousel .owl-item img.owl-lazy {
|
||||
transform-style: preserve-3d; }
|
||||
|
||||
/*
|
||||
* Owl Carousel - Video Plugin
|
||||
*/
|
||||
.owl-carousel .owl-video-wrapper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
background: #000; }
|
||||
|
||||
.owl-carousel .owl-video-play-icon {
|
||||
position: absolute;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -40px;
|
||||
margin-top: -40px;
|
||||
background: url("owl.video.play.png") no-repeat;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
-webkit-backface-visibility: hidden;
|
||||
transition: transform 100ms ease; }
|
||||
|
||||
.owl-carousel .owl-video-play-icon:hover {
|
||||
-ms-transform: scale(1.3, 1.3);
|
||||
transform: scale(1.3, 1.3); }
|
||||
|
||||
.owl-carousel .owl-video-playing .owl-video-tn,
|
||||
.owl-carousel .owl-video-playing .owl-video-play-icon {
|
||||
display: none; }
|
||||
|
||||
.owl-carousel .owl-video-tn {
|
||||
opacity: 0;
|
||||
height: 100%;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
transition: opacity 400ms ease; }
|
||||
|
||||
.owl-carousel .owl-video-frame {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: 100%;
|
||||
width: 100%; }
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Owl Carousel v2.3.4
|
||||
* Copyright 2013-2018 David Deutsch
|
||||
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
|
||||
*/
|
||||
.owl-carousel,.owl-carousel .owl-item{-webkit-tap-highlight-color:transparent;position:relative}.owl-carousel{display:none;width:100%;z-index:1}.owl-carousel .owl-stage{position:relative;-ms-touch-action:pan-Y;touch-action:manipulation;-moz-backface-visibility:hidden}.owl-carousel .owl-stage:after{content:".";display:block;clear:both;visibility:hidden;line-height:0;height:0}.owl-carousel .owl-stage-outer{position:relative;overflow:hidden;-webkit-transform:translate3d(0,0,0)}.owl-carousel .owl-item,.owl-carousel .owl-wrapper{-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0)}.owl-carousel .owl-item{min-height:1px;float:left;-webkit-backface-visibility:hidden;-webkit-touch-callout:none}.owl-carousel .owl-item img{display:block;width:100%}.owl-carousel .owl-dots.disabled,.owl-carousel .owl-nav.disabled{display:none}.no-js .owl-carousel,.owl-carousel.owl-loaded{display:block}.owl-carousel .owl-dot,.owl-carousel .owl-nav .owl-next,.owl-carousel .owl-nav .owl-prev{cursor:pointer;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.owl-carousel .owl-nav button.owl-next,.owl-carousel .owl-nav button.owl-prev,.owl-carousel button.owl-dot{background:0 0;color:inherit;border:none;padding:0!important;font:inherit}.owl-carousel.owl-loading{opacity:0;display:block}.owl-carousel.owl-hidden{opacity:0}.owl-carousel.owl-refresh .owl-item{visibility:hidden}.owl-carousel.owl-drag .owl-item{-ms-touch-action:pan-y;touch-action:pan-y;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.owl-carousel.owl-grab{cursor:move;cursor:grab}.owl-carousel.owl-rtl{direction:rtl}.owl-carousel.owl-rtl .owl-item{float:right}.owl-carousel .animated{animation-duration:1s;animation-fill-mode:both}.owl-carousel .owl-animated-in{z-index:0}.owl-carousel .owl-animated-out{z-index:1}.owl-carousel .fadeOut{animation-name:fadeOut}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.owl-height{transition:height .5s ease-in-out}.owl-carousel .owl-item .owl-lazy{opacity:0;transition:opacity .4s ease}.owl-carousel .owl-item .owl-lazy:not([src]),.owl-carousel .owl-item .owl-lazy[src^=""]{max-height:0}.owl-carousel .owl-item img.owl-lazy{transform-style:preserve-3d}.owl-carousel .owl-video-wrapper{position:relative;height:100%;background:#000}.owl-carousel .owl-video-play-icon{position:absolute;height:80px;width:80px;left:50%;top:50%;margin-left:-40px;margin-top:-40px;background:url(owl.video.play.png) no-repeat;cursor:pointer;z-index:1;-webkit-backface-visibility:hidden;transition:transform .1s ease}.owl-carousel .owl-video-play-icon:hover{-ms-transform:scale(1.3,1.3);transform:scale(1.3,1.3)}.owl-carousel .owl-video-playing .owl-video-play-icon,.owl-carousel .owl-video-playing .owl-video-tn{display:none}.owl-carousel .owl-video-tn{opacity:0;height:100%;background-position:center center;background-repeat:no-repeat;background-size:contain;transition:opacity .4s ease}.owl-carousel .owl-video-frame{position:relative;z-index:1;height:100%;width:100%}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Owl Carousel v2.3.4
|
||||
* Copyright 2013-2018 David Deutsch
|
||||
* Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
|
||||
*/
|
||||
!function(a,b,c,d){function e(b,c){this.settings=null,this.options=a.extend({},e.Defaults,c),this.$element=a(b),this._handlers={},this._plugins={},this._supress={},this._current=null,this._speed=null,this._coordinates=[],this._breakpoint=null,this._width=null,this._items=[],this._clones=[],this._mergers=[],this._widths=[],this._invalidated={},this._pipe=[],this._drag={time:null,target:null,pointer:null,stage:{start:null,current:null},direction:null},this._states={current:{},tags:{initializing:["busy"],animating:["busy"],dragging:["interacting"]}},a.each(["onResize","onThrottledResize"],a.proxy(function(b,c){this._handlers[c]=a.proxy(this[c],this)},this)),a.each(e.Plugins,a.proxy(function(a,b){this._plugins[a.charAt(0).toLowerCase()+a.slice(1)]=new b(this)},this)),a.each(e.Workers,a.proxy(function(b,c){this._pipe.push({filter:c.filter,run:a.proxy(c.run,this)})},this)),this.setup(),this.initialize()}e.Defaults={items:3,loop:!1,center:!1,rewind:!1,checkVisibility:!0,mouseDrag:!0,touchDrag:!0,pullDrag:!0,freeDrag:!1,margin:0,stagePadding:0,merge:!1,mergeFit:!0,autoWidth:!1,startPosition:0,rtl:!1,smartSpeed:250,fluidSpeed:!1,dragEndSpeed:!1,responsive:{},responsiveRefreshRate:200,responsiveBaseElement:b,fallbackEasing:"swing",slideTransition:"",info:!1,nestedItemSelector:!1,itemElement:"div",stageElement:"div",refreshClass:"owl-refresh",loadedClass:"owl-loaded",loadingClass:"owl-loading",rtlClass:"owl-rtl",responsiveClass:"owl-responsive",dragClass:"owl-drag",itemClass:"owl-item",stageClass:"owl-stage",stageOuterClass:"owl-stage-outer",grabClass:"owl-grab"},e.Width={Default:"default",Inner:"inner",Outer:"outer"},e.Type={Event:"event",State:"state"},e.Plugins={},e.Workers=[{filter:["width","settings"],run:function(){this._width=this.$element.width()}},{filter:["width","items","settings"],run:function(a){a.current=this._items&&this._items[this.relative(this._current)]}},{filter:["items","settings"],run:function(){this.$stage.children(".cloned").remove()}},{filter:["width","items","settings"],run:function(a){var b=this.settings.margin||"",c=!this.settings.autoWidth,d=this.settings.rtl,e={width:"auto","margin-left":d?b:"","margin-right":d?"":b};!c&&this.$stage.children().css(e),a.css=e}},{filter:["width","items","settings"],run:function(a){var b=(this.width()/this.settings.items).toFixed(3)-this.settings.margin,c=null,d=this._items.length,e=!this.settings.autoWidth,f=[];for(a.items={merge:!1,width:b};d--;)c=this._mergers[d],c=this.settings.mergeFit&&Math.min(c,this.settings.items)||c,a.items.merge=c>1||a.items.merge,f[d]=e?b*c:this._items[d].width();this._widths=f}},{filter:["items","settings"],run:function(){var b=[],c=this._items,d=this.settings,e=Math.max(2*d.items,4),f=2*Math.ceil(c.length/2),g=d.loop&&c.length?d.rewind?e:Math.max(e,f):0,h="",i="";for(g/=2;g>0;)b.push(this.normalize(b.length/2,!0)),h+=c[b[b.length-1]][0].outerHTML,b.push(this.normalize(c.length-1-(b.length-1)/2,!0)),i=c[b[b.length-1]][0].outerHTML+i,g-=1;this._clones=b,a(h).addClass("cloned").appendTo(this.$stage),a(i).addClass("cloned").prependTo(this.$stage)}},{filter:["width","items","settings"],run:function(){for(var a=this.settings.rtl?1:-1,b=this._clones.length+this._items.length,c=-1,d=0,e=0,f=[];++c<b;)d=f[c-1]||0,e=this._widths[this.relative(c)]+this.settings.margin,f.push(d+e*a);this._coordinates=f}},{filter:["width","items","settings"],run:function(){var a=this.settings.stagePadding,b=this._coordinates,c={width:Math.ceil(Math.abs(b[b.length-1]))+2*a,"padding-left":a||"","padding-right":a||""};this.$stage.css(c)}},{filter:["width","items","settings"],run:function(a){var b=this._coordinates.length,c=!this.settings.autoWidth,d=this.$stage.children();if(c&&a.items.merge)for(;b--;)a.css.width=this._widths[this.relative(b)],d.eq(b).css(a.css);else c&&(a.css.width=a.items.width,d.css(a.css))}},{filter:["items"],run:function(){this._coordinates.length<1&&this.$stage.removeAttr("style")}},{filter:["width","items","settings"],run:function(a){a.current=a.current?this.$stage.children().index(a.current):0,a.current=Math.max(this.minimum(),Math.min(this.maximum(),a.current)),this.reset(a.current)}},{filter:["position"],run:function(){this.animate(this.coordinates(this._current))}},{filter:["width","position","items","settings"],run:function(){var a,b,c,d,e=this.settings.rtl?1:-1,f=2*this.settings.stagePadding,g=this.coordinates(this.current())+f,h=g+this.width()*e,i=[];for(c=0,d=this._coordinates.length;c<d;c++)a=this._coordinates[c-1]||0,b=Math.abs(this._coordinates[c])+f*e,(this.op(a,"<=",g)&&this.op(a,">",h)||this.op(b,"<",g)&&this.op(b,">",h))&&i.push(c);this.$stage.children(".active").removeClass("active"),this.$stage.children(":eq("+i.join("), :eq(")+")").addClass("active"),this.$stage.children(".center").removeClass("center"),this.settings.center&&this.$stage.children().eq(this.current()).addClass("center")}}],e.prototype.initializeStage=function(){this.$stage=this.$element.find("."+this.settings.stageClass),this.$stage.length||(this.$elemeLine truncated
|
||||
animateIn:!1},e.prototype.swap=function(){if(1===this.core.settings.items&&a.support.animation&&a.support.transition){this.core.speed(0);var b,c=a.proxy(this.clear,this),d=this.core.$stage.children().eq(this.previous),e=this.core.$stage.children().eq(this.next),f=this.core.settings.animateIn,g=this.core.settings.animateOut;this.core.current()!==this.previous&&(g&&(b=this.core.coordinates(this.previous)-this.core.coordinates(this.next),d.one(a.support.animation.end,c).css({left:b+"px"}).addClass("animated owl-animated-out").addClass(g)),f&&e.one(a.support.animation.end,c).addClass("animated owl-animated-in").addClass(f))}},e.prototype.clear=function(b){a(b.target).css({left:""}).removeClass("animated owl-animated-out owl-animated-in").removeClass(this.core.settings.animateIn).removeClass(this.core.settings.animateOut),this.core.onTransitionEnd()},e.prototype.destroy=function(){var a,b;for(a in this.handlers)this.core.$element.off(a,this.handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.Animate=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){var e=function(b){this._core=b,this._call=null,this._time=0,this._timeout=0,this._paused=!0,this._handlers={"changed.owl.carousel":a.proxy(function(a){a.namespace&&"settings"===a.property.name?this._core.settings.autoplay?this.play():this.stop():a.namespace&&"position"===a.property.name&&this._paused&&(this._time=0)},this),"initialized.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.autoplay&&this.play()},this),"play.owl.autoplay":a.proxy(function(a,b,c){a.namespace&&this.play(b,c)},this),"stop.owl.autoplay":a.proxy(function(a){a.namespace&&this.stop()},this),"mouseover.owl.autoplay":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.pause()},this),"mouseleave.owl.autoplay":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.play()},this),"touchstart.owl.core":a.proxy(function(){this._core.settings.autoplayHoverPause&&this._core.is("rotating")&&this.pause()},this),"touchend.owl.core":a.proxy(function(){this._core.settings.autoplayHoverPause&&this.play()},this)},this._core.$element.on(this._handlers),this._core.options=a.extend({},e.Defaults,this._core.options)};e.Defaults={autoplay:!1,autoplayTimeout:5e3,autoplayHoverPause:!1,autoplaySpeed:!1},e.prototype._next=function(d){this._call=b.setTimeout(a.proxy(this._next,this,d),this._timeout*(Math.round(this.read()/this._timeout)+1)-this.read()),this._core.is("interacting")||c.hidden||this._core.next(d||this._core.settings.autoplaySpeed)},e.prototype.read=function(){return(new Date).getTime()-this._time},e.prototype.play=function(c,d){var e;this._core.is("rotating")||this._core.enter("rotating"),c=c||this._core.settings.autoplayTimeout,e=Math.min(this._time%(this._timeout||c),c),this._paused?(this._time=this.read(),this._paused=!1):b.clearTimeout(this._call),this._time+=this.read()%c-e,this._timeout=c,this._call=b.setTimeout(a.proxy(this._next,this,d),c-e)},e.prototype.stop=function(){this._core.is("rotating")&&(this._time=0,this._paused=!0,b.clearTimeout(this._call),this._core.leave("rotating"))},e.prototype.pause=function(){this._core.is("rotating")&&!this._paused&&(this._time=this.read(),this._paused=!0,b.clearTimeout(this._call))},e.prototype.destroy=function(){var a,b;this.stop();for(a in this._handlers)this._core.$element.off(a,this._handlers[a]);for(b in Object.getOwnPropertyNames(this))"function"!=typeof this[b]&&(this[b]=null)},a.fn.owlCarousel.Constructor.Plugins.autoplay=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){"use strict";var e=function(b){this._core=b,this._initialized=!1,this._pages=[],this._controls={},this._templates=[],this.$element=this._core.$element,this._overrides={next:this._core.next,prev:this._core.prev,to:this._core.to},this._handlers={"prepared.owl.carousel":a.proxy(function(b){b.namespace&&this._core.settings.dotsData&&this._templates.push('<div class="'+this._core.settings.dotClass+'">'+a(b.content).find("[data-dot]").addBack("[data-dot]").attr("data-dot")+"</div>")},this),"added.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.dotsData&&this._templates.splice(a.position,0,this._templates.pop())},this),"remove.owl.carousel":a.proxy(function(a){a.namespace&&this._core.settings.dotsData&&this._templates.splice(a.position,1)},this),"changed.owl.carousel":a.proxy(function(a){a.namespace&&"position"==a.property.name&&this.draw()},this),"initialized.owl.carousel":a.proxy(function(a){a.namespace&&!this._initialized&&(this._core.trigger("initialize",null,"navigation"),this.initialize(),this.update(),this.draw(),this._initialized=!0,this._core.trigger("initialized",null,"navigation"))},this),"refreshed.owl.carousel":a.proxy(function(a){a.namespace&&this._initialized&&(this._core.trigger("refresh",null,"navigation"),this.update(),this.draw(),this._core.trigger("refreLine truncated
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
/* Placeholders.js v4.0.1 */
|
||||
/*!
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 James Allardice
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
!function(a){"use strict";function b(){}function c(){try{return document.activeElement}catch(a){}}function d(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return!0;return!1}function e(a,b,c){return a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent?a.attachEvent("on"+b,c):void 0}function f(a,b){var c;a.createTextRange?(c=a.createTextRange(),c.move("character",b),c.select()):a.selectionStart&&(a.focus(),a.setSelectionRange(b,b))}function g(a,b){try{return a.type=b,!0}catch(c){return!1}}function h(a,b){if(a&&a.getAttribute(B))b(a);else for(var c,d=a?a.getElementsByTagName("input"):N,e=a?a.getElementsByTagName("textarea"):O,f=d?d.length:0,g=e?e.length:0,h=f+g,i=0;h>i;i++)c=f>i?d[i]:e[i-f],b(c)}function i(a){h(a,k)}function j(a){h(a,l)}function k(a,b){var c=!!b&&a.value!==b,d=a.value===a.getAttribute(B);if((c||d)&&"true"===a.getAttribute(C)){a.removeAttribute(C),a.value=a.value.replace(a.getAttribute(B),""),a.className=a.className.replace(A,"");var e=a.getAttribute(I);parseInt(e,10)>=0&&(a.setAttribute("maxLength",e),a.removeAttribute(I));var f=a.getAttribute(D);return f&&(a.type=f),!0}return!1}function l(a){var b=a.getAttribute(B);if(""===a.value&&b){a.setAttribute(C,"true"),a.value=b,a.className+=" "+z;var c=a.getAttribute(I);c||(a.setAttribute(I,a.maxLength),a.removeAttribute("maxLength"));var d=a.getAttribute(D);return d?a.type="text":"password"===a.type&&g(a,"text")&&a.setAttribute(D,"password"),!0}return!1}function m(a){return function(){P&&a.value===a.getAttribute(B)&&"true"===a.getAttribute(C)?f(a,0):k(a)}}function n(a){return function(){l(a)}}function o(a){return function(){i(a)}}function p(a){return function(b){return v=a.value,"true"===a.getAttribute(C)&&v===a.getAttribute(B)&&d(x,b.keyCode)?(b.preventDefault&&b.preventDefault(),!1):void 0}}function q(a){return function(){k(a,v),""===a.value&&(a.blur(),f(a,0))}}function r(a){return function(){a===c()&&a.value===a.getAttribute(B)&&"true"===a.getAttribute(C)&&f(a,0)}}function s(a){var b=a.form;b&&"string"==typeof b&&(b=document.getElementById(b),b.getAttribute(E)||(e(b,"submit",o(b)),b.setAttribute(E,"true"))),e(a,"focus",m(a)),e(a,"blur",n(a)),P&&(e(a,"keydown",p(a)),e(a,"keyup",q(a)),e(a,"click",r(a))),a.setAttribute(F,"true"),a.setAttribute(B,T),(P||a!==c())&&l(a)}var t=document.createElement("input"),u=void 0!==t.placeholder;if(a.Placeholders={nativeSupport:u,disable:u?b:i,enable:u?b:j},!u){var v,w=["text","search","url","tel","email","password","number","textarea"],x=[27,33,34,35,36,37,38,39,40,8,46],y="#ccc",z="placeholdersjs",A=new RegExp("(?:^|\\s)"+z+"(?!\\S)"),B="data-placeholder-value",C="data-placeholder-active",D="data-placeholder-type",E="data-placeholder-submit",F="data-placeholder-bound",G="data-placeholder-focus",H="data-placeholder-live",I="data-placeholder-maxlength",J=100,K=document.getElementsByTagName("head")[0],L=document.documentElement,M=a.Placeholders,N=document.getElementsByTagName("input"),O=document.getElementsByTagName("textarea"),P="false"===L.getAttribute(G),Q="false"!==L.getAttribute(H),R=document.createElement("style");R.type="text/css";var S=document.createTextNode("."+z+" {color:"+y+";}");R.styleSheet?R.styleSheet.cssText=S.nodeValue:R.appendChild(S),K.insertBefore(R,K.firstChild);for(var T,U,V=0,W=N.length+O.length;W>V;V++)U=V<N.length?N[V]:O[V-N.length],T=U.attributes.placeholder,T&&(T=T.nodeValue,T&&d(w,U.type)&&s(U));var X=setInterval(function(){for(var a=0,b=N.length+O.length;b>a;a++)U=a<N.length?N[a]:O[a-N.length],T=U.attributes.placeholder,T?(T=T.nodeValue,T&&d(w,U.type)&&(U.getAttribute(F)||s(U),(T!==U.getAttribute(B)||"password"===U.type&&!U.getAttribute(D))&&("password"===U.type&&!U.getAttribute(D)&&g(U,"text")&&U.setAttribute(D,"password"),U.value===U.getAttribute(B)&&(U.value=T),U.setAttribute(B,T)))):U.getAttribute(C)&&(k(U),U.removeAttribute(B));Q||clearInterval(X)},J);e(a,"beforeunload",function(){M.disable()})}}(this);
|
||||
@@ -0,0 +1,371 @@
|
||||
var wrestMsg = "";
|
||||
var wrestFld = null;
|
||||
var wrestFldDefaultColor = "";
|
||||
//var wrestFldBackColor = "#ff3061";
|
||||
|
||||
// subject 속성값을 얻어 return, 없으면 tag의 name을 넘김
|
||||
function wrestItemname(fld)
|
||||
{
|
||||
//return fld.getAttribute("title") ? fld.getAttribute("title") : ( fld.getAttribute("alt") ? fld.getAttribute("alt") : fld.name );
|
||||
var id = fld.getAttribute("id");
|
||||
var labels = document.getElementsByTagName("label");
|
||||
var el = null;
|
||||
|
||||
for(i=0; i<labels.length; i++) {
|
||||
if(id == labels[i].htmlFor) {
|
||||
el = labels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(el != null) {
|
||||
var text = el.innerHTML.replace(/[<].*[>].*[<]\/+.*[>]/gi, "");
|
||||
|
||||
if(text == '') {
|
||||
return fld.getAttribute("title") ? fld.getAttribute("title") : ( fld.getAttribute("placeholder") ? fld.getAttribute("placeholder") : fld.name );
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
} else {
|
||||
return fld.getAttribute("title") ? fld.getAttribute("title") : ( fld.getAttribute("placeholder") ? fld.getAttribute("placeholder") : fld.name );
|
||||
}
|
||||
}
|
||||
|
||||
// 양쪽 공백 없애기
|
||||
function wrestTrim(fld)
|
||||
{
|
||||
var pattern = /(^\s+)|(\s+$)/g; // \s 공백 문자
|
||||
return fld.value.replace(pattern, "");
|
||||
}
|
||||
|
||||
// 필수 입력 검사
|
||||
function wrestRequired(fld)
|
||||
{
|
||||
if (wrestTrim(fld) == "") {
|
||||
if (wrestFld == null) {
|
||||
// 셀렉트박스일 경우에도 필수 선택 검사합니다.
|
||||
wrestMsg = wrestItemname(fld) + " : 필수 "+(fld.type=="select-one"?"선택":"입력")+"입니다.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 김선용 2006.3 - 전화번호(휴대폰) 형식 검사 : 123-123(4)-5678
|
||||
function wrestTelNum(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var pattern = /^[0-9]{2,3}-[0-9]{3,4}-[0-9]{4}$/;
|
||||
if(!pattern.test(fld.value)){
|
||||
if(wrestFld == null){
|
||||
wrestMsg = wrestItemname(fld)+" : 전화번호 형식이 올바르지 않습니다.\n\n하이픈(-)을 포함하여 입력하세요.\n";
|
||||
wrestFld = fld;
|
||||
fld.select();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 이메일주소 형식 검사
|
||||
function wrestEmail(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
//var pattern = /(\S+)@(\S+)\.(\S+)/; 이메일주소에 한글 사용시
|
||||
var pattern = /([0-9a-zA-Z_-]+)@([0-9a-zA-Z_-]+)\.([0-9a-zA-Z_-]+)/;
|
||||
if (!pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + " : 이메일주소 형식이 아닙니다.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 한글인지 검사 (자음, 모음 조합된 한글만 가능)
|
||||
function wrestHangul(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
//var pattern = /([^가-힣\x20])/i;
|
||||
var pattern = /([^가-힣\x20])/;
|
||||
|
||||
if (pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + ' : 한글이 아닙니다. (자음, 모음 조합된 한글만 가능)\n';
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 한글인지 검사2 (자음, 모음만 있는 한글도 가능)
|
||||
function wrestHangul2(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var pattern = /([^가-힣ㄱ-ㅎㅏ-ㅣ\x20])/i;
|
||||
//var pattern = /([^가-힣ㄱ-ㅎㅏ-ㅣ\x20])/;
|
||||
|
||||
if (pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + ' : 한글이 아닙니다.\n';
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 한글,영문,숫자인지 검사3
|
||||
function wrestHangulAlNum(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var pattern = /([^가-힣\x20^a-z^A-Z^0-9])/i;
|
||||
|
||||
if (pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + ' : 한글, 영문, 숫자가 아닙니다.\n';
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 한글,영문 인지 검사
|
||||
function wrestHangulAlpha(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var pattern = /([^가-힣\x20^a-z^A-Z])/i;
|
||||
|
||||
if (pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + ' : 한글, 영문이 아닙니다.\n';
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 숫자인지검사
|
||||
// 배부른꿀꿀이님 추가 (http://dasir.com) 2003-06-24
|
||||
function wrestNumeric(fld)
|
||||
{
|
||||
if (fld.value.length > 0) {
|
||||
for (i = 0; i < fld.value.length; i++) {
|
||||
if (fld.value.charAt(i) < '0' || fld.value.charAt(i) > '9') {
|
||||
wrestMsg = wrestItemname(fld) + " : 숫자가 아닙니다.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 영문자 검사
|
||||
// 배부른꿀꿀이님 추가 (http://dasir.com) 2003-06-24
|
||||
function wrestAlpha(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var pattern = /(^[a-zA-Z]+$)/;
|
||||
|
||||
if (!pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + " : 영문이 아닙니다.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 영문자와 숫자 검사
|
||||
// 배부른꿀꿀이님 추가 (http://dasir.com) 2003-07-07
|
||||
function wrestAlNum(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var pattern = /(^[a-zA-Z0-9]+$)/;
|
||||
|
||||
if (!pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + " : 영문 또는 숫자가 아닙니다.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 영문자와 숫자 그리고 _ 검사
|
||||
function wrestAlNum_(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var pattern = /(^[a-zA-Z0-9\_]+$)/;
|
||||
|
||||
if (!pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + " : 영문, 숫자, _ 가 아닙니다.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 최소 길이 검사
|
||||
function wrestMinLength(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var minlength = fld.getAttribute("minlength");
|
||||
|
||||
if (wrestFld == null) {
|
||||
if (fld.value.length < parseInt(minlength)) {
|
||||
wrestMsg = wrestItemname(fld) + " : 최소 "+minlength+"글자 이상 입력하세요.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 이미지 확장자
|
||||
function wrestImgExt(fld)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var pattern = /\.(gif|jpg|png)$/i; // jpeg 는 제외
|
||||
if(!pattern.test(fld.value)){
|
||||
if(wrestFld == null){
|
||||
wrestMsg = wrestItemname(fld)+" : 이미지 파일이 아닙니다.\n.gif .jpg .png 파일만 가능합니다.\n";
|
||||
wrestFld = fld;
|
||||
fld.select();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 확장자
|
||||
function wrestExtension(fld, css)
|
||||
{
|
||||
if (!wrestTrim(fld)) return;
|
||||
|
||||
var str = css.split("="); // ext=?? <-- str[1]
|
||||
var src = fld.value.split(".");
|
||||
var ext = src[src.length - 1];
|
||||
|
||||
if (wrestFld == null) {
|
||||
if (ext.toLowerCase() < str[1].toLowerCase()) {
|
||||
wrestMsg = wrestItemname(fld) + " : ."+str[1]+" 파일만 가능합니다.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 공백 검사후 공백을 "" 로 변환
|
||||
function wrestNospace(fld)
|
||||
{
|
||||
var pattern = /(\s)/g; // \s 공백 문자
|
||||
|
||||
if (pattern.test(fld.value)) {
|
||||
if (wrestFld == null) {
|
||||
wrestMsg = wrestItemname(fld) + " : 공백이 없어야 합니다.\n";
|
||||
wrestFld = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// submit 할 때 속성을 검사한다.
|
||||
function wrestSubmit()
|
||||
{
|
||||
wrestMsg = "";
|
||||
wrestFld = null;
|
||||
|
||||
var attr = null;
|
||||
|
||||
// 해당폼에 대한 요소의 개수만큼 돌려라
|
||||
for (var i=0; i<this.elements.length; i++) {
|
||||
var el = this.elements[i];
|
||||
|
||||
// Input tag 의 type 이 text, file, password 일때만
|
||||
// 셀렉트 박스일때도 필수 선택 검사합니다. select-one
|
||||
if (el.type=="text" || el.type=="hidden" || el.type=="file" || el.type=="password" || el.type=="select-one" || el.type=="textarea") {
|
||||
if (el.getAttribute("required") != null) {
|
||||
wrestRequired(el);
|
||||
}
|
||||
|
||||
if (el.getAttribute("minlength") != null) {
|
||||
wrestMinLength(el);
|
||||
}
|
||||
|
||||
var array_css = el.className.split(" "); // class 를 공백으로 나눔
|
||||
|
||||
el.style.backgroundColor = wrestFldDefaultColor;
|
||||
|
||||
// 배열의 길이만큼 돌려라
|
||||
for (var k=0; k<array_css.length; k++) {
|
||||
var css = array_css[k];
|
||||
switch (css) {
|
||||
case "required" : wrestRequired(el); break;
|
||||
case "trim" : wrestTrim(el); break;
|
||||
case "email" : wrestEmail(el); break;
|
||||
case "hangul" : wrestHangul(el); break;
|
||||
case "hangul2" : wrestHangul2(el); break;
|
||||
case "hangulalpha" : wrestHangulAlpha(el); break;
|
||||
case "hangulalnum" : wrestHangulAlNum(el); break;
|
||||
case "nospace" : wrestNospace(el); break;
|
||||
case "numeric" : wrestNumeric(el); break;
|
||||
case "alpha" : wrestAlpha(el); break;
|
||||
case "alnum" : wrestAlNum(el); break;
|
||||
case "alnum_" : wrestAlNum_(el); break;
|
||||
case "telnum" : wrestTelNum(el); break; // 김선용 2006.3 - 전화번호 형식 검사
|
||||
case "imgext" : wrestImgExt(el); break;
|
||||
default :
|
||||
if (/^extension\=/.test(css)) {
|
||||
wrestExtension(el, css); break;
|
||||
}
|
||||
} // switch (css)
|
||||
} // for (k)
|
||||
} // if (el)
|
||||
} // for (i)
|
||||
|
||||
// 필드가 null 이 아니라면 오류메세지 출력후 포커스를 해당 오류 필드로 옮김
|
||||
// 오류 필드는 배경색상을 바꾼다.
|
||||
if (wrestFld != null) {
|
||||
// 경고메세지 출력
|
||||
alert(wrestMsg);
|
||||
|
||||
if (wrestFld.style.display != "none") {
|
||||
var id = wrestFld.getAttribute("id");
|
||||
|
||||
// 오류메세지를 위한 element 추가
|
||||
var msg_el = document.createElement("strong");
|
||||
msg_el.id = "msg_"+id;
|
||||
msg_el.className = "msg_sound_only";
|
||||
msg_el.innerHTML = wrestMsg;
|
||||
wrestFld.parentNode.insertBefore(msg_el, wrestFld);
|
||||
|
||||
var new_href = document.location.href.replace(/#msg.+$/, "")+"#msg_"+id;
|
||||
|
||||
document.location.href = new_href;
|
||||
|
||||
//wrestFld.style.backgroundColor = wrestFldBackColor;
|
||||
if (typeof(wrestFld.select) != "undefined")
|
||||
wrestFld.select();
|
||||
wrestFld.focus();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.oldsubmit && this.oldsubmit() == false)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// 초기에 onsubmit을 가로채도록 한다.
|
||||
function wrestInitialized()
|
||||
{
|
||||
for (var i = 0; i < document.forms.length; i++) {
|
||||
// onsubmit 이벤트가 있다면 저장해 놓는다.
|
||||
if (document.forms[i].onsubmit) {
|
||||
document.forms[i].oldsubmit = document.forms[i].onsubmit;
|
||||
}
|
||||
document.forms[i].onsubmit = wrestSubmit;
|
||||
}
|
||||
}
|
||||
|
||||
// 폼필드 자동검사
|
||||
$(document).ready(function(){
|
||||
// onload
|
||||
wrestInitialized();
|
||||
});
|
||||
@@ -0,0 +1,523 @@
|
||||
/**
|
||||
* Main Page Video Player & Navigation Controller
|
||||
* 모듈화된 구조로 리팩토링
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ============================================
|
||||
// Configuration
|
||||
// ============================================
|
||||
const CONFIG = {
|
||||
TOTAL_PAGES: 5,
|
||||
INTRO_DELAY: 2800,
|
||||
VISITED_STORAGE_KEY: 'visited',
|
||||
VIDEO_BASE_PATH: '/kngil/img/video',
|
||||
PAGE_LINKS: {
|
||||
1: './value.html',
|
||||
2: './provided.html',
|
||||
3: './primary.html',
|
||||
4: './analysis.html',
|
||||
5: './results.html'
|
||||
},
|
||||
SELECTORS: {
|
||||
video: '#video_play',
|
||||
videoLink: '#main_video_link',
|
||||
pagination: '.main-pagination',
|
||||
paginationItem: '.main-pagination div',
|
||||
intro: '.intro-wrap',
|
||||
mainMask: '.main-mask',
|
||||
footer: 'footer',
|
||||
footerClose: '.footer-close',
|
||||
main: '.main'
|
||||
},
|
||||
CLASSES: {
|
||||
pageOn: 'page-on',
|
||||
footerOn: 'on',
|
||||
footerOff: ' ',
|
||||
skip: 'skip'
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Utility Functions
|
||||
// ============================================
|
||||
const Utils = {
|
||||
/**
|
||||
* DOM 요소 선택 (jQuery 대체)
|
||||
*/
|
||||
$(selector) {
|
||||
return document.querySelector(selector);
|
||||
},
|
||||
|
||||
/**
|
||||
* DOM 요소들 선택 (jQuery 대체)
|
||||
*/
|
||||
$$(selector) {
|
||||
return document.querySelectorAll(selector);
|
||||
},
|
||||
|
||||
/**
|
||||
* 숫자 유효성 검사
|
||||
*/
|
||||
isValidPageNum(pageNum) {
|
||||
return Number.isInteger(pageNum) &&
|
||||
pageNum >= 1 &&
|
||||
pageNum <= CONFIG.TOTAL_PAGES;
|
||||
},
|
||||
|
||||
/**
|
||||
* 안전한 이벤트 리스너 추가
|
||||
*/
|
||||
safeAddEventListener(element, event, handler) {
|
||||
if (element && typeof handler === 'function') {
|
||||
element.addEventListener(event, handler);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* 클래스 토글 헬퍼
|
||||
*/
|
||||
toggleClass(element, className, force) {
|
||||
if (!element) return;
|
||||
if (force === undefined) {
|
||||
element.classList.toggle(className);
|
||||
} else {
|
||||
element.classList.toggle(className, force);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Video Player Module
|
||||
// ============================================
|
||||
const VideoPlayer = {
|
||||
currentPage: 1,
|
||||
videoElement: null,
|
||||
sourceElement: null,
|
||||
|
||||
init() {
|
||||
this.videoElement = Utils.$(CONFIG.SELECTORS.video);
|
||||
|
||||
if (!this.videoElement) {
|
||||
console.warn('[VideoPlayer] Video element not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
this.sourceElement = this.videoElement.querySelector('source');
|
||||
if (!this.sourceElement) {
|
||||
console.warn('[VideoPlayer] Source element not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
this.setupEventListeners();
|
||||
return true;
|
||||
},
|
||||
|
||||
setupEventListeners() {
|
||||
// 영상 종료 후 다음 영상 실행
|
||||
Utils.safeAddEventListener(this.videoElement, 'ended', () => {
|
||||
this.playNext();
|
||||
});
|
||||
},
|
||||
|
||||
loadVideo(pageNum) {
|
||||
if (!Utils.isValidPageNum(pageNum)) {
|
||||
console.warn(`[VideoPlayer] Invalid page number: ${pageNum}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const videoSource = `${CONFIG.VIDEO_BASE_PATH}/main_${pageNum}.mp4`;
|
||||
|
||||
try {
|
||||
this.sourceElement.src = videoSource;
|
||||
this.videoElement.load();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('[VideoPlayer] Failed to load video:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
play() {
|
||||
if (!this.videoElement) return false;
|
||||
|
||||
return this.videoElement.play()
|
||||
.then(() => true)
|
||||
.catch(err => {
|
||||
console.warn('[VideoPlayer] Play failed:', err);
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
pause() {
|
||||
if (this.videoElement) {
|
||||
this.videoElement.pause();
|
||||
}
|
||||
},
|
||||
|
||||
playNext() {
|
||||
this.currentPage = this.currentPage < CONFIG.TOTAL_PAGES
|
||||
? this.currentPage + 1
|
||||
: 1;
|
||||
|
||||
if (this.loadVideo(this.currentPage)) {
|
||||
Pagination.updateState(this.currentPage);
|
||||
this.play();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Pagination Module
|
||||
// ============================================
|
||||
const Pagination = {
|
||||
paginationElement: null,
|
||||
items: null,
|
||||
|
||||
init() {
|
||||
this.paginationElement = Utils.$(CONFIG.SELECTORS.pagination);
|
||||
|
||||
if (!this.paginationElement) {
|
||||
console.warn('[Pagination] Pagination element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
this.items = Utils.$$(CONFIG.SELECTORS.paginationItem);
|
||||
this.setupClickHandlers();
|
||||
},
|
||||
|
||||
setupClickHandlers() {
|
||||
// 이벤트 위임 사용
|
||||
Utils.safeAddEventListener(
|
||||
this.paginationElement,
|
||||
'click',
|
||||
this.handleClick.bind(this)
|
||||
);
|
||||
},
|
||||
|
||||
handleClick(e) {
|
||||
// 클릭된 요소 또는 그 부모 요소에서 data-page 속성을 찾음
|
||||
let target = e.target.closest('[data-page]');
|
||||
|
||||
// 만약 li 요소를 직접 클릭한 경우, 그 안의 div를 찾음
|
||||
if (!target) {
|
||||
const liElement = e.target.closest('li');
|
||||
if (liElement) {
|
||||
target = liElement.querySelector('[data-page]');
|
||||
}
|
||||
}
|
||||
|
||||
if (!target) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const pageNum = parseInt(target.getAttribute('data-page'), 10);
|
||||
if (Utils.isValidPageNum(pageNum)) {
|
||||
this.handlePageClick(pageNum);
|
||||
}
|
||||
},
|
||||
|
||||
handlePageClick(pageNum) {
|
||||
VideoPlayer.currentPage = pageNum;
|
||||
|
||||
if (VideoPlayer.loadVideo(pageNum)) {
|
||||
VideoPlayer.play();
|
||||
this.updateState(pageNum);
|
||||
this.updateLink(pageNum);
|
||||
}
|
||||
},
|
||||
|
||||
updateState(pageNum) {
|
||||
if (!this.items || !Utils.isValidPageNum(pageNum)) return;
|
||||
|
||||
// 모든 아이템에서 활성 클래스 제거
|
||||
this.items.forEach(item => {
|
||||
item.classList.remove(CONFIG.CLASSES.pageOn);
|
||||
});
|
||||
|
||||
// 해당 페이지 아이템에 활성 클래스 추가
|
||||
const targetItem = Array.from(this.items).find(item =>
|
||||
item.classList.contains(`page-0${pageNum}`)
|
||||
);
|
||||
|
||||
if (targetItem) {
|
||||
targetItem.classList.add(CONFIG.CLASSES.pageOn);
|
||||
}
|
||||
},
|
||||
|
||||
updateLink(pageNum) {
|
||||
if (!Utils.isValidPageNum(pageNum)) return;
|
||||
|
||||
const linkUrl = CONFIG.PAGE_LINKS[pageNum];
|
||||
const linkElement = Utils.$(CONFIG.SELECTORS.videoLink);
|
||||
|
||||
if (linkElement && linkUrl) {
|
||||
linkElement.href = linkUrl;
|
||||
}
|
||||
},
|
||||
|
||||
show() {
|
||||
if (this.paginationElement) {
|
||||
this.paginationElement.style.display = '';
|
||||
}
|
||||
},
|
||||
|
||||
hide() {
|
||||
if (this.paginationElement) {
|
||||
this.paginationElement.style.display = 'none';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Intro Controller Module
|
||||
// ============================================
|
||||
const IntroController = {
|
||||
init() {
|
||||
const visited = sessionStorage.getItem(CONFIG.VISITED_STORAGE_KEY);
|
||||
const intro = Utils.$(CONFIG.SELECTORS.intro);
|
||||
const mainMask = Utils.$(CONFIG.SELECTORS.mainMask);
|
||||
|
||||
if (visited) {
|
||||
this.hideIntro(intro, mainMask);
|
||||
} else {
|
||||
// 첫 방문 시 세션 스토리지에 저장
|
||||
setTimeout(() => {
|
||||
try {
|
||||
sessionStorage.setItem(CONFIG.VISITED_STORAGE_KEY, 'true');
|
||||
} catch (error) {
|
||||
console.warn('[IntroController] Failed to set sessionStorage:', error);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
hideIntro(intro, mainMask) {
|
||||
if (intro) {
|
||||
intro.style.display = 'none';
|
||||
}
|
||||
if (mainMask) {
|
||||
mainMask.classList.add(CONFIG.CLASSES.skip);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Cursor Text Controller Module
|
||||
// ============================================
|
||||
const CursorTextController = {
|
||||
cursorTextElement: null,
|
||||
|
||||
init() {
|
||||
// 메인 페이지인지 확인 (.wrap.main 클래스 존재 여부)
|
||||
const mainElement = Utils.$(CONFIG.SELECTORS.main);
|
||||
if (!mainElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 커서 따라다니는 텍스트 요소 생성
|
||||
this.cursorTextElement = document.createElement('div');
|
||||
this.cursorTextElement.textContent = 'Click!';
|
||||
this.cursorTextElement.style.cssText = `
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
transform: translate(-0%, -50%);
|
||||
transition: opacity 0.3s;
|
||||
opacity: 0;
|
||||
`;
|
||||
document.body.appendChild(this.cursorTextElement);
|
||||
|
||||
this.setupEventListeners();
|
||||
},
|
||||
|
||||
setupEventListeners() {
|
||||
// 마우스 움직임 추적
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
this.handleMouseMove(e);
|
||||
});
|
||||
|
||||
// 마우스가 페이지를 벗어나면 숨김
|
||||
document.addEventListener('mouseleave', () => {
|
||||
if (this.cursorTextElement) {
|
||||
this.cursorTextElement.style.opacity = '0';
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseenter', () => {
|
||||
if (this.cursorTextElement) {
|
||||
this.cursorTextElement.style.opacity = '1';
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
handleMouseMove(e) {
|
||||
if (!this.cursorTextElement) return;
|
||||
|
||||
// 마우스 위치의 요소 확인
|
||||
const elementUnderMouse = document.elementFromPoint(e.clientX, e.clientY);
|
||||
|
||||
// 특정 영역인지 확인
|
||||
const isInFooter = elementUnderMouse?.closest('footer');
|
||||
const isInPopup = elementUnderMouse?.closest('.popup_wrap') || elementUnderMouse?.closest('.popup-wrap');
|
||||
const isInFloating = elementUnderMouse?.closest('.floating_menu');
|
||||
const isInPagination = elementUnderMouse?.closest('.main-pagination');
|
||||
const isInHeader = elementUnderMouse?.closest('.header');
|
||||
const isInSitemap = elementUnderMouse?.closest('.popup_sitemap') || elementUnderMouse?.closest('.sitemap');
|
||||
|
||||
// 특정 영역이면 숨김
|
||||
if (isInFooter || isInPopup || isInFloating || isInPagination || isInHeader || isInSitemap) {
|
||||
this.cursorTextElement.style.opacity = '0';
|
||||
} else {
|
||||
this.cursorTextElement.style.opacity = '1';
|
||||
// 커서 오른쪽 아래에 위치
|
||||
this.cursorTextElement.style.left = (e.clientX + 15) + 'px';
|
||||
this.cursorTextElement.style.top = (e.clientY + 15) + 'px';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Footer Controller Module
|
||||
// ============================================
|
||||
const FooterController = {
|
||||
footerElement: null,
|
||||
mainElement: null,
|
||||
footerCloseElement: null,
|
||||
|
||||
init() {
|
||||
this.footerElement = Utils.$(CONFIG.SELECTORS.footer);
|
||||
this.mainElement = Utils.$(CONFIG.SELECTORS.main);
|
||||
this.footerCloseElement = Utils.$(CONFIG.SELECTORS.footerClose);
|
||||
|
||||
if (!this.footerElement || !this.mainElement) {
|
||||
console.warn('[FooterController] Required elements not found');
|
||||
return;
|
||||
}
|
||||
|
||||
this.setupMousewheelHandler();
|
||||
this.setupCloseHandler();
|
||||
},
|
||||
|
||||
setupMousewheelHandler() {
|
||||
// jQuery mousewheel 이벤트 대신 wheel 이벤트 사용
|
||||
Utils.safeAddEventListener(
|
||||
this.mainElement,
|
||||
'wheel',
|
||||
this.handleWheel.bind(this),
|
||||
{ passive: true }
|
||||
);
|
||||
},
|
||||
|
||||
handleWheel(e) {
|
||||
// deltaY가 양수면 아래로 스크롤 (footer 표시 - on 클래스 추가)
|
||||
// deltaY가 음수면 위로 스크롤 (footer 숨김 - on 클래스 제거)
|
||||
if (e.deltaY > 0) {
|
||||
this.show();
|
||||
} else if (e.deltaY < 0) {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
setupCloseHandler() {
|
||||
if (this.footerCloseElement) {
|
||||
Utils.safeAddEventListener(
|
||||
this.footerCloseElement,
|
||||
'click',
|
||||
() => this.hide()
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
show() {
|
||||
if (!this.footerElement) return;
|
||||
|
||||
this.footerElement.classList.add(CONFIG.CLASSES.footerOn);
|
||||
|
||||
// footerOff가 유효한 클래스 이름인 경우에만 제거
|
||||
const footerOff = CONFIG.CLASSES.footerOff.trim();
|
||||
if (footerOff) {
|
||||
this.footerElement.classList.remove(footerOff);
|
||||
}
|
||||
},
|
||||
|
||||
hide() {
|
||||
if (!this.footerElement) return;
|
||||
|
||||
// footerOff가 유효한 클래스 이름인 경우에만 추가
|
||||
const footerOff = CONFIG.CLASSES.footerOff.trim();
|
||||
if (footerOff) {
|
||||
this.footerElement.classList.add(footerOff);
|
||||
}
|
||||
|
||||
this.footerElement.classList.remove(CONFIG.CLASSES.footerOn);
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Main Initialization
|
||||
// ============================================
|
||||
const MainController = {
|
||||
init() {
|
||||
// DOM이 준비되면 초기화
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
this.start();
|
||||
});
|
||||
} else {
|
||||
this.start();
|
||||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
// Video Player 초기화
|
||||
if (!VideoPlayer.init()) {
|
||||
console.warn('[MainController] Video player initialization failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// 초기 비디오 일시정지 및 페이지네이션 숨김
|
||||
VideoPlayer.pause();
|
||||
Pagination.hide();
|
||||
|
||||
// 방문 여부 확인 및 비디오 재생
|
||||
const visited = sessionStorage.getItem(CONFIG.VISITED_STORAGE_KEY);
|
||||
|
||||
if (visited) {
|
||||
this.startVideoPlayback();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.startVideoPlayback();
|
||||
}, CONFIG.INTRO_DELAY);
|
||||
}
|
||||
|
||||
// 모듈 초기화
|
||||
Pagination.init();
|
||||
IntroController.init();
|
||||
FooterController.init();
|
||||
CursorTextController.init();
|
||||
|
||||
// 초기 링크 설정
|
||||
Pagination.updateLink(VideoPlayer.currentPage);
|
||||
},
|
||||
|
||||
startVideoPlayback() {
|
||||
VideoPlayer.play();
|
||||
Pagination.show();
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Start Application
|
||||
// ============================================
|
||||
MainController.init();
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,326 @@
|
||||
/* =========================
|
||||
전역 상태값
|
||||
========================= */
|
||||
let isIdChecked = false;
|
||||
let checkedUserId = '';
|
||||
let isPhoneVerified = false;
|
||||
let authTimer = null;
|
||||
|
||||
const REGEX = {
|
||||
id: /^[a-zA-Z][a-zA-Z0-9]{3,11}$/,
|
||||
password: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/,
|
||||
name: /^[가-힣a-zA-Z\s]+$/,
|
||||
phone: /^\d{3}-\d{4}-\d{4}$/
|
||||
};
|
||||
|
||||
/* =========================
|
||||
DOM 로드 후 초기화
|
||||
========================= */
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initMemberType();
|
||||
initEmailDomain();
|
||||
initIdCheck();
|
||||
initPhoneAuth();
|
||||
initFormSubmit();
|
||||
initPasswordValidation(); // 비밀번호 규칙
|
||||
initNameValidation(); // 이름 특수문자 차단
|
||||
initPhoneFormat(); // 휴대폰 자동 하이픈
|
||||
// initFormValidation(); // submit 최종 검증
|
||||
});
|
||||
|
||||
/* =========================
|
||||
1. 회원유형
|
||||
========================= */
|
||||
function initMemberType() {
|
||||
const radios = document.querySelectorAll('input[name="memberType"]');
|
||||
const companyRow = document.querySelector('.company-group');
|
||||
|
||||
radios.forEach(radio => {
|
||||
radio.addEventListener('change', () => {
|
||||
if (radio.value === '1') {
|
||||
companyRow.style.display = '';
|
||||
} else {
|
||||
companyRow.style.display = 'none';
|
||||
companyRow.querySelectorAll('input').forEach(i => i.value = '');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* =========================
|
||||
2. 이메일 도메인
|
||||
========================= */
|
||||
function initEmailDomain() {
|
||||
const select = document.getElementById('domain_list');
|
||||
const custom = document.getElementById('custom_domain');
|
||||
|
||||
select.addEventListener('change', () => {
|
||||
if (select.value === 'type') {
|
||||
custom.classList.remove('d-none');
|
||||
custom.required = true;
|
||||
} else {
|
||||
custom.classList.add('d-none');
|
||||
custom.required = false;
|
||||
custom.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* =========================
|
||||
3. 아이디 중복확인
|
||||
========================= */
|
||||
function initIdCheck() {
|
||||
const input = document.getElementById('user_id');
|
||||
const btn = document.getElementById('btn_id_check');
|
||||
|
||||
if (!btn || !input) {
|
||||
console.error('ID input 또는 중복확인 버튼 없음');
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ 아이디 입력값 변경 시 → 중복확인 무효화
|
||||
input.addEventListener('input', () => {
|
||||
isIdChecked = false;
|
||||
checkedUserId = '';
|
||||
input.readOnly = false;
|
||||
});
|
||||
|
||||
btn.addEventListener('click', async (e) => {
|
||||
e.preventDefault(); // ⭐ 중요 (폼 submit 방지)
|
||||
|
||||
const userId = input.value.trim();
|
||||
|
||||
if (!/^[a-zA-Z][a-zA-Z0-9]{3,11}$/.test(userId)) {
|
||||
alert('아이디 형식이 올바르지 않습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await fetch('/kngil/bbs/join.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'check_id',
|
||||
userId: userId
|
||||
})
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (data.available === true) {
|
||||
alert('사용 가능한 아이디입니다.');
|
||||
|
||||
isIdChecked = true;
|
||||
checkedUserId = userId;
|
||||
|
||||
// UX: 아이디 수정 못 하게
|
||||
input.readOnly = true;
|
||||
} else {
|
||||
alert(data.message || '이미 사용 중인 아이디입니다.');
|
||||
|
||||
isIdChecked = false;
|
||||
checkedUserId = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* =========================
|
||||
4. 휴대폰 인증번호
|
||||
========================= */
|
||||
function initPhoneAuth() {
|
||||
const btn = document.querySelector('.btn-code');
|
||||
const phoneInput = document.getElementById('user_phone');
|
||||
const timerEl = document.querySelector('.timer');
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
const phone = phoneInput.value.trim();
|
||||
if (!/^\d{3}-\d{4}-\d{4}$/.test(phone)) {
|
||||
alert('휴대폰 번호 형식이 올바르지 않습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
await fetch('/api/send_sms.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone })
|
||||
});
|
||||
|
||||
startTimer(timerEl, 180);
|
||||
alert('인증번호가 발송되었습니다.');
|
||||
});
|
||||
}
|
||||
|
||||
function startTimer(el, seconds) {
|
||||
clearInterval(authTimer);
|
||||
el.classList.remove('d-none');
|
||||
|
||||
let remain = seconds;
|
||||
authTimer = setInterval(() => {
|
||||
const m = String(Math.floor(remain / 60)).padStart(2, '0');
|
||||
const s = String(remain % 60).padStart(2, '0');
|
||||
el.textContent = `${m}:${s}`;
|
||||
remain--;
|
||||
|
||||
if (remain < 0) {
|
||||
clearInterval(authTimer);
|
||||
el.textContent = '만료';
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/* =========================
|
||||
5. 비밀번호 검증
|
||||
========================= */
|
||||
function validatePassword() {
|
||||
const pw = document.getElementById('user_password').value;
|
||||
const pw2 = document.getElementById('user_password_confirm').value;
|
||||
|
||||
if (!PASSWORD_REGEX.test(pw)) {
|
||||
alert('비밀번호는 영문, 숫자, 특수기호를 포함한 8자 이상이어야 합니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pw !== pw2) {
|
||||
alert('비밀번호가 일치하지 않습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
6. 가입하기 submit
|
||||
========================= */
|
||||
function initFormSubmit() {
|
||||
const form = document.forms.joinForm;
|
||||
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!isIdChecked) {
|
||||
alert('아이디 중복확인을 해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!validatePassword()) return;
|
||||
|
||||
const formData = new FormData(form);
|
||||
|
||||
const email =
|
||||
formData.get('userEmail') + '@' +
|
||||
(formData.get('emailDomain') === 'type'
|
||||
? formData.get('customDomain')
|
||||
: formData.get('emailDomain'));
|
||||
|
||||
const payload = {
|
||||
memberType: formData.get('memberType'),
|
||||
userId: formData.get('userId'),
|
||||
password: formData.get('userPassword'),
|
||||
userName: formData.get('userName'),
|
||||
email,
|
||||
phone: formData.get('userPhone'),
|
||||
company: formData.get('companyName'),
|
||||
department: formData.get('departmentName')
|
||||
};
|
||||
|
||||
const res = await fetch('/kngil/bbs/join.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
form.style.display = 'none';
|
||||
document.querySelector('.messages').style.display = 'block';
|
||||
} else {
|
||||
alert(data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* =========================
|
||||
회원 가입 유효성 체크
|
||||
========================= */
|
||||
function initPasswordValidation() {
|
||||
const pw = document.getElementById('user_password');
|
||||
const pw2 = document.getElementById('user_password_confirm');
|
||||
const msg = document.getElementById('password_help');
|
||||
|
||||
function validate() {
|
||||
if (!pw.value) return;
|
||||
|
||||
if (!PASSWORD_REGEX.test(pw.value)) {
|
||||
msg.textContent = '영문 + 숫자 + 특수기호 포함 8자 이상';
|
||||
msg.classList.remove('success');
|
||||
msg.classList.add('error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (pw2.value && pw.value !== pw2.value) {
|
||||
msg.textContent = '비밀번호가 일치하지 않습니다.';
|
||||
msg.classList.remove('success');
|
||||
msg.classList.add('error');
|
||||
return;
|
||||
}
|
||||
|
||||
msg.textContent = '사용 가능한 비밀번호입니다.';
|
||||
msg.classList.remove('error');
|
||||
msg.classList.add('success');
|
||||
}
|
||||
|
||||
pw.addEventListener('input', validate);
|
||||
pw2.addEventListener('input', validate);
|
||||
}
|
||||
|
||||
|
||||
// function initFormValidation() {
|
||||
// const form = document.forms.joinForm;
|
||||
|
||||
// form.addEventListener('submit', e => {
|
||||
// e.preventDefault();
|
||||
|
||||
// const id = form.userId.value.trim();
|
||||
// const pw = form.userPassword.value;
|
||||
// const pw2 = form.userPasswordConfirm.value;
|
||||
// const name = form.userName.value.trim();
|
||||
// const email = form.userEmail.value.trim();
|
||||
// const phone = form.userPhone.value.trim();
|
||||
|
||||
// if (!isIdChecked || checkedUserId !== form.userId.value.trim()) {
|
||||
// alert('아이디 중복확인을 해주세요.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (!id || !pw || !pw2 || !name || !email || !phone) {
|
||||
// alert('필수 항목을 모두 입력하세요.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (!REGEX.password.test(pw)) {
|
||||
// alert('비밀번호 규칙을 확인하세요.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (pw !== pw2) {
|
||||
// alert('비밀번호가 일치하지 않습니다.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (!REGEX.name.test(name)) {
|
||||
// alert('이름에 특수문자는 사용할 수 없습니다.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (!REGEX.phone.test(phone)) {
|
||||
// alert('휴대전화번호 형식이 올바르지 않습니다.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // 여기까지 왔으면 → 서버 signup 요청
|
||||
// submitSignup();
|
||||
// });
|
||||
// }
|
||||
@@ -0,0 +1,308 @@
|
||||
/* =========================
|
||||
전역 상태값
|
||||
========================= */
|
||||
let isIdChecked = false;
|
||||
let checkedUserId = '';
|
||||
|
||||
const REGEX = {
|
||||
id: /^[a-zA-Z][a-zA-Z0-9]{3,11}$/,
|
||||
password: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/,
|
||||
name: /^[가-힣a-zA-Z\s]+$/,
|
||||
phone: /^\d{3}-\d{4}-\d{4}$/
|
||||
};
|
||||
|
||||
|
||||
/* =========================
|
||||
DOM 로드 후 초기화
|
||||
========================= */
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initMemberType();
|
||||
initEmailDomain();
|
||||
initIdCheck();
|
||||
initPasswordValidation();
|
||||
// initNameValidation();
|
||||
initPhoneFormat();
|
||||
initFormSubmit();
|
||||
});
|
||||
|
||||
/* =========================
|
||||
1. 회원유형
|
||||
========================= */
|
||||
function initMemberType() {
|
||||
const radios = document.querySelectorAll('input[name="memberType"]');
|
||||
const companyRow = document.querySelector('.company-group');
|
||||
|
||||
radios.forEach(radio => {
|
||||
radio.addEventListener('change', () => {
|
||||
if (radio.value === '1') {
|
||||
companyRow.style.display = '';
|
||||
} else {
|
||||
companyRow.style.display = 'none';
|
||||
companyRow.querySelectorAll('input').forEach(i => i.value = '');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* =========================
|
||||
2. 이메일 도메인
|
||||
========================= */
|
||||
function initEmailDomain() {
|
||||
const select = document.getElementById('domain_list');
|
||||
const custom = document.getElementById('custom_domain');
|
||||
|
||||
select.addEventListener('change', () => {
|
||||
if (select.value === 'type') {
|
||||
custom.classList.remove('d-none');
|
||||
custom.required = true;
|
||||
} else {
|
||||
custom.classList.add('d-none');
|
||||
custom.required = false;
|
||||
custom.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* =========================
|
||||
3. 아이디 중복확인
|
||||
========================= */
|
||||
function initIdCheck() {
|
||||
const input = document.getElementById('user_id');
|
||||
const btn = document.getElementById('btn_id_check');
|
||||
|
||||
input.addEventListener('input', () => {
|
||||
isIdChecked = false;
|
||||
checkedUserId = '';
|
||||
input.readOnly = false;
|
||||
});
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
const userId = input.value.trim();
|
||||
|
||||
if (!userId) {
|
||||
alert('아이디를 입력해주세요.');
|
||||
input.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!REGEX.id.test(userId)) {
|
||||
alert('아이디 형식이 올바르지 않습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await fetch('/kngil/bbs/join.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'check_id', userId })
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (data.available) {
|
||||
alert('사용 가능한 아이디입니다.');
|
||||
isIdChecked = true;
|
||||
checkedUserId = userId;
|
||||
input.readOnly = true;
|
||||
} else {
|
||||
alert(data.message || '이미 사용 중인 아이디입니다.');
|
||||
isIdChecked = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* =========================
|
||||
4. 휴대폰 인증번호
|
||||
========================= */
|
||||
function initPhoneAuth() {
|
||||
const btn = document.querySelector('.btn-code');
|
||||
const phoneInput = document.getElementById('user_phone');
|
||||
const timerEl = document.querySelector('.timer');
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
const phone = phoneInput.value.trim();
|
||||
if (!/^\d{3}-\d{4}-\d{4}$/.test(phone)) {
|
||||
alert('휴대폰 번호 형식이 올바르지 않습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
await fetch('/api/send_sms.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ phone })
|
||||
});
|
||||
|
||||
startTimer(timerEl, 180);
|
||||
alert('인증번호가 발송되었습니다.');
|
||||
});
|
||||
}
|
||||
|
||||
function startTimer(el, seconds) {
|
||||
clearInterval(authTimer);
|
||||
el.classList.remove('d-none');
|
||||
|
||||
let remain = seconds;
|
||||
authTimer = setInterval(() => {
|
||||
const m = String(Math.floor(remain / 60)).padStart(2, '0');
|
||||
const s = String(remain % 60).padStart(2, '0');
|
||||
el.textContent = `${m}:${s}`;
|
||||
remain--;
|
||||
|
||||
if (remain < 0) {
|
||||
clearInterval(authTimer);
|
||||
el.textContent = '만료';
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/* =========================
|
||||
5. 비밀번호 검증
|
||||
========================= */
|
||||
function validatePassword() {
|
||||
const pw = document.getElementById('user_password').value;
|
||||
const pw2 = document.getElementById('user_password_confirm').value;
|
||||
|
||||
if (!PASSWORD_REGEX.test(pw)) {
|
||||
alert('비밀번호는 영문, 숫자, 특수기호를 포함한 8자 이상이어야 합니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pw !== pw2) {
|
||||
alert('비밀번호가 일치하지 않습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
6. 가입하기 submit
|
||||
========================= */
|
||||
function initFormSubmit() {
|
||||
const form = document.forms.joinForm;
|
||||
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!isIdChecked || checkedUserId !== form.userId.value.trim()) {
|
||||
alert('아이디 중복확인을 해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!REGEX.password.test(form.userPassword.value)) {
|
||||
alert('비밀번호 규칙을 확인하세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (form.userPassword.value !== form.userPasswordConfirm.value) {
|
||||
alert('비밀번호가 일치하지 않습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!REGEX.name.test(form.userName.value.trim())) {
|
||||
alert('이름에 특수문자는 사용할 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// if (!REGEX.phone.test(form.userPhone.value.trim())) {
|
||||
// alert('휴대전화번호 형식이 올바르지 않습니다.');
|
||||
// return;
|
||||
// }
|
||||
|
||||
// ✅ 서버 전송
|
||||
const formData = new FormData(form);
|
||||
|
||||
const email =
|
||||
formData.get('userEmail') + '@' +
|
||||
(formData.get('emailDomain') === 'type'
|
||||
? formData.get('customDomain')
|
||||
: formData.get('emailDomain'));
|
||||
|
||||
const payload = {
|
||||
action: 'signup',
|
||||
memberType: formData.get('memberType'),
|
||||
userId: formData.get('userId'),
|
||||
password: formData.get('userPassword'),
|
||||
userName: formData.get('userName'),
|
||||
email,
|
||||
phone: formData.get('userPhone'),
|
||||
company: formData.get('companyName') || null,
|
||||
department: formData.get('departmentName') || null
|
||||
};
|
||||
|
||||
const res = await fetch('/kngil/bbs/join.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
form.style.display = 'none';
|
||||
document.querySelector('.messages').style.display = 'block';
|
||||
} else {
|
||||
alert(data.message || '회원가입 실패');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =========================
|
||||
회원 가입 유효성 체크
|
||||
========================= */
|
||||
function initPasswordValidation() {
|
||||
const pw = document.getElementById('user_password');
|
||||
const pw2 = document.getElementById('user_password_confirm');
|
||||
const msg = document.getElementById('password_help');
|
||||
|
||||
function validate() {
|
||||
if (!pw.value) {
|
||||
msg.textContent = '영문+숫자+특수기호 8자 이상';
|
||||
msg.className = 'info-msg';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!REGEX.password.test(pw.value)) {
|
||||
msg.textContent = '비밀번호 규칙을 만족하지 않습니다.';
|
||||
msg.className = 'info-msg error';
|
||||
return;
|
||||
}
|
||||
|
||||
if (pw2.value && pw.value !== pw2.value) {
|
||||
msg.textContent = '비밀번호가 일치하지 않습니다.';
|
||||
msg.className = 'info-msg error';
|
||||
return;
|
||||
}
|
||||
|
||||
msg.textContent = '사용 가능한 비밀번호입니다.';
|
||||
msg.className = 'info-msg success';
|
||||
}
|
||||
|
||||
pw.addEventListener('input', validate);
|
||||
pw2.addEventListener('input', validate);
|
||||
}
|
||||
|
||||
function initPhoneFormat() {
|
||||
const phone = document.getElementById('user_phone');
|
||||
|
||||
phone.addEventListener('input', () => {
|
||||
let v = phone.value.replace(/\D/g, '');
|
||||
|
||||
if (v.length <= 3) phone.value = v;
|
||||
else if (v.length <= 7) phone.value = `${v.slice(0,3)}-${v.slice(3)}`;
|
||||
else phone.value = `${v.slice(0,3)}-${v.slice(3,7)}-${v.slice(7,11)}`;
|
||||
});
|
||||
}
|
||||
|
||||
// function initNameValidation() {
|
||||
// const nameInput = document.getElementById('user_name');
|
||||
// if (!nameInput) return;
|
||||
|
||||
// nameInput.addEventListener('input', () => {
|
||||
// nameInput.value = nameInput.value.replace(/[^가-힣a-zA-Z\s]/g, '');
|
||||
// });
|
||||
// }
|
||||
Vendored
+1533
File diff suppressed because it is too large.
Load diff
Vendored
+1
@@ -0,0 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AOS=t():e.AOS=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return e[o].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="dist/",t(0)}([function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}var i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},r=n(1),a=(o(r),n(6)),u=o(a),c=n(7),f=o(c),s=n(8),d=o(s),l=n(9),p=o(l),m=n(10),b=o(m),v=n(11),y=o(v),g=n(14),h=o(g),w=[],k=!1,x=document.all&&!window.atob,j={offset:120,delay:0,easing:"ease",duration:400,disable:!1,once:!1,startEvent:"DOMContentLoaded",throttleDelay:99,debounceDelay:50,disableMutationObserver:!1},O=function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(e&&(k=!0),k)return w=(0,y.default)(w,j),(0,b.default)(w,j.once),w},_=function(){w=(0,h.default)(),O()},S=function(){w.forEach(function(e,t){e.node.removeAttribute("data-aos"),e.node.removeAttribute("data-aos-easing"),e.node.removeAttribute("data-aos-duration"),e.node.removeAttribute("data-aos-delay")})},z=function(e){return e===!0||"mobile"===e&&p.default.mobile()||"phone"===e&&p.default.phone()||"tablet"===e&&p.default.tablet()||"function"==typeof e&&e()===!0},A=function(e){return j=i(j,e),w=(0,h.default)(),z(j.disable)||x?S():(document.querySelector("body").setAttribute("data-aos-easing",j.easing),document.querySelector("body").setAttribute("data-aos-duration",j.duration),document.querySelector("body").setAttribute("data-aos-delay",j.delay),"DOMContentLoaded"===j.startEvent&&["complete","interactive"].indexOf(document.readyState)>-1?O(!0):"load"===j.startEvent?window.addEventListener(j.startEvent,function(){O(!0)}):document.addEventListener(j.startEvent,function(){O(!0)}),window.addEventListener("resize",(0,f.default)(O,j.debounceDelay,!0)),window.addEventListener("orientationchange",(0,f.default)(O,j.debounceDelay,!0)),window.addEventListener("scroll",(0,u.default)(function(){(0,b.default)(w,j.once)},j.throttleDelay)),j.disableMutationObserver||(0,d.default)("[data-aos]",_),w)};e.exports={init:A,refresh:O,refreshHard:_}},function(e,t){},,,,,function(e,t){(function(t){"use strict";function n(e,t,n){function o(t){var n=b,o=v;return b=v=void 0,k=t,g=e.apply(o,n)}function r(e){return k=e,h=setTimeout(s,t),_?o(e):g}function a(e){var n=e-w,o=e-k,i=t-n;return S?j(i,y-o):i}function c(e){var n=e-w,o=e-k;return void 0===w||n>=t||n<0||S&&o>=y}function s(){var e=O();return c(e)?d(e):void(h=setTimeout(s,a(e)))}function d(e){return h=void 0,z&&b?o(e):(b=v=void 0,g)}function l(){void 0!==h&&clearTimeout(h),k=0,b=w=v=h=void 0}function p(){return void 0===h?g:d(O())}function m(){var e=O(),n=c(e);if(b=arguments,v=this,w=e,n){if(void 0===h)return r(w);if(S)return h=setTimeout(s,t),o(w)}return void 0===h&&(h=setTimeout(s,t)),g}var b,v,y,g,h,w,k=0,_=!1,S=!1,z=!0;if("function"!=typeof e)throw new TypeError(f);return t=u(t)||0,i(n)&&(_=!!n.leading,S="maxWait"in n,y=S?x(u(n.maxWait)||0,t):y,z="trailing"in n?!!n.trailing:z),m.cancel=l,m.flush=p,m}function o(e,t,o){var r=!0,a=!0;if("function"!=typeof e)throw new TypeError(f);return i(o)&&(r="leading"in o?!!o.leading:r,a="trailing"in o?!!o.trailing:a),n(e,t,{leading:r,maxWait:t,trailing:a})}function i(e){var t="undefined"==typeof e?"undefined":c(e);return!!e&&("object"==t||"function"==t)}function r(e){return!!e&&"object"==("undefined"==typeof e?"undefined":c(e))}function a(e){return"symbol"==("undefined"==typeof e?"undefined":c(e))||r(e)&&k.call(e)==d}function u(e){if("number"==typeof e)return e;if(a(e))return s;if(i(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=i(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(l,"");var n=m.test(e);return n||b.test(e)?v(e.slice(2),n?2:8):p.test(e)?s:+e}var c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},f="Expected a function",s=NaN,d="[object Symbol]",l=/^\s+|\s+$/g,p=/^[-+]0x[0-9a-f]+$/i,m=/^0b[01]+$/i,b=/^0o[0-7]+$/i,v=parseInt,y="object"==("undefined"==typeof t?"undefined":c(t))&&t&&t.Object===Object&&t,g="object"==("undefined"==typeof self?"undefined":c(self))&&self&&self.Object===Object&&self,h=y||g||Function("return this")(),w=Object.prototype,k=w.toString,x=Math.max,j=Math.min,O=function(){return h.Date.now()};e.exports=o}).call(t,function(){return this}())},function(e,t){(function(t){"use strict";function n(e,t,n){function i(t){var n=b,o=v;return b=v=void 0,O=t,g=e.apply(o,n)}function r(e){return O=e,h=setTimeout(s,t),_?i(e):g}function u(e){var n=e-w,o=e-O,i=t-n;return S?x(i,y-o):i}function f(e){var n=e-w,o=e-O;return void 0===Line truncated
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
/*!
|
||||
* GSAP 3.12.5
|
||||
* https://gsap.com
|
||||
*
|
||||
* @license Copyright 2024, GreenSock. All rights reserved.
|
||||
* Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership.
|
||||
* @author: Jack Doyle, jack@greensock.com
|
||||
*/
|
||||
|
||||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).window=t.window||{})}(this,function(e){"use strict";function _inheritsLoose(t,e){t.prototype=Object.create(e.prototype),(t.prototype.constructor=t).__proto__=e}function _assertThisInitialized(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function r(t){return"string"==typeof t}function s(t){return"function"==typeof t}function t(t){return"number"==typeof t}function u(t){return void 0===t}function v(t){return"object"==typeof t}function w(t){return!1!==t}function x(){return"undefined"!=typeof window}function y(t){return s(t)||r(t)}function P(t){return(i=yt(t,ot))&&ze}function Q(t,e){return console.warn("Invalid property",t,"set to",e,"Missing plugin? gsap.registerPlugin()")}function R(t,e){return!e&&console.warn(t)}function S(t,e){return t&&(ot[t]=e)&&i&&(i[t]=e)||ot}function T(){return 0}function ea(t){var e,r,i=t[0];if(v(i)||s(i)||(t=[t]),!(e=(i._gsap||{}).harness)){for(r=gt.length;r--&&!gt[r].targetTest(i););e=gt[r]}for(r=t.length;r--;)t[r]&&(t[r]._gsap||(t[r]._gsap=new Vt(t[r],e)))||t.splice(r,1);return t}function fa(t){return t._gsap||ea(Mt(t))[0]._gsap}function ga(t,e,r){return(r=t[e])&&s(r)?t[e]():u(r)&&t.getAttribute&&t.getAttribute(e)||r}function ha(t,e){return(t=t.split(",")).forEach(e)||t}function ia(t){return Math.round(1e5*t)/1e5||0}function ja(t){return Math.round(1e7*t)/1e7||0}function ka(t,e){var r=e.charAt(0),i=parseFloat(e.substr(2));return t=parseFloat(t),"+"===r?t+i:"-"===r?t-i:"*"===r?t*i:t/i}function la(t,e){for(var r=e.length,i=0;t.indexOf(e[i])<0&&++i<r;);return i<r}function ma(){var t,e,r=dt.length,i=dt.slice(0);for(ct={},t=dt.length=0;t<r;t++)(e=i[t])&&e._lazy&&(e.render(e._lazy[0],e._lazy[1],!0)._lazy=0)}function na(t,e,r,i){dt.length&&!L&&ma(),t.render(e,r,i||L&&e<0&&(t._initted||t._startAt)),dt.length&&!L&&ma()}function oa(t){var e=parseFloat(t);return(e||0===e)&&(t+"").match(at).length<2?e:r(t)?t.trim():t}function pa(t){return t}function qa(t,e){for(var r in e)r in t||(t[r]=e[r]);return t}function ta(t,e){for(var r in e)"__proto__"!==r&&"constructor"!==r&&"prototype"!==r&&(t[r]=v(e[r])?ta(t[r]||(t[r]={}),e[r]):e[r]);return t}function ua(t,e){var r,i={};for(r in t)r in e||(i[r]=t[r]);return i}function va(t){var e=t.parent||I,r=t.keyframes?function _setKeyframeDefaults(i){return function(t,e){for(var r in e)r in t||"duration"===r&&i||"ease"===r||(t[r]=e[r])}}(Z(t.keyframes)):qa;if(w(t.inherit))for(;e;)r(t,e.vars.defaults),e=e.parent||e._dp;return t}function xa(t,e,r,i,n){void 0===r&&(r="_first"),void 0===i&&(i="_last");var a,s=t[i];if(n)for(a=e[n];s&&s[n]>a;)s=s._prev;return s?(e._next=s._next,s._next=e):(e._next=t[r],t[r]=e),e._next?e._next._prev=e:t[i]=e,e._prev=s,e.parent=e._dp=t,e}function ya(t,e,r,i){void 0===r&&(r="_first"),void 0===i&&(i="_last");var n=e._prev,a=e._next;n?n._next=a:t[r]===e&&(t[r]=a),a?a._prev=n:t[i]===e&&(t[i]=n),e._next=e._prev=e.parent=null}function za(t,e){t.parent&&(!e||t.parent.autoRemoveChildren)&&t.parent.remove&&t.parent.remove(t),t._act=0}function Aa(t,e){if(t&&(!e||e._end>t._dur||e._start<0))for(var r=t;r;)r._dirty=1,r=r.parent;return t}function Ca(t,e,r,i){return t._startAt&&(L?t._startAt.revert(ht):t.vars.immediateRender&&!t.vars.autoRevert||t._startAt.render(e,!0,i))}function Ea(t){return t._repeat?Tt(t._tTime,t=t.duration()+t._rDelay)*t:0}function Ga(t,e){return(t-e._start)*e._ts+(0<=e._ts?0:e._dirty?e.totalDuration():e._tDur)}function Ha(t){return t._end=ja(t._start+(t._tDur/Math.abs(t._ts||t._rts||X)||0))}function Ia(t,e){var r=t._dp;return r&&r.smoothChildTiming&&t._ts&&(t._start=ja(r._time-(0<t._ts?e/t._ts:((t._dirty?t.totalDuration():t._tDur)-e)/-t._ts)),Ha(t),r._dirty||Aa(r,t)),t}function Ja(t,e){var r;if((e._time||!e._dur&&e._initted||e._start<t._time&&(e._dur||!e.add))&&(r=Ga(t.rawTime(),e),(!e._dur||Ot(0,e.totalDuration(),r)-e._tTime>X)&&e.render(r,!0)),Aa(t,e)._dp&&t._initted&&t._time>=t._dur&&t._ts){if(t._dur<t.duration())for(r=t;r._dp;)0<=r.rawTime()&&r.totalTime(r._tTime),r=r._dp;t._zTime=-X}}function Ka(e,r,i,n){return r.parent&&za(r),r._start=ja((t(i)?i:i||e!==I?xt(e,i,r):e._time)+r._delay),r._end=ja(r._start+(r.totalDuration()/Math.abs(r.timeScale())||0)),xa(e,r,"_first","_last",e._sort?"_start":0),bt(r)||(e._recent=r),n||Ja(e,r),e._ts<0&&Ia(e,e._tTime),e}function La(t,e){return(ot.ScrollTrigger||Q("scrollTrigger",e))&&ot.ScrollTrigger.create(e,t)}function Ma(t,e,r,i,n){return Qt(t,e,n),t._initted?!r&&t._pt&&!L&&(t._dur&&!1!==t.vars.lazy||!t._dur&&t.vars.lazy)&&f!==Rt.frame?(dt.push(t),t._lazy=[n,i],1):void 0:1}function Ra(t,e,r,i){var n=t._repeat,a=ja(e)||0,s=t._tTime/t._tDur;return s&&!i&&(t._time*=a/t._dur),t._dur=a,t._tDur=n?n<0?1e10:ja(a*(n+1)+t._rDelay*n):a,0<s&&!i&&Ia(t,t._tTime=t._tDur*s),t.parent&&Ha(t),r||Aa(t.parent,t),t}function Sa(t){return t instanceof Xt?Aa(t):Ra(t,t._dur)}function Va(e,r,i){var n,aLine truncated
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */
|
||||
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=y.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:v}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,y,s,c,v,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),j=function(e,t){return e===t&&(l=!0),0},D={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^Line truncated
|
||||
@@ -0,0 +1,4 @@
|
||||
/* == jquery mousewheel plugin == Version: 3.1.13, License: MIT License (MIT) */
|
||||
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).heighLine truncated
|
||||
/* == malihu jquery custom scrollbar plugin == Version: 3.1.6, License: MIT License (MIT) */
|
||||
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"undefined"!=typeof module&&module.exports?module.exports=e:e(jQuery,window,document)}(function(e){var t,o,a,n,i,r,l,s,c,d,u,f,m,h,p,g,v,x,S,_,w,C,b,y,B,T,k,M,O,I,D,E,W,R,A,L,z,P,H,U,F,q,j,Y,X,N,V,Q,G,J,K,Z,$,ee,te,oe,ae,ne;oe="function"==typeof define&&define.amd,ae="undefined"!=typeof module&&module.exports,ne="https:"==document.location.protocol?"https:":"http:",oe||(ae?require("jquery-mousewheel")(e):e.event.special.mousewheel||e("head").append(decodeURI("%3Cscript src="+ne+"//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js%3E%3C/script%3E"))),o="mCustomScrollbar",a={setTop:0,setLeft:0,axis:"y",scrollbarPosition:"inside",scrollInertia:950,autoDraggerLength:!0,alwaysShowScrollbar:0,snapOffset:0,mouseWheel:{enable:!0,scrollAmount:"auto",axis:"y",deltaFactor:"auto",disableOver:["select","option","keygen","datalist","textarea"]},scrollButtons:{scrollType:"stepless",scrollAmount:"auto"},keyboard:{enable:!0,scrollType:"stepless",scrollAmount:"auto"},contentTouchScroll:25,documentTouchScroll:!0,advanced:{autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']",updateOnContentResize:!0,updateOnImageLoad:"auto",autoUpdateTimeout:60},theme:"light",callbacks:{onTotalScrollOffset:0,onTotalScrollBackOffset:0,alwaysTriggerOffsets:!0}},n=0,i={},r=window.attachEvent&&!window.addEventListener?1:0,l=!1,s=["mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar","mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer","mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight"],c={init:function(t){var t=e.extend(!0,{},a,t),o=d.call(this);if(t.live){var r=t.liveSelector||this.selector||".mCustomScrollbar",l=e(r);if("off"===t.live)return void f(r);i[r]=setTimeout(function(){l.mCustomScrollbar(t),"once"===t.live&&l.length&&f(r)},500)}else f(r);return t.setWidth=t.set_width?t.set_width:t.setWidth,t.setHeight=t.set_height?t.set_height:t.setHeight,t.axis=t.horizontalScroll?"x":m(t.axis),t.scrollInertia=t.scrollInertia>0&&t.scrollInertia<17?17:t.scrollInertia,"object"!=typeof t.mouseWheel&&1==t.mouseWheel&&(t.mouseWheel={enable:!0,scrollAmount:"auto",axis:"y",preventDefault:!1,deltaFactor:"auto",normalizeDelta:!1,invert:!1}),t.mouseWheel.scrollAmount=t.mouseWheelPixels?t.mouseWheelPixels:t.mouseWheel.scrollAmount,t.mouseWheel.normalizeDelta=t.advanced.normalizeMouseWheelDelta?t.advanced.normalizeMouseWheelDelta:t.mouseWheel.normalizeDelta,t.scrollButtons.scrollType=h(t.scrollButtons.scrollType),u(t),e(o).each(function(){var o=e(this);if(!o.data("mCS")){o.data("mCS",{idx:++n,opt:t,scrollRatio:{y:null,x:null},overflowed:null,contentReset:{y:null,x:null},bindEvents:!1,tweenRunning:!1,sequential:{},langDir:o.css("direction"),cbOffsets:null,trigger:null,poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}}});var a=o.data("mCS"),i=a.opt,r=o.data("mcs-axis"),l=o.data("mcs-scrollbar-position"),d=o.data("mcs-theme");r&&(i.axis=r),l&&(i.scrollbarPosition=l),d&&(i.theme=d,u(i)),p.call(this),a&&i.callbacks.onCreate&&"function"==typeof i.callbacks.onCreate&&i.callbacks.onCreate.call(this),e("#mCSB_"+a.idx+"_container img:not(."+s[2]+")").addClass(s[2]),c.update.call(null,o)}})},update:function(t,o){var a=t||d.call(this);return e(a).each(function(){var t=e(this);if(t.data("mCS")){var a=t.data("mCS"),n=a.opt,i=e("#mCSB_"+a.idx+"_container"),r=e("#mCSB_"+a.idx),l=[e("#mCSB_"+a.idx+"_dragger_vertical"),e("#mCSB_"+a.idx+"_dragger_horizontal")];if(!i.length)return;a.tweenRunning&&X(t),o&&a&&n.callbacks.onBeforeUpdate&&"function"==typeof n.callbacks.onBeforeUpdate&&n.callbacks.onBeforeUpdate.call(this),t.hasClass(s[3])&&t.removeClass(s[3]),t.hasClass(s[4])&&t.removeClass(s[4]),r.css("max-height","none"),r.height()!==t.height()&&r.css("max-height",t.height()),v.call(this),"y"===n.axis||n.advanced.autoExpandHorizontalScroll||i.css("width",g(i)),a.overflowed=C.call(this),T.call(this),n.autoDraggerLength&&S.call(this),_.call(this),y.call(this);var c=[Math.abs(i[0].offsetTop),Math.abs(i[0].offsetLeft)];"x"!==n.axis&&(a.overflowed[0]?l[0].height()>l[0].parent().height()?b.call(this):(N(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}),a.contentReset.y=null):(b.call(this),"y"===n.axis?B.call(this):"yx"===n.axis&&a.overflowed[1]&&N(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}))),"y"!==n.axis&&(a.overflowed[1]?l[1].width()>l[1].parent().width()?b.call(this):(N(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}),a.contentReset.x=null):(b.call(this),"x"===n.axis?B.call(this):"yx"===n.axis&&a.overflowed[0]&&N(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}))),o&&a&&(2===o&&n.callbacks.onImageLoad&&"function"==typeof n.callbacks.onImageLoad?n.callbacks.onImageLoad.call(this):3===o&&n.callbacks.onSelectorChange&&"function"==typeof n.callbacks.onSelectorChangLine truncated
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* jQuery Mousewheel 3.1.13
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
*/
|
||||
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?module.exports=e:e(jQuery)}(function(a){var u,r,e=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],t="onwheel"in window.document||9<=window.document.documentMode?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],f=Array.prototype.slice;if(a.event.fixHooks)for(var n=e.length;n;)a.event.fixHooks[e[--n]]=a.event.mouseHooks;var d=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var e=t.length;e;)this.addEventListener(t[--e],i,!1);else this.onmousewheel=i;a.data(this,"mousewheel-line-height",d.getLineHeight(this)),a.data(this,"mousewheel-page-height",d.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var e=t.length;e;)this.removeEventListener(t[--e],i,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(e){var t=a(e),e=t["offsetParent"in a.fn?"offsetParent":"parent"]();return e.length||(e=a("body")),parseInt(e.css("fontSize"),10)||parseInt(t.css("fontSize"),10)||16},getPageHeight:function(e){return a(e).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};function i(e){var t,n=e||window.event,i=f.call(arguments,1),o=0,l=0,s=0,h=0;if((e=a.event.fix(n)).type="mousewheel","detail"in n&&(s=-1*n.detail),"wheelDelta"in n&&(s=n.wheelDelta),"wheelDeltaY"in n&&(s=n.wheelDeltaY),"wheelDeltaX"in n&&(l=-1*n.wheelDeltaX),"axis"in n&&n.axis===n.HORIZONTAL_AXIS&&(l=-1*s,s=0),o=0===s?l:s,"deltaY"in n&&(o=s=-1*n.deltaY),"deltaX"in n&&(l=n.deltaX,0===s&&(o=-1*l)),0!==s||0!==l)return 1===n.deltaMode?(o*=t=a.data(this,"mousewheel-line-height"),s*=t,l*=t):2===n.deltaMode&&(o*=t=a.data(this,"mousewheel-page-height"),s*=t,l*=t),h=Math.max(Math.abs(s),Math.abs(l)),(!r||h<r)&&c(n,r=h)&&(r/=40),c(n,h)&&(o/=40,l/=40,s/=40),o=Math[1<=o?"floor":"ceil"](o/r),l=Math[1<=l?"floor":"ceil"](l/r),s=Math[1<=s?"floor":"ceil"](s/r),d.settings.normalizeOffset&&this.getBoundingClientRect&&(h=this.getBoundingClientRect(),e.offsetX=e.clientX-h.left,e.offsetY=e.clientY-h.top),e.deltaX=l,e.deltaY=s,e.deltaFactor=r,e.deltaMode=0,i.unshift(e,o,l,s),u&&window.clearTimeout(u),u=window.setTimeout(w,200),(a.event.dispatch||a.event.handle).apply(this,i)}function w(){r=null}function c(e,t){return d.settings.adjustOldDeltas&&"mousewheel"===e.type&&t%120==0}a.fn.extend({mousewheel:function(e){return e?this.on("mousewheel",e):this.trigger("mousewheel")},unmousewheel:function(e){return this.off("mousewheel",e)}})});
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):(t="undefined"!=typeof globalThis?globalThis:t||self).Lenis=i()}(this,(function(){"use strict";function clamp(t,i,e){return Math.max(t,Math.min(i,e))}class Animate{constructor(){this.isRunning=!1,this.value=0,this.from=0,this.to=0,this.duration=0,this.currentTime=0}advance(t){var i;if(!this.isRunning)return;let e=!1;if(this.duration&&this.easing){this.currentTime+=t;const i=clamp(0,this.currentTime/this.duration,1);e=i>=1;const s=e?1:this.easing(i);this.value=this.from+(this.to-this.from)*s}else this.lerp?(this.value=function damp(t,i,e,s){return function lerp(t,i,e){return(1-e)*t+e*i}(t,i,1-Math.exp(-e*s))}(this.value,this.to,60*this.lerp,t),Math.round(this.value)===this.to&&(this.value=this.to,e=!0)):(this.value=this.to,e=!0);e&&this.stop(),null===(i=this.onUpdate)||void 0===i||i.call(this,this.value,e)}stop(){this.isRunning=!1}fromTo(t,i,{lerp:e,duration:s,easing:o,onStart:n,onUpdate:l}){this.from=this.value=t,this.to=i,this.lerp=e,this.duration=s,this.easing=o,this.currentTime=0,this.isRunning=!0,null==n||n(),this.onUpdate=l}}class Dimensions{constructor({wrapper:t,content:i,autoResize:e=!0,debounce:s=250}={}){this.width=0,this.height=0,this.scrollWidth=0,this.scrollHeight=0,this.resize=()=>{this.onWrapperResize(),this.onContentResize()},this.onWrapperResize=()=>{this.wrapper===window?(this.width=window.innerWidth,this.height=window.innerHeight):this.wrapper instanceof HTMLElement&&(this.width=this.wrapper.clientWidth,this.height=this.wrapper.clientHeight)},this.onContentResize=()=>{this.wrapper===window?(this.scrollHeight=this.content.scrollHeight,this.scrollWidth=this.content.scrollWidth):this.wrapper instanceof HTMLElement&&(this.scrollHeight=this.wrapper.scrollHeight,this.scrollWidth=this.wrapper.scrollWidth)},this.wrapper=t,this.content=i,e&&(this.debouncedResize=function debounce(t,i){let e;return function(){let s=arguments,o=this;clearTimeout(e),e=setTimeout((function(){t.apply(o,s)}),i)}}(this.resize,s),this.wrapper===window?window.addEventListener("resize",this.debouncedResize,!1):(this.wrapperResizeObserver=new ResizeObserver(this.debouncedResize),this.wrapperResizeObserver.observe(this.wrapper)),this.contentResizeObserver=new ResizeObserver(this.debouncedResize),this.contentResizeObserver.observe(this.content)),this.resize()}destroy(){var t,i;null===(t=this.wrapperResizeObserver)||void 0===t||t.disconnect(),null===(i=this.contentResizeObserver)||void 0===i||i.disconnect(),window.removeEventListener("resize",this.debouncedResize,!1)}get limit(){return{x:this.scrollWidth-this.width,y:this.scrollHeight-this.height}}}class Emitter{constructor(){this.events={}}emit(t,...i){let e=this.events[t]||[];for(let t=0,s=e.length;t<s;t++)e[t](...i)}on(t,i){var e;return(null===(e=this.events[t])||void 0===e?void 0:e.push(i))||(this.events[t]=[i]),()=>{var e;this.events[t]=null===(e=this.events[t])||void 0===e?void 0:e.filter((t=>i!==t))}}off(t,i){var e;this.events[t]=null===(e=this.events[t])||void 0===e?void 0:e.filter((t=>i!==t))}destroy(){this.events={}}}const t=100/6;class VirtualScroll{constructor(i,{wheelMultiplier:e=1,touchMultiplier:s=1}){this.lastDelta={x:0,y:0},this.windowWidth=0,this.windowHeight=0,this.onTouchStart=t=>{const{clientX:i,clientY:e}=t.targetTouches?t.targetTouches[0]:t;this.touchStart.x=i,this.touchStart.y=e,this.lastDelta={x:0,y:0},this.emitter.emit("scroll",{deltaX:0,deltaY:0,event:t})},this.onTouchMove=t=>{var i,e,s,o;const{clientX:n,clientY:l}=t.targetTouches?t.targetTouches[0]:t,r=-(n-(null!==(e=null===(i=this.touchStart)||void 0===i?void 0:i.x)&&void 0!==e?e:0))*this.touchMultiplier,h=-(l-(null!==(o=null===(s=this.touchStart)||void 0===s?void 0:s.y)&&void 0!==o?o:0))*this.touchMultiplier;this.touchStart.x=n,this.touchStart.y=l,this.lastDelta={x:r,y:h},this.emitter.emit("scroll",{deltaX:r,deltaY:h,event:t})},this.onTouchEnd=t=>{this.emitter.emit("scroll",{deltaX:this.lastDelta.x,deltaY:this.lastDelta.y,event:t})},this.onWheel=i=>{let{deltaX:e,deltaY:s,deltaMode:o}=i;e*=1===o?t:2===o?this.windowWidth:1,s*=1===o?t:2===o?this.windowHeight:1,e*=this.wheelMultiplier,s*=this.wheelMultiplier,this.emitter.emit("scroll",{deltaX:e,deltaY:s,event:i})},this.onWindowResize=()=>{this.windowWidth=window.innerWidth,this.windowHeight=window.innerHeight},this.element=i,this.wheelMultiplier=e,this.touchMultiplier=s,this.touchStart={x:null,y:null},this.emitter=new Emitter,window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize(),this.element.addEventListener("wheel",this.onWheel,{passive:!1}),this.element.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.addEventListener("touchend",this.onTouchEnd,{passive:!1})}on(t,i){return this.emitter.on(t,i)}destroy(){this.emitter.destroy(),window.removeEventListener("resize",this.onWindowResize,!1),this.elemeLine truncated
|
||||
//# sourceMappingURL=lenis.min.js.map
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
(typeof navigator !== "undefined") && (function(root, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(function() {
|
||||
return factory(root);
|
||||
});
|
||||
} else if (typeof module === "object" && module.exports) {
|
||||
module.exports = factory(root);
|
||||
} else {
|
||||
root.lottie = factory(root);
|
||||
root.bodymovin = root.lottie;
|
||||
}
|
||||
}((window || {}), function(window) {
|
||||
"use strict";var svgNS="http://www.w3.org/2000/svg",locationHref="",initialDefaultFrame=-999999,subframeEnabled=!0,expressionsPlugin,isSafari=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),cachedColors={},bm_rounder=Math.round,bm_rnd,bm_pow=Math.pow,bm_sqrt=Math.sqrt,bm_abs=Math.abs,bm_floor=Math.floor,bm_max=Math.max,bm_min=Math.min,blitter=10,BMMath={};function ProjectInterface(){return{}}!function(){var t,e=["abs","acos","acosh","asin","asinh","atan","atanh","atan2","ceil","cbrt","expm1","clz32","cos","cosh","exp","floor","fround","hypot","imul","log","log1p","log2","log10","max","min","pow","random","round","sign","sin","sinh","sqrt","tan","tanh","trunc","E","LN10","LN2","LOG10E","LOG2E","PI","SQRT1_2","SQRT2"],r=e.length;for(t=0;t<r;t+=1)BMMath[e[t]]=Math[e[t]]}(),BMMath.random=Math.random,BMMath.abs=function(t){if("object"===typeof t&&t.length){var e,r=createSizedArray(t.length),i=t.length;for(e=0;e<i;e+=1)r[e]=Math.abs(t[e]);return r}return Math.abs(t)};var defaultCurveSegments=150,degToRads=Math.PI/180,roundCorner=.5519;function roundValues(t){bm_rnd=t?Math.round:function(t){return t}}function styleDiv(t){t.style.position="absolute",t.style.top=0,t.style.left=0,t.style.display="block",t.style.transformOrigin=t.style.webkitTransformOrigin="0 0",t.style.backfaceVisibility=t.style.webkitBackfaceVisibility="visible",t.style.transformStyle=t.style.webkitTransformStyle=t.style.mozTransformStyle="preserve-3d"}function BMEnterFrameEvent(t,e,r,i){this.type=t,this.currentTime=e,this.totalTime=r,this.direction=i<0?-1:1}function BMCompleteEvent(t,e){this.type=t,this.direction=e<0?-1:1}function BMCompleteLoopEvent(t,e,r,i){this.type=t,this.currentLoop=r,this.totalLoops=e,this.direction=i<0?-1:1}function BMSegmentStartEvent(t,e,r){this.type=t,this.firstFrame=e,this.totalFrames=r}function BMDestroyEvent(t,e){this.type=t,this.target=e}function BMRenderFrameErrorEvent(t,e){this.type="renderFrameError",this.nativeError=t,this.currentTime=e}function BMConfigErrorEvent(t){this.type="configError",this.nativeError=t}function BMAnimationConfigErrorEvent(t,e){this.type=t,this.nativeError=e,this.currentTime=currentTime}roundValues(!1);var createElementID=(G=0,function(){return"__lottie_element_"+ ++G}),G;function HSVtoRGB(t,e,r){var i,s,a,n,o,h,l,p;switch(h=r*(1-e),l=r*(1-(o=6*t-(n=Math.floor(6*t)))*e),p=r*(1-(1-o)*e),n%6){case 0:i=r,s=p,a=h;break;case 1:i=l,s=r,a=h;break;case 2:i=h,s=r,a=p;break;case 3:i=h,s=l,a=r;break;case 4:i=p,s=h,a=r;break;case 5:i=r,s=h,a=l}return[i,s,a]}function RGBtoHSV(t,e,r){var i,s=Math.max(t,e,r),a=Math.min(t,e,r),n=s-a,o=0===s?0:n/s,h=s/255;switch(s){case a:i=0;break;case t:i=e-r+n*(e<r?6:0),i/=6*n;break;case e:i=r-t+2*n,i/=6*n;break;case r:i=t-e+4*n,i/=6*n}return[i,o,h]}function addSaturationToRGB(t,e){var r=RGBtoHSV(255*t[0],255*t[1],255*t[2]);return r[1]+=e,1<r[1]?r[1]=1:r[1]<=0&&(r[1]=0),HSVtoRGB(r[0],r[1],r[2])}function addBrightnessToRGB(t,e){var r=RGBtoHSV(255*t[0],255*t[1],255*t[2]);return r[2]+=e,1<r[2]?r[2]=1:r[2]<0&&(r[2]=0),HSVtoRGB(r[0],r[1],r[2])}function addHueToRGB(t,e){var r=RGBtoHSV(255*t[0],255*t[1],255*t[2]);return r[0]+=e/360,1<r[0]?r[0]-=1:r[0]<0&&(r[0]+=1),HSVtoRGB(r[0],r[1],r[2])}var rgbToHex=function(){var t,e,i=[];for(t=0;t<256;t+=1)e=t.toString(16),i[t]=1==e.length?"0"+e:e;return function(t,e,r){return t<0&&(t=0),e<0&&(e=0),r<0&&(r=0),"#"+i[t]+i[e]+i[r]}}();function BaseEvent(){}BaseEvent.prototype={triggerEvent:function(t,e){if(this._cbs[t])for(var r=this._cbs[t].length,i=0;i<r;i++)this._cbs[t][i](e)},addEventListener:function(t,e){return this._cbs[t]||(this._cbs[t]=[]),this._cbs[t].push(e),function(){this.removeEventListener(t,e)}.bind(this)},removeEventListener:function(t,e){if(e){if(this._cbs[t]){for(var r=0,i=this._cbs[t].length;r<i;)this._cbs[t][r]===e&&(this._cbs[t].splice(r,1),r-=1,i-=1),r+=1;this._cbs[t].length||(this._cbs[t]=null)}}else this._cbs[t]=null}};var createTypedArray="function"==typeof Uint8ClampedArray&&"function"==typeof Float32Array?function(t,e){return"float32"===t?new Float32Array(e):"int16"===t?new Int16Array(e):"uint8c"===t?new Uint8ClampedArray(e):void 0}:function(t,e){var r,i=0,s=[];switch(t){case"int16":case"uint8c":r=1;break;default:r=1.1}for(i=0;i<e;i+=1)s.push(r);return s};function createSizedArray(t){return Array.apply(null,{length:t})}function createNS(t){return document.createElementNS(svgNS,t)}function createTag(t){return document.createElement(t)}function DynamicPropertyContainer(){}DynamicPropertyContainer.prototype={addDynamicProperty:function(t){-1===this.dynamicProperties.indexOf(t)&&(this.dynamicProperties.push(t),this.container.addDynamicProperty(this),this._isAnimated=!0)},iterateDynamicProperties:function(){this._mdf=!1;var t,e=this.dynamicProperties.length;for(t=0;t<e;t+=1)this.dynamicProperties[t].getValue(),this.dynamicProperties[t]._mdf&&(this._mdf=!0)},initDynamicPropertyContainer:function(t){this.container=t,this.dynamicProperties=[],this._mdf=!1,this._isAnimated=!1}};var getBlendMode=(Pa={0:"source-ovLine truncated
|
||||
return lottie;
|
||||
}));
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
/*!
|
||||
* ScrollToPlugin 3.12.5
|
||||
* https://gsap.com
|
||||
*
|
||||
* @license Copyright 2024, GreenSock. All rights reserved.
|
||||
* Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership.
|
||||
* @author: Jack Doyle, jack@greensock.com
|
||||
*/
|
||||
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).window=e.window||{})}(this,function(e){"use strict";function l(){return"undefined"!=typeof window}function m(){return f||l()&&(f=window.gsap)&&f.registerPlugin&&f}function n(e){return"string"==typeof e}function o(e){return"function"==typeof e}function p(e,t){var o="x"===t?"Width":"Height",n="scroll"+o,r="client"+o;return e===T||e===i||e===c?Math.max(i[n],c[n])-(T["inner"+o]||i[r]||c[r]):e[n]-e["offset"+o]}function q(e,t){var o="scroll"+("x"===t?"Left":"Top");return e===T&&(null!=e.pageXOffset?o="page"+t.toUpperCase()+"Offset":e=null!=i[o]?i:c),function(){return e[o]}}function s(e,t){if(!(e=y(e)[0])||!e.getBoundingClientRect)return console.warn("scrollTo target doesn't exist. Using 0")||{x:0,y:0};var o=e.getBoundingClientRect(),n=!t||t===T||t===c,r=n?{top:i.clientTop-(T.pageYOffset||i.scrollTop||c.scrollTop||0),left:i.clientLeft-(T.pageXOffset||i.scrollLeft||c.scrollLeft||0)}:t.getBoundingClientRect(),l={x:o.left-r.left,y:o.top-r.top};return!n&&t&&(l.x+=q(t,"x")(),l.y+=q(t,"y")()),l}function t(e,t,o,r,l){return isNaN(e)||"object"==typeof e?n(e)&&"="===e.charAt(1)?parseFloat(e.substr(2))*("-"===e.charAt(0)?-1:1)+r-l:"max"===e?p(t,o)-l:Math.min(p(t,o),s(e,t)[o]-l):parseFloat(e)-l}function u(){f=m(),l()&&f&&"undefined"!=typeof document&&document.body&&(T=window,c=document.body,i=document.documentElement,y=f.utils.toArray,f.config({autoKillThreshold:7}),h=f.config(),a=1)}var f,a,T,i,c,y,h,v,r={version:"3.12.5",name:"scrollTo",rawVars:1,register:function register(e){f=e,u()},init:function init(e,r,l,s,i){a||u();var p=this,c=f.getProperty(e,"scrollSnapType");p.isWin=e===T,p.target=e,p.tween=l,r=function _clean(e,t,r,l){if(o(e)&&(e=e(t,r,l)),"object"!=typeof e)return n(e)&&"max"!==e&&"="!==e.charAt(1)?{x:e,y:e}:{y:e};if(e.nodeType)return{y:e,x:e};var s,i={};for(s in e)i[s]="onAutoKill"!==s&&o(e[s])?e[s](t,r,l):e[s];return i}(r,s,e,i),p.vars=r,p.autoKill=!!r.autoKill,p.getX=q(e,"x"),p.getY=q(e,"y"),p.x=p.xPrev=p.getX(),p.y=p.yPrev=p.getY(),v=v||f.core.globals().ScrollTrigger,"smooth"===f.getProperty(e,"scrollBehavior")&&f.set(e,{scrollBehavior:"auto"}),c&&"none"!==c&&(p.snap=1,p.snapInline=e.style.scrollSnapType,e.style.scrollSnapType="none"),null!=r.x?(p.add(p,"x",p.x,t(r.x,e,"x",p.x,r.offsetX||0),s,i),p._props.push("scrollTo_x")):p.skipX=1,null!=r.y?(p.add(p,"y",p.y,t(r.y,e,"y",p.y,r.offsetY||0),s,i),p._props.push("scrollTo_y")):p.skipY=1},render:function render(e,t){for(var o,n,r,l,s,i=t._pt,c=t.target,u=t.tween,f=t.autoKill,a=t.xPrev,y=t.yPrev,d=t.isWin,g=t.snap,x=t.snapInline;i;)i.r(e,i.d),i=i._next;o=d||!t.skipX?t.getX():a,r=(n=d||!t.skipY?t.getY():y)-y,l=o-a,s=h.autoKillThreshold,t.x<0&&(t.x=0),t.y<0&&(t.y=0),f&&(!t.skipX&&(s<l||l<-s)&&o<p(c,"x")&&(t.skipX=1),!t.skipY&&(s<r||r<-s)&&n<p(c,"y")&&(t.skipY=1),t.skipX&&t.skipY&&(u.kill(),t.vars.onAutoKill&&t.vars.onAutoKill.apply(u,t.vars.onAutoKillParams||[]))),d?T.scrollTo(t.skipX?o:t.x,t.skipY?n:t.y):(t.skipY||(c.scrollTop=t.y),t.skipX||(c.scrollLeft=t.x)),!g||1!==e&&0!==e||(n=c.scrollTop,o=c.scrollLeft,x?c.style.scrollSnapType=x:c.style.removeProperty("scroll-snap-type"),c.scrollTop=n+1,c.scrollLeft=o+1,c.scrollTop=n,c.scrollLeft=o),t.xPrev=t.x,t.yPrev=t.y,v&&v.update()},kill:function kill(e){var t="scrollTo"===e,o=this._props.indexOf(e);return!t&&"scrollTo_x"!==e||(this.skipX=1),!t&&"scrollTo_y"!==e||(this.skipY=1),-1<o&&this._props.splice(o,1),!this._props.length}};r.max=p,r.getOffset=s,r.buildGetter=q,m()&&f.registerPlugin(r),e.ScrollToPlugin=r,e.default=r;if (typeof(window)==="undefined"||window!==e){Object.defineProperty(e,"__esModule",{value:!0})} else {delete e.default}});
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
/*!
|
||||
* ScrollTrigger 3.12.5
|
||||
* https://gsap.com
|
||||
*
|
||||
* @license Copyright 2024, GreenSock. All rights reserved.
|
||||
* Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership.
|
||||
* @author: Jack Doyle, jack@greensock.com
|
||||
*/
|
||||
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).window=e.window||{})}(this,function(e){"use strict";function _defineProperties(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function r(){return Ce||"undefined"!=typeof window&&(Ce=window.gsap)&&Ce.registerPlugin&&Ce}function z(e,t){return~Le.indexOf(e)&&Le[Le.indexOf(e)+1][t]}function A(e){return!!~t.indexOf(e)}function B(e,t,r,n,o){return e.addEventListener(t,r,{passive:!1!==n,capture:!!o})}function C(e,t,r,n){return e.removeEventListener(t,r,!!n)}function F(){return De&&De.isPressed||Ie.cache++}function G(r,n){function dd(e){if(e||0===e){o&&(Se.history.scrollRestoration="manual");var t=De&&De.isPressed;e=dd.v=Math.round(e)||(De&&De.iOS?1:0),r(e),dd.cacheID=Ie.cache,t&&i("ss",e)}else(n||Ie.cache!==dd.cacheID||i("ref"))&&(dd.cacheID=Ie.cache,dd.v=r());return dd.v+dd.offset}return dd.offset=0,r&&dd}function J(e,t){return(t&&t._ctx&&t._ctx.selector||Ce.utils.toArray)(e)[0]||("string"==typeof e&&!1!==Ce.config().nullTargetWarn?console.warn("Element not found:",e):null)}function K(t,e){var r=e.s,n=e.sc;A(t)&&(t=ke.scrollingElement||Pe);var o=Ie.indexOf(t),i=n===Fe.sc?1:2;~o||(o=Ie.push(t)-1),Ie[o+i]||B(t,"scroll",F);var a=Ie[o+i],s=a||(Ie[o+i]=G(z(t,r),!0)||(A(t)?n:G(function(e){return arguments.length?t[r]=e:t[r]})));return s.target=t,a||(s.smooth="smooth"===Ce.getProperty(t,"scrollBehavior")),s}function L(e,t,o){function Cd(e,t){var r=ze();t||n<r-s?(a=i,i=e,l=s,s=r):o?i+=e:i=a+(e-a)/(r-l)*(s-l)}var i=e,a=e,s=ze(),l=s,n=t||50,c=Math.max(500,3*n);return{update:Cd,reset:function reset(){a=i=o?0:i,l=s=0},getVelocity:function getVelocity(e){var t=l,r=a,n=ze();return!e&&0!==e||e===i||Cd(e),s===l||c<n-l?0:(i+(o?r:-r))/((o?n:s)-t)*1e3}}}function M(e,t){return t&&!e._gsapAllow&&e.preventDefault(),e.changedTouches?e.changedTouches[0]:e}function N(e){var t=Math.max.apply(Math,e),r=Math.min.apply(Math,e);return Math.abs(t)>=Math.abs(r)?t:r}function O(){(Ae=Ce.core.globals().ScrollTrigger)&&Ae.core&&function _integrate(){var e=Ae.core,r=e.bridge||{},t=e._scrollers,n=e._proxies;t.push.apply(t,Ie),n.push.apply(n,Le),Ie=t,Le=n,i=function _bridge(e,t){return r[e](t)}}()}function P(e){return Ce=e||r(),!Te&&Ce&&"undefined"!=typeof document&&document.body&&(Se=window,Pe=(ke=document).documentElement,Me=ke.body,t=[Se,ke,Pe,Me],Ce.utils.clamp,Be=Ce.core.context||function(){},Oe="onpointerenter"in Me?"pointer":"mouse",Ee=k.isTouch=Se.matchMedia&&Se.matchMedia("(hover: none), (pointer: coarse)").matches?1:"ontouchstart"in Se||0<navigator.maxTouchPoints||0<navigator.msMaxTouchPoints?2:0,Re=k.eventTypes=("ontouchstart"in Pe?"touchstart,touchmove,touchcancel,touchend":"onpointerdown"in Pe?"pointerdown,pointermove,pointercancel,pointerup":"mousedown,mousemove,mouseup,mouseup").split(","),setTimeout(function(){return o=0},500),O(),Te=1),Te}var Ce,Te,Se,ke,Pe,Me,Ee,Oe,Ae,t,De,Re,Be,o=1,qe=[],Ie=[],Le=[],ze=Date.now,i=function _bridge(e,t){return t},n="scrollLeft",a="scrollTop",Ye={s:n,p:"left",p2:"Left",os:"right",os2:"Right",d:"width",d2:"Width",a:"x",sc:G(function(e){return arguments.length?Se.scrollTo(e,Fe.sc()):Se.pageXOffset||ke[n]||Pe[n]||Me[n]||0})},Fe={s:a,p:"top",p2:"Top",os:"bottom",os2:"Bottom",d:"height",d2:"Height",a:"y",op:Ye,sc:G(function(e){return arguments.length?Se.scrollTo(Ye.sc(),e):Se.pageYOffset||ke[a]||Pe[a]||Me[a]||0})};Ye.op=Fe,Ie.cache=0;var k=(Observer.prototype.init=function init(e){Te||P(Ce)||console.warn("Please gsap.registerPlugin(Observer)"),Ae||O();var o=e.tolerance,a=e.dragMinimum,t=e.type,i=e.target,r=e.lineHeight,n=e.debounce,s=e.preventDefault,l=e.onStop,c=e.onStopDelay,u=e.ignore,f=e.wheelSpeed,d=e.event,p=e.onDragStart,g=e.onDragEnd,h=e.onDrag,v=e.onPress,b=e.onRelease,m=e.onRight,y=e.onLeft,x=e.onUp,w=e.onDown,_=e.onChangeX,T=e.onChangeY,S=e.onChange,k=e.onToggleX,E=e.onToggleY,D=e.onHover,R=e.onHoverEnd,q=e.onMove,I=e.ignoreCheck,z=e.isNormalizer,Y=e.onGestureStart,H=e.onGestureEnd,X=e.onWheel,W=e.onEnable,V=e.onDisable,U=e.onClick,j=e.scrollSpeed,G=e.capture,Q=e.allowClicks,Z=e.lockAxis,$=e.onLockAxis;function cf(){return xe=ze()}function df(e,t){return(se.event=e)&&u&&~u.indexOf(e.target)||t&&he&&"touch"!==e.pointerType||I&&I(e,t)}function ff(){var e=se.deltaX=N(me),t=se.deltaY=N(ye),r=Math.abs(e)>=o,n=Math.abs(t)>=o;S&&(r||n)&&S(se,e,t,me,ye),r&&(m&&0<se.deltaX&&m(se),y&&se.deltaX<0&&y(se),_&&_(se),k&&se.deltaX<0!=le<0&&k(se),le=se.deltaX,me[0]=me[1]=me[2]=0),n&&(w&&0<se.deltaY&&w(se),x&&se.deltaY<0&&x(se),T&&T(se),E&&se.deltaY<0!=ce<0&&E(se),ce=se.deltaY,ye[0]=ye[1]=ye[2]=0),(ne||re)&&(q&&q(se),re&&(h(se),re=!1),ne=!1),ie&&!(ie=!1)&&$&&$(se),oe&&(X(se),oe=!1),ee=0}function gf(e,t,r){me[r]+=e,ye[r]+=t,se._vx.update(e),se._vy.update(t),n?ee=ee||requestAnimationFrame(ff):ff()}function hf(e,t){Z&&!ae&&(se.axis=ae=Math.abs(e)>Math.abs(t)?"xLine truncated
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Swiper 11.2.5
|
||||
* Most modern mobile touch slider and framework with hardware accelerated transitions
|
||||
* https://swiperjs.com
|
||||
*
|
||||
* Copyright 2014-2025 Vladimir Kharlampidi
|
||||
*
|
||||
* Released under the MIT License
|
||||
*
|
||||
* Released on: March 3, 2025
|
||||
*/
|
||||
|
||||
var Swiper=function(){"use strict";function e(e){return null!==e&&"object"==typeof e&&"constructor"in e&&e.constructor===Object}function t(s,a){void 0===s&&(s={}),void 0===a&&(a={});const i=["__proto__","constructor","prototype"];Object.keys(a).filter((e=>i.indexOf(e)<0)).forEach((i=>{void 0===s[i]?s[i]=a[i]:e(a[i])&&e(s[i])&&Object.keys(a[i]).length>0&&t(s[i],a[i])}))}const s={body:{},addEventListener(){},removeEventListener(){},activeElement:{blur(){},nodeName:""},querySelector:()=>null,querySelectorAll:()=>[],getElementById:()=>null,createEvent:()=>({initEvent(){}}),createElement:()=>({children:[],childNodes:[],style:{},setAttribute(){},getElementsByTagName:()=>[]}),createElementNS:()=>({}),importNode:()=>null,location:{hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",protocol:"",search:""}};function a(){const e="undefined"!=typeof document?document:{};return t(e,s),e}const i={document:s,navigator:{userAgent:""},location:{hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",protocol:"",search:""},history:{replaceState(){},pushState(){},go(){},back(){}},CustomEvent:function(){return this},addEventListener(){},removeEventListener(){},getComputedStyle:()=>({getPropertyValue:()=>""}),Image(){},Date(){},screen:{},setTimeout(){},clearTimeout(){},matchMedia:()=>({}),requestAnimationFrame:e=>"undefined"==typeof setTimeout?(e(),null):setTimeout(e,0),cancelAnimationFrame(e){"undefined"!=typeof setTimeout&&clearTimeout(e)}};function r(){const e="undefined"!=typeof window?window:{};return t(e,i),e}function n(e){return void 0===e&&(e=""),e.trim().split(" ").filter((e=>!!e.trim()))}function l(e,t){return void 0===t&&(t=0),setTimeout(e,t)}function o(){return Date.now()}function d(e,t){void 0===t&&(t="x");const s=r();let a,i,n;const l=function(e){const t=r();let s;return t.getComputedStyle&&(s=t.getComputedStyle(e,null)),!s&&e.currentStyle&&(s=e.currentStyle),s||(s=e.style),s}(e);return s.WebKitCSSMatrix?(i=l.transform||l.webkitTransform,i.split(",").length>6&&(i=i.split(", ").map((e=>e.replace(",","."))).join(", ")),n=new s.WebKitCSSMatrix("none"===i?"":i)):(n=l.MozTransform||l.OTransform||l.MsTransform||l.msTransform||l.transform||l.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),a=n.toString().split(",")),"x"===t&&(i=s.WebKitCSSMatrix?n.m41:16===a.length?parseFloat(a[12]):parseFloat(a[4])),"y"===t&&(i=s.WebKitCSSMatrix?n.m42:16===a.length?parseFloat(a[13]):parseFloat(a[5])),i||0}function c(e){return"object"==typeof e&&null!==e&&e.constructor&&"Object"===Object.prototype.toString.call(e).slice(8,-1)}function p(){const e=Object(arguments.length<=0?void 0:arguments[0]),t=["__proto__","constructor","prototype"];for(let a=1;a<arguments.length;a+=1){const i=a<0||arguments.length<=a?void 0:arguments[a];if(null!=i&&(s=i,!("undefined"!=typeof window&&void 0!==window.HTMLElement?s instanceof HTMLElement:s&&(1===s.nodeType||11===s.nodeType)))){const s=Object.keys(Object(i)).filter((e=>t.indexOf(e)<0));for(let t=0,a=s.length;t<a;t+=1){const a=s[t],r=Object.getOwnPropertyDescriptor(i,a);void 0!==r&&r.enumerable&&(c(e[a])&&c(i[a])?i[a].__swiper__?e[a]=i[a]:p(e[a],i[a]):!c(e[a])&&c(i[a])?(e[a]={},i[a].__swiper__?e[a]=i[a]:p(e[a],i[a])):e[a]=i[a])}}}var s;return e}function u(e,t,s){e.style.setProperty(t,s)}function m(e){let{swiper:t,targetPosition:s,side:a}=e;const i=r(),n=-t.translate;let l,o=null;const d=t.params.speed;t.wrapperEl.style.scrollSnapType="none",i.cancelAnimationFrame(t.cssModeFrameID);const c=s>n?"next":"prev",p=(e,t)=>"next"===c&&e>=t||"prev"===c&&e<=t,u=()=>{l=(new Date).getTime(),null===o&&(o=l);const e=Math.max(Math.min((l-o)/d,1),0),r=.5-Math.cos(e*Math.PI)/2;let c=n+r*(s-n);if(p(c,s)&&(c=s),t.wrapperEl.scrollTo({[a]:c}),p(c,s))return t.wrapperEl.style.overflow="hidden",t.wrapperEl.style.scrollSnapType="",setTimeout((()=>{t.wrapperEl.style.overflow="",t.wrapperEl.scrollTo({[a]:c})})),void i.cancelAnimationFrame(t.cssModeFrameID);t.cssModeFrameID=i.requestAnimationFrame(u)};u()}function h(e){return e.querySelector(".swiper-slide-transform")||e.shadowRoot&&e.shadowRoot.querySelector(".swiper-slide-transform")||e}function f(e,t){void 0===t&&(t="");const s=r(),a=[...e.children];return s.HTMLSlotElement&&e instanceof HTMLSlotElement&&a.push(...e.assignedElements()),t?a.filter((e=>e.matches(t))):a}function g(e){try{return void console.warn(e)}catch(e){}}function v(e,t){void 0===t&&(t=[]);const s=document.createElement(e);return s.classList.add(...Array.isArray(t)?t:n(t)),s}function w(e){const t=r(),s=a(),i=e.getBoundingClientRect(),n=s.body,l=e.clientTop||n.clientTop||0,o=e.clientLeft||n.clientLeft||0,d=e===t?t.scrollY:e.scrollTop,c=e===t?t.scrollX:e.scrollLeft;return{top:i.top+d-l,left:i.left+c-o}}function b(e,t){return r().getComputedStyle(e,null).getPropertyValue(t)}function y(e){let t,s=e;if(s){for(t=0;null!==(s=s.previousSibling);)1===s.nodeType&&(t+=1);return t}}function E(e,t){const s=[];let a=e.parentElement;for(;a;)t?a.matches(t)&&s.push(a):s.push(a),a=a.parentElement;rLine truncated
|
||||
//# sourceMappingURL=swiper-bundle.min.js.map
|
||||
@@ -0,0 +1,36 @@
|
||||
const form = document.querySelector('.tab-content.id form')
|
||||
|
||||
if (form) {
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const id = document.getElementById('login_id').value.trim()
|
||||
const pw = document.getElementById('login_password').value.trim()
|
||||
|
||||
if (!id || !pw) {
|
||||
alert('아이디와 비밀번호를 입력하세요.')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch('/kngil/bbs/login.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ id, pw })
|
||||
})
|
||||
console.log('login.js loaded')
|
||||
const json = await res.json()
|
||||
|
||||
if (json.status === 'success') {
|
||||
console.log('LOGIN OK, reload')
|
||||
document.getElementById('pop_login').style.display = 'none'
|
||||
location.reload()
|
||||
} else {
|
||||
alert(json.message)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
alert('로그인 중 오류가 발생했습니다.')
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
const smsBtn = document.getElementById('sms_button');
|
||||
const phoneInp = document.getElementById('login_phone');
|
||||
|
||||
if (!smsBtn || !phoneInp) return;
|
||||
|
||||
const form = smsBtn.closest('form');
|
||||
const infoBox = form.querySelector('.info-box');
|
||||
const timerEl = form.querySelector('.timer');
|
||||
|
||||
let pollTimer = null;
|
||||
let timerIntv = null;
|
||||
let remain = 180; // 3분
|
||||
|
||||
function startTimer() {
|
||||
clearInterval(timerIntv);
|
||||
remain = 180;
|
||||
|
||||
timerEl.classList.remove('d-none');
|
||||
updateTimer();
|
||||
|
||||
timerIntv = setInterval(() => {
|
||||
remain--;
|
||||
updateTimer();
|
||||
|
||||
if (remain <= 0) {
|
||||
clearInterval(timerIntv);
|
||||
smsBtn.disabled = false;
|
||||
timerEl.textContent = '00:00';
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function updateTimer() {
|
||||
const m = String(Math.floor(remain / 60)).padStart(2, '0');
|
||||
const s = String(remain % 60).padStart(2, '0');
|
||||
timerEl.textContent = `${m}:${s}`;
|
||||
}
|
||||
|
||||
smsBtn.addEventListener('click', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const phone = phoneInp.value.trim();
|
||||
if (!phone) {
|
||||
alert('휴대폰 번호를 입력하세요.');
|
||||
phoneInp.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
smsBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const res = await fetch('/kngil/bbs/login_sms.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
mode: 'request',
|
||||
phone
|
||||
})
|
||||
});
|
||||
|
||||
const json = await res.json();
|
||||
|
||||
if (json.status !== 'success') {
|
||||
alert(json.message || '인증 링크 요청 실패');
|
||||
smsBtn.disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// UI 처리
|
||||
infoBox.classList.remove('d-none');
|
||||
startTimer();
|
||||
startPolling();
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
alert('인증 요청 중 오류');
|
||||
smsBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
function startPolling() {
|
||||
clearInterval(pollTimer);
|
||||
|
||||
pollTimer = setInterval(async () => {
|
||||
try {
|
||||
const res = await fetch('/kngil/bbs/login_sms.php?mode=status');
|
||||
const json = await res.json();
|
||||
|
||||
if (json.status === 'success') {
|
||||
clearInterval(pollTimer);
|
||||
clearInterval(timerIntv);
|
||||
location.reload();
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,457 @@
|
||||
/**
|
||||
* mypage.js
|
||||
* 마이페이지 관련 모든 모달 흐름 관리
|
||||
*/
|
||||
|
||||
/* =========================
|
||||
공통 유틸
|
||||
========================= */
|
||||
function show(id) {
|
||||
const el = document.getElementById(id)
|
||||
if (el) el.style.display = 'block'
|
||||
}
|
||||
|
||||
function hide(id) {
|
||||
const el = document.getElementById(id)
|
||||
if (el) el.style.display = 'none'
|
||||
}
|
||||
|
||||
/* =========================
|
||||
마이페이지 1단계 (비밀번호 인증)
|
||||
- 헤더에서 호출
|
||||
========================= */
|
||||
window.mypage01 = function () {
|
||||
if (!window.IS_LOGIN) {
|
||||
if (typeof window.login === 'function') {
|
||||
window.login()
|
||||
}
|
||||
return
|
||||
}
|
||||
show('pop_mypage01')
|
||||
}
|
||||
|
||||
/* =========================
|
||||
마이페이지 2단계 (실제 마이페이지)
|
||||
========================= */
|
||||
let currentPage = 1
|
||||
|
||||
window.mypage02 = async function (page = 1) {
|
||||
currentPage = page
|
||||
hide('pop_mypage01')
|
||||
|
||||
try {
|
||||
const res = await fetch(`/kngil/bbs/mypage02.php?page=${page}`)
|
||||
const json = await res.json()
|
||||
|
||||
if (json.status !== 'success') {
|
||||
alert(json.message || '데이터 로드 실패')
|
||||
return
|
||||
}
|
||||
|
||||
renderMyPage02(json.user)
|
||||
renderMyPageHistory(json.history)
|
||||
renderPagination(json.pagination)
|
||||
|
||||
show('pop_mypage02')
|
||||
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
alert('마이페이지 로딩 오류')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function renderMyPage02(data) {
|
||||
|
||||
// 이름 / ID
|
||||
document.getElementById('mp_user_nm').textContent = data.user_nm
|
||||
document.getElementById('mp_user_id').textContent = `(${data.user_id})`
|
||||
|
||||
// 연락처
|
||||
document.getElementById('mp_tel').textContent = data.tel_no || '-'
|
||||
document.getElementById('mp_email').textContent = data.email || '-'
|
||||
|
||||
// 회사 정보
|
||||
document.getElementById('mp_co_nm').textContent = data.co_nm || '-'
|
||||
document.getElementById('mp_dept_nm').textContent = data.dept_nm || '-'
|
||||
|
||||
// 사용량
|
||||
document.getElementById('mp_tot_use').textContent =
|
||||
Number(data.tot_use || 0).toLocaleString()
|
||||
|
||||
document.getElementById('mp_year_use').textContent =
|
||||
Number(data.year_use || 0).toLocaleString()
|
||||
}
|
||||
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return '-'
|
||||
const d = new Date(dateStr)
|
||||
const yy = String(d.getFullYear()).slice(2)
|
||||
const mm = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const dd = String(d.getDate()).padStart(2, '0')
|
||||
return `${yy}-${mm}-${dd}`
|
||||
}
|
||||
|
||||
function renderMyPageHistory(list) {
|
||||
const tbody = document.getElementById('mp_history_body')
|
||||
tbody.innerHTML = ''
|
||||
|
||||
if (!list.length) {
|
||||
tbody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="4" style="text-align:center;">사용 이력이 없습니다.</td>
|
||||
</tr>
|
||||
`
|
||||
return
|
||||
}
|
||||
|
||||
list.forEach((row, idx) => {
|
||||
const tr = document.createElement('tr')
|
||||
tr.innerHTML = `
|
||||
<td>${(currentPage - 1) * 5 + idx + 1}</td>
|
||||
<td class="tit">${row.ser_bc}</td>
|
||||
<td>${formatDate(row.use_dt)}</td>
|
||||
<td><em>${Number(row.use_area).toLocaleString()}</em></td>
|
||||
`
|
||||
tbody.appendChild(tr)
|
||||
})
|
||||
}
|
||||
|
||||
function renderPagination(p) {
|
||||
|
||||
const ul = document.querySelector('.pagination-list')
|
||||
if (!ul) return
|
||||
|
||||
ul.innerHTML = ''
|
||||
|
||||
for (let i = 1; i <= p.totalPages; i++) {
|
||||
const li = document.createElement('li')
|
||||
li.className = (i === p.page) ? 'on' : ''
|
||||
|
||||
const a = document.createElement('a')
|
||||
a.href = '#'
|
||||
a.textContent = i
|
||||
a.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
mypage02(i)
|
||||
})
|
||||
|
||||
li.appendChild(a)
|
||||
ul.appendChild(li)
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================
|
||||
마이페이지 3단계 (마이페이지 정보수정)
|
||||
========================= */
|
||||
|
||||
window.mypage03 = async function () {
|
||||
|
||||
// ✅ 비밀번호 변경 영역 초기 상태 강제
|
||||
const rowCurrent = document.getElementById('row-pw-current')
|
||||
const rowNew = document.getElementById('row-pw-new')
|
||||
const rowView = document.querySelector('.btn-sm.change')?.closest('tr')
|
||||
|
||||
rowCurrent && (rowCurrent.style.display = 'none')
|
||||
rowNew && (rowNew.style.display = 'none')
|
||||
rowView && (rowView.style.display = '')
|
||||
|
||||
try {
|
||||
const res = await fetch('/kngil/bbs/mypage03.php')
|
||||
const json = await res.json()
|
||||
|
||||
if (json.status !== 'success') {
|
||||
alert(json.message)
|
||||
return
|
||||
}
|
||||
|
||||
fillMyPage03(json.data)
|
||||
bindPasswordValidation()
|
||||
hide('pop_mypage02')
|
||||
show('pop_mypage03')
|
||||
bindPasswordChangeUI()
|
||||
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
alert('회원정보 조회 오류')
|
||||
}
|
||||
};
|
||||
|
||||
;(function bindMyPage03Save() {
|
||||
|
||||
const popup = document.getElementById('pop_mypage03')
|
||||
if (!popup) return
|
||||
|
||||
const btnSave = popup.querySelector('.btn-full')
|
||||
|
||||
btnSave.addEventListener('click', async () => {
|
||||
|
||||
const password = popup.querySelector('#new_pw')?.value.trim() || ''
|
||||
|
||||
const emailId = popup.querySelector('.e-id')?.value.trim()
|
||||
const domainSel = popup.querySelector('#domain_list')
|
||||
const customDomain = popup.querySelector('#custom_domain')
|
||||
|
||||
let email = ''
|
||||
if (emailId) {
|
||||
const domain =
|
||||
domainSel.value === 'type'
|
||||
? customDomain.value.trim()
|
||||
: domainSel.options[domainSel.selectedIndex].text
|
||||
email = `${emailId}@${domain}`
|
||||
}
|
||||
|
||||
const telNo = popup.querySelector('#user_phone')?.value.trim()
|
||||
const deptNm = popup.querySelector('#department_name')?.value.trim()
|
||||
|
||||
try {
|
||||
const res = await fetch('/kngil/bbs/mypage03.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
password,
|
||||
email,
|
||||
tel_no: telNo,
|
||||
dept_nm: deptNm
|
||||
})
|
||||
})
|
||||
|
||||
const json = await res.json()
|
||||
|
||||
if (json.status === 'success') {
|
||||
alert('정보가 수정되었습니다.')
|
||||
hide('pop_mypage03')
|
||||
mypage02()
|
||||
} else {
|
||||
alert(json.message)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
alert('저장 중 오류 발생')
|
||||
}
|
||||
})
|
||||
|
||||
})();
|
||||
|
||||
|
||||
function fillMyPage03(data) {
|
||||
|
||||
const popup = document.getElementById('pop_mypage03')
|
||||
if (!popup) return
|
||||
|
||||
/* =========================
|
||||
아이디
|
||||
========================= */
|
||||
const idInput = popup.querySelector('input[readonly]')
|
||||
if (idInput) idInput.value = data.user_id || ''
|
||||
|
||||
/* =========================
|
||||
이름
|
||||
========================= */
|
||||
const nameInput = popup.querySelector('input[placeholder="이지빔"]')
|
||||
if (nameInput) nameInput.value = data.user_nm || ''
|
||||
|
||||
/* =========================
|
||||
이메일
|
||||
========================= */
|
||||
if (data.email) {
|
||||
const [emailId, domain] = data.email.split('@')
|
||||
|
||||
const emailInput = popup.querySelector('.e-id')
|
||||
const domainList = popup.querySelector('#domain_list')
|
||||
const customDomain = popup.querySelector('#custom_domain')
|
||||
|
||||
if (emailInput) emailInput.value = emailId
|
||||
|
||||
// 도메인 목록에 있으면 선택
|
||||
const option = [...domainList.options].find(opt => opt.text === domain)
|
||||
|
||||
if (option) {
|
||||
domainList.value = option.value
|
||||
customDomain.classList.add('d-none')
|
||||
customDomain.value = ''
|
||||
} else {
|
||||
domainList.value = 'type'
|
||||
customDomain.classList.remove('d-none')
|
||||
customDomain.value = domain
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================
|
||||
부서명
|
||||
========================= */
|
||||
const deptInput = popup.querySelector('#department_name')
|
||||
if (deptInput) deptInput.value = data.dept_nm || ''
|
||||
|
||||
/* =========================
|
||||
휴대폰 (표시만)
|
||||
========================= */
|
||||
const phoneInput = popup.querySelector('#user_phone')
|
||||
if (phoneInput) phoneInput.value = data.tel_no || ''
|
||||
}
|
||||
|
||||
|
||||
/* =========================
|
||||
비밀번호 재인증 처리
|
||||
========================= */
|
||||
;(function bindPasswordVerify() {
|
||||
|
||||
const popup = document.getElementById('pop_mypage01')
|
||||
if (!popup) return
|
||||
|
||||
const form = popup.querySelector('.tab-content.id form')
|
||||
if (!form) return
|
||||
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const pwInput = popup.querySelector('#login_password')
|
||||
const pw = pwInput?.value.trim()
|
||||
|
||||
if (!pw) {
|
||||
alert('비밀번호를 입력하세요.')
|
||||
pwInput?.focus()
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch('/kngil/bbs/mypage01.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ pw })
|
||||
})
|
||||
|
||||
const json = await res.json()
|
||||
|
||||
if (json.status === 'success') {
|
||||
pwInput.value = ''
|
||||
window.mypage02()
|
||||
} else {
|
||||
alert(json.message || '비밀번호가 올바르지 않습니다.')
|
||||
pwInput.focus()
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('[mypage verify error]', err)
|
||||
alert('인증 중 오류가 발생했습니다.')
|
||||
}
|
||||
})
|
||||
|
||||
})(); // ✅ IIFE 종료
|
||||
|
||||
/* =========================
|
||||
공통 닫기
|
||||
========================= */
|
||||
window.closeMyPage = function () {
|
||||
hide('pop_mypage01')
|
||||
hide('pop_mypage02')
|
||||
hide('pop_mypage03')
|
||||
}
|
||||
|
||||
/* =========================
|
||||
새로고침 / bfcache 대응 (script-only)
|
||||
========================= */
|
||||
window.addEventListener('pageshow', () => {
|
||||
['pop_mypage01','pop_mypage02','pop_mypage03']
|
||||
.forEach(hide)
|
||||
})
|
||||
|
||||
|
||||
/* =========================
|
||||
비밀번호 변경 UI 토글
|
||||
========================= */
|
||||
function bindPasswordChangeUI() {
|
||||
|
||||
const rowOriginal = document.getElementById('row-pw-original')
|
||||
const rowNew = document.getElementById('row-pw-new')
|
||||
const btnChange = document.getElementById('btnPwChange')
|
||||
const btnCancel = document.getElementById('btnPwCancel')
|
||||
|
||||
if (!rowOriginal || !rowNew || !btnChange || !btnCancel) {
|
||||
console.warn('[mypage] password toggle elements missing')
|
||||
return
|
||||
}
|
||||
|
||||
// 초기 상태
|
||||
rowNew.style.display = 'none'
|
||||
|
||||
// 비밀번호 변경
|
||||
btnChange.addEventListener('click', () => {
|
||||
rowOriginal.style.display = 'none'
|
||||
rowNew.style.display = ''
|
||||
})
|
||||
|
||||
// 취소
|
||||
btnCancel.addEventListener('click', () => {
|
||||
rowOriginal.style.display = ''
|
||||
rowNew.style.display = 'none'
|
||||
|
||||
document.getElementById('current_pw').value = ''
|
||||
document.getElementById('new_pw').value = ''
|
||||
document.getElementById('new_pw_confirm').value = ''
|
||||
})
|
||||
}
|
||||
/* =========================
|
||||
회원정보 유효성 체크
|
||||
========================= */
|
||||
function bindPasswordValidation() {
|
||||
const pw = document.getElementById('new_pw')
|
||||
const pwConfirm = document.getElementById('new_pw_confirm')
|
||||
const msg = document.getElementById('pwPolicyMsg')
|
||||
|
||||
if (!pw || !pwConfirm || !msg) return
|
||||
|
||||
function updateMessage(text, isError = true) {
|
||||
msg.textContent = text
|
||||
msg.classList.remove('d-none')
|
||||
msg.style.color = isError ? '#e60000' : '#2e7d32'
|
||||
}
|
||||
|
||||
function validate() {
|
||||
const v = pw.value
|
||||
const c = pwConfirm.value
|
||||
|
||||
if (!v && !c) {
|
||||
msg.classList.add('d-none')
|
||||
return
|
||||
}
|
||||
|
||||
const policy = checkPasswordPolicy(v)
|
||||
|
||||
if (!policy.length) {
|
||||
updateMessage('비밀번호는 8자 이상이어야 합니다.')
|
||||
return
|
||||
}
|
||||
if (!policy.eng) {
|
||||
updateMessage('영문자를 포함해야 합니다.')
|
||||
return
|
||||
}
|
||||
if (!policy.num) {
|
||||
updateMessage('숫자를 포함해야 합니다.')
|
||||
return
|
||||
}
|
||||
if (!policy.special) {
|
||||
updateMessage('특수문자를 포함해야 합니다.')
|
||||
return
|
||||
}
|
||||
if (c && v !== c) {
|
||||
updateMessage('비밀번호가 일치하지 않습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
updateMessage('사용 가능한 비밀번호입니다.', false)
|
||||
}
|
||||
|
||||
pw.addEventListener('input', validate)
|
||||
pwConfirm.addEventListener('input', validate)
|
||||
}
|
||||
|
||||
function checkPasswordPolicy(pw) {
|
||||
return {
|
||||
length: pw.length >= 8,
|
||||
eng: /[a-zA-Z]/.test(pw),
|
||||
num: /[0-9]/.test(pw),
|
||||
special: /[^a-zA-Z0-9]/.test(pw)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,680 @@
|
||||
/**
|
||||
* Popup Controller Module
|
||||
* 팝업 관련 기능을 관리하는 모듈
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ============================================
|
||||
// Configuration
|
||||
// ============================================
|
||||
const CONFIG = {
|
||||
SELECTORS: {
|
||||
btnClose: '.btn-close',
|
||||
btnMapClose: '.btn-map-close',
|
||||
popupWrap: '.popup-wrap',
|
||||
popupSitemap: '.popup-sitemap',
|
||||
domainList: '#domain-list',
|
||||
customDomain: '#custom-domain',
|
||||
certNumber: '.cert-number',
|
||||
code: '.code',
|
||||
check: '.check',
|
||||
checkComplete: '.check.complete',
|
||||
timer: '.timer',
|
||||
findEmail: '.find-email',
|
||||
findPh: '.find-ph',
|
||||
btnId: '.btn-id',
|
||||
btnPw: '.btn-pw',
|
||||
contentId: '.content.id',
|
||||
contentPw: '.content.pw',
|
||||
termsWrap: '.terms-wrap',
|
||||
checkboxWrap: '.checkbox-wrap.all',
|
||||
joinBtnWrap: '.join-btn-wrap',
|
||||
popInputWrap: '.pop-input-wrap',
|
||||
joinProgress: '.join-progress',
|
||||
joinStep: '.join-step',
|
||||
tabPrivacy: '.tab-privacy',
|
||||
tabAgreement: '.tab-agreement',
|
||||
tabContentPri: '.tab-content.pri',
|
||||
tabContentAgr: '.tab-content.agr',
|
||||
tabWrap: '.tab-menu',
|
||||
contentsWrap: '.contents_wrap',
|
||||
messages: '.messages'
|
||||
},
|
||||
TIMER: {
|
||||
DURATION: 60 * 3, // 3분
|
||||
INTERVAL: 1000 // 1초
|
||||
},
|
||||
CLASSES: {
|
||||
on: 'on',
|
||||
none: 'none',
|
||||
show: 'show',
|
||||
hide: 'hide',
|
||||
complete: 'complete'
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Utility Functions
|
||||
// ============================================
|
||||
const Utils = {
|
||||
/**
|
||||
* Lenis 스크롤 시작
|
||||
*/
|
||||
startLenis() {
|
||||
if (typeof lenis !== 'undefined' && lenis) {
|
||||
lenis.start();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 스크롤 복원
|
||||
*/
|
||||
restoreScroll() {
|
||||
$('body').css('overflow', '');
|
||||
this.startLenis();
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Popup Close Controller
|
||||
// ============================================
|
||||
const PopupCloseController = {
|
||||
init() {
|
||||
// 팝업 닫기 버튼
|
||||
$(document).on('click', CONFIG.SELECTORS.btnClose, () => {
|
||||
$(CONFIG.SELECTORS.popupWrap).hide();
|
||||
Utils.restoreScroll();
|
||||
});
|
||||
|
||||
// 사이트맵 닫기 버튼
|
||||
$(document).on('click', CONFIG.SELECTORS.btnMapClose, () => {
|
||||
$(CONFIG.SELECTORS.popupSitemap).hide();
|
||||
Utils.restoreScroll();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Email Domain Controller
|
||||
// ============================================
|
||||
const EmailDomainController = {
|
||||
init() {
|
||||
// ID 기반 선택자 (기존 호환성)
|
||||
$(document).on('change', CONFIG.SELECTORS.domainList, function() {
|
||||
const $select = $(this);
|
||||
const $selectBox = $select.closest('.select-box');
|
||||
const $customDomain = $selectBox.find(CONFIG.SELECTORS.customDomain);
|
||||
|
||||
if ($select.val() === 'type') {
|
||||
// 직접입력 선택 시 d-none 클래스 제거
|
||||
$customDomain.removeClass('d-none').focus();
|
||||
} else {
|
||||
// 다른 선택지 선택 시 d-none 클래스 추가 및 값 초기화
|
||||
$customDomain.addClass('d-none').val('');
|
||||
}
|
||||
});
|
||||
|
||||
// 클래스 기반 선택자 (.domain-list)
|
||||
$(document).on('change', '.domain-list', function() {
|
||||
const $select = $(this);
|
||||
const $inputBox = $select.closest('.input-box');
|
||||
const $customDomain = $inputBox.find('.domain-domain');
|
||||
|
||||
if ($select.val() === 'type') {
|
||||
// 직접입력 선택 시 d-none 클래스 제거
|
||||
$customDomain.removeClass('d-none').focus();
|
||||
} else {
|
||||
// 다른 선택지 선택 시 d-none 클래스 추가 및 값 초기화
|
||||
$customDomain.addClass('d-none').val('');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Timer Controller
|
||||
// ============================================
|
||||
// const TimerController = {
|
||||
// interval: null,
|
||||
// display: null,
|
||||
|
||||
// init() {
|
||||
// this.display = $(CONFIG.SELECTORS.timer);
|
||||
|
||||
// // 인증번호 버튼 클릭 시
|
||||
// $(document).on('click', CONFIG.SELECTORS.certNumber, () => {
|
||||
// $(CONFIG.SELECTORS.code).show();
|
||||
// this.start();
|
||||
// });
|
||||
|
||||
// // 확인 버튼 클릭 시
|
||||
// $(document).on('click', CONFIG.SELECTORS.check, function() {
|
||||
// $(this).hide();
|
||||
// $(CONFIG.SELECTORS.checkComplete).show();
|
||||
// TimerController.stop();
|
||||
// $(CONFIG.SELECTORS.timer).remove();
|
||||
// });
|
||||
|
||||
// // 로그인 페이지 휴대폰 인증 폼의 인증 링크 요청 버튼 클릭 시
|
||||
// $(document).on('submit', '#pop_login .tab-content.phone form', (e) => {
|
||||
// e.preventDefault();
|
||||
// const $form = $(e.target);
|
||||
// const $timer = $form.find('.timer');
|
||||
// const $infoBox = $form.find('.info-box');
|
||||
|
||||
// // 타이머와 info-box 표시
|
||||
// // $timer.removeClass('hide');
|
||||
// $timer.removeClass('d-none');
|
||||
// $infoBox.removeClass('d-none');
|
||||
|
||||
// // 타이머 시작 (해당 폼 내의 타이머만)
|
||||
// if ($timer.length) {
|
||||
// this.stop();
|
||||
// this.display = $timer;
|
||||
// this.start();
|
||||
// }
|
||||
// });
|
||||
|
||||
// // 초기 타이머 시작 (다른 페이지에서 사용하는 경우를 위해)
|
||||
// // 숨겨지지 않은 타이머만 자동 시작
|
||||
// const $visibleTimers = $(CONFIG.SELECTORS.timer).not('.hide').not('.d-none');
|
||||
// if ($visibleTimers.length > 0) {
|
||||
// this.display = $visibleTimers.first();
|
||||
// this.start();
|
||||
// }
|
||||
// },
|
||||
|
||||
// start() {
|
||||
// this.stop();
|
||||
// this.startTimer(CONFIG.TIMER.DURATION, this.display);
|
||||
// },
|
||||
|
||||
// stop() {
|
||||
// if (this.interval) {
|
||||
// clearInterval(this.interval);
|
||||
// this.interval = null;
|
||||
// }
|
||||
// },
|
||||
|
||||
// startTimer(duration, display) {
|
||||
// let timer = duration;
|
||||
|
||||
// const updateTimer = () => {
|
||||
// const minutes = Math.floor(timer / 60);
|
||||
// const seconds = timer % 60;
|
||||
// const formattedMinutes = minutes < 10 ? `0${minutes}` : minutes;
|
||||
// const formattedSeconds = seconds < 10 ? `0${seconds}` : seconds;
|
||||
|
||||
// if (display && display.length) {
|
||||
// display.text(`${formattedMinutes}:${formattedSeconds}`);
|
||||
// }
|
||||
|
||||
// if (--timer < 0) {
|
||||
// this.stop();
|
||||
// if (display && display.length) {
|
||||
// display.text('00:00');
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// updateTimer();
|
||||
// this.interval = setInterval(updateTimer, CONFIG.TIMER.INTERVAL);
|
||||
// }
|
||||
// };
|
||||
|
||||
// ============================================
|
||||
// Find Account Controller
|
||||
// ============================================
|
||||
const FindAccountController = {
|
||||
/**
|
||||
* 라디오 버튼 전환 처리
|
||||
* @param {jQuery} $radio - 클릭된 라디오 버튼
|
||||
* @param {string} type - 'ph' 또는 'email'
|
||||
*/
|
||||
switchRadio($radio, type) {
|
||||
const $radioWrap = $radio.closest('.radio-wrap');
|
||||
const $tabContent = $radioWrap.closest('.tab-content');
|
||||
|
||||
// 같은 라디오 그룹의 다른 라디오 버튼들
|
||||
const $otherRadio = type === 'ph'
|
||||
? $radioWrap.find(CONFIG.SELECTORS.findEmail)
|
||||
: $radioWrap.find(CONFIG.SELECTORS.findPh);
|
||||
|
||||
// 라디오 버튼 상태 변경
|
||||
$otherRadio.removeClass(CONFIG.CLASSES.on).prop('checked', false);
|
||||
$radio.addClass(CONFIG.CLASSES.on).prop('checked', true);
|
||||
|
||||
// 테이블 표시/숨김 (해당 탭 콘텐츠 내에서만)
|
||||
if (type === 'ph') {
|
||||
$tabContent.find('table.email').hide();
|
||||
$tabContent.find('table.ph').show();
|
||||
} else {
|
||||
$tabContent.find('table.ph').hide();
|
||||
$tabContent.find('table.email').show();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 초기 상태 설정
|
||||
*/
|
||||
initRadioState() {
|
||||
// 각 탭 콘텐츠별로 초기 상태 설정
|
||||
$('.tab-content').each(function() {
|
||||
const $tabContent = $(this);
|
||||
const $checkedRadio = $tabContent.find('.radio-wrap input[type="radio"]:checked');
|
||||
|
||||
if ($checkedRadio.length) {
|
||||
if ($checkedRadio.hasClass('find-ph')) {
|
||||
$tabContent.find('table.ph').show();
|
||||
$tabContent.find('table.email').hide();
|
||||
} else if ($checkedRadio.hasClass('find-email')) {
|
||||
$tabContent.find('table.email').show();
|
||||
$tabContent.find('table.ph').hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
// 이메일 찾기 라디오 버튼 클릭
|
||||
$(document).on('click', CONFIG.SELECTORS.findEmail, function(e) {
|
||||
e.preventDefault();
|
||||
FindAccountController.switchRadio($(this), 'email');
|
||||
});
|
||||
|
||||
// 전화번호 찾기 라디오 버튼 클릭
|
||||
$(document).on('click', CONFIG.SELECTORS.findPh, function(e) {
|
||||
e.preventDefault();
|
||||
FindAccountController.switchRadio($(this), 'ph');
|
||||
});
|
||||
|
||||
// 라디오 버튼 변경 이벤트 (체크 상태 동기화)
|
||||
$(document).on('change', '.radio-wrap input[type="radio"]', function() {
|
||||
const $radio = $(this);
|
||||
if ($radio.hasClass('find-ph')) {
|
||||
FindAccountController.switchRadio($radio, 'ph');
|
||||
} else if ($radio.hasClass('find-email')) {
|
||||
FindAccountController.switchRadio($radio, 'email');
|
||||
}
|
||||
});
|
||||
|
||||
// 초기 상태 설정
|
||||
this.initRadioState();
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Login Tab Controller
|
||||
// ============================================
|
||||
const LoginTabController = {
|
||||
init() {
|
||||
// ID 찾기 탭
|
||||
$(document).on('click', CONFIG.SELECTORS.btnId, () => {
|
||||
$(CONFIG.SELECTORS.btnId).addClass(CONFIG.CLASSES.on);
|
||||
$(CONFIG.SELECTORS.btnPw).removeClass(CONFIG.CLASSES.on);
|
||||
$(CONFIG.SELECTORS.contentId).show();
|
||||
$(CONFIG.SELECTORS.contentPw).hide();
|
||||
});
|
||||
|
||||
// 비밀번호 찾기 탭
|
||||
$(document).on('click', CONFIG.SELECTORS.btnPw, () => {
|
||||
$(CONFIG.SELECTORS.btnPw).addClass(CONFIG.CLASSES.on);
|
||||
$(CONFIG.SELECTORS.btnId).removeClass(CONFIG.CLASSES.on);
|
||||
$(CONFIG.SELECTORS.contentPw).show();
|
||||
$(CONFIG.SELECTORS.contentId).hide();
|
||||
});
|
||||
|
||||
// 도메인 선택 (중복 제거)
|
||||
$(CONFIG.SELECTORS.domainList).on('change', function() {
|
||||
const $customDomain = $(CONFIG.SELECTORS.customDomain);
|
||||
|
||||
if ($(this).val() === 'type') {
|
||||
$customDomain.show();
|
||||
} else {
|
||||
$customDomain.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Terms Agreement Controller
|
||||
// ============================================
|
||||
const TermsAgreementController = {
|
||||
init() {
|
||||
// 약관 동의 상태 업데이트
|
||||
this.updateJoinButton();
|
||||
|
||||
// 전체 동의 체크박스 (기존 호환성)
|
||||
$(CONFIG.SELECTORS.checkboxWrap).find('input[type="checkbox"]').on('change', (e) => {
|
||||
const isChecked = $(e.target).is(':checked');
|
||||
$(CONFIG.SELECTORS.termsWrap).find('input[type="checkbox"]').prop('checked', isChecked);
|
||||
this.updateJoinButton();
|
||||
});
|
||||
|
||||
// .chk-all 클래스를 가진 체크박스 (전체 동의)
|
||||
$(document).on('change click', '.chk-all', function(e) {
|
||||
e.stopPropagation(); // 이벤트 전파 중지
|
||||
const $chkAll = $(this);
|
||||
const isChecked = $chkAll.is(':checked');
|
||||
const $termsWrap = $chkAll.closest('.terms-wrap');
|
||||
|
||||
// .chk-all을 제외한 모든 체크박스 선택/해제
|
||||
$termsWrap.find('input[type="checkbox"]:not(.chk-all)').prop('checked', isChecked);
|
||||
|
||||
// updateJoinButton 호출 시 무한 루프 방지를 위해 플래그 설정
|
||||
TermsAgreementController._updatingFromChkAll = true;
|
||||
TermsAgreementController.updateJoinButton();
|
||||
TermsAgreementController._updatingFromChkAll = false;
|
||||
});
|
||||
|
||||
// 개별 체크박스
|
||||
$(CONFIG.SELECTORS.termsWrap).find('input[type="checkbox"]').on('change', () => {
|
||||
this.updateJoinButton();
|
||||
});
|
||||
|
||||
// .terms-wrap 내의 개별 체크박스 (chk-all 제외)
|
||||
$(document).on('change', '.terms-wrap input[type="checkbox"]:not(.chk-all)', () => {
|
||||
this.updateJoinButton();
|
||||
});
|
||||
},
|
||||
|
||||
updateJoinButton() {
|
||||
// .terms-wrap 내의 모든 체크박스 확인 (chk-all 제외)
|
||||
const $allTermsWraps = $('.terms-wrap');
|
||||
let allChecked = true;
|
||||
|
||||
$allTermsWraps.each(function() {
|
||||
const $checkboxes = $(this).find('input[type="checkbox"]:not(.chk-all)');
|
||||
const $checked = $checkboxes.filter(':checked');
|
||||
if ($checkboxes.length > 0 && $checkboxes.length !== $checked.length) {
|
||||
allChecked = false;
|
||||
return false; // break
|
||||
}
|
||||
});
|
||||
|
||||
// .chk-all 체크박스 상태 업데이트 (무한 루프 방지)
|
||||
if (!TermsAgreementController._updatingFromChkAll) {
|
||||
$('.chk-all').prop('checked', allChecked);
|
||||
}
|
||||
|
||||
// 전체 동의 체크박스 상태 업데이트 (기존 호환성)
|
||||
$(CONFIG.SELECTORS.checkboxWrap).find('input[type="checkbox"]').prop('checked', allChecked);
|
||||
|
||||
// 버튼 상태 업데이트
|
||||
const $joinBtnWrap = $(CONFIG.SELECTORS.joinBtnWrap);
|
||||
if (allChecked) {
|
||||
$joinBtnWrap.removeClass(CONFIG.CLASSES.none);
|
||||
$joinBtnWrap.find('button').prop('disabled', false);
|
||||
} else {
|
||||
$joinBtnWrap.addClass(CONFIG.CLASSES.none);
|
||||
$joinBtnWrap.find('button').prop('disabled', true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Join Completion Controller
|
||||
// ============================================
|
||||
const JoinCompletionController = {
|
||||
init() {
|
||||
// 전송완료
|
||||
$(document).on('click', '.pw ' + CONFIG.SELECTORS.joinBtnWrap + ' button', () => {
|
||||
$(CONFIG.SELECTORS.contentsWrap).children().not(CONFIG.SELECTORS.messages).hide();
|
||||
$(CONFIG.SELECTORS.messages).show();
|
||||
});
|
||||
|
||||
// 가입완료
|
||||
$(document).on('click', '.join.completion ' + CONFIG.SELECTORS.joinBtnWrap + ' button', () => {
|
||||
$(CONFIG.SELECTORS.popInputWrap).find('form').children().not(CONFIG.SELECTORS.messages).hide();
|
||||
$(CONFIG.SELECTORS.messages).show();
|
||||
|
||||
// 진행 단계 업데이트
|
||||
$(CONFIG.SELECTORS.joinProgress).find(CONFIG.SELECTORS.joinStep).removeClass(CONFIG.CLASSES.on);
|
||||
$(CONFIG.SELECTORS.joinProgress).find(CONFIG.SELECTORS.joinStep).eq(2).addClass(CONFIG.CLASSES.on);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Universal Tab Controller
|
||||
// ============================================
|
||||
const TabController = {
|
||||
/**
|
||||
* 탭 클래스명에서 콘텐츠 클래스명 추출
|
||||
* @param {jQuery} $tab - 탭 요소
|
||||
* @returns {string} 콘텐츠 클래스명
|
||||
*/
|
||||
getContentClass($tab) {
|
||||
// 탭 클래스명에서 tab- 접두사 제거
|
||||
const tabClasses = $tab.attr('class').split(' ');
|
||||
let contentClass = '';
|
||||
|
||||
for (let i = 0; i < tabClasses.length; i++) {
|
||||
const className = tabClasses[i];
|
||||
if (className.startsWith('tab-')) {
|
||||
const tabName = className.replace('tab-', '');
|
||||
|
||||
// 특수 케이스 매핑
|
||||
const specialCases = {
|
||||
'privacy': 'pri',
|
||||
'agreement': 'agr'
|
||||
};
|
||||
|
||||
contentClass = specialCases[tabName] || tabName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return contentClass;
|
||||
},
|
||||
|
||||
/**
|
||||
* 슬라이딩 인디케이터 위치 업데이트 (round 타입 탭 메뉴용)
|
||||
* @param {jQuery} $tabMenu - 탭 메뉴 요소
|
||||
* @param {jQuery} $activeTab - 활성화된 탭 요소
|
||||
*/
|
||||
updateSliderPosition($tabMenu, $activeTab) {
|
||||
// round 클래스가 있는 경우에만 처리
|
||||
if (!$tabMenu.hasClass('round')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $tabs = $tabMenu.find('li');
|
||||
const activeIndex = $tabs.index($activeTab);
|
||||
const tabCount = $tabs.length;
|
||||
|
||||
if (tabCount === 0) return;
|
||||
|
||||
// 탭 메뉴의 실제 너비와 패딩 확인
|
||||
const tabMenuWidth = $tabMenu.width();
|
||||
const padding = 0; // padding: 4px
|
||||
const gap = 4; // gap: 4px
|
||||
|
||||
// 사용 가능한 너비 (패딩 제외)
|
||||
const availableWidth = tabMenuWidth - (padding * 2);
|
||||
|
||||
// 각 탭의 너비 계산 (gap 포함)
|
||||
// gap은 탭 사이에만 있으므로, 탭 개수 - 1개의 gap이 있음
|
||||
const totalGapWidth = gap * (tabCount - 1);
|
||||
const tabWidth = (availableWidth - totalGapWidth) / tabCount;
|
||||
|
||||
// 인디케이터 위치 계산 (패딩 + 탭 너비 * 인덱스 + gap * 인덱스)
|
||||
const indicatorPosition = padding + (tabWidth + gap) * activeIndex;
|
||||
|
||||
// CSS 변수로 위치 설정 (픽셀 단위)
|
||||
$tabMenu[0].style.setProperty('--tab-indicator-position', `${indicatorPosition}px`);
|
||||
|
||||
// 인디케이터 너비도 동적으로 설정
|
||||
$tabMenu[0].style.setProperty('--tab-indicator-width', `${tabWidth}px`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 탭 전환 처리
|
||||
* @param {jQuery} $clickedTab - 클릭된 탭 요소
|
||||
*/
|
||||
switchTab($clickedTab) {
|
||||
const $tabMenu = $clickedTab.closest(CONFIG.SELECTORS.tabWrap);
|
||||
const $allTabs = $tabMenu.find('li');
|
||||
|
||||
// 콘텐츠 컨테이너 찾기 (pop-contents 또는 contents-wrap)
|
||||
const $contentContainer = $clickedTab.closest('.pop-contents, .contents-wrap');
|
||||
const $allContents = $contentContainer.find('.tab-content');
|
||||
|
||||
// 모든 탭에서 on 클래스 제거
|
||||
$allTabs.removeClass(CONFIG.CLASSES.on);
|
||||
|
||||
// 클릭된 탭에 on 클래스 추가
|
||||
$clickedTab.addClass(CONFIG.CLASSES.on);
|
||||
|
||||
// 슬라이딩 인디케이터 위치 업데이트 (round 타입인 경우)
|
||||
this.updateSliderPosition($tabMenu, $clickedTab);
|
||||
|
||||
// 모든 콘텐츠 숨기기
|
||||
$allContents.removeClass(CONFIG.CLASSES.show);
|
||||
|
||||
// 해당하는 콘텐츠만 표시
|
||||
const contentClass = this.getContentClass($clickedTab);
|
||||
if (contentClass) {
|
||||
const $targetContent = $contentContainer.find('.tab-content.' + contentClass);
|
||||
if ($targetContent.length) {
|
||||
$targetContent.addClass(CONFIG.CLASSES.show);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 탭 초기 상태 설정
|
||||
*/
|
||||
initTabState() {
|
||||
// 모든 tab-menu 찾기
|
||||
$(CONFIG.SELECTORS.tabWrap).each(function() {
|
||||
const $tabMenu = $(this);
|
||||
const $tabs = $tabMenu.find('li');
|
||||
const $contentContainer = $tabMenu.closest('.pop-contents, .contents-wrap');
|
||||
|
||||
if ($tabs.length === 0 || !$contentContainer.length) return;
|
||||
|
||||
// 활성화된 탭 찾기
|
||||
const $activeTab = $tabs.filter('.' + CONFIG.CLASSES.on);
|
||||
|
||||
if ($activeTab.length > 0) {
|
||||
// 활성화된 탭이 있으면 해당 콘텐츠 표시
|
||||
TabController.switchTab($activeTab);
|
||||
} else {
|
||||
// 활성화된 탭이 없으면 첫 번째 탭 활성화
|
||||
const $firstTab = $tabs.first();
|
||||
$firstTab.addClass(CONFIG.CLASSES.on);
|
||||
TabController.switchTab($firstTab);
|
||||
}
|
||||
|
||||
// 리사이즈 시 인디케이터 위치 재계산
|
||||
if ($tabMenu.hasClass('round')) {
|
||||
$(window).on('resize.tabSlider', function() {
|
||||
const $active = $tabMenu.find('li.' + CONFIG.CLASSES.on);
|
||||
if ($active.length) {
|
||||
TabController.updateSliderPosition($tabMenu, $active);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
// 모든 tab-menu의 탭 클릭 이벤트
|
||||
$(document).on('click', CONFIG.SELECTORS.tabWrap + ' li', function(e) {
|
||||
e.preventDefault();
|
||||
TabController.switchTab($(this));
|
||||
});
|
||||
|
||||
// 키보드 접근성 지원 (탭 + 엔터/스페이스)
|
||||
$(document).on('keydown', CONFIG.SELECTORS.tabWrap + ' li', function(e) {
|
||||
// Enter 또는 Space 키
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
TabController.switchTab($(this));
|
||||
}
|
||||
|
||||
// 화살표 키로 탭 전환
|
||||
const $tabMenu = $(this).closest(CONFIG.SELECTORS.tabWrap);
|
||||
const $tabs = $tabMenu.find('li');
|
||||
const currentIndex = $tabs.index(this);
|
||||
|
||||
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
|
||||
e.preventDefault();
|
||||
let targetIndex;
|
||||
|
||||
if (e.key === 'ArrowLeft') {
|
||||
targetIndex = currentIndex > 0 ? currentIndex - 1 : $tabs.length - 1;
|
||||
} else {
|
||||
targetIndex = currentIndex < $tabs.length - 1 ? currentIndex + 1 : 0;
|
||||
}
|
||||
|
||||
const $targetTab = $tabs.eq(targetIndex);
|
||||
$targetTab.focus();
|
||||
TabController.switchTab($targetTab);
|
||||
}
|
||||
});
|
||||
|
||||
// 초기 상태 설정
|
||||
this.initTabState();
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Privacy Tab Controller (하위 호환성 유지)
|
||||
// ============================================
|
||||
const PrivacyTabController = {
|
||||
switchTab: function($clickedTab) {
|
||||
return TabController.switchTab.call(TabController, $clickedTab);
|
||||
},
|
||||
init: function() {
|
||||
return TabController.init.call(TabController);
|
||||
},
|
||||
initTabState: function() {
|
||||
return TabController.initTabState.call(TabController);
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Main Initialization
|
||||
// ============================================
|
||||
const PopupController = {
|
||||
init() {
|
||||
// DOM이 준비되면 초기화
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
this.start();
|
||||
});
|
||||
} else {
|
||||
this.start();
|
||||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
PopupCloseController.init();
|
||||
EmailDomainController.init();
|
||||
TimerController.init();
|
||||
FindAccountController.init();
|
||||
LoginTabController.init();
|
||||
TermsAgreementController.init();
|
||||
JoinCompletionController.init();
|
||||
TabController.init();
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// Start Application
|
||||
// ============================================
|
||||
PopupController.init();
|
||||
|
||||
// ============================================
|
||||
// Global Functions
|
||||
// ============================================
|
||||
// 전역에서 접근 가능하도록 함수 노출
|
||||
window.PopupController = PopupController;
|
||||
window.TabController = TabController;
|
||||
window.PrivacyTabController = PrivacyTabController; // 하위 호환성 유지
|
||||
|
||||
})();
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */
|
||||
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=y.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:v}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,y,s,c,v,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),j=function(e,t){return e===t&&(l=!0),0},D={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^Line truncated
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* jQuery Mousewheel 3.1.13
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
*/
|
||||
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?module.exports=e:e(jQuery)}(function(a){var u,r,e=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],t="onwheel"in window.document||9<=window.document.documentMode?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],f=Array.prototype.slice;if(a.event.fixHooks)for(var n=e.length;n;)a.event.fixHooks[e[--n]]=a.event.mouseHooks;var d=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var e=t.length;e;)this.addEventListener(t[--e],i,!1);else this.onmousewheel=i;a.data(this,"mousewheel-line-height",d.getLineHeight(this)),a.data(this,"mousewheel-page-height",d.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var e=t.length;e;)this.removeEventListener(t[--e],i,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(e){var t=a(e),e=t["offsetParent"in a.fn?"offsetParent":"parent"]();return e.length||(e=a("body")),parseInt(e.css("fontSize"),10)||parseInt(t.css("fontSize"),10)||16},getPageHeight:function(e){return a(e).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};function i(e){var t,n=e||window.event,i=f.call(arguments,1),o=0,l=0,s=0,h=0;if((e=a.event.fix(n)).type="mousewheel","detail"in n&&(s=-1*n.detail),"wheelDelta"in n&&(s=n.wheelDelta),"wheelDeltaY"in n&&(s=n.wheelDeltaY),"wheelDeltaX"in n&&(l=-1*n.wheelDeltaX),"axis"in n&&n.axis===n.HORIZONTAL_AXIS&&(l=-1*s,s=0),o=0===s?l:s,"deltaY"in n&&(o=s=-1*n.deltaY),"deltaX"in n&&(l=n.deltaX,0===s&&(o=-1*l)),0!==s||0!==l)return 1===n.deltaMode?(o*=t=a.data(this,"mousewheel-line-height"),s*=t,l*=t):2===n.deltaMode&&(o*=t=a.data(this,"mousewheel-page-height"),s*=t,l*=t),h=Math.max(Math.abs(s),Math.abs(l)),(!r||h<r)&&c(n,r=h)&&(r/=40),c(n,h)&&(o/=40,l/=40,s/=40),o=Math[1<=o?"floor":"ceil"](o/r),l=Math[1<=l?"floor":"ceil"](l/r),s=Math[1<=s?"floor":"ceil"](s/r),d.settings.normalizeOffset&&this.getBoundingClientRect&&(h=this.getBoundingClientRect(),e.offsetX=e.clientX-h.left,e.offsetY=e.clientY-h.top),e.deltaX=l,e.deltaY=s,e.deltaFactor=r,e.deltaMode=0,i.unshift(e,o,l,s),u&&window.clearTimeout(u),u=window.setTimeout(w,200),(a.event.dispatch||a.event.handle).apply(this,i)}function w(){r=null}function c(e,t){return d.settings.adjustOldDeltas&&"mousewheel"===e.type&&t%120==0}a.fn.extend({mousewheel:function(e){return e?this.on("mousewheel",e):this.trigger("mousewheel")},unmousewheel:function(e){return this.off("mousewheel",e)}})});
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,198 @@
|
||||
$(function () {
|
||||
var obj = document.getElementById("video_play");
|
||||
var video = $("#video_play").get(0);
|
||||
var i = 1;
|
||||
|
||||
// 영상 소스를 비율에 맞게 설정하는 함수
|
||||
function updateVideoSource() {
|
||||
var width = $(window).width();
|
||||
var height = $(window).height();
|
||||
var ratio = width / height;
|
||||
|
||||
// 비율이 가로가 더 길면 기본 영상, 세로가 더 길면 '_v'가 붙은 영상
|
||||
if (ratio > 1) {
|
||||
$("#video_play").attr("src", "img/main_" + i + ".mp4");
|
||||
$("ul.pagination_main").removeClass("m");
|
||||
} else {
|
||||
$("#video_play").attr("src", "img/main_" + i + "_v.mp4");
|
||||
$("ul.pagination_main").addClass("m");
|
||||
}
|
||||
|
||||
// 영상 로드 및 자동 재생
|
||||
video.load();
|
||||
video.play();
|
||||
}
|
||||
|
||||
// 페이지 로드 시 비율에 맞는 영상 설정
|
||||
updateVideoSource();
|
||||
|
||||
// 화면 사이즈가 변경될 때마다 비율에 맞는 영상 설정
|
||||
$(window).resize(function () {
|
||||
updateVideoSource();
|
||||
});
|
||||
console.log("리사이징 완료");
|
||||
|
||||
// 인트로 페이지 종료 후 첫 영상 실행
|
||||
video.pause();
|
||||
$(".pagination_main").hide();
|
||||
|
||||
if (sessionStorage.getItem("visited")) {
|
||||
video.play();
|
||||
$(".pagination_main").show();
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
video.play();
|
||||
$(".pagination_main").show();
|
||||
}, 2800);
|
||||
}
|
||||
|
||||
// 페이지 네이션 - 클릭하면 해당 영상 실행
|
||||
function setPageVideo(pageNum) {
|
||||
i = pageNum;
|
||||
updateVideoSource(); // 비율에 맞는 영상으로 설정
|
||||
$(".page_0" + i).addClass("page_on");
|
||||
$(".pagination_main div")
|
||||
.not(".page_0" + i)
|
||||
.removeClass("page_on");
|
||||
$(".main_link_0" + i).addClass("link_on");
|
||||
$(".main_link a")
|
||||
.not(".main_link_0" + i)
|
||||
.removeClass("link_on");
|
||||
}
|
||||
|
||||
// 각 페이지 클릭 시 영상 변경
|
||||
$(".page_01").click(function () {
|
||||
setPageVideo(1);
|
||||
console.log("영상1 재생");
|
||||
});
|
||||
$(".page_02").click(function () {
|
||||
setPageVideo(2);
|
||||
console.log("영상2 재생");
|
||||
});
|
||||
$(".page_03").click(function () {
|
||||
setPageVideo(3);
|
||||
console.log("영상3 재생");
|
||||
});
|
||||
$(".page_04").click(function () {
|
||||
setPageVideo(4);
|
||||
console.log("영상4 재생");
|
||||
});
|
||||
$(".page_05").click(function () {
|
||||
setPageVideo(5);
|
||||
console.log("영상5 재생");
|
||||
});
|
||||
|
||||
// 영상 종료 후 다음 영상 실행
|
||||
$("#video_play").on("ended", function () {
|
||||
if (i < 5) {
|
||||
i = i + 1;
|
||||
updateVideoSource();
|
||||
$(".page_0" + i).addClass("page_on");
|
||||
$(".pagination_main div")
|
||||
.not(".page_0" + i)
|
||||
.removeClass("page_on");
|
||||
$(".main_link_0" + i).addClass("link_on");
|
||||
$(".main_link a")
|
||||
.not(".main_link_0" + i)
|
||||
.removeClass("link_on");
|
||||
} else {
|
||||
i = 1;
|
||||
updateVideoSource();
|
||||
$(".page_0" + i).addClass("page_on");
|
||||
$(".pagination_main div")
|
||||
.not(".page_0" + i)
|
||||
.removeClass("page_on");
|
||||
$(".main_link_0" + i).addClass("link_on");
|
||||
$(".main_link a")
|
||||
.not(".main_link_0" + i)
|
||||
.removeClass("link_on");
|
||||
}
|
||||
video.play(); // 영상 자동 재생
|
||||
});
|
||||
});
|
||||
|
||||
// index footer 동작
|
||||
$(function () {
|
||||
let currentMode = null;
|
||||
|
||||
// 디바이스 체크 함수
|
||||
function getDeviceType() {
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
const isMobile =
|
||||
/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(ua);
|
||||
const isTablet = /(ipad|tablet|playbook|silk)|(android(?!.*mobile))/i.test(
|
||||
ua
|
||||
);
|
||||
|
||||
// 터치 지원 여부도 체크
|
||||
const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
||||
|
||||
// 모바일 또는 태블릿이면서 터치 지원
|
||||
if ((isMobile || isTablet) && hasTouch) {
|
||||
return "mo";
|
||||
}
|
||||
|
||||
return "pc";
|
||||
}
|
||||
|
||||
function setupFooterEvents() {
|
||||
const newMode = getDeviceType();
|
||||
|
||||
// 모드가 변경되지 않았으면 리턴
|
||||
if (currentMode === newMode) return;
|
||||
|
||||
currentMode = newMode;
|
||||
|
||||
// 기존 이벤트 제거
|
||||
$(".main").off("wheel mousewheel touchmove");
|
||||
|
||||
if (newMode === "pc") {
|
||||
// PC: 기본 footer_off 상태
|
||||
$("footer").addClass("footer_off").removeClass("footer_on");
|
||||
|
||||
// wheel 이벤트로 토글
|
||||
$(".main").on("wheel", function (e) {
|
||||
if (e.originalEvent.deltaY < 0) {
|
||||
// 위로 스크롤
|
||||
$("footer").addClass("footer_off").removeClass("footer_on");
|
||||
} else {
|
||||
// 아래로 스크롤
|
||||
$("footer").addClass("footer_on").removeClass("footer_off");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 모바일/태블릿: touchmove 시 footer_on
|
||||
$(".main").on("touchmove", function () {
|
||||
$("footer").addClass("footer_on").removeClass("footer_off");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 초기 설정
|
||||
setupFooterEvents();
|
||||
|
||||
// footer 닫기
|
||||
$(".footer_close")
|
||||
.off("click")
|
||||
.on("click", function () {
|
||||
$("footer").addClass("footer_off").removeClass("footer_on");
|
||||
});
|
||||
});
|
||||
|
||||
// 인트로 없애기
|
||||
// 1. 홈페이지에 들어오면 sessionStorage에 visited 추가
|
||||
// 2. visited가 있는 동안에는 인트로 삭제
|
||||
// 3. 브라우저 종료 or 탭 닫으면 visited 자동 삭제
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const intro = document.querySelector(".intro_wrap");
|
||||
|
||||
if (sessionStorage.getItem("visited")) {
|
||||
console.log("visited");
|
||||
intro.style.display = "none";
|
||||
document.querySelector(".main_mask").classList.add("skip");
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
sessionStorage.setItem("visited", "true");
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,256 @@
|
||||
window.onload = function() {
|
||||
$.ajax({
|
||||
url: "some_api_endpoint",
|
||||
success: function(response) {
|
||||
},
|
||||
complete: function() {
|
||||
|
||||
// 팝업 닫기버튼
|
||||
$(document).ready(function() {
|
||||
$('.btn_close').click(function() {
|
||||
$('.popup_wrap').hide();
|
||||
$('body').css('overflow', ''); // 기본 스크롤 상태로 복귀
|
||||
lenis.start();
|
||||
console.log('lenis 재시작')
|
||||
});
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$('.btn_map_close').click(function() {
|
||||
$('.popup_sitemap').hide();
|
||||
$('body').css('overflow', ''); // 기본 스크롤 상태로 복귀
|
||||
lenis.start();
|
||||
console.log('lenis 재시작')
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 이메일 직접입력
|
||||
$(document).ready(function() {
|
||||
$('#domain-list').change(function() {
|
||||
if ($(this).val() === 'type') {
|
||||
$('#custom-domain').show().focus();
|
||||
} else {
|
||||
$('#custom-domain').hide().val('');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 인증번호 타이머
|
||||
$(document).ready(function() {
|
||||
// 인증번호 버튼 클릭 시
|
||||
$('.cert_number').click(function() {
|
||||
$('.code').show();
|
||||
});
|
||||
|
||||
// 확인 버튼 클릭 시
|
||||
$('.check').click(function() {
|
||||
$(this).hide();
|
||||
$('.check.complete').show();
|
||||
clearInterval(interval); // 타이머 멈춤
|
||||
$('.timer').remove(); // 타이머 요소 삭제
|
||||
});
|
||||
|
||||
// 타이머 함수
|
||||
var interval;
|
||||
function startTimer(duration, display) {
|
||||
clearInterval(interval);
|
||||
var timer = duration, minutes, seconds;
|
||||
|
||||
function updateTimer() {
|
||||
minutes = parseInt(timer / 60, 10);
|
||||
seconds = parseInt(timer % 60, 10);
|
||||
|
||||
minutes = minutes < 10 ? "0" + minutes : minutes;
|
||||
seconds = seconds < 10 ? "0" + seconds : seconds;
|
||||
|
||||
display.text(minutes + ":" + seconds);
|
||||
|
||||
if (--timer < 0) {
|
||||
clearInterval(interval);
|
||||
display.text("00:00");
|
||||
}
|
||||
}
|
||||
|
||||
updateTimer();
|
||||
interval = setInterval(updateTimer, 1000);
|
||||
}
|
||||
|
||||
var threeMinutes = 60 * 3,
|
||||
display = $('.timer');
|
||||
|
||||
startTimer(threeMinutes, display);
|
||||
|
||||
$('.cert_number').click(function() {
|
||||
startTimer(threeMinutes, display);
|
||||
});
|
||||
});
|
||||
|
||||
// 아이디찾기
|
||||
$(document).ready(function(){
|
||||
$('.find_email').click(function(){
|
||||
$('.find_ph').removeClass('on').prop('checked', false);
|
||||
$(this).addClass('on').prop('checked', true);
|
||||
$('.ph').hide();
|
||||
$('.email').show();
|
||||
});
|
||||
|
||||
$('.find_ph').click(function(){
|
||||
$('.find_email').removeClass('on').prop('checked', false);
|
||||
$(this).addClass('on').prop('checked', true);
|
||||
$('.email').hide();
|
||||
$('.ph').show();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.btn_id').on('click', function() {
|
||||
$('.btn_id').addClass('on');
|
||||
$('.btn_pw').removeClass('on');
|
||||
$('.content.id').show();
|
||||
$('.content.pw').hide();
|
||||
});
|
||||
|
||||
$('.btn_pw').on('click', function() {
|
||||
$('.btn_pw').addClass('on');
|
||||
$('.btn_id').removeClass('on');
|
||||
$('.content.pw').show();
|
||||
$('.content.id').hide();
|
||||
});
|
||||
|
||||
$('#domain-list').on('change', function() {
|
||||
if ($(this).val() === 'type') {
|
||||
$('#custom-domain').show();
|
||||
} else {
|
||||
$('#custom-domain').hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 전체약관동의
|
||||
// $(document).ready(function() {
|
||||
// function toggleJoinButton() {
|
||||
// // 모든 개별 체크박스가 체크되었는지 확인
|
||||
// var allChecked = $('.terms_wrap input[type="checkbox"]').length === $('.terms_wrap input[type="checkbox"]:checked').length;
|
||||
|
||||
// // '약관에 모두 동의합니다' 체크박스 상태에 따라 조정
|
||||
// $('.checkbox_wrap.all input[type="checkbox"]').prop('checked', allChecked);
|
||||
|
||||
// // 모든 체크박스가 체크되지 않은 경우 버튼에 'none' 클래스 추가하고 disabled 속성 추가
|
||||
// if (allChecked) {
|
||||
// $('.join_btn_wrap').removeClass('none');
|
||||
// $('.join_btn_wrap button').prop('disabled', false);
|
||||
// } else {
|
||||
// $('.join_btn_wrap').addClass('none');
|
||||
// $('.join_btn_wrap button').prop('disabled', true);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // '약관에 모두 동의합니다' 체크박스의 변경 이벤트
|
||||
// $('.checkbox_wrap.all input[type="checkbox"]').on('change', function() {
|
||||
// var isChecked = $(this).is(':checked');
|
||||
// $('.terms_wrap input[type="checkbox"]').prop('checked', isChecked);
|
||||
// toggleJoinButton(); // 버튼 상태 업데이트
|
||||
// });
|
||||
|
||||
// // 각 terms_wrap의 개별 체크박스 변경 이벤트
|
||||
// $('.terms_wrap input[type="checkbox"]').on('change', function() {
|
||||
// toggleJoinButton(); // 버튼 상태 업데이트
|
||||
// });
|
||||
|
||||
// // 초기 상태 설정
|
||||
// toggleJoinButton();
|
||||
// });
|
||||
|
||||
// 전체약관동의 수정 250813
|
||||
(function ($) {
|
||||
if (window.__agreeBound) return; // 중복 바인딩 방지
|
||||
window.__agreeBound = true;
|
||||
|
||||
const $container = $('#pop_agreement');
|
||||
const $items = $container.find('.terms_wrap input[type="checkbox"]'); // agree11, agree21
|
||||
const $all = $container.find('.checkbox_wrap.all input[type="checkbox"]');
|
||||
const $btn = $container.find('#btn_agree');
|
||||
|
||||
function syncAll() {
|
||||
const allChecked = $items.length > 0 && $items.filter(':checked').length === $items.length;
|
||||
$all.prop('checked', allChecked);
|
||||
// 버튼은 disable 하지 않음 (스타일만 조정하고 싶다면 클래스만 토글)
|
||||
// $('.join_btn_wrap').toggleClass('none', !allChecked); <-- 필요 없으면 제거
|
||||
}
|
||||
|
||||
// 전체동의 → 개별
|
||||
$all.on('change', function () {
|
||||
const on = $(this).is(':checked');
|
||||
$items.prop('checked', on);
|
||||
syncAll();
|
||||
});
|
||||
|
||||
// 개별 → 전체동의 동기화
|
||||
$items.on('change', syncAll);
|
||||
|
||||
// 동의 버튼 클릭 시에만 검사
|
||||
$btn.off('click.agree').on('click.agree', function (e) {
|
||||
e.preventDefault();
|
||||
const allChecked = $items.filter(':checked').length === $items.length;
|
||||
if (!allChecked) {
|
||||
alert('약관에 모두 동의해주세요.');
|
||||
return false;
|
||||
}
|
||||
// 통과 시 다음 단계로 진행(필요 시 주석 해제)
|
||||
// $('#pop_agreement').hide();
|
||||
// $('#pop_register_form').show();
|
||||
// $('body').css('overflow','hidden');
|
||||
});
|
||||
|
||||
// 외부에서 팝업 열 때 상태 초기화가 필요하면 이 함수 호출
|
||||
window.resetAgreementUI = function () {
|
||||
$items.prop('checked', false);
|
||||
$all.prop('checked', false);
|
||||
syncAll();
|
||||
// 버튼은 항상 활성
|
||||
$('#btn_agree, #fregister button[type=submit]')
|
||||
.prop('disabled', false)
|
||||
.css('pointer-events', 'auto');
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
|
||||
// 가입완료
|
||||
$(document).ready(function() {
|
||||
$('.join.completion .join_btn_wrap button').click(function() {
|
||||
$('.pop_input_wrap form').children().not('.messages').hide();
|
||||
$('.messages').show();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.join.completion .join_btn_wrap button').click(function() {
|
||||
$('.pop_input_wrap form').children().not('.messages').hide();
|
||||
$('.messages').show();
|
||||
|
||||
// 세 번째 단계에 'on' 클래스 추가하고, 다른 단계에서 'on' 클래스 제거
|
||||
$('.join_progress .join_step').removeClass('on');
|
||||
$('.join_progress .join_step').eq(2).addClass('on');
|
||||
});
|
||||
});
|
||||
|
||||
// 개인정보 보호정책 스크립트
|
||||
$(document).ready(function() {
|
||||
$('.tab_privacy').on('click', function() {
|
||||
$(this).addClass('on');
|
||||
$('.tab_agreement').removeClass('on');
|
||||
$('.content.pri').addClass('show').removeClass('hide');
|
||||
$('.content.agr').removeClass('show').addClass('hide');
|
||||
});
|
||||
$('.tab_agreement').on('click', function() {
|
||||
$(this).addClass('on');
|
||||
$('.tab_privacy').removeClass('on');
|
||||
$('.content.agr').addClass('show').removeClass('hide');
|
||||
$('.content.pri').removeClass('show').addClass('hide');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,109 @@
|
||||
// /kngil/js/qa/qa_write.js
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
/* ==========================
|
||||
* 1. CKEditor 초기화
|
||||
* ========================== */
|
||||
let editorInstance = null;
|
||||
|
||||
const contentEl = document.querySelector('#content');
|
||||
if (contentEl) {
|
||||
ClassicEditor
|
||||
.create(contentEl, {
|
||||
toolbar: [
|
||||
'heading','|',
|
||||
'bold','italic','link',
|
||||
'bulletedList','numberedList','|',
|
||||
'fontColor','fontBackgroundColor','fontSize',
|
||||
'|','blockQuote','insertTable','imageUpload',
|
||||
'undo','redo'
|
||||
],
|
||||
language: 'ko',
|
||||
ckfinder: {
|
||||
uploadUrl: '/kngil/bbs/qa_img_upload.php'
|
||||
}
|
||||
})
|
||||
.then(editor => {
|
||||
editorInstance = editor;
|
||||
})
|
||||
.catch(err => console.error(err));
|
||||
}
|
||||
|
||||
/* ==========================
|
||||
* 2. 폼 submit 검증
|
||||
* ========================== */
|
||||
const form = document.getElementById('qaForm');
|
||||
if (form) {
|
||||
form.addEventListener('submit', (e) => {
|
||||
if (!editorInstance) return;
|
||||
|
||||
const data = editorInstance.getData().trim();
|
||||
if (!data) {
|
||||
e.preventDefault();
|
||||
alert('내용을 입력해주세요.');
|
||||
editorInstance.editing.view.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
contentEl.value = data; // textarea에 반영
|
||||
});
|
||||
}
|
||||
|
||||
/* ==========================
|
||||
* 3. 첨부파일 Drag & Drop
|
||||
* ========================== */
|
||||
const dropZone = document.getElementById('drop-zone');
|
||||
const fileInput = document.getElementById('attach');
|
||||
const fileList = document.getElementById('file-list');
|
||||
|
||||
if (dropZone && fileInput && fileList) {
|
||||
|
||||
let uploadFiles = [];
|
||||
|
||||
dropZone.addEventListener('click', () => fileInput.click());
|
||||
|
||||
dropZone.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
dropZone.classList.add('dragover');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('dragleave', () => {
|
||||
dropZone.classList.remove('dragover');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
dropZone.classList.remove('dragover');
|
||||
addFiles(e.dataTransfer.files);
|
||||
});
|
||||
|
||||
fileInput.addEventListener('change', () => {
|
||||
addFiles(fileInput.files);
|
||||
});
|
||||
|
||||
function addFiles(files) {
|
||||
for (const file of files) {
|
||||
uploadFiles.push(file);
|
||||
}
|
||||
render();
|
||||
syncInput();
|
||||
}
|
||||
|
||||
function render() {
|
||||
fileList.innerHTML = '';
|
||||
uploadFiles.forEach(file => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = `${file.name} (${(file.size / 1024).toFixed(1)} KB)`;
|
||||
fileList.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
function syncInput() {
|
||||
const dt = new DataTransfer();
|
||||
uploadFiles.forEach(f => dt.items.add(f));
|
||||
fileInput.files = dt.files;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,96 @@
|
||||
(function($) {
|
||||
$.fn.viewimageresize = function(selector)
|
||||
{
|
||||
var cfg = {
|
||||
selector: "img"
|
||||
};
|
||||
|
||||
if(typeof selector == "object") {
|
||||
cfg = $.extend(cfg, selector);
|
||||
} else {
|
||||
if(selector) {
|
||||
cfg = $.extend({ selector: selector });
|
||||
}
|
||||
}
|
||||
|
||||
var $img = this.find(cfg.selector);
|
||||
var $this = this;
|
||||
|
||||
$img.removeAttr("height")
|
||||
.css("height", "");
|
||||
|
||||
function image_resize()
|
||||
{
|
||||
var width = $this.width();
|
||||
|
||||
$img.each(function() {
|
||||
if($(this).data("width") == undefined)
|
||||
$(this).data("width", $(this).width());
|
||||
|
||||
if($(this).data("width") > width) {
|
||||
$(this).removeAttr("width")
|
||||
.removeAttr("height")
|
||||
.css("width","")
|
||||
.css("height", "");
|
||||
|
||||
if($(this).data("width") > width) {
|
||||
$(this).css("width", "100%");
|
||||
}
|
||||
} else {
|
||||
$(this).attr("width", $(this).data("width"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(window).on("load", function() {
|
||||
image_resize();
|
||||
});
|
||||
|
||||
$(window).on("resize", function() {
|
||||
image_resize();
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.viewimageresize2 = function(selector)
|
||||
{
|
||||
var cfg = {
|
||||
selector: "img"
|
||||
};
|
||||
|
||||
if(typeof selector == "object") {
|
||||
cfg = $.extend(cfg, selector);
|
||||
} else {
|
||||
if(selector) {
|
||||
cfg = $.extend({ selector: selector });
|
||||
}
|
||||
}
|
||||
|
||||
var $img = this.find(cfg.selector);
|
||||
var $this = this;
|
||||
|
||||
function image_resize()
|
||||
{
|
||||
var width = $this.width();
|
||||
|
||||
$img.each(function() {
|
||||
$(this).removeAttr("width")
|
||||
.removeAttr("height")
|
||||
.css("width","")
|
||||
.css("height", "");
|
||||
|
||||
if($(this).data("width") == undefined)
|
||||
$(this).data("width", $(this).width());
|
||||
|
||||
if($(this).data("width") > width) {
|
||||
$(this).css("width", "100%");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(window).on("resize", function() {
|
||||
image_resize();
|
||||
});
|
||||
|
||||
image_resize();
|
||||
}
|
||||
}(jQuery));
|
||||
Reference in new issue
Block a user