Ответы пользователя по тегу JavaScript
  • Как прослушать XHR-запрос?

    @zkrvndm
    Софт для автоматизации
    Вы можете подменить метод XHR на свой и смотреть, что отправляется:
    var original = {
    	open: XMLHttpRequest.prototype.open,
    	send: XMLHttpRequest.prototype.send
    };
    
    XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
    	console.log(method, url, async, user, password);
    	return original.open.call(this, method, url, async, user, password);
    };
    
    XMLHttpRequest.prototype.send = function (data) {
    	console.log(data);
    	return original.send.call(this, data);
    };
    Ответ написан
    Комментировать
  • Какую js-библиотеку можно взять для такой стилизации селектов?

    @zkrvndm
    Софт для автоматизации
    Да любой. Например можешь взять UIkit: https://3uikit.ru/form
    Ответ написан
    Комментировать
  • В чем отличие Deferred.always / Deferred.done / Deferred.fail от Deferred.then?

    @zkrvndm Автор вопроса
    Софт для автоматизации
    Оказалось есть принципиальная разница в поведении.

    Методы Deferred.always / Deferred.done / Deferred.fail возвращают тот же самый Deferred на котором были вызваны, а вот метод Deferred.then работает чуть посложнее.

    Deferred.then - возвращает НОВЫЙ объект Deferred. Если функция обработчик который вы передали в Deferred.then возвращает Deferred, то Deferred.then вернет именно этот самый Deferred. Если функция обработчик который вы передали в Deferred.then возвращает значение, то Deferred.then вернет выполненый Deferred с этим значением.

    Соответственно, принципиальное различие между методами Deferred.always / Deferred.done / Deferred.fail и Deferred.then в том, что на втором можно построить цепочки вызовов для последовательного асинхронного выполнения своего кода, а вот на первых так не получится.

    Пример
    d = $.Deferred(function(def) {
        setTimeout(function() {
            console.log(1);
            def.resolve();
        }, 1000);
    });
    
    d.then(function() {
        var def = $.Deferred();
        setTimeout(function() {
            console.log(2);
            def.resolve();
        }, 1000);
        return def;
    })
    
    .then(function() {
        var def = $.Deferred();
        setTimeout(function() {
            console.log(3);
            def.resolve();
        }, 1000);
        return def;
    })
    
    .then(function() {
        var def = $.Deferred();
        setTimeout(function() {
            console.log(4);
            def.resolve();
        }, 1000);
        return def;
    })
    
    .then(function() {
        var def = $.Deferred();
        setTimeout(function() {
            console.log(5);
            def.resolve();
        }, 1000);
        return def;
    });
    Ответ написан
    Комментировать
  • Как определить номер строки вызвавший Deferred.reject?

    @zkrvndm Автор вопроса
    Софт для автоматизации
    Сергей Сергей, спасибо за решение.

    Сделал обёртку для $.Deferred() - это работает. Ниже пример, если кому надо:

    Развернуть пример
    $(function() {
    	
    	// Логирование всех reject-событий:
    	
    	var original_deferred = $.Deferred;
    	$.Deferred = function() {
    		var deferred = original_deferred.apply(this, arguments);
    		var original_reject = deferred.reject;
    		deferred.reject = function() {
    			try { throw Error(); } catch(err) {
    				var mod_args = $(arguments).toArray();
    				var str_num = err.stack.split(':').reverse()[1];
    				mod_args.unshift(str_num + ' строка:');
    				console.error.apply(this, mod_args);
    				original_reject.apply(this, arguments);
    			}
    		}
    		return deferred;
    	}
    	
    	init(); // Проверка
    	
    });
    
    function init() {
    	
    	var deferred = $.Deferred();
    	
    	setTimeout(function() {
    		deferred.reject('Тестовая ошибка!');
    	}, 1000);
    	
    	return deferred;
    	
    }
    Ответ написан
    Комментировать
  • Как выполнить удаленный код на Manifest V3?

    @zkrvndm Автор вопроса
    Софт для автоматизации
    Решение найдено. Выполнить удаленный код на Manifest V3 можно следующим образом:

    1. В манифесте расширения прописываем контент-скрипт для нужного вам сайта.

    2. В файле контент-скрипта выполняем вставку тега script со ссылкой src на локальный файл из папки расширения. Это важный момент, на этом этапе нельзя сразу вставить удаленный код, так как расширение просто не даст это сделать ссылаясь на Content Security Policy. Поэтому сначала вставляем скрипт загрузчик, который должен обязательно присутствовать локально внутри с папкой расширения. Не забываем, что для загрузки локального скрипта у вас должны стоят правильные разрешения в манифесте в параметре web_accessible_resources.

    3. Уже внутри этого локального скрипта загрузчика, который мы вставили на этапе 2, можно загрузить удаленный код со своего сервера и вставить его инлайново на страницу. Он будет гарантированно выполнен в контексте страницы словно это родной скрипт сайта. Для кого-то это не важно в каком контексте мы выполняем код, но для меня важно, так как иногда чтобы сгенерировать корректный Event надо это делать именно из контекста страницы.
    Ответ написан
    Комментировать
  • Почему не парсится строка в JSON?

    @zkrvndm
    Софт для автоматизации
    Вы передаете массив, а надо передавать строку. Изучите типы данных в JavaScript, чтобы больше так не ошибаться.

    https://learn.javascript.ru/types
    Ответ написан
    Комментировать
  • Как получить путь к файлу из input type="file"?

    @zkrvndm
    Софт для автоматизации
    Пути получить можно, но только если выбирается папка.

    Например, введите в консоли:
    var input = document.createElement('input');
    input.setAttribute('type', 'file');
    input.setAttribute('webkitdirectory', 'true');
    
    input.addEventListener('change', function() {
        
        console.log('Выбраны файлы', input.files);
    
        console.log('Пути файлов относительно выбранной папки:');
    
        for (var n = 0; n < input.files.length; n++) {
            console.log(input.files[n].webkitRelativePath);
        }
        
    });
    
    input.click();

    И выберите какую-нибудь папку, где будет хотя бы несколько файлов (любых).

    Также при большом желании можно получить путь в виде Data URL - это такой формат адреса, когда файл сам весь целиком помещается непосредственно в адрес (в ссылку). Ниже пример Data URL, попробуйте его открыть:
    data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAAOoAAADqAFKWhcCAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAfhQTFRF////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe7yhUAAAAKd0Uk5TAAECAwQFBgcICQoLDA4PEBESFBYYGRscHR4fICIjJSYnKSosLS8wMTM0Njc8PT5AQUJDRkxNUFJTVFVYWltcX2BhY2RlZmhpa25yc3V2eX1/gIKDhIaIiYqLjI+RlJWXmJmanJ6gpKanqKmtrq+ws7S2t7q7vr/AwsTFxsjKy8zOz9DR0tbX2Nrc3eDh4uTl5ufo6err7e7v8PHy9PX29/j5+vv8/f5wrz1tAAADsklEQVQYGe3BgT+UdxwH8M8dnQ6lzWQzSbnQVNO2ay2ZGqvWFKsZTQptIystWqlLtmWUohRnMi109/k3J8PL6fk9PM/9nu+z7eX9Bv6b0oOnWi8u0XoqmA45vtoIXxOp9UFITi8N9eZAhCdEhZAHEiqoVAEJg1QahIBkmkiG8/JoIg/O20sTe+G8QpoohPOyaSIbzkujiTQ4zxuhUsQLAWNUGoOEASoNQMIdKt2BhE4qdUJCG5XaIKGRSo2QUEOlGkiopFIlJJRTqRwS9lNpPyQUU6kYEvKplA8JWVTKgoQNVNoAETNUmIGMUSqMQsY9KtyDjNtUuA0ZHVTogIwWKrRAxjkqnIOM01Q4DRnHqXAcMg5T4TBk7KPCPmiVWHK5Z+BSZTaW20OFPVguu/LSQM/lkkTYsOsh50SvHfAhRoAKAcTwHbgW5ZyHu2BZ8DkXjdRtxRKZVMjEElvrRrjoeRAWZUwyxo2DSViQQoUULEg6eIMxJjNgTROXC9dvx7wpGprCvO31YS7XBEsSX9DArTI/XnlCQ0/wir/sFg28SIQVARobb9gBoI+G+gDsaBinsQCsCFKpuzw1REOh1PJuKgVhRYAmJsZoaGyCJgKwYv00NZteD0suULMLsCbnJbV6mQOLvqJW1bAqIUSNbibAsuwJajOeBRvKqE0JbGmjJt/Dnk2D1OJ+Kmx6P0INZt6Dbd9Qg5Owb10P43bdizjkTjJO4UzE5XPG6WPEqZ1xaUa83nzMOPQnI24fRmnbVAE0qKdtX0KHpF7a1OmBFnl/0ZbRDGjyBW0JQhdPB21ogD5vjdCy3/3QKEirpvKh1XladAJ6+ftoyXUvNCuYogV/vA3tKmlBCfTz/MxV+wFOyBzjKj3YCEd8wtWJ7IZDvuOq1MApqfe5Cj3r4JiiGa5oMhcOquKKjsJJCTe5gp/grHef0dTTdDislKY+guNaaOI8nLfxAZX6kyFgd4QK04UQ8TUVTkJGYjcNdXkhJOdPGniWBTGf0cCnEPQjX9MKSW884jKDaRD1QZQxIsUQ9i1j1EGa71cu8YsP4t55zEW/pcMFBUOcF0qDKzY1P+Ws4aYUuCa34kS+B2vWrPkf8G4rPdMo6kzpNi8WHQrTBeFD+Mfmq3TJ1c2Y5btL19z1Aaili2qBwghdFClEFV1VhXa6qh1DdNUQhumqYVyhq66gmq6qRlGULooWAWfporMA/P10Tb8fs7Z00SVdWzDHc2yCLpg45sEC384jzRdFNR/Z6cO/wt/U0ZZGPsJ+bAAAAABJRU5ErkJggg==

    Просто скопируйте и вставьте в адресную строку.
    Ответ написан
    Комментировать
  • Как синхронно дождаться данных с сервера?

    @zkrvndm
    Софт для автоматизации
    Если вам надо обработать все запросы словно это один запрос используйте промисы для оборачивания запросов и метод Promise.all - он разом вернет результаты всех запросов.
    Ответ написан
    Комментировать
  • Можно ли в цикле foreach взаимодействовать с элементами цикла?

    @zkrvndm
    Софт для автоматизации
    vegs.forEach((veg, index) => {
        if (index === 0) {
            veg.classList.add('active');
        }
    });
    Ответ написан
    Комментировать
  • Как сделать переход между страницами без перезагрузки?

    @zkrvndm
    Софт для автоматизации
    Ниже пример функции для загрузки контента страниц по AJAX и без перезагрузки страницы:
    async function pageUpdate(event) {
    	
    	// Если функция вызвана без аргументов:
    	
    	if (typeof event == 'undefined') {
    		
    		// Устанавливаем обработчики
    		// на все ссылки на странице:
    		
    		$('body a[href]').click(pageUpdate);
    		
    	}
    	
    	// Если функция вызвана
    	// в результате клика
    	// по ссылке:
    	
    	else {
    		
    		// Берём адрес с нажатой ссылки
    		// и записываем в переменную link:
    		
    		var link = event.target.href;
    		
    		// Если ссылка ведет на наш сайт:
    		
    		if (new URL(link)['host'] == location.host) {
    			
    			// Предотвращаем переход:
    			
    			event.preventDefault();
    			
    			// Блокируем страницу, чтобы
    			// больше нельзя было кликать:
    			$('body').css('pointer-events', 'none');
    			
    			// Активируем анимацию исчезновения (полупрозрачности):
    			
    			var hide = $('body').animate({ opacity: 0.2 }, 500).promise();
    			
    			var ajax = $.ajax(link); // Запускаем загрузку новой страницы
    			
    			await hide; // Ждем окончания анимации исчезновения
    			
    			// Вставляем данные на страницу беря их с ново-скачанной страницы:
    			
    			var doc = new DOMParser().parseFromString((await ajax), 'text/html');
    			var html = $('body', doc).html();
    			$('body').html(html);
    			
    			// Скролим в самый вверх:
    			$('body, html').animate({scrollTop: 0}, 0);
    			
    			// Меняем адрес в адресной строке:
    			history.pushState(null, null, link);
    			
    			// Заново ставим
    			// обработчики:
    			
    			pageUpdate();
    			
    			// Активируем анимацию
    			// постепенного появления:
    			
    			await $('body').animate({ opacity: 1 }, 500).promise();
    			
    			// Снимаем блокировку с документа:
    			
    			$('body').css('pointer-events', '');
    			
    		}
    		
    	}
    	
    }
    
    pageUpdate();

    Функция перехватывает клики по ссылкам, добавляет анимацию и обновляет контент страницы без перезагрузки.

    Важно! Если на сайте есть какой-то сложный функционал, данный скрипт скорее-всего их сломает!
    Ответ написан
    Комментировать
  • Как синхронно получить Data URL?

    @zkrvndm Автор вопроса
    Софт для автоматизации
    Alexandroppolus к сожалению оказалось, что используя XMLHttpRequest нельзя загрузить файл как ArrayBuffer в синхронном режиме, такое возможно только, если запрос идет асинхронно, но мне ни что не мешает скачать файл, как текст, а затем этот текст уже перегнать в Uint8Array при помощи TextEncoder, а дальше уже его конвертировать в Base64 используя код из предложенного тобой плагина.

    Соответственно после такой конвертации получить так желаемый мной Data URL:
    var request = new XMLHttpRequest();
    request.open('GET', '/', false);
    request.send(null);
    
    if (request.status === 200) {
    
    	var type = request.getResponseHeader('Content-Type').split(';')[0].toLowerCase();
    	var u8a = new TextEncoder().encode(request.responseText);
    
    	var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    
    	var bytes = u8a, i, len = bytes.length, base64 = '';
    
    	for (i = 0; i < len; i += 3) {
    		base64 += chars[bytes[i] >> 2];
    		base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
    		base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
    		base64 += chars[bytes[i + 2] & 63];
    	}
    
    	if (len % 3 === 2) {
    		base64 = base64.substring(0, base64.length - 1) + '=';
    	}
    
    	else if (len % 3 === 1) {
    		base64 = base64.substring(0, base64.length - 2) + '==';
    	}
    
    	var data_url = 'data:' + type + ';base64,' + base64;
    
    	console.log(data_url);
    
    }
    
    else {
    	
    	console.log('Ошибка', request);
    	
    }

    Главное, все это работает синхронно и метод можно применять для модификации скриптов сайта на лету через фоновый скрипт своего браузерного расширения, т. е. перехватываем запрос и делаем редирект на Data URL.
    Ответ написан
  • Как сделать простое расширение/пользовательский js для браузера?

    @zkrvndm
    Софт для автоматизации
    Расширение которое будет запускать какой-то код на сайте делает очень просто, другое дело что даже это самое просто мне лично сейчас лень объяснять, да и не до этого пока. Из простых решений рекомендую:
    https://chrome.google.com/webstore/detail/custom-j...
    Это стороннее расширение позволяющие запускать свой код на чужих сайтах.
    Ответ написан
  • Как создать картинку из строки base64?

    @zkrvndm
    Софт для автоматизации
    Это элементарно делается в одну строку через fetch:
    blob = await (await fetch('data:image/png;base64,блабла')).blob();

    В переменной blob будет лежать файл, его можно спокойно отправить на сервер при помощи FormData.
    Ответ написан
    4 комментария
  • Как открыть консоль при помощи Javascript?

    @zkrvndm
    Софт для автоматизации
    Комбинация Ctrl + Shift + J открывает консоль. Если сильно надо ты можешь эту комбинацию забить в макрос и открывать консоль в один клик. Программ создающих макросы для винды полно.
    Ответ написан
  • Почему регулярное выражение парсит лишь первую строку?

    @zkrvndm
    Софт для автоматизации
    Для парсинга html кода существует DOMParser:
    https://developer.mozilla.org/ru/docs/Web/API/DOMParser
    Использовать регулярки для получения ссылок это накладно по расходам и неоправданно.
    Ответ написан
    Комментировать
  • Как отменить событие скролла при достижении цели, а затем возобновить?

    @zkrvndm
    Софт для автоматизации
    Используй Intersection Observer API:
    developer.mozilla.org/ru/docs/Web/API/Intersection...
    Как только кнопка показать еще попадает в область видимости, то грузишь посты.
    Разумеется необходимо предусмотреть блокировку повторного вызова на время загрузки постов.

    Intersection Observer API позволяет указать функцию, которая будет вызвана всякий раз для элемента (target) при пересечении его с областью видимости документа (по умолчанию) или заданным элементом (root).
    Ответ написан
    Комментировать
  • Как заблокировать изменение значения инпута, кроме прямого ввода с клавиатуры?

    @zkrvndm
    Софт для автоматизации
    Нужно повесить обработчик на событие ввода и принимать данные только если имеется положительный isTrusted.
    Но по правде говоря все это бессмысленно, так как легко обходит любым, кто хоть немного смыслит в JavaScript.
    Ответ написан
    Комментировать
  • Как корректно кликать по формам JQuery?

    @zkrvndm
    Софт для автоматизации
    Если вызываете на элементе событие, то делайте его всплывающим. Например, после ввода текста в поле:
    input = document.querySelector('input');
    
    input.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true }));
    input.dispatchEvent(new KeyboardEvent('keypress', { bubbles: true }));
    input.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true }));
    input.dispatchEvent(new InputEvent('input', { bubbles: true }));
    input.dispatchEvent(new InputEvent('change', { bubbles: true }));

    Современные фреймворки они не следят за событиями на элементе, они следят за событиями на родителях этих элементов, поэтому чтобы сработали обработчики на странице, надо события делать всплывающими.
    Ответ написан
    1 комментарий
  • Как в JS сделать POST-запрос через fetch?

    @zkrvndm
    Софт для автоматизации
    Пробуй так:
    var url = 'https://адрес_запроса';
    
    var data = {
        'grant_type': ***,
        'client_id': ***,
        'client_secret': ***
    };
    
    var response = await (await fetch(url, {
    	'method': 'POST',
    	'headers': {
    		'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    	},
    	'body': new URLSearchParams(data).toString()
    })).json();
    
    console.log('Ответ сервера:');
    console.dir(response);
    
    console.log('Токен:');
    console.dir(response['access_token']);
    Ответ написан
    Комментировать