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英文日期(有时间)选择器
May 02 Javascript
JCalendar 日历控件 v1.0 beta[兼容IE&amp;Firefox] 有文档和例子
May 30 Javascript
那些年,我还在学习jquery 学习笔记
Mar 05 Javascript
解析Javascript小括号“()”的多义性
Dec 03 Javascript
28个常用JavaScript方法集锦
Jan 14 Javascript
jquery实现顶部向右伸缩的导航区域代码
Sep 02 Javascript
jQuery实现选项卡切换效果简单演示
Dec 09 Javascript
JS三级可折叠菜单实现方法
Feb 29 Javascript
使用vue点击li,获取当前点击li父辈元素的属性值方法
Sep 12 Javascript
vue router的基本使用和配置教程
Nov 05 Javascript
Js数组扁平化实现方法代码总汇
Nov 11 Javascript
JS监听Esc 键触发事键
Apr 14 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
ajax+php打造进度条 readyState各状态
2010/03/20 PHP
php处理json时中文问题的解决方法
2011/04/12 PHP
禁止你的左键复制实用技巧
2013/01/04 Javascript
5秒后跳转到另一个页面的js代码
2013/10/12 Javascript
jQuery操作Select的Option上下移动及移除添加等等
2013/11/18 Javascript
javascript实现日期格式转换
2014/12/16 Javascript
javascript中动态函数用法实例分析
2015/05/14 Javascript
原生js实现节日时间倒计时功能
2017/01/18 Javascript
Vue组件tree实现树形菜单
2017/04/13 Javascript
JavaScript实现时间表动态效果
2017/07/15 Javascript
vue loadmore 组件滑动加载更多源码解析
2017/07/19 Javascript
Vue中的Vux配置指南
2017/12/08 Javascript
微信小程序实现image组件图片自适应宽度比例显示的方法
2018/01/16 Javascript
JS点击动态添加标签、删除指定标签的代码
2018/04/18 Javascript
官方推荐react-navigation的具体使用详解
2018/05/08 Javascript
Vue脚手架的简单使用实例
2018/07/10 Javascript
一文搞懂ES6中的Map和Set
2019/05/20 Javascript
pm2启动ssr失败的解决方法
2019/06/29 Javascript
JQuery表单元素取值赋值方法总结
2020/05/12 jQuery
Vue如何基于vue-i18n实现多国语言兼容
2020/07/17 Javascript
OpenCV HSV颜色识别及HSV基本颜色分量范围
2019/03/22 Python
python实现文件的备份流程详解
2019/06/18 Python
python实现比较类的两个instance(对象)是否相等的方法分析
2019/06/26 Python
Django logging配置及使用详解
2019/07/23 Python
Python编程快速上手——强口令检测算法案例分析
2020/02/29 Python
python安装cx_Oracle和wxPython的方法
2020/09/14 Python
Python识别验证码的实现示例
2020/09/30 Python
印度购物网站:TATA CLiQ
2017/11/23 全球购物
TripAdvisor日本:全球领先的旅游网站
2019/02/14 全球购物
内部类的定义、种类以及优点
2013/10/16 面试题
注册资产评估专业求职信
2014/07/16 职场文书
争先创优演讲稿
2014/09/15 职场文书
学校党委干部个人对照检查材料思想汇报
2014/10/09 职场文书
社区党建工作汇报材料
2014/10/27 职场文书
爱的承诺书
2015/01/20 职场文书
聊聊Python String型列表求最值的问题
2022/01/18 Python