Subversion Repositories Applications.papyrus

Rev

Rev 1987 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1318 alexandre_ 1
/*
2
	Copyright (c) 2004-2006, The Dojo Foundation
3
	All Rights Reserved.
4
 
5
	Licensed under the Academic Free License version 2.1 or above OR the
6
	modified BSD license. For more information on Dojo licensing, see:
7
 
8
		http://dojotoolkit.org/community/licensing.shtml
9
*/
10
 
11
dojo.provide("dojo.docs");
12
dojo.require("dojo.io.*");
13
dojo.require("dojo.event.topic");
14
dojo.require("dojo.rpc.JotService");
15
dojo.require("dojo.dom");
16
dojo.require("dojo.uri.Uri");
17
dojo.require("dojo.Deferred");
18
dojo.require("dojo.DeferredList");
19
 
20
/*
21
 * TODO:
22
 *
23
 * Package summary needs to compensate for "is"
24
 * Handle host environments
25
 * Deal with dojo.widget weirdness
26
 * Parse parameters
27
 * Limit function parameters to only the valid ones (Involves packing parameters onto meta during rewriting)
28
 *
29
 */
30
 
31
dojo.docs = new function() {
32
	this._url = dojo.uri.dojoUri("docscripts");
33
	this._rpc = new dojo.rpc.JotService;
34
	this._rpc.serviceUrl = dojo.uri.dojoUri("docscripts/jsonrpc.php");
35
};
36
dojo.lang.mixin(dojo.docs, {
37
	_count: 0,
38
	_callbacks: {function_names: []},
39
	_cache: {}, // Saves the JSON objects in cache
40
	require: function(/*String*/ require, /*bool*/ sync) {
41
		dojo.debug("require(): " + require);
42
		var parts = require.split("/");
43
 
44
		var size = parts.length;
45
		var deferred = new dojo.Deferred;
46
		var args = {
47
			mimetype: "text/json",
48
			load: function(type, data){
49
				dojo.debug("require(): loaded for " + require);
50
 
51
				if(parts[0] != "function_names") {
52
					for(var i = 0, part; part = parts[i]; i++){
53
						data = data[part];
54
					}
55
				}
56
				deferred.callback(data);
57
			},
58
			error: function(){
59
				deferred.errback();
60
			}
61
		};
62
 
63
		if(location.protocol == "file:"){
64
			if(size){
65
				if(parts[parts.length - 1] == "documentation"){
66
					parts[parts.length - 1] = "meta";
67
				}
68
 
69
				if(parts[0] == "function_names"){
70
					args.url = [this._url, "local_json", "function_names"].join("/");
71
				}else{
72
					var dirs = parts[0].split(".");
73
					args.url = [this._url, "local_json", dirs[0]].join("/");
74
					if(dirs.length > 1){
75
						args.url = [args.url, dirs[1]].join(".");
76
					}
77
				}
78
			}
79
		}
80
 
81
		dojo.io.bind(args);
82
		return deferred;
83
	},
84
	getFunctionNames: function(){
85
		return this.require("function_names"); // dojo.Deferred
86
	},
87
	unFormat: function(/*String*/ string){
88
		var fString = string;
89
		if(string.charAt(string.length - 1) == "_"){
90
			fString = [string.substring(0, string.length - 1), "*"].join("");
91
		}
92
		return fString;
93
	},
94
	getMeta: function(/*String*/ pkg, /*String*/ name, /*Function*/ callback, /*String?*/ id){
95
		// summary: Gets information about a function in regards to its meta data
96
		if(typeof name == "function"){
97
			// pId: a
98
			// pkg: ignore
99
			id = callback;
100
			callback = name;
101
			name = pkg;
102
			pkg = null;
103
			dojo.debug("getMeta(" + name + ")");
104
		}else{
105
			dojo.debug("getMeta(" + pkg + "/" + name + ")");
106
		}
107
 
108
		if(!id){
109
			id = "_";
110
		}
111
	},
112
	_withPkg: function(/*String*/ type, /*Object*/ data, /*Object*/ evt, /*Object*/ input, /*String*/ newType){
113
		dojo.debug("_withPkg(" + evt.name + ") has package: " + data[0]);
114
		evt.pkg = data[0];
115
		if("load" == type && evt.pkg){
116
			evt.type = newType;
117
		}else{
118
			if(evt.callbacks && evt.callbacks.length){
119
				evt.callbacks.shift()("error", {}, evt, evt.input);
120
			}
121
		}
122
	},
123
	_gotMeta: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
124
		dojo.debug("_gotMeta(" + evt.name + ")");
125
 
126
		var cached = dojo.docs._getCache(evt.pkg, evt.name, "meta", "functions", evt.id);
127
		if(cached.summary){
128
			data.summary = cached.summary;
129
		}
130
		if(evt.callbacks && evt.callbacks.length){
131
			evt.callbacks.shift()(type, data, evt, evt.input);
132
		}
133
	},
134
	getSrc: function(/*String*/ name, /*Function*/ callback, /*String?*/ id){
135
		// summary: Gets src file (created by the doc parser)
136
		dojo.debug("getSrc(" + name + ")");
137
		if(!id){
138
			id = "_";
139
		}
140
	},
141
	getDoc: function(/*String*/ name, /*Function*/ callback, /*String?*/ id){
142
		// summary: Gets external documentation stored on Jot for a given function
143
		dojo.debug("getDoc(" + name  + ")");
144
 
145
		if(!id){
146
			id = "_";
147
		}
148
 
149
		var input = {};
150
 
151
		input.type = "doc";
152
		input.name = name;
153
		input.callbacks = [callback];
154
	},
155
	_gotDoc: function(/*String*/ type, /*Array*/ data, /*Object*/ evt, /*Object*/ input){
156
		dojo.debug("_gotDoc(" + evt.type + ")");
157
 
158
		evt[evt.type] = data;
159
		if(evt.expects && evt.expects.doc){
160
			for(var i = 0, expect; expect = evt.expects.doc[i]; i++){
161
				if(!(expect in evt)){
162
					dojo.debug("_gotDoc() waiting for more data");
163
					return;
164
				}
165
			}
166
		}
167
 
168
		var cache = dojo.docs._getCache(evt.pkg, "meta", "functions", evt.name, evt.id, "meta");
169
 
170
		var description = evt.fn.description;
171
		cache.description = description;
172
		data = {
173
			returns: evt.fn.returns,
174
			id: evt.id,
175
			variables: []
176
		}
177
		if(!cache.parameters){
178
			cache.parameters = {};
179
		}
180
		for(var i = 0, param; param = evt.param[i]; i++){
181
			var fName = param["DocParamForm/name"];
182
			if(!cache.parameters[fName]){
183
				cache.parameters[fName] = {};
184
			}
185
			cache.parameters[fName].description = param["DocParamForm/desc"]
186
		}
187
 
188
		data.description = cache.description;
189
		data.parameters = cache.parameters;
190
 
191
		evt.type = "doc";
192
 
193
		if(evt.callbacks && evt.callbacks.length){
194
			evt.callbacks.shift()("load", data, evt, input);
195
		}
196
	},
197
	getPkgDoc: function(/*String*/ name, /*Function*/ callback){
198
		// summary: Gets external documentation stored on Jot for a given package
199
		dojo.debug("getPkgDoc(" + name + ")");
200
		var input = {};
201
	},
202
	getPkgInfo: function(/*String*/ name, /*Function*/ callback){
203
		// summary: Gets a combination of the metadata and external documentation for a given package
204
		dojo.debug("getPkgInfo(" + name + ")");
205
 
206
		var input = {
207
			expects: {
208
				pkginfo: ["pkgmeta", "pkgdoc"]
209
			},
210
			callback: callback
211
		};
212
		dojo.docs.getPkgMeta(input, name, dojo.docs._getPkgInfo);
213
		dojo.docs.getPkgDoc(input, name, dojo.docs._getPkgInfo);
214
	},
215
	_getPkgInfo: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
216
		dojo.debug("_getPkgInfo() for " + evt.type);
217
		var input = {};
218
		var results = {};
219
		if(typeof key == "object"){
220
			input = key;
221
			input[evt.type] = data;
222
			if(input.expects && input.expects.pkginfo){
223
				for(var i = 0, expect; expect = input.expects.pkginfo[i]; i++){
224
					if(!(expect in input)){
225
						dojo.debug("_getPkgInfo() waiting for more data");
226
						return;
227
					}
228
				}
229
			}
230
			results = input.pkgmeta;
231
			results.description = input.pkgdoc;
232
		}
233
 
234
		if(input.callback){
235
			input.callback("load", results, evt);
236
		}
237
	},
238
	getInfo: function(/*String*/ name, /*Function*/ callback){
239
		dojo.debug("getInfo(" + name + ")");
240
		var input = {
241
			expects: {
242
				"info": ["meta", "doc"]
243
			},
244
			callback: callback
245
		}
246
		dojo.docs.getMeta(input, name, dojo.docs._getInfo);
247
		dojo.docs.getDoc(input, name, dojo.docs._getInfo);
248
	},
249
	_getInfo: function(/*String*/ type, /*String*/ data, /*Object*/ evt, /*Object*/ input){
250
		dojo.debug("_getInfo(" + evt.type + ")");
251
		if(input && input.expects && input.expects.info){
252
			input[evt.type] = data;
253
			for(var i = 0, expect; expect = input.expects.info[i]; i++){
254
				if(!(expect in input)){
255
					dojo.debug("_getInfo() waiting for more data");
256
					return;
257
				}
258
			}
259
		}
260
 
261
		if(input.callback){
262
			input.callback("load", dojo.docs._getCache(evt.pkg, "meta", "functions", evt.name, evt.id, "meta"), evt, input);
263
		}
264
	},
265
	_getMainText: function(/*String*/ text){
266
		// summary: Grabs the innerHTML from a Jot Rech Text node
267
		dojo.debug("_getMainText()");
268
		return text.replace(/^<html[^<]*>/, "").replace(/<\/html>$/, "").replace(/<\w+\s*\/>/g, "");
269
	},
270
	getPackageMeta: function(/*Object*/ input){
271
		dojo.debug("getPackageMeta(): " + input.package);
272
		return this.require(input.package + "/meta", input.sync);
273
	},
274
	getFunctionMeta: function(/*Object*/ input){
275
		var package = input.package || "";
276
		var name = input.name;
277
		var id = input.id || "_";
278
		dojo.debug("getFunctionMeta(): " + name);
279
 
280
		if(!name) return;
281
 
282
		if(package){
283
			return this.require(package + "/meta/functions/" + name + "/" + id + "/meta");
284
		}else{
285
			this.getFunctionNames();
286
		}
287
	},
288
	getFunctionDocumentation: function(/*Object*/ input){
289
		var package = input.package || "";
290
		var name = input.name;
291
		var id = input.id || "_";
292
		dojo.debug("getFunctionDocumentation(): " + name);
293
 
294
		if(!name) return;
295
 
296
		if(package){
297
			return this.require(package + "/meta/functions/" + name + "/" + id + "/documentation");
298
		}
299
	},
300
	_onDocSearch: function(/*Object*/ input){
301
		var _this = this;
302
		var name = input.name.toLowerCase();
303
		if(!name) return;
304
 
305
		this.getFunctionNames().addCallback(function(data){
306
			dojo.debug("_onDocSearch(): function names loaded for " + name);
307
 
308
			var output = [];
309
			var list = [];
310
			var closure = function(pkg, fn) {
311
				return function(data){
312
					dojo.debug("_onDocSearch(): package meta loaded for: " + pkg);
313
					if(data.functions){
314
						var functions = data.functions;
315
						for(var key in functions){
316
							if(fn == key){
317
								var ids = functions[key];
318
								for(var id in ids){
319
									var fnMeta = ids[id];
320
									output.push({
321
										package: pkg,
322
										name: fn,
323
										id: id,
324
										summary: fnMeta.summary
325
									});
326
								}
327
							}
328
						}
329
					}
330
					return output;
331
				}
332
			}
333
 
334
			pkgLoop:
335
			for(var pkg in data){
336
				if(pkg.toLowerCase() == name){
337
					name = pkg;
338
					dojo.debug("_onDocSearch found a package");
339
					//dojo.docs._onDocSelectPackage(input);
340
					return;
341
				}
342
				for(var i = 0, fn; fn = data[pkg][i]; i++){
343
					if(fn.toLowerCase().indexOf(name) != -1){
344
						dojo.debug("_onDocSearch(): Search matched " + fn);
345
						var meta = _this.getPackageMeta({package: pkg});
346
						meta.addCallback(closure(pkg, fn));
347
						list.push(meta);
348
 
349
						// Build a list of all packages that need to be loaded and their loaded state.
350
						continue pkgLoop;
351
					}
352
				}
353
			}
354
 
355
			list = new dojo.DeferredList(list);
356
			list.addCallback(function(results){
357
				dojo.debug("_onDocSearch(): All packages loaded");
358
				_this._printFunctionResults(results[0][1]);
359
			});
360
		});
361
	},
362
	_onDocSearchFn: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
363
		dojo.debug("_onDocSearchFn(" + evt.name + ")");
364
 
365
		var name = evt.name || evt.pkg;
366
 
367
		dojo.debug("_onDocSearchFn found a function");
368
 
369
		evt.pkgs = packages;
370
		evt.pkg = name;
371
		evt.loaded = 0;
372
		for(var i = 0, pkg; pkg = packages[i]; i++){
373
			dojo.docs.getPkgMeta(evt, pkg, dojo.docs._onDocResults);
374
		}
375
	},
376
	_onPkgResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt, /*Object*/ input){
377
		dojo.debug("_onPkgResults(" + evt.type + ")");
378
		var description = "";
379
		var path = "";
380
		var methods = {};
381
		var requires = {};
382
		if(input){
383
			input[evt.type] = data;
384
			if(input.expects && input.expects.pkgresults){
385
				for(var i = 0, expect; expect = input.expects.pkgresults[i]; i++){
386
					if(!(expect in input)){
387
						dojo.debug("_onPkgResults() waiting for more data");
388
						return;
389
					}
390
				}
391
			}
392
			path = input.pkgdoc.path;
393
			description = input.pkgdoc.description;
394
			methods = input.pkgmeta.methods;
395
			requires = input.pkgmeta.requires;
396
		}
397
		var pkg = evt.name.replace("_", "*");
398
		var results = {
399
			path: path,
400
			description: description,
401
			size: 0,
402
			methods: [],
403
			pkg: pkg,
404
			requires: requires
405
		}
406
		var rePrivate = /_[^.]+$/;
407
		for(var method in methods){
408
			if(!rePrivate.test(method)){
409
				for(var pId in methods[method]){
410
					results.methods.push({
411
						pkg: pkg,
412
						name: method,
413
						id: pId,
414
						summary: methods[method][pId].summary
415
					})
416
				}
417
			}
418
		}
419
		results.size = results.methods.length;
420
		dojo.docs._printPkgResult(results);
421
	},
422
	_onDocResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt, /*Object*/ input){
423
		dojo.debug("_onDocResults(" + evt.name + "/" + input.pkg + ") " + type);
424
		++input.loaded;
425
 
426
		if(input.loaded == input.pkgs.length){
427
			var pkgs = input.pkgs;
428
			var name = input.pkg;
429
			var results = {methods: []};
430
			var rePrivate = /_[^.]+$/;
431
			data = dojo.docs._cache;
432
 
433
			for(var i = 0, pkg; pkg = pkgs[i]; i++){
434
				var methods = dojo.docs._getCache(pkg, "meta", "methods");
435
				for(var fn in methods){
436
					if(fn.toLowerCase().indexOf(name) == -1){
437
						continue;
438
					}
439
					if(fn != "requires" && !rePrivate.test(fn)){
440
						for(var pId in methods[fn]){
441
							var result = {
442
								pkg: pkg,
443
								name: fn,
444
								id: "_",
445
								summary: ""
446
							}
447
							if(methods[fn][pId].summary){
448
								result.summary = methods[fn][pId].summary;
449
							}
450
							results.methods.push(result);
451
						}
452
					}
453
				}
454
			}
455
 
456
			dojo.debug("Publishing docResults");
457
			dojo.docs._printFnResults(results);
458
		}
459
	},
460
	_printFunctionResults: function(results){
461
		dojo.debug("_printFnResults(): called");
462
		// summary: Call this function to send the /docs/function/results topic
463
	},
464
	_printPkgResult: function(results){
465
		dojo.debug("_printPkgResult(): called");
466
	},
467
	_onDocSelectFunction: function(/*Object*/ input){
468
		// summary: Get doc, meta, and src
469
		var name = input.name;
470
		var package = input.package || "";
471
		var id = input.id || "_";
472
		dojo.debug("_onDocSelectFunction(" + name + ")");
473
		if(!name || !package) return false;
474
 
475
		var pkgMeta = this.getPackageMeta({package: package});
476
		var meta = this.getFunctionMeta({package: package, name: name, id: id});
477
		var doc = this.getFunctionDocumentation({package: package, name: name, id: id});
478
 
479
		var list = new dojo.DeferredList([pkgMeta, meta, doc]);
480
		list.addCallback(function(results){
481
			dojo.debug("_onDocSelectFunction() loaded");
482
			for(var i = 0, result; result = results[i]; i++){
483
				dojo.debugShallow(result[1]);
484
			}
485
		});
486
 
487
		return list;
488
	},
489
	_onDocSelectPackage: function(/*Object*/ input){
490
		dojo.debug("_onDocSelectPackage(" + input.name + ")")
491
		input.expects = {
492
			"pkgresults": ["pkgmeta", "pkgdoc"]
493
		};
494
		dojo.docs.getPkgMeta(input, input.name, dojo.docs._onPkgResults);
495
		dojo.docs.getPkgDoc(input, input.name, dojo.docs._onPkgResults);
496
	},
497
	_onDocSelectResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt, /*Object*/ input){
498
		dojo.debug("_onDocSelectResults(" + evt.type + ", " + evt.name + ")");
499
		if(evt.type == "meta"){
500
			dojo.docs.getPkgMeta(input, evt.pkg, dojo.docs._onDocSelectResults);
501
		}
502
		if(input){
503
			input[evt.type] = data;
504
			if(input.expects && input.expects.docresults){
505
				for(var i = 0, expect; expect = input.expects.docresults[i]; i++){
506
					if(!(expect in input)){
507
						dojo.debug("_onDocSelectResults() waiting for more data");
508
						return;
509
					}
510
				}
511
			}
512
		}
513
 
514
		dojo.docs._printFunctionDetail(input);
515
	},
516
 
517
	_printFunctionDetail: function(results) {
518
		// summary: Call this function to send the /docs/function/detail topic event
519
	},
520
 
521
	selectFunction: function(/*String*/ name, /*String?*/ id){
522
		// summary: The combined information
523
	},
524
	savePackage: function(/*Object*/ callbackObject, /*String*/ callback, /*Object*/ parameters){
525
		dojo.event.kwConnect({
526
			srcObj: dojo.docs,
527
			srcFunc: "_savedPkgRpc",
528
			targetObj: callbackObject,
529
			targetFunc: callback,
530
			once: true
531
		});
532
 
533
		var props = {};
534
		var cache = dojo.docs._getCache(parameters.pkg, "meta");
535
 
536
		var i = 1;
537
 
538
		if(!cache.path){
539
			var path = "id";
540
			props[["pname", i].join("")] = "DocPkgForm/require";
541
			props[["pvalue", i++].join("")] = parameters.pkg;
542
		}else{
543
			var path = cache.path;
544
		}
545
 
546
		props.form = "//DocPkgForm";
547
		props.path = ["/WikiHome/DojoDotDoc/", path].join("");
548
 
549
		if(parameters.description){
550
			props[["pname", i].join("")] = "main/text";
551
			props[["pvalue", i++].join("")] = parameters.description;
552
		}
553
 
554
		dojo.docs._rpc.callRemote("saveForm",	props).addCallbacks(dojo.docs._pkgRpc, dojo.docs._pkgRpc);
555
	},
556
	_pkgRpc: function(data){
557
		if(data.name){
558
			dojo.docs._getCache(data["DocPkgForm/require"], "meta").path = data.name;
559
			dojo.docs._savedPkgRpc("load");
560
		}else{
561
			dojo.docs._savedPkgRpc("error");
562
		}
563
	},
564
	_savedPkgRpc: function(type){
565
	},
566
	functionPackages: function(/*String*/ name, /*Function*/ callback, /*Object*/ input){
567
		// summary: Gets the package associated with a function and stores it in the .pkg value of input
568
		dojo.debug("functionPackages() name: " + name);
569
 
570
		if(!input){
571
			input = {};
572
		}
573
		if(!input.callbacks){
574
			input.callbacks = [];
575
		}
576
 
577
		input.type = "function_names";
578
		input.name = name;
579
		input.callbacks.unshift(callback);
580
		input.callbacks.unshift(dojo.docs._functionPackages);
581
	},
582
	_functionPackages: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
583
		dojo.debug("_functionPackages() name: " + evt.name);
584
		evt.pkg = '';
585
 
586
		var results = [];
587
		var data = dojo.docs._cache['function_names'];
588
		for(var key in data){
589
			if(dojo.lang.inArray(data[key], evt.name)){
590
				dojo.debug("_functionPackages() package: " + key);
591
				results.push(key);
592
			}
593
		}
594
 
595
		if(evt.callbacks && evt.callbacks.length){
596
			evt.callbacks.shift()(type, results, evt, evt.input);
597
		}
598
	},
599
	setUserName: function(/*String*/ name){
600
		dojo.docs._userName = name;
601
		if(name && dojo.docs._password){
602
			dojo.docs._logIn();
603
		}
604
	},
605
	setPassword: function(/*String*/ password){
606
		dojo.docs._password = password;
607
		if(password && dojo.docs._userName){
608
			dojo.docs._logIn();
609
		}
610
	},
611
	_logIn: function(){
612
		dojo.io.bind({
613
			url: dojo.docs._rpc.serviceUrl.toString(),
614
			method: "post",
615
			mimetype: "text/json",
616
			content: {
617
				username: dojo.docs._userName,
618
				password: dojo.docs._password
619
			},
620
			load: function(type, data){
621
				if(data.error){
622
					dojo.docs.logInSuccess();
623
				}else{
624
					dojo.docs.logInFailure();
625
				}
626
			},
627
			error: function(){
628
				dojo.docs.logInFailure();
629
			}
630
		});
631
	},
632
	logInSuccess: function(){},
633
	logInFailure: function(){},
634
	_set: function(/*Object*/ base, /*String...*/ keys, /*String*/ value){
635
		var args = [];
636
		for(var i = 0, arg; arg = arguments[i]; i++){
637
			args.push(arg);
638
		}
639
 
640
		if(args.length < 3) return;
641
		base = args.shift();
642
		value = args.pop();
643
		var key = args.pop();
644
		for(var i = 0, arg; arg = args[i]; i++){
645
			if(typeof base[arg] != "object"){
646
				base[arg] = {};
647
			}
648
			base = base[arg];
649
		}
650
		base[key] = value;
651
	},
652
	_getCache: function(/*String...*/ keys){
653
		var obj = dojo.docs._cache;
654
		for(var i = 0; i < arguments.length; i++){
655
			var arg = arguments[i];
656
			if(!obj[arg]){
657
				obj[arg] = {};
658
			}
659
			obj = obj[arg];
660
		}
661
		return obj;
662
	}
663
});
664
 
665
dojo.event.topic.subscribe("/docs/search", dojo.docs, "_onDocSearch");
666
dojo.event.topic.subscribe("/docs/function/select", dojo.docs, "_onDocSelectFunction");
667
dojo.event.topic.subscribe("/docs/package/select", dojo.docs, "_onDocSelectPackage");
668
 
669
dojo.event.topic.registerPublisher("/docs/function/results", dojo.docs, "_printFunctionResults");
670
dojo.event.topic.registerPublisher("/docs/function/detail", dojo.docs, "_printFunctionDetail");
671
dojo.event.topic.registerPublisher("/docs/package/detail", dojo.docs, "_printPkgResult");