Динамический HTML-тег ссылки с использованием внешней библиотеки JavaScript
Этот вопрос относится к предыдущему сообщению: проверьте, использует ли пользователь браузер, расположенный в Китае, или нет
Я загружаю внешнюю библиотеку js, чтобы оценить, какой CSS я хочу загрузить в свой заголовок. Следуя принятому ответу вышеупомянутого поста, я загружаю API userinfo.io в мою HTML-страницу, после чего оцениваю полученные данные. Вот что я сделал:
<head>
...
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/userinfo/1.0.0/userinfo.min.js"></script>
<script type="text/javascript">
UserInfo.getInfo(function(data) {
// the "data" object contains the info
if (data.country.code == 'CN') {
// Load fallback fonts
document.write('<link href="http://fonts.useso.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700" rel="stylesheet" type="text/css">');
} else {
// Load google fonts
document.write('<link href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700" rel="stylesheet" type="text/css">');
}
}, function(err) {
// the "err" object contains useful information in case of an error
});
</script>
</head>
Отлаживая js в Firefox, я вижу, что библиотека успешно загружается. Сначала случилось, что я получил сообщение об ошибке "Ссылочная ошибка: UserInfo не определено". Я немного поиграл с порядком строк в моей html-заголовке (есть еще несколько включений CSS, некоторые метатеги и, конечно же, заголовок). После сдачи
<head>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/userinfo/1.0.0/userinfo.min.js"></script>
...
<script type="text/javascript">
UserInfo.getInfo(function(data) {
// the "data" object contains the info
if (data.country.code == 'CN') {
// Load fallback fonts
document.write('<link href="http://fonts.useso.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700" rel="stylesheet" type="text/css">');
} else {
// Load google fonts
document.write('<link href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700" rel="stylesheet" type="text/css">');
}
}, function(err) {
// the "err" object contains useful information in case of an error
});
</script>
</head>
как первая строка внутри тега head, он начал фактически распознавать объект UserInfo
и его метод getInfo()
, Между тем он также распознает функцию, когда я возвращаю строку в исходное положение (например, в первом фрагменте кода). Такое поведение почему-то заставило меня задуматься о том, как выполняется javascript в теге head при загрузке html-страницы. Возможно ли, что время от времени вызывается метод перед загрузкой библиотеки?
В любом случае, теперь, когда он успешно импортирует библиотеку userinfo.io, сайт больше не загружается должным образом. Посмотрев на консоль браузера, я вижу:
Взглянув на исходный код моей страницы, я вижу только правильно загруженный тег ссылки, но остальная часть страницы отсутствует.
Итак, вот что я предполагаю:
Я могу как-то не использовать document.write()
в заголовке, потому что это мешает загрузке страницы. Скорее всего, я должен получить доступ и изменить тег ссылки с помощью getElementById()
после того, как страница успешно загружена. Так что я на самом деле вызову это, скажем, с помощью jQuery ready()
Функция, чтобы быть уверенным, что библиотека успешно загружена? Буду признателен за любые комментарии по поводу этих мыслей.
2 ответа
Хорошо, это работает отлично! Благодарю.
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/userinfo/1.0.0/userinfo.min.js"></script>
<script type="text/javascript">
UserInfo.getInfo(function(data) {
var elHead, elLink;
elLink = document.createElement('link');
elLink.rel = 'stylesheet';
elLink.type = 'text/css';
if (data.country.code == 'CN') {
elLink.href = 'http://fonts.useso.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700';
}else{
elLink.href = 'http://fonts.google.com/css?family=Source+Sans+Pro:200,400,700|Dancing+Script:400,700|PT+Serif|Open+Sans:400,300,700';
}
elHead = document.getElementsByTagName("head")[0];
elHead.appendChild(elLink);
}, function(err) {
});
</script>
...
<body onload="UserInfo.getInfo();">
document.write()
это очень опасная функция (для веб-страницы). Вы должны быть более конкретными о том, где вы хотите что-то написать (не весь документ!). Итак, в вашем HTML вы можете указать пустой div
заблокировать и назначить ему идентификатор:
<div id="writehere"></div>
Тогда в вашем JavaScript вы бы сделали что-то вроде этого:
var place; //global variable
и внутри некоторой функции инициализации страницы сделайте это:
place=document.getElementById("writehere");
и после этого вы можете делать все, что хотите, где угодно, например:
place.innerHTML += "Special output text<br />";
Вы даже можете переписать его (используйте "=" вместо "+=" при изменении innerHTML
).
Я признаюсь, что, возможно, я пропустил один из вопросов, о которых вы спрашивали в своем Вопросе. Теперь у меня складывается впечатление, что вы хотите указать, пока страница загружается, дополнительные материалы для загрузки страницы - и это не всегда будет один и тот же дополнительный материал. Я не уверен head
раздел является правильным местом, чтобы попытаться сделать это, потому что я не знаю, как заставить браузер обращать внимание на недавно добавленные link
предметы в head
раздел. Я знаю, что он может обратить внимание на НЕКОТОРЫЕ вещи, как в этом примере (который, в то время как код вызывается onload
событие, связанное с body
тег, помещает значок на вкладку браузера или в верхний левый угол окна браузера):
var hd, itm;
hd = document.getElementById('ID_of_Head');
itm = document.createElement('link');
itm.id = 'whatever';
itm.rel = 'shortcut icon';
itm.type = 'image/png';
itm.href = 'desired URL'; //OOPS; my comment below wrongly says 'src' property
hd.appendChild(itm);
//you can now re-use the 'itm' variable to specify another link, if you wish
Возможно, что appendChild()
Функция достаточна для того, чтобы браузер обращал внимание на вновь добавленную ссылку, в этом случае это может работать в общем случае, а не только для этого конкретного примера. С другой стороны, я не пробовал добавлять несколько link
s; Вполне возможно, что только одному из них одновременно можно "уделить внимание". В этом случае, тем не менее, есть способ, включающий последовательность функций, каждая из которых определяет добавление только одного link
к head
, В конце каждой функции вы должны сделать это:
setTimeout('nextlinkfunc();', 200); //give each function a different name!
Когда текущий link
- добавление функции завершается, она устанавливает таймер и дает браузеру возможность обратить внимание на только что добавленное link
, Через 200 миллисекунд (1/5 сек) таймер активирует указанную следующую функцию - где вы бы указали добавление еще одной link
к head
, Последняя функция этой функции будет другой setTimeOut()
в третью функцию, с ее собственным уникальным именем.... Разновидностью этого может быть более сложная одиночная функция, где параметр используется для указания того, какой "вызов" выполняется для функции (самый первый вызов функция должна указывать значение параметра 1
, конечно):
//Note need to declare the global 'hd' and 'itm' variables,
// and set the 'hd' variable, before calling this function the first time
function nextlinkfunc(p)
{ itm = document.createElement('link');
//more stuff as previously presented
switch(p++)
{ case 1: //Note each 'case' block could have extra 'conditional' code
itm.href = "URL_of_1st_link";
break;
case 2: //Conditional code can encompass many different combinations of URLs
itm.href = "URL_of_2nd_link";
break;
//etc
}
hd.appendChild(itm);
if(p<max_number_of_links_you_want_to_add)
setTimeout('nextlinkfunc('p');', 200);
}