Дата и время публикации:
Статический и динамический импорт
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