Siteβ―Builder
Editing:
social-links1.html
writable 0666
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Social Links Builder</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <style> :root{ --brand:#0066ff;--bg:#f9fbff;--fg:#111;--chip:#eaf1ff;--err:#c62828; font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif; } *{box-sizing:border-box;margin:0} body{background:var(--bg);color:var(--fg);display:flex;min-height:100vh;align-items:center;justify-content:center} .wrapper{width:clamp(340px,90vw,540px);background:#fff;border-radius:14px;padding:2rem;box-shadow:0 8px 26px rgba(0,0,0,.08)} h1{font-size:1.55rem;margin-bottom:1.3rem;text-align:center} select,button,input{font:inherit} select{width:100%;padding:.6rem .7rem;border:1px solid #ccd2e2;border-radius:8px} button.primary{margin-top:1.2rem;width:100%;padding:.7rem;border:none;border-radius:8px;background:var(--brand);color:#fff;font-weight:600;cursor:pointer} button.primary:hover{filter:brightness(1.08)} .chips{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:1.4rem} .chip{display:flex;align-items:center;background:var(--chip);padding:.35rem .6rem;border-radius:20px;font-size:.9rem} .chip b{margin-right:.35rem} .chip button{background:none;border:none;margin-left:.25rem;font-weight:700;cursor:pointer;color:#444} dialog{border:none;border-radius:12px;padding:0;width:clamp(300px,90vw,420px)} dialog::backdrop{background:rgba(0,0,0,.4)} .modal-body{padding:1.7rem} .modal-body h2{font-size:1.25rem;margin-bottom:.9rem} label{display:block;font-weight:600;margin:.7rem 0 .35rem} input[type=text]{width:100%;padding:.55rem .65rem;border:1px solid #ccd2e2;border-radius:6px} .err{color:var(--err);font-size:.87rem;margin-top:.4rem;display:none} .modal-actions{display:flex;gap:.8rem;padding:1rem 1.7rem;background:#f5f7fe;border-top:1px solid #dde4f5} .modal-actions button{flex:1;padding:.6rem 0;border-radius:8px;font-weight:600;cursor:pointer;border:none} .modal-actions .save{background:var(--brand);color:#fff} .modal-actions .cancel{background:#e0e5ee} #jsonOut{width:100%;margin-top:1.8rem;height:120px;font-family:monospace;font-size:.85rem} </style> </head> <body> <div class="wrapper"> <h1>Add your social links</h1> <select id="networkSel"> <option value="">βΒ choose a networkΒ β</option> </select> <button class="primary" id="addBtn" disabled>Add link</button> <div class="chips" id="chips"></div> <textarea id="jsonOut" readonly></textarea> <input type="hidden" id="linksJson" name="social_links"> </div> <dialog id="modal"> <form id="modalForm" method="dialog"> <div class="modal-body"> <h2 id="modalTitle"></h2> <label id="inputLabel"></label> <input type="text" id="valueInput" required> <div class="err" id="errMsg">Please match the required format.</div> </div> <div class="modal-actions"> <button type="button" class="cancel" id="cancelBtn">Cancel</button> <button type="submit" class="save">Save</button> </div> </form> </dialog> <script> /* ---------- config ---------- */ const networks = { facebook : {label:'Facebook page', type:'handle', url:'https://facebook.com/', pattern:/^[A-Za-z0-9.]{3,}$/}, instagram: {label:'Instagram handle', type:'handle', url:'https://instagram.com/',pattern:/^[A-Za-z0-9_.]{2,}$/}, twitter : {label:'@username', type:'handle', url:'https://twitter.com/', pattern:/^[A-Za-z0-9_]{1,15}$/}, tiktok : {label:'TikTok handle', type:'handle', url:'https://tiktok.com/@', pattern:/^[A-Za-z0-9_.]{2,}$/}, linkedin : {label:'Company/ID URL', type:'url'}, youtube : {label:'Channel / URL', type:'url'}, pinterest: {label:'Username or URL', type:'url'}, reddit : {label:'r/ subreddit', type:'handle', url:'https://reddit.com/r/',pattern:/^[A-Za-z0-9_]{3,}$/}, snapchat : {label:'Snapchat handle', type:'handle', url:'https://snapchat.com/add/',pattern:/^[A-Za-z0-9._-]{3,}$/}, whatsapp : {label:'Full share URL', type:'url'}, telegram : {label:'@channel / URL', type:'url'}, gitlab : {label:'GitLab URL', type:'url'}, github : {label:'GitHub username', type:'handle', url:'https://github.com/', pattern:/^[A-Za-z0-9-]{1,39}$/}, twitch : {label:'Twitch channel', type:'handle', url:'https://twitch.tv/', pattern:/^[A-Za-z0-9_]{4,25}$/}, nextdoor : {label:'Nextdoor URL', type:'url'}, bbb : {label:'BBB profile URL', type:'url'} }; /* ---------- populate dropdown ---------- */ const sel = document.getElementById('networkSel'); for (const key of Object.keys(networks)) { const opt = document.createElement('option'); opt.value = key; opt.textContent = key.charAt(0).toUpperCase()+key.slice(1); sel.appendChild(opt); } /* ---------- state ---------- */ let links = []; // {net:'facebook', value:'rfsafe', url:'https://..'} /* ---------- helpers ---------- */ function refreshChips(){ const zone = document.getElementById('chips'); zone.innerHTML=''; links.forEach((l,i)=>{ const chip=document.createElement('span'); chip.className='chip'; chip.innerHTML='<b>'+l.net+':</b>'+l.value+ '<button aria-label="Delete" data-i="'+i+'">β</button>'; zone.appendChild(chip); }); /* hidden + preview */ document.getElementById('linksJson').value=JSON.stringify(links); document.getElementById('jsonOut').value=JSON.stringify(links,null,2); } /* ---------- modal logic ---------- */ const dlg = document.getElementById('modal'); const title = document.getElementById('modalTitle'); const inp = document.getElementById('valueInput'); const lbl = document.getElementById('inputLabel'); const err = document.getElementById('errMsg'); document.getElementById('addBtn').onclick=()=>openModal(sel.value); sel.onchange = ()=>{document.getElementById('addBtn').disabled = !sel.value}; function openModal(net){ const cfg = networks[net]; title.textContent='Add '+net.charAt(0).toUpperCase()+net.slice(1); lbl.textContent=cfg.label; inp.placeholder=cfg.type==='handle' ? cfg.label : 'https://β¦'; inp.value=''; err.style.display='none'; dlg.showModal(); } document.getElementById('cancelBtn').onclick=()=>dlg.close(); dlg.addEventListener('close', ()=>{inp.value='';}); document.getElementById('modalForm').addEventListener('submit',e=>{ e.preventDefault(); const net=sel.value, cfg=networks[net], v=inp.value.trim(); if(!v) return; /* validation */ if(cfg.type==='handle' && cfg.pattern && !cfg.pattern.test(v)){ err.style.display='block'; return; } if(cfg.type==='url' && !/^https?:\/\//i.test(v)){ err.style.display='block'; return; } err.style.display='none'; links.push({ net, value:v, url: cfg.type==='handle' ? cfg.url+v : v }); refreshChips(); dlg.close(); }); /* chip delete */ document.getElementById('chips').addEventListener('click',e=>{ if(e.target.tagName==='BUTTON'){ links.splice(e.target.dataset.i,1); refreshChips(); } }); </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel