Add nickname position selector and "use as price" toggle

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) <noreply@anthropic.com>
This commit is contained in:
zuevav
2026-05-14 22:51:29 +03:00
parent a781deccdd
commit 8434a6888f
2 changed files with 67 additions and 3 deletions
+23
View File
@@ -685,6 +685,29 @@ https://live.staticflickr.com/65535/12345678901_abcdef1234_b.jpg"></textarea>
<input type="text" id="badge-nickname-value" maxlength="40" placeholder="Никнейм"> <input type="text" id="badge-nickname-value" maxlength="40" placeholder="Никнейм">
<span class="hint">По умолчанию — из настроек.</span> <span class="hint">По умолчанию — из настроек.</span>
</div> </div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="badge-nick-as-price">
<span>Использовать как цену — добавить ₽</span>
</label>
</div>
<div class="form-group">
<label>Положение надписи:</label>
<div class="badge-radio-row">
<label class="radio-label">
<input type="radio" name="badge-nick-position" value="auto" checked>
<span>Авто</span>
</label>
<label class="radio-label">
<input type="radio" name="badge-nick-position" value="bottom">
<span>Снизу</span>
</label>
<label class="radio-label">
<input type="radio" name="badge-nick-position" value="top">
<span>Сверху</span>
</label>
</div>
</div>
<div class="form-group"> <div class="form-group">
<label>Размер текста: <span id="badge-nick-size-value">100%</span></label> <label>Размер текста: <span id="badge-nick-size-value">100%</span></label>
<input type="range" id="badge-nick-size" min="60" max="160" step="5" value="100"> <input type="range" id="badge-nick-size" min="60" max="160" step="5" value="100">
+44 -3
View File
@@ -4265,6 +4265,7 @@ document.addEventListener('DOMContentLoaded', function() {
nickSizeValue: document.getElementById('badge-nick-size-value'), nickSizeValue: document.getElementById('badge-nick-size-value'),
nickEdge: document.getElementById('badge-nick-edge'), nickEdge: document.getElementById('badge-nick-edge'),
nickEdgeValue: document.getElementById('badge-nick-edge-value'), nickEdgeValue: document.getElementById('badge-nick-edge-value'),
nickAsPrice: document.getElementById('badge-nick-as-price'),
btnDownload: document.getElementById('btn-badge-download'), btnDownload: document.getElementById('btn-badge-download'),
btnRemove: document.getElementById('btn-badge-remove'), btnRemove: document.getElementById('btn-badge-remove'),
batchActions: document.getElementById('badge-batch-actions'), batchActions: document.getElementById('badge-batch-actions'),
@@ -4494,10 +4495,24 @@ document.addEventListener('DOMContentLoaded', function() {
} }
if (item.showNickname) { 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) { if (nick) {
// Auto-position: if price occupies the bottom, draw nickname as a top arc. // Position: manual override (top/bottom) or auto (top when price occupies the bottom).
drawNicknameArc(c, size, nick, item, hasPrice ? 'top' : '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) nickColor: '#FFFFFF', // text color (hex)
nickSize: 100, // 60..160 (% scale of font) nickSize: 100, // 60..160 (% scale of font)
nickEdge: 14, // 0..30: percent inset from circle edge (0 = at edge) 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.nickSizeValue.textContent = item.nickSize + '%';
el.nickEdge.value = item.nickEdge; el.nickEdge.value = item.nickEdge;
el.nickEdgeValue.textContent = 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(); renderItemsGrid();
renderPreview(); renderPreview();
} }
@@ -4962,6 +4983,26 @@ document.addEventListener('DOMContentLoaded', function() {
renderPreview(); 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', () => { el.btnRemove.addEventListener('click', () => {
const item = currentItem(); const item = currentItem();
if (item) removeItem(item.id); if (item) removeItem(item.id);