Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 22.05.2008, 04:53
Новичок на форуме
Отправить личное сообщение для Vladimir Посмотреть профиль Найти все сообщения от Vladimir
 
Регистрация: 22.05.2008
Сообщений: 8

Расширение к 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() получить текст первого скрипта в загруженном документе. Как построить строку обращения?

Помогите, плиз, кто в курсе.

Последний раз редактировалось Андрей Параничев, 06.01.2009 в 19:14. Причина: Пользуйтесь bb-тегами [js] и [html] для оформления листингов кода в теле сообщения
Ответить с цитированием
  #2 (permalink)  
Старый 22.05.2008, 11:47
Новичок на форуме
Отправить личное сообщение для Vladimir Посмотреть профиль Найти все сообщения от Vladimir
 
Регистрация: 22.05.2008
Сообщений: 8

Этот вопрос снимается. Строка обращения выглядит так
s=content.document.getElementsByTagName("script")[i].text;
и в переменной s содержимое скрипта.
Однако, теперь новая проблема.
Модифицируем s и присваиваем
content.document.getElementsByTagName("script")[i].text=s;

Инспектор DOM показывает измененный текст, однако в загруженной странице содержимое скрипта не изменилось и на выполнение запускается исходный вариант.

Как же заставить работать измененный скрипт?
Ответить с цитированием
  #3 (permalink)  
Старый 22.05.2008, 11:53
Профессор
Отправить личное сообщение для hogart Посмотреть профиль Найти все сообщения от hogart
 
Регистрация: 18.04.2008
Сообщений: 152

Vladimir, не знаток я ксула, но посоветую удалять первый скрипт и создавать вместо него новый.
Ответить с цитированием
  #4 (permalink)  
Старый 23.05.2008, 21:22
Новичок на форуме
Отправить личное сообщение для Vladimir Посмотреть профиль Найти все сообщения от Vladimir
 
Регистрация: 22.05.2008
Сообщений: 8

Спасибо. Однако, не могу найти подходящих методов для удаления старого и вставки нового скриптов. Поиски продолжаю, но может кто уже знает, подскажите, плиз.
Ответить с цитированием
  #5 (permalink)  
Старый 24.05.2008, 00:41
Отправить личное сообщение для Андрей Параничев Посмотреть профиль Найти все сообщения от Андрей Параничев
 
Регистрация: 21.02.2008
Сообщений: 1,250

Читайте туториалы 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, храните её в переменной.

Последний раз редактировалось Андрей Параничев, 24.05.2008 в 01:21.
Ответить с цитированием
  #6 (permalink)  
Старый 24.05.2008, 11:30
Новичок на форуме
Отправить личное сообщение для Vladimir Посмотреть профиль Найти все сообщения от Vladimir
 
Регистрация: 22.05.2008
Сообщений: 8

Спасибо за развернутый ответ. Я смотрел туториалы 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 файле.
Может защиту какую-то снять надо с основного документа или дать ксуловскому скрипту какие-то привилегии?
Ответить с цитированием
  #7 (permalink)  
Старый 24.05.2008, 15:34
Отправить личное сообщение для Андрей Параничев Посмотреть профиль Найти все сообщения от Андрей Параничев
 
Регистрация: 21.02.2008
Сообщений: 1,250

Vladimir,
Давайте немного разберёмся. Во-первых, все изменения и, собственно, текущее состояние документа отражено только в DOM. Значит, удалив <script> из DOM он удалится из текущего открытого документа. Вполне ожидаемо, что если вы посмотрите html код этого документа он будет первоначальный. Т.к. все изменения происходят только с текущим экземпляром, а не его "исходным" файлом. Хотя думаю вопрос не в этом. Во-вторых, удалив <script> мы не удаляем уже выполнившийся в нём код, так что если в нем была объявлена какая-то функция, она будет работать, даже после удаления этого элемента со страницы. И в третьих, если я не ошибаюсь, если вставить в DOM элемент <script>, содержащий javascript-код, этот код всё равно не будет выполнен. Этим способом можно только прикрепить <script> с определённым src, но не переписать уже загруженный код, а для выполнения кода есть функция eval().

Попробуйте подробнее описать задачу, которая перед вам стоит, наверно ответ тогда будет найден быстрее. Как я понимаю, вам надо переделать загруженный в страницу код, что-бы он выполнялся вместо уже загруженного кода? Тогда вы можете переопределить его, выполнив изменённый через eval() - все функции переопределятся и при их вызове будет выполнятся уже изменённый код.
Ответить с цитированием
  #8 (permalink)  
Старый 24.05.2008, 16:32
Новичок на форуме
Отправить личное сообщение для Vladimir Посмотреть профиль Найти все сообщения от Vladimir
 
Регистрация: 22.05.2008
Сообщений: 8

Полное описание задачи.
Есть такая страница которая грузится в 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" дает тот же результат.

Вроде как все заколдованное.
Как расколдовать и заставить его делать то, что нужно?
Ответить с цитированием
  #9 (permalink)  
Старый 24.05.2008, 16:40
Отправить личное сообщение для Андрей Параничев Посмотреть профиль Найти все сообщения от Андрей Параничев
 
Регистрация: 21.02.2008
Сообщений: 1,250

Vladimir,
Получается, что ваша основная задача не в том, чтобы заменить скрипт на изменённый, а опередить событие document.body.onLoad(), которое срабатывает до window.addEventListener("load", repl, true). Тут надо подумать.
Ответить с цитированием
  #10 (permalink)  
Старый 24.05.2008, 18:04
Новичок на форуме
Отправить личное сообщение для Vladimir Посмотреть профиль Найти все сообщения от Vladimir
 
Регистрация: 22.05.2008
Сообщений: 8

Я думаю, что событие document.body.onLoad() срабатывает после window.addEventListener("load", repl, true). Я так думаю потому, что если добавить в ксуловский скрипт после строки

node.text=z;

строку

alert('Ok.');

то "Ok" будет выведено до того, как появится "Hi Nickolay!".
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск