Вместе с Ajax в интернет ворвалась асинхронность. Веб-мастреа посходили с ума и начали делать асинхронным все, что только можно. Так появились разные модификации Ajax, например Ajaj(JSON), Ajah(html). Но иногда требуется асинхронно подключить к странице новый файл JavaScript.
Действительно, это даст некоторый выигрыш. Допустим, в этом файле сосредоточены функции для работы с формой комментариев. Пишем простой обработчик нажатия по элементу form комментария. После клика, обработчик лезет на сервер и подгружает нужные фунции JavaScript. При этом, посетитель, не пожелавший комментировать страницу, будет избавлен от необходимости тратить лишний траффик на загрузку скриптов комментирования.
Можно, конечно, подгружать JS традиционным аяксом и полученный текст "оживлять" eval-ом, но это долго (из-за последнего) и некрасиво. Я предлагаю более простой, но не менее эффективный метод.
Итак, нам нужно подгрузить внешний файл JS, по какому-то событию, не прибегая к eval. Как вообще можно подгрузить файл JS в html-документ? Это делается при помощи такой конструкции:
<script src="file.js" type="text/javascript" rel="javascript" language="javascript"></script>
Здесь нужно обратить внимание на атрибут src, который указывает браузеру, что нужно бы скачать файлик с кодом JavaScript. Сразу скажем, что скачанный JS-файл, тут же выполняется браузером. То есть, мы можем сразу использовать находящийся в файле код.
Предлагаю генерировать эту конструкцию на лету и записывать туда, где ей самое место — в секцию head.
Создаем файлы:
test.html
1.js
В файле 1.js содержится всего-лишь это:
function fromOut() {
alert('I\'m from 2.js file!!!');
}
Будем вызывать эту функцию из html, чтобы проверить, подключился ли наш внешний файл.
Содрежимое файла test.html:
<html>
<head>
<title>Тестируем подгрузку JS</title>
<!--пишем свою кодировку-->
<meta http-eqiv="Content-type" content="text/html; charset=utf-8"/>
</head>
<body>
<h1 id="header">Тестируем подгрузку JavaScript</h1>
<!--Этот код обязательно должен стоять тут, а не выше h1,
потому что происходит захват DOM-элемента.
Нужно, чтобы он существовал.-->
<script type="text/javascript" language="javascript">
//Прилепляем обработчик клика к нашему заголовку
document.getElementById('header').onclick = function() {
//создаем DOM-элемент и задаем его параметры
var loadedJS = document.createElement('script');
loadedJS.src = "1.js";
loadedJS.type = "text/javascript";
loadedJS.language = "javascript";
//получаем элемент секции head
var head = document.getElementsByTagName('head')[0];
//alert(head.innerHTML);
//вставляем новый script в head
head.appendChild(loadedJS);
//alert(head.innerHTML);
//используем функцию из файла 1.js
fromOut();
}
</script>
</body>
</html>
Пробуем, тестируем — получаем результат. Можете раскомментировать алерты в коде, чтобы увидеть изменения, которые происходят в секции head.
Есть важная особенность: если мы тыкнем на заголовок снова, не перезагружая страницу, то в него будет снова дописан тег. И файл со скриптом будет снова подгружен. Естественно, нам этого не нужно. Неплохо было бы поставить какой-то ограничитель, который бы показывал: загружали ли мы уже этот файл или нет.
Я вижу три решения: либо сделать глобальную переменную (или поле глобально видимого объекта, что удобнее), которая бы выполняла роль флага. Либо каждый раз, перед загрузкой перебирать теги <script> в секции head, проверяя их src. Третий вариант, наверное, самый правильный. Нужно присвоить тегу script еще один атрибут — id. А потом, при запуске функции, нужно пытаться схватить этот элемент функцией getElementById. Если не получается, значит нужно этот элемент создать.
Показывать реализацию не буду — вредный. Но сделать это не сложно, попробуйте сами.
Кроме того, хотелось бы заметить, что на загрузку файла требуется время. Особенно, на медленном коннекте. Поэтому не спешите использовать функции из внешнего файла сразу, как только сгенерировали нужный тег и вставили его в документ. Перед использованием внешних функций, загруженных таким образом, нужно убедиться, что они существуют.
Во-первых, я прошу прощения за перерывы в постинге. У меня появилась гора оффлайновых дел, поэтому на блог времени почти не остается. Очень жаль, конечно, но я буду стараться. В любом случае, постараюсь писать хотя бы один пост в неделю.
Еще я активизировался на Яндексе. Там завелся у меня бложик мелкий. Туда буду писать всякий лытдыбр. Если кому-то интересно узнать что-то обо мне, а не о моей профессии, то милости прошу.