如何检查是否已下载所有CSS文件以使用JavaScript插入HTML?

时间:2012-09-21 14:17:32

标签: javascript css ajax parallel-processing

我想通过JS动态插入一些HTML内容和一些CSS网址。

我有3个以上的CSS文件。我希望在我的内容插入页面之前下载它们。

有没有办法找出上述文件是否已下载?

这是它应该如何运作的:

  • 下载css文件;
  • 在下载完所有css文件后显示HTML;
  • 插入HTML后开始加载JS文件;
  • 在加载所有JS文件后触发回调;

10 个答案:

答案 0 :(得分:3)

  

来源: https://stackoverflow.com/a/3794242/1292652

使用AJAX

重新获取CSS文本

您可以使用AJAX函数创建动态CSS URL并将其作为纯文本格式获取,而不是使用凌乱的变通方法来确定已加载的CSS。

插入CSS

获取原始文本后,您可以使用此函数将CSS插入style标记并添加回调:

function loadCss(cssText, callback) {
    var style = document.createElement('style');
    style.type='text/css';
    if(callBack != undefined){
        style.onload = function() {
            callback();
        };
    }
    style.innerHTML = cssText;
    head.appendChild(style);
}

使用它

现在您可以将其用作:

loadCss(ajaxResponseText, function(){
    console.log("CSS loaded, you can show the dialog now :)");
})

允许跨域AJAX

在您的comment中,您提到必须加载jQueryjQueryUI我猜他们会在不同的域名上。

要解决AJAX跨域限制问题,请查看this linkthis one或此library

答案 1 :(得分:3)

您可以使用YepNope.js,YepNope允许您构建异步条件测试以查看资源是否已加载。一旦你的测试通过,你可以告诉它注入新的CSS或JS文件。

以下示例取自YepNope.js网站。

yepnope.injectCss( stylesheetSource [, callback ] [, elemAttributes ] [, timeout ]);

// Example
yepnope.injectCss("print.css", function () {
  console.log("css injected!");
}, {
  media: "print"
}, 5000);

你甚至可以让YepNope首先加载初始CSS文件,然后一旦加载完毕,YepNope就可以触发回调来执行其他任务,例如加载更多的JS或CSS文件。

答案 2 :(得分:1)

<html>
<head>
   <!-- 
       Put your styles here.  Make sure the *last* CSS file has the following:
       body { display: block !important }

       This will allow the stylesheets to load while the body is hidden.  
       When the last stylesheet is loaded, the body will be visible.
   -->
</head>

<body style="display: none">
    <!-- Lots of HTML here -->

    <!-- 
        Put your script tags here.
        In the first script, I recommend binding to the window.load event...  
        which will be fired once all your scripts are done loading.
    -->
</body>
</html>

答案 3 :(得分:0)

我认为这有点像你想要的那样:

<html>
  <head>
    <!-- CSS Stuff goes here -->
    <!-- JS Stuff come right after -->
  </head>
  <body>
    <!-- HTML Stuff comes withing Body -->
  </body>
</html>

这将导致: -

  1. 要并行下载的所有CSS文件;
  2. 然后解析并显示HTML内容;
  3. 浏览器获取所有JS;
  4. JS是tun,它可以执行任何插入操作;
  5. 你的问题有点令人困惑,你能澄清一下吗?我不明白为什么你要求有这样的订单,你能说出全局吗? JS本来就是一种昙花一现的语言,看看是否所有内容都下载都很麻烦。这对你有意义和/或帮助你吗?

答案 4 :(得分:0)

我知道这不是一个漂亮的解决方案,但您可以使用AJAX获取CSS文件并将其内容添加到<style>,而不是将<link>插入DOM。 使用AJAX,您可以确定何时完全下载CSS并将整个内容添加到您的条款下的页面中。

答案 5 :(得分:0)

  

来源: https://stackoverflow.com/a/8122005/1292652

我不建议这样做,原因与您不应使用while循环来实现sleep()的原因相同,但如果必须,您可以尝试。

在链接的答案中,添加了参考样式。例如:#ensure-cssload-8473649 { display: none }。但是,由于您下载的文件不在您的控件中,因此您必须从工作表中选择一些样式进行检测。

cssLoad()功能是:

var onCssLoad = function (options, callback) {
    var body = $("body");
    var div = document.createElement(constants.TAG_DIV);
    for (var key in options) {
        if (options.hasOwnProperty(key)) {
            if (key.toLowerCase() === "css") {
                continue;
            }
            div[key] = options[key];
        }
    }

    var css = options.css;
    if (css) {
        body.appendChild(div);
        var handle = -1;
        handle = window.setInterval(function () {
            var match = true;
            for (var key in css) {
                if (css.hasOwnProperty(key)) {
                    match = match && utils.getStyle(div, key) === css[key];
                }
            }

            if (match === true) {
                window.clearTimeout(handle);
                body.removeChild(div);
                callback();
            }
        }, 100);
    }
}

您可以将其用作:

onCssLoad({
    "id": <insert element CSS applies to>,
     css: <insert sample CSS styles>
}, function () {
    console.log("CSS loaded, you can show the dialog now :)");
});

答案 6 :(得分:0)

为什么不在页面上添加元素并检查一些js应该具有的样式。如果它具有该样式,则该样式表可能已加载。

像这样:

if (document.getElementById("csspage-3-box").style.color === "#somethingUnique") {
    //it is loaded
}

您可以附加一些隐藏的div,其中每个样式表都有唯一的ID。如果他们有任何样式,那么你知道你想要的表被加载。这个操作很便宜。它确实添加了一些非语义div元素。话虽如此,我觉得每个人的DOM中至少有一个非语义元素。

只是一个建议,但3 css文件并不多。其他简单的解决方案包括:

A)你可以将它们缩小并缩小它们并立即交付它们 B)将它们扔到CDN(如aws s3 + cloudfront)上,这是非常便宜的并且它们将被并行加载。
C)正常加载它们。您也可以将它们放在子域中。

现在,除非我是你,否则我将我的CSS分成一堆文件。 3文件太少了。我将网格和每种元素类型分开。然后在每页(或页面组)的基础上重新组装它们。这允许您根据需要包含每个单独的部分。

毕竟,附加链接标记相当容易(只要你可以轻松获得它的路径)。我建议使用链接而不是样式标记,因为如果你去CDN路由或子域路由,如果尝试使用某些xhr抓取css文件的内容,则会出现跨域问题。

答案 7 :(得分:0)

在构建我们团队开发的应用程序时,可以有很多CSS&amp;脚本文件和HTML的头部最终看起来相当麻烦。我构建了一个小脚本,通过将它们作为数组传递给方法来加载所有文件。但是,我在自己的脚本文件中有loadCSS(),我只是通过HTML中的脚本标记调用并传入Array。代码采用单片格式,以便于查看。

window.onload = function() {//Use $(document).ready() if using jQuery

    var cssArray = ["Style01.css", "Style02.css", "Style03.css"];
    loadCSS(cssArray, function () {

        alert("Style sheets have been loaded.");    
    });
    //Note: You can do a similar process for the JS files.
    //Load HTML when CSS is finished - Shown below
    loadHTML(); 
}

function loadCSS(array, callback) {

var cssArray = array;

    for (var i = 0; i < cssArray.length; i++)
    {
        document.write("<link rel='stylesheet' type='text/css' href='styles/" + cssArray[i] + "' />");
        //console.log(cssArray[i] + " style sheet has been loaded.");

        //Detects when for loop is finished evaluating the Array
        if (i == cssArray.length - 1) {

            return callback();
        } 
    }

    //loadHTML() can also be invoked here to ensure CSS files have been loaded.
}

如果你试图动态构建一些HTML,那么你可以在加载CSS文件后尝试这样的东西。

function loadHTML() {

//Create Main Table
var mainTable = document.createElement("table");
mainTable.id = "mainTable";
mainTable.cellPadding = 0;
mainTable.cellSpacing = 0;
mainTable.border = 0;       

//Create Body
var mainBody = document.createElement("tbody");   

//Create Table Row
var mainTR = document.createElement("tr");
mainTR.style.height = "50px";
mainTR.className = ""; //Insert class from one of the style sheets

//Create Main Cell
var mainTD = document.createElement("td");
mainTD.id = "mainTD";
//mainTD.style.width = "";
mainTD.style.textAlign = "left";
mainTD.style.padding = "5px 10px 5px 10px";
mainTD.className = ""; //Insert class from one of the style sheets
mainTD.innerHTML = "Test Text";

mainTR.appendChild(mainTD); 
mainBody.appendChild(mainTR);
mainTable.appendChild(mainBody);     

document.body.appendChild(mainTable);               
}

如果您有任何疑问,请随时提出。虽然已经发布了一些很好的例子,但希望这会有所帮助。

答案 8 :(得分:0)

怎么样:

$(document).ready(function() {
    $("body").hide();
});

然后,在下载的css文件中:

body { diaplay:block; }

答案 9 :(得分:0)

使用loadCSS加载CSS。并且在onload方法内部放置了你想要在所有css加载后执行的代码。

var counter = 0;
function onload(){
   counter--;
    setTimeout(function(){ // insuring if loaded immediately 
        if(counter == 0){ 
       // your code  here //******** CODEREPLACE ************/
          alert('all css files loaded!');
         }
    });
}
function loadCSS(href){
    counter++;
    l  = document.createElement('link');
    l.href = href;
    l.onreadystatechange = function () { // For IE
          if (this.readyState == 'loaded'){
              onload.call( this );
           }
     };
    l.rel = 'stylesheet';
    l.type='text/css';
    l.onload = onload;
    document.getElementsByTagName('head')[0].appendChild(l);
}

loadCSS('http://www.google.co.in/search?q=load+css+files+dynamically&aq=f&oq=load+css+files+dynamically&sugexp=chrome,mod=1&sourceid=chrome&ie=UTF-8');