Siteβ―Builder
Editing:
businessPromptinator.js
writable 0666
/* Promptinator β 2025β07β24Β Β (business edition + Hβtoken + flexible flags + pencil toggle + toolbar + blankβprompt AI guard) ------------------------------------------------------------------------- */ export default class Promptinator { /* βββββββββββ static helpers βββββββββββ */ static _lastMeta = []; static _lastState = []; static _hasE = false; static _escAttr (s = '') { return String(s) .replace(/&/g,'&').replace(/"/g,'"') .replace(/</g,'<').replace(/>/g,'>'); } /* βββββββββββ init βββββββββββ */ static init ({ mount, defaultPrompt }) { const prompt = mount.dataset.prompt || defaultPrompt || mount.textContent.trim(); let template = prompt; /* now recognises H */ const RX = /\[(?:([A-DEIH]?)-)?([^~|\-\]]*)(?:-([^~\]]*))?(?:~([^~]+)~)?\]/ig; const state = {}, meta = []; /* accept edit/think OR dataβedit/dataβthink */ const valEdit = mount.dataset.edit ?? mount.getAttribute('edit') ?? '1'; const valThink = mount.dataset.think ?? (mount.hasAttribute('think') ? mount.getAttribute('think') : '1'); const allowEdit = valEdit !== '0' && valEdit !== 'false'; const allowThink = valThink !== '0' && valThink !== 'false'; /* ---------- business helpers ---------- */ const biz = window.businessData || null; let phParam = new URLSearchParams(window.location.search).get('ph'); if (!phParam) { const segs = window.location.pathname.split('/').filter(Boolean); phParam = segs.find(s=>/^\d{10}$/.test(s)) || null; } const isBiz = biz && phParam && biz.phone && biz.phone === phParam; function applyBiz (st, mt) { if (!isBiz) return; const nonEmpty = v => v!==null && v!==undefined && String(v).trim()!==''; mt.forEach((m,i)=>{ const lab = (m.lab||'').toLowerCase(); const set = v=>{ if(nonEmpty(v)) st[i]=v; }; switch(lab){ case 'name':set(biz.name);return; case 'slogan':set(biz.slogan);return; case 'description':set(biz.description);return; case 'address':set(biz.address);return; case 'city':set(biz.city);return; case 'state':set(biz.state);return; case 'zip':set(biz.zip);return; case 'phone':set(biz.phone);return; case 'website':set(biz.website);return; case 'email':set(biz.email);return; } if(m.cmd==='C'){ if(lab.startsWith('service')&&Array.isArray(biz.tags)){ m.opts=biz.tags;if(!st[i].length&&biz.tags.length)st[i]=[biz.tags[0]]; } if(lab.startsWith('location')&&Array.isArray(biz.location_tags)){ m.opts=biz.location_tags;if(!st[i].length&&biz.location_tags.length)st[i]=[biz.location_tags[0]]; } } }); } /* ---------- renderer ---------- */ function render () { meta.length=0; let idx=0; template.replace(RX,(_,cmd='',lab='',ops='',def='')=>{ lab=lab.trim(); const opts=ops.split('|').filter(Boolean); if(!(idx in state)){ state[idx]=cmd==='C' ?(def?def.split(',').map(v=>v.trim()):opts.slice(0,1)) :(def||opts[0]||lab); } meta.push({cmd:cmd||'A',lab,opts,def}); idx++; return''; }); if(!render._bizApplied){applyBiz(state,meta); render._bizApplied=true;} idx=0; const html = template.replace(RX,(_,cmd='',lab='')=>{ lab=lab.trim(); const val=state[idx]; let out; if(cmd==='C'){ const list=(Array.isArray(val)?val:[val]).filter(Boolean); if(!list.length)list.push('+'); out=list.map(v=>`<span class="token" data-i="${idx}" data-label="${lab}">[${v}]</span>`).join(', '); }else if(cmd==='E'){ out=`<button class="token e-btn" data-i="${idx}" data-label="${lab}">${/^\S+@\S+\.\S+$/.test(val)?'Send':'Submit'}</button>`; }else if(cmd==='H'){ out=`<span class="token hidden-dot" title="${Promptinator._escAttr(lab)}" data-i="${idx}" data-label="${lab}" aria-hidden="true">β’</span>`; }else{ out=`<span class="token" data-i="${idx}" data-label="${lab}">[${val}]</span>`; } idx++; return out; }); const hasE = meta.some(m=>m.cmd==='E'); Promptinator._hasE = hasE; const noPrompt = template.trim()===''; const showAI = allowThink && !hasE && !noPrompt; const helper = noPrompt && allowEdit ? `<div class="promptinator-helper">π‘ Click the pencilΒ (βοΈ)Β toΒ addΒ aΒ prompt.</div>` : ''; const aiButtons = showAI ? ` <div class="ai-buttons" style="margin-top:1em;display:flex;flex-wrap:wrap;gap:.6em;"> <a class="ai-btn chatgpt" target="_blank" style="display:inline-flex;align-items:center;gap:.3em; background:#5c3bff;color:#fff;font-weight:600; border-radius:7px;padding:.4em 1.2em;text-decoration:none;"> π§ ChatGPT </a> <a class="ai-btn perplexity" target="_blank" style="display:inline-flex;align-items:center;gap:.3em; background:#2357d7;color:#fff;font-weight:600; border-radius:7px;padding:.4em 1.2em;text-decoration:none;"> π Perplexity </a> <a class="ai-btn copilot" target="_blank" style="display:inline-flex;align-items:center;gap:.3em; background:#047C3E;color:#fff;font-weight:600; border-radius:7px;padding:.4em 1.2em;text-decoration:none;"> π€ Copilot </a> </div>`:''; promptText.innerHTML = (noPrompt ? '' : html.replace(/\n/g,'<br>')) + helper + aiButtons; editor.classList.toggle('promptinator--empty', noPrompt); if(showAI){ let i=0; const full=template.replace(RX,()=>{ const v=state[i++]; return Array.isArray(v)?v.join(', '):v; }); promptText.querySelector('.chatgpt').href = 'https://chat.openai.com/?prompt='+encodeURIComponent(full); promptText.querySelector('.perplexity').href = 'https://www.perplexity.ai/search?q='+encodeURIComponent(full); promptText.querySelector('.copilot').href = 'https://copilot.microsoft.com/?q='+encodeURIComponent(full); } } /* render */ /* ---------- editor / pencil toggle ---------- */ const editor=document.createElement('div'); editor.className='Promptinator'; editor.innerHTML=` <div style="display:flex;align-items:baseline;gap:.5em;"> ${allowEdit?'<span id="edit-link" style="cursor:pointer">βοΈ</span>':''} <div class="prompt-text" style="flex:1 1 auto;"></div> </div> ${allowEdit?`<form id="edit-form" style="display:none;margin-top:.6em;"> <textarea style="width:100%;min-height:90px;font-family:monospace;"></textarea> <div style="text-align:right;margin-top:.7em;"><button type="submit">SaveΒ &Β Update</button></div> </form>`:''}`; mount.innerHTML=''; mount.append(editor); const promptText=editor.querySelector('.prompt-text'); if(allowEdit){ const link=editor.querySelector('#edit-link'), form=editor.querySelector('#edit-form'), ta=form.querySelector('textarea'); link.onclick=()=>{ const closed=getComputedStyle(form).display==='none'; if(closed){ form.style.display=''; ta.value=template; ta.focus(); Promptinator.enhanceTextarea?.(ta); }else{ form.style.display='none'; } }; form.onsubmit=e=>{ e.preventDefault(); template=ta.value.trim(); Object.keys(state).forEach(k=>delete state[k]); render._bizApplied=false; render(); form.style.display='none'; }; } /* ---------- CSS injection (toolbar + helper + hidden-dot) ---------- */ if(!Promptinator._styleInjected){ const css=` .promptinator-bar{display:flex;align-items:center;gap:.55em;margin-bottom:.35em;} .promptinator-select{flex:1 1 auto;padding:.3em .55em;} .promptinator-help{flex:0 0 auto;font-size:.9rem;color:#176edc;text-decoration:underline;cursor:pointer;} .promptinator-bar+textarea{width:100%;box-sizing:border-box;} .Promptinator.promptinator--empty .ai-buttons{display:none!important;} .promptinator-helper{margin-top:1em;font-size:.9em;color:#555;background:#fff9c4;text-align:center;padding:.5em .8em;border-radius:5px;} .hidden-dot{cursor:pointer;padding:0 .2em;} `; const st=document.createElement('style'); st.appendChild(document.createTextNode(css)); document.head.appendChild(st); Promptinator._styleInjected=true; } render(); /* token click β popup */ mount.addEventListener('click',e=>{ if(!e.target.matches('.token'))return; const i=+e.target.dataset.i, info=meta[i], val=state[i]; if(info.cmd==='E'){Promptinator._lastMeta=meta.slice();Promptinator._lastState=Object.assign([],state);} Promptinator._popup(info,Array.isArray(val)?val.join(', '):val,v=>{ state[i]=info.cmd==='C'?v.split(',').map(s=>s.trim()).filter(Boolean):v; render(); }); }); } /* init */ /* βββββββββββ popup (token editor) βββββββββββ */ static _popup(meta,cur,done){ let dlg=document.getElementById('promptinator-dlg'); if(!dlg){ dlg=document.createElement('dialog'); dlg.id='promptinator-dlg'; document.body.append(dlg); dlg.addEventListener('click',e=>{if(e.target===dlg)dlg.close();}); dlg.addEventListener('cancel',e=>{e.preventDefault();dlg.close();}); } const prettify=s=>s.replace(/[-_]/g,' ').replace(/\b\w/g,c=>c.toUpperCase()); const nice=meta.lab&&meta.lab.trim()?prettify(meta.lab): (cur||{A:'Text Input',B:'Choice',C:'Options',D:'Dropdown',E:'Send',I:'URL Picker',H:'Hidden'}[meta.cmd]||'Input'); const showPH = Promptinator._hasE && cur === meta.def; const phAttr = showPH ? ` placeholder="${Promptinator._escAttr(cur)}"` : ''; const valAttr= showPH ? '' : Promptinator._escAttr(cur); let inner=''; switch(meta.cmd){ /* A and new H share the same editor */ case 'A': case 'H': inner=`<label>${nice} <textarea style="width:100%;font-size:1rem;" rows="4"${phAttr}>${valAttr}</textarea> </label> <div style="text-align:right;margin-top:.7em;"><button type="button">Done</button></div>`; break; case 'B': inner=`<fieldset><legend>${nice}</legend>`+ meta.opts.map(o=>`<label><input type="radio" name="r" value="${o}" ${o===cur?'checked':''}> ${o}</label>`).join('')+ `</fieldset>`; break; case 'C':{ let opts=meta.opts; const labLow=(meta.lab||'').toLowerCase(); if(window.businessData){ if(labLow.startsWith('service')&&Array.isArray(window.businessData.tags))opts=window.businessData.tags; if(labLow.startsWith('location')&&Array.isArray(window.businessData.location_tags))opts=window.businessData.location_tags; } inner=`<fieldset><legend>${nice}</legend>`+ opts.map(o=>`<label><input type="checkbox" value="${o}" ${cur.split(', ').includes(o)?'checked':''}> ${o}</label>`).join('')+ `</fieldset><div style="text-align:right;margin-top:.7em;"><button type="button">Done</button></div>`; break; } case 'D':{ let opts=meta.opts; if(opts.length===1&&/^\d+$/.test(opts[0]))opts=Array.from({length:+opts[0]},(_,i)=>String(i+1)); inner=`<label>${nice}<select>`+ opts.map(o=>`<option${o===cur?' selected':''}>${o}</option>`).join('')+ `</select></label>`; break; } case 'I': inner=`<label>${nice}<select>`+ (showPH?`<option disabled selected>${Promptinator._escAttr(cur)}</option>`:'')+ meta.opts.map(u=>`<option${u===cur?' selected':''}>${u}</option>`).join('')+ `</select></label> <iframe hidden style="width:100%;height:300px;border:1px solid #ccc;margin-top:.6em;"></iframe> <div style="text-align:right;margin-top:.7em;"><button type="button">Use site</button></div>`; break; case 'E':{ const isEmail=/^\S+@\S+\.\S+$/.test(cur); inner=`<div style="padding:1em 0;text-align:center;font-size:1.1rem;font-weight:600;">${nice}</div> <div style="text-align:right;margin-top:.7em;"><button type="button">${isEmail?'Send':'Submit'}</button></div>`; break; } default: inner=`<label>${nice}<input type="text" style="width:100%;font-size:1rem;"${phAttr} value="${valAttr}"></label> <div style="text-align:right;margin-top:.7em;"><button type="button">Done</button></div>`; } dlg.innerHTML=`<div class="popup-body">${inner}</div>`; dlg.showModal(); const pb=dlg.querySelector('.popup-body'); /* --- perβcommand behaviour (A/H share code) --- */ const commit=v=>{done(v);dlg.close();}; if(meta.cmd==='A'||meta.cmd==='H'){ const ta=pb.querySelector('textarea'); ta.focus(); pb.querySelector('button').onclick=()=>commit(ta.value); return; } if(meta.cmd==='B'){pb.onclick=e=>{if(e.target.name==='r')commit(e.target.value);};return;} if(meta.cmd==='C'){pb.querySelector('button').onclick=()=>commit([...pb.querySelectorAll('input:checked')].map(i=>i.value).join(', ')||cur);return;} if(meta.cmd==='D'){pb.querySelector('select').onchange=e=>commit(e.target.value);return;} if(meta.cmd==='I'){ const sel=pb.querySelector('select'),fr=pb.querySelector('iframe'); sel.onchange=()=>{fr.hidden=false;fr.src=sel.value;}; pb.querySelector('button').onclick=()=>commit(sel.value||cur);return; } if(meta.cmd==='E'){ const btn=pb.querySelector('button'), isEmail=/^\S+@\S+\.\S+$/.test(cur); if(isEmail){ const body=Promptinator._lastMeta.map((m,i)=> `${prettify(m.lab)}: ${Promptinator._lastState[i]}`).join('\n'); btn.onclick=()=>{window.location.href= `mailto:${cur}?subject=${encodeURIComponent(nice)}&body=${encodeURIComponent(body)}`;dlg.close();}; }else{ const form=document.createElement('form'); form.method='post'; form.action=cur; const t=document.createElement('input'); t.type='hidden'; t.name='_formTitle'; t.value=nice; form.append(t); Promptinator._lastMeta.forEach((m,i)=>{ const inp=document.createElement('input');inp.type='hidden'; inp.name=prettify(m.lab).replace(/\s+/g,'-').toLowerCase(); inp.value=Promptinator._lastState[i]; form.append(inp); }); pb.append(form); btn.onclick=()=>{form.submit();dlg.close();}; } return; } /* default singleβline */ const inp=pb.querySelector('input'); inp.focus(); pb.querySelector('button').onclick=()=>commit(inp.value); inp.onkeydown=e=>{if(e.key==='Enter')commit(inp.value);}; } /* popup */ } /* end of class */ /* =================================================================== EMBEDDED PENCIL TOOLBAR Β (identical to SocialΒ Promptinator build) =================================================================== */ const HELP_URL='https://promptinator.ai/shortcode-help.php'; const SNIPPETS={name:'[name]',slogan:'[slogan]',description:'[description]',address:'[address]',city:'[city]', state:'[state]',zip:'[zip]',phone:'[phone]',website:'[website]',email:'[email]', c_service:'[C-service-]',c_location:'[C-location-]', h_hidden:'[H-hidden-~Internal GPT instructions here~]', plain_input:'[-labelfield-~Input~]',textarea_a:'[A-labelfield-~Textarea~]',radio_b:'[B-labelfield-|Choice 1|Choice 2|~Choice 2~]', checkbox_c:'[C-labelfield-|Opt A|Opt B|~Opt A~]',dropdown_num_d:'[D-labelfield-10~3~]', dropdown_txt_d:'[D-labelfield-|Opt A|Opt B|Opt C|~Opt B~]', url_picker_i:'[I-labelfield-|https://site1.com|site2.com|~Pick a site~]', email_submit_e:'[E-labelfield-~you@site.com~]',form_post_e:'[E-labelfield-~https://example.com/endpoint~]'}; const MENU=[['name','Name'],['slogan','Slogan'],['description','Description'],['address','Street address'], ['city','City'],['state','State'],['zip','ZIP code'],['phone','Phone number'],['website','Website URL'], ['email','Email address'],['c_service','Services (C)'],['c_location','Locations (C)'], ['h_hidden','Hidden instructions (H)'], ['plain_input','Plain input'],['textarea_a','Textarea (A)'],['radio_b','Radio buttons (B)'], ['checkbox_c','Checkbox group (C)'],['dropdown_num_d','Dropdown numeric (D)'],['dropdown_txt_d','Dropdown text (D)'], ['url_picker_i','URL pickerΒ +Β preview (I)'],['email_submit_e','Email submit (E)'],['form_post_e','FormβPOST submit (E)']]; function enhanceTextarea(ta){ if(!ta||ta.dataset.scMenu)return; ta.dataset.scMenu='yes'; /* maintain sequential label numbers per textarea */ const m=ta.value.match(/-label(\d+)(?=[-~|])/g); ta.dataset.labelCount = m ? String(Math.max(...m.map(s=>+s.replace(/\D/g,'')))+1) : '0'; /* --- toolbar select ------------------------------------------- */ const sel=document.createElement('select'); sel.className='promptinator-select'; sel.innerHTML='<option disabled selected>Insert shortcodeβ¦</option>'+ MENU.map(([k,t])=>`<option value="${k}">${t}</option>`).join(''); sel.onchange=()=>{ const raw=SNIPPETS[sel.value]; if(raw){ const n=+ta.dataset.labelCount; const snip=raw.replace(/-labelfield(?=[-~|])/i,`-label${n}`); ta.dataset.labelCount=String(n+1); insertAtCaret(ta,snip); } sel.selectedIndex=0; }; /* --- help link ------------------------------------------------- */ const help=document.createElement('a'); help.className='promptinator-help'; help.textContent='Help'; help.href=HELP_URL; help.title='Open shortcode helper'; help.onclick=e=>{ e.preventDefault(); window.open(HELP_URL,'promptinatorHelp','popup=yes,width=520,height=720,scrollbars=yes,resizable=yes'); }; const bar=document.createElement('div'); bar.className='promptinator-bar'; bar.append(sel,help); ta.parentNode.insertBefore(bar,ta); } function insertAtCaret(el,snippet){ el.focus(); const{selectionStart:s,selectionEnd:e,value:t}=el; el.value=t.slice(0,s)+snippet+t.slice(e); const p=s+snippet.length; el.selectionStart=el.selectionEnd=p; el.dispatchEvent(new Event('input',{bubbles:true})); } /* pencilβclick delegation (works for every Promptinator instance) */ document.addEventListener('click',e=>{ const pencil=e.target.closest('#edit-link'); if(!pencil)return; const form=(pencil.closest('.Promptinator')||document.body).querySelector('#edit-form'); if(!form)return; requestAnimationFrame(()=>{ if(getComputedStyle(form).display!=='none'){ const ta=form.querySelector('textarea'); if(ta)enhanceTextarea(ta); }}); }); /* expose enhancer for lazyβimport setups */ Promptinator.enhanceTextarea = enhanceTextarea; export { enhanceTextarea };
Save changes
Create folder
writable 0777
Create
Cancel