Pull to refresh

Простые вещи: Подгрузка через AJAX HTML-кода, содержащего JavaScript.

Reading time4 min
Views2.8K
При разработке CMS S.Builder наша команда активно использовала AJAX. Теперь вот решили поделиться накопленным опытом. Начнем с этого хабратопика.

Не буду здесь затрагивать различные фреймворки и библиотеки. Свой код всегда роднее. Для работы с AJAX-ом в S.Builder написана библиотека sbAJAX. Можете качать и пользоваться :). В этом файле есть функция sbEvalJS. Для тех, кто не знает, объясню. При подгрузке через AJAX и вставке на страницу HTML-кода, содержащего JavaScript, JavaScript выполняться не будет или полезут баги. Эта функция как раз решает поставленную задачу.

После загрузки, полученный код передается функции, она вырезает все что находится между тегами <script …> … </script> и, если это не вынесенный в файл JavaScript, прогоняет его через eval(), либо подгружает файл, содержащий JavaScript, и прогоняет через eval() полученный код. Все просто. Код функции приведен ниже:

  1. function sbExecScript(text)
  2. {
  3.    if (!text)
  4.       return;
  5.       
  6.    if (window.execScript)
  7.    {
  8.       window.execScript(text);
  9.    }
  10.    else
  11.    {
  12.       var script = document.createElement('script');
  13.       script.setAttribute('type', 'text/javascript');
  14.       script.setAttribute('language', 'JavaScript');
  15.       if (_isIE)
  16.          script.text = text;
  17.       else
  18.          script.appendChild( document.createTextNode( text ) );
  19.          
  20.       var head = document.getElementsByTagName("head")[0] || document.documentElement;
  21.       head.insertBefore( script, head.firstChild );
  22.       head.removeChild( script );
  23.    }
  24.    
  25.    return;
  26. }
  27.  
  28. var sbEvalJSSrcs = [];
  29. function sbEvalJS(s)
  30. {
  31.    var js_ScriptFragment = '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)';
  32.    var js_ScriptSrcFragment = '<script.+(src[ ]*=[ ]*\'(.*?)\'|src[ ]*=[ ]*"(.*?)").+';
  33.  
  34. var matchAll = new RegExp(js_ScriptFragment, 'img');
  35.   var matchOne = new RegExp(js_ScriptFragment, 'im');
  36.   var matchSrc = new RegExp(js_ScriptSrcFragment, 'im');
  37.  
  38.   var arr = s.match(matchAll) || [];
  39.   var JSCode = [];
  40.    
  41.    for (var i = 0; i < arr.length; i++)
  42.   {
  43.     var srcMt = arr[i].match(matchSrc);
  44.     if (srcMt)
  45.     {
  46.       if (srcMt.length > 3)
  47.          srcMt = srcMt[3];
  48.       else
  49.          srcMt = srcMt[2];
  50.       
  51.       if (srcMt != '')
  52.       {
  53.          var found = false;
  54.          for (var j = 0; j < sbEvalJSSrcs.length; j++)
  55.          {
  56.             if (sbEvalJSSrcs[j] == srcMt)
  57.             {
  58.                found = true;
  59.                break;
  60.             }
  61.          }
  62.          
  63.          if (found)
  64.             continue;
  65.             
  66.          sbEvalJSSrcs[sbEvalJSSrcs.length] = srcMt;
  67.          var res = sbLoadSync(srcMt);
  68.          if (res)
  69.             JSCode[JSCode.length] = res;
  70.       }
  71.     }
  72.  
  73.     var mtCode = arr[i].match(matchOne);
  74.     if (mtCode && mtCode[1] != '')
  75.       JSCode[JSCode.length] = mtCode[1];
  76.   }
  77.   
  78.   s = s.replace(matchAll, '');
  79.    
  80.   for(var i = 0; i < JSCode.length; i++)
  81.    sbExecScript(JSCode[i]);
  82.   
  83.   return s;
  84. }
  85.  
* This source code was highlighted with Source Code Highlighter.


Функция возвращает HTML-код без JavaScript, его и вставляем в нужное место страницы, чтобы избежать повторного выполнения скриптов под IE, например.

Если будете пользоваться нашей библиотекой, то Вам могут оказаться полезными следующие функции:
sbLoadSync(url) – синхронно подгружает содержимое указанного URL-а и возвращает его.

sbLoadAsync(url, pfunction) – асинхронно подгружает содержимое указанного URL-а и передает его как параметр в функцию pfunction.

sbSendForm(form) – синхронно отправляет данные формы POST-запросом и возвращает результат скрипта, прописанного в action формы.

sbSendFormAsync(form, pfunction) – асинхронно отправляет данные формы POST-запросом и передает результат скрипта, прописанного в action формы, как параметр в функцию pfunction.

Замечу, что у всех функций sbEvalJS вызывается сразу при получении ответа от сервера, а возвращаемый ими результат не содержит JavaScript. Если логику надо изменить, уберите везде return sbEvalJS(res);.

Библиотека тестировалась в IE 6, IE 7, FireFox 2, FireFox 3, Opera 9.5, Safari 3.0, Google Chrome 0.3.

Ну вот и все, для первого раза достаточно :).
Tags:
Hubs:
+2
Comments64

Articles