@Soul1

Как отследить загрузку элемента на странице?

На странице есть каскадная менюшка, при клике на пункт меню верхнего уровня раскрывается первый уровень меню и только после его раскрытия подгружаются внутренние подпункты. Далее нужно кликнуть следующий пункт меню уже вложенный, там тоже раскроется ещё один уровень вложенности. И так далее. Как не игрался с таймаутами всё равно асинхронный JavaScript бежит впереди паровоза и пытается найти следующие подпункты, которые ещё не подгрузились. С обработчиком DOMContentLoaded тоже ничего не получается((

Как сделать так, чтобы мы нажимали на пункт меню верхнего уровня, дожидались подгрузки всех вложенных элементов, затем нажимали на нужный подпункт, ждали подгрузки следующего уровня вложенности и всё это циклом, пока не доберёмся до конечного элемента?
  • Вопрос задан
  • 77 просмотров
Пригласить эксперта
Ответы на вопрос 1
@zkrvndm
Софт для автоматизации
Нужно использовать MutationObserver: https://learn.javascript.ru/mutation-observer
При помощи него можно отследить появление нужного элемента, ссылки или кнопки.

Пример:
Развернуть
function clickElements(selector, regexp, where) {
	
	return new Promise(function(returnResult) {
		
		var search_result = false;
		
		var local_reactive_function = async function() {
			
			var click_elements = searchElements(selector, regexp, where);
			
			if (click_elements.length > 0) {
				
				if (search_result === false) {
					
					search_result = true;
					
					await wait(500); // Время в миллисекундах между кликами
					
					var click_elements = searchElements(selector, regexp, where);
					
					if (click_elements.length > 0) {
						
						observer.disconnect();
						
						for (var n = 0; n < click_elements.length; n++) {
							click_elements[n].click();
						}
						
						returnResult(click_elements.length);
						
					}
					
					else {
						
						search_result = false;
						local_reactive_function();
						
					}
					
				}
				
			}
			
		}
		
		var observer = new MutationObserver(local_reactive_function);
		
		observer.observe(document.body, {
			characterData: true,
			attributes: true,
			childList: true,
			subtree: true
		});
		
		local_reactive_function();
		
	});
	
}

function searchElements(selector, regexp, where) {

	var search_elements = [];
	
	if (typeof where !== 'undefined') {
		
		var all_elements = where.querySelectorAll(selector);
		
	}
	
	else {
		
		var all_elements = document.querySelectorAll(selector);
		
	}
	
	for (var n = 0; n < all_elements.length; n++) {
		
		if (typeof regexp == 'object') {
			
			if (typeof regexp.test == 'function') {
				
				if (regexp.test(all_elements[n].innerText.trim())) {
					
					search_elements.push(all_elements[n]);
					
				}
				
			}
			
			
		}
		
		else {
			
			search_elements.push(all_elements[n]);
			
		}
	}
	
	return search_elements;

}

function wait(ms) {
	
	return new Promise(function(success) {
		
		setTimeout(function() {
			success(true);
		}, ms);
		
	});
	
}

Например, чтобы нажимать кнопки по мере их появления, вызывайте функцию clickElements:
await clickElements('Селектор первой кнопки');
await clickElements('Селектор второй кнопки');
await clickElements('Селектор третьей кнопки');

Будут прожжаты эти три кнопки по очереди, если какой-то кнопки еще нет, функция ее дождется и нажмет.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы