Дата и время публикации:
Статический и динамический импорт
1. Что это такое
Динамическое добавление стилей каскадных таблиц CSS (далее по тексту – стили) в заголовок документа НTML позволяет подгружать нужные правила декорирования в начале использования формы управления.
Как показано в листинге 1.1, обычно стили, содержащиеся в отдельном файле с расширением .css, импортируются ("подключаются") в документ HTML один раз, когда он загружается, т.е. статически.
Листинг 1.1
. . . <head> . . . <link rel="stylesheet" type="text/css" href="mystyles.css" media="screen" /> . . . </head> . . .
Поэтому, когда браузер в ходе лексического разбора документа сталкивается на элемент с именем (тэгом) <link>, он производит загрузку файла с сервера по ссылке, заданной атрибутом href, а затем все остальное.
1 function absUrlGetFromLocalHref(href)
2 {
3 var slash = (href[0] == '/' ?'':'/');
4 return ( location ? location.host+splash+href :
5 (window.location ? window.location.host+splash+href :''));
6 }
В строке 3 вычисляем нужно ли подставлять "косой" слэш или нет. В строках 4-5 составляем абсолютный URL из имени хоста сервера, свойства location.host, из "косого" слэша и локального HREF, где находиться файл на сервере. При этом учитывается, что одним брузерам будет достаточно указать просто объект location, как показано в строке 4, а другие потребуют window.location, как в строке 5.
При этом, атрибут real="stylesheet", указывает на отношение подгружаемого контента в виде файла со стилями в текущем документе HTML, а необязательный атрибут type содержит "text/css".
2. Использование
Для организации горячего подключения файла со стилями,вернее динамического импорта, разделим действо на несколько частей:
– создание узла <link> с атрибутами (Листинг 2.2);
– определение объекта styleSheet и свойства СSSRule (Листинг 2.3);
– запуск проверки завершения импорта стилей (Листинг 2.4);
– вставка узла <link> в заголовок документа HTML (Листинг 2.5).
В строке 1-9 листинга 2.2 производим создание узла <link> в соответствии с форматом, приведенным в начале.
Листинг 2.2
1 function loadStyleSheet( myHref, fn, scope ) {
2 var head = document.getElementsByTagName( 'head' )[0], // ссылка на узел <head> и
3 link = document.createElement( 'link' ); // создание узла <head> с атрибутами
4 link.setAttribute( 'href',getAbsUrlsForMyHref(myHref)); // где искать файл каскадных
5 link.setAttribute( 'rel', 'stylesheet' ); // таблиц в формате заданным
6 link.setAttribute( 'type', 'text/css' ); // для их использования
7
В строках 8-15 листинга 2.3 определяем объект импорта стилей CSS из-за старых версий MSIE, которые до 9-ой версии MSIE использовали объект styleSheet и свойство rules, в то время как остальные браузеры используют для этого объект sheet и свойство cssRules.
Листинг 2.3
8 var sheet, cssRules;
9 if ( 'sheet' in link ) { // узнаем, есть ли объекты с именованным индексом 'sheet'.
10 sheet = 'sheet'; cssRules = 'cssRules'; // устанавливаем
11 }
12 else {
13 sheet = 'styleSheet'; cssRules = 'rules';
14 }
8 var sheet= link.sheet ? link.sheet : link.styleSheet; 9 var cssRules = sheet.cssRules ? sheet.cssRules : sheet.rules; 10 11 12 13 14
Как показано в листинге 2.4 проверка завершения импорта стилей в документ HTML запускается раньше чем она фактически состоится позднее в листинге 2.4. При этом, сама проверка заключается в том, что на протяжение 15 секунд с интервалом 10 миллисекунд ждем завершения импорта стилей CSS.
Листинг 2.4
17 var interval_id = setInterval( function() {
18 try {
19 if (link[sheet] && link[sheet][cssRules].length ) {
20 if (window.clearInerval) // дождались,
21 window.clearInerval(interval_id); // останавливаем
22 else // интервальный таймер
23 clearInerval(interval_id);
24 if(window.clearTimeout) // таймер однократного
25 clearTimeout(interval_id); // действия
26 else
27 clearTimeout(interval_id);
28 fn.call( scope || window, true, link ); // производим вызов функции
29 } // обратного вызова
30 }catch(e) { console.log(e.message); } finally{}
31 }, 10),
32 timeout_id = setTimeout( function() { // не дождались
33 if (window.clearInerval) // останавливаем
34 window.clearInerval(interval_id); // интервальный таймер
35 else
36 clearInerval(interval_id);
37 head.removeChild( link ); // удаляем узел <link>
38 fn.call( scope || window, false, link );
39 }, 15000 );
В строке 19 листинга 2.4 проверяется не только факт получения файла со стилями CSS, но и сам факт наличия в нем правил. Поэтому в случае, если по истечению 15 секунд импорт не состоялся, в строке 37 производится удаление узла <link>.
В строке 37 листинга 2.5 вставляем узел , тем самым инициируем загрузку файла стилей по указанной ссылке href, а в строке 38 возвращаем ссылку на созданный узел.
Листинг 2.5
40 head.appendChild( link ); 41 return link; 42 } 43
3. Пример использования
3.1 Приведен в листинге 3.1
Листинг 3.1
1 loadStyleSheet( '/path/to/my/stylesheet.css', function( success, link ) {
2 if ( success ) {
3 // код будет выполнен, если стили CSS были импортированы
4 }
5 else {
6 // код для выполнения, если они не были импортированы
7 }
8 } );
4.Библиография
1) 4 methods of adding CSS to HTML
2) Using window.location to Redirect to a Different URL with JavaScript
3) MDN.<link>
4) stylesheet.onload: or lack thereof
5) CSS file added dynamically is not loaded
6) Obj.location