AJAX-проблемы
Александр СкакуновОпубликовано 17.02.2006 в Статьи
Сегодня с моим напарником Никитой разбирались, как динамически подгружать инфу на страницу без использования ифрейма. “Конечно, AJAX!” – привычно скажут продвинутые девелоперы и стройными рядами уйдут курить кеды. Фикус в том, что если в динамически подгруженный и отображённый на странице хтмл случайно затешется скрипт на яваскрипте, то он не выполнится. Просто отобразится хтмл и всё. Пример для неверующих:
<div id="output"></div>
<script>
var name = 'output';
var the_div = document.getElementById(name);
if(null!=the_div)
the_div.innerHTML = '<em>some HTML with JavaScripts here
<script>alert(666)<\/script> another one <script xsrc=
"<a title="Linkification: http://ya.ru" class="linkification-ext" href="http://ya.ru/">http://ya.ru</a>"><\/script></em>';
else
alert('cannot find the <div>');
</script>
То бишь есть див, в который подгружается некий хтмл (динамику этой загрузки пока оставим в стороне). Выполнится имеющийся в этом куске хтмля яваскрипт? Фиг.
Что делать? Стали копать исходники, как-то ж люди это делают. Пошли на уважаемый мной сайт dklab.ru и стали рыть пример имеющегося там движка типа AJAX’a. Что выяснили:
- создаётся контейнер (див или спан);
- в него помещается хтмл с одним яваскриптом, причём перед тегом <script> должен быть какой-то текст, а то у ИЕ с этим проблемы;
- далее берётся первый элемент массива скриптов этого контейнера (об этом ниже);
- обновляется его сурс (свойство “src”), что является отмашкой для запуска этого кода.
Общий вывод: хочешь запустить такой яваскрипт – обнови его сурс.
Посему поэтому приведённый выше код должен быть исправлен так:
<div id="output"></div>
<script>
var name = 'output';
var the_div = document.getElementById(name);
if(null!=the_div)
{
the_div.innerHTML = '<em>some HTML with JavaScripts here
<script>alert(666)<\/script> another one <script xsrc=
"<a title="Linkification: http://ya.ru" class="linkification-ext" href="http://ya.ru/">http://ya.ru</a>"><\/script></em>';
<strong>run_js(name);</strong>
}
else
alert('cannot find the <div>');
</script>
обращаем внимание на выделенный кусок “run_js(name)”. Это специальная функция, которая пробегает по массиву всех имеющихся в указанном контейнере скриптов, благо такая функциональность предоставляется броузером, и обновляем его сурс. Но тут одна загвоздка: если указать тегу script сурс, то автоматически перестаёт работать содержимое тега, просто не запускается. Например:
<script xsrc="<em><a title="Linkification: http://someserver.ua/1.js" class="linkification-ext" href="http://someserver.ua/1.js">http://someserver.ua/1.js</a></em>">
alert(4444);
</script>
Это как в правилах дорожного движения – если есть светофор, то знаки приоритета теряют силу. Таким образом, алерт не запустится, а выполнится только указанный файл.
Теперь вернёмся к проблеме: как обновить сурс так, чтобы:
случай А) если его нет, то он и не появился,
случай Б) если он есть, то изменился так, чтобы указывал на тот же самый файл.
Ответ:
случай А) обновить пустой строкой,
случай Б) приписать ничего не значащий УРЛ-параметр, например, “?1=2″ или “&1=2″ в зависимости от наличия других параметров.
Так или иначе, вот код многострадальной функции для запуска *статичного* JavaScript:
<script>
function run_js(name)
{
var the_div = document.getElementById(name);
if(null!=the_div)
{
with(the_div)
{
var arr_scripts = the_div.getElementsByTagName("script");
for(i in arr_scripts)
{
var src = arr_scripts[i].src;
if(null!=src)
{
var has_question = (src.indexOf('?', 1)>0 ? true : false );
if(0==src.length)
arr_scripts[i].setAttribute('src', '');
else
arr_scripts[i].setAttribute('src',
arr_scripts[i].src + (has_question==true ? '&' : '?') + '1=1');
}
}
}
}
}
</script>
Понравилась статья? Подпишись на обновления по RSS/E-mail

(8 голосов, средний: 4 из 5)
Для таво, чтобы не приходилось курить кеды, нужно курить документацию
В харячо любимом усеми нами ИнтернетЭксплорере есть
специальный атрибут тега . DEFFER называется (за количество букв F не отвечаю). Так вот, если ейный указан, скрипты
сами (шайтан!) выполняются при загрузке.
Если же наш суперсайт ориентирован еще и на вражеские firefox и safari к примеру (для экзотики), то придется покурить
вот это. У вот этого есть замечательный параметр в одной из хвункций, зовется evalScripts. Или runScripts…
Но честно говоря, я тоже в отдельных случаях не избежал описанного в посте способа
Потомушто AJAX.
Ошибка в самом подходе.
Возвращать JavaScript в responseText – это изврат.
А почему нет? Получается, что парикмахерам нельзя стричься :]
Кроме того, я не всегда знаю, какого вида придёт хтмл – с яваскриптом либо без оного. Поделись, если знаешь другой подход акромя описанного да использования ифрейма.
XSLT, тебе поможет, ведь, все есть а вручную трансформировать то зачем?
(я тож когдато мучился, только не из javascript а из style)
Используйте DOM, не будет таких проблем. Сначала – createElement, потом ему запихать текст в innerHTML и сделать replaceChild для родителя. Работает во всех бравзерах.
2Zeke
Интересный подход, надо будет попробовать.
способ, предложенный Zeke отлично работает.
Метод Zeke не работает в Opera 9.10..
Решил мою проблему, благодарствую
Ребята, “курите” http://www.fullajax.ru – много проблем решено на автоматическом уровне…
- Корректная работа под основными браузерами (Internet Explorer, Firefox, Opera, Safari)
- Прямые ссылки на AJAX сгенерированные вебстраницы
- История для кнопок в браузере «Назад» и «Вперед»
- Корректная работа счетчиков
- Обновление баннеров с каждым обновлением информации
- Функция изменение TITLE
- Мультипоточность
- Полная поддержка GET и POST запросов
- Раздельная история для каждого потока загрузки веб-страниц
- Парсинг и выполнение скриптов, линков и стилей в контенте динамически подгружаемых веб-страниц
- Реализация связанного меню
- Используется различные уровни кеширования как HTML, так и скриптов.
- Возможность отключения переинициализации сриптовых функций (отключение повторного исполнения) – повышает производительность, экономит вычислительные ресурсы и оперативную память. Возможна тонкая натройка.
- Загрузка на сервер (upload) файлов без перезагрузки
- Авто-фильтр – ссылки по указанным критериям автоматически превращаются в AJAX
- Триггер контента
- Ускоритель загрузки скриптов – паралельная загрузка с последовательным примнением
- Препроцессорная обработка ответов сервера
- Корректная обработка document.write в динамически подгружаемых страницах
- Поддержка событий onload и onunload тега для каждого потока
- Поддержка отработки на локальной файловой системе
2 Zeke
Прошу объяснить подробнее. Заранее спасибо.
Работает в Mozilla/5.0 – Firefox/3.0
Но не работает в IE
alert
#div1{
HEIGHT: 100;
WIDTH: 100;
BACKGROUND-COLOR: #dfe6ef;
BORDER: #aca794 1px solid
}
#span1{
HEIGHT: 50;
WIDTH: 50;
BACKGROUND-COLOR: red;
BORDER: blue 1px solid
}
var param;
param=”1alert(’Im in Run’);”;
function run(p){
var NewDiv = document.createElement(”DIV”);
var OldDiv = document.getElementById(”div1″);
var OldParent = OldDiv.parentNode;
// Нак нельзя
//NewDiv.innerHTML = p;
// Только так
NewDiv.innerHTML = ”+p+”;
OldParent.replaceChild(NewDiv, OldDiv);
// тоже, но одной строкой
//document.getElementById(”div1″).innerHTML = p;
}
Old TEXT element DIV
alert(’param’)
Replace DIV
alert #div1{ HEIGHT: 100; WIDTH: 100; BACKGROUND-COLOR: #dfe6ef; BORDER: #aca794 1px solid } #span1{ HEIGHT: 50; WIDTH: 50; BACKGROUND-COLOR: red; BORDER: blue 1px solid } var param; param="1alert('Im in Run');"; function run(p){ var NewDiv = document.createElement("DIV"); var OldDiv = document.getElementById("div1"); var OldParent = OldDiv.parentNode; // Нак нельзя //NewDiv.innerHTML = p; // Только так NewDiv.innerHTML = ''+p+''; OldParent.replaceChild(NewDiv, OldDiv); // тоже, но одной строкой //document.getElementById("div1").innerHTML = p; } Old TEXT element DIV alert('param') Replace DIVМетод Zeke не работает в IE 6