Украинское сообщество программистов

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. Что выяснили:

  1. создаётся контейнер (див или спан);
  2. в него помещается хтмл с одним яваскриптом, причём перед тегом <script> должен быть какой-то текст, а то у ИЕ с этим проблемы;
  3. далее берётся первый элемент массива скриптов этого контейнера (об этом ниже);
  4. обновляется его сурс (свойство “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>

Теги: ,

1 звезда2 звезды3 звезды4 звезды5 звезд (8 голосов, средний: 4 из 5)
Загрузка ... Загрузка ...
Распределение голосов

Понравилась статья? Подпишись на обновления по RSS/E-mail

Подписаться, не оставляя комментарий

Все комментарии (15) к “AJAX-проблемы” RSS

  1. Drobel

    Для таво, чтобы не приходилось курить кеды, нужно курить документацию :)
    В харячо любимом усеми нами ИнтернетЭксплорере есть
    специальный атрибут тега . DEFFER называется (за количество букв F не отвечаю). Так вот, если ейный указан, скрипты
    сами (шайтан!) выполняются при загрузке.

    Если же наш суперсайт ориентирован еще и на вражеские firefox и safari к примеру (для экзотики), то придется покурить
    вот это. У вот этого есть замечательный параметр в одной из хвункций, зовется evalScripts. Или runScripts…

    Но честно говоря, я тоже в отдельных случаях не избежал описанного в посте способа :( Потомушто AJAX.

  2. Mkdir

    Ошибка в самом подходе.
    Возвращать JavaScript в responseText – это изврат.

  3. Skakunov Alexander

    Возвращать JavaScript в responseText – это изврат

    А почему нет? Получается, что парикмахерам нельзя стричься :]
    Кроме того, я не всегда знаю, какого вида придёт хтмл – с яваскриптом либо без оного. Поделись, если знаешь другой подход акромя описанного да использования ифрейма.

  4. raibonsix

    XSLT, тебе поможет, ведь, все есть а вручную трансформировать то зачем?
    (я тож когдато мучился, только не из javascript а из style)

  5. Zeke

    Используйте DOM, не будет таких проблем. Сначала – createElement, потом ему запихать текст в innerHTML и сделать replaceChild для родителя. Работает во всех бравзерах.

  6. Skakunov Alexander

    2Zeke
    Интересный подход, надо будет попробовать.

  7. .cens

    способ, предложенный Zeke отлично работает.

  8. Dude

    Метод Zeke не работает в Opera 9.10..

  9. nino

    Решил мою проблему, благодарствую :)

  10. Alexx
  11. si-rus

    Ребята, “курите” http://www.fullajax.ru – много проблем решено на автоматическом уровне…

    - Корректная работа под основными браузерами (Internet Explorer, Firefox, Opera, Safari)
    - Прямые ссылки на AJAX сгенерированные вебстраницы
    - История для кнопок в браузере «Назад» и «Вперед»
    - Корректная работа счетчиков
    - Обновление баннеров с каждым обновлением информации
    - Функция изменение TITLE
    - Мультипоточность
    - Полная поддержка GET и POST запросов
    - Раздельная история для каждого потока загрузки веб-страниц
    - Парсинг и выполнение скриптов, линков и стилей в контенте динамически подгружаемых веб-страниц
    - Реализация связанного меню
    - Используется различные уровни кеширования как HTML, так и скриптов.
    - Возможность отключения переинициализации сриптовых функций (отключение повторного исполнения) – повышает производительность, экономит вычислительные ресурсы и оперативную память. Возможна тонкая натройка.
    - Загрузка на сервер (upload) файлов без перезагрузки
    - Авто-фильтр – ссылки по указанным критериям автоматически превращаются в AJAX
    - Триггер контента
    - Ускоритель загрузки скриптов – паралельная загрузка с последовательным примнением
    - Препроцессорная обработка ответов сервера
    - Корректная обработка document.write в динамически подгружаемых страницах
    - Поддержка событий onload и onunload тега для каждого потока
    - Поддержка отработки на локальной файловой системе

  12. yellowcat

    2 Zeke

    Прошу объяснить подробнее. Заранее спасибо.

  13. pgp

    Работает в 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

  14. pgp
    
    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
    
    
  15. pgp

    Метод Zeke не работает в IE 6

Оставить комментарий

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

Архив

Добавить статью

Станьте автором нашего сайта!

Какие материалы подходят для публикации? — Такие.

Присылайте статьи на editors@developers.org.ua.

Подробнее.

Популярные теги

Все теги

Комментарии

Последние комментарии

интернет магазин бытовая техника магазин Laptoper