1 /**
  2  * @fileOverview script transport for kissy io
  3  * @description: modified version of S.getScript , add abort ability
  4  * @author  yiminghe@gmail.com
  5  */
  6 KISSY.add("ajax/ScriptTransport", function (S, io) {
  7 
  8     var win = S.Env.host,
  9         doc = win.document,
 10         OK_CODE = 200,
 11         ERROR_CODE = 500;
 12 
 13     io.setupConfig({
 14         accepts:{
 15             script:"text/javascript, " +
 16                 "application/javascript, " +
 17                 "application/ecmascript, " +
 18                 "application/x-ecmascript"
 19         },
 20 
 21         contents:{
 22             script:/javascript|ecmascript/
 23         },
 24         converters:{
 25             text:{
 26                 // 如果以 xhr+eval 需要下面的,
 27                 // 否则直接 script node 不需要,引擎自己执行了,
 28                 // 不需要手动 eval
 29                 script:function (text) {
 30                     S.globalEval(text);
 31                     return text;
 32                 }
 33             }
 34         }
 35     });
 36 
 37     function ScriptTransport(xhrObj) {
 38         // 优先使用 xhr+eval 来执行脚本, ie 下可以探测到(更多)失败状态
 39         if (!xhrObj.config.crossDomain) {
 40             return new (io.getTransport("*"))(xhrObj);
 41         }
 42         this.xhrObj = xhrObj;
 43         return 0;
 44     }
 45 
 46     S.augment(ScriptTransport, {
 47         send:function () {
 48             var self = this,
 49                 script,
 50                 xhrObj = this.xhrObj,
 51                 c = xhrObj.config,
 52                 head = doc['head'] ||
 53                     doc.getElementsByTagName("head")[0] ||
 54                     doc.documentElement;
 55             self.head = head;
 56             script = doc.createElement("script");
 57             self.script = script;
 58             script.async = "async";
 59 
 60             if (c['scriptCharset']) {
 61                 script.charset = c['scriptCharset'];
 62             }
 63 
 64             script.src = c.url;
 65 
 66             script.onerror =
 67                 script.onload =
 68                     script.onreadystatechange = function (e) {
 69                         e = e || win.event;
 70                         // firefox onerror 没有 type ?!
 71                         self._callback((e.type || "error").toLowerCase());
 72                     };
 73 
 74             head.insertBefore(script, head.firstChild);
 75         },
 76 
 77         _callback:function (event, abort) {
 78             var script = this.script,
 79                 xhrObj = this.xhrObj,
 80                 head = this.head;
 81 
 82             // 防止重复调用,成功后 abort
 83             if (!script) {
 84                 return;
 85             }
 86 
 87             if (
 88                 abort ||
 89                     !script.readyState ||
 90                     /loaded|complete/.test(script.readyState) ||
 91                     event == "error"
 92                 ) {
 93 
 94                 script['onerror'] = script.onload = script.onreadystatechange = null;
 95 
 96                 // Remove the script
 97                 if (head && script.parentNode) {
 98                     // ie 报错载入无效 js
 99                     // 怎么 abort ??
100                     // script.src = "#";
101                     head.removeChild(script);
102                 }
103 
104                 this.script = undefined;
105                 this.head = undefined;
106 
107                 // Callback if not abort
108                 if (!abort && event != "error") {
109                     xhrObj._xhrReady(OK_CODE, "success");
110                 }
111                 // 非 ie<9 可以判断出来
112                 else if (event == "error") {
113                     xhrObj._xhrReady(ERROR_CODE, "scripterror");
114                 }
115             }
116         },
117 
118         abort:function () {
119             this._callback(0, 1);
120         }
121     });
122 
123     io.setupTransport("script", ScriptTransport);
124 
125     return io;
126 
127 }, {
128     requires:['./base', './XhrTransport']
129 });