openvibers/openvibe.tools Commits
Spinners become the mark's own wait (#290)
Changes
@@@ -37,6 +37,7 @@<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.css"><script src="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.js"></script><link rel="stylesheet" href="/css/style.css">++ <script src="/shared/ov-mark.js" defer></script></head><body><!-- The tool frame (the shared one, openvibe-shared >= 4.57.1): the server draws it for this@@@ -52,7 +52,7 @@async function loadFoodBanks() {if (!state.location) { $('#food-banks-list').innerHTML = '<div class="empty-state"><i class="fa-solid fa-location-dot fa-3x"></i><p>Enter your location above to find nearby food banks</p></div>'; return; }const c = $('#food-banks-list');-- c.innerHTML = '<div class="loading-state"><div class="spinner"></div><p>Finding food banks...</p></div>';++ c.innerHTML = '<div class="loading-state"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Finding food banks...</p></div>';try {const { lat, lon } = state.location;const res = await fetch(`${API}/api/food-banks?lat=${lat}&lon=${lon}&radius=10`);@@@ -82,7 +82,7 @@async function loadStores() {if (!state.location) { $('#stores-list').innerHTML = '<div class="empty-state"><i class="fa-solid fa-cart-shopping fa-3x"></i><p>Enter your location to find nearby stores</p></div>'; return; }const c = $('#stores-list');-- c.innerHTML = '<div class="loading-state"><div class="spinner"></div><p>Finding stores...</p></div>';++ c.innerHTML = '<div class="loading-state"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Finding stores...</p></div>';try {const { lat, lon } = state.location;const res = await fetch(`${API}/api/stores?lat=${lat}&lon=${lon}`);@@@ -115,7 +115,7 @@const camp = $('#mp-camp')?.checked;const shelf = $('#mp-shelf')?.checked;const rc = $('#meal-results');-- rc.innerHTML = '<div class="loading-state"><div class="spinner"></div><p>Optimizing meals...</p></div>';++ rc.innerHTML = '<div class="loading-state"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Optimizing meals...</p></div>';try {const res = await fetch(`${API}/api/meal-plan?budget=${budget}&days=${days}&campFriendly=${camp}&shelfStable=${shelf}&randomize=true`);const plan = await res.json();@@@ -157,7 +157,7 @@async function loadFoodDb() {const c = $('#food-list');-- c.innerHTML = '<div class="loading-state"><div class="spinner"></div><p>Loading food database...</p></div>';++ c.innerHTML = '<div class="loading-state"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Loading food database...</p></div>';try {const res = await fetch(`${API}/api/foods`);allFoods = await res.json();@@@ -57,6 +57,7 @@<script src="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.js"></script><link rel="stylesheet" href="/css/style.css">++ <script src="/shared/ov-mark.js" defer></script></head><body>@@@ -299,10 +299,10 @@query = query.trim();const btn = $('#btn-search');btn.classList.add('loading');-- btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i><span>Searching...</span>';-- setStatus(`<i class="fa-solid fa-spinner fa-spin"></i> Searching "${esc(query)}"...`);++ btn.innerHTML = '<span class="ov-mark" data-state="busy" data-size="16" data-tone="ink" aria-hidden="true"></span><span>Searching...</span>';++ setStatus(`<span class="ov-mark" data-state="busy" data-size="16" data-tone="ink" aria-hidden="true"></span> Searching "${esc(query)}"...`);hide($('#welcome-card'));-- $('#results-list').innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Geocoding location...</p></div>';++ $('#results-list').innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Geocoding location...</p></div>';// Reset statestate.locations = [];@@@ -329,7 +329,7 @@state.map.setView([lat, lon], 11, { animate: false });// Placeholder for source progress — will be replaced once sources manifest arrives-- $('#results-list').innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Connecting to sources...</p></div>';++ $('#results-list').innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Connecting to sources...</p></div>';const t0 = Date.now();@@@ -690,7 +690,7 @@async function loadFoodBanks() {const c = $('#food-banks');-- c.innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Finding food banks...</p></div>';++ c.innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Finding food banks...</p></div>';try {const {lat,lon} = state.searchCenter;const res = await fetch(`${API}/api/food-banks?lat=${lat}&lon=${lon}&radius=10`);@@@ -712,7 +712,7 @@async function loadStores() {const c = $('#stores');if (!state.searchCenter) { c.innerHTML = '<p class="muted-text">Search a location first.</p>'; return; }-- c.innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Finding stores...</p></div>';++ c.innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Finding stores...</p></div>';try {const {lat,lon} = state.searchCenter;const res = await fetch(`${API}/api/stores?lat=${lat}&lon=${lon}`);@@@ -745,7 +745,7 @@const days = parseInt($('#mp-days')?.value) || 3;const camp = $('#mp-camp')?.checked;const rc = $('#meal-plan-results');-- rc.innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Optimizing meals...</p></div>';++ rc.innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Optimizing meals...</p></div>';try {const res = await fetch(`${API}/api/meal-plan?budget=${budget}&days=${days}&campFriendly=${camp}&randomize=true`);const plan = await res.json();@@@ -772,7 +772,7 @@async function loadFoodDb() {const c = $('#food-db');-- c.innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Loading food database...</p></div>';++ c.innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Loading food database...</p></div>';try {const res = await fetch(`${API}/api/foods`);const foods = await res.json();@@@ -18,6 +18,7 @@</script><link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"><link rel="stylesheet" href="/css/style.css">++ <script src="/shared/ov-mark.js" defer></script></head><body><!-- Navbar injected by OpenVibeNavbar.init() -->@@@ -87,7 +87,7 @@ function boxFor() {${frame.verbButton('Fetch the video', { id: 'fetch-btn', icon: 'search' })}</div><p class="ovk-try"><span>Try</span><a href="?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Daqz-KE-bpKQ" data-ovk-try="https://www.youtube.com/watch?v=aqz-KE-bpKQ" data-ovk-name="url" data-ovk-for="#url-input">Big Buck Bunny</a></p>-- <section class="loading" id="loading" style="display:none"><div class="spinner"></div><p>Fetching video info…</p></section>++ <section class="loading" id="loading" style="display:none"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Fetching video info…</p></section><section class="video-card" id="video-card" style="display:none"><div class="video-thumb" id="video-thumb"></div><div class="video-info" id="video-info"></div>
@@ -37,6 +37,7 @@
@@ -37,6 +37,7 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.js"></script>
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/style.css">
+ <script src="/shared/ov-mark.js" defer></script>
</head>
</head>
<body>
<body>
<!-- The tool frame (the shared one, openvibe-shared >= 4.57.1): the server draws it for this
<!-- The tool frame (the shared one, openvibe-shared >= 4.57.1): the server draws it for this
@@ -52,7 +52,7 @@
@@ -52,7 +52,7 @@
async function loadFoodBanks() {
async function loadFoodBanks() {
if (!state.location) { $('#food-banks-list').innerHTML = '<div class="empty-state"><i class="fa-solid fa-location-dot fa-3x"></i><p>Enter your location above to find nearby food banks</p></div>'; return; }
if (!state.location) { $('#food-banks-list').innerHTML = '<div class="empty-state"><i class="fa-solid fa-location-dot fa-3x"></i><p>Enter your location above to find nearby food banks</p></div>'; return; }
const c = $('#food-banks-list');
const c = $('#food-banks-list');
- c.innerHTML = '<div class="loading-state"><div class="spinner"></div><p>Finding food banks...</p></div>';
+ c.innerHTML = '<div class="loading-state"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Finding food banks...</p></div>';
try {
try {
const { lat, lon } = state.location;
const { lat, lon } = state.location;
const res = await fetch(`${API}/api/food-banks?lat=${lat}&lon=${lon}&radius=10`);
const res = await fetch(`${API}/api/food-banks?lat=${lat}&lon=${lon}&radius=10`);
@@ -82,7 +82,7 @@
@@ -82,7 +82,7 @@
async function loadStores() {
async function loadStores() {
if (!state.location) { $('#stores-list').innerHTML = '<div class="empty-state"><i class="fa-solid fa-cart-shopping fa-3x"></i><p>Enter your location to find nearby stores</p></div>'; return; }
if (!state.location) { $('#stores-list').innerHTML = '<div class="empty-state"><i class="fa-solid fa-cart-shopping fa-3x"></i><p>Enter your location to find nearby stores</p></div>'; return; }
const c = $('#stores-list');
const c = $('#stores-list');
- c.innerHTML = '<div class="loading-state"><div class="spinner"></div><p>Finding stores...</p></div>';
+ c.innerHTML = '<div class="loading-state"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Finding stores...</p></div>';
try {
try {
const { lat, lon } = state.location;
const { lat, lon } = state.location;
const res = await fetch(`${API}/api/stores?lat=${lat}&lon=${lon}`);
const res = await fetch(`${API}/api/stores?lat=${lat}&lon=${lon}`);
@@ -115,7 +115,7 @@
@@ -115,7 +115,7 @@
const camp = $('#mp-camp')?.checked;
const camp = $('#mp-camp')?.checked;
const shelf = $('#mp-shelf')?.checked;
const shelf = $('#mp-shelf')?.checked;
const rc = $('#meal-results');
const rc = $('#meal-results');
- rc.innerHTML = '<div class="loading-state"><div class="spinner"></div><p>Optimizing meals...</p></div>';
+ rc.innerHTML = '<div class="loading-state"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Optimizing meals...</p></div>';
try {
try {
const res = await fetch(`${API}/api/meal-plan?budget=${budget}&days=${days}&campFriendly=${camp}&shelfStable=${shelf}&randomize=true`);
const res = await fetch(`${API}/api/meal-plan?budget=${budget}&days=${days}&campFriendly=${camp}&shelfStable=${shelf}&randomize=true`);
const plan = await res.json();
const plan = await res.json();
@@ -157,7 +157,7 @@
@@ -157,7 +157,7 @@
async function loadFoodDb() {
async function loadFoodDb() {
const c = $('#food-list');
const c = $('#food-list');
- c.innerHTML = '<div class="loading-state"><div class="spinner"></div><p>Loading food database...</p></div>';
+ c.innerHTML = '<div class="loading-state"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Loading food database...</p></div>';
try {
try {
const res = await fetch(`${API}/api/foods`);
const res = await fetch(`${API}/api/foods`);
allFoods = await res.json();
allFoods = await res.json();
@@ -57,6 +57,7 @@
@@ -57,6 +57,7 @@
<script src="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/src/toastify.min.js"></script>
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/style.css">
+ <script src="/shared/ov-mark.js" defer></script>
</head>
</head>
<body>
<body>
@@ -299,10 +299,10 @@
@@ -299,10 +299,10 @@
query = query.trim();
query = query.trim();
const btn = $('#btn-search');
const btn = $('#btn-search');
btn.classList.add('loading');
btn.classList.add('loading');
- btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i><span>Searching...</span>';
- setStatus(`<i class="fa-solid fa-spinner fa-spin"></i> Searching "${esc(query)}"...`);
+ btn.innerHTML = '<span class="ov-mark" data-state="busy" data-size="16" data-tone="ink" aria-hidden="true"></span><span>Searching...</span>';
+ setStatus(`<span class="ov-mark" data-state="busy" data-size="16" data-tone="ink" aria-hidden="true"></span> Searching "${esc(query)}"...`);
hide($('#welcome-card'));
hide($('#welcome-card'));
- $('#results-list').innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Geocoding location...</p></div>';
+ $('#results-list').innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Geocoding location...</p></div>';
// Reset state
// Reset state
state.locations = [];
state.locations = [];
@@ -329,7 +329,7 @@
@@ -329,7 +329,7 @@
state.map.setView([lat, lon], 11, { animate: false });
state.map.setView([lat, lon], 11, { animate: false });
// Placeholder for source progress — will be replaced once sources manifest arrives
// Placeholder for source progress — will be replaced once sources manifest arrives
- $('#results-list').innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Connecting to sources...</p></div>';
+ $('#results-list').innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Connecting to sources...</p></div>';
const t0 = Date.now();
const t0 = Date.now();
@@ -690,7 +690,7 @@
@@ -690,7 +690,7 @@
async function loadFoodBanks() {
async function loadFoodBanks() {
const c = $('#food-banks');
const c = $('#food-banks');
- c.innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Finding food banks...</p></div>';
+ c.innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Finding food banks...</p></div>';
try {
try {
const {lat,lon} = state.searchCenter;
const {lat,lon} = state.searchCenter;
const res = await fetch(`${API}/api/food-banks?lat=${lat}&lon=${lon}&radius=10`);
const res = await fetch(`${API}/api/food-banks?lat=${lat}&lon=${lon}&radius=10`);
@@ -712,7 +712,7 @@
@@ -712,7 +712,7 @@
async function loadStores() {
async function loadStores() {
const c = $('#stores');
const c = $('#stores');
if (!state.searchCenter) { c.innerHTML = '<p class="muted-text">Search a location first.</p>'; return; }
if (!state.searchCenter) { c.innerHTML = '<p class="muted-text">Search a location first.</p>'; return; }
- c.innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Finding stores...</p></div>';
+ c.innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Finding stores...</p></div>';
try {
try {
const {lat,lon} = state.searchCenter;
const {lat,lon} = state.searchCenter;
const res = await fetch(`${API}/api/stores?lat=${lat}&lon=${lon}`);
const res = await fetch(`${API}/api/stores?lat=${lat}&lon=${lon}`);
@@ -745,7 +745,7 @@
@@ -745,7 +745,7 @@
const days = parseInt($('#mp-days')?.value) || 3;
const days = parseInt($('#mp-days')?.value) || 3;
const camp = $('#mp-camp')?.checked;
const camp = $('#mp-camp')?.checked;
const rc = $('#meal-plan-results');
const rc = $('#meal-plan-results');
- rc.innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Optimizing meals...</p></div>';
+ rc.innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Optimizing meals...</p></div>';
try {
try {
const res = await fetch(`${API}/api/meal-plan?budget=${budget}&days=${days}&campFriendly=${camp}&randomize=true`);
const res = await fetch(`${API}/api/meal-plan?budget=${budget}&days=${days}&campFriendly=${camp}&randomize=true`);
const plan = await res.json();
const plan = await res.json();
@@ -772,7 +772,7 @@
@@ -772,7 +772,7 @@
async function loadFoodDb() {
async function loadFoodDb() {
const c = $('#food-db');
const c = $('#food-db');
- c.innerHTML = '<div class="search-progress"><div class="spinner"></div><p>Loading food database...</p></div>';
+ c.innerHTML = '<div class="search-progress"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Loading food database...</p></div>';
try {
try {
const res = await fetch(`${API}/api/foods`);
const res = await fetch(`${API}/api/foods`);
const foods = await res.json();
const foods = await res.json();
@@ -18,6 +18,7 @@
@@ -18,6 +18,7 @@
</script>
</script>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/style.css">
+ <script src="/shared/ov-mark.js" defer></script>
</head>
</head>
<body>
<body>
<!-- Navbar injected by OpenVibeNavbar.init() -->
<!-- Navbar injected by OpenVibeNavbar.init() -->
@@ -87,7 +87,7 @@ function boxFor() {
@@ -87,7 +87,7 @@ function boxFor() {
${frame.verbButton('Fetch the video', { id: 'fetch-btn', icon: 'search' })}
${frame.verbButton('Fetch the video', { id: 'fetch-btn', icon: 'search' })}
</div>
</div>
<p class="ovk-try"><span>Try</span><a href="?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Daqz-KE-bpKQ" data-ovk-try="https://www.youtube.com/watch?v=aqz-KE-bpKQ" data-ovk-name="url" data-ovk-for="#url-input">Big Buck Bunny</a></p>
<p class="ovk-try"><span>Try</span><a href="?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Daqz-KE-bpKQ" data-ovk-try="https://www.youtube.com/watch?v=aqz-KE-bpKQ" data-ovk-name="url" data-ovk-for="#url-input">Big Buck Bunny</a></p>
- <section class="loading" id="loading" style="display:none"><div class="spinner"></div><p>Fetching video info…</p></section>
+ <section class="loading" id="loading" style="display:none"><span class="ov-mark" data-state="busy" data-size="32" aria-hidden="true"></span><p>Fetching video info…</p></section>
<section class="video-card" id="video-card" style="display:none">
<section class="video-card" id="video-card" style="display:none">
<div class="video-thumb" id="video-thumb"></div>
<div class="video-thumb" id="video-thumb"></div>
<div class="video-info" id="video-info"></div>
<div class="video-info" id="video-info"></div>