PageSourceSearch

https://inkas.org/assets/design/donation-page.js

js inkas.org collected 2026-10-03 00:51:55 UTC 8,180 bytes, 43 lines download raw bytes

1import {donationConfig} from './donation-config.js';
2const escape = value => String(value ?? '').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
3export function renderDonation({tr, url, currency = '', config = donationConfig}) {
4  const bank = ['bank','krw','usd'].includes(currency), card = currency === 'card';
5  const ko = (english,korean) => korean, en = english => english;
6  const choice = `<nav class="donation-method-nav" aria-label="${tr('Donation method','기부 방법')}"><a href="${url('donate/bank')}" ${bank ? 'aria-current="page"' : ''}><span aria-hidden="true">🏦</span>${tr("Donate via domestic / int'l wire","계좌 이체로 기부하기")}</a><a aria-disabled="true" tabindex="-1" ${card ? 'aria-current="page"' : ''}><span aria-hidden="true">💳</span>${tr('Donate by card','카드로 기부하기')}</a></nav>`;
7
8  const copy = (value, label) => `<button type="button" class="button donation-copy" data-donation-copy="${escape(value)}">${label}</button>`;
9  const row = (label,value,canCopy=false) => `<div><dt>${label}</dt><dd>${escape(value)}${canCopy ? copy(value,'Copy') : ''}</dd></div>`;
10
11  const bankCard = `<section class="donation-paper donation-bank" lang="ko" aria-labelledby="bank-title"><div class="donation-paper-top"><div><span class="involved-eyebrow">${ko('BANK TRANSFER','계좌이체')}</span><h2 id="bank-title">${ko('Donate by bank transfer','국내 계좌 이체 안내')}</h2></div><span class="donation-currency-stamp">₩</span></div><p class="donation-bank-name">${ko('KB Kookmin Bank','KB국민은행')}</p><p class="donation-account-number">${escape(config.account)}</p><p class="donation-beneficiary">${ko('Account holder','예금주')}<br><strong>${escape(config.beneficiary)}</strong></p>${copy(config.account.replace(/\D/g,''),ko('Copy account number','계좌번호 복사'))}<p class="donation-copy-hint">${ko('Copy the number, then paste it into your banking app.','계좌번호를 복사한 뒤 은행 앱에 붙여넣어주세요.')}</p><p class="donation-copy-status" role="status" aria-live="polite"></p></section>`;
12  const wire = `<section class="donation-wire" lang="en" aria-labelledby="wire-title"><span class="involved-eyebrow">${en('BANK TRANSFER TO KOREA','한국 계좌로 해외송금')}</span><h2 id="wire-title">${tr('International wire transfer','해외송금 안내')}</h2><dl class="donation-wire-details">${row(en('Bank','은행'),config.bank)}${row('SWIFT / BIC',config.swift,true)}${row(en('Account number','계좌번호'),config.account,true)}${row(en('Account holder (Korean)','예금주 (한글)'),config.beneficiary)}${row(en('Bank address','은행 주소'),config.bankAddress)}${config.beneficiaryEnglish ? row(en('Beneficiary’s registered English name','은행 등록 영문 예금주'),config.beneficiaryEnglish) : ''}</dl><p class="donation-copy-status" role="status" aria-live="polite"></p><p>${en('KB Kookmin Bank does not require a separate routing number or clearing code. Use the SWIFT/BIC above.','국민은행은 별도의 Routing Number나 Clearing Code를 요구하지 않습니다. 위 SWIFT/BIC를 사용해주세요.')}</p><p class="donation-wire-note">${en('Before sending, contact InKAS for the exact English beneficiary name registered with the bank and any additional details your sending bank requests.','송금 전 InKAS에 은행에 등록된 정확한 영문 예금주와 송금은행에서 요구하는 추가 정보를 확인해주세요.')}</p><a class="involved-link" href="${url('contact?topic=donations')}">${en('Request complete wire instructions','해외송금 정보 문의')} ↗</a><a class="donation-bank-source" href="https://omoney.kbstar.com/quics?page=C102552" target="_blank" rel="noopener noreferrer">${en('KB’s official remittance guide','국민은행 공식 해외송금 안내')} ↗</a></section>`;
13  const cardPage = `<section class="donation-paper donation-card-payment"><span class="involved-eyebrow">EXIMBAY</span><h2>${tr("Card donations","카드 기부")}</h2><p>${tr("Card donations will be processed through Eximbay.","카드 기부는 Eximbay를 통해 진행됩니다.")}</p><div class="donation-availability" role="note"><strong>
13${tr("Card payments are being prepared.","카드 결제를 준비하고 있습니다.")}</strong><p>${tr("Online card donations are not available yet. You can currently donate by bank transfer.","온라인 카드 기부는 아직 이용할 수 없습니다. 현재는 계좌 이체로 기부하실 수 있습니다.")}</p></div><a class="button donation-raised-button" href="${url("donate/bank")}">${tr("Donate via domestic / int\'l wire","계좌 이체로 기부하기")} ↗</a></section>`;
14  const context = `<aside class="donation-context"><div class="donation-context-copy"><h2>${tr("Donation enquiries","후원 안내")}</h2><p>${tr("For donation receipts, regular giving, program sponsorship or company partnerships, contact InKAS.","기부금 영수증, 정기 후원, 프로그램 후원과 기업·단체 협력은 InKAS에 문의해주세요.")}</p></div><div class="donation-context-links"><a class="involved-link" href="${url('contact?topic=donations')}">${tr("Contact InKAS","후원 문의")} ↗</a><a class="involved-link" href="${url("transparency")}">${tr("Donation disclosures","기부금 공시 보기")} ↗</a></div></aside>`;
15  return `<div class="donation-page wrap" data-preserve-text><a class="involved-link" href="${url("involved#support")}">← ${tr("Donations & partnerships","후원·협력")}</a><header class="donation-heading"><span class="involved-eyebrow">InKAS / ${tr("DONATIONS","후원")}</span><h1>${bank ? tr("Donate via domestic / int\'l wire","계좌 이체로 기부하기") : card ? tr("Donate by card","카드로 기부하기") : tr("Donate to InKAS","InKAS 후원하기")}</h1><p>${tr("Individuals, companies and groups can support homeland visits, birth-family reunions, language education and cultural exchange.","개인·기업·단체의 후원으로 모국방문, 친가족 만남, 언어 교육과 문화 교류를 지원합니다.")}</p></header>${choice}${bank ? `<div class="donation-layout donation-transfer-layout">${bankCard}${wire}</div>${context}` : card ? `<div class="donation-layout donation-card-layout">${cardPage}</div>${context}` : context}</div>`;
16}
17export async function copyDonationText(text, {clipboard = globalThis.navigator?.clipboard, document = globalThis.document} = {}) {
18  try { if(clipboard?.writeText) { await clipboard.writeText(text); return true; } } catch {}
19  const field = document.createElement('textarea');
20  field.value = text; field.readOnly = true;
21  field.style.cssText = 'position:fixed;left:0;top:0;opacity:0;font-size:16px';
22  document.body.append(field); field.focus(); field.select(); field.setSelectionRange(0,text.length);
23  let copied = false;
24  try { copied = document.execCommand('copy'); } catch {} finally { field.remove(); }
25  return copied;
26}
27export function bindDonation(root, {tr: optionsTr}) {
28  for(const button of root.querySelectorAll('[data-donation-copy]')) button.addEventListener('click', async () => {
29    const text = button.dataset.donationCopy;
30    const section = button.closest('section');
31    const status = section.querySelector('.donation-copy-status');
32    const copied = await copyDonationText(text);
33    const tr = section.lang === 'en' ? en => en : section.lang === 'ko' ? (en,ko) => ko : optionsTr;
34    button.focus({preventScroll:true});
35    if(copied) { status.textContent = tr('Copied. Paste it into your banking app.','복사했어요. 은행 앱에 붙여넣어주세요.'); }
36    else {
37      status.textContent = tr('Select and copy the number below.','아래 내용을 길게 눌러 복사해주세요.');
38      let field = section.querySelector('.donation-manual-copy');
39      if(!field) { field = document.createElement('textarea'); field.className = 'donation-manual-copy'; field.readOnly = true; field.setAttribute('aria-label',tr('Bank details to copy','복사할 은행 정보')); status.after(field); }
40      field.value = text; field.focus(); field.select(); field.setSelectionRange(0,text.length);
41    }
42  });
43}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.