Changeset bb3f67c in Klonkt for src/views/pages/post-edit.ejs


Ignore:
Timestamp:
07/01/2026 01:18:04 PM (2 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
667fb41
Parents:
0403187
Message:

feat(polls): removable options + tidier editor layout

Each poll option is now its own row with a ✕ remove button (hidden at the
2-option minimum, add capped at 8); the "+ Add option" button sits on its own
line above a stacked "multiple choices" checkbox, matching the rest of the
options panel. Inline styles moved to a scoped block.

  • src/views/pages/post-edit.ejs — option rows with remove buttons, .pe-poll-* styles, refresh() enforces min-2/max-8; add button is block-level.
  • src/services/i18n.js — pedit.poll_remove (nl/en/de).

Co-Authored-By: Claude <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/post-edit.ejs

    r0403187 rbb3f67c  
    268268          <span>📊 <%= t('pedit.poll_label') %></span>
    269269        </label>
    270         <div id="pe-poll-fields" style="margin-top:6px<%= _poll ? '' : ';display:none' %>">
    271           <% if (_pollLocked) { %><p style="font-size:12px;opacity:.7;margin:0 0 6px"><%= t('pedit.poll_locked') %></p><% } %>
    272           <div id="pe-poll-opts">
     270        <style>
     271          .pe-poll { margin-top: 6px; }
     272          .pe-poll-locked { font-size: 12px; opacity: .7; margin: 0 0 6px; }
     273          .pe-poll-row { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
     274          .pe-poll-opt { flex: 1; min-width: 0; box-sizing: border-box; font-size: 13px; padding: 7px 9px; border-radius: 7px; border: 1px solid var(--rule, rgba(128,128,128,.35)); background: transparent; color: inherit; }
     275          .pe-poll-opt:focus { outline: none; border-color: var(--accent); }
     276          .pe-poll-del { flex: 0 0 auto; width: 30px; height: 32px; display: inline-flex; align-items: center; justify-content: center; font-size: 18px; line-height: 1; border: 1px solid var(--rule, rgba(128,128,128,.35)); border-radius: 7px; background: transparent; color: var(--ink-muted, #999); cursor: pointer; transition: color .12s, border-color .12s; }
     277          .pe-poll-del:hover { border-color: #c0392b; color: #c0392b; }
     278          .pe-poll-del[hidden] { display: none; }
     279          .pe-poll-add { display: block; width: fit-content; font-size: 12.5px; padding: 6px 12px; border-radius: 7px; border: 1px dashed var(--rule, rgba(128,128,128,.45)); background: transparent; color: inherit; cursor: pointer; margin: 0 0 10px; transition: color .12s, border-color .12s; }
     280          .pe-poll-add:hover { border-color: var(--accent); color: var(--accent); }
     281          .pe-poll-add:disabled { opacity: .4; cursor: default; border-style: dashed; }
     282          .pe-poll-durlabel { display: block; font-size: 12.5px; opacity: .8; margin: 8px 0 4px; }
     283          .pe-poll-dur { padding: 7px 9px; border-radius: 7px; border: 1px solid var(--rule, rgba(128,128,128,.35)); background: transparent; color: inherit; font-size: 13px; }
     284        </style>
     285        <div id="pe-poll-fields" class="pe-poll"<%= _poll ? '' : ' style="display:none"' %>>
     286          <% if (_pollLocked) { %><p class="pe-poll-locked"><%= t('pedit.poll_locked') %></p><% } %>
     287          <div id="pe-poll-opts" data-ph="<%= t('pedit.poll_option_ph') %>" data-del="<%= t('pedit.poll_remove') %>">
    273288            <% _pollOpts.forEach(function (o) { %>
    274               <input type="text" name="poll_option" class="pe-poll-opt" maxlength="100" value="<%= (o && o.name) || '' %>" placeholder="<%= t('pedit.poll_option_ph') %>" <%= _pollLocked ? 'disabled' : '' %>
    275                      style="display:block;width:100%;box-sizing:border-box;margin-bottom:5px;font-size:13px;padding:7px 9px;border-radius:7px;border:1px solid var(--rule,rgba(128,128,128,.35));background:transparent;color:inherit">
     289              <div class="pe-poll-row">
     290                <input type="text" name="poll_option" class="pe-poll-opt" maxlength="100" value="<%= (o && o.name) || '' %>" placeholder="<%= t('pedit.poll_option_ph') %>" <%= _pollLocked ? 'disabled' : '' %>>
     291                <% if (!_pollLocked) { %><button type="button" class="pe-poll-del" aria-label="<%= t('pedit.poll_remove') %>" title="<%= t('pedit.poll_remove') %>">&times;</button><% } %>
     292              </div>
    276293            <% }); %>
    277294          </div>
    278           <button type="button" id="pe-poll-add" class="btn" data-ph="<%= t('pedit.poll_option_ph') %>" <%= _pollLocked ? 'disabled' : '' %> style="font-size:12.5px;padding:5px 10px">+ <%= t('pedit.poll_add') %></button>
    279           <label class="pe-checkbox" style="margin-top:8px">
     295          <% if (!_pollLocked) { %><button type="button" id="pe-poll-add" class="pe-poll-add">+ <%= t('pedit.poll_add') %></button><% } %>
     296          <label class="pe-checkbox">
    280297            <input type="checkbox" name="poll_multiple" value="1" <%= (_poll && _poll.multiple) ? 'checked' : '' %> <%= _pollLocked ? 'disabled' : '' %>>
    281298            <span><%= t('pedit.poll_multiple') %></span>
    282299          </label>
    283           <label style="display:block;font-size:12.5px;opacity:.8;margin:6px 0 4px"><%= t('pedit.poll_duration') %></label>
    284           <select name="poll_duration" <%= _pollLocked ? 'disabled' : '' %> style="padding:7px 9px;border-radius:7px;border:1px solid var(--rule,rgba(128,128,128,.35));background:transparent;color:inherit;font-size:13px">
     300          <label class="pe-poll-durlabel"><%= t('pedit.poll_duration') %></label>
     301          <select name="poll_duration" class="pe-poll-dur" <%= _pollLocked ? 'disabled' : '' %>>
    285302            <% [['300','5m'],['1800','30m'],['3600','1h'],['21600','6h'],['43200','12h'],['86400','1d'],['259200','3d'],['604800','7d']].forEach(function (d) { %>
    286303              <option value="<%= d[0] %>" <%= d[0] === '86400' ? 'selected' : '' %>><%= t('pedit.poll_dur_' + d[1]) %></option>
     
    290307        <script>
    291308        (function () {
    292           var tog = document.getElementById('pe-poll-toggle'), box = document.getElementById('pe-poll-fields');
    293           if (tog && box && !tog.__wired) { tog.__wired = true; tog.addEventListener('change', function () { box.style.display = tog.checked ? '' : 'none'; }); }
    294           var add = document.getElementById('pe-poll-add'), opts = document.getElementById('pe-poll-opts');
    295           if (add && opts && !add.__wired) { add.__wired = true;
    296             add.addEventListener('click', function () {
    297               if (opts.querySelectorAll('.pe-poll-opt').length >= 8) return;
    298               var i = document.createElement('input');
    299               i.type = 'text'; i.name = 'poll_option'; i.className = 'pe-poll-opt'; i.maxLength = 100;
    300               i.placeholder = add.getAttribute('data-ph') || '';
    301               i.setAttribute('style', 'display:block;width:100%;box-sizing:border-box;margin-bottom:5px;font-size:13px;padding:7px 9px;border-radius:7px;border:1px solid var(--rule,rgba(128,128,128,.35));background:transparent;color:inherit');
    302               opts.appendChild(i);
    303             });
     309          var box = document.getElementById('pe-poll-fields');
     310          var tog = document.getElementById('pe-poll-toggle');
     311          var opts = document.getElementById('pe-poll-opts');
     312          var add = document.getElementById('pe-poll-add');
     313          if (!box || !opts) return;
     314          if (tog && !tog.__wired) { tog.__wired = true; tog.addEventListener('change', function () { box.style.display = tog.checked ? '' : 'none'; }); }
     315          var PH = opts.getAttribute('data-ph') || '', DEL = opts.getAttribute('data-del') || '';
     316          function rows() { return opts.querySelectorAll('.pe-poll-row'); }
     317          // A poll needs at least 2 options: hide the ✕ at the minimum, and cap adding at 8.
     318          function refresh() {
     319            var n = rows().length;
     320            opts.querySelectorAll('.pe-poll-del').forEach(function (b) { b.hidden = n <= 2; });
     321            if (add) add.disabled = n >= 8;
    304322          }
     323          function makeRow() {
     324            var row = document.createElement('div'); row.className = 'pe-poll-row';
     325            var i = document.createElement('input'); i.type = 'text'; i.name = 'poll_option'; i.className = 'pe-poll-opt'; i.maxLength = 100; i.placeholder = PH;
     326            var d = document.createElement('button'); d.type = 'button'; d.className = 'pe-poll-del'; d.setAttribute('aria-label', DEL); d.title = DEL; d.innerHTML = '&times;';
     327            row.appendChild(i); row.appendChild(d); return row;
     328          }
     329          if (add && !add.__wired) { add.__wired = true; add.addEventListener('click', function () { if (rows().length >= 8) return; opts.appendChild(makeRow()); refresh(); }); }
     330          if (!opts.__wired) { opts.__wired = true; opts.addEventListener('click', function (e) { var d = e.target.closest('.pe-poll-del'); if (!d || rows().length <= 2) return; d.closest('.pe-poll-row').remove(); refresh(); }); }
     331          refresh();
    305332        })();
    306333        </script>
Note: See TracChangeset for help on using the changeset viewer.