|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8" /> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
|
<title>Image Prompt Generator — Single Interface</title> |
|
|
<style> |
|
|
.pg-widget{font-family:sans-serif,Arial,Helvetica;display:block;margin:20px auto;max-width:560px} |
|
|
.pg-card{background:#f9f9f9;border-radius:14px;border-top:5px solid #8A2BE2;padding:20px;box-shadow:0 4px 14px rgba(0,0,0,.08)} |
|
|
.pg-title{margin:0 0 14px;color:#8A2BE2;text-align:center;font-size:1.6rem;font-weight:800} |
|
|
.pg-field{margin:12px 0} |
|
|
.pg-field label{display:block;margin-bottom:6px;color:#6A1B9A;font-weight:700} |
|
|
.pg-field input,.pg-field select{width:100%;padding:12px;border:1px solid #D1C4E9;border-radius:8px;background:#fff} |
|
|
.pg-field input:focus,.pg-field select:focus{outline:none;border-color:#8A2BE2;box-shadow:0 0 5px rgba(138,43,226,.3)} |
|
|
.pg-actions{display:flex;gap:10px;flex-wrap:wrap} |
|
|
.pg-btn{flex:1 1 180px;padding:14px;border-radius:8px;border:2px solid #D1C4E9;background:#F3E5F5;color:#6A1B9A;font-weight:700;cursor:pointer} |
|
|
.pg-btn:hover{background:#8A2BE2;color:#fff;border-color:#8A2BE2} |
|
|
.pg-result{margin-top:14px;min-height:140px;padding:14px;background:#F3E5F5;border:1px solid #D1C4E9;border-radius:8px;color:#6A1B9A;white-space:pre-wrap;word-break:break-word} |
|
|
.pg-status{margin-top:8px;font-size:.95rem;color:#2563eb;min-height:1.25em} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div class="pg-widget" data-gpt-href="https://chat.openai.com/g/gpt-XXXX-your-custom-gpt"> |
|
|
<div class="pg-card"> |
|
|
<h2 class="pg-title">Image Prompt Generator</h2> |
|
|
|
|
|
|
|
|
<div class="pg-field"> |
|
|
<label>Topic</label> |
|
|
<input type="text" placeholder="e.g. Product photo of a smartwatch" /> |
|
|
</div> |
|
|
<div class="pg-field"> |
|
|
<label>Tone</label> |
|
|
<select> |
|
|
<option>Friendly</option> |
|
|
<option>Professional</option> |
|
|
<option>Persuasive</option> |
|
|
<option>Informative</option> |
|
|
</select> |
|
|
</div> |
|
|
<div class="pg-field"> |
|
|
<label>Audience</label> |
|
|
<select> |
|
|
<option>General</option> |
|
|
<option>Students</option> |
|
|
<option>Customers</option> |
|
|
<option>Management</option> |
|
|
</select> |
|
|
</div> |
|
|
|
|
|
<div class="pg-actions"> |
|
|
<button class="pg-btn pg-generate">Generate Prompt</button> |
|
|
<button class="pg-btn pg-open">Copy & Paste Now</button> |
|
|
</div> |
|
|
|
|
|
<div class="pg-status" aria-live="polite"></div> |
|
|
<div class="pg-result" aria-live="polite"></div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
(() => { |
|
|
const root = document.querySelector('.pg-widget'); |
|
|
if (!root) return; |
|
|
|
|
|
const topic = root.querySelector('input'); |
|
|
const tone = root.querySelectorAll('select')[0]; |
|
|
const audience = root.querySelectorAll('select')[1]; |
|
|
const result = root.querySelector('.pg-result'); |
|
|
const status = root.querySelector('.pg-status'); |
|
|
const genBtn = root.querySelector('.pg-generate'); |
|
|
const openBtn = root.querySelector('.pg-open'); |
|
|
|
|
|
function buildPrompt(){ |
|
|
const t = (topic?.value || 'My Topic').trim(); |
|
|
const tn = tone?.selectedOptions?.[0]?.text || 'Friendly'; |
|
|
const aud = audience?.selectedOptions?.[0]?.text || 'General'; |
|
|
return [ |
|
|
'### Prompt', |
|
|
`Topic: ${t}`, |
|
|
`Tone: ${tn}`, |
|
|
`Audience: ${aud}`, |
|
|
'', |
|
|
'Instruction:', |
|
|
`Create a detailed, high-quality image prompt about "${t}" in a ${tn} tone for ${aud}. Use concise, vivid descriptors, camera/details if relevant, and avoid extra prose.`, |
|
|
].join('\n'); |
|
|
} |
|
|
|
|
|
async function copyText(txt){ |
|
|
try { |
|
|
await navigator.clipboard.writeText(txt); |
|
|
status.textContent = 'Prompt generated & copied to clipboard.'; |
|
|
} catch (e){ |
|
|
|
|
|
const ta = document.createElement('textarea'); |
|
|
ta.value = txt; document.body.appendChild(ta); ta.select(); |
|
|
try { document.execCommand('copy'); status.textContent = 'Prompt generated & copied.'; } |
|
|
catch { status.textContent = 'Prompt ready. Copy manually.'; } |
|
|
finally { document.body.removeChild(ta); } |
|
|
} |
|
|
} |
|
|
|
|
|
genBtn?.addEventListener('click', async () => { |
|
|
const txt = buildPrompt(); |
|
|
result.textContent = txt; |
|
|
await copyText(txt); |
|
|
}); |
|
|
|
|
|
openBtn?.addEventListener('click', async () => { |
|
|
const txt = result.textContent?.trim() || buildPrompt(); |
|
|
await copyText(txt); |
|
|
const href = root.dataset.gptHref || '#'; |
|
|
window.open(href, '_blank', 'noopener'); |
|
|
}); |
|
|
})(); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
|