вторник, 22 июня 2010 г.

Динамическая загрузка js

Я думаю многие сталкивались с задачей, когда надо динамически подгрузить js файл. Такая задача может возникнуть, например когда вы работаете с интернационализацией вашего сайта или функционал сайта может динамически меняться, в зависимости от каких-либо выбираемых параметров.  В данном посте я расскажу, как это делать.



Как всегда, начнем с того что есть браузеры, а есть IE. Да, я не люблю его, по той причине, что приходится всегда находить альтернативные и не всегда очевидные способы решения задач, которые в том же Хроме делаются на раз-два-три. Но вернемся к сути.

Итак, допустим есть скрипт 'dynamic.js' и если бы мы просто решили его вставить, то это выглядело бы вот так

<script type="text/javascript" src="dynamic.js"></script>

Но наша задаче - сделать все динамически - создадим тэг <script> и добавим его в <head>

var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'dynamic.js';
head.appendChild(script);


Проверено, что это работает в IE 5.0 и 7.0; Firefox 2.0; Safari 1.3; Opera 7.54 и 9.10; Konqueror 3.5; iCab 3.0.

Есть  еще один простой способ сделать то же самое. Изначально  создаем тэг <script>

<script id="loadarea" type="text/javascript"></script>


а потом в коде делаем следующий вызов


document.getElementById('loadarea').src= 'dynamic.js';


К сожалению, такой способ работает уже не везде. Он применим в Windows IE, Opera и iCab ,а вот в остальных браузерах уже как повезет.

Усложним нашу задачу - нужно вызвать какой-то метод из загруженного файла. Реализация будет выглядеть вот так

script.onreadystatechange= function () {
 if (this.readyState == 'complete') doSmth();
}
script.onload= doSmth;


Или если все вместе


var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';

script.onreadystatechange= function () {
 if (this.readyState == 'complete') doSmth();
}
script.onload= doSmth;
script.src= 'dynamic.js';
head.appendChild(script);


И вот тут уже есть немного магии. Вызов script.onload предназначен для не IE браузеров, так как согласно спецификациям работает onreadystatechange только в IE. Ложь и клевета - везде оно уже работает, другое дело, что могут readyState  различаться. Всего их 5 видов:


uninitialized
1loading
2loaded
3interactive
4complete


Но вот в разных браузерах возникают разные состояния. Например в том же хроме у меня стабильно возникал complete, а в IE он возник всего один раз, зато стабильно возникали loading и loaded. С учетом этого финальный код будет выглядеть вот так:


var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.onreadystatechange= function () {
if (this.readyState == 'complete' || this.readyState == 'loaded') doSmth();
}
script.onload= doSmth;
script.src= 'dynamic.js';
head.appendChild(script);


Есть и еще один способ - вместо указания урла скрипта, указать сам его код

var script = document.createElement('script');
var scr = 'alert("bah");';
var tag = document.createTextNode(scr);
script .appendChild(tag);
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);


Такой вариант у меня возник, когда я пытался сделать динамическую загрузку для Pocket IE 6.0. К сожалению ни один вариант в нем так и не заработал. Пришлось звать на помощь jsp и делать вот так:


<%
   String[] strings = request.getRequestURI().split("/");
   String scriptUrl = "/"+strings[1]+"/dynamic.js";
%>
<%="<SCRIPT TYPE=\"text/javascript\" charset=\"utf-8\" src=\""+scriptUrl+"\"></SCRIPT>"%>



Надеюсь, данный пост пригодится вам при решении подобной проблемы.

Related Posts by Categories



Комментариев нет:

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