Я не знаю, почему этот пост будет отнесен к категории “Сисадминство”, но категории “программирование” у меня тут нет. Мне просто лень открыть страницу и создать ее, распространяя хаос на этот блог. Давайте держать все организованным, хоть и не там, где надо.
Итак. Я реализую один очень интересный™ проект, и там встала проблема – скрипт загрузчика капчи надо грузить асинхронно через XMLHttpRequest, а в этом скрипте говнокод. А именно – document.write, чтобы размещали его просто в странице. Этот скрипт также вызывает уже саму капчу где, что бы вы думали? Тоже document.write!
Ну я конечно попробовал, но вот хуй там. Если раньше document.write из асинхронного запроса просто ломал DOM, то теперь нам вежливо намекают, что ты мудак:
Failed to execute ‘write’ on ‘Document’: It isn’t possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened
Такие вот дела.
Что же делать? Ну первая мысль была о том, чтобы попробовать загрузить src скрипта асинхронно, поменять код и затем выполнить eval. Но нет, так нельзя, все бьется о Same-Origin-Policy.
Что же делать? А давайте вспомним величайшие возможности javascript по изменению всего и вся и переназначем функцию document.write.
Наверное на этом моменте я ***нулся.
document.write = function (text) { if (text.match(/_puzzle/)) { document.querySelector('#_scriptloader').innerHTML = (text); var script = document.createElement("script"); script.type = "text/javascript"; script.src = (document.querySelector("#_scriptloader script").src); document.querySelector('#_captcha').appendChild(script); } else { document.querySelector('#_captcha').innerHTML = (text) } }
Просто берем и пишем в какой-либо div-плейсхолдер. Потом из этого дива берем src (ведь тупо вставкой кода в html асинхронно-загруженный html-код скрипта не выполнится, вы же помните это), создаем новый dom-объект script, и спокойно вставляем его в шапку или куда еще.
Важно знать, что вставлять могут не только скрипты, но еще и обычный html, по-этому важно делать проверки, я лично прегмачнул.
Итого, алгоритм следующий:
- Переопределить функцию document.write, чтобы она писала в какой-то скрытый div.
- Запросить target-страницу с <script src=blabla> с document.write.
- Вставить полученный <script src=blabla> в скрытый div.
- Создать пустой DOM-элемент script, установить ему src из div->script->src
- Добавить его в шапку или на страницу, он исполнится, вызывая переопреледенную document.write.
- Проверить, что там пришло в измененную функцию, и в зависимости от данных делать с ними что-либо.
- Начать сначала.
В п***у программирование, пойду выпью пива.