google.loader代码分析
好久没有发布关于技术的文章了,我最近可能会陆续发布一些,我现在先发布一个简单的,供大家参考一下,该内容是Google Ajax之中的loader,用来动态加载Google Maps API,Google Search API等API文件,不过说实在话,在我对代码进行捷思完成之后,我觉得相当的失望,因为这段代码虽然在Google API之中承担着比较重要的内容,可是实际上我认为设计的不太合理,起码我觉得这个文件从代码上来看好像不支持在onload之后执行,这就使loader这个类的作用大打折扣,用户不直接在页面上调用maps api可能最大的原因是希望能够根据用户的需求选择性的调用,也就是说在需要的时候再调用,也就是类似51ditu maps api的这个功能:(异步加载地图文件),不过我看loader之中并没有实现该内容。
以上的想法都是个人意见,未必正确,希望大家指正,下面我贴出对该JavaScript文件的解释内容,供大家参考:
该文件的原文件内容可以在这个地址查看到。
以上的想法都是个人意见,未必正确,希望大家指正,下面我贴出对该JavaScript文件的解释内容,供大家参考:
1 //定义window.google命名空间
2 if (!window['google'])
3 {
4 window['google'] = {};
5 }
6 //定义window.google.loader命名空间
7 if (!window['google']['loader'])
8 {
9 window['google']['loader'] = {};
10 google.loader.ServiceBase = 'http://www.google.com/uds';//默认文件加载路径
11 google.loader.ApiKey = 'internal';//用户的key值,该值对所有的API产品都应该是一致的
12 google.loader.KeyVerified = true;//该值在其他的API产品之中通过这个值来判断是否需要验证key的有效性
13 google.loader.LoadFailure = false;//该值没有被调用,应该是提供给用户来调用的接口,判断loader是否失败
14 google.loader.AdditionalParams = '';//请求文件的附加参数
15 google.loader.OriginalAppPath = 'http://code.google.com/apis/ajax/documentation/example.html';//原始HTML文件地址
16 (
17 function()
18 {
19 //判断用户使用的浏览器是否是指定的浏览器
20 //参数a是浏览器名称,例如"msie"
21 function isBroswer(a)
22 {
23 if(a in isBroswerArray)
24 {
25 return isBroswerArray[a]
26 }
27 return isBroswerArray[a]=navigator.userAgent.toLowerCase().indexOf(a)!=-1
28 }
29 //isBroswerArray:本对象记录浏览器判断信息,可以认为是一个缓存
30 var isBroswerArray={};
31 function isIE()
32 {
33 return isBroswer("msie")
34 }
35 function isSafari()
36 {
37 return isBroswer("safari")||isBroswer("konqueror")
38 };
39 //继承,让b作为a的基类
40 function inherit(a,b)
41 {
42 var c=function(){};
43 c.prototype=b.prototype;
44 a.o=b.prototype;
45 a.prototype=new c
46 }
47 //预先定义好的API文件,如Maps API等
48 var preDefinedApis={};
49 //类文件加载完成后执行的指定函数句柄
50 var callbacks={};
51 //用户的key值,用来发送给服务器验证
52 var userKey=null;
53 //用来记录是否已经向服务器发送了key值如果发送过了,则不再发送
54 var userKeySent=false;
55 //使用该类来定义一个API文件,例如maps api的类文件
56 function ApiFile(fileName)
57 {
58 this.fileName=fileName
59 }
60 //获得API文件的路径URL,参数为版本号和版本选项
61 ApiFile.prototype.getLoadUrl=function(version,config)
62 {
63 var c="";
64 if(config!=undefined)
65 {
66 if(config["locale"]!=undefined)
67 {
68 c+="&hl="+encodeURIComponent(config["locale"])
69 }
70 if(config["nocss"]!=undefined)
71 {
72 c+="&output="+encodeURIComponent("nocss="+config["nocss"])
73 }
74 if(config["callback"]!=undefined)
75 {//注册在API文件加载完成之后执行的函数,只是我不太明白为什么这个字段要发送给服务端,莫非服务器返回的内容会自动添加相应的语句?
76 var d=setApiCallback(config["callback"],this.fileName);
77 c+="&callback="+encodeURIComponent(d)
78 }
79 if(config["other_params"]!=undefined)
80 {
81 c+="&"+config["other_params"]
82 }
83 }
84 if(userKey!=null&&!userKeySent)
85 {
86 c+="&key="+encodeURIComponent(userKey);
87 userKeySent=true
88 }
89 return google.loader.ServiceBase+"/?file="+this.fileName+"&v="+version+google.loader.AdditionalParams+c
90 };
91 ApiFile.prototype.canCallback=function(){return true};
92 function CustomApiFile(a,b,c,d,e,f,config)
93 {
94 this.fileName=a;
95 this.j=b;
96 this.i=c;
97 this.keyName=d;
98 this.versionName=e;
99 this._canCallback=f;
100 this.fileConfig=config||{}
101 }
102 inherit(CustomApiFile,ApiFile);
103 //获得API文件的路径URL,参数为版本号和版本选项
104 CustomApiFile.prototype.getLoadUrl=function(version,config)
105 {
106 var c="";
107 if(this.keyName!=undefined)//如果提供了发送用户key的参数名称,则使用该参数名称发送key值
108 {
109 c+="&"+this.keyName+"="+encodeURIComponent(userKey?userKey:google.loader.ApiKey)
110 }
111 if(this.versionName!=undefined)//如果提供了发送版本号的参数名称,则使用该参数名称发送版本号
112 {
113 c+="&"+this.versionName+"="+encodeURIComponent(version)
114 }
115 if(config!=undefined&&this.fileConfig!=undefined)
116 {
117 for(var d in config)
118 {
119 if(this.fileConfig[":"+d]!=undefined)
120 {
121 var e;
122 if(d=="callback")
123 {
124 e=setApiCallback(config[d],this.fileName)
125 }
126 else
127 {
128 e=config[d]
129 }
130 var f=this.fileConfig[":"+d];
131 if(typeof f=="string")
132 {
133 c+="&"+f+"="+encodeURIComponent(e)
134 }
135 else
136 {
137 c+="&"+f(e)
138 }
139 }
140 else if(d=="other_params")
141 {
142 c+="&"+config[d]
143 }
144 }
145 }
146 google[this.fileName]={};//设置命名空间
147 if(!this.i&&c!="")
148 {
149 c="?"+c.substring(1)
150 }
151 recordStat("el",this.fileName);
152 return this.j+c
153 };
154 CustomApiFile.prototype.canCallback=function()
155 {
156 return this._canCallback
157 };
158 //提供的loader方法
159 function load(apiName,version,config)
160 {
161 var api=preDefinedApis[":"+apiName];
162 if(!api)
163 {
164 throw getError("Module: '"+apiName+"' not found!");
165 }
166 else
167 {
168 //判断是否需要在加载完成之后调用回调函数,如果需要,则只能使用DOM方式加载,而不能使用document.write方式
169 //google目前不支持在document.write的形式上使用回调函数
170 var needCallback=config&&config["callback"]!=null;
171 if(needCallback&&!api.canCallback())
172 {
173 throw getError("Module: '"+apiName+"' must be loaded before DOM onLoad!");
174 }
175 else if(needCallback)
176 {
177 if(callbacks[apiName])//如果已经定义了该API的回调函数数组,则添加到该数组,这种情况下,该API已经在加载过程之中,不需要重新加载
178 {
179 callbacks[apiName].actualCallbacks.push(config["callback"])
180 }
181 else if(google[apiName])//如果该API已经存在(下载完成),则直接调用回调函数
182 {
183 setTimeout(config["callback"],0)
184 }
185 else
186 {
187 writeLoadTag("script",api.getLoadUrl(version,config),needCallback)//调用加载进程
188 }
189 }
190 else
191 {
192 writeLoadTag("script",api.getLoadUrl(version,config),needCallback)//调用加载进程
193 }
194 }
195 }
196 //返回一个Error对象
197 function getError(str)
198 {
199 var b=new Error(str);
200 b.toString=function()
201 {
202 return this.message
203 };
204 return b
205 }
206 //设置页面加载完成之后执行的函数,b参数我没有见到调用
207 function setOnLoadCallback(a,b)
208 {
209 if(b)
210 {
211 addOnloadListener(a)
212 }
213 else
214 {
215 addDomListener(window,"load",a)
216 }
217 }
218 //添加一个DOM事件监视器
219 function addDomListener(node,eventName,handle)
220 {
221 if(node.addEventListener)
222 {
223 node.addEventListener(eventName,handle,false)
224 }
225 else if(node.attachEvent)
226 {
227 node.attachEvent("on"+eventName,handle)
228 }
229 else
230 {
231 var d=node["on"+eventName];
232 if(d!=null)
233 {
234 node["on"+eventName]=getRunAllListener([handle,d])
235 }
236 node["on"+eventName]=handle
237 }
238 }
239 //返回运行数组之中每一个函数的句柄
240 function getRunAllListener(a)
241 {
242 return function()
243 {
244 for(var b=0;b<a.length;b++)
245 {
246 a[b]()
247 }
248 }
249 }
250 //保存在页面加载完成时执行函数的的数组
251 var onloadListeners=[];
252 function addOnloadListener(a)
253 {
254 if(onloadListeners.length==0)//如果没有设置全局的onload事件监视器,则添加
255 {
256 addDomListener(window,"load",runOnloadListeners);
257 if(!isIE()&&!isSafari()&&isBroswer("mozilla")||window.opera)//如果是opera浏览器
258 {
259 window.addEventListener("DOMContentLoaded",runOnloadListeners,false)
260 }
261 else if(isIE())
262 {
263 setTimeout(checkIELoaded,10)//每隔0.01秒检查页面是否加载完成
264 }
265 else if(isSafari())
266 {
267 setTimeout(checkSafariLoaded,10)//每隔0.01秒检查页面是否加载完成
268 }
269 }
270 onloadListeners.push(a)
271 }
272 //在IE之中检查页面是否加载完成,如果加载完成,则执行所有的onload句柄
273 function checkIELoaded()
274 {
275 try
276 {
277 if(onloadListeners.length>0)
278 {
279 document.firstChild.doScroll("left");
280 runOnloadListeners()
281 }
282 }
283 catch(a)
284 {
285 setTimeout(checkIELoaded,10)
286 }
287 }
288 //在Safari之中检查页面是否加载完成,如果加载完成,则执行所有的onload句柄
289 var safariLoadedState={loaded:true,complete:true};//指定加载完成后的readyState状态
290 function checkSafariLoaded()
291 {
292 if(safariLoadedState[document.readyState])
293 {
294 runOnloadListeners()
295 }
296 else if(onloadListeners>0)
297 {
298 setTimeout(checkSafariLoaded,10)
299 }
300 }
301 //运行所有的onload事件句柄并清空onloadListeners函数
302 function runOnloadListeners()
303 {
304 for(var a=0;a<onloadListeners.length;a++)
305 {
306 onloadListeners[a]()
307 }
308 onloadListeners.length=0
309 }
310 //该函数没有在本API之中调用,大体意思应该是在URI之中解析出用户所使用的key
311 function setApiKeyLookupMap(a)
312 {
313 var b=window.location.href;
314 var c;
315 var d=b.length;
316 for(var e in a)
317 {
318 var f=b.indexOf(e);
319 if(f!=-1&&f<d)
320 {
321 c=e;
322 d=f
323 }
324 }
325 userKey=c?a[c]:null
326 }
327 //通过DOM方式加载内容
328 function writeLoadTag(type,url,needCallback)
329 {
330 if(needCallback)//通过DOM方式调用内容
331 {
332 var d;
333 if(type=="script")
334 {
335 d=document.createElement("script");
336 d.type="text/javascript";
337 d.src=url
338 }
339 else if(type=="css")
340 {
341 d=document.createElement("link");
342 d.type="text/css";
343 d.href=url;
344 d.rel="stylesheet"
345 }
346 document.getElementsByTagName("head")[0].appendChild(d)
347 }
348 else//通过document.write方式调用内容
349 {
350 if(type=="script")
351 {
352 document.write('<script src="'+url+'" type="text/javascript"><\/script>')
353 }
354 else if(type=="css")
355 {
356 document.write('<link href="'+url+'" type="text/css" rel="stylesheet"></link>')
357 }
358 }
359 }
360 //设置API加载完成后的回调函数
361 function setApiCallback(handle,apiName)
362 {
363 callbacks[apiName]=function()
364 {
365 for(var c=0;c<callbacks[apiName].actualCallbacks.length;c++)
366 {
367 setTimeout(callbacks[apiName].actualCallbacks[c],0)//运行每一个回调函数
368 }
369 delete callbacks[apiName]
370 };
371 callbacks[b].actualCallbacks=[handle];
372 return "google.loader.callbacks."+apiName
373 }
374 //设置类到命名空间
375 //a是该类的命名空间路径
376 //b是该类的function
377 function exportSymbol(path,cla)
378 {
379 var c=path.split(/\./);
380 var d=window;
381 for(var e=0;e<c.length-1;e++)
382 {
383 if(!d[c[e]])
384 {
385 d[c[e]]={}
386 }
387 d=d[c[e]]
388 }
389 d[c[c.length-1]]=cla
390 }
391 exportSymbol("google.load",load);
392 exportSymbol("google.setOnLoadCallback",setOnLoadCallback);
393 exportSymbol("google.loader.writeLoadTag",writeLoadTag);
394 exportSymbol("google.loader.setApiKeyLookupMap",setApiKeyLookupMap);
395 exportSymbol("google.loader.callbacks",callbacks);
396 exportSymbol("google_exportSymbol",exportSymbol);
397 //log对象用来向服务器发送一些记录信息,将每次需要发送的消息保存起来,在达到5条或者页面卸载的时候通过访问服务器端img的形式发送
398 function log(){}
399 var unloadListenerAdded=log.unloadListenerAdded=false;//是否已经添加unload事件监视器
400 var maxRecordNumber=log.maxRecordNumber=5;
401 var records=log.records=[];
402 //添加unload事件监视器
403 var addUnloadListener=log.addUnloadListener=function()
404 {
405 if(!unloadListenerAdded)//只有在没有添加的情况下才添加
406 {
407 addDomListener(window,"unload",sendRecords);
408 unloadListenerAdded=(log.unloadListenerAdded=true)
409 }
410 };
411 //将r2=name,或r2=name=value格式的记录保存到数组
412 var recordStat=log.record=function(name,value)
413 {
414 addUnloadListener();
415 var c=name+(value?"="+value:"");
416 records.push("r"+records.length+"="+encodeURIComponent(c));
417 if(records.length>maxRecordNumber)
418 {
419 setTimeout(sendRecords,0)
420 }
421 };
422 //在页面被卸载的时候执行的操作
423 var sendRecords=log.sendRecords=function()
424 {
425 if(records.length)//如果存在记录
426 {
427 //通过创建Image对象来向服务器发送记录信息
428 var a=new Image;
429 a.src=google.loader.ServiceBase+"/stats?"+records.join("&")+"&nocache="+Number(new Date);
430 records.length=0//清空对象
431 }
432 };
433 exportSymbol("google.loader.recordStat",recordStat);
434 preDefinedApis[":search"]=new ApiFile("search");
435 preDefinedApis[":feeds"]=new ApiFile("feeds");
436 preDefinedApis[":language"]=new ApiFile("language");
437 preDefinedApis[":maps"]=new CustomApiFile("maps","http://maps.google.com/maps?file=googleapi",true,"key","v",true,{":locale":"hl",":callback":function(a){return"callback="+encodeURIComponent(a)+"&async=2"}});
438 preDefinedApis[":gdata"]=new CustomApiFile("gdata","http://gd.google.com/gd/api?file=gdata.js",true,"key","v",false);
439 preDefinedApis[":sharing"]=new CustomApiFile("sharing","http://www.google.com/s2/sharing/js",false,"key","v",false,{":locale":"hl"});
440 }
441 )()
442 }
443
2 if (!window['google'])
3 {
4 window['google'] = {};
5 }
6 //定义window.google.loader命名空间
7 if (!window['google']['loader'])
8 {
9 window['google']['loader'] = {};
10 google.loader.ServiceBase = 'http://www.google.com/uds';//默认文件加载路径
11 google.loader.ApiKey = 'internal';//用户的key值,该值对所有的API产品都应该是一致的
12 google.loader.KeyVerified = true;//该值在其他的API产品之中通过这个值来判断是否需要验证key的有效性
13 google.loader.LoadFailure = false;//该值没有被调用,应该是提供给用户来调用的接口,判断loader是否失败
14 google.loader.AdditionalParams = '';//请求文件的附加参数
15 google.loader.OriginalAppPath = 'http://code.google.com/apis/ajax/documentation/example.html';//原始HTML文件地址
16 (
17 function()
18 {
19 //判断用户使用的浏览器是否是指定的浏览器
20 //参数a是浏览器名称,例如"msie"
21 function isBroswer(a)
22 {
23 if(a in isBroswerArray)
24 {
25 return isBroswerArray[a]
26 }
27 return isBroswerArray[a]=navigator.userAgent.toLowerCase().indexOf(a)!=-1
28 }
29 //isBroswerArray:本对象记录浏览器判断信息,可以认为是一个缓存
30 var isBroswerArray={};
31 function isIE()
32 {
33 return isBroswer("msie")
34 }
35 function isSafari()
36 {
37 return isBroswer("safari")||isBroswer("konqueror")
38 };
39 //继承,让b作为a的基类
40 function inherit(a,b)
41 {
42 var c=function(){};
43 c.prototype=b.prototype;
44 a.o=b.prototype;
45 a.prototype=new c
46 }
47 //预先定义好的API文件,如Maps API等
48 var preDefinedApis={};
49 //类文件加载完成后执行的指定函数句柄
50 var callbacks={};
51 //用户的key值,用来发送给服务器验证
52 var userKey=null;
53 //用来记录是否已经向服务器发送了key值如果发送过了,则不再发送
54 var userKeySent=false;
55 //使用该类来定义一个API文件,例如maps api的类文件
56 function ApiFile(fileName)
57 {
58 this.fileName=fileName
59 }
60 //获得API文件的路径URL,参数为版本号和版本选项
61 ApiFile.prototype.getLoadUrl=function(version,config)
62 {
63 var c="";
64 if(config!=undefined)
65 {
66 if(config["locale"]!=undefined)
67 {
68 c+="&hl="+encodeURIComponent(config["locale"])
69 }
70 if(config["nocss"]!=undefined)
71 {
72 c+="&output="+encodeURIComponent("nocss="+config["nocss"])
73 }
74 if(config["callback"]!=undefined)
75 {//注册在API文件加载完成之后执行的函数,只是我不太明白为什么这个字段要发送给服务端,莫非服务器返回的内容会自动添加相应的语句?
76 var d=setApiCallback(config["callback"],this.fileName);
77 c+="&callback="+encodeURIComponent(d)
78 }
79 if(config["other_params"]!=undefined)
80 {
81 c+="&"+config["other_params"]
82 }
83 }
84 if(userKey!=null&&!userKeySent)
85 {
86 c+="&key="+encodeURIComponent(userKey);
87 userKeySent=true
88 }
89 return google.loader.ServiceBase+"/?file="+this.fileName+"&v="+version+google.loader.AdditionalParams+c
90 };
91 ApiFile.prototype.canCallback=function(){return true};
92 function CustomApiFile(a,b,c,d,e,f,config)
93 {
94 this.fileName=a;
95 this.j=b;
96 this.i=c;
97 this.keyName=d;
98 this.versionName=e;
99 this._canCallback=f;
100 this.fileConfig=config||{}
101 }
102 inherit(CustomApiFile,ApiFile);
103 //获得API文件的路径URL,参数为版本号和版本选项
104 CustomApiFile.prototype.getLoadUrl=function(version,config)
105 {
106 var c="";
107 if(this.keyName!=undefined)//如果提供了发送用户key的参数名称,则使用该参数名称发送key值
108 {
109 c+="&"+this.keyName+"="+encodeURIComponent(userKey?userKey:google.loader.ApiKey)
110 }
111 if(this.versionName!=undefined)//如果提供了发送版本号的参数名称,则使用该参数名称发送版本号
112 {
113 c+="&"+this.versionName+"="+encodeURIComponent(version)
114 }
115 if(config!=undefined&&this.fileConfig!=undefined)
116 {
117 for(var d in config)
118 {
119 if(this.fileConfig[":"+d]!=undefined)
120 {
121 var e;
122 if(d=="callback")
123 {
124 e=setApiCallback(config[d],this.fileName)
125 }
126 else
127 {
128 e=config[d]
129 }
130 var f=this.fileConfig[":"+d];
131 if(typeof f=="string")
132 {
133 c+="&"+f+"="+encodeURIComponent(e)
134 }
135 else
136 {
137 c+="&"+f(e)
138 }
139 }
140 else if(d=="other_params")
141 {
142 c+="&"+config[d]
143 }
144 }
145 }
146 google[this.fileName]={};//设置命名空间
147 if(!this.i&&c!="")
148 {
149 c="?"+c.substring(1)
150 }
151 recordStat("el",this.fileName);
152 return this.j+c
153 };
154 CustomApiFile.prototype.canCallback=function()
155 {
156 return this._canCallback
157 };
158 //提供的loader方法
159 function load(apiName,version,config)
160 {
161 var api=preDefinedApis[":"+apiName];
162 if(!api)
163 {
164 throw getError("Module: '"+apiName+"' not found!");
165 }
166 else
167 {
168 //判断是否需要在加载完成之后调用回调函数,如果需要,则只能使用DOM方式加载,而不能使用document.write方式
169 //google目前不支持在document.write的形式上使用回调函数
170 var needCallback=config&&config["callback"]!=null;
171 if(needCallback&&!api.canCallback())
172 {
173 throw getError("Module: '"+apiName+"' must be loaded before DOM onLoad!");
174 }
175 else if(needCallback)
176 {
177 if(callbacks[apiName])//如果已经定义了该API的回调函数数组,则添加到该数组,这种情况下,该API已经在加载过程之中,不需要重新加载
178 {
179 callbacks[apiName].actualCallbacks.push(config["callback"])
180 }
181 else if(google[apiName])//如果该API已经存在(下载完成),则直接调用回调函数
182 {
183 setTimeout(config["callback"],0)
184 }
185 else
186 {
187 writeLoadTag("script",api.getLoadUrl(version,config),needCallback)//调用加载进程
188 }
189 }
190 else
191 {
192 writeLoadTag("script",api.getLoadUrl(version,config),needCallback)//调用加载进程
193 }
194 }
195 }
196 //返回一个Error对象
197 function getError(str)
198 {
199 var b=new Error(str);
200 b.toString=function()
201 {
202 return this.message
203 };
204 return b
205 }
206 //设置页面加载完成之后执行的函数,b参数我没有见到调用
207 function setOnLoadCallback(a,b)
208 {
209 if(b)
210 {
211 addOnloadListener(a)
212 }
213 else
214 {
215 addDomListener(window,"load",a)
216 }
217 }
218 //添加一个DOM事件监视器
219 function addDomListener(node,eventName,handle)
220 {
221 if(node.addEventListener)
222 {
223 node.addEventListener(eventName,handle,false)
224 }
225 else if(node.attachEvent)
226 {
227 node.attachEvent("on"+eventName,handle)
228 }
229 else
230 {
231 var d=node["on"+eventName];
232 if(d!=null)
233 {
234 node["on"+eventName]=getRunAllListener([handle,d])
235 }
236 node["on"+eventName]=handle
237 }
238 }
239 //返回运行数组之中每一个函数的句柄
240 function getRunAllListener(a)
241 {
242 return function()
243 {
244 for(var b=0;b<a.length;b++)
245 {
246 a[b]()
247 }
248 }
249 }
250 //保存在页面加载完成时执行函数的的数组
251 var onloadListeners=[];
252 function addOnloadListener(a)
253 {
254 if(onloadListeners.length==0)//如果没有设置全局的onload事件监视器,则添加
255 {
256 addDomListener(window,"load",runOnloadListeners);
257 if(!isIE()&&!isSafari()&&isBroswer("mozilla")||window.opera)//如果是opera浏览器
258 {
259 window.addEventListener("DOMContentLoaded",runOnloadListeners,false)
260 }
261 else if(isIE())
262 {
263 setTimeout(checkIELoaded,10)//每隔0.01秒检查页面是否加载完成
264 }
265 else if(isSafari())
266 {
267 setTimeout(checkSafariLoaded,10)//每隔0.01秒检查页面是否加载完成
268 }
269 }
270 onloadListeners.push(a)
271 }
272 //在IE之中检查页面是否加载完成,如果加载完成,则执行所有的onload句柄
273 function checkIELoaded()
274 {
275 try
276 {
277 if(onloadListeners.length>0)
278 {
279 document.firstChild.doScroll("left");
280 runOnloadListeners()
281 }
282 }
283 catch(a)
284 {
285 setTimeout(checkIELoaded,10)
286 }
287 }
288 //在Safari之中检查页面是否加载完成,如果加载完成,则执行所有的onload句柄
289 var safariLoadedState={loaded:true,complete:true};//指定加载完成后的readyState状态
290 function checkSafariLoaded()
291 {
292 if(safariLoadedState[document.readyState])
293 {
294 runOnloadListeners()
295 }
296 else if(onloadListeners>0)
297 {
298 setTimeout(checkSafariLoaded,10)
299 }
300 }
301 //运行所有的onload事件句柄并清空onloadListeners函数
302 function runOnloadListeners()
303 {
304 for(var a=0;a<onloadListeners.length;a++)
305 {
306 onloadListeners[a]()
307 }
308 onloadListeners.length=0
309 }
310 //该函数没有在本API之中调用,大体意思应该是在URI之中解析出用户所使用的key
311 function setApiKeyLookupMap(a)
312 {
313 var b=window.location.href;
314 var c;
315 var d=b.length;
316 for(var e in a)
317 {
318 var f=b.indexOf(e);
319 if(f!=-1&&f<d)
320 {
321 c=e;
322 d=f
323 }
324 }
325 userKey=c?a[c]:null
326 }
327 //通过DOM方式加载内容
328 function writeLoadTag(type,url,needCallback)
329 {
330 if(needCallback)//通过DOM方式调用内容
331 {
332 var d;
333 if(type=="script")
334 {
335 d=document.createElement("script");
336 d.type="text/javascript";
337 d.src=url
338 }
339 else if(type=="css")
340 {
341 d=document.createElement("link");
342 d.type="text/css";
343 d.href=url;
344 d.rel="stylesheet"
345 }
346 document.getElementsByTagName("head")[0].appendChild(d)
347 }
348 else//通过document.write方式调用内容
349 {
350 if(type=="script")
351 {
352 document.write('<script src="'+url+'" type="text/javascript"><\/script>')
353 }
354 else if(type=="css")
355 {
356 document.write('<link href="'+url+'" type="text/css" rel="stylesheet"></link>')
357 }
358 }
359 }
360 //设置API加载完成后的回调函数
361 function setApiCallback(handle,apiName)
362 {
363 callbacks[apiName]=function()
364 {
365 for(var c=0;c<callbacks[apiName].actualCallbacks.length;c++)
366 {
367 setTimeout(callbacks[apiName].actualCallbacks[c],0)//运行每一个回调函数
368 }
369 delete callbacks[apiName]
370 };
371 callbacks[b].actualCallbacks=[handle];
372 return "google.loader.callbacks."+apiName
373 }
374 //设置类到命名空间
375 //a是该类的命名空间路径
376 //b是该类的function
377 function exportSymbol(path,cla)
378 {
379 var c=path.split(/\./);
380 var d=window;
381 for(var e=0;e<c.length-1;e++)
382 {
383 if(!d[c[e]])
384 {
385 d[c[e]]={}
386 }
387 d=d[c[e]]
388 }
389 d[c[c.length-1]]=cla
390 }
391 exportSymbol("google.load",load);
392 exportSymbol("google.setOnLoadCallback",setOnLoadCallback);
393 exportSymbol("google.loader.writeLoadTag",writeLoadTag);
394 exportSymbol("google.loader.setApiKeyLookupMap",setApiKeyLookupMap);
395 exportSymbol("google.loader.callbacks",callbacks);
396 exportSymbol("google_exportSymbol",exportSymbol);
397 //log对象用来向服务器发送一些记录信息,将每次需要发送的消息保存起来,在达到5条或者页面卸载的时候通过访问服务器端img的形式发送
398 function log(){}
399 var unloadListenerAdded=log.unloadListenerAdded=false;//是否已经添加unload事件监视器
400 var maxRecordNumber=log.maxRecordNumber=5;
401 var records=log.records=[];
402 //添加unload事件监视器
403 var addUnloadListener=log.addUnloadListener=function()
404 {
405 if(!unloadListenerAdded)//只有在没有添加的情况下才添加
406 {
407 addDomListener(window,"unload",sendRecords);
408 unloadListenerAdded=(log.unloadListenerAdded=true)
409 }
410 };
411 //将r2=name,或r2=name=value格式的记录保存到数组
412 var recordStat=log.record=function(name,value)
413 {
414 addUnloadListener();
415 var c=name+(value?"="+value:"");
416 records.push("r"+records.length+"="+encodeURIComponent(c));
417 if(records.length>maxRecordNumber)
418 {
419 setTimeout(sendRecords,0)
420 }
421 };
422 //在页面被卸载的时候执行的操作
423 var sendRecords=log.sendRecords=function()
424 {
425 if(records.length)//如果存在记录
426 {
427 //通过创建Image对象来向服务器发送记录信息
428 var a=new Image;
429 a.src=google.loader.ServiceBase+"/stats?"+records.join("&")+"&nocache="+Number(new Date);
430 records.length=0//清空对象
431 }
432 };
433 exportSymbol("google.loader.recordStat",recordStat);
434 preDefinedApis[":search"]=new ApiFile("search");
435 preDefinedApis[":feeds"]=new ApiFile("feeds");
436 preDefinedApis[":language"]=new ApiFile("language");
437 preDefinedApis[":maps"]=new CustomApiFile("maps","http://maps.google.com/maps?file=googleapi",true,"key","v",true,{":locale":"hl",":callback":function(a){return"callback="+encodeURIComponent(a)+"&async=2"}});
438 preDefinedApis[":gdata"]=new CustomApiFile("gdata","http://gd.google.com/gd/api?file=gdata.js",true,"key","v",false);
439 preDefinedApis[":sharing"]=new CustomApiFile("sharing","http://www.google.com/s2/sharing/js",false,"key","v",false,{":locale":"hl"});
440 }
441 )()
442 }
443
该文件的原文件内容可以在这个地址查看到。
posted on 2007-11-27 16:28 K_Reverter 阅读(4146) 评论(5) 编辑 收藏 举报