diff --git a/frontend/js/assistant.js b/frontend/js/assistant.js index 563f034..e055c5b 100644 --- a/frontend/js/assistant.js +++ b/frontend/js/assistant.js @@ -337,6 +337,7 @@ document.body.appendChild(ov); var ring = ov.querySelector('.asst-tour-ring'); var tip = ov.querySelector('.asst-tour-tip'); + ov.addEventListener('click', function (e) { if (e.target === ov) finish(); }); // клик по фону — выход function finish() { ov.remove(); window.removeEventListener('resize', render); @@ -347,23 +348,11 @@ function render() { var st = steps[i]; var el = st.sel ? document.querySelector(st.sel) : null; + // сперва проматываем элемент в зону видимости, ПОТОМ меряем (иначе позиция стухшая) + if (el && vis(el) && el.scrollIntoView) { try { el.scrollIntoView({ block: 'center', inline: 'nearest' }); } catch (e) {} } var r = el && vis(el) ? el.getBoundingClientRect() : null; - if (r) { - var pad = 6; - ring.style.display = 'block'; - ring.style.left = (r.left - pad) + 'px'; ring.style.top = (r.top - pad) + 'px'; - ring.style.width = (r.width + pad * 2) + 'px'; ring.style.height = (r.height + pad * 2) + 'px'; - ov.style.background = ''; - var tx = r.right + 14, ty = Math.max(12, r.top); - if (tx + 290 > window.innerWidth) tx = Math.max(12, r.left - 294); // показать слева, если справа не влезает - tip.style.left = Math.min(tx, window.innerWidth - 290) + 'px'; - tip.style.top = Math.min(ty, window.innerHeight - 160) + 'px'; - tip.style.transform = ''; - } else { - ring.style.display = 'none'; - ov.style.background = 'rgba(15,12,30,.55)'; - tip.style.left = '50%'; tip.style.top = '50%'; tip.style.transform = 'translate(-50%,-50%)'; - } + + // контент сначала — чтобы измерить реальный размер подсказки и привязать кнопки tip.innerHTML = '
' + esc(st.title) + '
' + '
' + esc(st.text) + '
' + @@ -375,7 +364,28 @@ tip.querySelector('[data-a="next"]').onclick = function () { if (i === steps.length - 1) finish(); else { i++; render(); } }; var b = tip.querySelector('[data-a="back"]'); if (b) b.onclick = function () { i--; render(); }; tip.querySelector('[data-a="skip"]').onclick = finish; - if (el && el.scrollIntoView) { try { el.scrollIntoView({ block: 'nearest' }); } catch (e) {} } + + // позиционирование: подсказка ВСЕГДА целиком в пределах экрана + var W = window.innerWidth, H = window.innerHeight; + var tw = tip.offsetWidth || 280, th = tip.offsetHeight || 150; + tip.style.transform = ''; + if (r) { + var pad = 6; + ring.style.display = 'block'; + ring.style.left = (r.left - pad) + 'px'; ring.style.top = (r.top - pad) + 'px'; + ring.style.width = (r.width + pad * 2) + 'px'; ring.style.height = (r.height + pad * 2) + 'px'; + ov.style.background = ''; + var tx = r.right + 14; + if (tx + tw > W - 12) tx = r.left - tw - 14; // не влезает справа — показать слева + tx = Math.max(12, Math.min(tx, W - tw - 12)); + var ty = Math.max(12, Math.min(r.top, H - th - 12)); + tip.style.left = tx + 'px'; tip.style.top = ty + 'px'; + } else { + ring.style.display = 'none'; + ov.style.background = 'rgba(15,12,30,.55)'; + tip.style.left = Math.max(12, (W - tw) / 2) + 'px'; + tip.style.top = Math.max(12, (H - th) / 2) + 'px'; + } } window.addEventListener('resize', render); document.addEventListener('keydown', onKey);