16 февраля 2006

Типа AJAX

Сегодня с моим напарником Никитой разбирались, как динамически подгружать инфу на страницу без использования ифрейма. "Конечно, AJAX!" - привычно скажут продвинутые девелоперы и стройными рядами уйдут курить кеды. Фикус в том, что если в динамически подгруженный и отображённый на странице хтмл случайно затешется скрипт на яваскрипте, то он не выполнится. Просто отобразится хтмл и всё. Пример для неверующих:

<div id="output"></div>
<script>
  var name = 'output';
  var the_div = document.getElementById(name);
  if(null!=the_div)
    the_div.innerHTML = 'some HTML with JavaScripts here
<script>alert(666)<\/script> another one <script src=
"http://ya.ru"><\/script>
';
  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 = 'some HTML with JavaScripts here
<script>alert(666)<\/script> another one <script src=
"http://ya.ru"><\/script>
';
    run_js(name);
  }
  else
    alert('cannot find the <div>');
</script>

Oбращаем внимание на выделенный кусок "run_js(name)". Это специальная функция, которая пробегает по массиву всех имеющихся в указанном контейнере скриптов, благо такая функциональность предоставляется броузером, и обновляет его сурс. Но тут одна загвоздка: если указать тегу script сурс, то автоматически перестаёт работать содержимое тега, просто не запускается. Например:

<script src="http://someserver.ua/1.js">
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>

2 комментов:

Анонимный комментирует...

IE живет, FF ноль эмоций...

Анонимный комментирует...

Присоединяюсь к предыдущему посту, для FF, Opera такое решение не сработало. Если есть какие соображения напишите.

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