Динамический 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() Функция достаточна для того, чтобы браузер обращал внимание на вновь добавленную ссылку, в этом случае это может работать в общем случае, а не только для этого конкретного примера. С другой стороны, я не пробовал добавлять несколько links; Вполне возможно, что только одному из них одновременно можно "уделить внимание". В этом случае, тем не менее, есть способ, включающий последовательность функций, каждая из которых определяет добавление только одного 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);
}
Другие вопросы по тегам