Ключ к эффективному алгоритму здесь – определить, достаточно ли места по каждой из четырех сторон (сверху, снизу, слева, справа) от активатора, чтобы тултип вместился без выхода за пределы экрана.
Вот базовая идея алгоритма:
1. Определить размеры и положение элемента-активатора, используя getBoundingClientRect.
2. Определить размер окна браузера.
3. Рассчитать доступное пространство в каждом из направлений: сверху, снизу, слева, и справа от элемента.
4. Используя размеры тултипа, определить может ли он поместиться в каждом из этих направлений.
5. Если тултип не помещается в первоначальном направлении:
- Испытать альтернативные позиции на основе доступного пространства и размеров тултипа.
- Выбрать позицию, которая наилучшим образом подходит и не заходит за пределы экрана.
В реальной реализации вам нужно будет также учесть размеры самого тултипа, чтобы точно определить, поместится ли он в доступном пространстве, и возможно, предусмотреть отступы от краев экрана.
Также важно обеспечить динамическую перепроверку позиции тултипа при событиях, которые могут изменить положение или размер активатора, например, при изменении размера окна браузера (event resize) или прокрутке страницы (event scroll).
И наконец, поскольку это может быть ресурсоемкий процесс, обдумайте использование debounce функции для событий, вызываемых слишком часто.