Подгрузка через AJAX HTML-кода, содержащего JavaScript
При разработке CMS S.Builder наша команда активно использовала AJAX. Теперь вот решили поделиться накопленным опытом. Начнем с этого хабратопика. Не буду здесь затрагивать различные фреймворки и библиотеки. Свой код всегда роднее. Для работы с AJAX-ом в S.Builder написана библиотека sbAJAX. Можете качать и пользоваться :). В этом файле есть функция sbEvalJS. Для тех, кто не знает, объясню. При подгрузке через AJAX и вставке на страницу HTML-кода, содержащего JavaScript, JavaScript выполняться не будет или полезут баги. Эта функция как раз решает поставленную задачу.
После загрузки, полученный код передается функции, она вырезает все что находится между тегами <script …> … </script>
и, если это не вынесенный в файл JavaScript, прогоняет его через eval(), либо подгружает файл, содержащий JavaScript, и прогоняет через eval() полученный код. Все просто. Код функции приведен ниже:
function sbExecScript(text)
{
if (!text)
return;
if (window.execScript)
{
window.execScript(text);
}
else
{
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('language', 'JavaScript');
if (_isIE)
script.text = text;
else
script.appendChild( document.createTextNode( text ) );
var head = document.getElementsByTagName("head")[0] || document.documentElement;
head.insertBefore( script, head.firstChild );
head.removeChild( script );
}
return;
}
var sbEvalJSSrcs = [];
function sbEvalJS(s)
{
var js_ScriptFragment = '(?:<script.*?>)((n|r|.)*?)(?:</script>)';
var js_ScriptSrcFragment = '<script.+(src[ ]*=[ ]*'(.*?)'|src[ ]*=[ ]*"(.*?)").+';
var matchAll = new RegExp(js_ScriptFragment, 'img');
var matchOne = new RegExp(js_ScriptFragment, 'im');
var matchSrc = new RegExp(js_ScriptSrcFragment, 'im');
var arr = s.match(matchAll) || [];
var JSCode = [];
for (var i = 0; i < arr.length; i++)
{
var srcMt = arr[i].match(matchSrc);
if (srcMt)
{
if (srcMt.length > 3)
srcMt = srcMt[3];
else
srcMt = srcMt[2];
if (srcMt != '')
{
var found = false;
for (var j = 0; j < sbEvalJSSrcs.length; j++)
{
if (sbEvalJSSrcs[j] == srcMt)
{
found = true;
break;
}
}
if (found)
continue;
sbEvalJSSrcs[sbEvalJSSrcs.length] = srcMt;
var res = sbLoadSync(srcMt);
if (res)
JSCode[JSCode.length] = res;
}
}
var mtCode = arr[i].match(matchOne);
if (mtCode && mtCode[1] != '')
JSCode[JSCode.length] = mtCode[1];
}
s = s.replace(matchAll, '');
for(var i = 0; i < JSCode.length; i++)
sbExecScript(JSCode[i]);
return s;
}
* 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.
Ну вот и все, для первого раза достаточно :).
Рекомендуем почитать