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


Posted in Javascript onJanuary 17, 2014

要判断这个 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:
 *  https://3water.com * 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 3water.com 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。
好了,这次就说这么多了,希望对对大家的开发和学习有帮助!

Javascript 相关文章推荐
javascript获取select值的方法分析
Jul 02 Javascript
通过Jquery.cookie.js实现展示浏览网页的历史记录超管用
Oct 23 Javascript
JS如何生成一个不重复的ID的函数
Dec 25 Javascript
Ionic 2 实现列表滑动删除按钮的方法
Jan 22 Javascript
详解Javascript百度地图接口开发文档中的类和方法
Feb 07 Javascript
js中new一个对象的过程
Feb 20 Javascript
基于匀速运动的实例讲解(侧边栏,淡入淡出)
Oct 17 Javascript
JavaScript canvas实现围绕旋转动画
Nov 18 Javascript
详解vue axios用post提交的数据格式
Aug 07 Javascript
灵活使用console让js调试更简单的方法步骤
Apr 23 Javascript
vue里的data要用return返回的原因浅析
May 28 Javascript
vue+element实现图片上传及裁剪功能
Jun 29 Javascript
js使用eval解析json(js中使用json)
Jan 17 #Javascript
js window.open弹出新的网页窗口
Jan 16 #Javascript
jQuery$命名冲突怎么办如何解决
Jan 16 #Javascript
jQuery获得内容和属性示例代码
Jan 16 #Javascript
jQuery 追加元素的方法如append、prepend、before
Jan 16 #Javascript
jQuery 设置 CSS 属性示例介绍
Jan 16 #Javascript
jQuery 滑动方法slideDown向下滑动元素
Jan 16 #Javascript
You might like
一个ORACLE分页程序,挺实用的.
2006/10/09 PHP
PHP+MYSQL 出现乱码的解决方法
2008/08/08 PHP
php将字符串随机分割成不同长度数组的方法
2015/06/01 PHP
使用PHP编写发红包程序
2015/07/22 PHP
在Laravel5中正确设置文件权限的方法
2019/05/22 PHP
JavaScript入门教程(11) js事件处理
2009/01/31 Javascript
基于jquery的图片轮播 tab切换组件
2012/07/19 Javascript
JS将秒换成时分秒实现代码
2013/09/03 Javascript
js判读浏览器是否支持html5的canvas的代码
2013/11/18 Javascript
JS将所有对象s的属性复制给对象r(原生js+jquery)
2014/01/25 Javascript
jquery新的绑定事件机制on方法的使用方法
2014/04/15 Javascript
Javascript简单改变表单元素背景的方法
2015/07/15 Javascript
jQuery实现的无限级下拉菜单功能示例
2016/09/12 Javascript
js 点击a标签 获取a的自定义属性方法
2016/11/21 Javascript
Javascript实现信息滚动效果
2017/05/18 Javascript
微信小程序实现倒计时60s获取验证码
2020/04/17 Javascript
vue中引用阿里字体图标的方法
2018/02/10 Javascript
vue实现井字棋游戏
2020/09/29 Javascript
解决vue打包 npm run build-test突然不动了的问题
2020/11/13 Javascript
python通过get,post方式发送http请求和接收http响应的方法
2015/05/26 Python
python sys.argv[]用法实例详解
2018/05/25 Python
浅谈python下tiff图像的读取和保存方法
2018/12/04 Python
python贪吃蛇游戏代码
2020/04/18 Python
python处理DICOM并计算三维模型体积
2019/02/26 Python
python3.x提取中文的正则表达式示例代码
2019/07/23 Python
Python3如何对urllib和urllib2进行重构
2019/11/25 Python
Python 给下载文件显示进度条和下载时间的实现
2020/04/02 Python
Python使用多进程运行含有任意个参数的函数
2020/05/02 Python
Kipling澳洲官网:购买凯浦林包包
2020/12/17 全球购物
摩飞电器俄罗斯官方网站:Morphy Richards俄罗斯
2020/07/30 全球购物
公务员培训自我鉴定
2013/09/19 职场文书
党员创先争优承诺书
2014/03/26 职场文书
研究生考核个人自我鉴定
2014/03/27 职场文书
小学绿色学校申报材料
2014/08/23 职场文书
教师党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
使用canvas仿Echarts实现金字塔图的实例代码
2021/11/11 HTML / CSS