Spaces:
Running
Running
Download editor/static/widget.js from acecalisto3/SignalMesh: direct link, hf CLI and curl.
- Browser
- Download file 6.72 kB
-
https://huggingface.co/spaces/acecalisto3/SignalMesh/resolve/main/editor/static/widget.js
- Command line
-
hf download hf://spaces/acecalisto3/SignalMesh/editor/static/widget.js
-
curl -L -o widget.js https://huggingface.co/spaces/acecalisto3/SignalMesh/resolve/main/editor/static/widget.js
6.72 kB
| /* Site helper widget — answers from the site's own published pages. | |
| * | |
| * Embed on the Joomla site with one line: | |
| * <script src="https://YOUR-HOST/widget.js" defer></script> | |
| * | |
| * Read-only by construction: it calls one GET endpoint that can only return | |
| * published, public content. It cannot change anything on the site. | |
| */ | |
| (function () { | |
| 'use strict'; | |
| if (window.__fixmeshWidget) return; | |
| window.__fixmeshWidget = true; | |
| var BASE = (document.currentScript && document.currentScript.src || '').replace(/\/widget\.js.*$/, ''); | |
| var OPEN = false; | |
| var css = '\ | |
| .fxw-btn{position:fixed;right:20px;bottom:20px;z-index:2147483000;border:0;border-radius:999px;\ | |
| padding:14px 20px;font:600 15px/1 system-ui,sans-serif;background:#1f6feb;color:#fff;cursor:pointer;\ | |
| box-shadow:0 6px 22px rgba(0,0,0,.25)}\ | |
| .fxw-btn:hover{background:#1a5fd0}\ | |
| .fxw-panel{position:fixed;right:20px;bottom:84px;z-index:2147483000;width:min(380px,calc(100vw - 40px));\ | |
| max-height:min(560px,calc(100vh - 120px));background:#fff;color:#16181d;border-radius:14px;\ | |
| box-shadow:0 12px 44px rgba(0,0,0,.28);display:none;flex-direction:column;overflow:hidden;\ | |
| font:15px/1.5 system-ui,-apple-system,sans-serif}\ | |
| .fxw-panel.open{display:flex}\ | |
| .fxw-head{padding:12px 14px;background:#1f6feb;color:#fff;font-weight:700;display:flex;align-items:center}\ | |
| .fxw-head button{margin-left:auto;background:none;border:0;color:#fff;font-size:20px;cursor:pointer;line-height:1}\ | |
| .fxw-log{flex:1;overflow:auto;padding:12px;display:flex;flex-direction:column;gap:10px}\ | |
| .fxw-msg{padding:9px 12px;border-radius:12px;max-width:92%;white-space:pre-wrap}\ | |
| .fxw-me{align-self:flex-end;background:#1f6feb;color:#fff;border-bottom-right-radius:4px}\ | |
| .fxw-bot{align-self:flex-start;background:#f0f2f5;border-bottom-left-radius:4px}\ | |
| .fxw-src{margin-top:8px;display:flex;flex-direction:column;gap:6px}\ | |
| .fxw-src a{display:block;padding:8px 10px;background:#fff;border:1px solid #dfe3e8;border-radius:9px;\ | |
| text-decoration:none;color:#1f6feb;font-weight:600;font-size:14px}\ | |
| .fxw-src a:hover{border-color:#1f6feb}\ | |
| .fxw-src small{display:block;color:#5b6472;font-weight:400;margin-top:2px}\ | |
| .fxw-ask{display:flex;gap:6px;padding:10px;border-top:1px solid #e3e6ea;background:#fff}\ | |
| .fxw-ask input{flex:1;padding:10px;border:1px solid #dfe3e8;border-radius:9px;font:inherit;min-width:0}\ | |
| .fxw-ask button{padding:10px 14px;border:0;border-radius:9px;background:#1f6feb;color:#fff;font-weight:600;cursor:pointer}\ | |
| .fxw-chips{display:flex;flex-wrap:wrap;gap:6px;padding:0 12px 10px}\ | |
| .fxw-chips button{padding:6px 10px;border:1px solid #dfe3e8;background:#fff;border-radius:999px;\ | |
| font:inherit;font-size:13px;cursor:pointer;color:#16181d}\ | |
| @media(prefers-color-scheme:dark){\ | |
| .fxw-panel{background:#171a21;color:#e8eaed}.fxw-bot{background:#232833}\ | |
| .fxw-src a{background:#1d2129;border-color:#2d323c}.fxw-ask{background:#171a21;border-color:#272b34}\ | |
| .fxw-ask input{background:#1d2129;border-color:#2d323c;color:#e8eaed}\ | |
| .fxw-chips button{background:#1d2129;border-color:#2d323c;color:#e8eaed}}'; | |
| var style = document.createElement('style'); | |
| style.textContent = css; | |
| document.head.appendChild(style); | |
| var btn = document.createElement('button'); | |
| btn.className = 'fxw-btn'; | |
| btn.type = 'button'; | |
| btn.textContent = 'Ask a question'; | |
| btn.setAttribute('aria-expanded', 'false'); | |
| var panel = document.createElement('div'); | |
| panel.className = 'fxw-panel'; | |
| panel.setAttribute('role', 'dialog'); | |
| panel.setAttribute('aria-label', 'Site helper'); | |
| panel.innerHTML = | |
| '<div class="fxw-head">Site helper<button type="button" aria-label="Close">×</button></div>' + | |
| '<div class="fxw-log"></div>' + | |
| '<div class="fxw-chips"></div>' + | |
| '<form class="fxw-ask"><input placeholder="Ask about the school…" aria-label="Your question">' + | |
| '<button type="submit">Ask</button></form>'; | |
| document.body.appendChild(btn); | |
| document.body.appendChild(panel); | |
| var log = panel.querySelector('.fxw-log'); | |
| var chips = panel.querySelector('.fxw-chips'); | |
| var form = panel.querySelector('.fxw-ask'); | |
| var input = form.querySelector('input'); | |
| function bubble(text, who) { | |
| var d = document.createElement('div'); | |
| d.className = 'fxw-msg ' + (who === 'me' ? 'fxw-me' : 'fxw-bot'); | |
| d.textContent = text; | |
| log.appendChild(d); | |
| log.scrollTop = log.scrollHeight; | |
| return d; | |
| } | |
| function sources(list, into) { | |
| if (!list || !list.length) return; | |
| var box = document.createElement('div'); | |
| box.className = 'fxw-src'; | |
| list.forEach(function (s) { | |
| var a = document.createElement('a'); | |
| a.href = s.url; | |
| a.textContent = 'Visit ' + s.title + ' now'; | |
| var sm = document.createElement('small'); | |
| sm.textContent = (s.quote || '').slice(0, 90); | |
| a.appendChild(sm); | |
| box.appendChild(a); | |
| }); | |
| into.appendChild(box); | |
| log.scrollTop = log.scrollHeight; | |
| } | |
| var SUGGESTIONS = ['Lunch menu', 'School calendar', 'Who is the superintendent', | |
| 'Contact the office', 'Enrollment']; | |
| function drawChips() { | |
| chips.innerHTML = ''; | |
| SUGGESTIONS.forEach(function (s) { | |
| var b = document.createElement('button'); | |
| b.type = 'button'; | |
| b.textContent = s; | |
| b.onclick = function () { input.value = s; send(); }; | |
| chips.appendChild(b); | |
| }); | |
| } | |
| function send() { | |
| var q = input.value.trim(); | |
| if (!q) return; | |
| bubble(q, 'me'); | |
| input.value = ''; | |
| var pending = bubble('Looking…', 'bot'); | |
| fetch(BASE + '/api/ask?q=' + encodeURIComponent(q)) | |
| .then(function (r) { return r.json(); }) | |
| .then(function (d) { | |
| pending.textContent = (d.ok && d.lead ? d.lead + '\n\n' : '') + d.answer; | |
| if (d.ok) sources(d.sources, pending); | |
| }) | |
| .catch(function () { | |
| pending.textContent = 'Sorry — I could not reach the site information just now.'; | |
| }); | |
| } | |
| form.onsubmit = function (e) { e.preventDefault(); send(); }; | |
| function toggle(open) { | |
| OPEN = open; | |
| panel.classList.toggle('open', open); | |
| btn.setAttribute('aria-expanded', String(open)); | |
| btn.textContent = open ? 'Close' : 'Ask a question'; | |
| if (open) { | |
| if (!log.childElementCount) { | |
| bubble('Hi! Ask me about lunch menus, calendars, staff or any school office. ' | |
| + 'I answer using what is published on this site, and I can take you straight there.', 'bot'); | |
| drawChips(); | |
| } | |
| input.focus(); | |
| } | |
| } | |
| btn.onclick = function () { toggle(!OPEN); }; | |
| panel.querySelector('.fxw-head button').onclick = function () { toggle(false); }; | |
| document.addEventListener('keydown', function (e) { if (e.key === 'Escape' && OPEN) toggle(false); }); | |
| })(); | |