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
//定义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)!=-128
}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 c46
}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=fileName59
}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=true88
}89
return google.loader.ServiceBase+"/?file="+this.fileName+"&v="+version+google.loader.AdditionalParams+c90
};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
else127
{128
e=config[d]129
}130
var f=this.fileConfig[":"+d];131
if(typeof f=="string")132
{133
c+="&"+f+"="+encodeURIComponent(e)134
}135
else136
{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+c153
};154
CustomApiFile.prototype.canCallback=function()155
{156
return this._canCallback157
};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
else167
{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
else186
{187
writeLoadTag("script",api.getLoadUrl(version,config),needCallback)//调用加载进程188
}189
}190
else191
{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.message203
};204
return b205
}206
//设置页面加载完成之后执行的函数,b参数我没有见到调用207
function setOnLoadCallback(a,b)208
{209
if(b)210
{211
addOnloadListener(a)212
}213
else214
{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
else230
{231
var d=node["on"+eventName];232
if(d!=null)233
{234
node["on"+eventName]=getRunAllListener([handle,d])235
}236
node["on"+eventName]=handle237
}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
try276
{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=0309
}310
//该函数没有在本API之中调用,大体意思应该是在URI之中解析出用户所使用的key311
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=f323
}324
}325
userKey=c?a[c]:null326
}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=url338
}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."+apiName373
}374
//设置类到命名空间375
//a是该类的命名空间路径376
//b是该类的function377
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]]=cla390
}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 阅读(4168) 评论(5) 收藏 举报

window['google']
浙公网安备 33010602011771号