Files
cc-1c-skills/.claude/skills/web-test/scripts/dom/edit-state.mjs
T
Nick Shirokov 8f2fa21814 fix(web-test): deleteTableRow выходит из cell edit-mode перед Delete
Delete-клавиша в режиме редактирования ячейки очищает буфер ввода,
а не удаляет строку. Это становилось проблемой когда:
1. предыдущий fillTableRow закончил Tab-навигацией в input (например
   в Number-ячейку соседней колонки), и фокус остался там;
2. сам click на Number/Date ячейку в deleteTableRow автоматически
   входит в edit-mode (поведение 1С).

Фикс: в deleteTableRow проверяем isInputFocusedInGrid дважды — до и
после click — и шлём Escape если активен INPUT в целевом гриде. Строка
остаётся выделенной после Escape, Delete срабатывает.

Дополнительно: isInputFocusedInGridScript / isInputFocusedInGrid теперь
принимают опциональный gridSelector — чтобы можно было прицельно проверять
конкретный грид на многогрид-формах (а не любой `.grid` на странице).

Покрытие: новый шаг в 05-table проверяет сценарий «фокус снаружи грида
(Комментарий), потом delete» — гарантирует что post-click Escape ловит
автоматический вход в edit-mode при клике на Number-ячейку.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:42:10 +03:00

64 lines
2.0 KiB
JavaScript

// web-test dom/edit-state v1.1 — focus and popup detection inside the 1C web client
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
/**
* Is the currently focused element an INPUT (optionally TEXTAREA too)?
* Returns boolean.
*
* @param {object} [opts]
* @param {boolean} [opts.allowTextarea=false] — also return true for TEXTAREA.
*/
export function isInputFocusedScript({ allowTextarea = false } = {}) {
const cond = allowTextarea
? `f.tagName === 'INPUT' || f.tagName === 'TEXTAREA'`
: `f.tagName === 'INPUT'`;
return `(() => {
const f = document.activeElement;
return !!(f && (${cond}));
})()`;
}
/**
* Is the currently focused INPUT/TEXTAREA inside a `.grid` ancestor?
* Used to verify grid edit-mode (active cell editor).
*
* @param {string} [gridSelector] — when given, only `true` if the focused input
* is inside that specific grid. Without it — any `.grid` ancestor counts.
*
* Returns boolean.
*/
export function isInputFocusedInGridScript(gridSelector) {
const sel = gridSelector ? JSON.stringify(gridSelector) : 'null';
return `(() => {
const f = document.activeElement;
if (!f || (f.tagName !== 'INPUT' && f.tagName !== 'TEXTAREA')) return false;
const sel = ${sel};
if (sel) {
const grid = document.querySelector(sel);
return !!(grid && grid.contains(f));
}
let n = f;
while (n) {
if (n.classList?.contains('grid')) return true;
n = n.parentElement;
}
return false;
})()`;
}
/**
* Is a calculator (`.calculate`) or calendar (`.frameCalendar`) popup visible?
* Returns `'calculator' | 'calendar' | null`.
*
* For the "popup gone" check, callers use: `!await findOpenPopup()`.
*/
export function findOpenPopupScript() {
return `(() => {
const calc = document.querySelector('.calculate');
if (calc && calc.offsetWidth > 0) return 'calculator';
const cal = document.querySelector('.frameCalendar');
if (cal && cal.offsetWidth > 0) return 'calendar';
return null;
})()`;
}