Js判断CSS文件加载完毕的具体实现

要判断这个 CSS 文件是否加载完毕,各个浏览器的做法差异比较大,这次要说IE浏览器做的不错,我们可以直接通过onload方法来处理CSS加载完成以后的处理:


代码如下:

// 代码节选至seajs
function styleOnload(node, callback) {
    // for IE6-9 and Opera
    if (node.attachEvent) {
      node.attachEvent('onload', callback);
      // NOTICE:
      // 1. "onload" will be fired in IE6-9 when the file is 404, but in
      // this situation, Opera does nothing, so fallback to timeout.
      // 2. "onerror" doesn't fire in any browsers!
    }
}

很遗憾,这次在其他的浏览器中,想判断CSS是否加载完成就不是那么方便了,FF,webkit可以通过node.sheet.cssRules属性是否存在来判断是否加载完毕。而且需要使用setTimeout间隔事件轮询:


代码如下:

// 代码节选至seajs
function poll(node, callback) {
    if (callback.isCalled) {
      return;
    }
    var isLoaded = false;
    if (/webkit/i.test(navigator.userAgent)) {//webkit
      if (node['sheet']) {
        isLoaded = true;
      }
    }
    // for Firefox
    else if (node['sheet']) {
      try {
        if (node['sheet'].cssRules) {
          isLoaded = true;
        }
      } catch (ex) {
        // NS_ERROR_DOM_SECURITY_ERR
        if (ex.code === 1000) {
          isLoaded = true;
        }
      }
    }
    if (isLoaded) {
      // give time to render.
      setTimeout(function() {
        callback();
      }, 1);
    }
    else {
      setTimeout(function() {
        poll(node, callback);
      }, 1);
    }
  }

setTimeout(function() {
     poll(node, callback);
}, 0);

SeaJS给出的完整的处理是这样的:


代码如下:

function styleOnload(node, callback) {
    // for IE6-9 and Opera
    if (node.attachEvent) {
      node.attachEvent('onload', callback);
      // NOTICE:
      // 1. "onload" will be fired in IE6-9 when the file is 404, but in
      // this situation, Opera does nothing, so fallback to timeout.
      // 2. "onerror" doesn't fire in any browsers!
    }
    // polling for Firefox, Chrome, Safari
    else {
      setTimeout(function() {
        poll(node, callback);
      }, 0); // for cache
    }
  }
  function poll(node, callback) {
    if (callback.isCalled) {
      return;
    }
    var isLoaded = false;
    if (/webkit/i.test(navigator.userAgent)) {//webkit
      if (node['sheet']) {
        isLoaded = true;
      }
    }
    // for Firefox
    else if (node['sheet']) {
      try {
        if (node['sheet'].cssRules) {
          isLoaded = true;
        }
      } catch (ex) {
        // NS_ERROR_DOM_SECURITY_ERR
        if (ex.code === 1000) {
          isLoaded = true;
        }
      }
    }
    if (isLoaded) {
      // give time to render.
      setTimeout(function() {
        callback();
      }, 1);
    }
    else {
      setTimeout(function() {
        poll(node, callback);
      }, 1);
    }
  }
// 我的动态创建LINK函数
function createLink(cssURL,lnkId,charset,media){
    var head = document.getElementsByTagName('head')[0],
        linkTag = null;

if(!cssURL){
     return false;
 }

linkTag = document.createElement('link');
 linkTag.setAttribute('id',(lnkId || 'dynamic-style'));
 linkTag.setAttribute('rel','stylesheet');
 linkTag.setAttribute('charset',(charset || 'utf-8'));
 linkTag.setAttribute('media',(media||'all'));
 linkTag.setAttribute('type','text/css');
    linkTag.href = cssURL;

head.appendChild(linkTag);
}
function loadcss(){
    var styleNode = createLink('/wp-content/themes/BlueNight/style.css');

styleOnload(styleNode,function(){
        alert("loaded");
    });
}

在看到seajs的代码的时候,我立刻想起了我看到Diego Perini的另一个解决方案:


代码如下:

/*
 * Copyright (C) 2010 Diego Perini
 * All rights reserved.
 *
 * cssready.js - CSS loaded/ready state notification
 *
 * Author: Diego Perini <diego.perini at gmail com>
 * Version: 0.1
 * Created: 20100616
 * Release: 20101104
 *
 * License:
 *  http://www.jb51.net * Download:
 *  http://javascript.nwbox.com/cssready/cssready.js
 */
function cssReady(fn, link) {
  var d = document,
  t = d.createStyleSheet,
  r = t ? 'rules' : 'cssRules',
  s = t ? 'styleSheet' : 'sheet',
  l = d.getElementsByTagName('link');
  // passed link or last link node
  link || (link = l[l.length - 1]);
  function check() {
    try {
      return link && link[s] && link[s][r] && link[s][r][0];
    } catch(e) {
      return false;
    }
  }
  (function poll() {
    check() && setTimeout(fn, 0) || setTimeout(poll, 100);
  })();
}

其实,如果你读过jQuery的domready事件的判断的代码,原理也类似。也是通过setTimeout轮询的方式来判断DOM节点是否加载完毕。
还有,Fackbook则是通过在动态创建的CSS样式中包含一个固定的样式,例如#loadcssdom,loadcssdom就是一个高度为1px样式。然后动态创建一个DOM对象,添加这个loadcssdom样式。然后也是setTimeout轮询loadcssdo是否已经有1px的高度了。这个处理方式的解决方案,大家可以下《CSSP: Loading CSS with Javascript – and getting an onload callback.》
而《JavaScript Patterns》的作者Stoyan则在他的博客里,比较详细的说明了《When is a stylesheet really loaded?》。
看完了这些,你可能会感叹:汗,判断CSS是否加载完毕,目前还真不是那么容易!其实我这里算是一个抛砖引玉,因为开发中,除了动态加载CSS,我们还要动态加载JavaScript,动态加载HTML的操作,有空我也会写关于动态加载JavaScript的相关内容,不过在那之前,我建议你看看这些:
    《ensure – Ensure JavaScripts/HTML/CSS are loaded on-demand when needed》,这个库是专门处理动态加载HTML,CSS,JavaScript的。就像作者介绍的那样:
        ensure is a tiny JavaScript library that provides a handy function ensure which allows you to load JavaScript, HTML, CSS on-demand, and then execute your code. ensure www.jb51.net ensures that the relevant JavaScript and HTML snippets are already in the browser DOM before executing your code that uses them.
    《Tell CSS that JavaScript is available ASAP》
    看完这个后,你可能就不会纠结:When you're styling parts of a web page that will look and work differently depending on whether JavaScript is available or not。
好了,这次就说这么多了,希望对对大家的开发和学习有帮助!

(0)

相关推荐

  • 如何实现JavaScript动态加载CSS和JS文件

    项目中需要用到动态加载CSS 文件,整理了一下,顺便融合了动态加载JS 的功能写成了一个对象,先上代码: var dynamicLoading = { css: function(path){ if(!path || path.length === 0){ throw new Error('argument "path" is required !'); } var head = document.getElementsByTagName('head')[0]; var link =

  • 使用javaScript动态加载Js文件和Css文件

    JS动态加载CSS 在可换主题的界面中具有很重要的意义,用户可以根据自己的浏览习惯选择自己喜欢的页面显示方式,下面详细说明. 希望下面的方法对你有帮助. (1)使用JavaScript动态加载Js文件 /*JavaScript动态加载Js文件*/ var scriptNode = document.createElement('script'); scriptNode.src = 'proxy.js?t='+new Date().getTime();/*附带时间参数,防止缓存*/ documen

  • 常用js,css文件统一加载方法(推荐) 并在加载之后调用回调函数

    为了方便资源管理和提升工作效率,常用的js和css文件的加载应该放在一个统一文件里面完成,也方便后续的资源维护.所以我用js写了以下方法,存放在"sourceController.js"文件内. function sourceController(){ var root = ""; var cssCount = 0; // css加载计数器 var jsCount = 0; // js加载计数器 this.callfunc = null; // 回调函数 this.

  • 异步动态加载js与css文件的js代码

    jquery动态加载css,js文件方法简单很, 例 方法1: 代码如下 复制代码 代码如下: $.getscript("test.js"); 方法2: 代码如下 复制代码 代码如下: function loadjs(file){ var head = $('head').remove('#loadscript'); $("<scri"+"pt>"+"</scr"+"ipt>").a

  • Js判断CSS文件加载完毕的具体实现

    要判断这个 CSS 文件是否加载完毕,各个浏览器的做法差异比较大,这次要说IE浏览器做的不错,我们可以直接通过onload方法来处理CSS加载完成以后的处理: 复制代码 代码如下: // 代码节选至seajsfunction styleOnload(node, callback) {    // for IE6-9 and Opera    if (node.attachEvent) {      node.attachEvent('onload', callback);      // NOT

  • 详解axios中封装使用、拦截特定请求、判断所有请求加载完毕)

    •基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 Node.js 中使用 •vue2.0之后,就不再对 vue-resource 更新,而是推荐使用 axios,本项目也是使用 axios •功能特性 •在浏览器中发送 XMLHttpRequests 请求 •在 node.js 中发送 http请求 •支持 Promise API •拦截请求和响应 •转换请求和响应数据 •取消请求 •自动转换 JSON 数据 •客户端支持保护安全免受 CSRF/XSRF(跨站请求伪造) 攻击

  • JS判断图片是否加载完成方法汇总(最新版)

    有时需要获取图片的尺寸,这需要在图片加载完成以后才可以.下面小编给大家整理了几种关于JS判断图片是否加载完成方法汇总,一起看看吧. 一.load事件 <script type="text/javascript"> $('img').onload = function() { //code } </script> 优点:简单易用,不影响HTML代码. 缺点:只能指定一个元素,javascipt代码必须置于图片元素的下方 二.jquery方法 <script

  • 基于JS判断iframe是否加载成功的方法(多种浏览器)

    推荐阅读: JS iFrame加载慢怎么解决 在项目中经常要动态添加iframe,然后再对添加的iframe进行相关操作,而往往iframe还没添加完呢,后边的代码就已经执行完了,所以有些你写的东西根本没有显示出来.这时,我们就要考虑是否可以等iframe加载完后再执行后边的操作,当然,各种浏览器早就为我们考虑到啦,看下面: ie浏览器 IE的每个elem节点都会拥有一个onreadystatechange事件,这个事件每次在elem内容发送变化的时候触发,比如内容正在载入loading会触发,

  • js实现的页面加载完毕之前loading提示效果完整示例【附demo源码下载】

    本文实例讲述了js实现的页面加载完毕之前loading提示效果.分享给大家供大家参考,具体如下: 一.JS代码: //获取浏览器页面可见高度和宽度 var _PageHeight = document.documentElement.clientHeight, _PageWidth = document.documentElement.clientWidth; //计算loading框距离顶部和左部的距离(loading框的宽度为215px,高度为61px) var _LoadingTop =

  • JS判断iframe是否加载完成的方法

    本文实例讲述了JS判断iframe是否加载完成的方法.分享给大家供大家参考,具体如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content=&qu

  • JavaScript判断DOM何时加载完毕的技巧

    处理HTML DOM文档存在一个难题是,JavaScript可以在DOM完全加载之前执行,这会给你的代码引发不少的潜在问题.浏览器的渲染和操作顺序大致如下列表: HTML解析完毕 外部脚本和样式表加载完毕 脚本在文档内解析并执行 HTML DOM完全构造起来 图片和外部内容加载 网页完成加载 在网页头部并且从外部文件加载的脚本会在HTML真正构造之前执行.如前所述,这是个至关重要的问题,因为这两处执行的脚本并不能访问还不存在的DOM.幸好,我们还有若干的补救方法. 目前,最常用的级数是完全等待整

  • JavaScript & jQuery完美判断图片是否加载完毕

    众所周知,常见瀑布流当鼠标滚动到浏览器底部的时候,就会发起一个ajax的请求.在服务端生成item列表后,通过 js append到相应的div里边. 看起来很简单的样子,关键问题就出在图片的加载问题上,图片一般都放在服务器上,通过http下载到客户端. 例如我的图片地址: http://xxx.xxx.com/sc/item/cover/9-4352-c400.jpg 而图片下载到本地是需要一定时间的(网速快的路过).当图片还没有下载完的时候,使用js获取到元素的宽高将会是0. 有的同学说了我

  • js 判断图片是否加载完以及实现图片的预下载

    创建一个Image对象,实现图片的预下载,如果图片已经存在于浏览器缓存,直接调用回调函数,使用onload事件可以判断图片是否加载完成 function loadImage(url, callback) { var img = new Image(); //创建一个Image对象,实现图片的预下载 img.src = url; if(img.complete) { // 如果图片已经存在于浏览器缓存,直接调用回调函数 callback.call(img); return; // 直接返回,不用再

  • 关于JS判断图片是否加载完成且获取图片宽度的方法

    做web的同学们经常会碰到客户上传图片将网页内容区撑破了的情况,下面就这个问题我们一种如何使用js处理这个问题的方法,具体思路就是在js判断客户端的图片下载完毕之后适时的对该图片的宽度或者高度做一些处理,js处理图片主要是利用js中Image对象,通过 onload 事件和 onreadystatechange 来进行判断. (1)第一中方法,通过onload事件,比如: 复制代码 代码如下: <script type="text/javascript">var obj=n

随机推荐