SELECT static vs js: two dropdown variants in the action bar — which one when
BUTTON is "one action". TOGGLE3 is "three states". SELECT is "pick one of N" — where N can be 2, 5, 50, or dynamic. But SELECT has two variants that look the same and work differently: static (options in storage, editable via UI) and js (options generated by user code, reading from page DOM / fetched from an API). The choice depends on whether your option list is fixed or contextual.
Two variants — the key difference
| Trait | SELECT static | SELECT js |
|---|---|---|
| Source of options | From storage (action.options[]) | From user JS code (at render time) |
| Editing options | Manually in options.html | Code field |
| Best for | Fixed presets, language, theme | DOM categories, fetch API, dynamic list |
| Re-render | Only on storage change | Can refresh options programmatically |
| Requires code? | Yes — what to do after pick | Yes — generate options + handle pick |
| Selected value memory | dataset.jzValue | native <select>.value |
SELECT static — first action
Use case: language switcher for an app with its own i18n.
type: 'select' // no 'variant' = static
label: '🌐 Language'
options: [
{ id: 'pl', label: 'Polski', value: 'pl' },
{ id: 'en', label: 'English', value: 'en' },
{ id: 'de', label: 'Deutsch', value: 'de' },
{ id: 'fr', label: 'Français', value: 'fr' },
]
code: |
// `value` is the selected option's value (or label when no value)
document.cookie = `lang=${value}; path=/`;
location.reload();
JUSTZIX.log(`Language switched to ${value}`);
UI: "🌐 Language" button shows the current value (e.g. "Polski") as its label. Click → dropdown of 4 options → click "English" → cookie + reload. Memory: next visit to the domain → button shows "English" (preserved).
SELECT js — first action
Use case: jumps to anchors in a long article. Dropdown of the page's H2 headings.
type: 'select'
variant: 'js'
label: '📑 Sections'
code: |
// Code runs at bar render. Return an array of {value, label} (or {value} only).
return Array.from(document.querySelectorAll('h2')).map(h => ({
value: h.id || h.textContent.trim().slice(0, 40),
label: h.textContent.trim().slice(0, 40),
}));
codeOnSelect: |
// A second code field — runs after option pick. `value` is the chosen option's value.
const target = document.getElementById(value)
|| Array.from(document.querySelectorAll('h2')).find(h => h.textContent.includes(value));
if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
UI: "📑 Sections" button → dropdown of the page's current H2s → click → scroll to that H2. The list regenerates on page load — always up-to-date.
4 colours + dropdown customization
SELECT has 4 colours + 2 for the dropdown (static):
color → button background (like BUTTON)
colorText → label text colour (current value)
colorDropdownBg → background of the opened dropdown
colorOption → option text colour inside the dropdown
colorSelected → background of the currently-selected option
colorHover → option background on hover
All applied via CSS variables (--jz-dropdown-bg, --jz-option-color, etc.) — granular visual control. By default we use a dark dropdown on a light page (contrast).
SELECT js uses a native <select> element — dropdown colours are limited to what the system allows (varies per OS and browser). It's a trade-off: js variant has dynamically generated options but less styling, static variant has full visual control but requires manual editing.
Use case 1 — Environment switcher (static)
Classic: dropdown with 3-5 environments, click → redirects URL.
options: [
{ id: 'dev', label: '🟢 DEV', value: 'dev.app.com' },
{ id: 'stg', label: '🟡 STG', value: 'staging.app.com' },
{ id: 'prod', label: '🔴 PROD', value: 'app.com' },
]
code: |
const path = location.pathname + location.search;
location.href = `https://${value}${path}`;
For 3 states better use TOGGLE3 (each state visible). For 4+ → SELECT static is cleanest.
Use case 2 — Per-domain bookmarks (js)
List of "favourite" URLs per domain, in localStorage:
variant: 'js'
label: '⭐ Bookmarks'
code: |
const stored = JSON.parse(localStorage.getItem('jz_bookmarks') || '[]');
return stored.map(b => ({ value: b.url, label: b.label }));
codeOnSelect: |
window.location.href = value;
A second BUTTON "+ Bookmark" adds the current URL to the list:
// BUTTON action
const stored = JSON.parse(localStorage.getItem('jz_bookmarks') || '[]');
const label = prompt('Label?') || document.title.slice(0, 30);
stored.push({ url: location.href, label });
localStorage.setItem('jz_bookmarks', JSON.stringify(stored));
JUSTZIX.log(`Bookmark added: ${label}`);
// SELECT js auto-rerenders on reload, so F5 or:
JZ.action('Bookmarks')?.click(); // optional refresh
location.reload();
Use case 3 — Files from an FTP gist (js + fetch)
List of snippets you want to paste into a page's text field, fetched from a private gist:
variant: 'js'
label: '📋 Snippets'
code: |
const r = await fetch('https://gist.githubusercontent.com/.../snippets.json');
if (!r.ok) return [];
const snippets = await r.json();
return snippets.map(s => ({ value: s.content, label: s.name }));
codeOnSelect: |
navigator.clipboard.writeText(value);
JUSTZIX.log(`Copied snippet (${value.length} chars)`);
NOTE: async/await works in code, but render waits for resolve — high latency (>500ms) makes the button flicker. Cache in localStorage with fallback.
Use case 4 — Pick an action to run (static)
Mega-button: dropdown with the 10 most common flows:
options: [
{ id: 'login', label: '🔑 Login as test', value: 'login' },
{ id: 'addCart', label: '🛒 Add 3 items', value: 'addCart' },
{ id: 'checkout', label: '✅ Quick checkout', value: 'checkout' },
...
]
code: |
// Classic switch — each value maps to a flow
switch (value) {
case 'login':
JZ.click('Login');
break;
case 'addCart':
['p1','p2','p3'].forEach(id =>
document.querySelector(`[data-product=${id}] .add`)?.click()
);
break;
case 'checkout':
JZ.click('Checkout');
break;
}
JUSTZIX.log(`Ran flow: ${value}`);
1 dropdown instead of 10 separate buttons — more compact bar. Trade-off: 1 extra click (open → pick vs. single click).
Pitfalls
- SELECT static requires editing in options.html. No inline-edit in the action bar. Adding an option = restart the UI options page. For a frequently-changing list → js variant.
- SELECT js code runs AT bar render, not only when the user opens the dropdown. If the code is slow (external API fetch), the button hangs until resolve. Cache + sync defaults help.
- JZ.click('label') does NOT open the static SELECT dropdown. It clicks the button element (toggling the dropdown). For programmatic option pick:
JZ.setValue('label', 'optionValue')— since v2.13.33. - SELECT js value is always a string (native <select>). For a number value:
parseFloat(value)in code. - codeOnSelect vs code — two different editor fields:
coderenders options (return array),codeOnSelecthandles selection (one-off). Don't mix them up.
What's next
SELECT (static or js) is "pick one of many" — most flexible after BUTTON. Check also the other action types and the API:
- BUTTON — fire-and-forget, the simplest action
- INPUT — single-line text + Enter→run
- TEXTAREA — multi-line scratch pad
- SLIDER — native range controller
- TOGGLE3 — 3-state segmented controls
- window.JZ + JUSTZIX helpers — programmatic API (JZ.setValue for SELECT)
Install JustZix — completely free, no account, no server.
Rate this post
No ratings yet — be the first.