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 });