Расширение к FF
Вот скрипт расширения к FF
<?xml version="1.0"?> <overlay id="sample" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/x-javascript"> <![CDATA[ function repl() { alert('I am sample extension!'); } window.addEventListener("load", repl, true); ]]> </script> <statusbar id="status-bar"> <statusbarpanel id="my-panel" label="Sample extension work."/> </statusbar> </overlay> Он срабатывает после загрузки в браузер каждого нового документа. Задача: В функции repl() получить текст первого скрипта в загруженном документе. Как построить строку обращения? Помогите, плиз, кто в курсе. |
Этот вопрос снимается. Строка обращения выглядит так
s=content.document.getElementsByTagName("script")[i].text; и в переменной s содержимое скрипта. Однако, теперь новая проблема. Модифицируем s и присваиваем content.document.getElementsByTagName("script")[i].text=s; Инспектор DOM показывает измененный текст, однако в загруженной странице содержимое скрипта не изменилось и на выполнение запускается исходный вариант. Как же заставить работать измененный скрипт? |
Vladimir, не знаток я ксула, но посоветую удалять первый скрипт и создавать вместо него новый.
|
Спасибо. Однако, не могу найти подходящих методов для удаления старого и вставки нового скриптов. Поиски продолжаю, но может кто уже знает, подскажите, плиз.
|
Читайте туториалы DOM. Всё, что вам надо сделать, это сделать removeChild() для этого элемента <script>, а затем, создав новый вставить его через appendChild(). Это будет выглядеть примерно так (возможны ошибки, поэтому лучше сами прочтите материалы по этой теме):
var scriptElement = document.getElementsByTagName('script')[0]; var newScriptElement = document.createElement('script'); // Выполняем действия с новым элементом скрипт: newScriptElement.type = 'text/javascript'; if(scriptElement.parentNode) { var scriptParent = scriptElement.parentNode; scriptParent.removeChild(scriptElement); scriptParent.appendChild(newScriptElement); } Пока писал мне пришла в голову идея лучше. Собственно, зачем вам вставлять тег скрипт через javascript в тело html? Если только для того, что бы выполнить модифицированный код, то воспользуйтесь функцией eval(), например так: var scriptElement = document.getElementsByTagName("script")[0]; var scriptContent = scriptElement.text; // ... Тут выполняем действия с scriptContent ... eval(scriptContent); А если вам нужно "хранить" этот скрипт, то подходящим контейнером не обязательно должен быть какой-то элемент html, храните её в переменной. |
Спасибо за развернутый ответ. Я смотрел туториалы DOM и XUL. Перебробовал множество вариантов. Проблема, однако, в том, что скрипт расширения находится в chrome, а скрипт, который надо изменить - в основном документе. Т.е. сначала я получаю в хроме текст скрипта основного документа как
s=content.document.getElementsByTagName("script")[0].text; это работает. затем я меняю скрипт в переменной "s" и делаю обратное присвоение сontent.document.getElementsByTagName("script")[0].text=s; Инспектор DOM показывает измененный текст скрипта, однако страница в браузере прежняя - без учета изменений. replaceChild дает тот же результат. Ставлю эксперимент - просто хочу удалить скрипт с главной страницы: node=content.document.getElementsByTagName("script ")[0]; node.parentNode.removeChild(node); Инспектор DOM показывает дерево уже без скрипта, но в браузере страница прежняя - со скриптом. Нашел, что якобы для возможности модификации основного документа в XUL файле (где находится скрипт расширения) должен быть тэг <browser type="content-primary"/> Вставил. Все без изменений. Получается, что все изменения отображаются только в дереве DOM и никак не затрагивают самого, загруженного в браузер, документа. Но изменить-то нужно именно его. А как? Чего не хватает? (То, что ума не хватает, то понятно). Чего не хватает в хромовом скрипте. Или в XUL файле. Может защиту какую-то снять надо с основного документа или дать ксуловскому скрипту какие-то привилегии? |
Vladimir,
Давайте немного разберёмся. Во-первых, все изменения и, собственно, текущее состояние документа отражено только в DOM. Значит, удалив <script> из DOM он удалится из текущего открытого документа. Вполне ожидаемо, что если вы посмотрите html код этого документа он будет первоначальный. Т.к. все изменения происходят только с текущим экземпляром, а не его "исходным" файлом. Хотя думаю вопрос не в этом. Во-вторых, удалив <script> мы не удаляем уже выполнившийся в нём код, так что если в нем была объявлена какая-то функция, она будет работать, даже после удаления этого элемента со страницы. И в третьих, если я не ошибаюсь, если вставить в DOM элемент <script>, содержащий javascript-код, этот код всё равно не будет выполнен. Этим способом можно только прикрепить <script> с определённым src, но не переписать уже загруженный код, а для выполнения кода есть функция eval(). Попробуйте подробнее описать задачу, которая перед вам стоит, наверно ответ тогда будет найден быстрее. Как я понимаю, вам надо переделать загруженный в страницу код, что-бы он выполнялся вместо уже загруженного кода? Тогда вы можете переопределить его, выполнив изменённый через eval() - все функции переопределятся и при их вызове будет выполнятся уже изменённый код. |
Полное описание задачи.
Есть такая страница которая грузится в FF с какого-то сайта. <html> <head> <title>Test page 1</title> <script> function hiName() { alert("Hi Nickolay!"); } </script> </head> <body onLoad="hiName()"> <p>This is the body text. </body> </html> Задача: Средствами браузера изменить содержимое скрипта таким образом, чтобы после загрузки страницы в окне alert функцией "hiName()" был выведен текст "Hi Vladimir!", а не "Hi Nickolay!". Очевидно, что заменить "Nikolay" на "Vladimir" нужно после окончания загрузки страницы в браузер, но перед тем как будет выполнена функция "hiName()" по событию "onLoad" тэга "body". Пытаемся решить эту задачу с помощью небольшого расширения к FF. Гвоздем расширения является файл sample.xul в котором находится скрипт расширения. <?xml version="1.0"?> <overlay id="sample" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <browser type="content-primary"/> <script type="application/x-javascript"> <![CDATA[ function repl() { var s=content.document.getElementsByTagName("script"); for (i=0;i<s.length;++i) { node=s[i]; if (node.text) { t=node.text; e=t.indexOf('Nikolay'); if (e > 0) { z=t.replace('Nikolay','Vladimir'); node.text=z; } } } } window.addEventListener("load", repl, true); ]]> </script> <statusbar id="status-bar"> <statusbarpanel id="my-panel" label="Sample extension work."/> </statusbar> </overlay> В результате текст скрипта в дереве DOM содержит "Vladimir", но все равно в главной странице работает скрипт с "Nickolay". Строки ex="<script language=javascript1.2>"+z+"hiName()</script>"; eval(ex); вставленные после строки node.text=z; нечего не изменили. Метод "replaceChild" вместо "node.text=z" дает тот же результат. Вроде как все заколдованное. Как расколдовать и заставить его делать то, что нужно? |
Vladimir,
Получается, что ваша основная задача не в том, чтобы заменить скрипт на изменённый, а опередить событие document.body.onLoad(), которое срабатывает до window.addEventListener("load", repl, true). Тут надо подумать. |
Я думаю, что событие document.body.onLoad() срабатывает после window.addEventListener("load", repl, true). Я так думаю потому, что если добавить в ксуловский скрипт после строки
node.text=z; строку alert('Ok.'); то "Ok" будет выведено до того, как появится "Hi Nickolay!". |
Часовой пояс GMT +3, время: 06:59. |