کاوشهای هویت مارکتینگ ب.آ
منطقهای طراحی، صفحههای فرود تعاملی و تم اینستاگرام؛ برای انتخاب یک مسیر.
منطق طراحی
لندینگ تعاملی
تم اینستاگرام
Enter شروع · F تمامصفحه
←→ منطق بعدی/قبلی123 زبانههاC مقایسهS ستارهEsc فهرست
blob('A' + i));
return (landCache[file] = URL.createObjectURL(new Blob([html], { type: 'text/html' })));
}
// ---------- stars ----------
let stars = new Set();
try { stars = new Set(JSON.parse(localStorage.getItem('ba-stars') || '[]')); } catch (e) {}
const saveStars = () => { try { localStorage.setItem('ba-stars', JSON.stringify([...stars])); } catch (e) {} };
function toggleStar(id) { stars.has(id) ? stars.delete(id) : stars.add(id); saveStars(); toast(stars.has(id) ? `★ ${fa(id)} به فهرست کوتاه اضافه شد` : `${fa(id)} از فهرست کوتاه حذف شد`); renderMenu(); syncStar(); }
const toastEl = $('#toast'); let tt;
function toast(msg) { toastEl.textContent = msg; toastEl.classList.add('on'); clearTimeout(tt); tt = setTimeout(() => toastEl.classList.remove('on'), 1800); }
// ---------- screens ----------
const screens = { cover: $('#cover'), menu: $('#menu'), view: $('#view') };
let cur = 'cover';
function show(s) { cur = s; Object.entries(screens).forEach(([k, el]) => el.classList.toggle('on', k === s)); if (s !== 'view') clearStage(); }
// Cover
$('#sLogic').textContent = fa(LOGICS.length);
$('#sLand').textContent = fa(LOGICS.reduce((a, l) => a + l.land.length, 0));
$('#sIg').textContent = fa(LOGICS.reduce((a, l) => a + l.ig.length, 0));
const files = LOGICS.flatMap(l => l.land.map(x => x.file));
const mq = $('#marquee');
for (let r = 0; r < 3; r++) {
const row = document.createElement('div'); row.className = 'mrow' + (r % 2 ? ' rev' : '');
const list = files.slice(r * 8).concat(files.slice(0, r * 8));
row.innerHTML = [...list, ...list].map(f => `
`).join('');
mq.appendChild(row);
}
$('#startBtn').addEventListener('click', () => show('menu'));
$('#toCover').addEventListener('click', () => show('cover'));
// Menu
let famFilter = 'all';
const famChips = $('#famChips');
function renderChips() {
famChips.innerHTML = `` + FAMS.map(f => ``).join('') + ``;
}
famChips.addEventListener('click', e => { const b = e.target.closest('.chip'); if (!b) return; famFilter = b.dataset.f; renderMenu(); });
function renderMenu() {
renderChips();
const grid = $('#grid'); let html = '', i = 0;
FAMS.forEach(f => {
const items = LOGICS.filter(l => l.fam === f.k && (famFilter === 'all' || famFilter === f.k || (famFilter === 'star' && stars.has(l.id))));
if (!items.length) return;
html += `${f.n}${fa(items.length)} منطق
`;
items.forEach(l => {
const tags = [`${fa(l.land.length)} لندینگ`, l.ig.length ? `${l.ig.length > 1 ? fa(l.ig.length) + ' تم اینستاگرام' : 'تم اینستاگرام'}` : '', l.land.length > 1 || l.ig.length > 1 ? 'واریشن رنگی' : ''].join('');
html += `
${fa(l.id)}${l.name}${l.en}
${l.idea}
${tags}
`;
});
});
grid.innerHTML = html || 'هنوز منطقی ستاره نخورده. در هر منطق کلید S را بزنید.
';
}
$('#grid').addEventListener('click', e => {
const s = e.target.closest('[data-star]'); if (s) { e.stopPropagation(); toggleStar(s.dataset.star); return; }
const c = e.target.closest('.card'); if (c) open(c.dataset.id, 'land');
});
// ---------- Logic view ----------
const state = { id: null, tab: 'land', v: { board: 0, land: 0, ig: 0 }, cmp: null, cmpV: 0 };
const byId = id => LOGICS.find(l => l.id === id);
const order = () => LOGICS.filter(l => famFilter === 'star' ? stars.has(l.id) : (famFilter === 'all' || l.fam === famFilter));
const stage = $('#stage'), tabsEl = $('#tabs'), pill = $('.pill', tabsEl), varsEl = $('#vars');
function open(id, tab) { state.id = id; state.v = { board: 0, land: 0, ig: 0 }; state.cmpV = 0; if (tab) state.tab = tab; const l = byId(id); if (!l[state.tab].length) state.tab = 'land'; show('view'); render(); }
function clearStage() { stage.innerHTML = ''; }
function movePill() { const b = $(`button[data-t="${state.tab}"]`, tabsEl); pill.style.left = b.offsetLeft + 'px'; pill.style.width = b.offsetWidth + 'px'; }
function syncStar() { $('#starBtn').classList.toggle('on', stars.has(state.id)); }
function paneContent(pane, l, tab, vi) {
const list = l[tab];
if (!list.length) { pane.insertAdjacentHTML('beforeend', `برای «${l.name}» ${tab === 'ig' ? 'تم اینستاگرام' : 'این بخش'} طراحی نشده است.
این منطق یک واریشن لندینگ است.
`); return; }
const item = list[Math.min(vi, list.length - 1)];
if (tab === 'land') {
const ld = document.createElement('div'); ld.className = 'loading'; ld.innerHTML = 'در حال بارگذاری لندینگ…
'; pane.appendChild(ld);
const f = document.createElement('iframe'); f.title = l.name + ' — ' + item.n; f.addEventListener('load', () => ld.remove(), { once: true });
pane.appendChild(f);
requestAnimationFrame(() => { f.src = landURL(item.file); });
} else {
const w = document.createElement('div'); w.className = 'imgWrap';
if (tab === 'board' && item.key >= 'b22' && item.key <= 'b27') w.style.setProperty('--mw', '1300px');
const img = new Image(); img.alt = l.name + ' — ' + item.n; img.decoding = 'async';
img.onload = () => img.classList.add('ld'); img.src = imgSrc(item.key);
img.addEventListener('click', () => w.classList.toggle('zoom'));
w.appendChild(img); pane.appendChild(w);
}
}
function render() {
const l = byId(state.id);
$('#vNum').textContent = fa(l.id); $('#vName').textContent = l.name; $('#vEn').textContent = l.en;
$$('button', tabsEl).forEach(b => { b.classList.toggle('on', b.dataset.t === state.tab); b.disabled = !l[b.dataset.t].length; });
requestAnimationFrame(movePill);
syncStar();
// variant switcher
const list = l[state.tab];
varsEl.innerHTML = list.length > 1 ? list.map((x, i) => ``).join('') : '';
$('#newTab').style.display = state.tab === 'land' ? '' : 'none';
// panes
clearStage();
const p1 = document.createElement('div'); p1.className = 'pane'; stage.appendChild(p1);
if (state.cmp) {
const c = byId(state.cmp);
p1.classList.add('hasLbl'); p1.insertAdjacentHTML('beforeend', `${fa(l.id)}${l.name}${list[state.v[state.tab]] ? '· ' + list[state.v[state.tab]].n : ''}
`);
const p2 = document.createElement('div'); p2.className = 'pane hasLbl'; stage.appendChild(p2);
const cl = c[state.tab];
p2.insertAdjacentHTML('beforeend', `${fa(c.id)}${c.name}${cl.length > 1 ? `
` : ''}
`);
const sel = $('select', p2); if (sel) sel.addEventListener('change', () => { state.cmpV = +sel.value; render(); });
$('#cmpClose').addEventListener('click', () => { state.cmp = null; render(); });
paneContent(p2, c, state.tab, state.cmpV);
}
paneContent(p1, l, state.tab, state.v[state.tab]);
}
tabsEl.addEventListener('click', e => { const b = e.target.closest('button[data-t]'); if (!b || b.disabled) return; state.tab = b.dataset.t; render(); });
varsEl.addEventListener('click', e => { const b = e.target.closest('button[data-v]'); if (!b) return; state.v[state.tab] = +b.dataset.v; render(); });
function step(d) { const list = order(); if (!list.length) return; let i = list.findIndex(l => l.id === state.id); i = (i + d + list.length) % list.length; const tab = state.tab; state.id = list[i].id; state.v = { board: 0, land: 0, ig: 0 }; state.tab = list[i][tab].length ? tab : 'land'; render(); }
$('#prevBtn').addEventListener('click', () => step(-1));
$('#nextBtn').addEventListener('click', () => step(1));
$('#toMenu').addEventListener('click', () => { state.cmp = null; show('menu'); });
$('#starBtn').addEventListener('click', () => toggleStar(state.id));
$('#newTab').addEventListener('click', () => { const l = byId(state.id); window.open(landURL(l.land[state.v.land].file), '_blank'); });
function fullscreen() { if (!document.fullscreenElement) document.documentElement.requestFullscreen().catch(() => {}); else document.exitFullscreen(); }
$('#fsBtn').addEventListener('click', fullscreen);
// Compare picker
const pick = $('#pickModal');
function openPick() {
$('#pickGrid').innerHTML = LOGICS.filter(l => l.id !== state.id).map(l => ``).join('');
pick.classList.add('on');
}
$('#cmpBtn').addEventListener('click', () => { if (state.cmp) { state.cmp = null; render(); } else openPick(); });
pick.addEventListener('click', e => { const b = e.target.closest('button[data-id]'); if (b) { state.cmp = b.dataset.id; state.cmpV = 0; pick.classList.remove('on'); render(); } else if (e.target === pick) pick.classList.remove('on'); });
// Keyboard
addEventListener('keydown', e => {
if (e.target.closest && e.target.closest('input, select')) return;
const k = e.key;
if (pick.classList.contains('on')) { if (k === 'Escape') pick.classList.remove('on'); return; }
if (k === 'f' || k === 'F' || k === 'ف') { fullscreen(); return; }
if (cur === 'cover') { if (k === 'Enter' || k === ' ' || k === 'ArrowLeft') show('menu'); return; }
if (cur === 'menu') { if (k === 'Escape') show('cover'); return; }
if (k === 'Escape') { if (state.cmp) { state.cmp = null; render(); } else show('menu'); }
else if (k === 'ArrowLeft') step(1);
else if (k === 'ArrowRight') step(-1);
else if (k === '1' || k === '2' || k === '3') { const t = TABS[+k - 1]; if (byId(state.id)[t].length) { state.tab = t; render(); } }
else if (k === 's' || k === 'S' || k === 'س') toggleStar(state.id);
else if (k === 'c' || k === 'C' || k === 'ز') $('#cmpBtn').click();
else if (k === 'v' || k === 'V') { const n = byId(state.id)[state.tab].length; if (n > 1) { state.v[state.tab] = (state.v[state.tab] + 1) % n; render(); } }
});
addEventListener('resize', () => { if (cur === 'view') movePill(); });
renderMenu();
})();