使用外部JavaScript库的动态html链接标记

时间:2014-11-09 17:31:42

标签: javascript html css userinfo link-tag

此问题与之前的帖子有关:Check if user is using browser located in China or not

我正在加载外部js库来评估我要在头文件中加载哪个css。按照上面提到的帖子的接受答案,我在我的HTML头中加载userinfo.io API,然后评估收到的数据。这是我做的:

<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>

在Firefox中调试js,我可以看到库已成功加载。它首先发生了,我收到了一条错误消息&#34;参考错误:UserInfo未定义&#34;。我玩了一下我的html头中的行的顺序(还有一些css包括,一些meta标签和标题当然)。

之后
<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()。同时,当我将线路放回原来的位置时(例如在第一个代码片段中),它也会识别该功能。这种行为让我想知道在加载html页面时如何在head标签中执行javascript。有可能偶尔在>加载库之前调用方法吗?

无论如何,现在当它成功导入userinfo.io库时,该站点不再正常加载。看一下浏览器控制台,我看到了:

Broser console output

看一下我的页面的源代码,我只看到正确加载的链接标记,但页面的其余部分缺失。

enter image description here

以下是我的想法:

我可以以某种方式在head标记中不使用document.write(),因为它会干扰页面加载。在页面成功加载后,我更有可能通过getElementById()访问和修改链接标记。所以我实际上会触发这个,让我们说jQuery的ready()函数来确保库已成功加载?我很感激对这些想法的任何评论。

2 个答案:

答案 0 :(得分:2)

document.write()是一个非常危险的功能(对于网页)。你应该更具体地说明你想要写东西的地方(而不是整个文件!)。因此,在HTML中,您可以指定一个空的div块,并为其指定一个id:

<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;它可能一次只能“注意”它们中的一个。但是,在这种情况下,仍然有一种方法,涉及一系列函数,每个函数都指定只向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);
}

答案 1 :(得分:0)

好的,这很好用!感谢。

<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();">