0

这个问题与之前的帖子有关:检查用户是否使用位于中国的浏览器

我正在加载一个外部 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,可以看到库被成功加载。首先发生的是,我收到一条错误消息“参考错误:未定义用户信息”。我在我的 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()。同时,当我将行放回其原始位置时(例如在第一个代码片段中),它也可以识别该功能。这种行为不知何故让我想知道在加载 html 页面时如何在 head 标记中执行 javascript。是否有可能在加载库之前偶尔调用该方法?

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

Broser 控制台输出

查看我页面的源代码,我只看到正确加载的链接标签,但页面的其余部分丢失了。

在此处输入图像描述

所以这就是我的假设:

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

4

2 回答 2

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()函数可能足以触发浏览器关注新添加的链接,在这种情况下,这可能是通用的,而不仅仅是针对这个特定示例。另一方面,我没有尝试添加多个links; 有可能一次只能“关注”其中一个。但是,在这种情况下,仍然有一种方法,涉及一系列函数,每个函数都指定只linkhead. 在每个函数结束时,您将执行以下操作:

setTimeout('nextlinkfunc();', 200);  //give each function a different name!

当前link添加功能结束时,它会设置一个计时器,让浏览器有机会关注刚刚添加的link. 200 毫秒(1/5 秒)后,计时器触发指定的下一个函数——您可以在其中指定将另一个添加linkhead. 该函数的最后一件事将是另一个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);
}
于 2014-11-09T20:51:55.053 回答
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();">
于 2014-11-11T08:06:00.090 回答