fix(assistant): тур не залипает на нижних шагах
Подсказка тура уезжала за край на нижних пунктах сайдбара (Питомец), а оверлей ловил клики → «ничего не сделать». Теперь: scrollIntoView ДО замера позиции, подсказка жёстко клампится в пределах экрана (меряем реальный размер), и клик по затемнённому фону закрывает тур (escape-hatch вдобавок к Esc). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+27
-17
@@ -337,6 +337,7 @@
|
|||||||
document.body.appendChild(ov);
|
document.body.appendChild(ov);
|
||||||
var ring = ov.querySelector('.asst-tour-ring');
|
var ring = ov.querySelector('.asst-tour-ring');
|
||||||
var tip = ov.querySelector('.asst-tour-tip');
|
var tip = ov.querySelector('.asst-tour-tip');
|
||||||
|
ov.addEventListener('click', function (e) { if (e.target === ov) finish(); }); // клик по фону — выход
|
||||||
function finish() {
|
function finish() {
|
||||||
ov.remove();
|
ov.remove();
|
||||||
window.removeEventListener('resize', render);
|
window.removeEventListener('resize', render);
|
||||||
@@ -347,23 +348,11 @@
|
|||||||
function render() {
|
function render() {
|
||||||
var st = steps[i];
|
var st = steps[i];
|
||||||
var el = st.sel ? document.querySelector(st.sel) : null;
|
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;
|
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 =
|
tip.innerHTML =
|
||||||
'<div class="asst-tour-h">' + esc(st.title) + '</div>' +
|
'<div class="asst-tour-h">' + esc(st.title) + '</div>' +
|
||||||
'<div class="asst-tour-t">' + esc(st.text) + '</div>' +
|
'<div class="asst-tour-t">' + esc(st.text) + '</div>' +
|
||||||
@@ -375,7 +364,28 @@
|
|||||||
tip.querySelector('[data-a="next"]').onclick = function () { if (i === steps.length - 1) finish(); else { i++; render(); } };
|
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(); };
|
var b = tip.querySelector('[data-a="back"]'); if (b) b.onclick = function () { i--; render(); };
|
||||||
tip.querySelector('[data-a="skip"]').onclick = finish;
|
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);
|
window.addEventListener('resize', render);
|
||||||
document.addEventListener('keydown', onKey);
|
document.addEventListener('keydown', onKey);
|
||||||
|
|||||||
Reference in New Issue
Block a user