Ответы пользователя по тегу JavaScript
  • Как с jquery лучше отследить изменение класса?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Используйте MutationObserver.
    Ответ написан
  • Как нажать кнопку на чужом сайте через консоль?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Нажимать надо чекбокс, а не бордюр вокруг него. Попробуйте прожжать сам чекбокс, при этом не забудьте переключить консоль браузера в контекст того iframe, в котором висит галочка.
    Ответ написан
  • JavaScript. Цикл. Кнопка?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Я дам вам функцию кликер с одного из своих расширений, используйте его:
    Асинхронная функция кликер
    function clickElements(selector, regexp, where) {
    	
    	return new Promise(function(returnResult) {
    		
    		var search_result = false;
    		
    		var local_reactive_function = function() {
    			
    			var click_elements = searchElements(selector, regexp, where);
    			
    			if (click_elements.length > 0) {
    				
    				if (search_result === false) {
    					
    					search_result = true;
    					
    					await wait(100);
    					
    					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:
    (async function() {
        await clickElements('CSS-селектор');
    })();

    Функция clickElements обязательно дождется появления кнопок соответствующих указанному CSS-селектору, подождет 100 мс. после появления кнопок, после чего все их нажмёт. Обратите внимание, что если кнопок соответствующих селектору будет несколько, будут нажаты они все, поэтому тщательно подбирайте селектор.

    P. S. Если вам нужно после появления кнопки кликать его безостановочно, просто используйте цикл:
    (async function() {
        while(true) {
            await clickElements('CSS-селектор');
            console.log('Успешно выполнен клик');
        }
    })();

    После появления кнопки клики на него начнут сыпаться с частой один клик каждые 100 мс. пока кнопка не исчезнет.
    Ответ написан
    Комментировать
  • Как отказаться от jquery и jquery библиотек?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Я сам когда пишу расширения, не использую jQuery, но jQuery необходим когда пилишь сайты и заказчик просит, чтобы функционал корректно работал и в старых браузерах. Как по мне jQuery это самый просто способ обеспечить какую-никакую, но кроссбраузерность.
    Ответ написан
    Комментировать
  • Как подключить (аналог php include) html файл в js?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Если на сайте подключен jQuery, то просто используйте метод load, чтобы вставить HTML файл внутрь нужного вам блока:
    https://basicweb.ru/jquery/jquery_method_load.php

    Пример:
    $('.top-section').load('hello.html');
    Ответ написан
    1 комментарий
  • Как изменить заголовок страницы до загрузки DOM (расширение Chrome)?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Это конечно можно сделать, но только через костыль. Укажите в манифесте расширения опцию run_at со значением document_start, чтобы ваш контент-скрипт запускался до готовности документа:
    {
    	
    	"name" : "Имя расширения",
    	
    	"manifest_version" : 2,
    	
    	// ............................
    	
    	"content_scripts" : [
    		
    		{	
    			"matches" : [ "https://*.site.ru/*", ],
    			"run_at": "document_start",
    			"js" : [ "content-script.js" ]
    		}
    		
    	]
    	
    }

    Далее в контент-скрипте вызывайте:
    document.write('');
    document.close();

    Это мгновенно перезапишет содержимое страницы пустотой, а дальше делайте с ней (со страницей), что хотите.

    P. S. Зачем вам это нужно, если не секрет? Может другое решение подскажу.
    Ответ написан
    5 комментариев
  • Какой есть чат для сайта с API и приложением?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Вам подойдет любой чат не использующий iframe. Просто посмотрите топ 10 чатов, если в каком-то из них чат выводится НЕ при помощи iframe, то в такой чат можно легко и просто JavaScript кодом на вашей стороне дописать данные о размерах колес.
    Ответ написан
    1 комментарий
  • Как из ответа Ajax удалить всё кроме таблицы с определённым айди?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Допустим в переменной html лежит ответ сервера и нужно извлечь из него только таблицу id="myTable"

    Делается это следующим образом:
    table = new DOMParser().parseFromString(html, 'text/html').querySelector('table[id="myTable"]').outerHTML;
    console.log("Таблица успешно извлечена: \n" + table);
    Ответ написан
    1 комментарий
  • Как правильно хранить Blob в бд?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Если дело происходит в браузере, можно файлы сохранить в IndexedDB и они там будут оставаться даже после перезагрузки страницы. Для сохранения file в IndexedDB сначала подключайте на станице библиотеку localforage:
    <script src="https://cdnjs.cloudflare.com/ajax/libs/localforage/1.9.0/localforage.min.js"></script>


    Далее уже можно спокойно закинуть файл в память браузер вот так:
    async function saveFile(file) {
        var result = await localforage.setItem('file', file);
        console.log('Файл сохранён:');
        console.dir(result);
    }

    Вызывайте функцию saveFile передав ему аргументом тот файл, который надо сохранить.

    Чтобы потом извлечь этот файл из памяти и вставить в тег src у картинки:
    async function getFile() {
        var file = await localforage.getItem('file');
        document.querySelectror('img').src = URL.createObjectURL(file);
        console.log('Файл вставлен:');
        console.dir(file);
    }

    Просто вызывайте функцию getFile.

    Подробнее о библиотеке localforage можно почитать здесь:
    https://html5.by/blog/localforage/

    Выше просто примеры. Чтобы допилить под себя рекомендую ознакомится с тем, что такое промисы и чем отличаются асинхронные функции от обычных + постараться понять, как работает async / await.
    Ответ написан
  • Есть ли полноценное серверное решения для запуска браузерного JS?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Ты можешь на VDS запустить хром и там уже выполнять задачи нужные в плане отрисовки, сами задачи получать и отдавать по веб-сокету с того сервера, где твой сайт размещен. Так себе решение конечно, но если NodeJS не тянет нужные задачи, то боюсь это единственное доступное решение, хотя может кто еще что-нибудь посоветует.
    Ответ написан
    Комментировать
  • Как отправить данные на сервер с Ajax на чистом JavaScript?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Отправку данных делаете так:
    spoiler
    // Ждем когда элементы на странице прогрузятся:
    
    document.addEventListener('DOMContentLoaded', function() {
    
    	// Вешаем на кпопку обработчик клика, чтобы при каждом клике
    	// сразу запускалась функц я dataSend отвечающая за отправку данных:
    	
    	document.querySelector('.button').addEventListener('click', dataSend);
    	
    });
    
    // Функция для отправки данных на сервер:
    
    async function dataSend() {
    
    	// Получаем данные с нужных нам полей в переменные:
    	
    	var loginValue = document.querySelector('.login').value
    	var emailValue = document.querySelector('.email').value
    	var passwordValue = document.querySelector('.password').value
    	var conf_passwordValue = document.querySelector('.conf_password').value
    
    	// Создаем объект с данными:
    
    	var data = {
    		'login': loginValue,
    		'email': emailValue,
    		'password': passwordValue,
    		'conf_password': conf_passwordValue
    	}
    
    	// Конвертируем объект в JSON:
    
    	var json = JSON.stringify(data);
    
    	// Отправялеям полученный JSON на сервер обычным POST-запросом:
    
    	var response = await (await fetch('https://yousite.ru/handler.php', {
    		'method': 'POST',
    		'headers': {
    			'Content-Type': 'application/json; charset=utf-8'
    		},
    		'body': json
    	})).text();
    
    	// Выводим ответ сервера в консоли:
    
    	console.log('Ответ сервера:');
    	console.log(response);
    
    }

    Замените только ссылку на php-обработчик на свой. Далее, принимать данные отправленные, как JSON надо по другому. Пример получения данных отправленных, как JSON:
    spoiler
    <?php
    
    // Включим показ ошибок:
    
    ini_set('error_reporting', E_ALL);
    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    
    // Считываем полученный JSON:
    
    $json = file_get_contents('php://input');
    
    // Раскодируем JSON в массив:
    
    $array = json_decode($json, true);
    
    // Выведем массив, чтобы посмотиеть, что в нем:
    
    header('Content-Type: text/plain; charset=UTF-8'); // Указыавем браузеру, что ответ будет обычным текстом
    echo "Из браузера получены следующие данные:\n"; // Выведем текст-предупреждение
    print_r($array); // Выведем все, что находится в массиве
    Ответ написан
    7 комментариев
  • Как сделать, что бы Iframe грузился после того, как загрузится весь контент сайта?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Там где должен быть фрейм вставь следующий скрипт:
    <script id="iframe_loader">
    	window.addEventListener('load', function() {
    		document.querySelector('#iframe_loader').outerHTML = '<iframe src="https://81adcaf58307d2589d4c66bdc2d7e3e8.customizer.amigo.ru" id="calcAmigo" height="640px" width="100%"></iframe>';
    	});
    </script>
    Ответ написан
    Комментировать
  • Как обновить html таблицу с php циклом?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Если структура таблицы не меняется, вы можете полученную через AJAX таблцу распарсить через DOMParser, а далее тупо через querySelectorAll и цикл for перебрать все ячейки и обновить данные в вашей основной таблице.
    Ответ написан
  • Как правильно составить тело запроса при multipart/form-data?

    zkrvndm
    @zkrvndm Автор вопроса
    Архитектор решений
    Благодоря подсказе Alexandroppolus наконец удалось правильно собрать тело запроса, теперь все работает =)

    Пример ручной отправки файлов на сервер для будущих поколений:
    // Тестовый объект:
    
    test_obj = {
    	'per1': 'Привет!',
    	'per2': 'Это проверка!',
    	'per3': new File(['Привет, мир!'], 'test.txt', {type: 'text/plain'})
    };
    
    // Тестовая отправка:
    await multipartSend(test_obj);
    
    // Функция для отправки данных:
    
    async function multipartSend(obj) {
    	
    	// Генерируем уникальный разделитель:
    	var boundary = '----WebKitFormBoundary';
    	var symbols = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    	for (var i = 0; i < 18; i++) { boundary += symbols.charAt(Math.floor(Math.random() * symbols.length)); }
    
    	var arr = [ ]; // Массив для записи тела запроса
    	
    	// Перебираем свойства отправляемого объекта:
    	
    	for (key in obj) {
    		
    		// Если текущее свойство объекта строка или число:
    		
    		if (typeof obj[key] == 'string' || typeof obj[key] == 'number') {
    			
    			// Добавляем значение текущего параметра в массив как строку, разумеется вместе с разделителем и метаданными:
    			arr.push("--" + boundary + "\r\nContent-Disposition: form-data; name=\"" + key + "\"\r\n\r\n" + obj[key] + "\r\n");
    			
    		}
    		
    		// Если текущее свойство объекта файл:
    		
    		else if (typeof obj[key] == 'object') {
    			
    			if (typeof obj[key]['name'] !== 'undefined' && typeof obj[key]['type'] !== 'undefined') {
    				
    				// Добавляем метаданные от файла и разделитель, как обычную строку:
    				arr.push("--" + boundary + "\r\nContent-Disposition: form-data; name=\"" + key.replace(/\[[0-9]*\]$/, '[]') + "\"; filename=\"" + obj[key]['name'] + "\"\r\nContent-Type: " + obj[key]['type'] + "\r\n\r\n");
    				
    				arr.push(obj[key]); // Сам файл добавляем целиком, как есть
    				
    				arr.push("\r\n"); // И не забываем про перенос строкки с конца
    				
    			}
    			
    		}
    		
    	}
    
    	arr.push("--" + boundary + "--\r\n"); // Добавляем последний разделитель в массив
    	var body = new Blob(arr); // Формируем тело запроса (бинарник) для отправки из собранного ранее массива
    	
    	// Отправляем бинарник и смотрим результат:
    	
    	var response = await (await fetch('https://nadim.work/test.php', {
    		'method': 'POST',
    		'headers': {
    			'Content-Type': 'multipart/form-data; boundary=' + boundary
    		},
    		'body': body
    	})).text();
    	
    	console.log(response);
    	
    	return response;
    
    }
    Ответ написан
  • Как обновлять дату каждые n-дней, статический сайт?

    zkrvndm
    @zkrvndm
    Архитектор решений
    JavaScript-ом запрашивайте дату с любого публичного сервера, их дохрена. Далее эту дату тупо подставляйте куда надо. При этом вы избежите привязки к дате компьютера пользователя.
    Ответ написан
    Комментировать
  • Как создать бота, делающий автоматические действия на сайте?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Вам нужно написать браузерное расширение, которое будет выполнять ваш JavaScript на чужих сайтах. Нужная вам штука называется контент-скрипт.
    Ответ написан
    Комментировать
  • Как сделать "если все с кнопки с val="off", то..."?

    zkrvndm
    @zkrvndm
    Архитектор решений
    $('button.pr_water').click(function() {
        if ($('button.pr_water[val="off"]').length === $('button.pr_water').length) {
            $('button.all_water').attr('val', 'on');
        }
    });
    Ответ написан
    3 комментария
  • Как скачать файлы с другого сайта при помощи JS?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Вам нужно на стороне своего сервера написать скрипт, который авторизуется на сайте поставщика, скачает прайс и отдаст его посетителю. Если ваш сайт работает на PHP, соотвественно вам нужен php-скрипт. В языке PHP для парсинга чужих сайтов есть инструмент cURL, используйте его.

    P. S. И нет, примеров вам тут никто не даст, если сами не тянете написание скрипта, либо конкретизируйте вопрос до конкретной техниечской проблемы, либо оращайтесь на фрилансим за готовым кодом: https://freelance.habr.com/
    Ответ написан
  • Как узнать id формы через его дочерний input?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Вызывайте parentElement в цикле до тех пор, пока не получите элемент с тегом form.
    Ответ написан
    Комментировать
  • Как сделать последовательное выполнение функций?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Это делается не так. Во первых, для поиска элементов на странице лучше использовать не таймеры, а MutationObserver. Во вторых, функцию кликер лучше оборачивать в промис и уже затем вызывать ее последовательно в том порядке в котором нужны клики. Ниже пример с одного из моих проектов:
    Асинхронная функция кликер
    async function main() {
        await clickElements('CSS-селектор 1');
        await clickElements('CSS-селектор 2');
        await clickElements('CSS-селектор 3');
    }
    
    main(); // Запускаем последовательные клики
    
    function clickElements(selector, regexp, where) {
    	
    	return new Promise(function(returnResult) {
    		
    		var search_result = false;
    		
    		var local_reactive_function = function() {
    			
    			var click_elements = searchElements(selector, regexp, where);
    			
    			if (click_elements.length > 0) {
    				
    				if (search_result === false) {
    					
    					search_result = true;
    					observer.disconnect(); 
    					
    					setTimeout(function() {
    						
    						var click_elements = searchElements(selector, regexp, where);
    						
    						for (var n = 0; n < click_elements.length; n++) {
    							click_elements[n].click();
    						}
    						
    						returnResult(click_elements.length);
    						
    					}, 500);
    					
    				}
    				
    			}
    			
    		}
    		
    		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;
    
    }

    Функция clickElements обязательно дождется появления кнопок соотвествующих указанным CSS-селекторам и только тогда их нажмёт, последовательно сверху вниз. При этом в эту функцию вторым параметром можно передать регулярное выражение, чтобы найти кнопку по его тексту. Третьим параметрим, при желании, можно указать узел внутри котрого надо искать элемент.
    Ответ написан
    Комментировать