From 8434a6888f4a41cc2f6b7d812b7c37a93bb859a7 Mon Sep 17 00:00:00 2001 From: zuevav <34027267+zuevav@users.noreply.github.com> Date: Thu, 14 May 2026 22:51:29 +0300 Subject: [PATCH] Add nickname position selector and "use as price" toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two more nickname controls. A position selector (Auto / Снизу / Сверху) lets users override the auto-positioning that previously moved the nickname to the top whenever a price tag was visible — Auto keeps the old behavior. A "Use as price — add ₽" checkbox appends the ruble symbol to the rendered nickname text and inserts thousands separators when the text is purely digits, making it usable as a price label without the yellow band (handy when you want a curved price instead). Co-Authored-By: Claude Opus 4.7 (1M context) --- index.php | 23 +++++++++++++++++++++++ js/app.js | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index 5dbba4b..66042fb 100644 --- a/index.php +++ b/index.php @@ -685,6 +685,29 @@ https://live.staticflickr.com/65535/12345678901_abcdef1234_b.jpg"> По умолчанию — из настроек. +
+ +
+
+ +
+ + + +
+
diff --git a/js/app.js b/js/app.js index 64249a2..dc964bf 100644 --- a/js/app.js +++ b/js/app.js @@ -4265,6 +4265,7 @@ document.addEventListener('DOMContentLoaded', function() { nickSizeValue: document.getElementById('badge-nick-size-value'), nickEdge: document.getElementById('badge-nick-edge'), nickEdgeValue: document.getElementById('badge-nick-edge-value'), + nickAsPrice: document.getElementById('badge-nick-as-price'), btnDownload: document.getElementById('btn-badge-download'), btnRemove: document.getElementById('btn-badge-remove'), batchActions: document.getElementById('badge-batch-actions'), @@ -4494,10 +4495,24 @@ document.addEventListener('DOMContentLoaded', function() { } if (item.showNickname) { - const nick = (item.nickname || '').trim(); + let nick = (item.nickname || '').trim(); + // "Use as price" formatting: append ₽; if the text is purely digits, + // also insert thousands separators so it reads as a proper price. + if (item.nickAsPrice && nick) { + const digits = nick.replace(/[^\d]/g, ''); + if (digits && /^\d+$/.test(nick)) { + nick = parseInt(digits, 10).toLocaleString('ru-RU') + ' ₽'; + } else if (!nick.includes('₽')) { + nick = nick + ' ₽'; + } + } if (nick) { - // Auto-position: if price occupies the bottom, draw nickname as a top arc. - drawNicknameArc(c, size, nick, item, hasPrice ? 'top' : 'bottom'); + // Position: manual override (top/bottom) or auto (top when price occupies the bottom). + let pos; + if (item.nickPosition === 'top') pos = 'top'; + else if (item.nickPosition === 'bottom') pos = 'bottom'; + else pos = hasPrice ? 'top' : 'bottom'; + drawNicknameArc(c, size, nick, item, pos); } } @@ -4563,6 +4578,8 @@ document.addEventListener('DOMContentLoaded', function() { nickColor: '#FFFFFF', // text color (hex) nickSize: 100, // 60..160 (% scale of font) nickEdge: 14, // 0..30: percent inset from circle edge (0 = at edge) + nickPosition: 'auto', // 'auto' | 'top' | 'bottom' + nickAsPrice: false, // append ₽ + format digits as price }; } @@ -4627,6 +4644,10 @@ document.addEventListener('DOMContentLoaded', function() { el.nickSizeValue.textContent = item.nickSize + '%'; el.nickEdge.value = item.nickEdge; el.nickEdgeValue.textContent = item.nickEdge; + el.nickAsPrice.checked = !!item.nickAsPrice; + document.querySelectorAll('input[name="badge-nick-position"]').forEach(r => { + r.checked = r.value === (item.nickPosition || 'auto'); + }); renderItemsGrid(); renderPreview(); } @@ -4962,6 +4983,26 @@ document.addEventListener('DOMContentLoaded', function() { renderPreview(); }); + // Nickname "use as price" — append ₽ to the rendered text. + el.nickAsPrice.addEventListener('change', () => { + const item = currentItem(); + if (!item) return; + item.nickAsPrice = el.nickAsPrice.checked; + renderPreview(); + }); + + // Nickname position (auto / top / bottom). + document.querySelectorAll('input[name="badge-nick-position"]').forEach(r => { + r.addEventListener('change', () => { + const item = currentItem(); + if (!item) return; + if (r.checked) { + item.nickPosition = r.value; + renderPreview(); + } + }); + }); + el.btnRemove.addEventListener('click', () => { const item = currentItem(); if (item) removeItem(item.id);