1 /**
  2  * @fileOverview script/css load across browser
  3  * @author yiminghe@gmail.com
  4  */
  5 (function (S) {
  6     if (typeof require !== 'undefined') {
  7         return;
  8     }
  9 
 10     var CSS_POLL_INTERVAL = 30,
 11         win = S.Env.host,
 12         utils = S.Loader.Utils,
 13         /**
 14          * central poll for link node
 15          */
 16             timer = 0,
 17 
 18         monitors = {
 19             /**
 20              * node.id:{callback:callback,node:node}
 21              */
 22         };
 23 
 24     function startCssTimer() {
 25         if (!timer) {
 26             // S.log("start css polling");
 27             cssPoll();
 28         }
 29     }
 30 
 31     // single thread is ok
 32     function cssPoll() {
 33         for (var url in monitors) {
 34             var callbackObj = monitors[url],
 35                 node = callbackObj.node,
 36                 exName,
 37                 loaded = 0;
 38             if (utils.isWebKit) {
 39                 if (node['sheet']) {
 40                     S.log("webkit loaded : " + url);
 41                     loaded = 1;
 42                 }
 43             } else if (node['sheet']) {
 44                 try {
 45                     var cssRules;
 46                     if (cssRules = node['sheet'].cssRules) {
 47                         S.log('firefox loaded : ' + url);
 48                         loaded = 1;
 49                     }
 50                 } catch (ex) {
 51                     exName = ex.name;
 52                     S.log('firefox getStyle : ' + exName + ' ' + ex.code + ' ' + url);
 53                     // http://www.w3.org/TR/dom/#dom-domexception-code
 54                     if (exName == 'SecurityError' ||
 55                         exName == 'NS_ERROR_DOM_SECURITY_ERR') {
 56                         S.log('firefox loaded : ' + url);
 57                         loaded = 1;
 58                     }
 59                 }
 60             }
 61 
 62             if (loaded) {
 63                 if (callbackObj.callback) {
 64                     callbackObj.callback.call(node);
 65                 }
 66                 delete monitors[url];
 67             }
 68         }
 69         if (S.isEmptyObject(monitors)) {
 70             timer = 0;
 71             // S.log("end css polling");
 72         } else {
 73             timer = setTimeout(cssPoll, CSS_POLL_INTERVAL);
 74         }
 75     }
 76 
 77     S.mix(utils, {
 78         /**
 79          * monitor css onload across browsers
 80          * 暂时不考虑如何判断失败,如 404 等
 81          * @see <pre>
 82          *  - firefox 不可行(结论4错误):
 83          *    - http://yearofmoo.com/2011/03/cross-browser-stylesheet-preloading/
 84          *  - 全浏览器兼容
 85          *    - http://lifesinger.org/lab/2011/load-js-css/css-preload.html
 86          *  - 其他
 87          *    - http://www.zachleat.com/web/load-css-dynamically/
 88          *  </pre>
 89          */
 90         styleOnLoad:win.attachEvent || utils.isPresto ?
 91             // ie/opera
 92             // try in opera
 93             // alert(win.attachEvent);
 94             // alert(!!win.attachEvent);
 95             function (node, callback) {
 96                 // whether to detach using function wrapper?
 97                 function t() {
 98                     node.detachEvent('onload', t);
 99                     S.log('ie/opera loaded : ' + node.href);
100                     callback.call(node);
101                 }
102 
103                 node.attachEvent('onload', t);
104             } :
105             // refer : http://lifesinger.org/lab/2011/load-js-css/css-preload.html
106             // 暂时不考虑如何判断失败,如 404 等
107             function (node, callback) {
108                 var href = node.href,
109                     arr;
110                 arr = monitors[href] = {};
111                 arr.node = node;
112                 arr.callback = callback;
113                 startCssTimer();
114             }
115     });
116 })(KISSY);