Subversion Repositories Applications.papyrus

Rev

Rev 1318 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1318 Rev 1422
1
/*
1
/*
2
	Copyright (c) 2004-2006, The Dojo Foundation
2
	Copyright (c) 2004-2006, The Dojo Foundation
3
	All Rights Reserved.
3
	All Rights Reserved.
4
 
4
 
5
	Licensed under the Academic Free License version 2.1 or above OR the
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:
6
	modified BSD license. For more information on Dojo licensing, see:
7
 
7
 
8
		http://dojotoolkit.org/community/licensing.shtml
8
		http://dojotoolkit.org/community/licensing.shtml
9
*/
9
*/
10
 
10
 
11
if(typeof dojo == "undefined"){
11
if(typeof dojo == "undefined"){
12
 
12
 
13
// TODOC: HOW TO DOC THE BELOW?
13
// TODOC: HOW TO DOC THE BELOW?
14
// @global: djConfig
14
// @global: djConfig
15
// summary:
15
// summary:
16
//		Application code can set the global 'djConfig' prior to loading
16
//		Application code can set the global 'djConfig' prior to loading
17
//		the library to override certain global settings for how dojo works.
17
//		the library to override certain global settings for how dojo works.
18
// description:  The variables that can be set are as follows:
18
// description:  The variables that can be set are as follows:
19
//			- isDebug: false
19
//			- isDebug: false
20
//			- allowQueryConfig: false
20
//			- allowQueryConfig: false
21
//			- baseScriptUri: ""
21
//			- baseScriptUri: ""
22
//			- baseRelativePath: ""
22
//			- baseRelativePath: ""
23
//			- libraryScriptUri: ""
23
//			- libraryScriptUri: ""
24
//			- iePreventClobber: false
24
//			- iePreventClobber: false
25
//			- ieClobberMinimal: true
25
//			- ieClobberMinimal: true
26
//			- locale: undefined
26
//			- locale: undefined
27
//			- extraLocale: undefined
27
//			- extraLocale: undefined
28
//			- preventBackButtonFix: true
28
//			- preventBackButtonFix: true
29
//			- searchIds: []
29
//			- searchIds: []
30
//			- parseWidgets: true
30
//			- parseWidgets: true
31
// TODOC: HOW TO DOC THESE VARIABLES?
31
// TODOC: HOW TO DOC THESE VARIABLES?
32
// TODOC: IS THIS A COMPLETE LIST?
32
// TODOC: IS THIS A COMPLETE LIST?
33
// note:
33
// note:
34
//		'djConfig' does not exist under 'dojo.*' so that it can be set before the
34
//		'djConfig' does not exist under 'dojo.*' so that it can be set before the
35
//		'dojo' variable exists.
35
//		'dojo' variable exists.
36
// note:
36
// note:
37
//		Setting any of these variables *after* the library has loaded does nothing at all.
37
//		Setting any of these variables *after* the library has loaded does nothing at all.
38
// TODOC: is this still true?  Release notes for 0.3 indicated they could be set after load.
38
// TODOC: is this still true?  Release notes for 0.3 indicated they could be set after load.
39
//
39
//
40
 
40
 
41
 
41
 
42
//TODOC:  HOW TO DOC THIS?
42
//TODOC:  HOW TO DOC THIS?
43
// @global: dj_global
43
// @global: dj_global
44
// summary:
44
// summary:
45
//		an alias for the top-level global object in the host environment
45
//		an alias for the top-level global object in the host environment
46
//		(e.g., the window object in a browser).
46
//		(e.g., the window object in a browser).
47
// description:
47
// description:
48
//		Refer to 'dj_global' rather than referring to window to ensure your
48
//		Refer to 'dj_global' rather than referring to window to ensure your
49
//		code runs correctly in contexts other than web browsers (eg: Rhino on a server).
49
//		code runs correctly in contexts other than web browsers (eg: Rhino on a server).
50
var dj_global = this;
50
var dj_global = this;
51
 
51
 
52
//TODOC:  HOW TO DOC THIS?
52
//TODOC:  HOW TO DOC THIS?
53
// @global: dj_currentContext
53
// @global: dj_currentContext
54
// summary:
54
// summary:
55
//		Private global context object. Where 'dj_global' always refers to the boot-time
55
//		Private global context object. Where 'dj_global' always refers to the boot-time
56
//    global context, 'dj_currentContext' can be modified for temporary context shifting.
56
//    global context, 'dj_currentContext' can be modified for temporary context shifting.
57
//    dojo.global() returns dj_currentContext.
57
//    dojo.global() returns dj_currentContext.
58
// description:
58
// description:
59
//		Refer to dojo.global() rather than referring to dj_global to ensure your
59
//		Refer to dojo.global() rather than referring to dj_global to ensure your
60
//		code runs correctly in managed contexts.
60
//		code runs correctly in managed contexts.
61
var dj_currentContext = this;
61
var dj_currentContext = this;
62
 
62
 
63
 
63
 
64
// ****************************************************************
64
// ****************************************************************
65
// global public utils
65
// global public utils
66
// TODOC: DO WE WANT TO NOTE THAT THESE ARE GLOBAL PUBLIC UTILS?
66
// TODOC: DO WE WANT TO NOTE THAT THESE ARE GLOBAL PUBLIC UTILS?
67
// ****************************************************************
67
// ****************************************************************
68
 
68
 
69
function dj_undef(/*String*/ name, /*Object?*/ object){
69
function dj_undef(/*String*/ name, /*Object?*/ object){
70
	//summary: Returns true if 'name' is defined on 'object' (or globally if 'object' is null).
70
	//summary: Returns true if 'name' is defined on 'object' (or globally if 'object' is null).
71
	//description: Note that 'defined' and 'exists' are not the same concept.
71
	//description: Note that 'defined' and 'exists' are not the same concept.
72
	return (typeof (object || dj_currentContext)[name] == "undefined");	// Boolean
72
	return (typeof (object || dj_currentContext)[name] == "undefined");	// Boolean
73
}
73
}
74
 
74
 
75
// make sure djConfig is defined
75
// make sure djConfig is defined
76
if(dj_undef("djConfig", this)){
76
if(dj_undef("djConfig", this)){
77
	var djConfig = {};
77
	var djConfig = {};
78
}
78
}
79
 
79
 
80
//TODOC:  HOW TO DOC THIS?
80
//TODOC:  HOW TO DOC THIS?
81
// dojo is the root variable of (almost all) our public symbols -- make sure it is defined.
81
// dojo is the root variable of (almost all) our public symbols -- make sure it is defined.
82
if(dj_undef("dojo", this)){
82
if(dj_undef("dojo", this)){
83
	var dojo = {};
83
	var dojo = {};
84
}
84
}
85
 
85
 
86
dojo.global = function(){
86
dojo.global = function(){
87
	// summary:
87
	// summary:
88
	//		return the current global context object
88
	//		return the current global context object
89
	//		(e.g., the window object in a browser).
89
	//		(e.g., the window object in a browser).
90
	// description:
90
	// description:
91
	//		Refer to 'dojo.global()' rather than referring to window to ensure your
91
	//		Refer to 'dojo.global()' rather than referring to window to ensure your
92
	//		code runs correctly in contexts other than web browsers (eg: Rhino on a server).
92
	//		code runs correctly in contexts other than web browsers (eg: Rhino on a server).
93
	return dj_currentContext;
93
	return dj_currentContext;
94
}
94
}
95
 
95
 
96
// Override locale setting, if specified
96
// Override locale setting, if specified
97
dojo.locale  = djConfig.locale;
97
dojo.locale  = djConfig.locale;
98
 
98
 
99
//TODOC:  HOW TO DOC THIS?
99
//TODOC:  HOW TO DOC THIS?
100
dojo.version = {
100
dojo.version = {
101
	// summary: version number of this instance of dojo.
101
	// summary: version number of this instance of dojo.
102
	major: 0, minor: 4, patch: 2, flag: "",
102
	major: 0, minor: 4, patch: 3, flag: "",
103
	revision: Number("$Rev: 7616 $".match(/[0-9]+/)[0]),
103
	revision: Number("$Rev: 8617 $".match(/[0-9]+/)[0]),
104
	toString: function(){
104
	toString: function(){
105
		with(dojo.version){
105
		with(dojo.version){
106
			return major + "." + minor + "." + patch + flag + " (" + revision + ")";	// String
106
			return major + "." + minor + "." + patch + flag + " (" + revision + ")";	// String
107
		}
107
		}
108
	}
108
	}
109
}
109
}
110
 
110
 
111
dojo.evalProp = function(/*String*/ name, /*Object*/ object, /*Boolean?*/ create){
111
dojo.evalProp = function(/*String*/ name, /*Object*/ object, /*Boolean?*/ create){
112
	// summary: Returns 'object[name]'.  If not defined and 'create' is true, will return a new Object.
112
	// summary: Returns 'object[name]'.  If not defined and 'create' is true, will return a new Object.
113
	// description:
113
	// description:
114
	//		Returns null if 'object[name]' is not defined and 'create' is not true.
114
	//		Returns null if 'object[name]' is not defined and 'create' is not true.
115
	// 		Note: 'defined' and 'exists' are not the same concept.
115
	// 		Note: 'defined' and 'exists' are not the same concept.
116
	if((!object)||(!name)) return undefined; // undefined
116
	if((!object)||(!name)) return undefined; // undefined
117
	if(!dj_undef(name, object)) return object[name]; // mixed
117
	if(!dj_undef(name, object)) return object[name]; // mixed
118
	return (create ? (object[name]={}) : undefined);	// mixed
118
	return (create ? (object[name]={}) : undefined);	// mixed
119
}
119
}
120
 
120
 
121
dojo.parseObjPath = function(/*String*/ path, /*Object?*/ context, /*Boolean?*/ create){
121
dojo.parseObjPath = function(/*String*/ path, /*Object?*/ context, /*Boolean?*/ create){
122
	// summary: Parse string path to an object, and return corresponding object reference and property name.
122
	// summary: Parse string path to an object, and return corresponding object reference and property name.
123
	// description:
123
	// description:
124
	//		Returns an object with two properties, 'obj' and 'prop'.
124
	//		Returns an object with two properties, 'obj' and 'prop'.
125
	//		'obj[prop]' is the reference indicated by 'path'.
125
	//		'obj[prop]' is the reference indicated by 'path'.
126
	// path: Path to an object, in the form "A.B.C".
126
	// path: Path to an object, in the form "A.B.C".
127
	// context: Object to use as root of path.  Defaults to 'dojo.global()'.
127
	// context: Object to use as root of path.  Defaults to 'dojo.global()'.
128
	// create: If true, Objects will be created at any point along the 'path' that is undefined.
128
	// create: If true, Objects will be created at any point along the 'path' that is undefined.
129
	var object = (context || dojo.global());
129
	var object = (context || dojo.global());
130
	var names = path.split('.');
130
	var names = path.split('.');
131
	var prop = names.pop();
131
	var prop = names.pop();
132
	for (var i=0,l=names.length;i<l && object;i++){
132
	for (var i=0,l=names.length;i<l && object;i++){
133
		object = dojo.evalProp(names[i], object, create);
133
		object = dojo.evalProp(names[i], object, create);
134
	}
134
	}
135
	return {obj: object, prop: prop};	// Object: {obj: Object, prop: String}
135
	return {obj: object, prop: prop};	// Object: {obj: Object, prop: String}
136
}
136
}
137
 
137
 
138
dojo.evalObjPath = function(/*String*/ path, /*Boolean?*/ create){
138
dojo.evalObjPath = function(/*String*/ path, /*Boolean?*/ create){
139
	// summary: Return the value of object at 'path' in the global scope, without using 'eval()'.
139
	// summary: Return the value of object at 'path' in the global scope, without using 'eval()'.
140
	// path: Path to an object, in the form "A.B.C".
140
	// path: Path to an object, in the form "A.B.C".
141
	// create: If true, Objects will be created at any point along the 'path' that is undefined.
141
	// create: If true, Objects will be created at any point along the 'path' that is undefined.
142
	if(typeof path != "string"){
142
	if(typeof path != "string"){
143
		return dojo.global();
143
		return dojo.global();
144
	}
144
	}
145
	// fast path for no periods
145
	// fast path for no periods
146
	if(path.indexOf('.') == -1){
146
	if(path.indexOf('.') == -1){
147
		return dojo.evalProp(path, dojo.global(), create);		// mixed
147
		return dojo.evalProp(path, dojo.global(), create);		// mixed
148
	}
148
	}
149
 
149
 
150
	//MOW: old 'with' syntax was confusing and would throw an error if parseObjPath returned null.
150
	//MOW: old 'with' syntax was confusing and would throw an error if parseObjPath returned null.
151
	var ref = dojo.parseObjPath(path, dojo.global(), create);
151
	var ref = dojo.parseObjPath(path, dojo.global(), create);
152
	if(ref){
152
	if(ref){
153
		return dojo.evalProp(ref.prop, ref.obj, create);	// mixed
153
		return dojo.evalProp(ref.prop, ref.obj, create);	// mixed
154
	}
154
	}
155
	return null;
155
	return null;
156
}
156
}
157
 
157
 
158
dojo.errorToString = function(/*Error*/ exception){
158
dojo.errorToString = function(/*Error*/ exception){
159
	// summary: Return an exception's 'message', 'description' or text.
159
	// summary: Return an exception's 'message', 'description' or text.
160
 
160
 
161
	// TODO: overriding Error.prototype.toString won't accomplish this?
161
	// TODO: overriding Error.prototype.toString won't accomplish this?
162
 	// 		... since natively generated Error objects do not always reflect such things?
162
 	// 		... since natively generated Error objects do not always reflect such things?
163
	if(!dj_undef("message", exception)){
163
	if(!dj_undef("message", exception)){
164
		return exception.message;		// String
164
		return exception.message;		// String
165
	}else if(!dj_undef("description", exception)){
165
	}else if(!dj_undef("description", exception)){
166
		return exception.description;	// String
166
		return exception.description;	// String
167
	}else{
167
	}else{
168
		return exception;				// Error
168
		return exception;				// Error
169
	}
169
	}
170
}
170
}
171
 
171
 
172
dojo.raise = function(/*String*/ message, /*Error?*/ exception){
172
dojo.raise = function(/*String*/ message, /*Error?*/ exception){
173
	// summary: Common point for raising exceptions in Dojo to enable logging.
173
	// summary: Common point for raising exceptions in Dojo to enable logging.
174
	//	Throws an error message with text of 'exception' if provided, or
174
	//	Throws an error message with text of 'exception' if provided, or
175
	//	rethrows exception object.
175
	//	rethrows exception object.
176
 
176
 
177
	if(exception){
177
	if(exception){
178
		message = message + ": "+dojo.errorToString(exception);
178
		message = message + ": "+dojo.errorToString(exception);
179
	}else{
179
	}else{
180
		message = dojo.errorToString(message);
180
		message = dojo.errorToString(message);
181
	}
181
	}
182
 
182
 
183
	// print the message to the user if hostenv.println is defined
183
	// print the message to the user if hostenv.println is defined
184
	try { if(djConfig.isDebug){ dojo.hostenv.println("FATAL exception raised: "+message); } } catch (e) {}
184
	try { if(djConfig.isDebug){ dojo.hostenv.println("FATAL exception raised: "+message); } } catch (e) {}
185
 
185
 
186
	throw exception || Error(message);
186
	throw exception || Error(message);
187
}
187
}
188
 
188
 
189
//Stub functions so things don't break.
189
//Stub functions so things don't break.
190
//TODOC:  HOW TO DOC THESE?
190
//TODOC:  HOW TO DOC THESE?
191
dojo.debug = function(){};
191
dojo.debug = function(){};
192
dojo.debugShallow = function(obj){};
192
dojo.debugShallow = function(obj){};
193
dojo.profile = { start: function(){}, end: function(){}, stop: function(){}, dump: function(){} };
193
dojo.profile = { start: function(){}, end: function(){}, stop: function(){}, dump: function(){} };
194
 
194
 
195
function dj_eval(/*String*/ scriptFragment){
195
function dj_eval(/*String*/ scriptFragment){
196
	// summary: Perform an evaluation in the global scope.  Use this rather than calling 'eval()' directly.
196
	// summary: Perform an evaluation in the global scope.  Use this rather than calling 'eval()' directly.
197
	// description: Placed in a separate function to minimize size of trapped evaluation context.
197
	// description: Placed in a separate function to minimize size of trapped evaluation context.
198
	// note:
198
	// note:
199
	//	 - JSC eval() takes an optional second argument which can be 'unsafe'.
199
	//	 - JSC eval() takes an optional second argument which can be 'unsafe'.
200
	//	 - Mozilla/SpiderMonkey eval() takes an optional second argument which is the
200
	//	 - Mozilla/SpiderMonkey eval() takes an optional second argument which is the
201
	//  	 scope object for new symbols.
201
	//  	 scope object for new symbols.
202
	return dj_global.eval ? dj_global.eval(scriptFragment) : eval(scriptFragment); 	// mixed
202
	return dj_global.eval ? dj_global.eval(scriptFragment) : eval(scriptFragment); 	// mixed
203
}
203
}
204
 
204
 
205
dojo.unimplemented = function(/*String*/ funcname, /*String?*/ extra){
205
dojo.unimplemented = function(/*String*/ funcname, /*String?*/ extra){
206
	// summary: Throw an exception because some function is not implemented.
206
	// summary: Throw an exception because some function is not implemented.
207
	// extra: Text to append to the exception message.
207
	// extra: Text to append to the exception message.
208
	var message = "'" + funcname + "' not implemented";
208
	var message = "'" + funcname + "' not implemented";
209
	if (extra != null) { message += " " + extra; }
209
	if (extra != null) { message += " " + extra; }
210
	dojo.raise(message);
210
	dojo.raise(message);
211
}
211
}
212
 
212
 
213
dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){
213
dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){
214
	// summary: Log a debug message to indicate that a behavior has been deprecated.
214
	// summary: Log a debug message to indicate that a behavior has been deprecated.
215
	// extra: Text to append to the message.
215
	// extra: Text to append to the message.
216
	// removal: Text to indicate when in the future the behavior will be removed.
216
	// removal: Text to indicate when in the future the behavior will be removed.
217
	var message = "DEPRECATED: " + behaviour;
217
	var message = "DEPRECATED: " + behaviour;
218
	if(extra){ message += " " + extra; }
218
	if(extra){ message += " " + extra; }
219
	if(removal){ message += " -- will be removed in version: " + removal; }
219
	if(removal){ message += " -- will be removed in version: " + removal; }
220
	dojo.debug(message);
220
	dojo.debug(message);
221
}
221
}
222
 
222
 
223
dojo.render = (function(){
223
dojo.render = (function(){
224
	//TODOC: HOW TO DOC THIS?
224
	//TODOC: HOW TO DOC THIS?
225
	// summary: Details rendering support, OS and browser of the current environment.
225
	// summary: Details rendering support, OS and browser of the current environment.
226
	// TODOC: is this something many folks will interact with?  If so, we should doc the structure created...
226
	// TODOC: is this something many folks will interact with?  If so, we should doc the structure created...
227
	function vscaffold(prefs, names){
227
	function vscaffold(prefs, names){
228
		var tmp = {
228
		var tmp = {
229
			capable: false,
229
			capable: false,
230
			support: {
230
			support: {
231
				builtin: false,
231
				builtin: false,
232
				plugin: false
232
				plugin: false
233
			},
233
			},
234
			prefixes: prefs
234
			prefixes: prefs
235
		};
235
		};
236
		for(var i=0; i<names.length; i++){
236
		for(var i=0; i<names.length; i++){
237
			tmp[names[i]] = false;
237
			tmp[names[i]] = false;
238
		}
238
		}
239
		return tmp;
239
		return tmp;
240
	}
240
	}
241
 
241
 
242
	return {
242
	return {
243
		name: "",
243
		name: "",
244
		ver: dojo.version,
244
		ver: dojo.version,
245
		os: { win: false, linux: false, osx: false },
245
		os: { win: false, linux: false, osx: false },
246
		html: vscaffold(["html"], ["ie", "opera", "khtml", "safari", "moz"]),
246
		html: vscaffold(["html"], ["ie", "opera", "khtml", "safari", "moz"]),
247
		svg: vscaffold(["svg"], ["corel", "adobe", "batik"]),
247
		svg: vscaffold(["svg"], ["corel", "adobe", "batik"]),
248
		vml: vscaffold(["vml"], ["ie"]),
248
		vml: vscaffold(["vml"], ["ie"]),
249
		swf: vscaffold(["Swf", "Flash", "Mm"], ["mm"]),
249
		swf: vscaffold(["Swf", "Flash", "Mm"], ["mm"]),
250
		swt: vscaffold(["Swt"], ["ibm"])
250
		swt: vscaffold(["Swt"], ["ibm"])
251
	};
251
	};
252
})();
252
})();
253
 
253
 
254
// ****************************************************************
254
// ****************************************************************
255
// dojo.hostenv methods that must be defined in hostenv_*.js
255
// dojo.hostenv methods that must be defined in hostenv_*.js
256
// ****************************************************************
256
// ****************************************************************
257
 
257
 
258
/**
258
/**
259
 * The interface definining the interaction with the EcmaScript host environment.
259
 * The interface definining the interaction with the EcmaScript host environment.
260
*/
260
*/
261
 
261
 
262
/*
262
/*
263
 * None of these methods should ever be called directly by library users.
263
 * None of these methods should ever be called directly by library users.
264
 * Instead public methods such as loadModule should be called instead.
264
 * Instead public methods such as loadModule should be called instead.
265
 */
265
 */
266
dojo.hostenv = (function(){
266
dojo.hostenv = (function(){
267
	// TODOC:  HOW TO DOC THIS?
267
	// TODOC:  HOW TO DOC THIS?
268
	// summary: Provides encapsulation of behavior that changes across different 'host environments'
268
	// summary: Provides encapsulation of behavior that changes across different 'host environments'
269
	//			(different browsers, server via Rhino, etc).
269
	//			(different browsers, server via Rhino, etc).
270
	// description: None of these methods should ever be called directly by library users.
270
	// description: None of these methods should ever be called directly by library users.
271
	//				Use public methods such as 'loadModule' instead.
271
	//				Use public methods such as 'loadModule' instead.
272
 
272
 
273
	// default configuration options
273
	// default configuration options
274
	var config = {
274
	var config = {
275
		isDebug: false,
275
		isDebug: false,
276
		allowQueryConfig: false,
276
		allowQueryConfig: false,
277
		baseScriptUri: "",
277
		baseScriptUri: "",
278
		baseRelativePath: "",
278
		baseRelativePath: "",
279
		libraryScriptUri: "",
279
		libraryScriptUri: "",
280
		iePreventClobber: false,
280
		iePreventClobber: false,
281
		ieClobberMinimal: true,
281
		ieClobberMinimal: true,
282
		preventBackButtonFix: true,
282
		preventBackButtonFix: true,
283
		delayMozLoadingFix: false,
283
		delayMozLoadingFix: false,
284
		searchIds: [],
284
		searchIds: [],
285
		parseWidgets: true
285
		parseWidgets: true
286
	};
286
	};
287
 
287
 
288
	if (typeof djConfig == "undefined") { djConfig = config; }
288
	if (typeof djConfig == "undefined") { djConfig = config; }
289
	else {
289
	else {
290
		for (var option in config) {
290
		for (var option in config) {
291
			if (typeof djConfig[option] == "undefined") {
291
			if (typeof djConfig[option] == "undefined") {
292
				djConfig[option] = config[option];
292
				djConfig[option] = config[option];
293
			}
293
			}
294
		}
294
		}
295
	}
295
	}
296
 
296
 
297
	return {
297
	return {
298
		name_: '(unset)',
298
		name_: '(unset)',
299
		version_: '(unset)',
299
		version_: '(unset)',
300
 
300
 
301
 
301
 
302
		getName: function(){
302
		getName: function(){
303
			// sumary: Return the name of the host environment.
303
			// sumary: Return the name of the host environment.
304
			return this.name_; 	// String
304
			return this.name_; 	// String
305
		},
305
		},
306
 
306
 
307
 
307
 
308
		getVersion: function(){
308
		getVersion: function(){
309
			// summary: Return the version of the hostenv.
309
			// summary: Return the version of the hostenv.
310
			return this.version_; // String
310
			return this.version_; // String
311
		},
311
		},
312
 
312
 
313
		getText: function(/*String*/ uri){
313
		getText: function(/*String*/ uri){
314
			// summary:	Read the plain/text contents at the specified 'uri'.
314
			// summary:	Read the plain/text contents at the specified 'uri'.
315
			// description:
315
			// description:
316
			//			If 'getText()' is not implemented, then it is necessary to override
316
			//			If 'getText()' is not implemented, then it is necessary to override
317
			//			'loadUri()' with an implementation that doesn't rely on it.
317
			//			'loadUri()' with an implementation that doesn't rely on it.
318
 
318
 
319
			dojo.unimplemented('getText', "uri=" + uri);
319
			dojo.unimplemented('getText', "uri=" + uri);
320
		}
320
		}
321
	};
321
	};
322
})();
322
})();
323
 
323
 
324
 
324
 
325
dojo.hostenv.getBaseScriptUri = function(){
325
dojo.hostenv.getBaseScriptUri = function(){
326
	// summary: Return the base script uri that other scripts are found relative to.
326
	// summary: Return the base script uri that other scripts are found relative to.
327
	// TODOC: HUH?  This comment means nothing to me.  What other scripts? Is this the path to other dojo libraries?
327
	// TODOC: HUH?  This comment means nothing to me.  What other scripts? Is this the path to other dojo libraries?
328
	//		MAYBE:  Return the base uri to scripts in the dojo library.	 ???
328
	//		MAYBE:  Return the base uri to scripts in the dojo library.	 ???
329
	// return: Empty string or a path ending in '/'.
329
	// return: Empty string or a path ending in '/'.
330
	if(djConfig.baseScriptUri.length){
330
	if(djConfig.baseScriptUri.length){
331
		return djConfig.baseScriptUri;
331
		return djConfig.baseScriptUri;
332
	}
332
	}
333
 
333
 
334
	// MOW: Why not:
334
	// MOW: Why not:
335
	//			uri = djConfig.libraryScriptUri || djConfig.baseRelativePath
335
	//			uri = djConfig.libraryScriptUri || djConfig.baseRelativePath
336
	//		??? Why 'new String(...)'
336
	//		??? Why 'new String(...)'
337
	var uri = new String(djConfig.libraryScriptUri||djConfig.baseRelativePath);
337
	var uri = new String(djConfig.libraryScriptUri||djConfig.baseRelativePath);
338
	if (!uri) { dojo.raise("Nothing returned by getLibraryScriptUri(): " + uri); }
338
	if (!uri) { dojo.raise("Nothing returned by getLibraryScriptUri(): " + uri); }
339
 
339
 
340
	// MOW: uri seems to not be actually used.  Seems to be hard-coding to djConfig.baseRelativePath... ???
340
	// MOW: uri seems to not be actually used.  Seems to be hard-coding to djConfig.baseRelativePath... ???
341
	var lastslash = uri.lastIndexOf('/');		// MOW ???
341
	var lastslash = uri.lastIndexOf('/');		// MOW ???
342
	djConfig.baseScriptUri = djConfig.baseRelativePath;
342
	djConfig.baseScriptUri = djConfig.baseRelativePath;
343
	return djConfig.baseScriptUri;	// String
343
	return djConfig.baseScriptUri;	// String
344
}
344
}
345
 
345
 
346
/*
346
/*
347
 * loader.js - A bootstrap module.  Runs before the hostenv_*.js file. Contains all of the package loading methods.
347
 * loader.js - A bootstrap module.  Runs before the hostenv_*.js file. Contains all of the package loading methods.
348
 */
348
 */
349
 
349
 
350
//A semi-colon is at the start of the line because after doing a build, this function definition
350
//A semi-colon is at the start of the line because after doing a build, this function definition
351
//get compressed onto the same line as the last line in bootstrap1.js. That list line is just a
351
//get compressed onto the same line as the last line in bootstrap1.js. That list line is just a
352
//curly bracket, and the browser complains about that syntax. The semicolon fixes it. Putting it
352
//curly bracket, and the browser complains about that syntax. The semicolon fixes it. Putting it
353
//here instead of at the end of bootstrap1.js, since it is more of an issue for this file, (using
353
//here instead of at the end of bootstrap1.js, since it is more of an issue for this file, (using
354
//the closure), and bootstrap1.js could change in the future.
354
//the closure), and bootstrap1.js could change in the future.
355
;(function(){
355
;(function(){
356
	//Additional properties for dojo.hostenv
356
	//Additional properties for dojo.hostenv
357
	var _addHostEnv = {
357
	var _addHostEnv = {
358
		pkgFileName: "__package__",
358
		pkgFileName: "__package__",
359
	
359
	
360
		// for recursion protection
360
		// for recursion protection
361
		loading_modules_: {},
361
		loading_modules_: {},
362
		loaded_modules_: {},
362
		loaded_modules_: {},
363
		addedToLoadingCount: [],
363
		addedToLoadingCount: [],
364
		removedFromLoadingCount: [],
364
		removedFromLoadingCount: [],
365
	
365
	
366
		inFlightCount: 0,
366
		inFlightCount: 0,
367
	
367
	
368
		// FIXME: it should be possible to pull module prefixes in from djConfig
368
		// FIXME: it should be possible to pull module prefixes in from djConfig
369
		modulePrefixes_: {
369
		modulePrefixes_: {
370
			dojo: {name: "dojo", value: "src"}
370
			dojo: {name: "dojo", value: "src"}
371
		},
371
		},
372
 
372
 
373
		setModulePrefix: function(/*String*/module, /*String*/prefix){
373
		setModulePrefix: function(/*String*/module, /*String*/prefix){
374
			// summary: establishes module/prefix pair
374
			// summary: establishes module/prefix pair
375
			this.modulePrefixes_[module] = {name: module, value: prefix};
375
			this.modulePrefixes_[module] = {name: module, value: prefix};
376
		},
376
		},
377
 
377
 
378
		moduleHasPrefix: function(/*String*/module){
378
		moduleHasPrefix: function(/*String*/module){
379
			// summary: checks to see if module has been established
379
			// summary: checks to see if module has been established
380
			var mp = this.modulePrefixes_;
380
			var mp = this.modulePrefixes_;
381
			return Boolean(mp[module] && mp[module].value); // Boolean
381
			return Boolean(mp[module] && mp[module].value); // Boolean
382
		},
382
		},
383
 
383
 
384
		getModulePrefix: function(/*String*/module){
384
		getModulePrefix: function(/*String*/module){
385
			// summary: gets the prefix associated with module
385
			// summary: gets the prefix associated with module
386
			if(this.moduleHasPrefix(module)){
386
			if(this.moduleHasPrefix(module)){
387
				return this.modulePrefixes_[module].value; // String
387
				return this.modulePrefixes_[module].value; // String
388
			}
388
			}
389
			return module; // String
389
			return module; // String
390
		},
390
		},
391
 
391
 
392
		getTextStack: [],
392
		getTextStack: [],
393
		loadUriStack: [],
393
		loadUriStack: [],
394
		loadedUris: [],
394
		loadedUris: [],
395
	
395
	
396
		//WARNING: This variable is referenced by packages outside of bootstrap: FloatingPane.js and undo/browser.js
396
		//WARNING: This variable is referenced by packages outside of bootstrap: FloatingPane.js and undo/browser.js
397
		post_load_: false,
397
		post_load_: false,
398
		
398
		
399
		//Egad! Lots of test files push on this directly instead of using dojo.addOnLoad.
399
		//Egad! Lots of test files push on this directly instead of using dojo.addOnLoad.
400
		modulesLoadedListeners: [],
400
		modulesLoadedListeners: [],
401
		unloadListeners: [],
401
		unloadListeners: [],
402
		loadNotifying: false
402
		loadNotifying: false
403
	};
403
	};
404
	
404
	
405
	//Add all of these properties to dojo.hostenv
405
	//Add all of these properties to dojo.hostenv
406
	for(var param in _addHostEnv){
406
	for(var param in _addHostEnv){
407
		dojo.hostenv[param] = _addHostEnv[param];
407
		dojo.hostenv[param] = _addHostEnv[param];
408
	}
408
	}
409
})();
409
})();
410
 
410
 
411
dojo.hostenv.loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
411
dojo.hostenv.loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
412
// summary:
412
// summary:
413
//	Load a Javascript module given a relative path
413
//	Load a Javascript module given a relative path
414
//
414
//
415
// description:
415
// description:
416
//	Loads and interprets the script located at relpath, which is relative to the
416
//	Loads and interprets the script located at relpath, which is relative to the
417
//	script root directory.  If the script is found but its interpretation causes
417
//	script root directory.  If the script is found but its interpretation causes
418
//	a runtime exception, that exception is not caught by us, so the caller will
418
//	a runtime exception, that exception is not caught by us, so the caller will
419
//	see it.  We return a true value if and only if the script is found.
419
//	see it.  We return a true value if and only if the script is found.
420
//
420
//
421
//	For now, we do not have an implementation of a true search path.  We
421
//	For now, we do not have an implementation of a true search path.  We
422
//	consider only the single base script uri, as returned by getBaseScriptUri().
422
//	consider only the single base script uri, as returned by getBaseScriptUri().
423
//
423
//
424
// relpath: A relative path to a script (no leading '/', and typically
424
// relpath: A relative path to a script (no leading '/', and typically
425
// 	ending in '.js').
425
// 	ending in '.js').
426
// module: A module whose existance to check for after loading a path.
426
// module: A module whose existance to check for after loading a path.
427
//	Can be used to determine success or failure of the load.
427
//	Can be used to determine success or failure of the load.
428
// cb: a callback function to pass the result of evaluating the script
428
// cb: a callback function to pass the result of evaluating the script
429
 
429
 
430
	var uri;
430
	var uri;
431
	if(relpath.charAt(0) == '/' || relpath.match(/^\w+:/)){
431
	if(relpath.charAt(0) == '/' || relpath.match(/^\w+:/)){
432
		// dojo.raise("relpath '" + relpath + "'; must be relative");
432
		// dojo.raise("relpath '" + relpath + "'; must be relative");
433
		uri = relpath;
433
		uri = relpath;
434
	}else{
434
	}else{
435
		uri = this.getBaseScriptUri() + relpath;
435
		uri = this.getBaseScriptUri() + relpath;
436
	}
436
	}
437
	if(djConfig.cacheBust && dojo.render.html.capable){
437
	if(djConfig.cacheBust && dojo.render.html.capable){
438
		uri += "?" + String(djConfig.cacheBust).replace(/\W+/g,"");
438
		uri += "?" + String(djConfig.cacheBust).replace(/\W+/g,"");
439
	}
439
	}
440
	try{
440
	try{
441
		return !module ? this.loadUri(uri, cb) : this.loadUriAndCheck(uri, module, cb); // Boolean
441
		return !module ? this.loadUri(uri, cb) : this.loadUriAndCheck(uri, module, cb); // Boolean
442
	}catch(e){
442
	}catch(e){
443
		dojo.debug(e);
443
		dojo.debug(e);
444
		return false; // Boolean
444
		return false; // Boolean
445
	}
445
	}
446
}
446
}
447
 
447
 
448
dojo.hostenv.loadUri = function(/*String (URL)*/uri, /*Function?*/cb){
448
dojo.hostenv.loadUri = function(/*String (URL)*/uri, /*Function?*/cb){
449
// summary:
449
// summary:
450
//	Loads JavaScript from a URI
450
//	Loads JavaScript from a URI
451
//
451
//
452
// description:
452
// description:
453
//	Reads the contents of the URI, and evaluates the contents.  This is used to load modules as well
453
//	Reads the contents of the URI, and evaluates the contents.  This is used to load modules as well
454
//	as resource bundles.  Returns true if it succeeded. Returns false if the URI reading failed.
454
//	as resource bundles.  Returns true if it succeeded. Returns false if the URI reading failed.
455
//	Throws if the evaluation throws.
455
//	Throws if the evaluation throws.
456
//
456
//
457
// uri: a uri which points at the script to be loaded
457
// uri: a uri which points at the script to be loaded
458
// cb: a callback function to process the result of evaluating the script as an expression, typically
458
// cb: a callback function to process the result of evaluating the script as an expression, typically
459
//	used by the resource bundle loader to load JSON-style resources
459
//	used by the resource bundle loader to load JSON-style resources
460
 
460
 
461
	if(this.loadedUris[uri]){
461
	if(this.loadedUris[uri]){
462
		return true; // Boolean
462
		return true; // Boolean
463
	}
463
	}
464
	var contents = this.getText(uri, null, true);
464
	var contents = this.getText(uri, null, true);
465
	if(!contents){ return false; } // Boolean
465
	if(!contents){ return false; } // Boolean
466
	this.loadedUris[uri] = true;
466
	this.loadedUris[uri] = true;
467
	if(cb){ contents = '('+contents+')'; }
467
	if(cb){ contents = '('+contents+')'; }
468
	var value = dj_eval(contents);
468
	var value = dj_eval(contents);
469
	if(cb){ cb(value); }
469
	if(cb){ cb(value); }
470
	return true; // Boolean
470
	return true; // Boolean
471
}
471
}
472
 
472
 
473
// FIXME: probably need to add logging to this method
473
// FIXME: probably need to add logging to this method
474
dojo.hostenv.loadUriAndCheck = function(/*String (URL)*/uri, /*String*/moduleName, /*Function?*/cb){
474
dojo.hostenv.loadUriAndCheck = function(/*String (URL)*/uri, /*String*/moduleName, /*Function?*/cb){
475
	// summary: calls loadUri then findModule and returns true if both succeed
475
	// summary: calls loadUri then findModule and returns true if both succeed
476
	var ok = true;
476
	var ok = true;
477
	try{
477
	try{
478
		ok = this.loadUri(uri, cb);
478
		ok = this.loadUri(uri, cb);
479
	}catch(e){
479
	}catch(e){
480
		dojo.debug("failed loading ", uri, " with error: ", e);
480
		dojo.debug("failed loading ", uri, " with error: ", e);
481
	}
481
	}
482
	return Boolean(ok && this.findModule(moduleName, false)); // Boolean
482
	return Boolean(ok && this.findModule(moduleName, false)); // Boolean
483
}
483
}
484
 
484
 
485
dojo.loaded = function(){ }
485
dojo.loaded = function(){ }
486
dojo.unloaded = function(){ }
486
dojo.unloaded = function(){ }
487
 
487
 
488
dojo.hostenv.loaded = function(){
488
dojo.hostenv.loaded = function(){
489
	this.loadNotifying = true;
489
	this.loadNotifying = true;
490
	this.post_load_ = true;
490
	this.post_load_ = true;
491
	var mll = this.modulesLoadedListeners;
491
	var mll = this.modulesLoadedListeners;
492
	for(var x=0; x<mll.length; x++){
492
	for(var x=0; x<mll.length; x++){
493
		mll[x]();
493
		mll[x]();
494
	}
494
	}
495
 
495
 
496
	//Clear listeners so new ones can be added
496
	//Clear listeners so new ones can be added
497
	//For other xdomain package loads after the initial load.
497
	//For other xdomain package loads after the initial load.
498
	this.modulesLoadedListeners = [];
498
	this.modulesLoadedListeners = [];
499
	this.loadNotifying = false;
499
	this.loadNotifying = false;
500
 
500
 
501
	dojo.loaded();
501
	dojo.loaded();
502
}
502
}
503
 
503
 
504
dojo.hostenv.unloaded = function(){
504
dojo.hostenv.unloaded = function(){
505
	var mll = this.unloadListeners;
505
	var mll = this.unloadListeners;
506
	while(mll.length){
506
	while(mll.length){
507
		(mll.pop())();
507
		(mll.pop())();
508
	}
508
	}
509
	dojo.unloaded();
509
	dojo.unloaded();
510
}
510
}
511
 
511
 
512
dojo.addOnLoad = function(/*Object?*/obj, /*String|Function*/functionName) {
512
dojo.addOnLoad = function(/*Object?*/obj, /*String|Function*/functionName) {
513
// summary:
513
// summary:
514
//	Registers a function to be triggered after the DOM has finished loading 
514
//	Registers a function to be triggered after the DOM has finished loading 
515
//	and widgets declared in markup have been instantiated.  Images and CSS files
515
//	and widgets declared in markup have been instantiated.  Images and CSS files
516
//	may or may not have finished downloading when the specified function is called.
516
//	may or may not have finished downloading when the specified function is called.
517
//	(Note that widgets' CSS and HTML code is guaranteed to be downloaded before said
517
//	(Note that widgets' CSS and HTML code is guaranteed to be downloaded before said
518
//	widgets are instantiated.)
518
//	widgets are instantiated.)
519
//
519
//
520
// usage:
520
// usage:
521
//	dojo.addOnLoad(functionPointer)
521
//	dojo.addOnLoad(functionPointer)
522
//	dojo.addOnLoad(object, "functionName")
522
//	dojo.addOnLoad(object, "functionName")
523
 
523
 
524
	var dh = dojo.hostenv;
524
	var dh = dojo.hostenv;
525
	if(arguments.length == 1) {
525
	if(arguments.length == 1) {
526
		dh.modulesLoadedListeners.push(obj);
526
		dh.modulesLoadedListeners.push(obj);
527
	} else if(arguments.length > 1) {
527
	} else if(arguments.length > 1) {
528
		dh.modulesLoadedListeners.push(function() {
528
		dh.modulesLoadedListeners.push(function() {
529
			obj[functionName]();
529
			obj[functionName]();
530
		});
530
		});
531
	}
531
	}
532
 
532
 
533
	//Added for xdomain loading. dojo.addOnLoad is used to
533
	//Added for xdomain loading. dojo.addOnLoad is used to
534
	//indicate callbacks after doing some dojo.require() statements.
534
	//indicate callbacks after doing some dojo.require() statements.
535
	//In the xdomain case, if all the requires are loaded (after initial
535
	//In the xdomain case, if all the requires are loaded (after initial
536
	//page load), then immediately call any listeners.
536
	//page load), then immediately call any listeners.
537
	if(dh.post_load_ && dh.inFlightCount == 0 && !dh.loadNotifying){
537
	if(dh.post_load_ && dh.inFlightCount == 0 && !dh.loadNotifying){
538
		dh.callLoaded();
538
		dh.callLoaded();
539
	}
539
	}
540
}
540
}
541
 
541
 
542
dojo.addOnUnload = function(/*Object?*/obj, /*String|Function?*/functionName){
542
dojo.addOnUnload = function(/*Object?*/obj, /*String|Function?*/functionName){
543
// summary: registers a function to be triggered when the page unloads
543
// summary: registers a function to be triggered when the page unloads
544
//
544
//
545
// usage:
545
// usage:
546
//	dojo.addOnLoad(functionPointer)
546
//	dojo.addOnLoad(functionPointer)
547
//	dojo.addOnLoad(object, "functionName")
547
//	dojo.addOnLoad(object, "functionName")
548
	var dh = dojo.hostenv;
548
	var dh = dojo.hostenv;
549
	if(arguments.length == 1){
549
	if(arguments.length == 1){
550
		dh.unloadListeners.push(obj);
550
		dh.unloadListeners.push(obj);
551
	} else if(arguments.length > 1) {
551
	} else if(arguments.length > 1) {
552
		dh.unloadListeners.push(function() {
552
		dh.unloadListeners.push(function() {
553
			obj[functionName]();
553
			obj[functionName]();
554
		});
554
		});
555
	}
555
	}
556
}
556
}
557
 
557
 
558
dojo.hostenv.modulesLoaded = function(){
558
dojo.hostenv.modulesLoaded = function(){
559
	if(this.post_load_){ return; }
559
	if(this.post_load_){ return; }
560
	if(this.loadUriStack.length==0 && this.getTextStack.length==0){
560
	if(this.loadUriStack.length==0 && this.getTextStack.length==0){
561
		if(this.inFlightCount > 0){ 
561
		if(this.inFlightCount > 0){ 
562
			dojo.debug("files still in flight!");
562
			dojo.debug("files still in flight!");
563
			return;
563
			return;
564
		}
564
		}
565
		dojo.hostenv.callLoaded();
565
		dojo.hostenv.callLoaded();
566
	}
566
	}
567
}
567
}
568
 
568
 
569
dojo.hostenv.callLoaded = function(){
569
dojo.hostenv.callLoaded = function(){
570
	//The "object" check is for IE, and the other opera check fixes an issue
570
	//The "object" check is for IE, and the other opera check fixes an issue
571
	//in Opera where it could not find the body element in some widget test cases.
571
	//in Opera where it could not find the body element in some widget test cases.
572
	//For 0.9, maybe route all browsers through the setTimeout (need protection
572
	//For 0.9, maybe route all browsers through the setTimeout (need protection
573
	//still for non-browser environments though). This might also help the issue with
573
	//still for non-browser environments though). This might also help the issue with
574
	//FF 2.0 and freezing issues where we try to do sync xhr while background css images
574
	//FF 2.0 and freezing issues where we try to do sync xhr while background css images
575
	//are being loaded (trac #2572)? Consider for 0.9.
575
	//are being loaded (trac #2572)? Consider for 0.9.
576
	if(typeof setTimeout == "object" || (djConfig["useXDomain"] && dojo.render.html.opera)){
576
	if(typeof setTimeout == "object" || (djConfig["useXDomain"] && dojo.render.html.opera)){
577
		setTimeout("dojo.hostenv.loaded();", 0);
577
		setTimeout("dojo.hostenv.loaded();", 0);
578
	}else{
578
	}else{
579
		dojo.hostenv.loaded();
579
		dojo.hostenv.loaded();
580
	}
580
	}
581
}
581
}
582
 
582
 
583
dojo.hostenv.getModuleSymbols = function(/*String*/modulename){
583
dojo.hostenv.getModuleSymbols = function(/*String*/modulename){
584
// summary:
584
// summary:
585
//	Converts a module name in dotted JS notation to an array representing the path in the source tree
585
//	Converts a module name in dotted JS notation to an array representing the path in the source tree
586
	var syms = modulename.split(".");
586
	var syms = modulename.split(".");
587
	for(var i = syms.length; i>0; i--){
587
	for(var i = syms.length; i>0; i--){
588
		var parentModule = syms.slice(0, i).join(".");
588
		var parentModule = syms.slice(0, i).join(".");
589
		if((i==1) && !this.moduleHasPrefix(parentModule)){		
589
		if((i==1) && !this.moduleHasPrefix(parentModule)){		
590
			// Support default module directory (sibling of dojo) for top-level modules 
590
			// Support default module directory (sibling of dojo) for top-level modules 
591
			syms[0] = "../" + syms[0];
591
			syms[0] = "../" + syms[0];
592
		}else{
592
		}else{
593
			var parentModulePath = this.getModulePrefix(parentModule);
593
			var parentModulePath = this.getModulePrefix(parentModule);
594
			if(parentModulePath != parentModule){
594
			if(parentModulePath != parentModule){
595
				syms.splice(0, i, parentModulePath);
595
				syms.splice(0, i, parentModulePath);
596
				break;
596
				break;
597
			}
597
			}
598
		}
598
		}
599
	}
599
	}
600
	return syms; // Array
600
	return syms; // Array
601
}
601
}
602
 
602
 
603
dojo.hostenv._global_omit_module_check = false;
603
dojo.hostenv._global_omit_module_check = false;
604
dojo.hostenv.loadModule = function(/*String*/moduleName, /*Boolean?*/exactOnly, /*Boolean?*/omitModuleCheck){
604
dojo.hostenv.loadModule = function(/*String*/moduleName, /*Boolean?*/exactOnly, /*Boolean?*/omitModuleCheck){
605
// summary:
605
// summary:
606
//	loads a Javascript module from the appropriate URI
606
//	loads a Javascript module from the appropriate URI
607
//
607
//
608
// description:
608
// description:
609
//	loadModule("A.B") first checks to see if symbol A.B is defined. 
609
//	loadModule("A.B") first checks to see if symbol A.B is defined. 
610
//	If it is, it is simply returned (nothing to do).
610
//	If it is, it is simply returned (nothing to do).
611
//	
611
//	
612
//	If it is not defined, it will look for "A/B.js" in the script root directory,
612
//	If it is not defined, it will look for "A/B.js" in the script root directory,
613
//	followed by "A.js".
613
//	followed by "A.js".
614
//	
614
//	
615
//	It throws if it cannot find a file to load, or if the symbol A.B is not
615
//	It throws if it cannot find a file to load, or if the symbol A.B is not
616
//	defined after loading.
616
//	defined after loading.
617
//	
617
//	
618
//	It returns the object A.B.
618
//	It returns the object A.B.
619
//	
619
//	
620
//	This does nothing about importing symbols into the current package.
620
//	This does nothing about importing symbols into the current package.
621
//	It is presumed that the caller will take care of that. For example, to import
621
//	It is presumed that the caller will take care of that. For example, to import
622
//	all symbols:
622
//	all symbols:
623
//	
623
//	
624
//	   with (dojo.hostenv.loadModule("A.B")) {
624
//	   with (dojo.hostenv.loadModule("A.B")) {
625
//	      ...
625
//	      ...
626
//	   }
626
//	   }
627
//	
627
//	
628
//	And to import just the leaf symbol:
628
//	And to import just the leaf symbol:
629
//	
629
//	
630
//	   var B = dojo.hostenv.loadModule("A.B");
630
//	   var B = dojo.hostenv.loadModule("A.B");
631
//	   ...
631
//	   ...
632
//	
632
//	
633
//	dj_load is an alias for dojo.hostenv.loadModule
633
//	dj_load is an alias for dojo.hostenv.loadModule
634
 
634
 
635
	if(!moduleName){ return; }
635
	if(!moduleName){ return; }
636
	omitModuleCheck = this._global_omit_module_check || omitModuleCheck;
636
	omitModuleCheck = this._global_omit_module_check || omitModuleCheck;
637
	var module = this.findModule(moduleName, false);
637
	var module = this.findModule(moduleName, false);
638
	if(module){
638
	if(module){
639
		return module;
639
		return module;
640
	}
640
	}
641
 
641
 
642
	// protect against infinite recursion from mutual dependencies
642
	// protect against infinite recursion from mutual dependencies
643
	if(dj_undef(moduleName, this.loading_modules_)){
643
	if(dj_undef(moduleName, this.loading_modules_)){
644
		this.addedToLoadingCount.push(moduleName);
644
		this.addedToLoadingCount.push(moduleName);
645
	}
645
	}
646
	this.loading_modules_[moduleName] = 1;
646
	this.loading_modules_[moduleName] = 1;
647
 
647
 
648
	// convert periods to slashes
648
	// convert periods to slashes
649
	var relpath = moduleName.replace(/\./g, '/') + '.js';
649
	var relpath = moduleName.replace(/\./g, '/') + '.js';
650
 
650
 
651
	var nsyms = moduleName.split(".");
651
	var nsyms = moduleName.split(".");
652
	
652
	
653
	// this line allowed loading of a module manifest as if it were a namespace
653
	// this line allowed loading of a module manifest as if it were a namespace
654
	// it's an interesting idea, but shouldn't be combined with 'namespaces' proper
654
	// it's an interesting idea, but shouldn't be combined with 'namespaces' proper
655
	// and leads to unwanted dependencies
655
	// and leads to unwanted dependencies
656
	// the effect can be achieved in other (albeit less-flexible) ways now, so I am
656
	// the effect can be achieved in other (albeit less-flexible) ways now, so I am
657
	// removing this pending further design work
657
	// removing this pending further design work
658
	// perhaps we can explicitly define this idea of a 'module manifest', and subclass
658
	// perhaps we can explicitly define this idea of a 'module manifest', and subclass
659
	// 'namespace manifest' from that
659
	// 'namespace manifest' from that
660
	//dojo.getNamespace(nsyms[0]);
660
	//dojo.getNamespace(nsyms[0]);
661
 
661
 
662
	var syms = this.getModuleSymbols(moduleName);
662
	var syms = this.getModuleSymbols(moduleName);
663
	var startedRelative = ((syms[0].charAt(0) != '/') && !syms[0].match(/^\w+:/));
663
	var startedRelative = ((syms[0].charAt(0) != '/') && !syms[0].match(/^\w+:/));
664
	var last = syms[syms.length - 1];
664
	var last = syms[syms.length - 1];
665
	var ok;
665
	var ok;
666
	// figure out if we're looking for a full package, if so, we want to do
666
	// figure out if we're looking for a full package, if so, we want to do
667
	// things slightly diffrently
667
	// things slightly diffrently
668
	if(last=="*"){
668
	if(last=="*"){
669
		moduleName = nsyms.slice(0, -1).join('.');
669
		moduleName = nsyms.slice(0, -1).join('.');
670
		while(syms.length){
670
		while(syms.length){
671
			syms.pop();
671
			syms.pop();
672
			syms.push(this.pkgFileName);
672
			syms.push(this.pkgFileName);
673
			relpath = syms.join("/") + '.js';
673
			relpath = syms.join("/") + '.js';
674
			if(startedRelative && relpath.charAt(0)=="/"){
674
			if(startedRelative && relpath.charAt(0)=="/"){
675
				relpath = relpath.slice(1);
675
				relpath = relpath.slice(1);
676
			}
676
			}
677
			ok = this.loadPath(relpath, !omitModuleCheck ? moduleName : null);
677
			ok = this.loadPath(relpath, !omitModuleCheck ? moduleName : null);
678
			if(ok){ break; }
678
			if(ok){ break; }
679
			syms.pop();
679
			syms.pop();
680
		}
680
		}
681
	}else{
681
	}else{
682
		relpath = syms.join("/") + '.js';
682
		relpath = syms.join("/") + '.js';
683
		moduleName = nsyms.join('.');
683
		moduleName = nsyms.join('.');
684
		var modArg = !omitModuleCheck ? moduleName : null;
684
		var modArg = !omitModuleCheck ? moduleName : null;
685
		ok = this.loadPath(relpath, modArg);
685
		ok = this.loadPath(relpath, modArg);
686
		if(!ok && !exactOnly){
686
		if(!ok && !exactOnly){
687
			syms.pop();
687
			syms.pop();
688
			while(syms.length){
688
			while(syms.length){
689
				relpath = syms.join('/') + '.js';
689
				relpath = syms.join('/') + '.js';
690
				ok = this.loadPath(relpath, modArg);
690
				ok = this.loadPath(relpath, modArg);
691
				if(ok){ break; }
691
				if(ok){ break; }
692
				syms.pop();
692
				syms.pop();
693
				relpath = syms.join('/') + '/'+this.pkgFileName+'.js';
693
				relpath = syms.join('/') + '/'+this.pkgFileName+'.js';
694
				if(startedRelative && relpath.charAt(0)=="/"){
694
				if(startedRelative && relpath.charAt(0)=="/"){
695
					relpath = relpath.slice(1);
695
					relpath = relpath.slice(1);
696
				}
696
				}
697
				ok = this.loadPath(relpath, modArg);
697
				ok = this.loadPath(relpath, modArg);
698
				if(ok){ break; }
698
				if(ok){ break; }
699
			}
699
			}
700
		}
700
		}
701
 
701
 
702
		if(!ok && !omitModuleCheck){
702
		if(!ok && !omitModuleCheck){
703
			dojo.raise("Could not load '" + moduleName + "'; last tried '" + relpath + "'");
703
			dojo.raise("Could not load '" + moduleName + "'; last tried '" + relpath + "'");
704
		}
704
		}
705
	}
705
	}
706
 
706
 
707
	// check that the symbol was defined
707
	// check that the symbol was defined
708
	//Don't bother if we're doing xdomain (asynchronous) loading.
708
	//Don't bother if we're doing xdomain (asynchronous) loading.
709
	if(!omitModuleCheck && !this["isXDomain"]){
709
	if(!omitModuleCheck && !this["isXDomain"]){
710
		// pass in false so we can give better error
710
		// pass in false so we can give better error
711
		module = this.findModule(moduleName, false);
711
		module = this.findModule(moduleName, false);
712
		if(!module){
712
		if(!module){
713
			dojo.raise("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'"); 
713
			dojo.raise("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'"); 
714
		}
714
		}
715
	}
715
	}
716
 
716
 
717
	return module;
717
	return module;
718
}
718
}
719
 
719
 
720
dojo.hostenv.startPackage = function(/*String*/packageName){
720
dojo.hostenv.startPackage = function(/*String*/packageName){
721
// summary:
721
// summary:
722
//	Creates a JavaScript package
722
//	Creates a JavaScript package
723
//
723
//
724
// description:
724
// description:
725
//	startPackage("A.B") follows the path, and at each level creates a new empty
725
//	startPackage("A.B") follows the path, and at each level creates a new empty
726
//	object or uses what already exists. It returns the result.
726
//	object or uses what already exists. It returns the result.
727
//
727
//
728
// packageName: the package to be created as a String in dot notation
728
// packageName: the package to be created as a String in dot notation
729
 
729
 
730
	//Make sure we have a string.
730
	//Make sure we have a string.
731
	var fullPkgName = String(packageName);
731
	var fullPkgName = String(packageName);
732
	var strippedPkgName = fullPkgName;
732
	var strippedPkgName = fullPkgName;
733
 
733
 
734
	var syms = packageName.split(/\./);
734
	var syms = packageName.split(/\./);
735
	if(syms[syms.length-1]=="*"){
735
	if(syms[syms.length-1]=="*"){
736
		syms.pop();
736
		syms.pop();
737
		strippedPkgName = syms.join(".");
737
		strippedPkgName = syms.join(".");
738
	}
738
	}
739
	var evaledPkg = dojo.evalObjPath(strippedPkgName, true);
739
	var evaledPkg = dojo.evalObjPath(strippedPkgName, true);
740
	this.loaded_modules_[fullPkgName] = evaledPkg;
740
	this.loaded_modules_[fullPkgName] = evaledPkg;
741
	this.loaded_modules_[strippedPkgName] = evaledPkg;
741
	this.loaded_modules_[strippedPkgName] = evaledPkg;
742
	
742
	
743
	return evaledPkg; // Object
743
	return evaledPkg; // Object
744
}
744
}
745
 
745
 
746
dojo.hostenv.findModule = function(/*String*/moduleName, /*Boolean?*/mustExist){
746
dojo.hostenv.findModule = function(/*String*/moduleName, /*Boolean?*/mustExist){
747
// summary:
747
// summary:
748
//	Returns the Object representing the module, if it exists, otherwise null.
748
//	Returns the Object representing the module, if it exists, otherwise null.
749
//
749
//
750
// moduleName A fully qualified module including package name, like 'A.B'.
750
// moduleName A fully qualified module including package name, like 'A.B'.
751
// mustExist Optional, default false. throw instead of returning null
751
// mustExist Optional, default false. throw instead of returning null
752
//	if the module does not currently exist.
752
//	if the module does not currently exist.
753
 
753
 
754
	var lmn = String(moduleName);
754
	var lmn = String(moduleName);
755
 
755
 
756
	if(this.loaded_modules_[lmn]){
756
	if(this.loaded_modules_[lmn]){
757
		return this.loaded_modules_[lmn]; // Object
757
		return this.loaded_modules_[lmn]; // Object
758
	}
758
	}
759
 
759
 
760
	if(mustExist){
760
	if(mustExist){
761
		dojo.raise("no loaded module named '" + moduleName + "'");
761
		dojo.raise("no loaded module named '" + moduleName + "'");
762
	}
762
	}
763
	return null; // null
763
	return null; // null
764
}
764
}
765
 
765
 
766
//Start of old bootstrap2:
766
//Start of old bootstrap2:
767
 
767
 
768
dojo.kwCompoundRequire = function(/*Object containing Arrays*/modMap){
768
dojo.kwCompoundRequire = function(/*Object containing Arrays*/modMap){
769
// description:
769
// description:
770
//	This method taks a "map" of arrays which one can use to optionally load dojo
770
//	This method taks a "map" of arrays which one can use to optionally load dojo
771
//	modules. The map is indexed by the possible dojo.hostenv.name_ values, with
771
//	modules. The map is indexed by the possible dojo.hostenv.name_ values, with
772
//	two additional values: "default" and "common". The items in the "default"
772
//	two additional values: "default" and "common". The items in the "default"
773
//	array will be loaded if none of the other items have been choosen based on
773
//	array will be loaded if none of the other items have been choosen based on
774
//	the hostenv.name_ item. The items in the "common" array will _always_ be
774
//	the hostenv.name_ item. The items in the "common" array will _always_ be
775
//	loaded, regardless of which list is chosen.  Here's how it's normally
775
//	loaded, regardless of which list is chosen.  Here's how it's normally
776
//	called:
776
//	called:
777
//	
777
//	
778
//	dojo.kwCompoundRequire({
778
//	dojo.kwCompoundRequire({
779
//		browser: [
779
//		browser: [
780
//			["foo.bar.baz", true, true], // an example that passes multiple args to loadModule()
780
//			["foo.bar.baz", true, true], // an example that passes multiple args to loadModule()
781
//			"foo.sample.*",
781
//			"foo.sample.*",
782
//			"foo.test,
782
//			"foo.test,
783
//		],
783
//		],
784
//		default: [ "foo.sample.*" ],
784
//		default: [ "foo.sample.*" ],
785
//		common: [ "really.important.module.*" ]
785
//		common: [ "really.important.module.*" ]
786
//	});
786
//	});
787
 
787
 
788
	var common = modMap["common"]||[];
788
	var common = modMap["common"]||[];
789
	var result = modMap[dojo.hostenv.name_] ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);
789
	var result = modMap[dojo.hostenv.name_] ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);
790
 
790
 
791
	for(var x=0; x<result.length; x++){
791
	for(var x=0; x<result.length; x++){
792
		var curr = result[x];
792
		var curr = result[x];
793
		if(curr.constructor == Array){
793
		if(curr.constructor == Array){
794
			dojo.hostenv.loadModule.apply(dojo.hostenv, curr);
794
			dojo.hostenv.loadModule.apply(dojo.hostenv, curr);
795
		}else{
795
		}else{
796
			dojo.hostenv.loadModule(curr);
796
			dojo.hostenv.loadModule(curr);
797
		}
797
		}
798
	}
798
	}
799
}
799
}
800
 
800
 
801
dojo.require = function(/*String*/ resourceName){
801
dojo.require = function(/*String*/ resourceName){
802
	// summary
802
	// summary
803
	//	Ensure that the given resource (ie, javascript
803
	//	Ensure that the given resource (ie, javascript
804
	//	source file) has been loaded.
804
	//	source file) has been loaded.
805
	// description
805
	// description
806
	//	dojo.require() is similar to C's #include command or java's "import" command.
806
	//	dojo.require() is similar to C's #include command or java's "import" command.
807
	//	You call dojo.require() to pull in the resources (ie, javascript source files)
807
	//	You call dojo.require() to pull in the resources (ie, javascript source files)
808
	//	that define the functions you are using. 
808
	//	that define the functions you are using. 
809
	//
809
	//
810
	//	Note that in the case of a build, many resources have already been included
810
	//	Note that in the case of a build, many resources have already been included
811
	//	into dojo.js (ie, many of the javascript source files have been compressed and
811
	//	into dojo.js (ie, many of the javascript source files have been compressed and
812
	//	concatened into dojo.js), so many dojo.require() calls will simply return
812
	//	concatened into dojo.js), so many dojo.require() calls will simply return
813
	//	without downloading anything.
813
	//	without downloading anything.
814
	dojo.hostenv.loadModule.apply(dojo.hostenv, arguments);
814
	dojo.hostenv.loadModule.apply(dojo.hostenv, arguments);
815
}
815
}
816
 
816
 
817
dojo.requireIf = function(/*Boolean*/ condition, /*String*/ resourceName){
817
dojo.requireIf = function(/*Boolean*/ condition, /*String*/ resourceName){
818
	// summary
818
	// summary
819
	//	If the condition is true then call dojo.require() for the specified resource
819
	//	If the condition is true then call dojo.require() for the specified resource
820
	var arg0 = arguments[0];
820
	var arg0 = arguments[0];
821
	if((arg0 === true)||(arg0=="common")||(arg0 && dojo.render[arg0].capable)){
821
	if((arg0 === true)||(arg0=="common")||(arg0 && dojo.render[arg0].capable)){
822
		var args = [];
822
		var args = [];
823
		for (var i = 1; i < arguments.length; i++) { args.push(arguments[i]); }
823
		for (var i = 1; i < arguments.length; i++) { args.push(arguments[i]); }
824
		dojo.require.apply(dojo, args);
824
		dojo.require.apply(dojo, args);
825
	}
825
	}
826
}
826
}
827
 
827
 
828
dojo.requireAfterIf = dojo.requireIf;
828
dojo.requireAfterIf = dojo.requireIf;
829
 
829
 
830
dojo.provide = function(/*String*/ resourceName){
830
dojo.provide = function(/*String*/ resourceName){
831
	// summary
831
	// summary
832
	//	Each javascript source file must have (exactly) one dojo.provide()
832
	//	Each javascript source file must have (exactly) one dojo.provide()
833
	//	call at the top of the file, corresponding to the file name.
833
	//	call at the top of the file, corresponding to the file name.
834
	//	For example, dojo/src/foo.js must have dojo.provide("dojo.foo"); at the top of the file.
834
	//	For example, dojo/src/foo.js must have dojo.provide("dojo.foo"); at the top of the file.
835
	//
835
	//
836
	// description
836
	// description
837
	//	Each javascript source file is called a resource.  When a resource
837
	//	Each javascript source file is called a resource.  When a resource
838
	//	is loaded by the browser, dojo.provide() registers that it has
838
	//	is loaded by the browser, dojo.provide() registers that it has
839
	//	been loaded.
839
	//	been loaded.
840
	//	
840
	//	
841
	//	For backwards compatibility reasons, in addition to registering the resource,
841
	//	For backwards compatibility reasons, in addition to registering the resource,
842
	//	dojo.provide() also ensures that the javascript object for the module exists.  For
842
	//	dojo.provide() also ensures that the javascript object for the module exists.  For
843
	//	example, dojo.provide("dojo.html.common"), in addition to registering that common.js
843
	//	example, dojo.provide("dojo.html.common"), in addition to registering that common.js
844
	//	is a resource for the dojo.html module, will ensure that the dojo.html javascript object
844
	//	is a resource for the dojo.html module, will ensure that the dojo.html javascript object
845
	//	exists, so that calls like dojo.html.foo = function(){ ... } don't fail.
845
	//	exists, so that calls like dojo.html.foo = function(){ ... } don't fail.
846
	//
846
	//
847
	//	In the case of a build (or in the future, a rollup), where multiple javascript source
847
	//	In the case of a build (or in the future, a rollup), where multiple javascript source
848
	//	files are combined into one bigger file (similar to a .lib or .jar file), that file
848
	//	files are combined into one bigger file (similar to a .lib or .jar file), that file
849
	//	will contain multiple dojo.provide() calls, to note that it includes
849
	//	will contain multiple dojo.provide() calls, to note that it includes
850
	//	multiple resources.
850
	//	multiple resources.
851
	return dojo.hostenv.startPackage.apply(dojo.hostenv, arguments);
851
	return dojo.hostenv.startPackage.apply(dojo.hostenv, arguments);
852
}
852
}
853
 
853
 
854
dojo.registerModulePath = function(/*String*/module, /*String*/prefix){
854
dojo.registerModulePath = function(/*String*/module, /*String*/prefix){
855
	// summary: maps a module name to a path
855
	// summary: maps a module name to a path
856
	// description: An unregistered module is given the default path of ../<module>,
856
	// description: An unregistered module is given the default path of ../<module>,
857
	//	relative to Dojo root. For example, module acme is mapped to ../acme.
857
	//	relative to Dojo root. For example, module acme is mapped to ../acme.
858
	//	If you want to use a different module name, use dojo.registerModulePath. 
858
	//	If you want to use a different module name, use dojo.registerModulePath. 
859
	return dojo.hostenv.setModulePrefix(module, prefix);
859
	return dojo.hostenv.setModulePrefix(module, prefix);
860
}
860
}
861
 
861
 
862
if(djConfig["modulePaths"]){
862
if(djConfig["modulePaths"]){
863
	for(var param in djConfig["modulePaths"]){
863
	for(var param in djConfig["modulePaths"]){
864
		dojo.registerModulePath(param, djConfig["modulePaths"][param]);
864
		dojo.registerModulePath(param, djConfig["modulePaths"][param]);
865
	}
865
	}
866
}
866
}
867
 
867
 
868
dojo.setModulePrefix = function(/*String*/module, /*String*/prefix){
868
dojo.setModulePrefix = function(/*String*/module, /*String*/prefix){
869
	// summary: maps a module name to a path
869
	// summary: maps a module name to a path
870
	dojo.deprecated('dojo.setModulePrefix("' + module + '", "' + prefix + '")', "replaced by dojo.registerModulePath", "0.5");
870
	dojo.deprecated('dojo.setModulePrefix("' + module + '", "' + prefix + '")', "replaced by dojo.registerModulePath", "0.5");
871
	return dojo.registerModulePath(module, prefix);
871
	return dojo.registerModulePath(module, prefix);
872
}
872
}
873
 
873
 
874
dojo.exists = function(/*Object*/obj, /*String*/name){
874
dojo.exists = function(/*Object*/obj, /*String*/name){
875
	// summary: determine if an object supports a given method
875
	// summary: determine if an object supports a given method
876
	// description: useful for longer api chains where you have to test each object in the chain
876
	// description: useful for longer api chains where you have to test each object in the chain
877
	var p = name.split(".");
877
	var p = name.split(".");
878
	for(var i = 0; i < p.length; i++){
878
	for(var i = 0; i < p.length; i++){
879
		if(!obj[p[i]]){ return false; } // Boolean
879
		if(!obj[p[i]]){ return false; } // Boolean
880
		obj = obj[p[i]];
880
		obj = obj[p[i]];
881
	}
881
	}
882
	return true; // Boolean
882
	return true; // Boolean
883
}
883
}
884
 
884
 
885
// Localization routines
885
// Localization routines
886
 
886
 
887
dojo.hostenv.normalizeLocale = function(/*String?*/locale){
887
dojo.hostenv.normalizeLocale = function(/*String?*/locale){
888
//	summary:
888
//	summary:
889
//		Returns canonical form of locale, as used by Dojo.  All variants are case-insensitive and are separated by '-'
889
//		Returns canonical form of locale, as used by Dojo.  All variants are case-insensitive and are separated by '-'
890
//		as specified in RFC 3066. If no locale is specified, the user agent's default is returned.
890
//		as specified in RFC 3066. If no locale is specified, the user agent's default is returned.
891
 
891
 
892
	var result = locale ? locale.toLowerCase() : dojo.locale;
892
	var result = locale ? locale.toLowerCase() : dojo.locale;
893
	if(result == "root"){
893
	if(result == "root"){
894
		result = "ROOT";
894
		result = "ROOT";
895
	}
895
	}
896
	return result;// String
896
	return result;// String
897
};
897
};
898
 
898
 
899
dojo.hostenv.searchLocalePath = function(/*String*/locale, /*Boolean*/down, /*Function*/searchFunc){
899
dojo.hostenv.searchLocalePath = function(/*String*/locale, /*Boolean*/down, /*Function*/searchFunc){
900
//	summary:
900
//	summary:
901
//		A helper method to assist in searching for locale-based resources.  Will iterate through
901
//		A helper method to assist in searching for locale-based resources.  Will iterate through
902
//		the variants of a particular locale, either up or down, executing a callback function.
902
//		the variants of a particular locale, either up or down, executing a callback function.
903
//		For example, "en-us" and true will try "en-us" followed by "en" and finally "ROOT".
903
//		For example, "en-us" and true will try "en-us" followed by "en" and finally "ROOT".
904
 
904
 
905
	locale = dojo.hostenv.normalizeLocale(locale);
905
	locale = dojo.hostenv.normalizeLocale(locale);
906
 
906
 
907
	var elements = locale.split('-');
907
	var elements = locale.split('-');
908
	var searchlist = [];
908
	var searchlist = [];
909
	for(var i = elements.length; i > 0; i--){
909
	for(var i = elements.length; i > 0; i--){
910
		searchlist.push(elements.slice(0, i).join('-'));
910
		searchlist.push(elements.slice(0, i).join('-'));
911
	}
911
	}
912
	searchlist.push(false);
912
	searchlist.push(false);
913
	if(down){searchlist.reverse();}
913
	if(down){searchlist.reverse();}
914
 
914
 
915
	for(var j = searchlist.length - 1; j >= 0; j--){
915
	for(var j = searchlist.length - 1; j >= 0; j--){
916
		var loc = searchlist[j] || "ROOT";
916
		var loc = searchlist[j] || "ROOT";
917
		var stop = searchFunc(loc);
917
		var stop = searchFunc(loc);
918
		if(stop){ break; }
918
		if(stop){ break; }
919
	}
919
	}
920
}
920
}
921
 
921
 
922
//These two functions are placed outside of preloadLocalizations
922
//These two functions are placed outside of preloadLocalizations
923
//So that the xd loading can use/override them.
923
//So that the xd loading can use/override them.
924
dojo.hostenv.localesGenerated /***BUILD:localesGenerated***/; // value will be inserted here at build time, if necessary
924
dojo.hostenv.localesGenerated /***BUILD:localesGenerated***/; // value will be inserted here at build time, if necessary
925
 
925
 
926
dojo.hostenv.registerNlsPrefix = function(){
926
dojo.hostenv.registerNlsPrefix = function(){
927
// summary:
927
// summary:
928
//	Register module "nls" to point where Dojo can find pre-built localization files
928
//	Register module "nls" to point where Dojo can find pre-built localization files
929
	dojo.registerModulePath("nls","nls");	
929
	dojo.registerModulePath("nls","nls");	
930
}
930
}
931
 
931
 
932
dojo.hostenv.preloadLocalizations = function(){
932
dojo.hostenv.preloadLocalizations = function(){
933
// summary:
933
// summary:
934
//	Load built, flattened resource bundles, if available for all locales used in the page.
934
//	Load built, flattened resource bundles, if available for all locales used in the page.
935
//	Execute only once.  Note that this is a no-op unless there is a build.
935
//	Execute only once.  Note that this is a no-op unless there is a build.
936
 
936
 
937
	if(dojo.hostenv.localesGenerated){
937
	if(dojo.hostenv.localesGenerated){
938
		dojo.hostenv.registerNlsPrefix();
938
		dojo.hostenv.registerNlsPrefix();
939
 
939
 
940
		function preload(locale){
940
		function preload(locale){
941
			locale = dojo.hostenv.normalizeLocale(locale);
941
			locale = dojo.hostenv.normalizeLocale(locale);
942
			dojo.hostenv.searchLocalePath(locale, true, function(loc){
942
			dojo.hostenv.searchLocalePath(locale, true, function(loc){
943
				for(var i=0; i<dojo.hostenv.localesGenerated.length;i++){
943
				for(var i=0; i<dojo.hostenv.localesGenerated.length;i++){
944
					if(dojo.hostenv.localesGenerated[i] == loc){
944
					if(dojo.hostenv.localesGenerated[i] == loc){
945
						dojo["require"]("nls.dojo_"+loc);
945
						dojo["require"]("nls.dojo_"+loc);
946
						return true; // Boolean
946
						return true; // Boolean
947
					}
947
					}
948
				}
948
				}
949
				return false; // Boolean
949
				return false; // Boolean
950
			});
950
			});
951
		}
951
		}
952
		preload();
952
		preload();
953
		var extra = djConfig.extraLocale||[];
953
		var extra = djConfig.extraLocale||[];
954
		for(var i=0; i<extra.length; i++){
954
		for(var i=0; i<extra.length; i++){
955
			preload(extra[i]);
955
			preload(extra[i]);
956
		}
956
		}
957
	}
957
	}
958
	dojo.hostenv.preloadLocalizations = function(){};
958
	dojo.hostenv.preloadLocalizations = function(){};
959
}
959
}
960
 
960
 
961
dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
961
dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
962
// summary:
962
// summary:
963
//	Declares translated resources and loads them if necessary, in the same style as dojo.require.
963
//	Declares translated resources and loads them if necessary, in the same style as dojo.require.
964
//	Contents of the resource bundle are typically strings, but may be any name/value pair,
964
//	Contents of the resource bundle are typically strings, but may be any name/value pair,
965
//	represented in JSON format.  See also dojo.i18n.getLocalization.
965
//	represented in JSON format.  See also dojo.i18n.getLocalization.
966
//
966
//
967
// moduleName: name of the package containing the "nls" directory in which the bundle is found
967
// moduleName: name of the package containing the "nls" directory in which the bundle is found
968
// bundleName: bundle name, i.e. the filename without the '.js' suffix
968
// bundleName: bundle name, i.e. the filename without the '.js' suffix
969
// locale: the locale to load (optional)  By default, the browser's user locale as defined by dojo.locale
969
// locale: the locale to load (optional)  By default, the browser's user locale as defined by dojo.locale
970
// availableFlatLocales: A comma-separated list of the available, flattened locales for this bundle.
970
// availableFlatLocales: A comma-separated list of the available, flattened locales for this bundle.
971
// This argument should only be set by the build process.
971
// This argument should only be set by the build process.
972
//
972
//
973
// description:
973
// description:
974
//	Load translated resource bundles provided underneath the "nls" directory within a package.
974
//	Load translated resource bundles provided underneath the "nls" directory within a package.
975
//	Translated resources may be located in different packages throughout the source tree.  For example,
975
//	Translated resources may be located in different packages throughout the source tree.  For example,
976
//	a particular widget may define one or more resource bundles, structured in a program as follows,
976
//	a particular widget may define one or more resource bundles, structured in a program as follows,
977
//	where moduleName is mycode.mywidget and bundleNames available include bundleone and bundletwo:
977
//	where moduleName is mycode.mywidget and bundleNames available include bundleone and bundletwo:
978
//	...
978
//	...
979
//	mycode/
979
//	mycode/
980
//	 mywidget/
980
//	 mywidget/
981
//	  nls/
981
//	  nls/
982
//	   bundleone.js (the fallback translation, English in this example)
982
//	   bundleone.js (the fallback translation, English in this example)
983
//	   bundletwo.js (also a fallback translation)
983
//	   bundletwo.js (also a fallback translation)
984
//	   de/
984
//	   de/
985
//	    bundleone.js
985
//	    bundleone.js
986
//	    bundletwo.js
986
//	    bundletwo.js
987
//	   de-at/
987
//	   de-at/
988
//	    bundleone.js
988
//	    bundleone.js
989
//	   en/
989
//	   en/
990
//	    (empty; use the fallback translation)
990
//	    (empty; use the fallback translation)
991
//	   en-us/
991
//	   en-us/
992
//	    bundleone.js
992
//	    bundleone.js
993
//	   en-gb/
993
//	   en-gb/
994
//	    bundleone.js
994
//	    bundleone.js
995
//	   es/
995
//	   es/
996
//	    bundleone.js
996
//	    bundleone.js
997
//	    bundletwo.js
997
//	    bundletwo.js
998
//	  ...etc
998
//	  ...etc
999
//	...
999
//	...
1000
//	Each directory is named for a locale as specified by RFC 3066, (http://www.ietf.org/rfc/rfc3066.txt),
1000
//	Each directory is named for a locale as specified by RFC 3066, (http://www.ietf.org/rfc/rfc3066.txt),
1001
//	normalized in lowercase.  Note that the two bundles in the example do not define all the same variants.
1001
//	normalized in lowercase.  Note that the two bundles in the example do not define all the same variants.
1002
//	For a given locale, bundles will be loaded for that locale and all more general locales above it, including
1002
//	For a given locale, bundles will be loaded for that locale and all more general locales above it, including
1003
//	a fallback at the root directory.  For example, a declaration for the "de-at" locale will first
1003
//	a fallback at the root directory.  For example, a declaration for the "de-at" locale will first
1004
//	load nls/de-at/bundleone.js, then nls/de/bundleone.js and finally nls/bundleone.js.  The data will
1004
//	load nls/de-at/bundleone.js, then nls/de/bundleone.js and finally nls/bundleone.js.  The data will
1005
//	be flattened into a single Object so that lookups will follow this cascading pattern.  An optional build
1005
//	be flattened into a single Object so that lookups will follow this cascading pattern.  An optional build
1006
//	step can preload the bundles to avoid data redundancy and the multiple network hits normally required to
1006
//	step can preload the bundles to avoid data redundancy and the multiple network hits normally required to
1007
//	load these resources.
1007
//	load these resources.
1008
 
1008
 
1009
	dojo.hostenv.preloadLocalizations();
1009
	dojo.hostenv.preloadLocalizations();
1010
	var targetLocale = dojo.hostenv.normalizeLocale(locale);
1010
	var targetLocale = dojo.hostenv.normalizeLocale(locale);
1011
 	var bundlePackage = [moduleName, "nls", bundleName].join(".");
1011
 	var bundlePackage = [moduleName, "nls", bundleName].join(".");
1012
//NOTE: When loading these resources, the packaging does not match what is on disk.  This is an
1012
//NOTE: When loading these resources, the packaging does not match what is on disk.  This is an
1013
// implementation detail, as this is just a private data structure to hold the loaded resources.
1013
// implementation detail, as this is just a private data structure to hold the loaded resources.
1014
// e.g. tests/hello/nls/en-us/salutations.js is loaded as the object tests.hello.nls.salutations.en_us={...}
1014
// e.g. tests/hello/nls/en-us/salutations.js is loaded as the object tests.hello.nls.salutations.en_us={...}
1015
// The structure on disk is intended to be most convenient for developers and translators, but in memory
1015
// The structure on disk is intended to be most convenient for developers and translators, but in memory
1016
// it is more logical and efficient to store in a different order.  Locales cannot use dashes, since the
1016
// it is more logical and efficient to store in a different order.  Locales cannot use dashes, since the
1017
// resulting path will not evaluate as valid JS, so we translate them to underscores.
1017
// resulting path will not evaluate as valid JS, so we translate them to underscores.
1018
	
1018
	
1019
	//Find the best-match locale to load if we have available flat locales.
1019
	//Find the best-match locale to load if we have available flat locales.
1020
	var bestLocale = "";
1020
	var bestLocale = "";
1021
	if(availableFlatLocales){
1021
	if(availableFlatLocales){
1022
		var flatLocales = availableFlatLocales.split(",");
1022
		var flatLocales = availableFlatLocales.split(",");
1023
		for(var i = 0; i < flatLocales.length; i++){
1023
		for(var i = 0; i < flatLocales.length; i++){
1024
			//Locale must match from start of string.
1024
			//Locale must match from start of string.
1025
			if(targetLocale.indexOf(flatLocales[i]) == 0){
1025
			if(targetLocale.indexOf(flatLocales[i]) == 0){
1026
				if(flatLocales[i].length > bestLocale.length){
1026
				if(flatLocales[i].length > bestLocale.length){
1027
					bestLocale = flatLocales[i];
1027
					bestLocale = flatLocales[i];
1028
				}
1028
				}
1029
			}
1029
			}
1030
		}
1030
		}
1031
		if(!bestLocale){
1031
		if(!bestLocale){
1032
			bestLocale = "ROOT";
1032
			bestLocale = "ROOT";
1033
		}		
1033
		}		
1034
	}
1034
	}
1035
 
1035
 
1036
	//See if the desired locale is already loaded.
1036
	//See if the desired locale is already loaded.
1037
	var tempLocale = availableFlatLocales ? bestLocale : targetLocale;
1037
	var tempLocale = availableFlatLocales ? bestLocale : targetLocale;
1038
	var bundle = dojo.hostenv.findModule(bundlePackage);
1038
	var bundle = dojo.hostenv.findModule(bundlePackage);
1039
	var localizedBundle = null;
1039
	var localizedBundle = null;
1040
	if(bundle){
1040
	if(bundle){
1041
		if(djConfig.localizationComplete && bundle._built){return;}
1041
		if(djConfig.localizationComplete && bundle._built){return;}
1042
		var jsLoc = tempLocale.replace('-', '_');
1042
		var jsLoc = tempLocale.replace('-', '_');
1043
		var translationPackage = bundlePackage+"."+jsLoc;
1043
		var translationPackage = bundlePackage+"."+jsLoc;
1044
		localizedBundle = dojo.hostenv.findModule(translationPackage);
1044
		localizedBundle = dojo.hostenv.findModule(translationPackage);
1045
	}
1045
	}
1046
 
1046
 
1047
	if(!localizedBundle){
1047
	if(!localizedBundle){
1048
		bundle = dojo.hostenv.startPackage(bundlePackage);
1048
		bundle = dojo.hostenv.startPackage(bundlePackage);
1049
		var syms = dojo.hostenv.getModuleSymbols(moduleName);
1049
		var syms = dojo.hostenv.getModuleSymbols(moduleName);
1050
		var modpath = syms.concat("nls").join("/");
1050
		var modpath = syms.concat("nls").join("/");
1051
		var parent;
1051
		var parent;
1052
 
1052
 
1053
		dojo.hostenv.searchLocalePath(tempLocale, availableFlatLocales, function(loc){
1053
		dojo.hostenv.searchLocalePath(tempLocale, availableFlatLocales, function(loc){
1054
			var jsLoc = loc.replace('-', '_');
1054
			var jsLoc = loc.replace('-', '_');
1055
			var translationPackage = bundlePackage + "." + jsLoc;
1055
			var translationPackage = bundlePackage + "." + jsLoc;
1056
			var loaded = false;
1056
			var loaded = false;
1057
			if(!dojo.hostenv.findModule(translationPackage)){
1057
			if(!dojo.hostenv.findModule(translationPackage)){
1058
				// Mark loaded whether it's found or not, so that further load attempts will not be made
1058
				// Mark loaded whether it's found or not, so that further load attempts will not be made
1059
				dojo.hostenv.startPackage(translationPackage);
1059
				dojo.hostenv.startPackage(translationPackage);
1060
				var module = [modpath];
1060
				var module = [modpath];
1061
				if(loc != "ROOT"){module.push(loc);}
1061
				if(loc != "ROOT"){module.push(loc);}
1062
				module.push(bundleName);
1062
				module.push(bundleName);
1063
				var filespec = module.join("/") + '.js';
1063
				var filespec = module.join("/") + '.js';
1064
				loaded = dojo.hostenv.loadPath(filespec, null, function(hash){
1064
				loaded = dojo.hostenv.loadPath(filespec, null, function(hash){
1065
					// Use singleton with prototype to point to parent bundle, then mix-in result from loadPath
1065
					// Use singleton with prototype to point to parent bundle, then mix-in result from loadPath
1066
					var clazz = function(){};
1066
					var clazz = function(){};
1067
					clazz.prototype = parent;
1067
					clazz.prototype = parent;
1068
					bundle[jsLoc] = new clazz();
1068
					bundle[jsLoc] = new clazz();
1069
					for(var j in hash){ bundle[jsLoc][j] = hash[j]; }
1069
					for(var j in hash){ bundle[jsLoc][j] = hash[j]; }
1070
				});
1070
				});
1071
			}else{
1071
			}else{
1072
				loaded = true;
1072
				loaded = true;
1073
			}
1073
			}
1074
			if(loaded && bundle[jsLoc]){
1074
			if(loaded && bundle[jsLoc]){
1075
				parent = bundle[jsLoc];
1075
				parent = bundle[jsLoc];
1076
			}else{
1076
			}else{
1077
				bundle[jsLoc] = parent;
1077
				bundle[jsLoc] = parent;
1078
			}
1078
			}
1079
			
1079
			
1080
			if(availableFlatLocales){
1080
			if(availableFlatLocales){
1081
				//Stop the locale path searching if we know the availableFlatLocales, since
1081
				//Stop the locale path searching if we know the availableFlatLocales, since
1082
				//the first call to this function will load the only bundle that is needed.
1082
				//the first call to this function will load the only bundle that is needed.
1083
				return true;
1083
				return true;
1084
			}
1084
			}
1085
		});
1085
		});
1086
	}
1086
	}
1087
 
1087
 
1088
	//Save the best locale bundle as the target locale bundle when we know the
1088
	//Save the best locale bundle as the target locale bundle when we know the
1089
	//the available bundles.
1089
	//the available bundles.
1090
	if(availableFlatLocales && targetLocale != bestLocale){
1090
	if(availableFlatLocales && targetLocale != bestLocale){
1091
		bundle[targetLocale.replace('-', '_')] = bundle[bestLocale.replace('-', '_')];
1091
		bundle[targetLocale.replace('-', '_')] = bundle[bestLocale.replace('-', '_')];
1092
	}
1092
	}
1093
};
1093
};
1094
 
1094
 
1095
(function(){
1095
(function(){
1096
	// If other locales are used, dojo.requireLocalization should load them as well, by default.
1096
	// If other locales are used, dojo.requireLocalization should load them as well, by default.
1097
	// Override dojo.requireLocalization to do load the default bundle, then iterate through the
1097
	// Override dojo.requireLocalization to do load the default bundle, then iterate through the
1098
	// extraLocale list and load those translations as well, unless a particular locale was requested.
1098
	// extraLocale list and load those translations as well, unless a particular locale was requested.
1099
 
1099
 
1100
	var extra = djConfig.extraLocale;
1100
	var extra = djConfig.extraLocale;
1101
	if(extra){
1101
	if(extra){
1102
		if(!extra instanceof Array){
1102
		if(!extra instanceof Array){
1103
			extra = [extra];
1103
			extra = [extra];
1104
		}
1104
		}
1105
 
1105
 
1106
		var req = dojo.requireLocalization;
1106
		var req = dojo.requireLocalization;
1107
		dojo.requireLocalization = function(m, b, locale, availableFlatLocales){
1107
		dojo.requireLocalization = function(m, b, locale, availableFlatLocales){
1108
			req(m,b,locale, availableFlatLocales);
1108
			req(m,b,locale, availableFlatLocales);
1109
			if(locale){return;}
1109
			if(locale){return;}
1110
			for(var i=0; i<extra.length; i++){
1110
			for(var i=0; i<extra.length; i++){
1111
				req(m,b,extra[i], availableFlatLocales);
1111
				req(m,b,extra[i], availableFlatLocales);
1112
			}
1112
			}
1113
		};
1113
		};
1114
	}
1114
	}
1115
})();
1115
})();
1116
 
1116
 
1117
};
1117
};
1118
 
1118
 
1119
if(typeof window != 'undefined'){
1119
if(typeof window != 'undefined'){
1120
 
1120
 
1121
	// attempt to figure out the path to dojo if it isn't set in the config
1121
	// attempt to figure out the path to dojo if it isn't set in the config
1122
	(function(){
1122
	(function(){
1123
		// before we get any further with the config options, try to pick them out
1123
		// before we get any further with the config options, try to pick them out
1124
		// of the URL. Most of this code is from NW
1124
		// of the URL. Most of this code is from NW
1125
		if(djConfig.allowQueryConfig){
1125
		if(djConfig.allowQueryConfig){
1126
			var baseUrl = document.location.toString(); // FIXME: use location.query instead?
1126
			var baseUrl = document.location.toString(); // FIXME: use location.query instead?
1127
			var params = baseUrl.split("?", 2);
1127
			var params = baseUrl.split("?", 2);
1128
			if(params.length > 1){
1128
			if(params.length > 1){
1129
				var paramStr = params[1];
1129
				var paramStr = params[1];
1130
				var pairs = paramStr.split("&");
1130
				var pairs = paramStr.split("&");
1131
				for(var x in pairs){
1131
				for(var x in pairs){
1132
					var sp = pairs[x].split("=");
1132
					var sp = pairs[x].split("=");
1133
					// FIXME: is this eval dangerous?
1133
					// FIXME: is this eval dangerous?
1134
					if((sp[0].length > 9)&&(sp[0].substr(0, 9) == "djConfig.")){
1134
					if((sp[0].length > 9)&&(sp[0].substr(0, 9) == "djConfig.")){
1135
						var opt = sp[0].substr(9);
1135
						var opt = sp[0].substr(9);
1136
						try{
1136
						try{
1137
							djConfig[opt]=eval(sp[1]);
1137
							djConfig[opt]=eval(sp[1]);
1138
						}catch(e){
1138
						}catch(e){
1139
							djConfig[opt]=sp[1];
1139
							djConfig[opt]=sp[1];
1140
						}
1140
						}
1141
					}
1141
					}
1142
				}
1142
				}
1143
			}
1143
			}
1144
		}
1144
		}
1145
 
1145
 
1146
		if(
1146
		if(
1147
			((djConfig["baseScriptUri"] == "")||(djConfig["baseRelativePath"] == "")) && 
1147
			((djConfig["baseScriptUri"] == "")||(djConfig["baseRelativePath"] == "")) && 
1148
			(document && document.getElementsByTagName)
1148
			(document && document.getElementsByTagName)
1149
		){
1149
		){
1150
			var scripts = document.getElementsByTagName("script");
1150
			var scripts = document.getElementsByTagName("script");
1151
			var rePkg = /(__package__|dojo|bootstrap1)\.js([\?\.]|$)/i;
1151
			var rePkg = /(__package__|dojo|bootstrap1)\.js([\?\.]|$)/i;
1152
			for(var i = 0; i < scripts.length; i++) {
1152
			for(var i = 0; i < scripts.length; i++) {
1153
				var src = scripts[i].getAttribute("src");
1153
				var src = scripts[i].getAttribute("src");
1154
				if(!src) { continue; }
1154
				if(!src) { continue; }
1155
				var m = src.match(rePkg);
1155
				var m = src.match(rePkg);
1156
				if(m) {
1156
				if(m) {
1157
					var root = src.substring(0, m.index);
1157
					var root = src.substring(0, m.index);
1158
					if(src.indexOf("bootstrap1") > -1) { root += "../"; }
1158
					if(src.indexOf("bootstrap1") > -1) { root += "../"; }
1159
					if(!this["djConfig"]) { djConfig = {}; }
1159
					if(!this["djConfig"]) { djConfig = {}; }
1160
					if(djConfig["baseScriptUri"] == "") { djConfig["baseScriptUri"] = root; }
1160
					if(djConfig["baseScriptUri"] == "") { djConfig["baseScriptUri"] = root; }
1161
					if(djConfig["baseRelativePath"] == "") { djConfig["baseRelativePath"] = root; }
1161
					if(djConfig["baseRelativePath"] == "") { djConfig["baseRelativePath"] = root; }
1162
					break;
1162
					break;
1163
				}
1163
				}
1164
			}
1164
			}
1165
		}
1165
		}
1166
 
1166
 
1167
		// fill in the rendering support information in dojo.render.*
1167
		// fill in the rendering support information in dojo.render.*
1168
		var dr = dojo.render;
1168
		var dr = dojo.render;
1169
		var drh = dojo.render.html;
1169
		var drh = dojo.render.html;
1170
		var drs = dojo.render.svg;
1170
		var drs = dojo.render.svg;
1171
		var dua = (drh.UA = navigator.userAgent);
1171
		var dua = (drh.UA = navigator.userAgent);
1172
		var dav = (drh.AV = navigator.appVersion);
1172
		var dav = (drh.AV = navigator.appVersion);
1173
		var t = true;
1173
		var t = true;
1174
		var f = false;
1174
		var f = false;
1175
		drh.capable = t;
1175
		drh.capable = t;
1176
		drh.support.builtin = t;
1176
		drh.support.builtin = t;
1177
 
1177
 
1178
		dr.ver = parseFloat(drh.AV);
1178
		dr.ver = parseFloat(drh.AV);
1179
		dr.os.mac = dav.indexOf("Macintosh") >= 0;
1179
		dr.os.mac = dav.indexOf("Macintosh") >= 0;
1180
		dr.os.win = dav.indexOf("Windows") >= 0;
1180
		dr.os.win = dav.indexOf("Windows") >= 0;
1181
		// could also be Solaris or something, but it's the same browser
1181
		// could also be Solaris or something, but it's the same browser
1182
		dr.os.linux = dav.indexOf("X11") >= 0;
1182
		dr.os.linux = dav.indexOf("X11") >= 0;
1183
 
1183
 
1184
		drh.opera = dua.indexOf("Opera") >= 0;
1184
		drh.opera = dua.indexOf("Opera") >= 0;
1185
		drh.khtml = (dav.indexOf("Konqueror") >= 0)||(dav.indexOf("Safari") >= 0);
1185
		drh.khtml = (dav.indexOf("Konqueror") >= 0)||(dav.indexOf("Safari") >= 0);
1186
		drh.safari = dav.indexOf("Safari") >= 0;
1186
		drh.safari = dav.indexOf("Safari") >= 0;
1187
		var geckoPos = dua.indexOf("Gecko");
1187
		var geckoPos = dua.indexOf("Gecko");
1188
		drh.mozilla = drh.moz = (geckoPos >= 0)&&(!drh.khtml);
1188
		drh.mozilla = drh.moz = (geckoPos >= 0)&&(!drh.khtml);
1189
		if (drh.mozilla) {
1189
		if (drh.mozilla) {
1190
			// gecko version is YYYYMMDD
1190
			// gecko version is YYYYMMDD
1191
			drh.geckoVersion = dua.substring(geckoPos + 6, geckoPos + 14);
1191
			drh.geckoVersion = dua.substring(geckoPos + 6, geckoPos + 14);
1192
		}
1192
		}
1193
		drh.ie = (document.all)&&(!drh.opera);
1193
		drh.ie = (document.all)&&(!drh.opera);
1194
		drh.ie50 = drh.ie && dav.indexOf("MSIE 5.0")>=0;
1194
		drh.ie50 = drh.ie && dav.indexOf("MSIE 5.0")>=0;
1195
		drh.ie55 = drh.ie && dav.indexOf("MSIE 5.5")>=0;
1195
		drh.ie55 = drh.ie && dav.indexOf("MSIE 5.5")>=0;
1196
		drh.ie60 = drh.ie && dav.indexOf("MSIE 6.0")>=0;
1196
		drh.ie60 = drh.ie && dav.indexOf("MSIE 6.0")>=0;
1197
		drh.ie70 = drh.ie && dav.indexOf("MSIE 7.0")>=0;
1197
		drh.ie70 = drh.ie && dav.indexOf("MSIE 7.0")>=0;
1198
 
1198
 
1199
		var cm = document["compatMode"];
1199
		var cm = document["compatMode"];
1200
		drh.quirks = (cm == "BackCompat")||(cm == "QuirksMode")||drh.ie55||drh.ie50;
1200
		drh.quirks = (cm == "BackCompat")||(cm == "QuirksMode")||drh.ie55||drh.ie50;
1201
 
1201
 
1202
		// TODO: is the HTML LANG attribute relevant?
1202
		// TODO: is the HTML LANG attribute relevant?
1203
		dojo.locale = dojo.locale || (drh.ie ? navigator.userLanguage : navigator.language).toLowerCase();
1203
		dojo.locale = dojo.locale || (drh.ie ? navigator.userLanguage : navigator.language).toLowerCase();
1204
 
1204
 
1205
		dr.vml.capable=drh.ie;
1205
		dr.vml.capable=drh.ie;
1206
		drs.capable = f;
1206
		drs.capable = f;
1207
		drs.support.plugin = f;
1207
		drs.support.plugin = f;
1208
		drs.support.builtin = f;
1208
		drs.support.builtin = f;
1209
		var tdoc = window["document"];
1209
		var tdoc = window["document"];
1210
		var tdi = tdoc["implementation"];
1210
		var tdi = tdoc["implementation"];
1211
 
1211
 
1212
		if((tdi)&&(tdi["hasFeature"])&&(tdi.hasFeature("org.w3c.dom.svg", "1.0"))){
1212
		if((tdi)&&(tdi["hasFeature"])&&(tdi.hasFeature("org.w3c.dom.svg", "1.0"))){
1213
			drs.capable = t;
1213
			drs.capable = t;
1214
			drs.support.builtin = t;
1214
			drs.support.builtin = t;
1215
			drs.support.plugin = f;
1215
			drs.support.plugin = f;
1216
		}
1216
		}
1217
		// webkits after 420 support SVG natively. The test string is "AppleWebKit/420+"
1217
		// webkits after 420 support SVG natively. The test string is "AppleWebKit/420+"
1218
		if(drh.safari){
1218
		if(drh.safari){
1219
			var tmp = dua.split("AppleWebKit/")[1];
1219
			var tmp = dua.split("AppleWebKit/")[1];
1220
			var ver = parseFloat(tmp.split(" ")[0]);
1220
			var ver = parseFloat(tmp.split(" ")[0]);
1221
			if(ver >= 420){
1221
			if(ver >= 420){
1222
				drs.capable = t;
1222
				drs.capable = t;
1223
				drs.support.builtin = t;
1223
				drs.support.builtin = t;
1224
				drs.support.plugin = f;
1224
				drs.support.plugin = f;
1225
			}
1225
			}
1226
		}else{
1226
		}else{
1227
		}
1227
		}
1228
	})();
1228
	})();
1229
 
1229
 
1230
	dojo.hostenv.startPackage("dojo.hostenv");
1230
	dojo.hostenv.startPackage("dojo.hostenv");
1231
 
1231
 
1232
	dojo.render.name = dojo.hostenv.name_ = 'browser';
1232
	dojo.render.name = dojo.hostenv.name_ = 'browser';
1233
	dojo.hostenv.searchIds = [];
1233
	dojo.hostenv.searchIds = [];
1234
 
1234
 
1235
	// These are in order of decreasing likelihood; this will change in time.
1235
	// These are in order of decreasing likelihood; this will change in time.
1236
	dojo.hostenv._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
1236
	dojo.hostenv._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
1237
 
1237
 
1238
	dojo.hostenv.getXmlhttpObject = function(){
1238
	dojo.hostenv.getXmlhttpObject = function(){
1239
		// summary: does the work of portably generating a new XMLHTTPRequest object.
1239
		// summary: does the work of portably generating a new XMLHTTPRequest object.
1240
		var http = null;
1240
		var http = null;
1241
		var last_e = null;
1241
		var last_e = null;
1242
		try{ http = new XMLHttpRequest(); }catch(e){}
1242
		try{ http = new XMLHttpRequest(); }catch(e){}
1243
		if(!http){
1243
		if(!http){
1244
			for(var i=0; i<3; ++i){
1244
			for(var i=0; i<3; ++i){
1245
				var progid = dojo.hostenv._XMLHTTP_PROGIDS[i];
1245
				var progid = dojo.hostenv._XMLHTTP_PROGIDS[i];
1246
				try{
1246
				try{
1247
					http = new ActiveXObject(progid);
1247
					http = new ActiveXObject(progid);
1248
				}catch(e){
1248
				}catch(e){
1249
					last_e = e;
1249
					last_e = e;
1250
				}
1250
				}
1251
 
1251
 
1252
				if(http){
1252
				if(http){
1253
					dojo.hostenv._XMLHTTP_PROGIDS = [progid];  // so faster next time
1253
					dojo.hostenv._XMLHTTP_PROGIDS = [progid];  // so faster next time
1254
					break;
1254
					break;
1255
				}
1255
				}
1256
			}
1256
			}
1257
 
1257
 
1258
			/*if(http && !http.toString) {
1258
			/*if(http && !http.toString) {
1259
				http.toString = function() { "[object XMLHttpRequest]"; }
1259
				http.toString = function() { "[object XMLHttpRequest]"; }
1260
			}*/
1260
			}*/
1261
		}
1261
		}
1262
 
1262
 
1263
		if(!http){
1263
		if(!http){
1264
			return dojo.raise("XMLHTTP not available", last_e);
1264
			return dojo.raise("XMLHTTP not available", last_e);
1265
		}
1265
		}
1266
 
1266
 
1267
		return http; // XMLHTTPRequest instance
1267
		return http; // XMLHTTPRequest instance
1268
	}
1268
	}
1269
 
1269
 
1270
	dojo.hostenv._blockAsync = false;
1270
	dojo.hostenv._blockAsync = false;
1271
	dojo.hostenv.getText = function(uri, async_cb, fail_ok){
1271
	dojo.hostenv.getText = function(uri, async_cb, fail_ok){
1272
		// summary: Read the contents of the specified uri and return those contents.
1272
		// summary: Read the contents of the specified uri and return those contents.
1273
		// uri:
1273
		// uri:
1274
		//		A relative or absolute uri. If absolute, it still must be in
1274
		//		A relative or absolute uri. If absolute, it still must be in
1275
		//		the same "domain" as we are.
1275
		//		the same "domain" as we are.
1276
		// async_cb:
1276
		// async_cb:
1277
		//		If not specified, load synchronously. If specified, load
1277
		//		If not specified, load synchronously. If specified, load
1278
		//		asynchronously, and use async_cb as the progress handler which
1278
		//		asynchronously, and use async_cb as the progress handler which
1279
		//		takes the xmlhttp object as its argument. If async_cb, this
1279
		//		takes the xmlhttp object as its argument. If async_cb, this
1280
		//		function returns null.
1280
		//		function returns null.
1281
		// fail_ok:
1281
		// fail_ok:
1282
		//		Default false. If fail_ok and !async_cb and loading fails,
1282
		//		Default false. If fail_ok and !async_cb and loading fails,
1283
		//		return null instead of throwing.
1283
		//		return null instead of throwing.
1284
 
1284
 
1285
		// need to block async callbacks from snatching this thread as the result
1285
		// need to block async callbacks from snatching this thread as the result
1286
		// of an async callback might call another sync XHR, this hangs khtml forever
1286
		// of an async callback might call another sync XHR, this hangs khtml forever
1287
		// hostenv._blockAsync must also be checked in BrowserIO's watchInFlight()
1287
		// hostenv._blockAsync must also be checked in BrowserIO's watchInFlight()
1288
		// NOTE: must be declared before scope switches ie. this.getXmlhttpObject()
1288
		// NOTE: must be declared before scope switches ie. this.getXmlhttpObject()
1289
		if(!async_cb){ this._blockAsync = true; }
1289
		if(!async_cb){ this._blockAsync = true; }
1290
 
1290
 
1291
		var http = this.getXmlhttpObject();
1291
		var http = this.getXmlhttpObject();
1292
 
1292
 
1293
		function isDocumentOk(http){
1293
		function isDocumentOk(http){
1294
			var stat = http["status"];
1294
			var stat = http["status"];
1295
			// allow a 304 use cache, needed in konq (is this compliant with the http spec?)
1295
			// allow a 304 use cache, needed in konq (is this compliant with the http spec?)
1296
			return Boolean((!stat)||((200 <= stat)&&(300 > stat))||(stat==304));
1296
			return Boolean((!stat)||((200 <= stat)&&(300 > stat))||(stat==304));
1297
		}
1297
		}
1298
 
1298
 
1299
		if(async_cb){
1299
		if(async_cb){
1300
			var _this = this, timer = null, gbl = dojo.global();
1300
			var _this = this, timer = null, gbl = dojo.global();
1301
			var xhr = dojo.evalObjPath("dojo.io.XMLHTTPTransport");
1301
			var xhr = dojo.evalObjPath("dojo.io.XMLHTTPTransport");
1302
			http.onreadystatechange = function(){
1302
			http.onreadystatechange = function(){
1303
				if(timer){ gbl.clearTimeout(timer); timer = null; }
1303
				if(timer){ gbl.clearTimeout(timer); timer = null; }
1304
				if(_this._blockAsync || (xhr && xhr._blockAsync)){
1304
				if(_this._blockAsync || (xhr && xhr._blockAsync)){
1305
					timer = gbl.setTimeout(function () { http.onreadystatechange.apply(this); }, 10);
1305
					timer = gbl.setTimeout(function () { http.onreadystatechange.apply(this); }, 10);
1306
				}else{
1306
				}else{
1307
					if(4==http.readyState){
1307
					if(4==http.readyState){
1308
						if(isDocumentOk(http)){
1308
						if(isDocumentOk(http)){
1309
							// dojo.debug("LOADED URI: "+uri);
1309
							// dojo.debug("LOADED URI: "+uri);
1310
							async_cb(http.responseText);
1310
							async_cb(http.responseText);
1311
						}
1311
						}
1312
					}
1312
					}
1313
				}
1313
				}
1314
			}
1314
			}
1315
		}
1315
		}
1316
 
1316
 
1317
		http.open('GET', uri, async_cb ? true : false);
1317
		http.open('GET', uri, async_cb ? true : false);
1318
		try{
1318
		try{
1319
			http.send(null);
1319
			http.send(null);
1320
			if(async_cb){
1320
			if(async_cb){
1321
				return null;
1321
				return null;
1322
			}
1322
			}
1323
			if(!isDocumentOk(http)){
1323
			if(!isDocumentOk(http)){
1324
				var err = Error("Unable to load "+uri+" status:"+ http.status);
1324
				var err = Error("Unable to load "+uri+" status:"+ http.status);
1325
				err.status = http.status;
1325
				err.status = http.status;
1326
				err.responseText = http.responseText;
1326
				err.responseText = http.responseText;
1327
				throw err;
1327
				throw err;
1328
			}
1328
			}
1329
		}catch(e){
1329
		}catch(e){
1330
			this._blockAsync = false;
1330
			this._blockAsync = false;
1331
			if((fail_ok)&&(!async_cb)){
1331
			if((fail_ok)&&(!async_cb)){
1332
				return null;
1332
				return null;
1333
			}else{
1333
			}else{
1334
				throw e;
1334
				throw e;
1335
			}
1335
			}
1336
		}
1336
		}
1337
 
1337
 
1338
		this._blockAsync = false;
1338
		this._blockAsync = false;
1339
		return http.responseText; // String
1339
		return http.responseText; // String
1340
	}
1340
	}
1341
 
1341
 
1342
	dojo.hostenv.defaultDebugContainerId = 'dojoDebug';
1342
	dojo.hostenv.defaultDebugContainerId = 'dojoDebug';
1343
	dojo.hostenv._println_buffer = [];
1343
	dojo.hostenv._println_buffer = [];
1344
	dojo.hostenv._println_safe = false;
1344
	dojo.hostenv._println_safe = false;
1345
	dojo.hostenv.println = function(/*String*/line){
1345
	dojo.hostenv.println = function(/*String*/line){
1346
		// summary:
1346
		// summary:
1347
		//		prints the provided line to whatever logging container is
1347
		//		prints the provided line to whatever logging container is
1348
		//		available. If the page isn't loaded yet, the line may be added
1348
		//		available. If the page isn't loaded yet, the line may be added
1349
		//		to a buffer for printing later.
1349
		//		to a buffer for printing later.
1350
		if(!dojo.hostenv._println_safe){
1350
		if(!dojo.hostenv._println_safe){
1351
			dojo.hostenv._println_buffer.push(line);
1351
			dojo.hostenv._println_buffer.push(line);
1352
		}else{
1352
		}else{
1353
			try {
1353
			try {
1354
				var console = document.getElementById(djConfig.debugContainerId ?
1354
				var console = document.getElementById(djConfig.debugContainerId ?
1355
					djConfig.debugContainerId : dojo.hostenv.defaultDebugContainerId);
1355
					djConfig.debugContainerId : dojo.hostenv.defaultDebugContainerId);
1356
				if(!console) { console = dojo.body(); }
1356
				if(!console) { console = dojo.body(); }
1357
 
1357
 
1358
				var div = document.createElement("div");
1358
				var div = document.createElement("div");
1359
				div.appendChild(document.createTextNode(line));
1359
				div.appendChild(document.createTextNode(line));
1360
				console.appendChild(div);
1360
				console.appendChild(div);
1361
			} catch (e) {
1361
			} catch (e) {
1362
				try{
1362
				try{
1363
					// safari needs the output wrapped in an element for some reason
1363
					// safari needs the output wrapped in an element for some reason
1364
					document.write("<div>" + line + "</div>");
1364
					document.write("<div>" + line + "</div>");
1365
				}catch(e2){
1365
				}catch(e2){
1366
					window.status = line;
1366
					window.status = line;
1367
				}
1367
				}
1368
			}
1368
			}
1369
		}
1369
		}
1370
	}
1370
	}
1371
 
1371
 
1372
	dojo.addOnLoad(function(){
1372
	dojo.addOnLoad(function(){
1373
		dojo.hostenv._println_safe = true;
1373
		dojo.hostenv._println_safe = true;
1374
		while(dojo.hostenv._println_buffer.length > 0){
1374
		while(dojo.hostenv._println_buffer.length > 0){
1375
			dojo.hostenv.println(dojo.hostenv._println_buffer.shift());
1375
			dojo.hostenv.println(dojo.hostenv._println_buffer.shift());
1376
		}
1376
		}
1377
	});
1377
	});
1378
 
1378
 
1379
	function dj_addNodeEvtHdlr(/*DomNode*/node, /*String*/evtName, /*Function*/fp){
1379
	function dj_addNodeEvtHdlr(/*DomNode*/node, /*String*/evtName, /*Function*/fp){
1380
		// summary:
1380
		// summary:
1381
		//		non-destructively adds the specified function to the node's
1381
		//		non-destructively adds the specified function to the node's
1382
		//		evtName handler.
1382
		//		evtName handler.
1383
		// node: the DomNode to add the handler to
1383
		// node: the DomNode to add the handler to
1384
		// evtName: should be in the form "click" for "onclick" handlers
1384
		// evtName: should be in the form "click" for "onclick" handlers
1385
		var oldHandler = node["on"+evtName] || function(){};
1385
		var oldHandler = node["on"+evtName] || function(){};
1386
		node["on"+evtName] = function(){
1386
		node["on"+evtName] = function(){
1387
			fp.apply(node, arguments);
1387
			fp.apply(node, arguments);
1388
			oldHandler.apply(node, arguments);
1388
			oldHandler.apply(node, arguments);
1389
		}
1389
		}
1390
		return true;
1390
		return true;
1391
	}
1391
	}
-
 
1392
 
1392
 
1393
	dojo.hostenv._djInitFired = false;
1393
	//	BEGIN DOMContentLoaded, from Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/)
1394
	//	BEGIN DOMContentLoaded, from Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/)
-
 
1395
	function dj_load_init(e){
1394
	function dj_load_init(e){
1396
		dojo.hostenv._djInitFired = true;
1395
		// allow multiple calls, only first one will take effect
1397
		// allow multiple calls, only first one will take effect
1396
		// A bug in khtml calls events callbacks for document for event which isnt supported
1398
		// A bug in khtml calls events callbacks for document for event which isnt supported
1397
		// for example a created contextmenu event calls DOMContentLoaded, workaround
1399
		// for example a created contextmenu event calls DOMContentLoaded, workaround
1398
		var type = (e && e.type) ? e.type.toLowerCase() : "load";
1400
		var type = (e && e.type) ? e.type.toLowerCase() : "load";
1399
		if(arguments.callee.initialized || (type!="domcontentloaded" && type!="load")){ return; }
1401
		if(arguments.callee.initialized || (type!="domcontentloaded" && type!="load")){ return; }
1400
		arguments.callee.initialized = true;
1402
		arguments.callee.initialized = true;
1401
		if(typeof(_timer) != 'undefined'){
1403
		if(typeof(_timer) != 'undefined'){
1402
			clearInterval(_timer);
1404
			clearInterval(_timer);
1403
			delete _timer;
1405
			delete _timer;
1404
		}
1406
		}
1405
 
1407
 
1406
		var initFunc = function(){
1408
		var initFunc = function(){
1407
			//perform initialization
1409
			//perform initialization
1408
			if(dojo.render.html.ie){
1410
			if(dojo.render.html.ie){
1409
				dojo.hostenv.makeWidgets();
1411
				dojo.hostenv.makeWidgets();
1410
			}
1412
			}
1411
		};
1413
		};
1412
 
1414
 
1413
		if(dojo.hostenv.inFlightCount == 0){
1415
		if(dojo.hostenv.inFlightCount == 0){
1414
			initFunc();
1416
			initFunc();
1415
			dojo.hostenv.modulesLoaded();
1417
			dojo.hostenv.modulesLoaded();
1416
		}else{
1418
		}else{
1417
			//This else case should be xdomain loading.
1419
			//This else case should be xdomain loading.
1418
			//Make sure this is the first thing in the load listener array.
1420
			//Make sure this is the first thing in the load listener array.
1419
			//Part of the dojo.addOnLoad guarantee is that when the listeners are notified,
1421
			//Part of the dojo.addOnLoad guarantee is that when the listeners are notified,
1420
			//It means the DOM (or page) has loaded and that widgets have been parsed.
1422
			//It means the DOM (or page) has loaded and that widgets have been parsed.
1421
			dojo.hostenv.modulesLoadedListeners.unshift(initFunc);
1423
			dojo.hostenv.modulesLoadedListeners.unshift(initFunc);
1422
		}
1424
		}
1423
	}
1425
	}
1424
 
1426
 
1425
	//	START DOMContentLoaded
1427
	//	START DOMContentLoaded
1426
	// Mozilla and Opera 9 expose the event we could use
1428
	// Mozilla and Opera 9 expose the event we could use
1427
	if(document.addEventListener){
1429
	if(document.addEventListener){
1428
		// NOTE: 
1430
		// NOTE: 
1429
		//		due to a threading issue in Firefox 2.0, we can't enable
1431
		//		due to a threading issue in Firefox 2.0, we can't enable
1430
		//		DOMContentLoaded on that platform. For more information, see:
1432
		//		DOMContentLoaded on that platform. For more information, see:
1431
		//		http://trac.dojotoolkit.org/ticket/1704
1433
		//		http://trac.dojotoolkit.org/ticket/1704
1432
		if(dojo.render.html.opera || (dojo.render.html.moz && (djConfig["enableMozDomContentLoaded"] === true))){
1434
		if(dojo.render.html.opera || (dojo.render.html.moz && (djConfig["enableMozDomContentLoaded"] === true))){
1433
			document.addEventListener("DOMContentLoaded", dj_load_init, null);
1435
			document.addEventListener("DOMContentLoaded", dj_load_init, null);
1434
		}
1436
		}
1435
 
1437
 
1436
		//	mainly for Opera 8.5, won't be fired if DOMContentLoaded fired already.
1438
		//	mainly for Opera 8.5, won't be fired if DOMContentLoaded fired already.
1437
		//  also used for Mozilla because of trac #1640
1439
		//  also used for Mozilla because of trac #1640
1438
		window.addEventListener("load", dj_load_init, null);
1440
		window.addEventListener("load", dj_load_init, null);
1439
	}
1441
	}
1440
 
1442
 
1441
	// 	for Internet Explorer. readyState will not be achieved on init call, but dojo doesn't need it
1443
	// 	for Internet Explorer. readyState will not be achieved on init call, but dojo doesn't need it
1442
	//	however, we'll include it because we don't know if there are other functions added that might.
1444
	//	however, we'll include it because we don't know if there are other functions added that might.
1443
	//	Note that this has changed because the build process strips all comments--including conditional
1445
	//	Note that this has changed because the build process strips all comments--including conditional
1444
	//		ones.
1446
	//		ones.
1445
	if(dojo.render.html.ie && dojo.render.os.win){
1447
	if(dojo.render.html.ie && dojo.render.os.win){
1446
		document.attachEvent("onreadystatechange", function(e){
1448
		document.attachEvent("onreadystatechange", function(e){
1447
			if(document.readyState == "complete"){
1449
			if(document.readyState == "complete"){
1448
				dj_load_init();
1450
				dj_load_init();
1449
			}
1451
			}
1450
		});
1452
		});
1451
	}
1453
	}
1452
 
1454
 
1453
	if (/(WebKit|khtml)/i.test(navigator.userAgent)) { // sniff
1455
	if (/(WebKit|khtml)/i.test(navigator.userAgent)) { // sniff
1454
		var _timer = setInterval(function() {
1456
		var _timer = setInterval(function() {
1455
			if (/loaded|complete/.test(document.readyState)) {
1457
			if (/loaded|complete/.test(document.readyState)) {
1456
				dj_load_init(); // call the onload handler
1458
				dj_load_init(); // call the onload handler
1457
			}
1459
			}
1458
		}, 10);
1460
		}, 10);
1459
	}
1461
	}
1460
	//	END DOMContentLoaded
1462
	//	END DOMContentLoaded
1461
 
1463
 
1462
	// IE WebControl hosted in an application can fire "beforeunload" and "unload"
1464
	// IE WebControl hosted in an application can fire "beforeunload" and "unload"
1463
	// events when control visibility changes, causing Dojo to unload too soon. The
1465
	// events when control visibility changes, causing Dojo to unload too soon. The
1464
	// following code fixes the problem
1466
	// following code fixes the problem
1465
	// Reference: http://support.microsoft.com/default.aspx?scid=kb;en-us;199155
1467
	// Reference: http://support.microsoft.com/default.aspx?scid=kb;en-us;199155
1466
	if(dojo.render.html.ie){
1468
	if(dojo.render.html.ie){
1467
		dj_addNodeEvtHdlr(window, "beforeunload", function(){
1469
		dj_addNodeEvtHdlr(window, "beforeunload", function(){
1468
			dojo.hostenv._unloading = true;
1470
			dojo.hostenv._unloading = true;
1469
			window.setTimeout(function() {
1471
			window.setTimeout(function() {
1470
				dojo.hostenv._unloading = false;
1472
				dojo.hostenv._unloading = false;
1471
			}, 0);
1473
			}, 0);
1472
		});
1474
		});
1473
	}
1475
	}
1474
 
1476
 
1475
	dj_addNodeEvtHdlr(window, "unload", function(){
1477
	dj_addNodeEvtHdlr(window, "unload", function(){
1476
		dojo.hostenv.unloaded();
1478
		dojo.hostenv.unloaded();
1477
		if((!dojo.render.html.ie)||(dojo.render.html.ie && dojo.hostenv._unloading)){
1479
		if((!dojo.render.html.ie)||(dojo.render.html.ie && dojo.hostenv._unloading)){
1478
			dojo.hostenv.unloaded();
1480
			dojo.hostenv.unloaded();
1479
		}
1481
		}
1480
	});
1482
	});
1481
 
1483
 
1482
	dojo.hostenv.makeWidgets = function(){
1484
	dojo.hostenv.makeWidgets = function(){
1483
		// you can put searchIds in djConfig and dojo.hostenv at the moment
1485
		// you can put searchIds in djConfig and dojo.hostenv at the moment
1484
		// we should probably eventually move to one or the other
1486
		// we should probably eventually move to one or the other
1485
		var sids = [];
1487
		var sids = [];
1486
		if(djConfig.searchIds && djConfig.searchIds.length > 0) {
1488
		if(djConfig.searchIds && djConfig.searchIds.length > 0) {
1487
			sids = sids.concat(djConfig.searchIds);
1489
			sids = sids.concat(djConfig.searchIds);
1488
		}
1490
		}
1489
		if(dojo.hostenv.searchIds && dojo.hostenv.searchIds.length > 0) {
1491
		if(dojo.hostenv.searchIds && dojo.hostenv.searchIds.length > 0) {
1490
			sids = sids.concat(dojo.hostenv.searchIds);
1492
			sids = sids.concat(dojo.hostenv.searchIds);
1491
		}
1493
		}
1492
 
1494
 
1493
		if((djConfig.parseWidgets)||(sids.length > 0)){
1495
		if((djConfig.parseWidgets)||(sids.length > 0)){
1494
			if(dojo.evalObjPath("dojo.widget.Parse")){
1496
			if(dojo.evalObjPath("dojo.widget.Parse")){
1495
				// we must do this on a delay to avoid:
1497
				// we must do this on a delay to avoid:
1496
				//	http://www.shaftek.org/blog/archives/000212.html
1498
				//	http://www.shaftek.org/blog/archives/000212.html
1497
				// (IE bug)
1499
				// (IE bug)
1498
					var parser = new dojo.xml.Parse();
1500
					var parser = new dojo.xml.Parse();
1499
					if(sids.length > 0){
1501
					if(sids.length > 0){
1500
						for(var x=0; x<sids.length; x++){
1502
						for(var x=0; x<sids.length; x++){
1501
							var tmpNode = document.getElementById(sids[x]);
1503
							var tmpNode = document.getElementById(sids[x]);
1502
							if(!tmpNode){ continue; }
1504
							if(!tmpNode){ continue; }
1503
							var frag = parser.parseElement(tmpNode, null, true);
1505
							var frag = parser.parseElement(tmpNode, null, true);
1504
							dojo.widget.getParser().createComponents(frag);
1506
							dojo.widget.getParser().createComponents(frag);
1505
						}
1507
						}
1506
					}else if(djConfig.parseWidgets){
1508
					}else if(djConfig.parseWidgets){
1507
						var frag  = parser.parseElement(dojo.body(), null, true);
1509
						var frag  = parser.parseElement(dojo.body(), null, true);
1508
						dojo.widget.getParser().createComponents(frag);
1510
						dojo.widget.getParser().createComponents(frag);
1509
					}
1511
					}
1510
			}
1512
			}
1511
		}
1513
		}
1512
	}
1514
	}
1513
 
1515
 
1514
	dojo.addOnLoad(function(){
1516
	dojo.addOnLoad(function(){
1515
		if(!dojo.render.html.ie) {
1517
		if(!dojo.render.html.ie) {
1516
			dojo.hostenv.makeWidgets();
1518
			dojo.hostenv.makeWidgets();
1517
		}
1519
		}
1518
	});
1520
	});
1519
 
1521
 
1520
	try{
1522
	try{
1521
		if(dojo.render.html.ie){
1523
		if(dojo.render.html.ie){
1522
			document.namespaces.add("v","urn:schemas-microsoft-com:vml");
1524
			document.namespaces.add("v","urn:schemas-microsoft-com:vml");
1523
			document.createStyleSheet().addRule("v\\:*", "behavior:url(#default#VML)");
1525
			document.createStyleSheet().addRule("v\\:*", "behavior:url(#default#VML)");
1524
		}
1526
		}
1525
	}catch(e){ }
1527
	}catch(e){ }
1526
 
1528
 
1527
	// stub, over-ridden by debugging code. This will at least keep us from
1529
	// stub, over-ridden by debugging code. This will at least keep us from
1528
	// breaking when it's not included
1530
	// breaking when it's not included
1529
	dojo.hostenv.writeIncludes = function(){}
1531
	dojo.hostenv.writeIncludes = function(){}
1530
 
1532
 
1531
	//TODOC:  HOW TO DOC THIS?
1533
	//TODOC:  HOW TO DOC THIS?
1532
	// @global: dj_currentDocument
1534
	// @global: dj_currentDocument
1533
	// summary:
1535
	// summary:
1534
	//		Current document object. 'dj_currentDocument' can be modified for temporary context shifting.
1536
	//		Current document object. 'dj_currentDocument' can be modified for temporary context shifting.
1535
	// description:
1537
	// description:
1536
	//    dojo.doc() returns dojo.currentDocument.
1538
	//    dojo.doc() returns dojo.currentDocument.
1537
	//		Refer to dojo.doc() rather than referring to 'window.document' to ensure your
1539
	//		Refer to dojo.doc() rather than referring to 'window.document' to ensure your
1538
	//		code runs correctly in managed contexts.
1540
	//		code runs correctly in managed contexts.
1539
	if(!dj_undef("document", this)){
1541
	if(!dj_undef("document", this)){
1540
		dj_currentDocument = this.document;
1542
		dj_currentDocument = this.document;
1541
	}
1543
	}
1542
 
1544
 
1543
	dojo.doc = function(){
1545
	dojo.doc = function(){
1544
		// summary:
1546
		// summary:
1545
		//		return the document object associated with the dojo.global()
1547
		//		return the document object associated with the dojo.global()
1546
		return dj_currentDocument;
1548
		return dj_currentDocument;
1547
	}
1549
	}
1548
 
1550
 
1549
	dojo.body = function(){
1551
	dojo.body = function(){
1550
		// summary:
1552
		// summary:
1551
		//		return the body object associated with dojo.doc()
1553
		//		return the body object associated with dojo.doc()
1552
		// Note: document.body is not defined for a strict xhtml document
1554
		// Note: document.body is not defined for a strict xhtml document
1553
		return dojo.doc().body || dojo.doc().getElementsByTagName("body")[0];
1555
		return dojo.doc().body || dojo.doc().getElementsByTagName("body")[0];
1554
	}
1556
	}
1555
 
1557
 
1556
	dojo.byId = function(/*String*/id, /*DocumentElement*/doc){
1558
	dojo.byId = function(/*String*/id, /*DocumentElement*/doc){
1557
		// summary:
1559
		// summary:
1558
		// 		similar to other library's "$" function, takes a string
1560
		// 		similar to other library's "$" function, takes a string
1559
		// 		representing a DOM id or a DomNode and returns the
1561
		// 		representing a DOM id or a DomNode and returns the
1560
		// 		corresponding DomNode. If a Node is passed, this function is a
1562
		// 		corresponding DomNode. If a Node is passed, this function is a
1561
		// 		no-op. Returns a single DOM node or null, working around
1563
		// 		no-op. Returns a single DOM node or null, working around
1562
		// 		several browser-specific bugs to do so.
1564
		// 		several browser-specific bugs to do so.
1563
		// id: DOM id or DOM Node
1565
		// id: DOM id or DOM Node
1564
		// doc:
1566
		// doc:
1565
		//		optional, defaults to the current value of dj_currentDocument.
1567
		//		optional, defaults to the current value of dj_currentDocument.
1566
		//		Can be used to retreive node references from other documents.
1568
		//		Can be used to retreive node references from other documents.
1567
		if((id)&&((typeof id == "string")||(id instanceof String))){
1569
		if((id)&&((typeof id == "string")||(id instanceof String))){
1568
			if(!doc){ doc = dj_currentDocument; }
1570
			if(!doc){ doc = dj_currentDocument; }
1569
			var ele = doc.getElementById(id);
1571
			var ele = doc.getElementById(id);
1570
			// workaround bug in IE and Opera 8.2 where getElementById returns wrong element
1572
			// workaround bug in IE and Opera 8.2 where getElementById returns wrong element
1571
			if(ele && (ele.id != id) && doc.all){
1573
			if(ele && (ele.id != id) && doc.all){
1572
				ele = null;
1574
				ele = null;
1573
				// get all matching elements with this id
1575
				// get all matching elements with this id
1574
				eles = doc.all[id];
1576
				eles = doc.all[id];
1575
				if(eles){
1577
				if(eles){
1576
					// if more than 1, choose first with the correct id
1578
					// if more than 1, choose first with the correct id
1577
					if(eles.length){
1579
					if(eles.length){
1578
						for(var i=0; i<eles.length; i++){
1580
						for(var i=0; i<eles.length; i++){
1579
							if(eles[i].id == id){
1581
							if(eles[i].id == id){
1580
								ele = eles[i];
1582
								ele = eles[i];
1581
								break;
1583
								break;
1582
							}
1584
							}
1583
						}
1585
						}
1584
					// return 1 and only element
1586
					// return 1 and only element
1585
					}else{
1587
					}else{
1586
						ele = eles;
1588
						ele = eles;
1587
					}
1589
					}
1588
				}
1590
				}
1589
			}
1591
			}
1590
			return ele; // DomNode
1592
			return ele; // DomNode
1591
		}
1593
		}
1592
		return id; // DomNode
1594
		return id; // DomNode
1593
	}
1595
	}
1594
 
1596
 
1595
	dojo.setContext = function(/*Object*/globalObject, /*DocumentElement*/globalDocument){
1597
	dojo.setContext = function(/*Object*/globalObject, /*DocumentElement*/globalDocument){
1596
		// summary:
1598
		// summary:
1597
		//		changes the behavior of many core Dojo functions that deal with
1599
		//		changes the behavior of many core Dojo functions that deal with
1598
		//		namespace and DOM lookup, changing them to work in a new global
1600
		//		namespace and DOM lookup, changing them to work in a new global
1599
		//		context. The varibles dj_currentContext and dj_currentDocument
1601
		//		context. The varibles dj_currentContext and dj_currentDocument
1600
		//		are modified as a result of calling this function.
1602
		//		are modified as a result of calling this function.
1601
		dj_currentContext = globalObject;
1603
		dj_currentContext = globalObject;
1602
		dj_currentDocument = globalDocument;
1604
		dj_currentDocument = globalDocument;
1603
	};
1605
	};
1604
 
1606
 
1605
	dojo._fireCallback = function(callback, context, cbArguments){
1607
	dojo._fireCallback = function(callback, context, cbArguments){
1606
		if((context)&&((typeof callback == "string")||(callback instanceof String))){
1608
		if((context)&&((typeof callback == "string")||(callback instanceof String))){
1607
			callback=context[callback];
1609
			callback=context[callback];
1608
		}
1610
		}
1609
		return (context ? callback.apply(context, cbArguments || [ ]) : callback());
1611
		return (context ? callback.apply(context, cbArguments || [ ]) : callback());
1610
	}
1612
	}
1611
 
1613
 
1612
	dojo.withGlobal = function(/*Object*/globalObject, /*Function*/callback, /*Object?*/thisObject, /*Array?*/cbArguments){
1614
	dojo.withGlobal = function(/*Object*/globalObject, /*Function*/callback, /*Object?*/thisObject, /*Array?*/cbArguments){
1613
		// summary:
1615
		// summary:
1614
		//		Call callback with globalObject as dojo.global() and globalObject.document
1616
		//		Call callback with globalObject as dojo.global() and globalObject.document
1615
		//		as dojo.doc(). If provided, globalObject will be executed in the context of
1617
		//		as dojo.doc(). If provided, globalObject will be executed in the context of
1616
		//		object thisObject
1618
		//		object thisObject
1617
		// description:
1619
		// description:
1618
		//		When callback() returns or throws an error, the dojo.global() and dojo.doc() will
1620
		//		When callback() returns or throws an error, the dojo.global() and dojo.doc() will
1619
		//		be restored to its previous state.
1621
		//		be restored to its previous state.
1620
		var rval;
1622
		var rval;
1621
		var oldGlob = dj_currentContext;
1623
		var oldGlob = dj_currentContext;
1622
		var oldDoc = dj_currentDocument;
1624
		var oldDoc = dj_currentDocument;
1623
		try{
1625
		try{
1624
			dojo.setContext(globalObject, globalObject.document);
1626
			dojo.setContext(globalObject, globalObject.document);
1625
			rval = dojo._fireCallback(callback, thisObject, cbArguments);
1627
			rval = dojo._fireCallback(callback, thisObject, cbArguments);
1626
		}finally{
1628
		}finally{
1627
			dojo.setContext(oldGlob, oldDoc);
1629
			dojo.setContext(oldGlob, oldDoc);
1628
		}
1630
		}
1629
		return rval;
1631
		return rval;
1630
	}
1632
	}
1631
 
1633
 
1632
	dojo.withDoc = function (/*Object*/documentObject, /*Function*/callback, /*Object?*/thisObject, /*Array?*/cbArguments) {
1634
	dojo.withDoc = function (/*Object*/documentObject, /*Function*/callback, /*Object?*/thisObject, /*Array?*/cbArguments) {
1633
		// summary:
1635
		// summary:
1634
		//		Call callback with documentObject as dojo.doc(). If provided, callback will be executed
1636
		//		Call callback with documentObject as dojo.doc(). If provided, callback will be executed
1635
		//		in the context of object thisObject
1637
		//		in the context of object thisObject
1636
		// description:
1638
		// description:
1637
		//		When callback() returns or throws an error, the dojo.doc() will
1639
		//		When callback() returns or throws an error, the dojo.doc() will
1638
		//		be restored to its previous state.
1640
		//		be restored to its previous state.
1639
		var rval;
1641
		var rval;
1640
		var oldDoc = dj_currentDocument;
1642
		var oldDoc = dj_currentDocument;
1641
		try{
1643
		try{
1642
			dj_currentDocument = documentObject;
1644
			dj_currentDocument = documentObject;
1643
			rval = dojo._fireCallback(callback, thisObject, cbArguments);
1645
			rval = dojo._fireCallback(callback, thisObject, cbArguments);
1644
		}finally{
1646
		}finally{
1645
			dj_currentDocument = oldDoc;
1647
			dj_currentDocument = oldDoc;
1646
		}
1648
		}
1647
		return rval;
1649
		return rval;
1648
	}
1650
	}
1649
 
1651
 
1650
} //if (typeof window != 'undefined')
1652
} //if (typeof window != 'undefined')
1651
 
1653
 
1652
//Load debug code if necessary.
1654
//Load debug code if necessary.
1653
dojo.requireIf((djConfig["isDebug"] || djConfig["debugAtAllCosts"]), "dojo.debug");
1655
dojo.requireIf((djConfig["isDebug"] || djConfig["debugAtAllCosts"]), "dojo.debug");
1654
 
1656
 
1655
//window.widget is for Dashboard detection
1657
//window.widget is for Dashboard detection
1656
//The full conditionals are spelled out to avoid issues during builds.
1658
//The full conditionals are spelled out to avoid issues during builds.
1657
//Builds may be looking for require/requireIf statements and processing them.
1659
//Builds may be looking for require/requireIf statements and processing them.
1658
dojo.requireIf(djConfig["debugAtAllCosts"] && !window.widget && !djConfig["useXDomain"], "dojo.browser_debug");
1660
dojo.requireIf(djConfig["debugAtAllCosts"] && !window.widget && !djConfig["useXDomain"], "dojo.browser_debug");
1659
dojo.requireIf(djConfig["debugAtAllCosts"] && !window.widget && djConfig["useXDomain"], "dojo.browser_debug_xd");
1661
dojo.requireIf(djConfig["debugAtAllCosts"] && !window.widget && djConfig["useXDomain"], "dojo.browser_debug_xd");
1660
 
1662
 
1661
dojo.provide("dojo.string.common");
1663
dojo.provide("dojo.string.common");
1662
 
1664
 
1663
dojo.string.trim = function(/* string */str, /* integer? */wh){
1665
dojo.string.trim = function(/* string */str, /* integer? */wh){
1664
	//	summary
1666
	//	summary
1665
	//	Trim whitespace from str.  If wh > 0, trim from start, if wh < 0, trim from end, else both
1667
	//	Trim whitespace from str.  If wh > 0, trim from start, if wh < 0, trim from end, else both
1666
	if(!str.replace){ return str; }
1668
	if(!str.replace){ return str; }
1667
	if(!str.length){ return str; }
1669
	if(!str.length){ return str; }
1668
	var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
1670
	var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
1669
	return str.replace(re, "");	//	string
1671
	return str.replace(re, "");	//	string
1670
}
1672
}
1671
 
1673
 
1672
dojo.string.trimStart = function(/* string */str) {
1674
dojo.string.trimStart = function(/* string */str) {
1673
	//	summary
1675
	//	summary
1674
	//	Trim whitespace at the beginning of 'str'
1676
	//	Trim whitespace at the beginning of 'str'
1675
	return dojo.string.trim(str, 1);	//	string
1677
	return dojo.string.trim(str, 1);	//	string
1676
}
1678
}
1677
 
1679
 
1678
dojo.string.trimEnd = function(/* string */str) {
1680
dojo.string.trimEnd = function(/* string */str) {
1679
	//	summary
1681
	//	summary
1680
	//	Trim whitespace at the end of 'str'
1682
	//	Trim whitespace at the end of 'str'
1681
	return dojo.string.trim(str, -1);
1683
	return dojo.string.trim(str, -1);
1682
}
1684
}
1683
 
1685
 
1684
dojo.string.repeat = function(/* string */str, /* integer */count, /* string? */separator) {
1686
dojo.string.repeat = function(/* string */str, /* integer */count, /* string? */separator) {
1685
	//	summary
1687
	//	summary
1686
	//	Return 'str' repeated 'count' times, optionally placing 'separator' between each rep
1688
	//	Return 'str' repeated 'count' times, optionally placing 'separator' between each rep
1687
	var out = "";
1689
	var out = "";
1688
	for(var i = 0; i < count; i++) {
1690
	for(var i = 0; i < count; i++) {
1689
		out += str;
1691
		out += str;
1690
		if(separator && i < count - 1) {
1692
		if(separator && i < count - 1) {
1691
			out += separator;
1693
			out += separator;
1692
		}
1694
		}
1693
	}
1695
	}
1694
	return out;	//	string
1696
	return out;	//	string
1695
}
1697
}
1696
 
1698
 
1697
dojo.string.pad = function(/* string */str, /* integer */len/*=2*/, /* string */ c/*='0'*/, /* integer */dir/*=1*/) {
1699
dojo.string.pad = function(/* string */str, /* integer */len/*=2*/, /* string */ c/*='0'*/, /* integer */dir/*=1*/) {
1698
	//	summary
1700
	//	summary
1699
	//	Pad 'str' to guarantee that it is at least 'len' length with the character 'c' at either the 
1701
	//	Pad 'str' to guarantee that it is at least 'len' length with the character 'c' at either the 
1700
	//	start (dir=1) or end (dir=-1) of the string
1702
	//	start (dir=1) or end (dir=-1) of the string
1701
	var out = String(str);
1703
	var out = String(str);
1702
	if(!c) {
1704
	if(!c) {
1703
		c = '0';
1705
		c = '0';
1704
	}
1706
	}
1705
	if(!dir) {
1707
	if(!dir) {
1706
		dir = 1;
1708
		dir = 1;
1707
	}
1709
	}
1708
	while(out.length < len) {
1710
	while(out.length < len) {
1709
		if(dir > 0) {
1711
		if(dir > 0) {
1710
			out = c + out;
1712
			out = c + out;
1711
		} else {
1713
		} else {
1712
			out += c;
1714
			out += c;
1713
		}
1715
		}
1714
	}
1716
	}
1715
	return out;	//	string
1717
	return out;	//	string
1716
}
1718
}
1717
 
1719
 
1718
dojo.string.padLeft = function(/* string */str, /* integer */len, /* string */c) {
1720
dojo.string.padLeft = function(/* string */str, /* integer */len, /* string */c) {
1719
	//	summary
1721
	//	summary
1720
	//	same as dojo.string.pad(str, len, c, 1)
1722
	//	same as dojo.string.pad(str, len, c, 1)
1721
	return dojo.string.pad(str, len, c, 1);	//	string
1723
	return dojo.string.pad(str, len, c, 1);	//	string
1722
}
1724
}
1723
 
1725
 
1724
dojo.string.padRight = function(/* string */str, /* integer */len, /* string */c) {
1726
dojo.string.padRight = function(/* string */str, /* integer */len, /* string */c) {
1725
	//	summary
1727
	//	summary
1726
	//	same as dojo.string.pad(str, len, c, -1)
1728
	//	same as dojo.string.pad(str, len, c, -1)
1727
	return dojo.string.pad(str, len, c, -1);	//	string
1729
	return dojo.string.pad(str, len, c, -1);	//	string
1728
}
1730
}
1729
 
1731
 
1730
dojo.provide("dojo.string");
1732
dojo.provide("dojo.string");
1731
 
1733
 
1732
 
1734
 
1733
dojo.provide("dojo.lang.common");
1735
dojo.provide("dojo.lang.common");
1734
 
1736
 
1735
dojo.lang.inherits = function(/*Function*/subclass, /*Function*/superclass){
1737
dojo.lang.inherits = function(/*Function*/subclass, /*Function*/superclass){
1736
	// summary: Set up inheritance between two classes.
1738
	// summary: Set up inheritance between two classes.
1737
	if(!dojo.lang.isFunction(superclass)){ 
1739
	if(!dojo.lang.isFunction(superclass)){ 
1738
		dojo.raise("dojo.inherits: superclass argument ["+superclass+"] must be a function (subclass: ["+subclass+"']");
1740
		dojo.raise("dojo.inherits: superclass argument ["+superclass+"] must be a function (subclass: ["+subclass+"']");
1739
	}
1741
	}
1740
	subclass.prototype = new superclass();
1742
	subclass.prototype = new superclass();
1741
	subclass.prototype.constructor = subclass;
1743
	subclass.prototype.constructor = subclass;
1742
	subclass.superclass = superclass.prototype;
1744
	subclass.superclass = superclass.prototype;
1743
	// DEPRECATED: super is a reserved word, use 'superclass'
1745
	// DEPRECATED: super is a reserved word, use 'superclass'
1744
	subclass['super'] = superclass.prototype;
1746
	subclass['super'] = superclass.prototype;
1745
}
1747
}
1746
 
1748
 
1747
dojo.lang._mixin = function(/*Object*/ obj, /*Object*/ props){
1749
dojo.lang._mixin = function(/*Object*/ obj, /*Object*/ props){
1748
	// summary:
1750
	// summary:
1749
	//		Adds all properties and methods of props to obj. This addition is
1751
	//		Adds all properties and methods of props to obj. This addition is
1750
	//		"prototype extension safe", so that instances of objects will not
1752
	//		"prototype extension safe", so that instances of objects will not
1751
	//		pass along prototype defaults.
1753
	//		pass along prototype defaults.
1752
	var tobj = {};
1754
	var tobj = {};
1753
	for(var x in props){
1755
	for(var x in props){
1754
		// the "tobj" condition avoid copying properties in "props"
1756
		// the "tobj" condition avoid copying properties in "props"
1755
		// inherited from Object.prototype.  For example, if obj has a custom
1757
		// inherited from Object.prototype.  For example, if obj has a custom
1756
		// toString() method, don't overwrite it with the toString() method
1758
		// toString() method, don't overwrite it with the toString() method
1757
		// that props inherited from Object.protoype
1759
		// that props inherited from Object.protoype
1758
		if((typeof tobj[x] == "undefined") || (tobj[x] != props[x])){
1760
		if((typeof tobj[x] == "undefined") || (tobj[x] != props[x])){
1759
			obj[x] = props[x];
1761
			obj[x] = props[x];
1760
		}
1762
		}
1761
	}
1763
	}
1762
	// IE doesn't recognize custom toStrings in for..in
1764
	// IE doesn't recognize custom toStrings in for..in
1763
	if(dojo.render.html.ie 
1765
	if(dojo.render.html.ie 
1764
		&& (typeof(props["toString"]) == "function")
1766
		&& (typeof(props["toString"]) == "function")
1765
		&& (props["toString"] != obj["toString"])
1767
		&& (props["toString"] != obj["toString"])
1766
		&& (props["toString"] != tobj["toString"]))
1768
		&& (props["toString"] != tobj["toString"]))
1767
	{
1769
	{
1768
		obj.toString = props.toString;
1770
		obj.toString = props.toString;
1769
	}
1771
	}
1770
	return obj; // Object
1772
	return obj; // Object
1771
}
1773
}
1772
 
1774
 
1773
dojo.lang.mixin = function(/*Object*/obj, /*Object...*/props){
1775
dojo.lang.mixin = function(/*Object*/obj, /*Object...*/props){
1774
	// summary:	Adds all properties and methods of props to obj. 
1776
	// summary:	Adds all properties and methods of props to obj. 
1775
	for(var i=1, l=arguments.length; i<l; i++){
1777
	for(var i=1, l=arguments.length; i<l; i++){
1776
		dojo.lang._mixin(obj, arguments[i]);
1778
		dojo.lang._mixin(obj, arguments[i]);
1777
	}
1779
	}
1778
	return obj; // Object
1780
	return obj; // Object
1779
}
1781
}
1780
 
1782
 
1781
dojo.lang.extend = function(/*Object*/ constructor, /*Object...*/ props){
1783
dojo.lang.extend = function(/*Object*/ constructor, /*Object...*/ props){
1782
	// summary:
1784
	// summary:
1783
	//		Adds all properties and methods of props to constructor's
1785
	//		Adds all properties and methods of props to constructor's
1784
	//		prototype, making them available to all instances created with
1786
	//		prototype, making them available to all instances created with
1785
	//		constructor.
1787
	//		constructor.
1786
	for(var i=1, l=arguments.length; i<l; i++){
1788
	for(var i=1, l=arguments.length; i<l; i++){
1787
		dojo.lang._mixin(constructor.prototype, arguments[i]);
1789
		dojo.lang._mixin(constructor.prototype, arguments[i]);
1788
	}
1790
	}
1789
	return constructor; // Object
1791
	return constructor; // Object
1790
}
1792
}
1791
 
1793
 
1792
// Promote to dojo module
1794
// Promote to dojo module
1793
dojo.inherits = dojo.lang.inherits;
1795
dojo.inherits = dojo.lang.inherits;
1794
//dojo.lang._mixin = dojo.lang._mixin;
1796
//dojo.lang._mixin = dojo.lang._mixin;
1795
dojo.mixin = dojo.lang.mixin;
1797
dojo.mixin = dojo.lang.mixin;
1796
dojo.extend = dojo.lang.extend;
1798
dojo.extend = dojo.lang.extend;
1797
 
1799
 
1798
dojo.lang.find = function(	/*Array*/		array, 
1800
dojo.lang.find = function(	/*Array*/		array, 
1799
							/*Object*/		value,
1801
							/*Object*/		value,
1800
							/*Boolean?*/	identity,
1802
							/*Boolean?*/	identity,
1801
							/*Boolean?*/	findLast){
1803
							/*Boolean?*/	findLast){
1802
	// summary:	
1804
	// summary:	
1803
	//		Return the index of value in array, returning -1 if not found.
1805
	//		Return the index of value in array, returning -1 if not found.
1804
	// array: just what you think
1806
	// array: just what you think
1805
	// value: the value to locate
1807
	// value: the value to locate
1806
	// identity: 
1808
	// identity: 
1807
	//		If true, matches with identity comparison (===). If false, uses
1809
	//		If true, matches with identity comparison (===). If false, uses
1808
	//		normal comparison (==).
1810
	//		normal comparison (==).
1809
	// findLast: 
1811
	// findLast: 
1810
	//		If true, returns index of last instance of value.
1812
	//		If true, returns index of last instance of value.
1811
	// examples:
1813
	// examples:
1812
	//		find(array, value[, identity [findLast]]) // recommended
1814
	//		find(array, value[, identity [findLast]]) // recommended
1813
 	//		find(value, array[, identity [findLast]]) // deprecated
1815
 	//		find(value, array[, identity [findLast]]) // deprecated
1814
							
1816
							
1815
	// support both (array, value) and (value, array)
1817
	// support both (array, value) and (value, array)
1816
	if(!dojo.lang.isArrayLike(array) && dojo.lang.isArrayLike(value)) {
1818
	if(!dojo.lang.isArrayLike(array) && dojo.lang.isArrayLike(value)) {
1817
		dojo.deprecated('dojo.lang.find(value, array)', 'use dojo.lang.find(array, value) instead', "0.5");
1819
		dojo.deprecated('dojo.lang.find(value, array)', 'use dojo.lang.find(array, value) instead', "0.5");
1818
		var temp = array;
1820
		var temp = array;
1819
		array = value;
1821
		array = value;
1820
		value = temp;
1822
		value = temp;
1821
	}
1823
	}
1822
	var isString = dojo.lang.isString(array);
1824
	var isString = dojo.lang.isString(array);
1823
	if(isString) { array = array.split(""); }
1825
	if(isString) { array = array.split(""); }
1824
 
1826
 
1825
	if(findLast) {
1827
	if(findLast) {
1826
		var step = -1;
1828
		var step = -1;
1827
		var i = array.length - 1;
1829
		var i = array.length - 1;
1828
		var end = -1;
1830
		var end = -1;
1829
	} else {
1831
	} else {
1830
		var step = 1;
1832
		var step = 1;
1831
		var i = 0;
1833
		var i = 0;
1832
		var end = array.length;
1834
		var end = array.length;
1833
	}
1835
	}
1834
	if(identity){
1836
	if(identity){
1835
		while(i != end) {
1837
		while(i != end) {
1836
			if(array[i] === value){ return i; }
1838
			if(array[i] === value){ return i; }
1837
			i += step;
1839
			i += step;
1838
		}
1840
		}
1839
	}else{
1841
	}else{
1840
		while(i != end) {
1842
		while(i != end) {
1841
			if(array[i] == value){ return i; }
1843
			if(array[i] == value){ return i; }
1842
			i += step;
1844
			i += step;
1843
		}
1845
		}
1844
	}
1846
	}
1845
	return -1;	// number
1847
	return -1;	// number
1846
}
1848
}
1847
 
1849
 
1848
dojo.lang.indexOf = dojo.lang.find;
1850
dojo.lang.indexOf = dojo.lang.find;
1849
 
1851
 
1850
dojo.lang.findLast = function(/*Array*/array, /*Object*/value, /*boolean?*/identity){
1852
dojo.lang.findLast = function(/*Array*/array, /*Object*/value, /*boolean?*/identity){
1851
	// summary:
1853
	// summary:
1852
	//		Return index of last occurance of value in array, returning -1 if
1854
	//		Return index of last occurance of value in array, returning -1 if
1853
	//		not found. This is a shortcut for dojo.lang.find() with a true
1855
	//		not found. This is a shortcut for dojo.lang.find() with a true
1854
	//		value for its "findLast" parameter.
1856
	//		value for its "findLast" parameter.
1855
	// identity:
1857
	// identity:
1856
	//		If true, matches with identity comparison (===). If false, uses
1858
	//		If true, matches with identity comparison (===). If false, uses
1857
	//		normal comparison (==).
1859
	//		normal comparison (==).
1858
	return dojo.lang.find(array, value, identity, true); // number
1860
	return dojo.lang.find(array, value, identity, true); // number
1859
}
1861
}
1860
 
1862
 
1861
dojo.lang.lastIndexOf = dojo.lang.findLast;
1863
dojo.lang.lastIndexOf = dojo.lang.findLast;
1862
 
1864
 
1863
dojo.lang.inArray = function(array /*Array*/, value /*Object*/){
1865
dojo.lang.inArray = function(array /*Array*/, value /*Object*/){
1864
	// summary:	Return true if value is present in array.
1866
	// summary:	Return true if value is present in array.
1865
	return dojo.lang.find(array, value) > -1; // boolean
1867
	return dojo.lang.find(array, value) > -1; // boolean
1866
}
1868
}
1867
 
1869
 
1868
/**
1870
/**
1869
 * Partial implmentation of is* functions from
1871
 * Partial implmentation of is* functions from
1870
 * http://www.crockford.com/javascript/recommend.html
1872
 * http://www.crockford.com/javascript/recommend.html
1871
 * NOTE: some of these may not be the best thing to use in all situations
1873
 * NOTE: some of these may not be the best thing to use in all situations
1872
 * as they aren't part of core JS and therefore can't work in every case.
1874
 * as they aren't part of core JS and therefore can't work in every case.
1873
 * See WARNING messages inline for tips.
1875
 * See WARNING messages inline for tips.
1874
 *
1876
 *
1875
 * The following is* functions are fairly "safe"
1877
 * The following is* functions are fairly "safe"
1876
 */
1878
 */
1877
 
1879
 
1878
dojo.lang.isObject = function(/*anything*/ it){
1880
dojo.lang.isObject = function(/*anything*/ it){
1879
	// summary:	Return true if it is an Object, Array or Function.
1881
	// summary:	Return true if it is an Object, Array or Function.
1880
	if(typeof it == "undefined"){ return false; }
1882
	if(typeof it == "undefined"){ return false; }
1881
	return (typeof it == "object" || it === null || dojo.lang.isArray(it) || dojo.lang.isFunction(it)); // Boolean
1883
	return (typeof it == "object" || it === null || dojo.lang.isArray(it) || dojo.lang.isFunction(it)); // Boolean
1882
}
1884
}
1883
 
1885
 
1884
dojo.lang.isArray = function(/*anything*/ it){
1886
dojo.lang.isArray = function(/*anything*/ it){
1885
	// summary:	Return true if it is an Array.
1887
	// summary:	Return true if it is an Array.
1886
	return (it && it instanceof Array || typeof it == "array"); // Boolean
1888
	return (it && it instanceof Array || typeof it == "array"); // Boolean
1887
}
1889
}
1888
 
1890
 
1889
dojo.lang.isArrayLike = function(/*anything*/ it){
1891
dojo.lang.isArrayLike = function(/*anything*/ it){
1890
	// summary:	
1892
	// summary:	
1891
	//		Return true if it can be used as an array (i.e. is an object with
1893
	//		Return true if it can be used as an array (i.e. is an object with
1892
	//		an integer length property).
1894
	//		an integer length property).
1893
	if((!it)||(dojo.lang.isUndefined(it))){ return false; }
1895
	if((!it)||(dojo.lang.isUndefined(it))){ return false; }
1894
	if(dojo.lang.isString(it)){ return false; }
1896
	if(dojo.lang.isString(it)){ return false; }
1895
	if(dojo.lang.isFunction(it)){ return false; } // keeps out built-in constructors (Number, String, ...) which have length properties
1897
	if(dojo.lang.isFunction(it)){ return false; } // keeps out built-in constructors (Number, String, ...) which have length properties
1896
	if(dojo.lang.isArray(it)){ return true; }
1898
	if(dojo.lang.isArray(it)){ return true; }
1897
	// form node itself is ArrayLike, but not always iterable. Use form.elements instead.
1899
	// form node itself is ArrayLike, but not always iterable. Use form.elements instead.
1898
	if((it.tagName)&&(it.tagName.toLowerCase()=='form')){ return false; }
1900
	if((it.tagName)&&(it.tagName.toLowerCase()=='form')){ return false; }
1899
	if(dojo.lang.isNumber(it.length) && isFinite(it.length)){ return true; }
1901
	if(dojo.lang.isNumber(it.length) && isFinite(it.length)){ return true; }
1900
	return false; // Boolean
1902
	return false; // Boolean
1901
}
1903
}
1902
 
1904
 
1903
dojo.lang.isFunction = function(/*anything*/ it){
1905
dojo.lang.isFunction = function(/*anything*/ it){
1904
	// summary:	Return true if it is a Function.
1906
	// summary:	Return true if it is a Function.
1905
	return (it instanceof Function || typeof it == "function"); // Boolean
1907
	return (it instanceof Function || typeof it == "function"); // Boolean
1906
};
1908
};
1907
 
1909
 
1908
(function(){
1910
(function(){
1909
	// webkit treats NodeList as a function, which is bad
1911
	// webkit treats NodeList as a function, which is bad
1910
	if((dojo.render.html.capable)&&(dojo.render.html["safari"])){
1912
	if((dojo.render.html.capable)&&(dojo.render.html["safari"])){
1911
		dojo.lang.isFunction = function(/*anything*/ it){
1913
		dojo.lang.isFunction = function(/*anything*/ it){
1912
			if((typeof(it) == "function") && (it == "[object NodeList]")) { return false; }
1914
			if((typeof(it) == "function") && (it == "[object NodeList]")) { return false; }
1913
			return (it instanceof Function || typeof it == "function"); // Boolean
1915
			return (it instanceof Function || typeof it == "function"); // Boolean
1914
		}
1916
		}
1915
	}
1917
	}
1916
})();
1918
})();
1917
 
1919
 
1918
dojo.lang.isString = function(/*anything*/ it){
1920
dojo.lang.isString = function(/*anything*/ it){
1919
	// summary:	Return true if it is a String.
1921
	// summary:	Return true if it is a String.
1920
	return (typeof it == "string" || it instanceof String);
1922
	return (typeof it == "string" || it instanceof String);
1921
}
1923
}
1922
 
1924
 
1923
dojo.lang.isAlien = function(/*anything*/ it){
1925
dojo.lang.isAlien = function(/*anything*/ it){
1924
	// summary: Return true if it is not a built-in function. False if not.
1926
	// summary: Return true if it is not a built-in function. False if not.
1925
	if(!it){ return false; }
1927
	if(!it){ return false; }
1926
	return !dojo.lang.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
1928
	return !dojo.lang.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
1927
}
1929
}
1928
 
1930
 
1929
dojo.lang.isBoolean = function(/*anything*/ it){
1931
dojo.lang.isBoolean = function(/*anything*/ it){
1930
	// summary:	Return true if it is a Boolean.
1932
	// summary:	Return true if it is a Boolean.
1931
	return (it instanceof Boolean || typeof it == "boolean"); // Boolean
1933
	return (it instanceof Boolean || typeof it == "boolean"); // Boolean
1932
}
1934
}
1933
 
1935
 
1934
/**
1936
/**
1935
 * The following is***() functions are somewhat "unsafe". Fortunately,
1937
 * The following is***() functions are somewhat "unsafe". Fortunately,
1936
 * there are workarounds the the language provides and are mentioned
1938
 * there are workarounds the the language provides and are mentioned
1937
 * in the WARNING messages.
1939
 * in the WARNING messages.
1938
 *
1940
 *
1939
 */
1941
 */
1940
dojo.lang.isNumber = function(/*anything*/ it){
1942
dojo.lang.isNumber = function(/*anything*/ it){
1941
	// summary:	Return true if it is a number.
1943
	// summary:	Return true if it is a number.
1942
	// description: 
1944
	// description: 
1943
	//		WARNING - In most cases, isNaN(it) is sufficient to determine whether or not
1945
	//		WARNING - In most cases, isNaN(it) is sufficient to determine whether or not
1944
	// 		something is a number or can be used as such. For example, a number or string
1946
	// 		something is a number or can be used as such. For example, a number or string
1945
	// 		can be used interchangably when accessing array items (array["1"] is the same as
1947
	// 		can be used interchangably when accessing array items (array["1"] is the same as
1946
	// 		array[1]) and isNaN will return false for both values ("1" and 1). However,
1948
	// 		array[1]) and isNaN will return false for both values ("1" and 1). However,
1947
	// 		isNumber("1")  will return false, which is generally not too useful.
1949
	// 		isNumber("1")  will return false, which is generally not too useful.
1948
	// 		Also, isNumber(NaN) returns true, again, this isn't generally useful, but there
1950
	// 		Also, isNumber(NaN) returns true, again, this isn't generally useful, but there
1949
	// 		are corner cases (like when you want to make sure that two things are really
1951
	// 		are corner cases (like when you want to make sure that two things are really
1950
	// 		the same type of thing). That is really where isNumber "shines".
1952
	// 		the same type of thing). That is really where isNumber "shines".
1951
	//
1953
	//
1952
	// Recommendation - Use isNaN(it) when possible
1954
	// Recommendation - Use isNaN(it) when possible
1953
	
1955
	
1954
	return (it instanceof Number || typeof it == "number"); // Boolean
1956
	return (it instanceof Number || typeof it == "number"); // Boolean
1955
}
1957
}
1956
 
1958
 
1957
/*
1959
/*
1958
 * FIXME: Should isUndefined go away since it is error prone?
1960
 * FIXME: Should isUndefined go away since it is error prone?
1959
 */
1961
 */
1960
dojo.lang.isUndefined = function(/*anything*/ it){
1962
dojo.lang.isUndefined = function(/*anything*/ it){
1961
	// summary: Return true if it is not defined.
1963
	// summary: Return true if it is not defined.
1962
	// description: 
1964
	// description: 
1963
	//		WARNING - In some cases, isUndefined will not behave as you
1965
	//		WARNING - In some cases, isUndefined will not behave as you
1964
	// 		might expect. If you do isUndefined(foo) and there is no earlier
1966
	// 		might expect. If you do isUndefined(foo) and there is no earlier
1965
	// 		reference to foo, an error will be thrown before isUndefined is
1967
	// 		reference to foo, an error will be thrown before isUndefined is
1966
	// 		called. It behaves correctly if you scope yor object first, i.e.
1968
	// 		called. It behaves correctly if you scope yor object first, i.e.
1967
	// 		isUndefined(foo.bar) where foo is an object and bar isn't a
1969
	// 		isUndefined(foo.bar) where foo is an object and bar isn't a
1968
	// 		property of the object.
1970
	// 		property of the object.
1969
	//
1971
	//
1970
	// Recommendation - Use typeof foo == "undefined" when possible
1972
	// Recommendation - Use typeof foo == "undefined" when possible
1971
 
1973
 
1972
	return ((typeof(it) == "undefined")&&(it == undefined)); // Boolean
1974
	return ((typeof(it) == "undefined")&&(it == undefined)); // Boolean
1973
}
1975
}
1974
 
1976
 
1975
// end Crockford functions
1977
// end Crockford functions
1976
 
1978
 
1977
dojo.provide("dojo.lang.extras");
1979
dojo.provide("dojo.lang.extras");
1978
 
1980
 
1979
 
1981
 
1980
 
1982
 
1981
dojo.lang.setTimeout = function(/*Function*/func, /*int*/delay /*, ...*/){
1983
dojo.lang.setTimeout = function(/*Function*/func, /*int*/delay /*, ...*/){
1982
	// summary:
1984
	// summary:
1983
	//		Sets a timeout in milliseconds to execute a function in a given
1985
	//		Sets a timeout in milliseconds to execute a function in a given
1984
	//		context with optional arguments.
1986
	//		context with optional arguments.
1985
	// usage:
1987
	// usage:
1986
	//		dojo.lang.setTimeout(Object context, function func, number delay[, arg1[, ...]]);
1988
	//		dojo.lang.setTimeout(Object context, function func, number delay[, arg1[, ...]]);
1987
	//		dojo.lang.setTimeout(function func, number delay[, arg1[, ...]]);
1989
	//		dojo.lang.setTimeout(function func, number delay[, arg1[, ...]]);
1988
 
1990
 
1989
	var context = window, argsStart = 2;
1991
	var context = window, argsStart = 2;
1990
	if(!dojo.lang.isFunction(func)){
1992
	if(!dojo.lang.isFunction(func)){
1991
		context = func;
1993
		context = func;
1992
		func = delay;
1994
		func = delay;
1993
		delay = arguments[2];
1995
		delay = arguments[2];
1994
		argsStart++;
1996
		argsStart++;
1995
	}
1997
	}
1996
 
1998
 
1997
	if(dojo.lang.isString(func)){
1999
	if(dojo.lang.isString(func)){
1998
		func = context[func];
2000
		func = context[func];
1999
	}
2001
	}
2000
	
2002
	
2001
	var args = [];
2003
	var args = [];
2002
	for (var i = argsStart; i < arguments.length; i++){
2004
	for (var i = argsStart; i < arguments.length; i++){
2003
		args.push(arguments[i]);
2005
		args.push(arguments[i]);
2004
	}
2006
	}
2005
	return dojo.global().setTimeout(function(){ func.apply(context, args); }, delay); // int
2007
	return dojo.global().setTimeout(function(){ func.apply(context, args); }, delay); // int
2006
}
2008
}
2007
 
2009
 
2008
dojo.lang.clearTimeout = function(/*int*/timer){
2010
dojo.lang.clearTimeout = function(/*int*/timer){
2009
	// summary: clears timer by number from the execution queue
2011
	// summary: clears timer by number from the execution queue
2010
 
2012
 
2011
	// FIXME:
2013
	// FIXME:
2012
	//		why do we have this function? It's not portable outside of browser
2014
	//		why do we have this function? It's not portable outside of browser
2013
	//		environments and it's a stupid wrapper on something that browsers
2015
	//		environments and it's a stupid wrapper on something that browsers
2014
	//		provide anyway.
2016
	//		provide anyway.
2015
	dojo.global().clearTimeout(timer);
2017
	dojo.global().clearTimeout(timer);
2016
}
2018
}
2017
 
2019
 
2018
dojo.lang.getNameInObj = function(/*Object*/ns, /*unknown*/item){
2020
dojo.lang.getNameInObj = function(/*Object*/ns, /*unknown*/item){
2019
	// summary: 
2021
	// summary: 
2020
	//		looks for a value in the object ns with a value matching item and
2022
	//		looks for a value in the object ns with a value matching item and
2021
	//		returns the property name
2023
	//		returns the property name
2022
	// ns: if null, dj_global is used
2024
	// ns: if null, dj_global is used
2023
	// item: value to return a name for
2025
	// item: value to return a name for
2024
	if(!ns){ ns = dj_global; }
2026
	if(!ns){ ns = dj_global; }
2025
 
2027
 
2026
	for(var x in ns){
2028
	for(var x in ns){
2027
		if(ns[x] === item){
2029
		if(ns[x] === item){
2028
			return new String(x); // String
2030
			return new String(x); // String
2029
		}
2031
		}
2030
	}
2032
	}
2031
	return null; // null
2033
	return null; // null
2032
}
2034
}
2033
 
2035
 
2034
dojo.lang.shallowCopy = function(/*Object*/obj, /*Boolean?*/deep){
2036
dojo.lang.shallowCopy = function(/*Object*/obj, /*Boolean?*/deep){
2035
	// summary:
2037
	// summary:
2036
	//		copies object obj one level deep, or full depth if deep is true
2038
	//		copies object obj one level deep, or full depth if deep is true
2037
	var i, ret;	
2039
	var i, ret;	
2038
 
2040
 
2039
	if(obj === null){ /*obj: null*/ return null; } // null
2041
	if(obj === null){ /*obj: null*/ return null; } // null
2040
	
2042
	
2041
	if(dojo.lang.isObject(obj)){
2043
	if(dojo.lang.isObject(obj)){
2042
		// obj: Object	
2044
		// obj: Object	
2043
		ret = new obj.constructor();
2045
		ret = new obj.constructor();
2044
		for(i in obj){
2046
		for(i in obj){
2045
			if(dojo.lang.isUndefined(ret[i])){
2047
			if(dojo.lang.isUndefined(ret[i])){
2046
				ret[i] = deep ? dojo.lang.shallowCopy(obj[i], deep) : obj[i];
2048
				ret[i] = deep ? dojo.lang.shallowCopy(obj[i], deep) : obj[i];
2047
			}
2049
			}
2048
		}
2050
		}
2049
	}else if(dojo.lang.isArray(obj)){
2051
	}else if(dojo.lang.isArray(obj)){
2050
		// obj: Array
2052
		// obj: Array
2051
		ret = [];
2053
		ret = [];
2052
		for(i=0; i<obj.length; i++){
2054
		for(i=0; i<obj.length; i++){
2053
			ret[i] = deep ? dojo.lang.shallowCopy(obj[i], deep) : obj[i];
2055
			ret[i] = deep ? dojo.lang.shallowCopy(obj[i], deep) : obj[i];
2054
		}
2056
		}
2055
	}else{
2057
	}else{
2056
		// obj: Object
2058
		// obj: Object
2057
		ret = obj;
2059
		ret = obj;
2058
	}
2060
	}
2059
 
2061
 
2060
	return ret; // Object
2062
	return ret; // Object
2061
}
2063
}
2062
 
2064
 
2063
dojo.lang.firstValued = function(/* ... */){
2065
dojo.lang.firstValued = function(/* ... */){
2064
	// summary: Return the first argument that isn't undefined
2066
	// summary: Return the first argument that isn't undefined
2065
 
2067
 
2066
	for(var i = 0; i < arguments.length; i++){
2068
	for(var i = 0; i < arguments.length; i++){
2067
		if(typeof arguments[i] != "undefined"){
2069
		if(typeof arguments[i] != "undefined"){
2068
			return arguments[i]; // Object
2070
			return arguments[i]; // Object
2069
		}
2071
		}
2070
	}
2072
	}
2071
	return undefined; // undefined
2073
	return undefined; // undefined
2072
}
2074
}
2073
 
2075
 
2074
dojo.lang.getObjPathValue = function(/*String*/objpath, /*Object?*/context, /*Boolean?*/create){
2076
dojo.lang.getObjPathValue = function(/*String*/objpath, /*Object?*/context, /*Boolean?*/create){
2075
	// summary:
2077
	// summary:
2076
	//		Gets a value from a reference specified as a string descriptor,
2078
	//		Gets a value from a reference specified as a string descriptor,
2077
	//		(e.g. "A.B") in the given context.
2079
	//		(e.g. "A.B") in the given context.
2078
	// context: if not specified, dj_global is used
2080
	// context: if not specified, dj_global is used
2079
	// create: if true, undefined objects in the path are created.
2081
	// create: if true, undefined objects in the path are created.
2080
	with(dojo.parseObjPath(objpath, context, create)){
2082
	with(dojo.parseObjPath(objpath, context, create)){
2081
		return dojo.evalProp(prop, obj, create); // Object
2083
		return dojo.evalProp(prop, obj, create); // Object
2082
	}
2084
	}
2083
}
2085
}
2084
 
2086
 
2085
dojo.lang.setObjPathValue = function(/*String*/objpath, /*anything*/value, /*Object?*/context, /*Boolean?*/create){
2087
dojo.lang.setObjPathValue = function(/*String*/objpath, /*anything*/value, /*Object?*/context, /*Boolean?*/create){
2086
	// summary:
2088
	// summary:
2087
	//		Sets a value on a reference specified as a string descriptor.
2089
	//		Sets a value on a reference specified as a string descriptor.
2088
	//		(e.g. "A.B") in the given context. This is similar to straight
2090
	//		(e.g. "A.B") in the given context. This is similar to straight
2089
	//		assignment, except that the object structure in question can
2091
	//		assignment, except that the object structure in question can
2090
	//		optionally be created if it does not exist.
2092
	//		optionally be created if it does not exist.
2091
	//	context: if not specified, dj_global is used
2093
	//	context: if not specified, dj_global is used
2092
	//	create: if true, undefined objects in the path are created.
2094
	//	create: if true, undefined objects in the path are created.
2093
 
2095
 
2094
	// FIXME: why is this function valuable? It should be scheduled for
2096
	// FIXME: why is this function valuable? It should be scheduled for
2095
	// removal on the grounds that dojo.parseObjPath does most of it's work and
2097
	// removal on the grounds that dojo.parseObjPath does most of it's work and
2096
	// is more straightforward and has fewer dependencies. Also, the order of
2098
	// is more straightforward and has fewer dependencies. Also, the order of
2097
	// arguments is bone-headed. "context" should clearly come after "create".
2099
	// arguments is bone-headed. "context" should clearly come after "create".
2098
	// *sigh*
2100
	// *sigh*
2099
	dojo.deprecated("dojo.lang.setObjPathValue", "use dojo.parseObjPath and the '=' operator", "0.6");
2101
	dojo.deprecated("dojo.lang.setObjPathValue", "use dojo.parseObjPath and the '=' operator", "0.6");
2100
 
2102
 
2101
	if(arguments.length < 4){
2103
	if(arguments.length < 4){
2102
		create = true;
2104
		create = true;
2103
	}
2105
	}
2104
	with(dojo.parseObjPath(objpath, context, create)){
2106
	with(dojo.parseObjPath(objpath, context, create)){
2105
		if(obj && (create || (prop in obj))){
2107
		if(obj && (create || (prop in obj))){
2106
			obj[prop] = value;
2108
			obj[prop] = value;
2107
		}
2109
		}
2108
	}
2110
	}
2109
}
2111
}
2110
 
2112
 
2111
dojo.provide("dojo.io.common");
2113
dojo.provide("dojo.io.common");
2112
 
2114
 
2113
 
2115
 
2114
 
2116
 
2115
/******************************************************************************
2117
/******************************************************************************
2116
 *	Notes about dojo.io design:
2118
 *	Notes about dojo.io design:
2117
 *	
2119
 *	
2118
 *	The dojo.io.* package has the unenviable task of making a lot of different
2120
 *	The dojo.io.* package has the unenviable task of making a lot of different
2119
 *	types of I/O feel natural, despite a universal lack of good (or even
2121
 *	types of I/O feel natural, despite a universal lack of good (or even
2120
 *	reasonable!) I/O capability in the host environment. So lets pin this down
2122
 *	reasonable!) I/O capability in the host environment. So lets pin this down
2121
 *	a little bit further.
2123
 *	a little bit further.
2122
 *
2124
 *
2123
 *	Rhino:
2125
 *	Rhino:
2124
 *		perhaps the best situation anywhere. Access to Java classes allows you
2126
 *		perhaps the best situation anywhere. Access to Java classes allows you
2125
 *		to do anything one might want in terms of I/O, both synchronously and
2127
 *		to do anything one might want in terms of I/O, both synchronously and
2126
 *		async. Can open TCP sockets and perform low-latency client/server
2128
 *		async. Can open TCP sockets and perform low-latency client/server
2127
 *		interactions. HTTP transport is available through Java HTTP client and
2129
 *		interactions. HTTP transport is available through Java HTTP client and
2128
 *		server classes. Wish it were always this easy.
2130
 *		server classes. Wish it were always this easy.
2129
 *
2131
 *
2130
 *	xpcshell:
2132
 *	xpcshell:
2131
 *		XPCOM for I/O.
2133
 *		XPCOM for I/O.
2132
 *
2134
 *
2133
 *	spidermonkey:
2135
 *	spidermonkey:
2134
 *		S.O.L.
2136
 *		S.O.L.
2135
 *
2137
 *
2136
 *	Browsers:
2138
 *	Browsers:
2137
 *		Browsers generally do not provide any useable filesystem access. We are
2139
 *		Browsers generally do not provide any useable filesystem access. We are
2138
 *		therefore limited to HTTP for moving information to and from Dojo
2140
 *		therefore limited to HTTP for moving information to and from Dojo
2139
 *		instances living in a browser.
2141
 *		instances living in a browser.
2140
 *
2142
 *
2141
 *		XMLHTTP:
2143
 *		XMLHTTP:
2142
 *			Sync or async, allows reading of arbitrary text files (including
2144
 *			Sync or async, allows reading of arbitrary text files (including
2143
 *			JS, which can then be eval()'d), writing requires server
2145
 *			JS, which can then be eval()'d), writing requires server
2144
 *			cooperation and is limited to HTTP mechanisms (POST and GET).
2146
 *			cooperation and is limited to HTTP mechanisms (POST and GET).
2145
 *
2147
 *
2146
 *		<iframe> hacks:
2148
 *		<iframe> hacks:
2147
 *			iframe document hacks allow browsers to communicate asynchronously
2149
 *			iframe document hacks allow browsers to communicate asynchronously
2148
 *			with a server via HTTP POST and GET operations. With significant
2150
 *			with a server via HTTP POST and GET operations. With significant
2149
 *			effort and server cooperation, low-latency data transit between
2151
 *			effort and server cooperation, low-latency data transit between
2150
 *			client and server can be acheived via iframe mechanisms (repubsub).
2152
 *			client and server can be acheived via iframe mechanisms (repubsub).
2151
 *
2153
 *
2152
 *		SVG:
2154
 *		SVG:
2153
 *			Adobe's SVG viewer implements helpful primitives for XML-based
2155
 *			Adobe's SVG viewer implements helpful primitives for XML-based
2154
 *			requests, but receipt of arbitrary text data seems unlikely w/o
2156
 *			requests, but receipt of arbitrary text data seems unlikely w/o
2155
 *			<![CDATA[]]> sections.
2157
 *			<![CDATA[]]> sections.
2156
 *
2158
 *
2157
 *
2159
 *
2158
 *	A discussion between Dylan, Mark, Tom, and Alex helped to lay down a lot
2160
 *	A discussion between Dylan, Mark, Tom, and Alex helped to lay down a lot
2159
 *	the IO API interface. A transcript of it can be found at:
2161
 *	the IO API interface. A transcript of it can be found at:
2160
 *		http://dojotoolkit.org/viewcvs/viewcvs.py/documents/irc/irc_io_api_log.txt?rev=307&view=auto
2162
 *		http://dojotoolkit.org/viewcvs/viewcvs.py/documents/irc/irc_io_api_log.txt?rev=307&view=auto
2161
 *	
2163
 *	
2162
 *	Also referenced in the design of the API was the DOM 3 L&S spec:
2164
 *	Also referenced in the design of the API was the DOM 3 L&S spec:
2163
 *		http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/load-save.html
2165
 *		http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/load-save.html
2164
 ******************************************************************************/
2166
 ******************************************************************************/
2165
 
2167
 
2166
// a map of the available transport options. Transports should add themselves
2168
// a map of the available transport options. Transports should add themselves
2167
// by calling add(name)
2169
// by calling add(name)
2168
dojo.io.transports = [];
2170
dojo.io.transports = [];
2169
dojo.io.hdlrFuncNames = [ "load", "error", "timeout" ]; // we're omitting a progress() event for now
2171
dojo.io.hdlrFuncNames = [ "load", "error", "timeout" ]; // we're omitting a progress() event for now
2170
 
2172
 
2171
dojo.io.Request = function(/*String*/ url, /*String*/ mimetype, /*String*/ transport, /*String or Boolean*/ changeUrl){
2173
dojo.io.Request = function(/*String*/ url, /*String*/ mimetype, /*String*/ transport, /*String or Boolean*/ changeUrl){
2172
// summary:
2174
// summary:
2173
//		Constructs a Request object that is used by dojo.io.bind().
2175
//		Constructs a Request object that is used by dojo.io.bind().
2174
// description:
2176
// description:
2175
//		dojo.io.bind() will create one of these for you if
2177
//		dojo.io.bind() will create one of these for you if
2176
//		you call dojo.io.bind() with an plain object containing the bind parameters.
2178
//		you call dojo.io.bind() with an plain object containing the bind parameters.
2177
//		This method can either take the arguments specified, or an Object containing all of the parameters that you
2179
//		This method can either take the arguments specified, or an Object containing all of the parameters that you
2178
//		want to use to create the dojo.io.Request (similar to how dojo.io.bind() is called.
2180
//		want to use to create the dojo.io.Request (similar to how dojo.io.bind() is called.
2179
//		The named parameters to this constructor represent the minimum set of parameters need
2181
//		The named parameters to this constructor represent the minimum set of parameters need
2180
	if((arguments.length == 1)&&(arguments[0].constructor == Object)){
2182
	if((arguments.length == 1)&&(arguments[0].constructor == Object)){
2181
		this.fromKwArgs(arguments[0]);
2183
		this.fromKwArgs(arguments[0]);
2182
	}else{
2184
	}else{
2183
		this.url = url;
2185
		this.url = url;
2184
		if(mimetype){ this.mimetype = mimetype; }
2186
		if(mimetype){ this.mimetype = mimetype; }
2185
		if(transport){ this.transport = transport; }
2187
		if(transport){ this.transport = transport; }
2186
		if(arguments.length >= 4){ this.changeUrl = changeUrl; }
2188
		if(arguments.length >= 4){ this.changeUrl = changeUrl; }
2187
	}
2189
	}
2188
}
2190
}
2189
 
2191
 
2190
dojo.lang.extend(dojo.io.Request, {
2192
dojo.lang.extend(dojo.io.Request, {
2191
 
2193
 
2192
	/** The URL to hit */
2194
	/** The URL to hit */
2193
	url: "",
2195
	url: "",
2194
	
2196
	
2195
	/** The mime type used to interrpret the response body */
2197
	/** The mime type used to interrpret the response body */
2196
	mimetype: "text/plain",
2198
	mimetype: "text/plain",
2197
	
2199
	
2198
	/** The HTTP method to use */
2200
	/** The HTTP method to use */
2199
	method: "GET",
2201
	method: "GET",
2200
	
2202
	
2201
	/** An Object containing key-value pairs to be included with the request */
2203
	/** An Object containing key-value pairs to be included with the request */
2202
	content: undefined, // Object
2204
	content: undefined, // Object
2203
	
2205
	
2204
	/** The transport medium to use */
2206
	/** The transport medium to use */
2205
	transport: undefined, // String
2207
	transport: undefined, // String
2206
	
2208
	
2207
	/** If defined the URL of the page is physically changed */
2209
	/** If defined the URL of the page is physically changed */
2208
	changeUrl: undefined, // String
2210
	changeUrl: undefined, // String
2209
	
2211
	
2210
	/** A form node to use in the request */
2212
	/** A form node to use in the request */
2211
	formNode: undefined, // HTMLFormElement
2213
	formNode: undefined, // HTMLFormElement
2212
	
2214
	
2213
	/** Whether the request should be made synchronously */
2215
	/** Whether the request should be made synchronously */
2214
	sync: false,
2216
	sync: false,
2215
	
2217
	
2216
	bindSuccess: false,
2218
	bindSuccess: false,
2217
 
2219
 
2218
	/** Cache/look for the request in the cache before attempting to request?
2220
	/** Cache/look for the request in the cache before attempting to request?
2219
	 *  NOTE: this isn't a browser cache, this is internal and would only cache in-page
2221
	 *  NOTE: this isn't a browser cache, this is internal and would only cache in-page
2220
	 */
2222
	 */
2221
	useCache: false,
2223
	useCache: false,
2222
 
2224
 
2223
	/** Prevent the browser from caching this by adding a query string argument to the URL */
2225
	/** Prevent the browser from caching this by adding a query string argument to the URL */
2224
	preventCache: false,
2226
	preventCache: false,
-
 
2227
 
-
 
2228
	jsonFilter: function(value){
-
 
2229
		if(	(this.mimetype == "text/json-comment-filtered")||
-
 
2230
			(this.mimetype == "application/json-comment-filtered")
-
 
2231
		){
-
 
2232
			var cStartIdx = value.indexOf("\/*");
-
 
2233
			var cEndIdx = value.lastIndexOf("*\/");
-
 
2234
			if((cStartIdx == -1)||(cEndIdx == -1)){
-
 
2235
				dojo.debug("your JSON wasn't comment filtered!"); // FIXME: throw exception instead?
-
 
2236
				return "";
-
 
2237
			}
-
 
2238
			return value.substring(cStartIdx+2, cEndIdx);
-
 
2239
		}
-
 
2240
		dojo.debug("please consider using a mimetype of text/json-comment-filtered to avoid potential security issues with JSON endpoints");
-
 
2241
		return value;
-
 
2242
	},
2225
	
2243
	
2226
	// events stuff
2244
	// events stuff
2227
	load: function(/*String*/type, /*Object*/data, /*Object*/transportImplementation, /*Object*/kwArgs){
2245
	load: function(/*String*/type, /*Object*/data, /*Object*/transportImplementation, /*Object*/kwArgs){
2228
		// summary:
2246
		// summary:
2229
		//		Called on successful completion of a bind.
2247
		//		Called on successful completion of a bind.
2230
		//		type: String
2248
		//		type: String
2231
		//				A string with value "load"
2249
		//				A string with value "load"
2232
		//		data: Object
2250
		//		data: Object
2233
		//				The object representing the result of the bind. The actual structure
2251
		//				The object representing the result of the bind. The actual structure
2234
		//				of the data object will depend on the mimetype that was given to bind
2252
		//				of the data object will depend on the mimetype that was given to bind
2235
		//				in the bind arguments.
2253
		//				in the bind arguments.
2236
		//		transportImplementation: Object
2254
		//		transportImplementation: Object
2237
		//				The object that implements a particular transport. Structure is depedent
2255
		//				The object that implements a particular transport. Structure is depedent
2238
		//				on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the
2256
		//				on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the
2239
		//				XMLHttpRequest object from the browser.
2257
		//				XMLHttpRequest object from the browser.
2240
		//		kwArgs: Object
2258
		//		kwArgs: Object
2241
		//				Object that contains the request parameters that were given to the
2259
		//				Object that contains the request parameters that were given to the
2242
		//				bind call. Useful for storing and retrieving state from when bind
2260
		//				bind call. Useful for storing and retrieving state from when bind
2243
		//				was called.
2261
		//				was called.
2244
	},
2262
	},
2245
	error: function(/*String*/type, /*Object*/error, /*Object*/transportImplementation, /*Object*/kwArgs){
2263
	error: function(/*String*/type, /*Object*/error, /*Object*/transportImplementation, /*Object*/kwArgs){
2246
		// summary:
2264
		// summary:
2247
		//		Called when there is an error with a bind.
2265
		//		Called when there is an error with a bind.
2248
		//		type: String
2266
		//		type: String
2249
		//				A string with value "error"
2267
		//				A string with value "error"
2250
		//		error: Object
2268
		//		error: Object
2251
		//				The error object. Should be a dojo.io.Error object, but not guaranteed.
2269
		//				The error object. Should be a dojo.io.Error object, but not guaranteed.
2252
		//		transportImplementation: Object
2270
		//		transportImplementation: Object
2253
		//				The object that implements a particular transport. Structure is depedent
2271
		//				The object that implements a particular transport. Structure is depedent
2254
		//				on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the
2272
		//				on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the
2255
		//				XMLHttpRequest object from the browser.
2273
		//				XMLHttpRequest object from the browser.
2256
		//		kwArgs: Object
2274
		//		kwArgs: Object
2257
		//				Object that contains the request parameters that were given to the
2275
		//				Object that contains the request parameters that were given to the
2258
		//				bind call. Useful for storing and retrieving state from when bind
2276
		//				bind call. Useful for storing and retrieving state from when bind
2259
		//				was called.
2277
		//				was called.
2260
	},
2278
	},
2261
	timeout: function(/*String*/type, /*Object*/empty, /*Object*/transportImplementation, /*Object*/kwArgs){
2279
	timeout: function(/*String*/type, /*Object*/empty, /*Object*/transportImplementation, /*Object*/kwArgs){
2262
		// summary:
2280
		// summary:
2263
		//		Called when there is an error with a bind. Only implemented in certain transports at this time.
2281
		//		Called when there is an error with a bind. Only implemented in certain transports at this time.
2264
		//		type: String
2282
		//		type: String
2265
		//				A string with value "timeout"
2283
		//				A string with value "timeout"
2266
		//		empty: Object
2284
		//		empty: Object
2267
		//				Should be null. Just a spacer argument so that load, error, timeout and handle have the
2285
		//				Should be null. Just a spacer argument so that load, error, timeout and handle have the
2268
		//				same signatures.
2286
		//				same signatures.
2269
		//		transportImplementation: Object
2287
		//		transportImplementation: Object
2270
		//				The object that implements a particular transport. Structure is depedent
2288
		//				The object that implements a particular transport. Structure is depedent
2271
		//				on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the
2289
		//				on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the
2272
		//				XMLHttpRequest object from the browser. May be null for the timeout case for
2290
		//				XMLHttpRequest object from the browser. May be null for the timeout case for
2273
		//				some transports.
2291
		//				some transports.
2274
		//		kwArgs: Object
2292
		//		kwArgs: Object
2275
		//				Object that contains the request parameters that were given to the
2293
		//				Object that contains the request parameters that were given to the
2276
		//				bind call. Useful for storing and retrieving state from when bind
2294
		//				bind call. Useful for storing and retrieving state from when bind
2277
		//				was called.
2295
		//				was called.
2278
	},
2296
	},
2279
	handle: function(/*String*/type, /*Object*/data, /*Object*/transportImplementation, /*Object*/kwArgs){
2297
	handle: function(/*String*/type, /*Object*/data, /*Object*/transportImplementation, /*Object*/kwArgs){
2280
		// summary:
2298
		// summary:
2281
		//		The handle method can be defined instead of defining separate load, error and timeout
2299
		//		The handle method can be defined instead of defining separate load, error and timeout
2282
		//		callbacks.
2300
		//		callbacks.
2283
		//		type: String
2301
		//		type: String
2284
		//				A string with the type of callback: "load", "error", or "timeout".
2302
		//				A string with the type of callback: "load", "error", or "timeout".
2285
		//		data: Object
2303
		//		data: Object
2286
		//				See the above callbacks for what this parameter could be.
2304
		//				See the above callbacks for what this parameter could be.
2287
		//		transportImplementation: Object
2305
		//		transportImplementation: Object
2288
		//				The object that implements a particular transport. Structure is depedent
2306
		//				The object that implements a particular transport. Structure is depedent
2289
		//				on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the
2307
		//				on the transport. For XMLHTTPTransport (dojo.io.BrowserIO), it will be the
2290
		//				XMLHttpRequest object from the browser.
2308
		//				XMLHttpRequest object from the browser.
2291
		//		kwArgs: Object
2309
		//		kwArgs: Object
2292
		//				Object that contains the request parameters that were given to the
2310
		//				Object that contains the request parameters that were given to the
2293
		//				bind call. Useful for storing and retrieving state from when bind
2311
		//				bind call. Useful for storing and retrieving state from when bind
2294
		//				was called.	
2312
		//				was called.	
2295
	},
2313
	},
2296
 
2314
 
2297
	//FIXME: change IframeIO.js to use timeouts?
2315
	//FIXME: change IframeIO.js to use timeouts?
2298
	// The number of seconds to wait until firing a timeout callback.
2316
	// The number of seconds to wait until firing a timeout callback.
2299
	// If it is zero, that means, don't do a timeout check.
2317
	// If it is zero, that means, don't do a timeout check.
2300
	timeoutSeconds: 0,
2318
	timeoutSeconds: 0,
2301
	
2319
	
2302
	// the abort method needs to be filled in by the transport that accepts the
2320
	// the abort method needs to be filled in by the transport that accepts the
2303
	// bind() request
2321
	// bind() request
2304
	abort: function(){ },
2322
	abort: function(){ },
2305
	
2323
	
2306
	// backButton: function(){ },
2324
	// backButton: function(){ },
2307
	// forwardButton: function(){ },
2325
	// forwardButton: function(){ },
2308
 
2326
 
2309
	fromKwArgs: function(/*Object*/ kwArgs){
2327
	fromKwArgs: function(/*Object*/ kwArgs){
2310
		// summary:
2328
		// summary:
2311
		//		Creates a dojo.io.Request from a simple object (kwArgs object).
2329
		//		Creates a dojo.io.Request from a simple object (kwArgs object).
2312
 
2330
 
2313
		// normalize args
2331
		// normalize args
2314
		if(kwArgs["url"]){ kwArgs.url = kwArgs.url.toString(); }
2332
		if(kwArgs["url"]){ kwArgs.url = kwArgs.url.toString(); }
2315
		if(kwArgs["formNode"]) { kwArgs.formNode = dojo.byId(kwArgs.formNode); }
2333
		if(kwArgs["formNode"]) { kwArgs.formNode = dojo.byId(kwArgs.formNode); }
2316
		if(!kwArgs["method"] && kwArgs["formNode"] && kwArgs["formNode"].method) {
2334
		if(!kwArgs["method"] && kwArgs["formNode"] && kwArgs["formNode"].method) {
2317
			kwArgs.method = kwArgs["formNode"].method;
2335
			kwArgs.method = kwArgs["formNode"].method;
2318
		}
2336
		}
2319
		
2337
		
2320
		// backwards compatibility
2338
		// backwards compatibility
2321
		if(!kwArgs["handle"] && kwArgs["handler"]){ kwArgs.handle = kwArgs.handler; }
2339
		if(!kwArgs["handle"] && kwArgs["handler"]){ kwArgs.handle = kwArgs.handler; }
2322
		if(!kwArgs["load"] && kwArgs["loaded"]){ kwArgs.load = kwArgs.loaded; }
2340
		if(!kwArgs["load"] && kwArgs["loaded"]){ kwArgs.load = kwArgs.loaded; }
2323
		if(!kwArgs["changeUrl"] && kwArgs["changeURL"]) { kwArgs.changeUrl = kwArgs.changeURL; }
2341
		if(!kwArgs["changeUrl"] && kwArgs["changeURL"]) { kwArgs.changeUrl = kwArgs.changeURL; }
2324
 
2342
 
2325
		// encoding fun!
2343
		// encoding fun!
2326
		kwArgs.encoding = dojo.lang.firstValued(kwArgs["encoding"], djConfig["bindEncoding"], "");
2344
		kwArgs.encoding = dojo.lang.firstValued(kwArgs["encoding"], djConfig["bindEncoding"], "");
2327
 
2345
 
2328
		kwArgs.sendTransport = dojo.lang.firstValued(kwArgs["sendTransport"], djConfig["ioSendTransport"], false);
2346
		kwArgs.sendTransport = dojo.lang.firstValued(kwArgs["sendTransport"], djConfig["ioSendTransport"], false);
2329
 
2347
 
2330
		var isFunction = dojo.lang.isFunction;
2348
		var isFunction = dojo.lang.isFunction;
2331
		for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){
2349
		for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){
2332
			var fn = dojo.io.hdlrFuncNames[x];
2350
			var fn = dojo.io.hdlrFuncNames[x];
2333
			if(kwArgs[fn] && isFunction(kwArgs[fn])){ continue; }
2351
			if(kwArgs[fn] && isFunction(kwArgs[fn])){ continue; }
2334
			if(kwArgs["handle"] && isFunction(kwArgs["handle"])){
2352
			if(kwArgs["handle"] && isFunction(kwArgs["handle"])){
2335
				kwArgs[fn] = kwArgs.handle;
2353
				kwArgs[fn] = kwArgs.handle;
2336
			}
2354
			}
2337
			// handler is aliased above, shouldn't need this check
2355
			// handler is aliased above, shouldn't need this check
2338
			/* else if(dojo.lang.isObject(kwArgs.handler)){
2356
			/* else if(dojo.lang.isObject(kwArgs.handler)){
2339
				if(isFunction(kwArgs.handler[fn])){
2357
				if(isFunction(kwArgs.handler[fn])){
2340
					kwArgs[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"]||function(){};
2358
					kwArgs[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"]||function(){};
2341
				}
2359
				}
2342
			}*/
2360
			}*/
2343
		}
2361
		}
2344
		dojo.lang.mixin(this, kwArgs);
2362
		dojo.lang.mixin(this, kwArgs);
2345
	}
2363
	}
2346
 
2364
 
2347
});
2365
});
2348
 
2366
 
2349
dojo.io.Error = function(/*String*/ msg, /*String*/ type, /*Number*/num){
2367
dojo.io.Error = function(/*String*/ msg, /*String*/ type, /*Number*/num){
2350
	// summary:
2368
	// summary:
2351
	//		Constructs an object representing a bind error.
2369
	//		Constructs an object representing a bind error.
2352
	this.message = msg;
2370
	this.message = msg;
2353
	this.type =  type || "unknown"; // must be one of "io", "parse", "unknown"
2371
	this.type =  type || "unknown"; // must be one of "io", "parse", "unknown"
2354
	this.number = num || 0; // per-substrate error number, not normalized
2372
	this.number = num || 0; // per-substrate error number, not normalized
2355
}
2373
}
2356
 
2374
 
2357
dojo.io.transports.addTransport = function(/*String*/name){
2375
dojo.io.transports.addTransport = function(/*String*/name){
2358
	// summary:
2376
	// summary:
2359
	//		Used to register transports that can support bind calls.
2377
	//		Used to register transports that can support bind calls.
2360
	this.push(name);
2378
	this.push(name);
2361
	// FIXME: do we need to handle things that aren't direct children of the
2379
	// FIXME: do we need to handle things that aren't direct children of the
2362
	// dojo.io module? (say, dojo.io.foo.fooTransport?)
2380
	// dojo.io module? (say, dojo.io.foo.fooTransport?)
2363
	this[name] = dojo.io[name];
2381
	this[name] = dojo.io[name];
2364
}
2382
}
2365
 
2383
 
2366
// binding interface, the various implementations register their capabilities
2384
// binding interface, the various implementations register their capabilities
2367
// and the bind() method dispatches
2385
// and the bind() method dispatches
2368
dojo.io.bind = function(/*dojo.io.Request or Object*/request){
2386
dojo.io.bind = function(/*dojo.io.Request or Object*/request){
2369
	// summary:
2387
	// summary:
2370
	//		Binding interface for IO. Loading different IO transports, like
2388
	//		Binding interface for IO. Loading different IO transports, like
2371
	//		dojo.io.BrowserIO or dojo.io.IframeIO, will register with bind
2389
	//		dojo.io.BrowserIO or dojo.io.IframeIO, will register with bind
2372
	//		to handle particular types of bind calls.
2390
	//		to handle particular types of bind calls.
2373
	//		request: Object
2391
	//		request: Object
2374
	//				Object containing bind arguments. This object is converted to
2392
	//				Object containing bind arguments. This object is converted to
2375
	//				a dojo.io.Request object, and that request object is the return
2393
	//				a dojo.io.Request object, and that request object is the return
2376
	//				value for this method.
2394
	//				value for this method.
2377
	if(!(request instanceof dojo.io.Request)){
2395
	if(!(request instanceof dojo.io.Request)){
2378
		try{
2396
		try{
2379
			request = new dojo.io.Request(request);
2397
			request = new dojo.io.Request(request);
2380
		}catch(e){ dojo.debug(e); }
2398
		}catch(e){ dojo.debug(e); }
2381
	}
2399
	}
2382
 
2400
 
2383
	// if the request asks for a particular implementation, use it
2401
	// if the request asks for a particular implementation, use it
2384
	var tsName = "";
2402
	var tsName = "";
2385
	if(request["transport"]){
2403
	if(request["transport"]){
2386
		tsName = request["transport"];
2404
		tsName = request["transport"];
2387
		if(!this[tsName]){
2405
		if(!this[tsName]){
2388
			dojo.io.sendBindError(request, "No dojo.io.bind() transport with name '"
2406
			dojo.io.sendBindError(request, "No dojo.io.bind() transport with name '"
2389
				+ request["transport"] + "'.");
2407
				+ request["transport"] + "'.");
2390
			return request; //dojo.io.Request
2408
			return request; //dojo.io.Request
2391
		}
2409
		}
2392
		if(!this[tsName].canHandle(request)){
2410
		if(!this[tsName].canHandle(request)){
2393
			dojo.io.sendBindError(request, "dojo.io.bind() transport with name '"
2411
			dojo.io.sendBindError(request, "dojo.io.bind() transport with name '"
2394
				+ request["transport"] + "' cannot handle this type of request.");
2412
				+ request["transport"] + "' cannot handle this type of request.");
2395
			return request;	//dojo.io.Request
2413
			return request;	//dojo.io.Request
2396
		}
2414
		}
2397
	}else{
2415
	}else{
2398
		// otherwise we do our best to auto-detect what available transports
2416
		// otherwise we do our best to auto-detect what available transports
2399
		// will handle 
2417
		// will handle 
2400
		for(var x=0; x<dojo.io.transports.length; x++){
2418
		for(var x=0; x<dojo.io.transports.length; x++){
2401
			var tmp = dojo.io.transports[x];
2419
			var tmp = dojo.io.transports[x];
2402
			if((this[tmp])&&(this[tmp].canHandle(request))){
2420
			if((this[tmp])&&(this[tmp].canHandle(request))){
2403
				tsName = tmp;
2421
				tsName = tmp;
2404
				break;
2422
				break;
2405
			}
2423
			}
2406
		}
2424
		}
2407
		if(tsName == ""){
2425
		if(tsName == ""){
2408
			dojo.io.sendBindError(request, "None of the loaded transports for dojo.io.bind()"
2426
			dojo.io.sendBindError(request, "None of the loaded transports for dojo.io.bind()"
2409
				+ " can handle the request.");
2427
				+ " can handle the request.");
2410
			return request; //dojo.io.Request
2428
			return request; //dojo.io.Request
2411
		}
2429
		}
2412
	}
2430
	}
2413
	this[tsName].bind(request);
2431
	this[tsName].bind(request);
2414
	request.bindSuccess = true;
2432
	request.bindSuccess = true;
2415
	return request; //dojo.io.Request
2433
	return request; //dojo.io.Request
2416
}
2434
}
2417
 
2435
 
2418
dojo.io.sendBindError = function(/* Object */request, /* String */message){
2436
dojo.io.sendBindError = function(/* Object */request, /* String */message){
2419
	// summary:
2437
	// summary:
2420
	//		Used internally by dojo.io.bind() to return/raise a bind error.
2438
	//		Used internally by dojo.io.bind() to return/raise a bind error.
2421
 
2439
 
2422
	//Need to be careful since not all hostenvs support setTimeout.
2440
	//Need to be careful since not all hostenvs support setTimeout.
2423
	if((typeof request.error == "function" || typeof request.handle == "function")
2441
	if((typeof request.error == "function" || typeof request.handle == "function")
2424
		&& (typeof setTimeout == "function" || typeof setTimeout == "object")){
2442
		&& (typeof setTimeout == "function" || typeof setTimeout == "object")){
2425
		var errorObject = new dojo.io.Error(message);
2443
		var errorObject = new dojo.io.Error(message);
2426
		setTimeout(function(){
2444
		setTimeout(function(){
2427
			request[(typeof request.error == "function") ? "error" : "handle"]("error", errorObject, null, request);
2445
			request[(typeof request.error == "function") ? "error" : "handle"]("error", errorObject, null, request);
2428
		}, 50);
2446
		}, 50);
2429
	}else{
2447
	}else{
2430
		dojo.raise(message);
2448
		dojo.raise(message);
2431
	}
2449
	}
2432
}
2450
}
2433
 
2451
 
2434
dojo.io.queueBind = function(/*dojo.io.Request or Object*/request){
2452
dojo.io.queueBind = function(/*dojo.io.Request or Object*/request){
2435
	// summary:
2453
	// summary:
2436
	//		queueBind will use dojo.io.bind() but guarantee that only one bind
2454
	//		queueBind will use dojo.io.bind() but guarantee that only one bind
2437
	//		call is handled at a time.
2455
	//		call is handled at a time.
2438
	// description:
2456
	// description:
2439
	//		If queueBind is called while a bind call
2457
	//		If queueBind is called while a bind call
2440
	//		is in process, it will queue up the other calls to bind and call them
2458
	//		is in process, it will queue up the other calls to bind and call them
2441
	//		in order as bind calls complete.
2459
	//		in order as bind calls complete.
2442
	//		request: Object
2460
	//		request: Object
2443
	//			Same sort of request object as used for dojo.io.bind().
2461
	//			Same sort of request object as used for dojo.io.bind().
2444
	if(!(request instanceof dojo.io.Request)){
2462
	if(!(request instanceof dojo.io.Request)){
2445
		try{
2463
		try{
2446
			request = new dojo.io.Request(request);
2464
			request = new dojo.io.Request(request);
2447
		}catch(e){ dojo.debug(e); }
2465
		}catch(e){ dojo.debug(e); }
2448
	}
2466
	}
2449
 
2467
 
2450
	// make sure we get called if/when we get a response
2468
	// make sure we get called if/when we get a response
2451
	var oldLoad = request.load;
2469
	var oldLoad = request.load;
2452
	request.load = function(){
2470
	request.load = function(){
2453
		dojo.io._queueBindInFlight = false;
2471
		dojo.io._queueBindInFlight = false;
2454
		var ret = oldLoad.apply(this, arguments);
2472
		var ret = oldLoad.apply(this, arguments);
2455
		dojo.io._dispatchNextQueueBind();
2473
		dojo.io._dispatchNextQueueBind();
2456
		return ret;
2474
		return ret;
2457
	}
2475
	}
2458
 
2476
 
2459
	var oldErr = request.error;
2477
	var oldErr = request.error;
2460
	request.error = function(){
2478
	request.error = function(){
2461
		dojo.io._queueBindInFlight = false;
2479
		dojo.io._queueBindInFlight = false;
2462
		var ret = oldErr.apply(this, arguments);
2480
		var ret = oldErr.apply(this, arguments);
2463
		dojo.io._dispatchNextQueueBind();
2481
		dojo.io._dispatchNextQueueBind();
2464
		return ret;
2482
		return ret;
2465
	}
2483
	}
2466
 
2484
 
2467
	dojo.io._bindQueue.push(request);
2485
	dojo.io._bindQueue.push(request);
2468
	dojo.io._dispatchNextQueueBind();
2486
	dojo.io._dispatchNextQueueBind();
2469
	return request; //dojo.io.Request
2487
	return request; //dojo.io.Request
2470
}
2488
}
2471
 
2489
 
2472
dojo.io._dispatchNextQueueBind = function(){
2490
dojo.io._dispatchNextQueueBind = function(){
2473
	// summary:
2491
	// summary:
2474
	//	Private method used by dojo.io.queueBind().
2492
	//	Private method used by dojo.io.queueBind().
2475
	if(!dojo.io._queueBindInFlight){
2493
	if(!dojo.io._queueBindInFlight){
2476
		dojo.io._queueBindInFlight = true;
2494
		dojo.io._queueBindInFlight = true;
2477
		if(dojo.io._bindQueue.length > 0){
2495
		if(dojo.io._bindQueue.length > 0){
2478
			dojo.io.bind(dojo.io._bindQueue.shift());
2496
			dojo.io.bind(dojo.io._bindQueue.shift());
2479
		}else{
2497
		}else{
2480
			dojo.io._queueBindInFlight = false;
2498
			dojo.io._queueBindInFlight = false;
2481
		}
2499
		}
2482
	}
2500
	}
2483
}
2501
}
2484
dojo.io._bindQueue = [];
2502
dojo.io._bindQueue = [];
2485
dojo.io._queueBindInFlight = false;
2503
dojo.io._queueBindInFlight = false;
2486
 
2504
 
2487
dojo.io.argsFromMap = function(/*Object*/map, /*String?*/encoding, /*String?*/last){
2505
dojo.io.argsFromMap = function(/*Object*/map, /*String?*/encoding, /*String?*/last){
2488
	// summary:
2506
	// summary:
2489
	//		Converts name/values pairs in the map object to an URL-encoded string
2507
	//		Converts name/values pairs in the map object to an URL-encoded string
2490
	//		with format of name1=value1&name2=value2...
2508
	//		with format of name1=value1&name2=value2...
2491
	//		map: Object
2509
	//		map: Object
2492
	//			Object that has the contains the names and values.
2510
	//			Object that has the contains the names and values.
2493
	//		encoding: String?
2511
	//		encoding: String?
2494
	//			String to specify how to encode the name and value. If the encoding string
2512
	//			String to specify how to encode the name and value. If the encoding string
2495
	//			contains "utf" (case-insensitive), then encodeURIComponent is used. Otherwise
2513
	//			contains "utf" (case-insensitive), then encodeURIComponent is used. Otherwise
2496
	//			dojo.string.encodeAscii is used.
2514
	//			dojo.string.encodeAscii is used.
2497
	//		last: String?
2515
	//		last: String?
2498
	//			The last parameter in the list. Helps with final string formatting?
2516
	//			The last parameter in the list. Helps with final string formatting?
2499
	var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
2517
	var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
2500
	var mapped = [];
2518
	var mapped = [];
2501
	var control = new Object();
2519
	var control = new Object();
2502
	for(var name in map){
2520
	for(var name in map){
2503
		var domap = function(elt){
2521
		var domap = function(elt){
2504
			var val = enc(name)+"="+enc(elt);
2522
			var val = enc(name)+"="+enc(elt);
2505
			mapped[(last == name) ? "push" : "unshift"](val);
2523
			mapped[(last == name) ? "push" : "unshift"](val);
2506
		}
2524
		}
2507
		if(!control[name]){
2525
		if(!control[name]){
2508
			var value = map[name];
2526
			var value = map[name];
2509
			// FIXME: should be isArrayLike?
2527
			// FIXME: should be isArrayLike?
2510
			if (dojo.lang.isArray(value)){
2528
			if (dojo.lang.isArray(value)){
2511
				dojo.lang.forEach(value, domap);
2529
				dojo.lang.forEach(value, domap);
2512
			}else{
2530
			}else{
2513
				domap(value);
2531
				domap(value);
2514
			}
2532
			}
2515
		}
2533
		}
2516
	}
2534
	}
2517
	return mapped.join("&"); //String
2535
	return mapped.join("&"); //String
2518
}
2536
}
2519
 
2537
 
2520
dojo.io.setIFrameSrc = function(/*DOMNode*/ iframe, /*String*/ src, /*Boolean*/ replace){
2538
dojo.io.setIFrameSrc = function(/*DOMNode*/ iframe, /*String*/ src, /*Boolean*/ replace){
2521
	//summary:
2539
	//summary:
2522
	//		Sets the URL that is loaded in an IFrame. The replace parameter indicates whether
2540
	//		Sets the URL that is loaded in an IFrame. The replace parameter indicates whether
2523
	//		location.replace() should be used when changing the location of the iframe.
2541
	//		location.replace() should be used when changing the location of the iframe.
2524
	try{
2542
	try{
2525
		var r = dojo.render.html;
2543
		var r = dojo.render.html;
2526
		// dojo.debug(iframe);
2544
		// dojo.debug(iframe);
2527
		if(!replace){
2545
		if(!replace){
2528
			if(r.safari){
2546
			if(r.safari){
2529
				iframe.location = src;
2547
				iframe.location = src;
2530
			}else{
2548
			}else{
2531
				frames[iframe.name].location = src;
2549
				frames[iframe.name].location = src;
2532
			}
2550
			}
2533
		}else{
2551
		}else{
2534
			// Fun with DOM 0 incompatibilities!
2552
			// Fun with DOM 0 incompatibilities!
2535
			var idoc;
2553
			var idoc;
2536
			if(r.ie){
2554
			if(r.ie){
2537
				idoc = iframe.contentWindow.document;
2555
				idoc = iframe.contentWindow.document;
2538
			}else if(r.safari){
2556
			}else if(r.safari){
2539
				idoc = iframe.document;
2557
				idoc = iframe.document;
2540
			}else{ //  if(r.moz){
2558
			}else{ //  if(r.moz){
2541
				idoc = iframe.contentWindow;
2559
				idoc = iframe.contentWindow;
2542
			}
2560
			}
2543
 
2561
 
2544
			//For Safari (at least 2.0.3) and Opera, if the iframe
2562
			//For Safari (at least 2.0.3) and Opera, if the iframe
2545
			//has just been created but it doesn't have content
2563
			//has just been created but it doesn't have content
2546
			//yet, then iframe.document may be null. In that case,
2564
			//yet, then iframe.document may be null. In that case,
2547
			//use iframe.location and return.
2565
			//use iframe.location and return.
2548
			if(!idoc){
2566
			if(!idoc){
2549
				iframe.location = src;
2567
				iframe.location = src;
2550
				return;
2568
				return;
2551
			}else{
2569
			}else{
2552
				idoc.location.replace(src);
2570
				idoc.location.replace(src);
2553
			}
2571
			}
2554
		}
2572
		}
2555
	}catch(e){ 
2573
	}catch(e){ 
2556
		dojo.debug(e); 
2574
		dojo.debug(e); 
2557
		dojo.debug("setIFrameSrc: "+e); 
2575
		dojo.debug("setIFrameSrc: "+e); 
2558
	}
2576
	}
2559
}
2577
}
2560
 
2578
 
2561
/*
2579
/*
2562
dojo.io.sampleTranport = new function(){
2580
dojo.io.sampleTranport = new function(){
2563
	this.canHandle = function(kwArgs){
2581
	this.canHandle = function(kwArgs){
2564
		// canHandle just tells dojo.io.bind() if this is a good transport to
2582
		// canHandle just tells dojo.io.bind() if this is a good transport to
2565
		// use for the particular type of request.
2583
		// use for the particular type of request.
2566
		if(	
2584
		if(	
2567
			(
2585
			(
2568
				(kwArgs["mimetype"] == "text/plain") ||
2586
				(kwArgs["mimetype"] == "text/plain") ||
2569
				(kwArgs["mimetype"] == "text/html") ||
2587
				(kwArgs["mimetype"] == "text/html") ||
2570
				(kwArgs["mimetype"] == "text/javascript")
2588
				(kwArgs["mimetype"] == "text/javascript")
2571
			)&&(
2589
			)&&(
2572
				(kwArgs["method"] == "get") ||
2590
				(kwArgs["method"] == "get") ||
2573
				( (kwArgs["method"] == "post") && (!kwArgs["formNode"]) )
2591
				( (kwArgs["method"] == "post") && (!kwArgs["formNode"]) )
2574
			)
2592
			)
2575
		){
2593
		){
2576
			return true;
2594
			return true;
2577
		}
2595
		}
2578
 
2596
 
2579
		return false;
2597
		return false;
2580
	}
2598
	}
2581
 
2599
 
2582
	this.bind = function(kwArgs){
2600
	this.bind = function(kwArgs){
2583
		var hdlrObj = {};
2601
		var hdlrObj = {};
2584
 
2602
 
2585
		// set up a handler object
2603
		// set up a handler object
2586
		for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){
2604
		for(var x=0; x<dojo.io.hdlrFuncNames.length; x++){
2587
			var fn = dojo.io.hdlrFuncNames[x];
2605
			var fn = dojo.io.hdlrFuncNames[x];
2588
			if(typeof kwArgs.handler == "object"){
2606
			if(typeof kwArgs.handler == "object"){
2589
				if(typeof kwArgs.handler[fn] == "function"){
2607
				if(typeof kwArgs.handler[fn] == "function"){
2590
					hdlrObj[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"];
2608
					hdlrObj[fn] = kwArgs.handler[fn]||kwArgs.handler["handle"];
2591
				}
2609
				}
2592
			}else if(typeof kwArgs[fn] == "function"){
2610
			}else if(typeof kwArgs[fn] == "function"){
2593
				hdlrObj[fn] = kwArgs[fn];
2611
				hdlrObj[fn] = kwArgs[fn];
2594
			}else{
2612
			}else{
2595
				hdlrObj[fn] = kwArgs["handle"]||function(){};
2613
				hdlrObj[fn] = kwArgs["handle"]||function(){};
2596
			}
2614
			}
2597
		}
2615
		}
2598
 
2616
 
2599
		// build a handler function that calls back to the handler obj
2617
		// build a handler function that calls back to the handler obj
2600
		var hdlrFunc = function(evt){
2618
		var hdlrFunc = function(evt){
2601
			if(evt.type == "onload"){
2619
			if(evt.type == "onload"){
2602
				hdlrObj.load("load", evt.data, evt);
2620
				hdlrObj.load("load", evt.data, evt);
2603
			}else if(evt.type == "onerr"){
2621
			}else if(evt.type == "onerr"){
2604
				var errObj = new dojo.io.Error("sampleTransport Error: "+evt.msg);
2622
				var errObj = new dojo.io.Error("sampleTransport Error: "+evt.msg);
2605
				hdlrObj.error("error", errObj);
2623
				hdlrObj.error("error", errObj);
2606
			}
2624
			}
2607
		}
2625
		}
2608
 
2626
 
2609
		// the sample transport would attach the hdlrFunc() when sending the
2627
		// the sample transport would attach the hdlrFunc() when sending the
2610
		// request down the pipe at this point
2628
		// request down the pipe at this point
2611
		var tgtURL = kwArgs.url+"?"+dojo.io.argsFromMap(kwArgs.content);
2629
		var tgtURL = kwArgs.url+"?"+dojo.io.argsFromMap(kwArgs.content);
2612
		// sampleTransport.sendRequest(tgtURL, hdlrFunc);
2630
		// sampleTransport.sendRequest(tgtURL, hdlrFunc);
2613
	}
2631
	}
2614
 
2632
 
2615
	dojo.io.transports.addTransport("sampleTranport");
2633
	dojo.io.transports.addTransport("sampleTranport");
2616
}
2634
}
2617
*/
2635
*/
2618
 
2636
 
2619
dojo.provide("dojo.lang.array");
2637
dojo.provide("dojo.lang.array");
2620
 
2638
 
2621
 
2639
 
2622
 
2640
 
2623
// FIXME: Is this worthless since you can do: if(name in obj)
2641
// FIXME: Is this worthless since you can do: if(name in obj)
2624
// is this the right place for this?
2642
// is this the right place for this?
2625
 
2643
 
2626
dojo.lang.mixin(dojo.lang, {
2644
dojo.lang.mixin(dojo.lang, {
2627
	has: function(/*Object*/obj, /*String*/name){
2645
	has: function(/*Object*/obj, /*String*/name){
2628
		// summary: is there a property with the passed name in obj?
2646
		// summary: is there a property with the passed name in obj?
2629
		try{
2647
		try{
2630
			return typeof obj[name] != "undefined"; // Boolean
2648
			return typeof obj[name] != "undefined"; // Boolean
2631
		}catch(e){ return false; } // Boolean
2649
		}catch(e){ return false; } // Boolean
2632
	},
2650
	},
2633
 
2651
 
2634
	isEmpty: function(/*Object*/obj){
2652
	isEmpty: function(/*Object*/obj){
2635
		// summary:
2653
		// summary:
2636
		//		can be used to determine if the passed object is "empty". In
2654
		//		can be used to determine if the passed object is "empty". In
2637
		//		the case of array-like objects, the length, property is
2655
		//		the case of array-like objects, the length, property is
2638
		//		examined, but for other types of objects iteration is used to
2656
		//		examined, but for other types of objects iteration is used to
2639
		//		examine the iterable "surface area" to determine if any
2657
		//		examine the iterable "surface area" to determine if any
2640
		//		non-prototypal properties have been assigned. This iteration is
2658
		//		non-prototypal properties have been assigned. This iteration is
2641
		//		prototype-extension safe.
2659
		//		prototype-extension safe.
2642
		if(dojo.lang.isObject(obj)){
2660
		if(dojo.lang.isObject(obj)){
2643
			var tmp = {};
2661
			var tmp = {};
2644
			var count = 0;
2662
			var count = 0;
2645
			for(var x in obj){
2663
			for(var x in obj){
2646
				if(obj[x] && (!tmp[x])){
2664
				if(obj[x] && (!tmp[x])){
2647
					count++;
2665
					count++;
2648
					break;
2666
					break;
2649
				} 
2667
				} 
2650
			}
2668
			}
2651
			return count == 0; // boolean
2669
			return count == 0; // boolean
2652
		}else if(dojo.lang.isArrayLike(obj) || dojo.lang.isString(obj)){
2670
		}else if(dojo.lang.isArrayLike(obj) || dojo.lang.isString(obj)){
2653
			return obj.length == 0; // boolean
2671
			return obj.length == 0; // boolean
2654
		}
2672
		}
2655
	},
2673
	},
2656
 
2674
 
2657
	map: function(/*Array*/arr, /*Object|Function*/obj, /*Function?*/unary_func){
2675
	map: function(/*Array*/arr, /*Object|Function*/obj, /*Function?*/unary_func){
2658
		// summary:
2676
		// summary:
2659
		//		returns a new array constituded from the return values of
2677
		//		returns a new array constituded from the return values of
2660
		//		passing each element of arr into unary_func. The obj parameter
2678
		//		passing each element of arr into unary_func. The obj parameter
2661
		//		may be passed to enable the passed function to be called in
2679
		//		may be passed to enable the passed function to be called in
2662
		//		that scope. In environments that support JavaScript 1.6, this
2680
		//		that scope. In environments that support JavaScript 1.6, this
2663
		//		function is a passthrough to the built-in map() function
2681
		//		function is a passthrough to the built-in map() function
2664
		//		provided by Array instances. For details on this, see:
2682
		//		provided by Array instances. For details on this, see:
2665
		// 			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map
2683
		// 			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map
2666
		// examples:
2684
		// examples:
2667
		//		dojo.lang.map([1, 2, 3, 4], function(item){ return item+1 });
2685
		//		dojo.lang.map([1, 2, 3, 4], function(item){ return item+1 });
2668
		//		// returns [2, 3, 4, 5]
2686
		//		// returns [2, 3, 4, 5]
2669
		var isString = dojo.lang.isString(arr);
2687
		var isString = dojo.lang.isString(arr);
2670
		if(isString){
2688
		if(isString){
2671
			// arr: String
2689
			// arr: String
2672
			arr = arr.split("");
2690
			arr = arr.split("");
2673
		}
2691
		}
2674
		if(dojo.lang.isFunction(obj)&&(!unary_func)){
2692
		if(dojo.lang.isFunction(obj)&&(!unary_func)){
2675
			unary_func = obj;
2693
			unary_func = obj;
2676
			obj = dj_global;
2694
			obj = dj_global;
2677
		}else if(dojo.lang.isFunction(obj) && unary_func){
2695
		}else if(dojo.lang.isFunction(obj) && unary_func){
2678
			// ff 1.5 compat
2696
			// ff 1.5 compat
2679
			var tmpObj = obj;
2697
			var tmpObj = obj;
2680
			obj = unary_func;
2698
			obj = unary_func;
2681
			unary_func = tmpObj;
2699
			unary_func = tmpObj;
2682
		}
2700
		}
2683
		if(Array.map){
2701
		if(Array.map){
2684
			var outArr = Array.map(arr, unary_func, obj);
2702
			var outArr = Array.map(arr, unary_func, obj);
2685
		}else{
2703
		}else{
2686
			var outArr = [];
2704
			var outArr = [];
2687
			for(var i=0;i<arr.length;++i){
2705
			for(var i=0;i<arr.length;++i){
2688
				outArr.push(unary_func.call(obj, arr[i]));
2706
				outArr.push(unary_func.call(obj, arr[i]));
2689
			}
2707
			}
2690
		}
2708
		}
2691
		if(isString) {
2709
		if(isString) {
2692
			return outArr.join(""); // String
2710
			return outArr.join(""); // String
2693
		} else {
2711
		} else {
2694
			return outArr; // Array
2712
			return outArr; // Array
2695
		}
2713
		}
2696
	},
2714
	},
2697
 
2715
 
2698
	reduce: function(/*Array*/arr, initialValue, /*Object|Function*/obj, /*Function*/binary_func){
2716
	reduce: function(/*Array*/arr, initialValue, /*Object|Function*/obj, /*Function*/binary_func){
2699
		// summary:
2717
		// summary:
2700
		// 		similar to Python's builtin reduce() function. The result of
2718
		// 		similar to Python's builtin reduce() function. The result of
2701
		// 		the previous computation is passed as the first argument to
2719
		// 		the previous computation is passed as the first argument to
2702
		// 		binary_func along with the next value from arr. The result of
2720
		// 		binary_func along with the next value from arr. The result of
2703
		// 		this call is used along with the subsequent value from arr, and
2721
		// 		this call is used along with the subsequent value from arr, and
2704
		// 		this continues until arr is exhausted. The return value is the
2722
		// 		this continues until arr is exhausted. The return value is the
2705
		// 		last result. The "obj" and "initialValue" parameters may be
2723
		// 		last result. The "obj" and "initialValue" parameters may be
2706
		// 		safely omitted and the order of obj and binary_func may be
2724
		// 		safely omitted and the order of obj and binary_func may be
2707
		// 		reversed. The default order of the obj and binary_func argument
2725
		// 		reversed. The default order of the obj and binary_func argument
2708
		// 		will probably be reversed in a future release, and this call
2726
		// 		will probably be reversed in a future release, and this call
2709
		// 		order is supported today.
2727
		// 		order is supported today.
2710
		// examples:
2728
		// examples:
2711
		//		dojo.lang.reduce([1, 2, 3, 4], function(last, next){ return last+next});
2729
		//		dojo.lang.reduce([1, 2, 3, 4], function(last, next){ return last+next});
2712
		//		returns 10
2730
		//		returns 10
2713
		var reducedValue = initialValue;
2731
		var reducedValue = initialValue;
2714
		if(arguments.length == 2){
2732
		if(arguments.length == 2){
2715
			binary_func = initialValue;
2733
			binary_func = initialValue;
2716
			reducedValue = arr[0];
2734
			reducedValue = arr[0];
2717
			arr = arr.slice(1);
2735
			arr = arr.slice(1);
2718
		}else if(arguments.length == 3){
2736
		}else if(arguments.length == 3){
2719
			if(dojo.lang.isFunction(obj)){
2737
			if(dojo.lang.isFunction(obj)){
2720
				binary_func = obj;
2738
				binary_func = obj;
2721
				obj = null;
2739
				obj = null;
2722
			}
2740
			}
2723
		}else{
2741
		}else{
2724
			// un-fsck the default order
2742
			// un-fsck the default order
2725
			// FIXME:
2743
			// FIXME:
2726
			//		could be wrong for some strange function object cases. Not
2744
			//		could be wrong for some strange function object cases. Not
2727
			//		sure how to test for them.
2745
			//		sure how to test for them.
2728
			if(dojo.lang.isFunction(obj)){
2746
			if(dojo.lang.isFunction(obj)){
2729
				var tmp = binary_func;
2747
				var tmp = binary_func;
2730
				binary_func = obj;
2748
				binary_func = obj;
2731
				obj = tmp;
2749
				obj = tmp;
2732
			}
2750
			}
2733
		}
2751
		}
2734
 
2752
 
2735
		var ob = obj || dj_global;
2753
		var ob = obj || dj_global;
2736
		dojo.lang.map(arr, 
2754
		dojo.lang.map(arr, 
2737
			function(val){
2755
			function(val){
2738
				reducedValue = binary_func.call(ob, reducedValue, val);
2756
				reducedValue = binary_func.call(ob, reducedValue, val);
2739
			}
2757
			}
2740
		);
2758
		);
2741
		return reducedValue;
2759
		return reducedValue;
2742
	},
2760
	},
2743
 
2761
 
2744
	forEach: function(/*Array*/anArray, /*Function*/callback, /*Object?*/thisObject){
2762
	forEach: function(/*Array*/anArray, /*Function*/callback, /*Object?*/thisObject){
2745
		// summary:
2763
		// summary:
2746
		//		for every item in anArray, call callback with that item as its
2764
		//		for every item in anArray, call callback with that item as its
2747
		//		only parameter. Return values are ignored. This funciton
2765
		//		only parameter. Return values are ignored. This funciton
2748
		//		corresponds (and wraps) the JavaScript 1.6 forEach method. For
2766
		//		corresponds (and wraps) the JavaScript 1.6 forEach method. For
2749
		//		more details, see:
2767
		//		more details, see:
2750
		//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach
2768
		//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach
2751
		if(dojo.lang.isString(anArray)){
2769
		if(dojo.lang.isString(anArray)){
2752
			// anArray: String
2770
			// anArray: String
2753
			anArray = anArray.split(""); 
2771
			anArray = anArray.split(""); 
2754
		}
2772
		}
2755
		if(Array.forEach){
2773
		if(Array.forEach){
2756
			Array.forEach(anArray, callback, thisObject);
2774
			Array.forEach(anArray, callback, thisObject);
2757
		}else{
2775
		}else{
2758
			// FIXME: there are several ways of handilng thisObject. Is dj_global always the default context?
2776
			// FIXME: there are several ways of handilng thisObject. Is dj_global always the default context?
2759
			if(!thisObject){
2777
			if(!thisObject){
2760
				thisObject=dj_global;
2778
				thisObject=dj_global;
2761
			}
2779
			}
2762
			for(var i=0,l=anArray.length; i<l; i++){ 
2780
			for(var i=0,l=anArray.length; i<l; i++){ 
2763
				callback.call(thisObject, anArray[i], i, anArray);
2781
				callback.call(thisObject, anArray[i], i, anArray);
2764
			}
2782
			}
2765
		}
2783
		}
2766
	},
2784
	},
2767
 
2785
 
2768
	_everyOrSome: function(/*Boolean*/every, /*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2786
	_everyOrSome: function(/*Boolean*/every, /*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2769
		if(dojo.lang.isString(arr)){ 
2787
		if(dojo.lang.isString(arr)){ 
2770
			//arr: String
2788
			//arr: String
2771
			arr = arr.split(""); 
2789
			arr = arr.split(""); 
2772
		}
2790
		}
2773
		if(Array.every){
2791
		if(Array.every){
2774
			return Array[ every ? "every" : "some" ](arr, callback, thisObject);
2792
			return Array[ every ? "every" : "some" ](arr, callback, thisObject);
2775
		}else{
2793
		}else{
2776
			if(!thisObject){
2794
			if(!thisObject){
2777
				thisObject = dj_global;
2795
				thisObject = dj_global;
2778
			}
2796
			}
2779
			for(var i=0,l=arr.length; i<l; i++){
2797
			for(var i=0,l=arr.length; i<l; i++){
2780
				var result = callback.call(thisObject, arr[i], i, arr);
2798
				var result = callback.call(thisObject, arr[i], i, arr);
2781
				if(every && !result){
2799
				if(every && !result){
2782
					return false; // Boolean
2800
					return false; // Boolean
2783
				}else if((!every)&&(result)){
2801
				}else if((!every)&&(result)){
2784
					return true; // Boolean
2802
					return true; // Boolean
2785
				}
2803
				}
2786
			}
2804
			}
2787
			return Boolean(every); // Boolean
2805
			return Boolean(every); // Boolean
2788
		}
2806
		}
2789
	},
2807
	},
2790
 
2808
 
2791
	every: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2809
	every: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2792
		// summary:
2810
		// summary:
2793
		//		determines whether or not every item in the array satisfies the
2811
		//		determines whether or not every item in the array satisfies the
2794
		//		condition implemented by callback. thisObject may be used to
2812
		//		condition implemented by callback. thisObject may be used to
2795
		//		scope the call to callback. The function signature is derived
2813
		//		scope the call to callback. The function signature is derived
2796
		//		from the JavaScript 1.6 Array.every() function. More
2814
		//		from the JavaScript 1.6 Array.every() function. More
2797
		//		information on this can be found here:
2815
		//		information on this can be found here:
2798
		//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every
2816
		//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every
2799
		// examples:
2817
		// examples:
2800
		//		dojo.lang.every([1, 2, 3, 4], function(item){ return item>1; });
2818
		//		dojo.lang.every([1, 2, 3, 4], function(item){ return item>1; });
2801
		//		// returns false
2819
		//		// returns false
2802
		//		dojo.lang.every([1, 2, 3, 4], function(item){ return item>0; });
2820
		//		dojo.lang.every([1, 2, 3, 4], function(item){ return item>0; });
2803
		//		// returns true 
2821
		//		// returns true 
2804
		return this._everyOrSome(true, arr, callback, thisObject); // Boolean
2822
		return this._everyOrSome(true, arr, callback, thisObject); // Boolean
2805
	},
2823
	},
2806
 
2824
 
2807
	some: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2825
	some: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2808
		// summary:
2826
		// summary:
2809
		//		determines whether or not any item in the array satisfies the
2827
		//		determines whether or not any item in the array satisfies the
2810
		//		condition implemented by callback. thisObject may be used to
2828
		//		condition implemented by callback. thisObject may be used to
2811
		//		scope the call to callback. The function signature is derived
2829
		//		scope the call to callback. The function signature is derived
2812
		//		from the JavaScript 1.6 Array.some() function. More
2830
		//		from the JavaScript 1.6 Array.some() function. More
2813
		//		information on this can be found here:
2831
		//		information on this can be found here:
2814
		//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some
2832
		//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some
2815
		// examples:
2833
		// examples:
2816
		//		dojo.lang.some([1, 2, 3, 4], function(item){ return item>1; });
2834
		//		dojo.lang.some([1, 2, 3, 4], function(item){ return item>1; });
2817
		//		// returns true
2835
		//		// returns true
2818
		//		dojo.lang.some([1, 2, 3, 4], function(item){ return item<1; });
2836
		//		dojo.lang.some([1, 2, 3, 4], function(item){ return item<1; });
2819
		//		// returns false
2837
		//		// returns false
2820
		return this._everyOrSome(false, arr, callback, thisObject); // Boolean
2838
		return this._everyOrSome(false, arr, callback, thisObject); // Boolean
2821
	},
2839
	},
2822
 
2840
 
2823
	filter: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2841
	filter: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2824
		// summary:
2842
		// summary:
2825
		//		returns a new Array with those items from arr that match the
2843
		//		returns a new Array with those items from arr that match the
2826
		//		condition implemented by callback.thisObject may be used to
2844
		//		condition implemented by callback.thisObject may be used to
2827
		//		scope the call to callback. The function signature is derived
2845
		//		scope the call to callback. The function signature is derived
2828
		//		from the JavaScript 1.6 Array.filter() function, although
2846
		//		from the JavaScript 1.6 Array.filter() function, although
2829
		//		special accomidation is made in our implementation for strings.
2847
		//		special accomidation is made in our implementation for strings.
2830
		//		More information on the JS 1.6 API can be found here:
2848
		//		More information on the JS 1.6 API can be found here:
2831
		//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter
2849
		//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter
2832
		// examples:
2850
		// examples:
2833
		//		dojo.lang.some([1, 2, 3, 4], function(item){ return item>1; });
2851
		//		dojo.lang.some([1, 2, 3, 4], function(item){ return item>1; });
2834
		//		// returns [2, 3, 4]
2852
		//		// returns [2, 3, 4]
2835
		var isString = dojo.lang.isString(arr);
2853
		var isString = dojo.lang.isString(arr);
2836
		if(isString){ /*arr: String*/arr = arr.split(""); }
2854
		if(isString){ /*arr: String*/arr = arr.split(""); }
2837
		var outArr;
2855
		var outArr;
2838
		if(Array.filter){
2856
		if(Array.filter){
2839
			outArr = Array.filter(arr, callback, thisObject);
2857
			outArr = Array.filter(arr, callback, thisObject);
2840
		}else{
2858
		}else{
2841
			if(!thisObject){
2859
			if(!thisObject){
2842
				if(arguments.length >= 3){ dojo.raise("thisObject doesn't exist!"); }
2860
				if(arguments.length >= 3){ dojo.raise("thisObject doesn't exist!"); }
2843
				thisObject = dj_global;
2861
				thisObject = dj_global;
2844
			}
2862
			}
2845
 
2863
 
2846
			outArr = [];
2864
			outArr = [];
2847
			for(var i = 0; i < arr.length; i++){
2865
			for(var i = 0; i < arr.length; i++){
2848
				if(callback.call(thisObject, arr[i], i, arr)){
2866
				if(callback.call(thisObject, arr[i], i, arr)){
2849
					outArr.push(arr[i]);
2867
					outArr.push(arr[i]);
2850
				}
2868
				}
2851
			}
2869
			}
2852
		}
2870
		}
2853
		if(isString){
2871
		if(isString){
2854
			return outArr.join(""); // String
2872
			return outArr.join(""); // String
2855
		} else {
2873
		} else {
2856
			return outArr; // Array
2874
			return outArr; // Array
2857
		}
2875
		}
2858
	},
2876
	},
2859
 
2877
 
2860
	unnest: function(/* ... */){
2878
	unnest: function(/* ... */){
2861
		// summary:
2879
		// summary:
2862
		//		Creates a 1-D array out of all the arguments passed,
2880
		//		Creates a 1-D array out of all the arguments passed,
2863
		//		unravelling any array-like objects in the process
2881
		//		unravelling any array-like objects in the process
2864
		// usage:
2882
		// usage:
2865
		//		unnest(1, 2, 3) ==> [1, 2, 3]
2883
		//		unnest(1, 2, 3) ==> [1, 2, 3]
2866
		//		unnest(1, [2, [3], [[[4]]]]) ==> [1, 2, 3, 4]
2884
		//		unnest(1, [2, [3], [[[4]]]]) ==> [1, 2, 3, 4]
2867
 
2885
 
2868
		var out = [];
2886
		var out = [];
2869
		for(var i = 0; i < arguments.length; i++){
2887
		for(var i = 0; i < arguments.length; i++){
2870
			if(dojo.lang.isArrayLike(arguments[i])){
2888
			if(dojo.lang.isArrayLike(arguments[i])){
2871
				var add = dojo.lang.unnest.apply(this, arguments[i]);
2889
				var add = dojo.lang.unnest.apply(this, arguments[i]);
2872
				out = out.concat(add);
2890
				out = out.concat(add);
2873
			}else{
2891
			}else{
2874
				out.push(arguments[i]);
2892
				out.push(arguments[i]);
2875
			}
2893
			}
2876
		}
2894
		}
2877
		return out; // Array
2895
		return out; // Array
2878
	},
2896
	},
2879
 
2897
 
2880
	toArray: function(/*Object*/arrayLike, /*Number*/startOffset){
2898
	toArray: function(/*Object*/arrayLike, /*Number*/startOffset){
2881
		// summary:
2899
		// summary:
2882
		//		Converts an array-like object (i.e. arguments, DOMCollection)
2900
		//		Converts an array-like object (i.e. arguments, DOMCollection)
2883
		//		to an array. Returns a new Array object.
2901
		//		to an array. Returns a new Array object.
2884
		var array = [];
2902
		var array = [];
2885
		for(var i = startOffset||0; i < arrayLike.length; i++){
2903
		for(var i = startOffset||0; i < arrayLike.length; i++){
2886
			array.push(arrayLike[i]);
2904
			array.push(arrayLike[i]);
2887
		}
2905
		}
2888
		return array; // Array
2906
		return array; // Array
2889
	}
2907
	}
2890
});
2908
});
2891
 
2909
 
2892
dojo.provide("dojo.lang.func");
2910
dojo.provide("dojo.lang.func");
2893
 
2911
 
2894
 
2912
 
2895
dojo.lang.hitch = function(/*Object*/thisObject, /*Function|String*/method){
2913
dojo.lang.hitch = function(/*Object*/thisObject, /*Function|String*/method /*, ...*/){
2896
	// summary: 
2914
	// summary: 
2897
	//		Returns a function that will only ever execute in the a given scope
2915
	//		Returns a function that will only ever execute in the a given scope
2898
	//		(thisObject). This allows for easy use of object member functions
2916
	//		(thisObject). This allows for easy use of object member functions
2899
	//		in callbacks and other places in which the "this" keyword may
2917
	//		in callbacks and other places in which the "this" keyword may
2900
	//		otherwise not reference the expected scope. Note that the order of
2918
	//		otherwise not reference the expected scope. Any number of default
-
 
2919
	//		positional arguments may be passed as parameters beyond "method".
-
 
2920
	//		Each of these values will be used to "placehold" (similar to curry)
-
 
2921
	//		for the hitched function. Note that the order of arguments may be
2901
	//		arguments may be reversed in a future version.
2922
	//		reversed in a future version.
2902
	// thisObject: the scope to run the method in
2923
	// thisObject: the scope to run the method in
2903
	// method:
2924
	// method:
2904
	//		a function to be "bound" to thisObject or the name of the method in
2925
	//		a function to be "bound" to thisObject or the name of the method in
2905
	//		thisObject to be used as the basis for the binding
2926
	//		thisObject to be used as the basis for the binding
2906
	// usage:
2927
	// usage:
2907
	//		dojo.lang.hitch(foo, "bar")(); // runs foo.bar() in the scope of foo
2928
	//		dojo.lang.hitch(foo, "bar")(); // runs foo.bar() in the scope of foo
2908
	//		dojo.lang.hitch(foo, myFunction); // returns a function that runs myFunction in the scope of foo
2929
	//		dojo.lang.hitch(foo, myFunction); // returns a function that runs myFunction in the scope of foo
2909
 
2930
 
2910
	// FIXME:
2931
	var args = [];
2911
	//		should this be extended to "fixate" arguments in a manner similar
2932
	for(var x=2; x<arguments.length; x++){
-
 
2933
		args.push(arguments[x]);
2912
	//		to dojo.lang.curry, but without the default execution of curry()?
2934
	}
2913
	var fcn = (dojo.lang.isString(method) ? thisObject[method] : method) || function(){};
2935
	var fcn = (dojo.lang.isString(method) ? thisObject[method] : method) || function(){};
-
 
2936
	return function(){
-
 
2937
		var ta = args.concat([]); // make a copy
-
 
2938
		for(var x=0; x<arguments.length; x++){
-
 
2939
			ta.push(arguments[x]);
-
 
2940
		}
2914
	return function(){
2941
		return fcn.apply(thisObject, ta); // Function
2915
		return fcn.apply(thisObject, arguments); // Function
2942
		// return fcn.apply(thisObject, arguments); // Function
2916
	};
2943
	};
2917
}
2944
}
2918
 
2945
 
2919
dojo.lang.anonCtr = 0;
2946
dojo.lang.anonCtr = 0;
2920
dojo.lang.anon = {};
2947
dojo.lang.anon = {};
2921
 
2948
 
2922
dojo.lang.nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj, /*Boolean*/searchForNames){
2949
dojo.lang.nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj, /*Boolean*/searchForNames){
2923
	// summary:
2950
	// summary:
2924
	//		Creates a reference to anonFuncPtr in thisObj with a completely
2951
	//		Creates a reference to anonFuncPtr in thisObj with a completely
2925
	//		unique name. The new name is returned as a String.  If
2952
	//		unique name. The new name is returned as a String.  If
2926
	//		searchForNames is true, an effort will be made to locate an
2953
	//		searchForNames is true, an effort will be made to locate an
2927
	//		existing reference to anonFuncPtr in thisObj, and if one is found,
2954
	//		existing reference to anonFuncPtr in thisObj, and if one is found,
2928
	//		the existing name will be returned instead. The default is for
2955
	//		the existing name will be returned instead. The default is for
2929
	//		searchForNames to be false.
2956
	//		searchForNames to be false.
2930
	var nso = (thisObj|| dojo.lang.anon);
2957
	var nso = (thisObj|| dojo.lang.anon);
2931
	if( (searchForNames) ||
2958
	if( (searchForNames) ||
2932
		((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)) ){
2959
		((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)) ){
2933
		for(var x in nso){
2960
		for(var x in nso){
2934
			try{
2961
			try{
2935
				if(nso[x] === anonFuncPtr){
2962
				if(nso[x] === anonFuncPtr){
2936
					return x;
2963
					return x;
2937
				}
2964
				}
2938
			}catch(e){} // window.external fails in IE embedded in Eclipse (Eclipse bug #151165)
2965
			}catch(e){} // window.external fails in IE embedded in Eclipse (Eclipse bug #151165)
2939
		}
2966
		}
2940
	}
2967
	}
2941
	var ret = "__"+dojo.lang.anonCtr++;
2968
	var ret = "__"+dojo.lang.anonCtr++;
2942
	while(typeof nso[ret] != "undefined"){
2969
	while(typeof nso[ret] != "undefined"){
2943
		ret = "__"+dojo.lang.anonCtr++;
2970
		ret = "__"+dojo.lang.anonCtr++;
2944
	}
2971
	}
2945
	nso[ret] = anonFuncPtr;
2972
	nso[ret] = anonFuncPtr;
2946
	return ret; // String
2973
	return ret; // String
2947
}
2974
}
2948
 
2975
 
2949
dojo.lang.forward = function(funcName){
2976
dojo.lang.forward = function(funcName){
2950
	// summary:
2977
	// summary:
2951
	// 		Returns a function that forwards a method call to
2978
	// 		Returns a function that forwards a method call to
2952
	// 		this.funcName(...).  Unlike dojo.lang.hitch(), the "this" scope is
2979
	// 		this.funcName(...).  Unlike dojo.lang.hitch(), the "this" scope is
2953
	// 		not fixed on a single object. Ported from MochiKit.
2980
	// 		not fixed on a single object. Ported from MochiKit.
2954
	return function(){
2981
	return function(){
2955
		return this[funcName].apply(this, arguments);
2982
		return this[funcName].apply(this, arguments);
2956
	}; // Function
2983
	}; // Function
2957
}
2984
}
2958
 
2985
 
2959
dojo.lang.curry = function(thisObj, func /* args ... */){
2986
dojo.lang.curry = function(thisObj, func /* args ... */){
2960
	// summary:
2987
	// summary:
2961
	//		similar to the curry() method found in many functional programming
2988
	//		similar to the curry() method found in many functional programming
2962
	//		environments, this function returns an "argument accumulator"
2989
	//		environments, this function returns an "argument accumulator"
2963
	//		function, bound to a particular scope, and "primed" with a variable
2990
	//		function, bound to a particular scope, and "primed" with a variable
2964
	//		number of arguments. The curry method is unique in that it returns
2991
	//		number of arguments. The curry method is unique in that it returns
2965
	//		a function that may return other "partial" function which can be
2992
	//		a function that may return other "partial" function which can be
2966
	//		called repeatedly. New functions are returned until the arity of
2993
	//		called repeatedly. New functions are returned until the arity of
2967
	//		the original function is reached, at which point the underlying
2994
	//		the original function is reached, at which point the underlying
2968
	//		function (func) is called in the scope thisObj with all of the
2995
	//		function (func) is called in the scope thisObj with all of the
2969
	//		accumulated arguments (plus any extras) in positional order.
2996
	//		accumulated arguments (plus any extras) in positional order.
2970
	// examples:
2997
	// examples:
2971
	//		assuming a function defined like this:
2998
	//		assuming a function defined like this:
2972
	//			var foo = {
2999
	//			var foo = {
2973
	//				bar: function(arg1, arg2, arg3){
3000
	//				bar: function(arg1, arg2, arg3){
2974
	//					dojo.debug.apply(dojo, arguments);
3001
	//					dojo.debug.apply(dojo, arguments);
2975
	//				}
3002
	//				}
2976
	//			};
3003
	//			};
2977
	//		
3004
	//		
2978
	//		dojo.lang.curry() can be used most simply in this way:
3005
	//		dojo.lang.curry() can be used most simply in this way:
2979
	//		
3006
	//		
2980
	//			tmp = dojo.lang.curry(foo, foo.bar, "arg one", "thinger");
3007
	//			tmp = dojo.lang.curry(foo, foo.bar, "arg one", "thinger");
2981
	//			tmp("blah", "this is superfluous");
3008
	//			tmp("blah", "this is superfluous");
2982
	//			// debugs: "arg one thinger blah this is superfluous"
3009
	//			// debugs: "arg one thinger blah this is superfluous"
2983
	//			tmp("blah");
3010
	//			tmp("blah");
2984
	//			// debugs: "arg one thinger blah"
3011
	//			// debugs: "arg one thinger blah"
2985
	//			tmp();
3012
	//			tmp();
2986
	//			// returns a function exactly like tmp that expects one argument
3013
	//			// returns a function exactly like tmp that expects one argument
2987
	//
3014
	//
2988
	//		other intermittent functions could be created until the 3
3015
	//		other intermittent functions could be created until the 3
2989
	//		positional arguments are filled:
3016
	//		positional arguments are filled:
2990
	//
3017
	//
2991
	//			tmp = dojo.lang.curry(foo, foo.bar, "arg one");
3018
	//			tmp = dojo.lang.curry(foo, foo.bar, "arg one");
2992
	//			tmp2 = tmp("arg two");
3019
	//			tmp2 = tmp("arg two");
2993
	//			tmp2("blah blah");
3020
	//			tmp2("blah blah");
2994
	//			// debugs: "arg one arg two blah blah"
3021
	//			// debugs: "arg one arg two blah blah"
2995
	//			tmp2("oy");
3022
	//			tmp2("oy");
2996
	//			// debugs: "arg one arg two oy"
3023
	//			// debugs: "arg one arg two oy"
2997
	//
3024
	//
2998
	//		curry() can also be used to call the function if enough arguments
3025
	//		curry() can also be used to call the function if enough arguments
2999
	//		are passed in the initial invocation:
3026
	//		are passed in the initial invocation:
3000
	//
3027
	//
3001
	//			dojo.lang.curry(foo, foo.bar, "one", "two", "three", "four");
3028
	//			dojo.lang.curry(foo, foo.bar, "one", "two", "three", "four");
3002
	//			// debugs: "one two three four"
3029
	//			// debugs: "one two three four"
3003
	//			dojo.lang.curry(foo, foo.bar, "one", "two", "three");
3030
	//			dojo.lang.curry(foo, foo.bar, "one", "two", "three");
3004
	//			// debugs: "one two three"
3031
	//			// debugs: "one two three"
3005
 
3032
 
3006
 
3033
 
3007
	// FIXME: the order of func and thisObj should be changed!!!
3034
	// FIXME: the order of func and thisObj should be changed!!!
3008
	var outerArgs = [];
3035
	var outerArgs = [];
3009
	thisObj = thisObj||dj_global;
3036
	thisObj = thisObj||dj_global;
3010
	if(dojo.lang.isString(func)){
3037
	if(dojo.lang.isString(func)){
3011
		func = thisObj[func];
3038
		func = thisObj[func];
3012
	}
3039
	}
3013
	for(var x=2; x<arguments.length; x++){
3040
	for(var x=2; x<arguments.length; x++){
3014
		outerArgs.push(arguments[x]);
3041
		outerArgs.push(arguments[x]);
3015
	}
3042
	}
3016
	// since the event system replaces the original function with a new
3043
	// since the event system replaces the original function with a new
3017
	// join-point runner with an arity of 0, we check to see if it's left us
3044
	// join-point runner with an arity of 0, we check to see if it's left us
3018
	// any clues about the original arity in lieu of the function's actual
3045
	// any clues about the original arity in lieu of the function's actual
3019
	// length property
3046
	// length property
3020
	var ecount = (func["__preJoinArity"]||func.length) - outerArgs.length;
3047
	var ecount = (func["__preJoinArity"]||func.length) - outerArgs.length;
3021
	// borrowed from svend tofte
3048
	// borrowed from svend tofte
3022
	function gather(nextArgs, innerArgs, expected){
3049
	function gather(nextArgs, innerArgs, expected){
3023
		var texpected = expected;
3050
		var texpected = expected;
3024
		var totalArgs = innerArgs.slice(0); // copy
3051
		var totalArgs = innerArgs.slice(0); // copy
3025
		for(var x=0; x<nextArgs.length; x++){
3052
		for(var x=0; x<nextArgs.length; x++){
3026
			totalArgs.push(nextArgs[x]);
3053
			totalArgs.push(nextArgs[x]);
3027
		}
3054
		}
3028
		// check the list of provided nextArgs to see if it, plus the
3055
		// check the list of provided nextArgs to see if it, plus the
3029
		// number of innerArgs already supplied, meets the total
3056
		// number of innerArgs already supplied, meets the total
3030
		// expected.
3057
		// expected.
3031
		expected = expected-nextArgs.length;
3058
		expected = expected-nextArgs.length;
3032
		if(expected<=0){
3059
		if(expected<=0){
3033
			var res = func.apply(thisObj, totalArgs);
3060
			var res = func.apply(thisObj, totalArgs);
3034
			expected = texpected;
3061
			expected = texpected;
3035
			return res;
3062
			return res;
3036
		}else{
3063
		}else{
3037
			return function(){
3064
			return function(){
3038
				return gather(arguments,// check to see if we've been run
3065
				return gather(arguments,// check to see if we've been run
3039
										// with enough args
3066
										// with enough args
3040
							totalArgs,	// a copy
3067
							totalArgs,	// a copy
3041
							expected);	// how many more do we need to run?;
3068
							expected);	// how many more do we need to run?;
3042
			};
3069
			};
3043
		}
3070
		}
3044
	}
3071
	}
3045
	return gather([], outerArgs, ecount);
3072
	return gather([], outerArgs, ecount);
3046
}
3073
}
3047
 
3074
 
3048
dojo.lang.curryArguments = function(/*Object*/thisObj, /*Function*/func, /*Array*/args, /*Integer, optional*/offset){
3075
dojo.lang.curryArguments = function(/*Object*/thisObj, /*Function*/func, /*Array*/args, /*Integer, optional*/offset){
3049
	// summary:
3076
	// summary:
3050
	//		similar to dojo.lang.curry(), except that a list of arguments to
3077
	//		similar to dojo.lang.curry(), except that a list of arguments to
3051
	//		start the curry with may be provided as an array instead of as
3078
	//		start the curry with may be provided as an array instead of as
3052
	//		positional arguments. An offset may be specified from the 0 index
3079
	//		positional arguments. An offset may be specified from the 0 index
3053
	//		to skip some elements in args.
3080
	//		to skip some elements in args.
3054
	var targs = [];
3081
	var targs = [];
3055
	var x = offset||0;
3082
	var x = offset||0;
3056
	for(x=offset; x<args.length; x++){
3083
	for(x=offset; x<args.length; x++){
3057
		targs.push(args[x]); // ensure that it's an arr
3084
		targs.push(args[x]); // ensure that it's an arr
3058
	}
3085
	}
3059
	return dojo.lang.curry.apply(dojo.lang, [thisObj, func].concat(targs));
3086
	return dojo.lang.curry.apply(dojo.lang, [thisObj, func].concat(targs));
3060
}
3087
}
3061
 
3088
 
3062
dojo.lang.tryThese = function(/*...*/){
3089
dojo.lang.tryThese = function(/*...*/){
3063
	// summary:
3090
	// summary:
3064
	//		executes each function argument in turn, returning the return value
3091
	//		executes each function argument in turn, returning the return value
3065
	//		from the first one which does not throw an exception in execution.
3092
	//		from the first one which does not throw an exception in execution.
3066
	//		Any number of functions may be passed.
3093
	//		Any number of functions may be passed.
3067
	for(var x=0; x<arguments.length; x++){
3094
	for(var x=0; x<arguments.length; x++){
3068
		try{
3095
		try{
3069
			if(typeof arguments[x] == "function"){
3096
			if(typeof arguments[x] == "function"){
3070
				var ret = (arguments[x]());
3097
				var ret = (arguments[x]());
3071
				if(ret){
3098
				if(ret){
3072
					return ret;
3099
					return ret;
3073
				}
3100
				}
3074
			}
3101
			}
3075
		}catch(e){
3102
		}catch(e){
3076
			dojo.debug(e);
3103
			dojo.debug(e);
3077
		}
3104
		}
3078
	}
3105
	}
3079
}
3106
}
3080
 
3107
 
3081
dojo.lang.delayThese = function(/*Array*/farr, /*Function, optional*/cb, /*Integer*/delay, /*Function, optional*/onend){
3108
dojo.lang.delayThese = function(/*Array*/farr, /*Function, optional*/cb, /*Integer*/delay, /*Function, optional*/onend){
3082
	// summary:
3109
	// summary:
3083
	//		executes a series of functions contained in farr, but spaces out
3110
	//		executes a series of functions contained in farr, but spaces out
3084
	//		calls to each function by the millisecond delay provided. If cb is
3111
	//		calls to each function by the millisecond delay provided. If cb is
3085
	//		provided, it will be called directly after each item in farr is
3112
	//		provided, it will be called directly after each item in farr is
3086
	//		called and if onend is passed, it will be called when all items
3113
	//		called and if onend is passed, it will be called when all items
3087
	//		have completed executing.
3114
	//		have completed executing.
3088
 
3115
 
3089
	/**
3116
	/**
3090
	 * alternate: (array funcArray, function callback, function onend)
3117
	 * alternate: (array funcArray, function callback, function onend)
3091
	 * alternate: (array funcArray, function callback)
3118
	 * alternate: (array funcArray, function callback)
3092
	 * alternate: (array funcArray)
3119
	 * alternate: (array funcArray)
3093
	 */
3120
	 */
3094
	if(!farr.length){ 
3121
	if(!farr.length){ 
3095
		if(typeof onend == "function"){
3122
		if(typeof onend == "function"){
3096
			onend();
3123
			onend();
3097
		}
3124
		}
3098
		return;
3125
		return;
3099
	}
3126
	}
3100
	if((typeof delay == "undefined")&&(typeof cb == "number")){
3127
	if((typeof delay == "undefined")&&(typeof cb == "number")){
3101
		delay = cb;
3128
		delay = cb;
3102
		cb = function(){};
3129
		cb = function(){};
3103
	}else if(!cb){
3130
	}else if(!cb){
3104
		cb = function(){};
3131
		cb = function(){};
3105
		if(!delay){ delay = 0; }
3132
		if(!delay){ delay = 0; }
3106
	}
3133
	}
3107
	setTimeout(function(){
3134
	setTimeout(function(){
3108
		(farr.shift())();
3135
		(farr.shift())();
3109
		cb();
3136
		cb();
3110
		dojo.lang.delayThese(farr, cb, delay, onend);
3137
		dojo.lang.delayThese(farr, cb, delay, onend);
3111
	}, delay);
3138
	}, delay);
3112
}
3139
}
3113
 
3140
 
3114
dojo.provide("dojo.string.extras");
3141
dojo.provide("dojo.string.extras");
3115
 
3142
 
3116
 
3143
 
3117
 
3144
 
3118
 
3145
 
3119
 
3146
 
3120
//TODO: should we use ${} substitution syntax instead, like widgets do?
3147
//TODO: should we use ${} substitution syntax instead, like widgets do?
3121
dojo.string.substituteParams = function(/*string*/template, /* object - optional or ... */hash){
3148
dojo.string.substituteParams = function(/*string*/template, /* object - optional or ... */hash){
3122
// summary:
3149
// summary:
3123
//	Performs parameterized substitutions on a string. Throws an exception if any parameter is unmatched.
3150
//	Performs parameterized substitutions on a string. Throws an exception if any parameter is unmatched.
3124
//
3151
//
3125
// description:
3152
// description:
3126
//	For example,
3153
//	For example,
3127
//		dojo.string.substituteParams("File '%{0}' is not found in directory '%{1}'.","foo.html","/temp");
3154
//		dojo.string.substituteParams("File '%{0}' is not found in directory '%{1}'.","foo.html","/temp");
3128
//	returns
3155
//	returns
3129
//		"File 'foo.html' is not found in directory '/temp'."
3156
//		"File 'foo.html' is not found in directory '/temp'."
3130
//
3157
//
3131
// template: the original string template with %{values} to be replaced
3158
// template: the original string template with %{values} to be replaced
3132
// hash: name/value pairs (type object) to provide substitutions.  Alternatively, substitutions may be
3159
// hash: name/value pairs (type object) to provide substitutions.  Alternatively, substitutions may be
3133
//	included as arguments 1..n to this function, corresponding to template parameters 0..n-1
3160
//	included as arguments 1..n to this function, corresponding to template parameters 0..n-1
3134
 
3161
 
3135
	var map = (typeof hash == 'object') ? hash : dojo.lang.toArray(arguments, 1);
3162
	var map = (typeof hash == 'object') ? hash : dojo.lang.toArray(arguments, 1);
3136
 
3163
 
3137
	return template.replace(/\%\{(\w+)\}/g, function(match, key){
3164
	return template.replace(/\%\{(\w+)\}/g, function(match, key){
3138
		if(typeof(map[key]) != "undefined" && map[key] != null){
3165
		if(typeof(map[key]) != "undefined" && map[key] != null){
3139
			return map[key];
3166
			return map[key];
3140
		}
3167
		}
3141
		dojo.raise("Substitution not found: " + key);
3168
		dojo.raise("Substitution not found: " + key);
3142
	}); // string
3169
	}); // string
3143
};
3170
};
3144
 
3171
 
3145
dojo.string.capitalize = function(/*string*/str){
3172
dojo.string.capitalize = function(/*string*/str){
3146
// summary:
3173
// summary:
3147
//	Uppercases the first letter of each word
3174
//	Uppercases the first letter of each word
3148
 
3175
 
3149
	if(!dojo.lang.isString(str)){ return ""; }
3176
	if(!dojo.lang.isString(str)){ return ""; }
3150
	if(arguments.length == 0){ str = this; }
3177
	if(arguments.length == 0){ str = this; }
3151
 
3178
 
3152
	var words = str.split(' ');
3179
	var words = str.split(' ');
3153
	for(var i=0; i<words.length; i++){
3180
	for(var i=0; i<words.length; i++){
3154
		words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
3181
		words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1);
3155
	}
3182
	}
3156
	return words.join(" "); // string
3183
	return words.join(" "); // string
3157
}
3184
}
3158
 
3185
 
3159
dojo.string.isBlank = function(/*string*/str){
3186
dojo.string.isBlank = function(/*string*/str){
3160
// summary:
3187
// summary:
3161
//	Return true if the entire string is whitespace characters
3188
//	Return true if the entire string is whitespace characters
3162
 
3189
 
3163
	if(!dojo.lang.isString(str)){ return true; }
3190
	if(!dojo.lang.isString(str)){ return true; }
3164
	return (dojo.string.trim(str).length == 0); // boolean
3191
	return (dojo.string.trim(str).length == 0); // boolean
3165
}
3192
}
3166
 
3193
 
3167
//FIXME: not sure exactly what encodeAscii is trying to do, or if it's working right
3194
//FIXME: not sure exactly what encodeAscii is trying to do, or if it's working right
3168
dojo.string.encodeAscii = function(/*string*/str){
3195
dojo.string.encodeAscii = function(/*string*/str){
3169
	if(!dojo.lang.isString(str)){ return str; } // unknown
3196
	if(!dojo.lang.isString(str)){ return str; } // unknown
3170
	var ret = "";
3197
	var ret = "";
3171
	var value = escape(str);
3198
	var value = escape(str);
3172
	var match, re = /%u([0-9A-F]{4})/i;
3199
	var match, re = /%u([0-9A-F]{4})/i;
3173
	while((match = value.match(re))){
3200
	while((match = value.match(re))){
3174
		var num = Number("0x"+match[1]);
3201
		var num = Number("0x"+match[1]);
3175
		var newVal = escape("&#" + num + ";");
3202
		var newVal = escape("&#" + num + ";");
3176
		ret += value.substring(0, match.index) + newVal;
3203
		ret += value.substring(0, match.index) + newVal;
3177
		value = value.substring(match.index+match[0].length);
3204
		value = value.substring(match.index+match[0].length);
3178
	}
3205
	}
3179
	ret += value.replace(/\+/g, "%2B");
3206
	ret += value.replace(/\+/g, "%2B");
3180
	return ret; // string
3207
	return ret; // string
3181
}
3208
}
3182
 
3209
 
3183
dojo.string.escape = function(/*string*/type, /*string*/str){
3210
dojo.string.escape = function(/*string*/type, /*string*/str){
3184
// summary:
3211
// summary:
3185
//	Adds escape sequences for special characters according to the convention of 'type'
3212
//	Adds escape sequences for special characters according to the convention of 'type'
3186
//
3213
//
3187
// type: one of xml|html|xhtml|sql|regexp|regex|javascript|jscript|js|ascii
3214
// type: one of xml|html|xhtml|sql|regexp|regex|javascript|jscript|js|ascii
3188
// str: the string to be escaped
3215
// str: the string to be escaped
3189
 
3216
 
3190
	var args = dojo.lang.toArray(arguments, 1);
3217
	var args = dojo.lang.toArray(arguments, 1);
3191
	switch(type.toLowerCase()){
3218
	switch(type.toLowerCase()){
3192
		case "xml":
3219
		case "xml":
3193
		case "html":
3220
		case "html":
3194
		case "xhtml":
3221
		case "xhtml":
3195
			return dojo.string.escapeXml.apply(this, args); // string
3222
			return dojo.string.escapeXml.apply(this, args); // string
3196
		case "sql":
3223
		case "sql":
3197
			return dojo.string.escapeSql.apply(this, args); // string
3224
			return dojo.string.escapeSql.apply(this, args); // string
3198
		case "regexp":
3225
		case "regexp":
3199
		case "regex":
3226
		case "regex":
3200
			return dojo.string.escapeRegExp.apply(this, args); // string
3227
			return dojo.string.escapeRegExp.apply(this, args); // string
3201
		case "javascript":
3228
		case "javascript":
3202
		case "jscript":
3229
		case "jscript":
3203
		case "js":
3230
		case "js":
3204
			return dojo.string.escapeJavaScript.apply(this, args); // string
3231
			return dojo.string.escapeJavaScript.apply(this, args); // string
3205
		case "ascii":
3232
		case "ascii":
3206
			// so it's encode, but it seems useful
3233
			// so it's encode, but it seems useful
3207
			return dojo.string.encodeAscii.apply(this, args); // string
3234
			return dojo.string.encodeAscii.apply(this, args); // string
3208
		default:
3235
		default:
3209
			return str; // string
3236
			return str; // string
3210
	}
3237
	}
3211
}
3238
}
3212
 
3239
 
3213
dojo.string.escapeXml = function(/*string*/str, /*boolean*/noSingleQuotes){
3240
dojo.string.escapeXml = function(/*string*/str, /*boolean*/noSingleQuotes){
3214
//summary:
3241
//summary:
3215
//	Adds escape sequences for special characters in XML: &<>"'
3242
//	Adds escape sequences for special characters in XML: &<>"'
3216
//  Optionally skips escapes for single quotes
3243
//  Optionally skips escapes for single quotes
3217
 
3244
 
3218
	str = str.replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
3245
	str = str.replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
3219
		.replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
3246
		.replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
3220
	if(!noSingleQuotes){ str = str.replace(/'/gm, "&#39;"); }
3247
	if(!noSingleQuotes){ str = str.replace(/'/gm, "&#39;"); }
3221
	return str; // string
3248
	return str; // string
3222
}
3249
}
3223
 
3250
 
3224
dojo.string.escapeSql = function(/*string*/str){
3251
dojo.string.escapeSql = function(/*string*/str){
3225
//summary:
3252
//summary:
3226
//	Adds escape sequences for single quotes in SQL expressions
3253
//	Adds escape sequences for single quotes in SQL expressions
3227
 
3254
 
3228
	return str.replace(/'/gm, "''"); //string
3255
	return str.replace(/'/gm, "''"); //string
3229
}
3256
}
3230
 
3257
 
3231
dojo.string.escapeRegExp = function(/*string*/str){
3258
dojo.string.escapeRegExp = function(/*string*/str){
3232
//summary:
3259
//summary:
3233
//	Adds escape sequences for special characters in regular expressions
3260
//	Adds escape sequences for special characters in regular expressions
3234
 
3261
 
3235
	return str.replace(/\\/gm, "\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm, "\\$1"); // string
3262
	return str.replace(/\\/gm, "\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm, "\\$1"); // string
3236
}
3263
}
3237
 
3264
 
3238
//FIXME: should this one also escape backslash?
3265
//FIXME: should this one also escape backslash?
3239
dojo.string.escapeJavaScript = function(/*string*/str){
3266
dojo.string.escapeJavaScript = function(/*string*/str){
3240
//summary:
3267
//summary:
3241
//	Adds escape sequences for single and double quotes as well
3268
//	Adds escape sequences for single and double quotes as well
3242
//	as non-visible characters in JavaScript string literal expressions
3269
//	as non-visible characters in JavaScript string literal expressions
3243
 
3270
 
3244
	return str.replace(/(["'\f\b\n\t\r])/gm, "\\$1"); // string
3271
	return str.replace(/(["'\f\b\n\t\r])/gm, "\\$1"); // string
3245
}
3272
}
3246
 
3273
 
3247
//FIXME: looks a lot like escapeJavaScript, just adds quotes? deprecate one?
3274
//FIXME: looks a lot like escapeJavaScript, just adds quotes? deprecate one?
3248
dojo.string.escapeString = function(/*string*/str){
3275
dojo.string.escapeString = function(/*string*/str){
3249
//summary:
3276
//summary:
3250
//	Adds escape sequences for non-visual characters, double quote and backslash
3277
//	Adds escape sequences for non-visual characters, double quote and backslash
3251
//	and surrounds with double quotes to form a valid string literal.
3278
//	and surrounds with double quotes to form a valid string literal.
3252
	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
3279
	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
3253
		).replace(/[\f]/g, "\\f"
3280
		).replace(/[\f]/g, "\\f"
3254
		).replace(/[\b]/g, "\\b"
3281
		).replace(/[\b]/g, "\\b"
3255
		).replace(/[\n]/g, "\\n"
3282
		).replace(/[\n]/g, "\\n"
3256
		).replace(/[\t]/g, "\\t"
3283
		).replace(/[\t]/g, "\\t"
3257
		).replace(/[\r]/g, "\\r"); // string
3284
		).replace(/[\r]/g, "\\r"); // string
3258
}
3285
}
3259
 
3286
 
3260
// TODO: make an HTML version
3287
// TODO: make an HTML version
3261
dojo.string.summary = function(/*string*/str, /*number*/len){
3288
dojo.string.summary = function(/*string*/str, /*number*/len){
3262
// summary:
3289
// summary:
3263
//	Truncates 'str' after 'len' characters and appends periods as necessary so that it ends with "..."
3290
//	Truncates 'str' after 'len' characters and appends periods as necessary so that it ends with "..."
3264
 
3291
 
3265
	if(!len || str.length <= len){
3292
	if(!len || str.length <= len){
3266
		return str; // string
3293
		return str; // string
3267
	}
3294
	}
3268
 
3295
 
3269
	return str.substring(0, len).replace(/\.+$/, "") + "..."; // string
3296
	return str.substring(0, len).replace(/\.+$/, "") + "..."; // string
3270
}
3297
}
3271
 
3298
 
3272
dojo.string.endsWith = function(/*string*/str, /*string*/end, /*boolean*/ignoreCase){
3299
dojo.string.endsWith = function(/*string*/str, /*string*/end, /*boolean*/ignoreCase){
3273
// summary:
3300
// summary:
3274
//	Returns true if 'str' ends with 'end'
3301
//	Returns true if 'str' ends with 'end'
3275
 
3302
 
3276
	if(ignoreCase){
3303
	if(ignoreCase){
3277
		str = str.toLowerCase();
3304
		str = str.toLowerCase();
3278
		end = end.toLowerCase();
3305
		end = end.toLowerCase();
3279
	}
3306
	}
3280
	if((str.length - end.length) < 0){
3307
	if((str.length - end.length) < 0){
3281
		return false; // boolean
3308
		return false; // boolean
3282
	}
3309
	}
3283
	return str.lastIndexOf(end) == str.length - end.length; // boolean
3310
	return str.lastIndexOf(end) == str.length - end.length; // boolean
3284
}
3311
}
3285
 
3312
 
3286
dojo.string.endsWithAny = function(/*string*/str /* , ... */){
3313
dojo.string.endsWithAny = function(/*string*/str /* , ... */){
3287
// summary:
3314
// summary:
3288
//	Returns true if 'str' ends with any of the arguments[2 -> n]
3315
//	Returns true if 'str' ends with any of the arguments[2 -> n]
3289
 
3316
 
3290
	for(var i = 1; i < arguments.length; i++) {
3317
	for(var i = 1; i < arguments.length; i++) {
3291
		if(dojo.string.endsWith(str, arguments[i])) {
3318
		if(dojo.string.endsWith(str, arguments[i])) {
3292
			return true; // boolean
3319
			return true; // boolean
3293
		}
3320
		}
3294
	}
3321
	}
3295
	return false; // boolean
3322
	return false; // boolean
3296
}
3323
}
3297
 
3324
 
3298
dojo.string.startsWith = function(/*string*/str, /*string*/start, /*boolean*/ignoreCase){
3325
dojo.string.startsWith = function(/*string*/str, /*string*/start, /*boolean*/ignoreCase){
3299
// summary:
3326
// summary:
3300
//	Returns true if 'str' starts with 'start'
3327
//	Returns true if 'str' starts with 'start'
3301
 
3328
 
3302
	if(ignoreCase) {
3329
	if(ignoreCase) {
3303
		str = str.toLowerCase();
3330
		str = str.toLowerCase();
3304
		start = start.toLowerCase();
3331
		start = start.toLowerCase();
3305
	}
3332
	}
3306
	return str.indexOf(start) == 0; // boolean
3333
	return str.indexOf(start) == 0; // boolean
3307
}
3334
}
3308
 
3335
 
3309
dojo.string.startsWithAny = function(/*string*/str /* , ... */){
3336
dojo.string.startsWithAny = function(/*string*/str /* , ... */){
3310
// summary:
3337
// summary:
3311
//	Returns true if 'str' starts with any of the arguments[2 -> n]
3338
//	Returns true if 'str' starts with any of the arguments[2 -> n]
3312
 
3339
 
3313
	for(var i = 1; i < arguments.length; i++) {
3340
	for(var i = 1; i < arguments.length; i++) {
3314
		if(dojo.string.startsWith(str, arguments[i])) {
3341
		if(dojo.string.startsWith(str, arguments[i])) {
3315
			return true; // boolean
3342
			return true; // boolean
3316
		}
3343
		}
3317
	}
3344
	}
3318
	return false; // boolean
3345
	return false; // boolean
3319
}
3346
}
3320
 
3347
 
3321
dojo.string.has = function(/*string*/str /* , ... */) {
3348
dojo.string.has = function(/*string*/str /* , ... */) {
3322
// summary:
3349
// summary:
3323
//	Returns true if 'str' contains any of the arguments 2 -> n
3350
//	Returns true if 'str' contains any of the arguments 2 -> n
3324
 
3351
 
3325
	for(var i = 1; i < arguments.length; i++) {
3352
	for(var i = 1; i < arguments.length; i++) {
3326
		if(str.indexOf(arguments[i]) > -1){
3353
		if(str.indexOf(arguments[i]) > -1){
3327
			return true; // boolean
3354
			return true; // boolean
3328
		}
3355
		}
3329
	}
3356
	}
3330
	return false; // boolean
3357
	return false; // boolean
3331
}
3358
}
3332
 
3359
 
3333
dojo.string.normalizeNewlines = function(/*string*/text, /*string? (\n or \r)*/newlineChar){
3360
dojo.string.normalizeNewlines = function(/*string*/text, /*string? (\n or \r)*/newlineChar){
3334
// summary:
3361
// summary:
3335
//	Changes occurences of CR and LF in text to CRLF, or if newlineChar is provided as '\n' or '\r',
3362
//	Changes occurences of CR and LF in text to CRLF, or if newlineChar is provided as '\n' or '\r',
3336
//	substitutes newlineChar for occurrences of CR/LF and CRLF
3363
//	substitutes newlineChar for occurrences of CR/LF and CRLF
3337
 
3364
 
3338
	if (newlineChar == "\n"){
3365
	if (newlineChar == "\n"){
3339
		text = text.replace(/\r\n/g, "\n");
3366
		text = text.replace(/\r\n/g, "\n");
3340
		text = text.replace(/\r/g, "\n");
3367
		text = text.replace(/\r/g, "\n");
3341
	} else if (newlineChar == "\r"){
3368
	} else if (newlineChar == "\r"){
3342
		text = text.replace(/\r\n/g, "\r");
3369
		text = text.replace(/\r\n/g, "\r");
3343
		text = text.replace(/\n/g, "\r");
3370
		text = text.replace(/\n/g, "\r");
3344
	}else{
3371
	}else{
3345
		text = text.replace(/([^\r])\n/g, "$1\r\n").replace(/\r([^\n])/g, "\r\n$1");
3372
		text = text.replace(/([^\r])\n/g, "$1\r\n").replace(/\r([^\n])/g, "\r\n$1");
3346
	}
3373
	}
3347
	return text; // string
3374
	return text; // string
3348
}
3375
}
3349
 
3376
 
3350
dojo.string.splitEscaped = function(/*string*/str, /*string of length=1*/charac){
3377
dojo.string.splitEscaped = function(/*string*/str, /*string of length=1*/charac){
3351
// summary:
3378
// summary:
3352
//	Splits 'str' into an array separated by 'charac', but skips characters escaped with a backslash
3379
//	Splits 'str' into an array separated by 'charac', but skips characters escaped with a backslash
3353
 
3380
 
3354
	var components = [];
3381
	var components = [];
3355
	for (var i = 0, prevcomma = 0; i < str.length; i++){
3382
	for (var i = 0, prevcomma = 0; i < str.length; i++){
3356
		if (str.charAt(i) == '\\'){ i++; continue; }
3383
		if (str.charAt(i) == '\\'){ i++; continue; }
3357
		if (str.charAt(i) == charac){
3384
		if (str.charAt(i) == charac){
3358
			components.push(str.substring(prevcomma, i));
3385
			components.push(str.substring(prevcomma, i));
3359
			prevcomma = i + 1;
3386
			prevcomma = i + 1;
3360
		}
3387
		}
3361
	}
3388
	}
3362
	components.push(str.substr(prevcomma));
3389
	components.push(str.substr(prevcomma));
3363
	return components; // array
3390
	return components; // array
3364
}
3391
}
3365
 
3392
 
3366
dojo.provide("dojo.dom");
3393
dojo.provide("dojo.dom");
3367
 
3394
 
3368
dojo.dom.ELEMENT_NODE                  = 1;
3395
dojo.dom.ELEMENT_NODE                  = 1;
3369
dojo.dom.ATTRIBUTE_NODE                = 2;
3396
dojo.dom.ATTRIBUTE_NODE                = 2;
3370
dojo.dom.TEXT_NODE                     = 3;
3397
dojo.dom.TEXT_NODE                     = 3;
3371
dojo.dom.CDATA_SECTION_NODE            = 4;
3398
dojo.dom.CDATA_SECTION_NODE            = 4;
3372
dojo.dom.ENTITY_REFERENCE_NODE         = 5;
3399
dojo.dom.ENTITY_REFERENCE_NODE         = 5;
3373
dojo.dom.ENTITY_NODE                   = 6;
3400
dojo.dom.ENTITY_NODE                   = 6;
3374
dojo.dom.PROCESSING_INSTRUCTION_NODE   = 7;
3401
dojo.dom.PROCESSING_INSTRUCTION_NODE   = 7;
3375
dojo.dom.COMMENT_NODE                  = 8;
3402
dojo.dom.COMMENT_NODE                  = 8;
3376
dojo.dom.DOCUMENT_NODE                 = 9;
3403
dojo.dom.DOCUMENT_NODE                 = 9;
3377
dojo.dom.DOCUMENT_TYPE_NODE            = 10;
3404
dojo.dom.DOCUMENT_TYPE_NODE            = 10;
3378
dojo.dom.DOCUMENT_FRAGMENT_NODE        = 11;
3405
dojo.dom.DOCUMENT_FRAGMENT_NODE        = 11;
3379
dojo.dom.NOTATION_NODE                 = 12;
3406
dojo.dom.NOTATION_NODE                 = 12;
3380
	
3407
	
3381
dojo.dom.dojoml = "http://www.dojotoolkit.org/2004/dojoml";
3408
dojo.dom.dojoml = "http://www.dojotoolkit.org/2004/dojoml";
3382
 
3409
 
3383
/**
3410
/**
3384
 *	comprehensive list of XML namespaces
3411
 *	comprehensive list of XML namespaces
3385
**/
3412
**/
3386
dojo.dom.xmlns = {
3413
dojo.dom.xmlns = {
3387
	//	summary
3414
	//	summary
3388
	//	aliases for various common XML namespaces
3415
	//	aliases for various common XML namespaces
3389
	svg : "http://www.w3.org/2000/svg",
3416
	svg : "http://www.w3.org/2000/svg",
3390
	smil : "http://www.w3.org/2001/SMIL20/",
3417
	smil : "http://www.w3.org/2001/SMIL20/",
3391
	mml : "http://www.w3.org/1998/Math/MathML",
3418
	mml : "http://www.w3.org/1998/Math/MathML",
3392
	cml : "http://www.xml-cml.org",
3419
	cml : "http://www.xml-cml.org",
3393
	xlink : "http://www.w3.org/1999/xlink",
3420
	xlink : "http://www.w3.org/1999/xlink",
3394
	xhtml : "http://www.w3.org/1999/xhtml",
3421
	xhtml : "http://www.w3.org/1999/xhtml",
3395
	xul : "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
3422
	xul : "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
3396
	xbl : "http://www.mozilla.org/xbl",
3423
	xbl : "http://www.mozilla.org/xbl",
3397
	fo : "http://www.w3.org/1999/XSL/Format",
3424
	fo : "http://www.w3.org/1999/XSL/Format",
3398
	xsl : "http://www.w3.org/1999/XSL/Transform",
3425
	xsl : "http://www.w3.org/1999/XSL/Transform",
3399
	xslt : "http://www.w3.org/1999/XSL/Transform",
3426
	xslt : "http://www.w3.org/1999/XSL/Transform",
3400
	xi : "http://www.w3.org/2001/XInclude",
3427
	xi : "http://www.w3.org/2001/XInclude",
3401
	xforms : "http://www.w3.org/2002/01/xforms",
3428
	xforms : "http://www.w3.org/2002/01/xforms",
3402
	saxon : "http://icl.com/saxon",
3429
	saxon : "http://icl.com/saxon",
3403
	xalan : "http://xml.apache.org/xslt",
3430
	xalan : "http://xml.apache.org/xslt",
3404
	xsd : "http://www.w3.org/2001/XMLSchema",
3431
	xsd : "http://www.w3.org/2001/XMLSchema",
3405
	dt: "http://www.w3.org/2001/XMLSchema-datatypes",
3432
	dt: "http://www.w3.org/2001/XMLSchema-datatypes",
3406
	xsi : "http://www.w3.org/2001/XMLSchema-instance",
3433
	xsi : "http://www.w3.org/2001/XMLSchema-instance",
3407
	rdf : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
3434
	rdf : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
3408
	rdfs : "http://www.w3.org/2000/01/rdf-schema#",
3435
	rdfs : "http://www.w3.org/2000/01/rdf-schema#",
3409
	dc : "http://purl.org/dc/elements/1.1/",
3436
	dc : "http://purl.org/dc/elements/1.1/",
3410
	dcq: "http://purl.org/dc/qualifiers/1.0",
3437
	dcq: "http://purl.org/dc/qualifiers/1.0",
3411
	"soap-env" : "http://schemas.xmlsoap.org/soap/envelope/",
3438
	"soap-env" : "http://schemas.xmlsoap.org/soap/envelope/",
3412
	wsdl : "http://schemas.xmlsoap.org/wsdl/",
3439
	wsdl : "http://schemas.xmlsoap.org/wsdl/",
3413
	AdobeExtensions : "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
3440
	AdobeExtensions : "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
3414
};
3441
};
3415
 
3442
 
3416
dojo.dom.isNode = function(/* object */wh){
3443
dojo.dom.isNode = function(/* object */wh){
3417
	//	summary:
3444
	//	summary:
3418
	//		checks to see if wh is actually a node.
3445
	//		checks to see if wh is actually a node.
3419
	if(typeof Element == "function") {
3446
	if(typeof Element == "function") {
3420
		try {
3447
		try {
3421
			return wh instanceof Element;	//	boolean
3448
			return wh instanceof Element;	//	boolean
3422
		} catch(e) {}
3449
		} catch(e) {}
3423
	} else {
3450
	} else {
3424
		// best-guess
3451
		// best-guess
3425
		return wh && !isNaN(wh.nodeType);	//	boolean
3452
		return wh && !isNaN(wh.nodeType);	//	boolean
3426
	}
3453
	}
3427
}
3454
}
3428
 
3455
 
3429
dojo.dom.getUniqueId = function(){
3456
dojo.dom.getUniqueId = function(){
3430
	//	summary:
3457
	//	summary:
3431
	//		returns a unique string for use with any DOM element
3458
	//		returns a unique string for use with any DOM element
3432
	var _document = dojo.doc();
3459
	var _document = dojo.doc();
3433
	do {
3460
	do {
3434
		var id = "dj_unique_" + (++arguments.callee._idIncrement);
3461
		var id = "dj_unique_" + (++arguments.callee._idIncrement);
3435
	}while(_document.getElementById(id));
3462
	}while(_document.getElementById(id));
3436
	return id;	//	string
3463
	return id;	//	string
3437
}
3464
}
3438
dojo.dom.getUniqueId._idIncrement = 0;
3465
dojo.dom.getUniqueId._idIncrement = 0;
3439
 
3466
 
3440
dojo.dom.firstElement = dojo.dom.getFirstChildElement = function(/* Element */parentNode, /* string? */tagName){
3467
dojo.dom.firstElement = dojo.dom.getFirstChildElement = function(/* Element */parentNode, /* string? */tagName){
3441
	//	summary:
3468
	//	summary:
3442
	//		returns the first child element matching tagName
3469
	//		returns the first child element matching tagName
3443
	var node = parentNode.firstChild;
3470
	var node = parentNode.firstChild;
3444
	while(node && node.nodeType != dojo.dom.ELEMENT_NODE){
3471
	while(node && node.nodeType != dojo.dom.ELEMENT_NODE){
3445
		node = node.nextSibling;
3472
		node = node.nextSibling;
3446
	}
3473
	}
3447
	if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
3474
	if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
3448
		node = dojo.dom.nextElement(node, tagName);
3475
		node = dojo.dom.nextElement(node, tagName);
3449
	}
3476
	}
3450
	return node;	//	Element
3477
	return node;	//	Element
3451
}
3478
}
3452
 
3479
 
3453
dojo.dom.lastElement = dojo.dom.getLastChildElement = function(/* Element */parentNode, /* string? */tagName){
3480
dojo.dom.lastElement = dojo.dom.getLastChildElement = function(/* Element */parentNode, /* string? */tagName){
3454
	//	summary:
3481
	//	summary:
3455
	//		returns the last child element matching tagName
3482
	//		returns the last child element matching tagName
3456
	var node = parentNode.lastChild;
3483
	var node = parentNode.lastChild;
3457
	while(node && node.nodeType != dojo.dom.ELEMENT_NODE) {
3484
	while(node && node.nodeType != dojo.dom.ELEMENT_NODE) {
3458
		node = node.previousSibling;
3485
		node = node.previousSibling;
3459
	}
3486
	}
3460
	if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
3487
	if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
3461
		node = dojo.dom.prevElement(node, tagName);
3488
		node = dojo.dom.prevElement(node, tagName);
3462
	}
3489
	}
3463
	return node;	//	Element
3490
	return node;	//	Element
3464
}
3491
}
3465
 
3492
 
3466
dojo.dom.nextElement = dojo.dom.getNextSiblingElement = function(/* Node */node, /* string? */tagName){
3493
dojo.dom.nextElement = dojo.dom.getNextSiblingElement = function(/* Node */node, /* string? */tagName){
3467
	//	summary:
3494
	//	summary:
3468
	//		returns the next sibling element matching tagName
3495
	//		returns the next sibling element matching tagName
3469
	if(!node) { return null; }
3496
	if(!node) { return null; }
3470
	do {
3497
	do {
3471
		node = node.nextSibling;
3498
		node = node.nextSibling;
3472
	} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
3499
	} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
3473
 
3500
 
3474
	if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
3501
	if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
3475
		return dojo.dom.nextElement(node, tagName);
3502
		return dojo.dom.nextElement(node, tagName);
3476
	}
3503
	}
3477
	return node;	//	Element
3504
	return node;	//	Element
3478
}
3505
}
3479
 
3506
 
3480
dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement = function(/* Node */node, /* string? */tagName){
3507
dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement = function(/* Node */node, /* string? */tagName){
3481
	//	summary:
3508
	//	summary:
3482
	//		returns the previous sibling element matching tagName
3509
	//		returns the previous sibling element matching tagName
3483
	if(!node) { return null; }
3510
	if(!node) { return null; }
3484
	if(tagName) { tagName = tagName.toLowerCase(); }
3511
	if(tagName) { tagName = tagName.toLowerCase(); }
3485
	do {
3512
	do {
3486
		node = node.previousSibling;
3513
		node = node.previousSibling;
3487
	} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
3514
	} while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
3488
 
3515
 
3489
	if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
3516
	if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
3490
		return dojo.dom.prevElement(node, tagName);
3517
		return dojo.dom.prevElement(node, tagName);
3491
	}
3518
	}
3492
	return node;	//	Element
3519
	return node;	//	Element
3493
}
3520
}
3494
 
3521
 
3495
// TODO: hmph
3522
// TODO: hmph
3496
/*this.forEachChildTag = function(node, unaryFunc) {
3523
/*this.forEachChildTag = function(node, unaryFunc) {
3497
	var child = this.getFirstChildTag(node);
3524
	var child = this.getFirstChildTag(node);
3498
	while(child) {
3525
	while(child) {
3499
		if(unaryFunc(child) == "break") { break; }
3526
		if(unaryFunc(child) == "break") { break; }
3500
		child = this.getNextSiblingTag(child);
3527
		child = this.getNextSiblingTag(child);
3501
	}
3528
	}
3502
}*/
3529
}*/
3503
 
3530
 
3504
dojo.dom.moveChildren = function(/*Element*/srcNode, /*Element*/destNode, /*boolean?*/trim){
3531
dojo.dom.moveChildren = function(/*Element*/srcNode, /*Element*/destNode, /*boolean?*/trim){
3505
	//	summary:
3532
	//	summary:
3506
	//		Moves children from srcNode to destNode and returns the count of
3533
	//		Moves children from srcNode to destNode and returns the count of
3507
	//		children moved; will trim off text nodes if trim == true
3534
	//		children moved; will trim off text nodes if trim == true
3508
	var count = 0;
3535
	var count = 0;
3509
	if(trim) {
3536
	if(trim) {
3510
		while(srcNode.hasChildNodes() &&
3537
		while(srcNode.hasChildNodes() &&
3511
			srcNode.firstChild.nodeType == dojo.dom.TEXT_NODE) {
3538
			srcNode.firstChild.nodeType == dojo.dom.TEXT_NODE) {
3512
			srcNode.removeChild(srcNode.firstChild);
3539
			srcNode.removeChild(srcNode.firstChild);
3513
		}
3540
		}
3514
		while(srcNode.hasChildNodes() &&
3541
		while(srcNode.hasChildNodes() &&
3515
			srcNode.lastChild.nodeType == dojo.dom.TEXT_NODE) {
3542
			srcNode.lastChild.nodeType == dojo.dom.TEXT_NODE) {
3516
			srcNode.removeChild(srcNode.lastChild);
3543
			srcNode.removeChild(srcNode.lastChild);
3517
		}
3544
		}
3518
	}
3545
	}
3519
	while(srcNode.hasChildNodes()){
3546
	while(srcNode.hasChildNodes()){
3520
		destNode.appendChild(srcNode.firstChild);
3547
		destNode.appendChild(srcNode.firstChild);
3521
		count++;
3548
		count++;
3522
	}
3549
	}
3523
	return count;	//	number
3550
	return count;	//	number
3524
}
3551
}
3525
 
3552
 
3526
dojo.dom.copyChildren = function(/*Element*/srcNode, /*Element*/destNode, /*boolean?*/trim){
3553
dojo.dom.copyChildren = function(/*Element*/srcNode, /*Element*/destNode, /*boolean?*/trim){
3527
	//	summary:
3554
	//	summary:
3528
	//		Copies children from srcNde to destNode and returns the count of
3555
	//		Copies children from srcNde to destNode and returns the count of
3529
	//		children copied; will trim off text nodes if trim == true
3556
	//		children copied; will trim off text nodes if trim == true
3530
	var clonedNode = srcNode.cloneNode(true);
3557
	var clonedNode = srcNode.cloneNode(true);
3531
	return this.moveChildren(clonedNode, destNode, trim);	//	number
3558
	return this.moveChildren(clonedNode, destNode, trim);	//	number
3532
}
3559
}
3533
 
3560
 
3534
dojo.dom.replaceChildren = function(/*Element*/node, /*Node*/newChild){
3561
dojo.dom.replaceChildren = function(/*Element*/node, /*Node*/newChild){
3535
	//	summary:
3562
	//	summary:
3536
	//		Removes all children of node and appends newChild. All the existing
3563
	//		Removes all children of node and appends newChild. All the existing
3537
	//		children will be destroyed.
3564
	//		children will be destroyed.
3538
	// FIXME: what if newChild is an array-like object?
3565
	// FIXME: what if newChild is an array-like object?
3539
	var nodes = [];
3566
	var nodes = [];
3540
	if(dojo.render.html.ie){
3567
	if(dojo.render.html.ie){
3541
		for(var i=0;i<node.childNodes.length;i++){
3568
		for(var i=0;i<node.childNodes.length;i++){
3542
			nodes.push(node.childNodes[i]);
3569
			nodes.push(node.childNodes[i]);
3543
		}
3570
		}
3544
	}
3571
	}
3545
	dojo.dom.removeChildren(node);
3572
	dojo.dom.removeChildren(node);
3546
	node.appendChild(newChild);
3573
	node.appendChild(newChild);
3547
	for(var i=0;i<nodes.length;i++){
3574
	for(var i=0;i<nodes.length;i++){
3548
		dojo.dom.destroyNode(nodes[i]);
3575
		dojo.dom.destroyNode(nodes[i]);
3549
	}
3576
	}
3550
}
3577
}
3551
 
3578
 
3552
dojo.dom.removeChildren = function(/*Element*/node){
3579
dojo.dom.removeChildren = function(/*Element*/node){
3553
	//	summary:
3580
	//	summary:
3554
	//		removes all children from node and returns the count of children removed.
3581
	//		removes all children from node and returns the count of children removed.
3555
	//		The children nodes are not destroyed. Be sure to call destroyNode on them
3582
	//		The children nodes are not destroyed. Be sure to call destroyNode on them
3556
	//		after they are not used anymore.
3583
	//		after they are not used anymore.
3557
	var count = node.childNodes.length;
3584
	var count = node.childNodes.length;
3558
	while(node.hasChildNodes()){ dojo.dom.removeNode(node.firstChild); }
3585
	while(node.hasChildNodes()){ dojo.dom.removeNode(node.firstChild); }
3559
	return count; // int
3586
	return count; // int
3560
}
3587
}
3561
 
3588
 
3562
dojo.dom.replaceNode = function(/*Element*/node, /*Element*/newNode){
3589
dojo.dom.replaceNode = function(/*Element*/node, /*Element*/newNode){
3563
	//	summary:
3590
	//	summary:
3564
	//		replaces node with newNode and returns a reference to the removed node.
3591
	//		replaces node with newNode and returns a reference to the removed node.
3565
	//		To prevent IE memory leak, call destroyNode on the returned node when
3592
	//		To prevent IE memory leak, call destroyNode on the returned node when
3566
	//		it is no longer needed.
3593
	//		it is no longer needed.
3567
	return node.parentNode.replaceChild(newNode, node); // Node
3594
	return node.parentNode.replaceChild(newNode, node); // Node
3568
}
3595
}
3569
 
3596
 
3570
dojo.dom.destroyNode = function(/*Node*/node){
3597
dojo.dom.destroyNode = function(/*Node*/node){
3571
	// summary:
3598
	// summary:
3572
	//		destroy a node (it can not be used any more). For IE, this is the
3599
	//		destroy a node (it can not be used any more). For IE, this is the
3573
	//		right function to call to prevent memory leaks. While for other
3600
	//		right function to call to prevent memory leaks. While for other
3574
	//		browsers, this is identical to dojo.dom.removeNode
3601
	//		browsers, this is identical to dojo.dom.removeNode
3575
	if(node.parentNode){
3602
	if(node.parentNode){
3576
		node = dojo.dom.removeNode(node);
3603
		node = dojo.dom.removeNode(node);
3577
	}
3604
	}
3578
	if(node.nodeType != 3){ // ingore TEXT_NODE
3605
	if(node.nodeType != 3){ // ingore TEXT_NODE
3579
		if(dojo.evalObjPath("dojo.event.browser.clean", false)){
3606
		if(dojo.evalObjPath("dojo.event.browser.clean", false)){
3580
			dojo.event.browser.clean(node);
3607
			dojo.event.browser.clean(node);
3581
		}
3608
		}
3582
		if(dojo.render.html.ie){
3609
		if(dojo.render.html.ie){
3583
			node.outerHTML=''; //prevent ugly IE mem leak associated with Node.removeChild (ticket #1727)
3610
			node.outerHTML=''; //prevent ugly IE mem leak associated with Node.removeChild (ticket #1727)
3584
		}
3611
		}
3585
	}
3612
	}
3586
}
3613
}
3587
 
3614
 
3588
dojo.dom.removeNode = function(/*Node*/node){
3615
dojo.dom.removeNode = function(/*Node*/node){
3589
	// summary:
3616
	// summary:
3590
	//		if node has a parent, removes node from parent and returns a
3617
	//		if node has a parent, removes node from parent and returns a
3591
	//		reference to the removed child.
3618
	//		reference to the removed child.
3592
	//		To prevent IE memory leak, call destroyNode on the returned node when
3619
	//		To prevent IE memory leak, call destroyNode on the returned node when
3593
	//		it is no longer needed.
3620
	//		it is no longer needed.
3594
	//	node:
3621
	//	node:
3595
	//		the node to remove from its parent.
3622
	//		the node to remove from its parent.
3596
 
3623
 
3597
	if(node && node.parentNode){
3624
	if(node && node.parentNode){
3598
		// return a ref to the removed child
3625
		// return a ref to the removed child
3599
		return node.parentNode.removeChild(node); //Node
3626
		return node.parentNode.removeChild(node); //Node
3600
	}
3627
	}
3601
}
3628
}
3602
 
3629
 
3603
dojo.dom.getAncestors = function(/*Node*/node, /*function?*/filterFunction, /*boolean?*/returnFirstHit){
3630
dojo.dom.getAncestors = function(/*Node*/node, /*function?*/filterFunction, /*boolean?*/returnFirstHit){
3604
	//	summary:
3631
	//	summary:
3605
	//		returns all ancestors matching optional filterFunction; will return
3632
	//		returns all ancestors matching optional filterFunction; will return
3606
	//		only the first if returnFirstHit
3633
	//		only the first if returnFirstHit
3607
	var ancestors = [];
3634
	var ancestors = [];
3608
	var isFunction = (filterFunction && (filterFunction instanceof Function || typeof filterFunction == "function"));
3635
	var isFunction = (filterFunction && (filterFunction instanceof Function || typeof filterFunction == "function"));
3609
	while(node){
3636
	while(node){
3610
		if(!isFunction || filterFunction(node)){
3637
		if(!isFunction || filterFunction(node)){
3611
			ancestors.push(node);
3638
			ancestors.push(node);
3612
		}
3639
		}
3613
		if(returnFirstHit && ancestors.length > 0){ 
3640
		if(returnFirstHit && ancestors.length > 0){ 
3614
			return ancestors[0]; 	//	Node
3641
			return ancestors[0]; 	//	Node
3615
		}
3642
		}
3616
		
3643
		
3617
		node = node.parentNode;
3644
		node = node.parentNode;
3618
	}
3645
	}
3619
	if(returnFirstHit){ return null; }
3646
	if(returnFirstHit){ return null; }
3620
	return ancestors;	//	array
3647
	return ancestors;	//	array
3621
}
3648
}
3622
 
3649
 
3623
dojo.dom.getAncestorsByTag = function(/*Node*/node, /*String*/tag, /*boolean?*/returnFirstHit){
3650
dojo.dom.getAncestorsByTag = function(/*Node*/node, /*String*/tag, /*boolean?*/returnFirstHit){
3624
	//	summary:
3651
	//	summary:
3625
	//		returns all ancestors matching tag (as tagName), will only return
3652
	//		returns all ancestors matching tag (as tagName), will only return
3626
	//		first one if returnFirstHit
3653
	//		first one if returnFirstHit
3627
	tag = tag.toLowerCase();
3654
	tag = tag.toLowerCase();
3628
	return dojo.dom.getAncestors(node, function(el){
3655
	return dojo.dom.getAncestors(node, function(el){
3629
		return ((el.tagName)&&(el.tagName.toLowerCase() == tag));
3656
		return ((el.tagName)&&(el.tagName.toLowerCase() == tag));
3630
	}, returnFirstHit);	//	Node || array
3657
	}, returnFirstHit);	//	Node || array
3631
}
3658
}
3632
 
3659
 
3633
dojo.dom.getFirstAncestorByTag = function(/*Node*/node, /*string*/tag){
3660
dojo.dom.getFirstAncestorByTag = function(/*Node*/node, /*string*/tag){
3634
	//	summary:
3661
	//	summary:
3635
	//		Returns first ancestor of node with tag tagName
3662
	//		Returns first ancestor of node with tag tagName
3636
	return dojo.dom.getAncestorsByTag(node, tag, true);	//	Node
3663
	return dojo.dom.getAncestorsByTag(node, tag, true);	//	Node
3637
}
3664
}
3638
 
3665
 
3639
dojo.dom.isDescendantOf = function(/* Node */node, /* Node */ancestor, /* boolean? */guaranteeDescendant){
3666
dojo.dom.isDescendantOf = function(/* Node */node, /* Node */ancestor, /* boolean? */guaranteeDescendant){
3640
	//	summary
3667
	//	summary
3641
	//	Returns boolean if node is a descendant of ancestor
3668
	//	Returns boolean if node is a descendant of ancestor
3642
	// guaranteeDescendant allows us to be a "true" isDescendantOf function
3669
	// guaranteeDescendant allows us to be a "true" isDescendantOf function
3643
	if(guaranteeDescendant && node) { node = node.parentNode; }
3670
	if(guaranteeDescendant && node) { node = node.parentNode; }
3644
	while(node) {
3671
	while(node) {
3645
		if(node == ancestor){ 
3672
		if(node == ancestor){ 
3646
			return true; 	//	boolean
3673
			return true; 	//	boolean
3647
		}
3674
		}
3648
		node = node.parentNode;
3675
		node = node.parentNode;
3649
	}
3676
	}
3650
	return false;	//	boolean
3677
	return false;	//	boolean
3651
}
3678
}
3652
 
3679
 
3653
dojo.dom.innerXML = function(/*Node*/node){
3680
dojo.dom.innerXML = function(/*Node*/node){
3654
	//	summary:
3681
	//	summary:
3655
	//		Implementation of MS's innerXML function.
3682
	//		Implementation of MS's innerXML function.
3656
	if(node.innerXML){
3683
	if(node.innerXML){
3657
		return node.innerXML;	//	string
3684
		return node.innerXML;	//	string
3658
	}else if (node.xml){
3685
	}else if (node.xml){
3659
		return node.xml;		//	string
3686
		return node.xml;		//	string
3660
	}else if(typeof XMLSerializer != "undefined"){
3687
	}else if(typeof XMLSerializer != "undefined"){
3661
		return (new XMLSerializer()).serializeToString(node);	//	string
3688
		return (new XMLSerializer()).serializeToString(node);	//	string
3662
	}
3689
	}
3663
}
3690
}
3664
 
3691
 
3665
dojo.dom.createDocument = function(){
3692
dojo.dom.createDocument = function(){
3666
	//	summary:
3693
	//	summary:
3667
	//		cross-browser implementation of creating an XML document object.
3694
	//		cross-browser implementation of creating an XML document object.
3668
	var doc = null;
3695
	var doc = null;
3669
	var _document = dojo.doc();
3696
	var _document = dojo.doc();
3670
 
3697
 
3671
	if(!dj_undef("ActiveXObject")){
3698
	if(!dj_undef("ActiveXObject")){
3672
		var prefixes = [ "MSXML2", "Microsoft", "MSXML", "MSXML3" ];
3699
		var prefixes = [ "MSXML2", "Microsoft", "MSXML", "MSXML3" ];
3673
		for(var i = 0; i<prefixes.length; i++){
3700
		for(var i = 0; i<prefixes.length; i++){
3674
			try{
3701
			try{
3675
				doc = new ActiveXObject(prefixes[i]+".XMLDOM");
3702
				doc = new ActiveXObject(prefixes[i]+".XMLDOM");
3676
			}catch(e){ /* squelch */ };
3703
			}catch(e){ /* squelch */ };
3677
 
3704
 
3678
			if(doc){ break; }
3705
			if(doc){ break; }
3679
		}
3706
		}
3680
	}else if((_document.implementation)&&
3707
	}else if((_document.implementation)&&
3681
		(_document.implementation.createDocument)){
3708
		(_document.implementation.createDocument)){
3682
		doc = _document.implementation.createDocument("", "", null);
3709
		doc = _document.implementation.createDocument("", "", null);
3683
	}
3710
	}
3684
	
3711
	
3685
	return doc;	//	DOMDocument
3712
	return doc;	//	DOMDocument
3686
}
3713
}
3687
 
3714
 
3688
dojo.dom.createDocumentFromText = function(/*string*/str, /*string?*/mimetype){
3715
dojo.dom.createDocumentFromText = function(/*string*/str, /*string?*/mimetype){
3689
	//	summary:
3716
	//	summary:
3690
	//		attempts to create a Document object based on optional mime-type,
3717
	//		attempts to create a Document object based on optional mime-type,
3691
	//		using str as the contents of the document
3718
	//		using str as the contents of the document
3692
	if(!mimetype){ mimetype = "text/xml"; }
3719
	if(!mimetype){ mimetype = "text/xml"; }
3693
	if(!dj_undef("DOMParser")){
3720
	if(!dj_undef("DOMParser")){
3694
		var parser = new DOMParser();
3721
		var parser = new DOMParser();
3695
		return parser.parseFromString(str, mimetype);	//	DOMDocument
3722
		return parser.parseFromString(str, mimetype);	//	DOMDocument
3696
	}else if(!dj_undef("ActiveXObject")){
3723
	}else if(!dj_undef("ActiveXObject")){
3697
		var domDoc = dojo.dom.createDocument();
3724
		var domDoc = dojo.dom.createDocument();
3698
		if(domDoc){
3725
		if(domDoc){
3699
			domDoc.async = false;
3726
			domDoc.async = false;
3700
			domDoc.loadXML(str);
3727
			domDoc.loadXML(str);
3701
			return domDoc;	//	DOMDocument
3728
			return domDoc;	//	DOMDocument
3702
		}else{
3729
		}else{
3703
			dojo.debug("toXml didn't work?");
3730
			dojo.debug("toXml didn't work?");
3704
		}
3731
		}
3705
	/*
3732
	/*
3706
	}else if((dojo.render.html.capable)&&(dojo.render.html.safari)){
3733
	}else if((dojo.render.html.capable)&&(dojo.render.html.safari)){
3707
		// FIXME: this doesn't appear to work!
3734
		// FIXME: this doesn't appear to work!
3708
		// from: http://web-graphics.com/mtarchive/001606.php
3735
		// from: http://web-graphics.com/mtarchive/001606.php
3709
		// var xml = '<?xml version="1.0"?>'+str;
3736
		// var xml = '<?xml version="1.0"?>'+str;
3710
		var mtype = "text/xml";
3737
		var mtype = "text/xml";
3711
		var xml = '<?xml version="1.0"?>'+str;
3738
		var xml = '<?xml version="1.0"?>'+str;
3712
		var url = "data:"+mtype+";charset=utf-8,"+encodeURIComponent(xml);
3739
		var url = "data:"+mtype+";charset=utf-8,"+encodeURIComponent(xml);
3713
		var req = new XMLHttpRequest();
3740
		var req = new XMLHttpRequest();
3714
		req.open("GET", url, false);
3741
		req.open("GET", url, false);
3715
		req.overrideMimeType(mtype);
3742
		req.overrideMimeType(mtype);
3716
		req.send(null);
3743
		req.send(null);
3717
		return req.responseXML;
3744
		return req.responseXML;
3718
	*/
3745
	*/
3719
	}else{
3746
	}else{
3720
		var _document = dojo.doc();
3747
		var _document = dojo.doc();
3721
		if(_document.createElement){
3748
		if(_document.createElement){
3722
			// FIXME: this may change all tags to uppercase!
3749
			// FIXME: this may change all tags to uppercase!
3723
			var tmp = _document.createElement("xml");
3750
			var tmp = _document.createElement("xml");
3724
			tmp.innerHTML = str;
3751
			tmp.innerHTML = str;
3725
			if(_document.implementation && _document.implementation.createDocument){
3752
			if(_document.implementation && _document.implementation.createDocument){
3726
				var xmlDoc = _document.implementation.createDocument("foo", "", null);
3753
				var xmlDoc = _document.implementation.createDocument("foo", "", null);
3727
				for(var i = 0; i < tmp.childNodes.length; i++) {
3754
				for(var i = 0; i < tmp.childNodes.length; i++) {
3728
					xmlDoc.importNode(tmp.childNodes.item(i), true);
3755
					xmlDoc.importNode(tmp.childNodes.item(i), true);
3729
				}
3756
				}
3730
				return xmlDoc;	//	DOMDocument
3757
				return xmlDoc;	//	DOMDocument
3731
			}
3758
			}
3732
			// FIXME: probably not a good idea to have to return an HTML fragment
3759
			// FIXME: probably not a good idea to have to return an HTML fragment
3733
			// FIXME: the tmp.doc.firstChild is as tested from IE, so it may not
3760
			// FIXME: the tmp.doc.firstChild is as tested from IE, so it may not
3734
			// work that way across the board
3761
			// work that way across the board
3735
			return ((tmp.document)&&
3762
			return ((tmp.document)&&
3736
				(tmp.document.firstChild ?  tmp.document.firstChild : tmp));	//	DOMDocument
3763
				(tmp.document.firstChild ?  tmp.document.firstChild : tmp));	//	DOMDocument
3737
		}
3764
		}
3738
	}
3765
	}
3739
	return null;
3766
	return null;
3740
}
3767
}
3741
 
3768
 
3742
dojo.dom.prependChild = function(/*Element*/node, /*Element*/parent){
3769
dojo.dom.prependChild = function(/*Element*/node, /*Element*/parent){
3743
	//	summary:
3770
	//	summary:
3744
	//		prepends node to parent's children nodes
3771
	//		prepends node to parent's children nodes
3745
	if(parent.firstChild) {
3772
	if(parent.firstChild) {
3746
		parent.insertBefore(node, parent.firstChild);
3773
		parent.insertBefore(node, parent.firstChild);
3747
	} else {
3774
	} else {
3748
		parent.appendChild(node);
3775
		parent.appendChild(node);
3749
	}
3776
	}
3750
	return true;	//	boolean
3777
	return true;	//	boolean
3751
}
3778
}
3752
 
3779
 
3753
dojo.dom.insertBefore = function(/*Node*/node, /*Node*/ref, /*boolean?*/force){
3780
dojo.dom.insertBefore = function(/*Node*/node, /*Node*/ref, /*boolean?*/force){
3754
	//	summary:
3781
	//	summary:
3755
	//		Try to insert node before ref
3782
	//		Try to insert node before ref
3756
	if(	(force != true)&&
3783
	if(	(force != true)&&
3757
		(node === ref || node.nextSibling === ref)){ return false; }
3784
		(node === ref || node.nextSibling === ref)){ return false; }
3758
	var parent = ref.parentNode;
3785
	var parent = ref.parentNode;
3759
	parent.insertBefore(node, ref);
3786
	parent.insertBefore(node, ref);
3760
	return true;	//	boolean
3787
	return true;	//	boolean
3761
}
3788
}
3762
 
3789
 
3763
dojo.dom.insertAfter = function(/*Node*/node, /*Node*/ref, /*boolean?*/force){
3790
dojo.dom.insertAfter = function(/*Node*/node, /*Node*/ref, /*boolean?*/force){
3764
	//	summary:
3791
	//	summary:
3765
	//		Try to insert node after ref
3792
	//		Try to insert node after ref
3766
	var pn = ref.parentNode;
3793
	var pn = ref.parentNode;
3767
	if(ref == pn.lastChild){
3794
	if(ref == pn.lastChild){
3768
		if((force != true)&&(node === ref)){
3795
		if((force != true)&&(node === ref)){
3769
			return false;	//	boolean
3796
			return false;	//	boolean
3770
		}
3797
		}
3771
		pn.appendChild(node);
3798
		pn.appendChild(node);
3772
	}else{
3799
	}else{
3773
		return this.insertBefore(node, ref.nextSibling, force);	//	boolean
3800
		return this.insertBefore(node, ref.nextSibling, force);	//	boolean
3774
	}
3801
	}
3775
	return true;	//	boolean
3802
	return true;	//	boolean
3776
}
3803
}
3777
 
3804
 
3778
dojo.dom.insertAtPosition = function(/*Node*/node, /*Node*/ref, /*string*/position){
3805
dojo.dom.insertAtPosition = function(/*Node*/node, /*Node*/ref, /*string*/position){
3779
	//	summary:
3806
	//	summary:
3780
	//		attempt to insert node in relation to ref based on position
3807
	//		attempt to insert node in relation to ref based on position
3781
	if((!node)||(!ref)||(!position)){ 
3808
	if((!node)||(!ref)||(!position)){ 
3782
		return false;	//	boolean 
3809
		return false;	//	boolean 
3783
	}
3810
	}
3784
	switch(position.toLowerCase()){
3811
	switch(position.toLowerCase()){
3785
		case "before":
3812
		case "before":
3786
			return dojo.dom.insertBefore(node, ref);	//	boolean
3813
			return dojo.dom.insertBefore(node, ref);	//	boolean
3787
		case "after":
3814
		case "after":
3788
			return dojo.dom.insertAfter(node, ref);		//	boolean
3815
			return dojo.dom.insertAfter(node, ref);		//	boolean
3789
		case "first":
3816
		case "first":
3790
			if(ref.firstChild){
3817
			if(ref.firstChild){
3791
				return dojo.dom.insertBefore(node, ref.firstChild);	//	boolean
3818
				return dojo.dom.insertBefore(node, ref.firstChild);	//	boolean
3792
			}else{
3819
			}else{
3793
				ref.appendChild(node);
3820
				ref.appendChild(node);
3794
				return true;	//	boolean
3821
				return true;	//	boolean
3795
			}
3822
			}
3796
			break;
3823
			break;
3797
		default: // aka: last
3824
		default: // aka: last
3798
			ref.appendChild(node);
3825
			ref.appendChild(node);
3799
			return true;	//	boolean
3826
			return true;	//	boolean
3800
	}
3827
	}
3801
}
3828
}
3802
 
3829
 
3803
dojo.dom.insertAtIndex = function(/*Node*/node, /*Element*/containingNode, /*number*/insertionIndex){
3830
dojo.dom.insertAtIndex = function(/*Node*/node, /*Element*/containingNode, /*number*/insertionIndex){
3804
	//	summary:
3831
	//	summary:
3805
	//		insert node into child nodes nodelist of containingNode at
3832
	//		insert node into child nodes nodelist of containingNode at
3806
	//		insertionIndex. insertionIndex should be between 0 and 
3833
	//		insertionIndex. insertionIndex should be between 0 and 
3807
	//		the number of the childNodes in containingNode. insertionIndex
3834
	//		the number of the childNodes in containingNode. insertionIndex
3808
	//		specifys after how many childNodes in containingNode the node
3835
	//		specifys after how many childNodes in containingNode the node
3809
	//		shall be inserted. If 0 is given, node will be appended to 
3836
	//		shall be inserted. If 0 is given, node will be appended to 
3810
	//		containingNode.
3837
	//		containingNode.
3811
	var siblingNodes = containingNode.childNodes;
3838
	var siblingNodes = containingNode.childNodes;
3812
 
3839
 
3813
	// if there aren't any kids yet, just add it to the beginning
3840
	// if there aren't any kids yet, just add it to the beginning
3814
 
3841
 
3815
	if (!siblingNodes.length || siblingNodes.length == insertionIndex){
3842
	if (!siblingNodes.length || siblingNodes.length == insertionIndex){
3816
		containingNode.appendChild(node);
3843
		containingNode.appendChild(node);
3817
		return true;	//	boolean
3844
		return true;	//	boolean
3818
	}
3845
	}
3819
 
3846
 
3820
	if(insertionIndex == 0){
3847
	if(insertionIndex == 0){
3821
		return dojo.dom.prependChild(node, containingNode);	//	boolean
3848
		return dojo.dom.prependChild(node, containingNode);	//	boolean
3822
	}
3849
	}
3823
	// otherwise we need to walk the childNodes
3850
	// otherwise we need to walk the childNodes
3824
	// and find our spot
3851
	// and find our spot
3825
 
3852
 
3826
	return dojo.dom.insertAfter(node, siblingNodes[insertionIndex-1]);	//	boolean
3853
	return dojo.dom.insertAfter(node, siblingNodes[insertionIndex-1]);	//	boolean
3827
}
3854
}
3828
	
3855
	
3829
dojo.dom.textContent = function(/*Node*/node, /*string*/text){
3856
dojo.dom.textContent = function(/*Node*/node, /*string*/text){
3830
	//	summary:
3857
	//	summary:
3831
	//		implementation of the DOM Level 3 attribute; scan node for text
3858
	//		implementation of the DOM Level 3 attribute; scan node for text
3832
	if (arguments.length>1) {
3859
	if (arguments.length>1) {
3833
		var _document = dojo.doc();
3860
		var _document = dojo.doc();
3834
		dojo.dom.replaceChildren(node, _document.createTextNode(text));
3861
		dojo.dom.replaceChildren(node, _document.createTextNode(text));
3835
		return text;	//	string
3862
		return text;	//	string
3836
	} else {
3863
	} else {
3837
		if(node.textContent != undefined){ //FF 1.5
3864
		if(node.textContent != undefined){ //FF 1.5
3838
			return node.textContent;	//	string
3865
			return node.textContent;	//	string
3839
		}
3866
		}
3840
		var _result = "";
3867
		var _result = "";
3841
		if (node == null) { return _result; }
3868
		if (node == null) { return _result; }
3842
		for (var i = 0; i < node.childNodes.length; i++) {
3869
		for (var i = 0; i < node.childNodes.length; i++) {
3843
			switch (node.childNodes[i].nodeType) {
3870
			switch (node.childNodes[i].nodeType) {
3844
				case 1: // ELEMENT_NODE
3871
				case 1: // ELEMENT_NODE
3845
				case 5: // ENTITY_REFERENCE_NODE
3872
				case 5: // ENTITY_REFERENCE_NODE
3846
					_result += dojo.dom.textContent(node.childNodes[i]);
3873
					_result += dojo.dom.textContent(node.childNodes[i]);
3847
					break;
3874
					break;
3848
				case 3: // TEXT_NODE
3875
				case 3: // TEXT_NODE
3849
				case 2: // ATTRIBUTE_NODE
3876
				case 2: // ATTRIBUTE_NODE
3850
				case 4: // CDATA_SECTION_NODE
3877
				case 4: // CDATA_SECTION_NODE
3851
					_result += node.childNodes[i].nodeValue;
3878
					_result += node.childNodes[i].nodeValue;
3852
					break;
3879
					break;
3853
				default:
3880
				default:
3854
					break;
3881
					break;
3855
			}
3882
			}
3856
		}
3883
		}
3857
		return _result;	//	string
3884
		return _result;	//	string
3858
	}
3885
	}
3859
}
3886
}
3860
 
3887
 
3861
dojo.dom.hasParent = function(/*Node*/node){
3888
dojo.dom.hasParent = function(/*Node*/node){
3862
	//	summary:
3889
	//	summary:
3863
	//		returns whether or not node is a child of another node.
3890
	//		returns whether or not node is a child of another node.
3864
	return Boolean(node && node.parentNode && dojo.dom.isNode(node.parentNode));	//	boolean
3891
	return Boolean(node && node.parentNode && dojo.dom.isNode(node.parentNode));	//	boolean
3865
}
3892
}
3866
 
3893
 
3867
/**
3894
/**
3868
 * Examples:
3895
 * Examples:
3869
 *
3896
 *
3870
 * myFooNode = <foo />
3897
 * myFooNode = <foo />
3871
 * isTag(myFooNode, "foo"); // returns "foo"
3898
 * isTag(myFooNode, "foo"); // returns "foo"
3872
 * isTag(myFooNode, "bar"); // returns ""
3899
 * isTag(myFooNode, "bar"); // returns ""
3873
 * isTag(myFooNode, "FOO"); // returns ""
3900
 * isTag(myFooNode, "FOO"); // returns ""
3874
 * isTag(myFooNode, "hey", "foo", "bar"); // returns "foo"
3901
 * isTag(myFooNode, "hey", "foo", "bar"); // returns "foo"
3875
**/
3902
**/
3876
dojo.dom.isTag = function(/* Node */node /* ... */){
3903
dojo.dom.isTag = function(/* Node */node /* ... */){
3877
	//	summary:
3904
	//	summary:
3878
	//		determines if node has any of the provided tag names and returns
3905
	//		determines if node has any of the provided tag names and returns
3879
	//		the tag name that matches, empty string otherwise.
3906
	//		the tag name that matches, empty string otherwise.
3880
	if(node && node.tagName) {
3907
	if(node && node.tagName) {
3881
		for(var i=1; i<arguments.length; i++){
3908
		for(var i=1; i<arguments.length; i++){
3882
			if(node.tagName==String(arguments[i])){
3909
			if(node.tagName==String(arguments[i])){
3883
				return String(arguments[i]);	//	string
3910
				return String(arguments[i]);	//	string
3884
			}
3911
			}
3885
		}
3912
		}
3886
	}
3913
	}
3887
	return "";	//	string
3914
	return "";	//	string
3888
}
3915
}
3889
 
3916
 
3890
dojo.dom.setAttributeNS = function(	/*Element*/elem, /*string*/namespaceURI, 
3917
dojo.dom.setAttributeNS = function(	/*Element*/elem, /*string*/namespaceURI, 
3891
									/*string*/attrName, /*string*/attrValue){
3918
									/*string*/attrName, /*string*/attrValue){
3892
	//	summary:
3919
	//	summary:
3893
	//		implementation of DOM2 setAttributeNS that works cross browser.
3920
	//		implementation of DOM2 setAttributeNS that works cross browser.
3894
	if(elem == null || ((elem == undefined)&&(typeof elem == "undefined"))){
3921
	if(elem == null || ((elem == undefined)&&(typeof elem == "undefined"))){
3895
		dojo.raise("No element given to dojo.dom.setAttributeNS");
3922
		dojo.raise("No element given to dojo.dom.setAttributeNS");
3896
	}
3923
	}
3897
	
3924
	
3898
	if(!((elem.setAttributeNS == undefined)&&(typeof elem.setAttributeNS == "undefined"))){ // w3c
3925
	if(!((elem.setAttributeNS == undefined)&&(typeof elem.setAttributeNS == "undefined"))){ // w3c
3899
		elem.setAttributeNS(namespaceURI, attrName, attrValue);
3926
		elem.setAttributeNS(namespaceURI, attrName, attrValue);
3900
	}else{ // IE
3927
	}else{ // IE
3901
		// get a root XML document
3928
		// get a root XML document
3902
		var ownerDoc = elem.ownerDocument;
3929
		var ownerDoc = elem.ownerDocument;
3903
		var attribute = ownerDoc.createNode(
3930
		var attribute = ownerDoc.createNode(
3904
			2, // node type
3931
			2, // node type
3905
			attrName,
3932
			attrName,
3906
			namespaceURI
3933
			namespaceURI
3907
		);
3934
		);
3908
		
3935
		
3909
		// set value
3936
		// set value
3910
		attribute.nodeValue = attrValue;
3937
		attribute.nodeValue = attrValue;
3911
		
3938
		
3912
		// attach to element
3939
		// attach to element
3913
		elem.setAttributeNode(attribute);
3940
		elem.setAttributeNode(attribute);
3914
	}
3941
	}
3915
}
3942
}
3916
 
3943
 
3917
dojo.provide("dojo.undo.browser");
3944
dojo.provide("dojo.undo.browser");
3918
 
3945
 
3919
 
3946
 
3920
try{
3947
try{
3921
	if((!djConfig["preventBackButtonFix"])&&(!dojo.hostenv.post_load_)){
3948
	if((!djConfig["preventBackButtonFix"])&&(!dojo.hostenv.post_load_)){
3922
		document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='" + (djConfig["dojoIframeHistoryUrl"] || dojo.hostenv.getBaseScriptUri()+'iframe_history.html') + "'></iframe>");
3949
		document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='" + (djConfig["dojoIframeHistoryUrl"] || dojo.hostenv.getBaseScriptUri()+'iframe_history.html') + "'></iframe>");
3923
	}
3950
	}
3924
}catch(e){/* squelch */}
3951
}catch(e){/* squelch */}
3925
 
3952
 
3926
if(dojo.render.html.opera){
3953
if(dojo.render.html.opera){
3927
	dojo.debug("Opera is not supported with dojo.undo.browser, so back/forward detection will not work.");
3954
	dojo.debug("Opera is not supported with dojo.undo.browser, so back/forward detection will not work.");
3928
}
3955
}
3929
 
3956
 
3930
dojo.undo.browser = {
3957
dojo.undo.browser = {
3931
	initialHref: (!dj_undef("window")) ? window.location.href : "",
3958
	initialHref: (!dj_undef("window")) ? window.location.href : "",
3932
	initialHash: (!dj_undef("window")) ? window.location.hash : "",
3959
	initialHash: (!dj_undef("window")) ? window.location.hash : "",
3933
 
3960
 
3934
	moveForward: false,
3961
	moveForward: false,
3935
	historyStack: [],
3962
	historyStack: [],
3936
	forwardStack: [],
3963
	forwardStack: [],
3937
	historyIframe: null,
3964
	historyIframe: null,
3938
	bookmarkAnchor: null,
3965
	bookmarkAnchor: null,
3939
	locationTimer: null,
3966
	locationTimer: null,
3940
 
3967
 
3941
	/**
3968
	/**
3942
	 * 
3969
	 * 
3943
	 */
3970
	 */
3944
	setInitialState: function(/*Object*/args){
3971
	setInitialState: function(/*Object*/args){
3945
		//summary: Sets the state object and back callback for the very first page that is loaded.
3972
		//summary: Sets the state object and back callback for the very first page that is loaded.
3946
		//description: It is recommended that you call this method as part of an event listener that is registered via
3973
		//description: It is recommended that you call this method as part of an event listener that is registered via
3947
		//dojo.addOnLoad().
3974
		//dojo.addOnLoad().
3948
		//args: Object
3975
		//args: Object
3949
		//		See the addToHistory() function for the list of valid args properties.
3976
		//		See the addToHistory() function for the list of valid args properties.
3950
		this.initialState = this._createState(this.initialHref, args, this.initialHash);
3977
		this.initialState = this._createState(this.initialHref, args, this.initialHash);
3951
	},
3978
	},
3952
 
3979
 
3953
	//FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
3980
	//FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
3954
	//FIXME: is there a slight race condition in moz using change URL with the timer check and when
3981
	//FIXME: is there a slight race condition in moz using change URL with the timer check and when
3955
	//       the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
3982
	//       the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
3956
	addToHistory: function(args){
3983
	addToHistory: function(args){
3957
		//summary: adds a state object (args) to the history list. You must set
3984
		//summary: adds a state object (args) to the history list. You must set
3958
		//djConfig.preventBackButtonFix = false to use dojo.undo.browser.
3985
		//djConfig.preventBackButtonFix = false to use dojo.undo.browser.
3959
 
3986
 
3960
		//args: Object
3987
		//args: Object
3961
		//		args can have the following properties:
3988
		//		args can have the following properties:
3962
		//		To support getting back button notifications, the object argument should implement a
3989
		//		To support getting back button notifications, the object argument should implement a
3963
		//		function called either "back", "backButton", or "handle". The string "back" will be
3990
		//		function called either "back", "backButton", or "handle". The string "back" will be
3964
		//		passed as the first and only argument to this callback.
3991
		//		passed as the first and only argument to this callback.
3965
		//		- To support getting forward button notifications, the object argument should implement a
3992
		//		- To support getting forward button notifications, the object argument should implement a
3966
		//		function called either "forward", "forwardButton", or "handle". The string "forward" will be
3993
		//		function called either "forward", "forwardButton", or "handle". The string "forward" will be
3967
		//		passed as the first and only argument to this callback.
3994
		//		passed as the first and only argument to this callback.
3968
		//		- If you want the browser location string to change, define "changeUrl" on the object. If the
3995
		//		- If you want the browser location string to change, define "changeUrl" on the object. If the
3969
		//		value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
3996
		//		value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
3970
		//		identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
3997
		//		identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
3971
		//		not evaluate to false, that value will be used as the fragment identifier. For example,
3998
		//		not evaluate to false, that value will be used as the fragment identifier. For example,
3972
		//		if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
3999
		//		if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
3973
	 	//		Full example:
4000
	 	//		Full example:
3974
		//		dojo.undo.browser.addToHistory({
4001
		//		dojo.undo.browser.addToHistory({
3975
		//		  back: function() { alert('back pressed'); },
4002
		//		  back: function() { alert('back pressed'); },
3976
		//		  forward: function() { alert('forward pressed'); },
4003
		//		  forward: function() { alert('forward pressed'); },
3977
		//		  changeUrl: true
4004
		//		  changeUrl: true
3978
		//		});
4005
		//		});
3979
		//
4006
		//
3980
		//	BROWSER NOTES:
4007
		//	BROWSER NOTES:
3981
		//  Safari 1.2: 
4008
		//  Safari 1.2: 
3982
		//	back button "works" fine, however it's not possible to actually
4009
		//	back button "works" fine, however it's not possible to actually
3983
		//	DETECT that you've moved backwards by inspecting window.location.
4010
		//	DETECT that you've moved backwards by inspecting window.location.
3984
		//	Unless there is some other means of locating.
4011
		//	Unless there is some other means of locating.
3985
		//	FIXME: perhaps we can poll on history.length?
4012
		//	FIXME: perhaps we can poll on history.length?
3986
		//	Safari 2.0.3+ (and probably 1.3.2+):
4013
		//	Safari 2.0.3+ (and probably 1.3.2+):
3987
		//	works fine, except when changeUrl is used. When changeUrl is used,
4014
		//	works fine, except when changeUrl is used. When changeUrl is used,
3988
		//	Safari jumps all the way back to whatever page was shown before
4015
		//	Safari jumps all the way back to whatever page was shown before
3989
		//	the page that uses dojo.undo.browser support.
4016
		//	the page that uses dojo.undo.browser support.
3990
		//	IE 5.5 SP2:
4017
		//	IE 5.5 SP2:
3991
		//	back button behavior is macro. It does not move back to the
4018
		//	back button behavior is macro. It does not move back to the
3992
		//	previous hash value, but to the last full page load. This suggests
4019
		//	previous hash value, but to the last full page load. This suggests
3993
		//	that the iframe is the correct way to capture the back button in
4020
		//	that the iframe is the correct way to capture the back button in
3994
		//	these cases.
4021
		//	these cases.
3995
		//	Don't test this page using local disk for MSIE. MSIE will not create 
4022
		//	Don't test this page using local disk for MSIE. MSIE will not create 
3996
		//	a history list for iframe_history.html if served from a file: URL. 
4023
		//	a history list for iframe_history.html if served from a file: URL. 
3997
		//	The XML served back from the XHR tests will also not be properly 
4024
		//	The XML served back from the XHR tests will also not be properly 
3998
		//	created if served from local disk. Serve the test pages from a web 
4025
		//	created if served from local disk. Serve the test pages from a web 
3999
		//	server to test in that browser.
4026
		//	server to test in that browser.
4000
		//	IE 6.0:
4027
		//	IE 6.0:
4001
		//	same behavior as IE 5.5 SP2
4028
		//	same behavior as IE 5.5 SP2
4002
		//	Firefox 1.0+:
4029
		//	Firefox 1.0+:
4003
		//	the back button will return us to the previous hash on the same
4030
		//	the back button will return us to the previous hash on the same
4004
		//	page, thereby not requiring an iframe hack, although we do then
4031
		//	page, thereby not requiring an iframe hack, although we do then
4005
		//	need to run a timer to detect inter-page movement.
4032
		//	need to run a timer to detect inter-page movement.
4006
 
4033
 
4007
		//If addToHistory is called, then that means we prune the
4034
		//If addToHistory is called, then that means we prune the
4008
		//forward stack -- the user went back, then wanted to
4035
		//forward stack -- the user went back, then wanted to
4009
		//start a new forward path.
4036
		//start a new forward path.
4010
		this.forwardStack = []; 
4037
		this.forwardStack = []; 
4011
 
4038
 
4012
		var hash = null;
4039
		var hash = null;
4013
		var url = null;
4040
		var url = null;
4014
		if(!this.historyIframe){
4041
		if(!this.historyIframe){
4015
			if(djConfig["useXDomain"] && !djConfig["dojoIframeHistoryUrl"]){
4042
			if(djConfig["useXDomain"] && !djConfig["dojoIframeHistoryUrl"]){
4016
				dojo.debug("dojo.undo.browser: When using cross-domain Dojo builds,"
4043
				dojo.debug("dojo.undo.browser: When using cross-domain Dojo builds,"
4017
					+ " please save iframe_history.html to your domain and set djConfig.dojoIframeHistoryUrl"
4044
					+ " please save iframe_history.html to your domain and set djConfig.dojoIframeHistoryUrl"
4018
					+ " to the path on your domain to iframe_history.html");
4045
					+ " to the path on your domain to iframe_history.html");
4019
			}
4046
			}
4020
			this.historyIframe = window.frames["djhistory"];
4047
			this.historyIframe = window.frames["djhistory"];
4021
		}
4048
		}
4022
		if(!this.bookmarkAnchor){
4049
		if(!this.bookmarkAnchor){
4023
			this.bookmarkAnchor = document.createElement("a");
4050
			this.bookmarkAnchor = document.createElement("a");
4024
			dojo.body().appendChild(this.bookmarkAnchor);
4051
			dojo.body().appendChild(this.bookmarkAnchor);
4025
			this.bookmarkAnchor.style.display = "none";
4052
			this.bookmarkAnchor.style.display = "none";
4026
		}
4053
		}
4027
		if(args["changeUrl"]){
4054
		if(args["changeUrl"]){
4028
			hash = "#"+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
4055
			hash = "#"+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
4029
			
4056
			
4030
			//If the current hash matches the new one, just replace the history object with
4057
			//If the current hash matches the new one, just replace the history object with
4031
			//this new one. It doesn't make sense to track different state objects for the same
4058
			//this new one. It doesn't make sense to track different state objects for the same
4032
			//logical URL. This matches the browser behavior of only putting in one history
4059
			//logical URL. This matches the browser behavior of only putting in one history
4033
			//item no matter how many times you click on the same #hash link, at least in Firefox
4060
			//item no matter how many times you click on the same #hash link, at least in Firefox
4034
			//and Safari, and there is no reliable way in those browsers to know if a #hash link
4061
			//and Safari, and there is no reliable way in those browsers to know if a #hash link
4035
			//has been clicked on multiple times. So making this the standard behavior in all browsers
4062
			//has been clicked on multiple times. So making this the standard behavior in all browsers
4036
			//so that dojo.undo.browser's behavior is the same in all browsers.
4063
			//so that dojo.undo.browser's behavior is the same in all browsers.
4037
			if(this.historyStack.length == 0 && this.initialState.urlHash == hash){
4064
			if(this.historyStack.length == 0 && this.initialState.urlHash == hash){
4038
				this.initialState = this._createState(url, args, hash);
4065
				this.initialState = this._createState(url, args, hash);
4039
				return;
4066
				return;
4040
			}else if(this.historyStack.length > 0 && this.historyStack[this.historyStack.length - 1].urlHash == hash){
4067
			}else if(this.historyStack.length > 0 && this.historyStack[this.historyStack.length - 1].urlHash == hash){
4041
				this.historyStack[this.historyStack.length - 1] = this._createState(url, args, hash);
4068
				this.historyStack[this.historyStack.length - 1] = this._createState(url, args, hash);
4042
				return;
4069
				return;
4043
			}
4070
			}
4044
 
4071
 
4045
			this.changingUrl = true;
4072
			this.changingUrl = true;
4046
			setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;", 1);
4073
			setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;", 1);
4047
			this.bookmarkAnchor.href = hash;
4074
			this.bookmarkAnchor.href = hash;
4048
			
4075
			
4049
			if(dojo.render.html.ie){
4076
			if(dojo.render.html.ie){
4050
				url = this._loadIframeHistory();
4077
				url = this._loadIframeHistory();
4051
 
4078
 
4052
				var oldCB = args["back"]||args["backButton"]||args["handle"];
4079
				var oldCB = args["back"]||args["backButton"]||args["handle"];
4053
 
4080
 
4054
				//The function takes handleName as a parameter, in case the
4081
				//The function takes handleName as a parameter, in case the
4055
				//callback we are overriding was "handle". In that case,
4082
				//callback we are overriding was "handle". In that case,
4056
				//we will need to pass the handle name to handle.
4083
				//we will need to pass the handle name to handle.
4057
				var tcb = function(handleName){
4084
				var tcb = function(handleName){
4058
					if(window.location.hash != ""){
4085
					if(window.location.hash != ""){
4059
						setTimeout("window.location.href = '"+hash+"';", 1);
4086
						setTimeout("window.location.href = '"+hash+"';", 1);
4060
					}
4087
					}
4061
					//Use apply to set "this" to args, and to try to avoid memory leaks.
4088
					//Use apply to set "this" to args, and to try to avoid memory leaks.
4062
					oldCB.apply(this, [handleName]);
4089
					oldCB.apply(this, [handleName]);
4063
				}
4090
				}
4064
		
4091
		
4065
				//Set interceptor function in the right place.
4092
				//Set interceptor function in the right place.
4066
				if(args["back"]){
4093
				if(args["back"]){
4067
					args.back = tcb;
4094
					args.back = tcb;
4068
				}else if(args["backButton"]){
4095
				}else if(args["backButton"]){
4069
					args.backButton = tcb;
4096
					args.backButton = tcb;
4070
				}else if(args["handle"]){
4097
				}else if(args["handle"]){
4071
					args.handle = tcb;
4098
					args.handle = tcb;
4072
				}
4099
				}
4073
		
4100
		
4074
				var oldFW = args["forward"]||args["forwardButton"]||args["handle"];
4101
				var oldFW = args["forward"]||args["forwardButton"]||args["handle"];
4075
		
4102
		
4076
				//The function takes handleName as a parameter, in case the
4103
				//The function takes handleName as a parameter, in case the
4077
				//callback we are overriding was "handle". In that case,
4104
				//callback we are overriding was "handle". In that case,
4078
				//we will need to pass the handle name to handle.
4105
				//we will need to pass the handle name to handle.
4079
				var tfw = function(handleName){
4106
				var tfw = function(handleName){
4080
					if(window.location.hash != ""){
4107
					if(window.location.hash != ""){
4081
						window.location.href = hash;
4108
						window.location.href = hash;
4082
					}
4109
					}
4083
					if(oldFW){ // we might not actually have one
4110
					if(oldFW){ // we might not actually have one
4084
						//Use apply to set "this" to args, and to try to avoid memory leaks.
4111
						//Use apply to set "this" to args, and to try to avoid memory leaks.
4085
						oldFW.apply(this, [handleName]);
4112
						oldFW.apply(this, [handleName]);
4086
					}
4113
					}
4087
				}
4114
				}
4088
 
4115
 
4089
				//Set interceptor function in the right place.
4116
				//Set interceptor function in the right place.
4090
				if(args["forward"]){
4117
				if(args["forward"]){
4091
					args.forward = tfw;
4118
					args.forward = tfw;
4092
				}else if(args["forwardButton"]){
4119
				}else if(args["forwardButton"]){
4093
					args.forwardButton = tfw;
4120
					args.forwardButton = tfw;
4094
				}else if(args["handle"]){
4121
				}else if(args["handle"]){
4095
					args.handle = tfw;
4122
					args.handle = tfw;
4096
				}
4123
				}
4097
 
4124
 
4098
			}else if(dojo.render.html.moz){
4125
			}else if(dojo.render.html.moz){
4099
				// start the timer
4126
				// start the timer
4100
				if(!this.locationTimer){
4127
				if(!this.locationTimer){
4101
					this.locationTimer = setInterval("dojo.undo.browser.checkLocation();", 200);
4128
					this.locationTimer = setInterval("dojo.undo.browser.checkLocation();", 200);
4102
				}
4129
				}
4103
			}
4130
			}
4104
		}else{
4131
		}else{
4105
			url = this._loadIframeHistory();
4132
			url = this._loadIframeHistory();
4106
		}
4133
		}
4107
 
4134
 
4108
		this.historyStack.push(this._createState(url, args, hash));
4135
		this.historyStack.push(this._createState(url, args, hash));
4109
	},
4136
	},
4110
 
4137
 
4111
	checkLocation: function(){
4138
	checkLocation: function(){
4112
		//summary: private method. Do not call this directly.
4139
		//summary: private method. Do not call this directly.
4113
		if (!this.changingUrl){
4140
		if (!this.changingUrl){
4114
			var hsl = this.historyStack.length;
4141
			var hsl = this.historyStack.length;
4115
 
4142
 
4116
			if((window.location.hash == this.initialHash||window.location.href == this.initialHref)&&(hsl == 1)){
4143
			if((window.location.hash == this.initialHash||window.location.href == this.initialHref)&&(hsl == 1)){
4117
				// FIXME: could this ever be a forward button?
4144
				// FIXME: could this ever be a forward button?
4118
				// we can't clear it because we still need to check for forwards. Ugg.
4145
				// we can't clear it because we still need to check for forwards. Ugg.
4119
				// clearInterval(this.locationTimer);
4146
				// clearInterval(this.locationTimer);
4120
				this.handleBackButton();
4147
				this.handleBackButton();
4121
				return;
4148
				return;
4122
			}
4149
			}
4123
			
4150
			
4124
			// first check to see if we could have gone forward. We always halt on
4151
			// first check to see if we could have gone forward. We always halt on
4125
			// a no-hash item.
4152
			// a no-hash item.
4126
			if(this.forwardStack.length > 0){
4153
			if(this.forwardStack.length > 0){
4127
				if(this.forwardStack[this.forwardStack.length-1].urlHash == window.location.hash){
4154
				if(this.forwardStack[this.forwardStack.length-1].urlHash == window.location.hash){
4128
					this.handleForwardButton();
4155
					this.handleForwardButton();
4129
					return;
4156
					return;
4130
				}
4157
				}
4131
			}
4158
			}
4132
	
4159
	
4133
			// ok, that didn't work, try someplace back in the history stack
4160
			// ok, that didn't work, try someplace back in the history stack
4134
			if((hsl >= 2)&&(this.historyStack[hsl-2])){
4161
			if((hsl >= 2)&&(this.historyStack[hsl-2])){
4135
				if(this.historyStack[hsl-2].urlHash==window.location.hash){
4162
				if(this.historyStack[hsl-2].urlHash==window.location.hash){
4136
					this.handleBackButton();
4163
					this.handleBackButton();
4137
					return;
4164
					return;
4138
				}
4165
				}
4139
			}
4166
			}
4140
		}
4167
		}
4141
	},
4168
	},
4142
 
4169
 
4143
	iframeLoaded: function(evt, ifrLoc){
4170
	iframeLoaded: function(evt, ifrLoc){
4144
		//summary: private method. Do not call this directly.
4171
		//summary: private method. Do not call this directly.
4145
		if(!dojo.render.html.opera){
4172
		if(!dojo.render.html.opera){
4146
			var query = this._getUrlQuery(ifrLoc.href);
4173
			var query = this._getUrlQuery(ifrLoc.href);
4147
			if(query == null){ 
4174
			if(query == null){ 
4148
				// alert("iframeLoaded");
4175
				// alert("iframeLoaded");
4149
				// we hit the end of the history, so we should go back
4176
				// we hit the end of the history, so we should go back
4150
				if(this.historyStack.length == 1){
4177
				if(this.historyStack.length == 1){
4151
					this.handleBackButton();
4178
					this.handleBackButton();
4152
				}
4179
				}
4153
				return;
4180
				return;
4154
			}
4181
			}
4155
			if(this.moveForward){
4182
			if(this.moveForward){
4156
				// we were expecting it, so it's not either a forward or backward movement
4183
				// we were expecting it, so it's not either a forward or backward movement
4157
				this.moveForward = false;
4184
				this.moveForward = false;
4158
				return;
4185
				return;
4159
			}
4186
			}
4160
	
4187
	
4161
			//Check the back stack first, since it is more likely.
4188
			//Check the back stack first, since it is more likely.
4162
			//Note that only one step back or forward is supported.
4189
			//Note that only one step back or forward is supported.
4163
			if(this.historyStack.length >= 2 && query == this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){
4190
			if(this.historyStack.length >= 2 && query == this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){
4164
				this.handleBackButton();
4191
				this.handleBackButton();
4165
			}
4192
			}
4166
			else if(this.forwardStack.length > 0 && query == this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){
4193
			else if(this.forwardStack.length > 0 && query == this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){
4167
				this.handleForwardButton();
4194
				this.handleForwardButton();
4168
			}
4195
			}
4169
		}
4196
		}
4170
	},
4197
	},
4171
 
4198
 
4172
	handleBackButton: function(){
4199
	handleBackButton: function(){
4173
		//summary: private method. Do not call this directly.
4200
		//summary: private method. Do not call this directly.
4174
 
4201
 
4175
		//The "current" page is always at the top of the history stack.
4202
		//The "current" page is always at the top of the history stack.
4176
		var current = this.historyStack.pop();
4203
		var current = this.historyStack.pop();
4177
		if(!current){ return; }
4204
		if(!current){ return; }
4178
		var last = this.historyStack[this.historyStack.length-1];
4205
		var last = this.historyStack[this.historyStack.length-1];
4179
		if(!last && this.historyStack.length == 0){
4206
		if(!last && this.historyStack.length == 0){
4180
			last = this.initialState;
4207
			last = this.initialState;
4181
		}
4208
		}
4182
		if (last){
4209
		if (last){
4183
			if(last.kwArgs["back"]){
4210
			if(last.kwArgs["back"]){
4184
				last.kwArgs["back"]();
4211
				last.kwArgs["back"]();
4185
			}else if(last.kwArgs["backButton"]){
4212
			}else if(last.kwArgs["backButton"]){
4186
				last.kwArgs["backButton"]();
4213
				last.kwArgs["backButton"]();
4187
			}else if(last.kwArgs["handle"]){
4214
			}else if(last.kwArgs["handle"]){
4188
				last.kwArgs.handle("back");
4215
				last.kwArgs.handle("back");
4189
			}
4216
			}
4190
		}
4217
		}
4191
		this.forwardStack.push(current);
4218
		this.forwardStack.push(current);
4192
	},
4219
	},
4193
 
4220
 
4194
	handleForwardButton: function(){
4221
	handleForwardButton: function(){
4195
		//summary: private method. Do not call this directly.
4222
		//summary: private method. Do not call this directly.
4196
 
4223
 
4197
		var last = this.forwardStack.pop();
4224
		var last = this.forwardStack.pop();
4198
		if(!last){ return; }
4225
		if(!last){ return; }
4199
		if(last.kwArgs["forward"]){
4226
		if(last.kwArgs["forward"]){
4200
			last.kwArgs.forward();
4227
			last.kwArgs.forward();
4201
		}else if(last.kwArgs["forwardButton"]){
4228
		}else if(last.kwArgs["forwardButton"]){
4202
			last.kwArgs.forwardButton();
4229
			last.kwArgs.forwardButton();
4203
		}else if(last.kwArgs["handle"]){
4230
		}else if(last.kwArgs["handle"]){
4204
			last.kwArgs.handle("forward");
4231
			last.kwArgs.handle("forward");
4205
		}
4232
		}
4206
		this.historyStack.push(last);
4233
		this.historyStack.push(last);
4207
	},
4234
	},
4208
 
4235
 
4209
	_createState: function(url, args, hash){
4236
	_createState: function(url, args, hash){
4210
		//summary: private method. Do not call this directly.
4237
		//summary: private method. Do not call this directly.
4211
 
4238
 
4212
		return {"url": url, "kwArgs": args, "urlHash": hash};	//Object
4239
		return {"url": url, "kwArgs": args, "urlHash": hash};	//Object
4213
	},
4240
	},
4214
 
4241
 
4215
	_getUrlQuery: function(url){
4242
	_getUrlQuery: function(url){
4216
		//summary: private method. Do not call this directly.
4243
		//summary: private method. Do not call this directly.
4217
		var segments = url.split("?");
4244
		var segments = url.split("?");
4218
		if (segments.length < 2){
4245
		if (segments.length < 2){
4219
			return null; //null
4246
			return null; //null
4220
		}
4247
		}
4221
		else{
4248
		else{
4222
			return segments[1]; //String
4249
			return segments[1]; //String
4223
		}
4250
		}
4224
	},
4251
	},
4225
	
4252
	
4226
	_loadIframeHistory: function(){
4253
	_loadIframeHistory: function(){
4227
		//summary: private method. Do not call this directly.
4254
		//summary: private method. Do not call this directly.
4228
		var url = (djConfig["dojoIframeHistoryUrl"] || dojo.hostenv.getBaseScriptUri()+'iframe_history.html')
4255
		var url = (djConfig["dojoIframeHistoryUrl"] || dojo.hostenv.getBaseScriptUri()+'iframe_history.html')
4229
			+ "?" + (new Date()).getTime();
4256
			+ "?" + (new Date()).getTime();
4230
		this.moveForward = true;
4257
		this.moveForward = true;
4231
		dojo.io.setIFrameSrc(this.historyIframe, url, false);	
4258
		dojo.io.setIFrameSrc(this.historyIframe, url, false);	
4232
		return url; //String
4259
		return url; //String
4233
	}
4260
	}
4234
}
4261
}
4235
 
4262
 
4236
dojo.provide("dojo.io.BrowserIO");
4263
dojo.provide("dojo.io.BrowserIO");
4237
 
4264
 
4238
 
4265
 
4239
 
4266
 
4240
 
4267
 
4241
 
4268
 
4242
 
4269
 
4243
 
4270
 
4244
 
4271
 
4245
if(!dj_undef("window")) {
4272
if(!dj_undef("window")) {
4246
 
4273
 
4247
dojo.io.checkChildrenForFile = function(/*DOMNode*/node){
4274
dojo.io.checkChildrenForFile = function(/*DOMNode*/node){
4248
	//summary: Checks any child nodes of node for an input type="file" element.
4275
	//summary: Checks any child nodes of node for an input type="file" element.
4249
	var hasFile = false;
4276
	var hasFile = false;
4250
	var inputs = node.getElementsByTagName("input");
4277
	var inputs = node.getElementsByTagName("input");
4251
	dojo.lang.forEach(inputs, function(input){
4278
	dojo.lang.forEach(inputs, function(input){
4252
		if(hasFile){ return; }
4279
		if(hasFile){ return; }
4253
		if(input.getAttribute("type")=="file"){
4280
		if(input.getAttribute("type")=="file"){
4254
			hasFile = true;
4281
			hasFile = true;
4255
		}
4282
		}
4256
	});
4283
	});
4257
	return hasFile; //boolean
4284
	return hasFile; //boolean
4258
}
4285
}
4259
 
4286
 
4260
dojo.io.formHasFile = function(/*DOMNode*/formNode){
4287
dojo.io.formHasFile = function(/*DOMNode*/formNode){
4261
	//summary: Just calls dojo.io.checkChildrenForFile().
4288
	//summary: Just calls dojo.io.checkChildrenForFile().
4262
	return dojo.io.checkChildrenForFile(formNode); //boolean
4289
	return dojo.io.checkChildrenForFile(formNode); //boolean
4263
}
4290
}
4264
 
4291
 
4265
dojo.io.updateNode = function(/*DOMNode*/node, /*String or Object*/urlOrArgs){
4292
dojo.io.updateNode = function(/*DOMNode*/node, /*String or Object*/urlOrArgs){
4266
	//summary: Updates a DOMnode with the result of a dojo.io.bind() call.
4293
	//summary: Updates a DOMnode with the result of a dojo.io.bind() call.
4267
	//node: DOMNode
4294
	//node: DOMNode
4268
	//urlOrArgs: String or Object
4295
	//urlOrArgs: String or Object
4269
	//		Either a String that has an URL, or an object containing dojo.io.bind()
4296
	//		Either a String that has an URL, or an object containing dojo.io.bind()
4270
	//		arguments.
4297
	//		arguments.
4271
	node = dojo.byId(node);
4298
	node = dojo.byId(node);
4272
	var args = urlOrArgs;
4299
	var args = urlOrArgs;
4273
	if(dojo.lang.isString(urlOrArgs)){
4300
	if(dojo.lang.isString(urlOrArgs)){
4274
		args = { url: urlOrArgs };
4301
		args = { url: urlOrArgs };
4275
	}
4302
	}
4276
	args.mimetype = "text/html";
4303
	args.mimetype = "text/html";
4277
	args.load = function(t, d, e){
4304
	args.load = function(t, d, e){
4278
		while(node.firstChild){
4305
		while(node.firstChild){
4279
			dojo.dom.destroyNode(node.firstChild);
4306
			dojo.dom.destroyNode(node.firstChild);
4280
		}
4307
		}
4281
		node.innerHTML = d;
4308
		node.innerHTML = d;
4282
	};
4309
	};
4283
	dojo.io.bind(args);
4310
	dojo.io.bind(args);
4284
}
4311
}
4285
 
4312
 
4286
dojo.io.formFilter = function(/*DOMNode*/node) {
4313
dojo.io.formFilter = function(/*DOMNode*/node) {
4287
	//summary: Returns true if the node is an input element that is enabled, has
4314
	//summary: Returns true if the node is an input element that is enabled, has
4288
	//a name, and whose type is one of the following values: ["file", "submit", "image", "reset", "button"]
4315
	//a name, and whose type is one of the following values: ["file", "submit", "image", "reset", "button"]
4289
	var type = (node.type||"").toLowerCase();
4316
	var type = (node.type||"").toLowerCase();
4290
	return !node.disabled && node.name
4317
	return !node.disabled && node.name
4291
		&& !dojo.lang.inArray(["file", "submit", "image", "reset", "button"], type); //boolean
4318
		&& !dojo.lang.inArray(["file", "submit", "image", "reset", "button"], type); //boolean
4292
}
4319
}
4293
 
4320
 
4294
// TODO: Move to htmlUtils
4321
// TODO: Move to htmlUtils
4295
dojo.io.encodeForm = function(/*DOMNode*/formNode, /*String?*/encoding, /*Function?*/formFilter){
4322
dojo.io.encodeForm = function(/*DOMNode*/formNode, /*String?*/encoding, /*Function?*/formFilter){
4296
	//summary: Converts the names and values of form elements into an URL-encoded
4323
	//summary: Converts the names and values of form elements into an URL-encoded
4297
	//string (name=value&name=value...).
4324
	//string (name=value&name=value...).
4298
	//formNode: DOMNode
4325
	//formNode: DOMNode
4299
	//encoding: String?
4326
	//encoding: String?
4300
	//		The encoding to use for the values. Specify a string that starts with
4327
	//		The encoding to use for the values. Specify a string that starts with
4301
	//		"utf" (for instance, "utf8"), to use encodeURIComponent() as the encoding
4328
	//		"utf" (for instance, "utf8"), to use encodeURIComponent() as the encoding
4302
	//		function. Otherwise, dojo.string.encodeAscii will be used.
4329
	//		function. Otherwise, dojo.string.encodeAscii will be used.
4303
	//formFilter: Function?
4330
	//formFilter: Function?
4304
	//	A function used to filter out form elements. The element node will be passed
4331
	//	A function used to filter out form elements. The element node will be passed
4305
	//	to the formFilter function, and a boolean result is expected (true indicating
4332
	//	to the formFilter function, and a boolean result is expected (true indicating
4306
	//	indicating that the element should have its name/value included in the output).
4333
	//	indicating that the element should have its name/value included in the output).
4307
	//	If no formFilter is specified, then dojo.io.formFilter() will be used.
4334
	//	If no formFilter is specified, then dojo.io.formFilter() will be used.
4308
	if((!formNode)||(!formNode.tagName)||(!formNode.tagName.toLowerCase() == "form")){
4335
	if((!formNode)||(!formNode.tagName)||(!formNode.tagName.toLowerCase() == "form")){
4309
		dojo.raise("Attempted to encode a non-form element.");
4336
		dojo.raise("Attempted to encode a non-form element.");
4310
	}
4337
	}
4311
	if(!formFilter) { formFilter = dojo.io.formFilter; }
4338
	if(!formFilter) { formFilter = dojo.io.formFilter; }
4312
	var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
4339
	var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
4313
	var values = [];
4340
	var values = [];
4314
 
4341
 
4315
	for(var i = 0; i < formNode.elements.length; i++){
4342
	for(var i = 0; i < formNode.elements.length; i++){
4316
		var elm = formNode.elements[i];
4343
		var elm = formNode.elements[i];
4317
		if(!elm || elm.tagName.toLowerCase() == "fieldset" || !formFilter(elm)) { continue; }
4344
		if(!elm || elm.tagName.toLowerCase() == "fieldset" || !formFilter(elm)) { continue; }
4318
		var name = enc(elm.name);
4345
		var name = enc(elm.name);
4319
		var type = elm.type.toLowerCase();
4346
		var type = elm.type.toLowerCase();
4320
 
4347
 
4321
		if(type == "select-multiple"){
4348
		if(type == "select-multiple"){
4322
			for(var j = 0; j < elm.options.length; j++){
4349
			for(var j = 0; j < elm.options.length; j++){
4323
				if(elm.options[j].selected) {
4350
				if(elm.options[j].selected) {
4324
					values.push(name + "=" + enc(elm.options[j].value));
4351
					values.push(name + "=" + enc(elm.options[j].value));
4325
				}
4352
				}
4326
			}
4353
			}
4327
		}else if(dojo.lang.inArray(["radio", "checkbox"], type)){
4354
		}else if(dojo.lang.inArray(["radio", "checkbox"], type)){
4328
			if(elm.checked){
4355
			if(elm.checked){
4329
				values.push(name + "=" + enc(elm.value));
4356
				values.push(name + "=" + enc(elm.value));
4330
			}
4357
			}
4331
		}else{
4358
		}else{
4332
			values.push(name + "=" + enc(elm.value));
4359
			values.push(name + "=" + enc(elm.value));
4333
		}
4360
		}
4334
	}
4361
	}
4335
 
4362
 
4336
	// now collect input type="image", which doesn't show up in the elements array
4363
	// now collect input type="image", which doesn't show up in the elements array
4337
	var inputs = formNode.getElementsByTagName("input");
4364
	var inputs = formNode.getElementsByTagName("input");
4338
	for(var i = 0; i < inputs.length; i++) {
4365
	for(var i = 0; i < inputs.length; i++) {
4339
		var input = inputs[i];
4366
		var input = inputs[i];
4340
		if(input.type.toLowerCase() == "image" && input.form == formNode
4367
		if(input.type.toLowerCase() == "image" && input.form == formNode
4341
			&& formFilter(input)) {
4368
			&& formFilter(input)) {
4342
			var name = enc(input.name);
4369
			var name = enc(input.name);
4343
			values.push(name + "=" + enc(input.value));
4370
			values.push(name + "=" + enc(input.value));
4344
			values.push(name + ".x=0");
4371
			values.push(name + ".x=0");
4345
			values.push(name + ".y=0");
4372
			values.push(name + ".y=0");
4346
		}
4373
		}
4347
	}
4374
	}
4348
	return values.join("&") + "&"; //String
4375
	return values.join("&") + "&"; //String
4349
}
4376
}
4350
 
4377
 
4351
dojo.io.FormBind = function(/*DOMNode or Object*/args) {
4378
dojo.io.FormBind = function(/*DOMNode or Object*/args) {
4352
	//summary: constructor for a dojo.io.FormBind object. See the Dojo Book for
4379
	//summary: constructor for a dojo.io.FormBind object. See the Dojo Book for
4353
	//some information on usage: http://manual.dojotoolkit.org/WikiHome/DojoDotBook/Book23
4380
	//some information on usage: http://manual.dojotoolkit.org/WikiHome/DojoDotBook/Book23
4354
	//args: DOMNode or Object
4381
	//args: DOMNode or Object
4355
	//		args can either be the DOMNode for a form element, or an object containing
4382
	//		args can either be the DOMNode for a form element, or an object containing
4356
	//		dojo.io.bind() arguments, one of which should be formNode with the value of
4383
	//		dojo.io.bind() arguments, one of which should be formNode with the value of
4357
	//		a form element DOMNode.
4384
	//		a form element DOMNode.
4358
	this.bindArgs = {};
4385
	this.bindArgs = {};
4359
 
4386
 
4360
	if(args && args.formNode) {
4387
	if(args && args.formNode) {
4361
		this.init(args);
4388
		this.init(args);
4362
	} else if(args) {
4389
	} else if(args) {
4363
		this.init({formNode: args});
4390
		this.init({formNode: args});
4364
	}
4391
	}
4365
}
4392
}
4366
dojo.lang.extend(dojo.io.FormBind, {
4393
dojo.lang.extend(dojo.io.FormBind, {
4367
	form: null,
4394
	form: null,
4368
 
4395
 
4369
	bindArgs: null,
4396
	bindArgs: null,
4370
 
4397
 
4371
	clickedButton: null,
4398
	clickedButton: null,
4372
 
4399
 
4373
	init: function(/*DOMNode or Object*/args) {
4400
	init: function(/*DOMNode or Object*/args) {
4374
		//summary: Internal function called by the dojo.io.FormBind() constructor
4401
		//summary: Internal function called by the dojo.io.FormBind() constructor
4375
		//do not call this method directly.
4402
		//do not call this method directly.
4376
		var form = dojo.byId(args.formNode);
4403
		var form = dojo.byId(args.formNode);
4377
 
4404
 
4378
		if(!form || !form.tagName || form.tagName.toLowerCase() != "form") {
4405
		if(!form || !form.tagName || form.tagName.toLowerCase() != "form") {
4379
			throw new Error("FormBind: Couldn't apply, invalid form");
4406
			throw new Error("FormBind: Couldn't apply, invalid form");
4380
		} else if(this.form == form) {
4407
		} else if(this.form == form) {
4381
			return;
4408
			return;
4382
		} else if(this.form) {
4409
		} else if(this.form) {
4383
			throw new Error("FormBind: Already applied to a form");
4410
			throw new Error("FormBind: Already applied to a form");
4384
		}
4411
		}
4385
 
4412
 
4386
		dojo.lang.mixin(this.bindArgs, args);
4413
		dojo.lang.mixin(this.bindArgs, args);
4387
		this.form = form;
4414
		this.form = form;
4388
 
4415
 
4389
		this.connect(form, "onsubmit", "submit");
4416
		this.connect(form, "onsubmit", "submit");
4390
 
4417
 
4391
		for(var i = 0; i < form.elements.length; i++) {
4418
		for(var i = 0; i < form.elements.length; i++) {
4392
			var node = form.elements[i];
4419
			var node = form.elements[i];
4393
			if(node && node.type && dojo.lang.inArray(["submit", "button"], node.type.toLowerCase())) {
4420
			if(node && node.type && dojo.lang.inArray(["submit", "button"], node.type.toLowerCase())) {
4394
				this.connect(node, "onclick", "click");
4421
				this.connect(node, "onclick", "click");
4395
			}
4422
			}
4396
		}
4423
		}
4397
 
4424
 
4398
		var inputs = form.getElementsByTagName("input");
4425
		var inputs = form.getElementsByTagName("input");
4399
		for(var i = 0; i < inputs.length; i++) {
4426
		for(var i = 0; i < inputs.length; i++) {
4400
			var input = inputs[i];
4427
			var input = inputs[i];
4401
			if(input.type.toLowerCase() == "image" && input.form == form) {
4428
			if(input.type.toLowerCase() == "image" && input.form == form) {
4402
				this.connect(input, "onclick", "click");
4429
				this.connect(input, "onclick", "click");
4403
			}
4430
			}
4404
		}
4431
		}
4405
	},
4432
	},
4406
 
4433
 
4407
	onSubmit: function(/*DOMNode*/form) {
4434
	onSubmit: function(/*DOMNode*/form) {
4408
		//summary: Function used to verify that the form is OK to submit.
4435
		//summary: Function used to verify that the form is OK to submit.
4409
		//Override this function if you want specific form validation done.
4436
		//Override this function if you want specific form validation done.
4410
		return true; //boolean
4437
		return true; //boolean
4411
	},
4438
	},
4412
 
4439
 
4413
	submit: function(/*Event*/e) {
4440
	submit: function(/*Event*/e) {
4414
		//summary: internal function that is connected as a listener to the
4441
		//summary: internal function that is connected as a listener to the
4415
		//form's onsubmit event.
4442
		//form's onsubmit event.
4416
		e.preventDefault();
4443
		e.preventDefault();
4417
		if(this.onSubmit(this.form)) {
4444
		if(this.onSubmit(this.form)) {
4418
			dojo.io.bind(dojo.lang.mixin(this.bindArgs, {
4445
			dojo.io.bind(dojo.lang.mixin(this.bindArgs, {
4419
				formFilter: dojo.lang.hitch(this, "formFilter")
4446
				formFilter: dojo.lang.hitch(this, "formFilter")
4420
			}));
4447
			}));
4421
		}
4448
		}
4422
	},
4449
	},
4423
 
4450
 
4424
	click: function(/*Event*/e) {
4451
	click: function(/*Event*/e) {
4425
		//summary: internal method that is connected as a listener to the
4452
		//summary: internal method that is connected as a listener to the
4426
		//form's elements whose click event can submit a form.
4453
		//form's elements whose click event can submit a form.
4427
		var node = e.currentTarget;
4454
		var node = e.currentTarget;
4428
		if(node.disabled) { return; }
4455
		if(node.disabled) { return; }
4429
		this.clickedButton = node;
4456
		this.clickedButton = node;
4430
	},
4457
	},
4431
 
4458
 
4432
	formFilter: function(/*DOMNode*/node) {
4459
	formFilter: function(/*DOMNode*/node) {
4433
		//summary: internal function used to know which form element values to include
4460
		//summary: internal function used to know which form element values to include
4434
		//		in the dojo.io.bind() request.
4461
		//		in the dojo.io.bind() request.
4435
		var type = (node.type||"").toLowerCase();
4462
		var type = (node.type||"").toLowerCase();
4436
		var accept = false;
4463
		var accept = false;
4437
		if(node.disabled || !node.name) {
4464
		if(node.disabled || !node.name) {
4438
			accept = false;
4465
			accept = false;
4439
		} else if(dojo.lang.inArray(["submit", "button", "image"], type)) {
4466
		} else if(dojo.lang.inArray(["submit", "button", "image"], type)) {
4440
			if(!this.clickedButton) { this.clickedButton = node; }
4467
			if(!this.clickedButton) { this.clickedButton = node; }
4441
			accept = node == this.clickedButton;
4468
			accept = node == this.clickedButton;
4442
		} else {
4469
		} else {
4443
			accept = !dojo.lang.inArray(["file", "submit", "reset", "button"], type);
4470
			accept = !dojo.lang.inArray(["file", "submit", "reset", "button"], type);
4444
		}
4471
		}
4445
		return accept; //boolean
4472
		return accept; //boolean
4446
	},
4473
	},
4447
 
4474
 
4448
	// in case you don't have dojo.event.* pulled in
4475
	// in case you don't have dojo.event.* pulled in
4449
	connect: function(/*Object*/srcObj, /*Function*/srcFcn, /*Function*/targetFcn) {
4476
	connect: function(/*Object*/srcObj, /*Function*/srcFcn, /*Function*/targetFcn) {
4450
		//summary: internal function used to connect event listeners to form elements
4477
		//summary: internal function used to connect event listeners to form elements
4451
		//that trigger events. Used in case dojo.event is not loaded.
4478
		//that trigger events. Used in case dojo.event is not loaded.
4452
		if(dojo.evalObjPath("dojo.event.connect")) {
4479
		if(dojo.evalObjPath("dojo.event.connect")) {
4453
			dojo.event.connect(srcObj, srcFcn, this, targetFcn);
4480
			dojo.event.connect(srcObj, srcFcn, this, targetFcn);
4454
		} else {
4481
		} else {
4455
			var fcn = dojo.lang.hitch(this, targetFcn);
4482
			var fcn = dojo.lang.hitch(this, targetFcn);
4456
			srcObj[srcFcn] = function(e) {
4483
			srcObj[srcFcn] = function(e) {
4457
				if(!e) { e = window.event; }
4484
				if(!e) { e = window.event; }
4458
				if(!e.currentTarget) { e.currentTarget = e.srcElement; }
4485
				if(!e.currentTarget) { e.currentTarget = e.srcElement; }
4459
				if(!e.preventDefault) { e.preventDefault = function() { window.event.returnValue = false; } }
4486
				if(!e.preventDefault) { e.preventDefault = function() { window.event.returnValue = false; } }
4460
				fcn(e);
4487
				fcn(e);
4461
			}
4488
			}
4462
		}
4489
		}
4463
	}
4490
	}
4464
});
4491
});
4465
 
4492
 
4466
dojo.io.XMLHTTPTransport = new function(){
4493
dojo.io.XMLHTTPTransport = new function(){
4467
	//summary: The object that implements the dojo.io.bind transport for XMLHttpRequest.
4494
	//summary: The object that implements the dojo.io.bind transport for XMLHttpRequest.
4468
	var _this = this;
4495
	var _this = this;
4469
 
4496
 
4470
	var _cache = {}; // FIXME: make this public? do we even need to?
4497
	var _cache = {}; // FIXME: make this public? do we even need to?
4471
	this.useCache = false; // if this is true, we'll cache unless kwArgs.useCache = false
4498
	this.useCache = false; // if this is true, we'll cache unless kwArgs.useCache = false
4472
	this.preventCache = false; // if this is true, we'll always force GET requests to cache
4499
	this.preventCache = false; // if this is true, we'll always force GET requests to cache
4473
 
4500
 
4474
	// FIXME: Should this even be a function? or do we just hard code it in the next 2 functions?
4501
	// FIXME: Should this even be a function? or do we just hard code it in the next 2 functions?
4475
	function getCacheKey(url, query, method) {
4502
	function getCacheKey(url, query, method) {
4476
		return url + "|" + query + "|" + method.toLowerCase();
4503
		return url + "|" + query + "|" + method.toLowerCase();
4477
	}
4504
	}
4478
 
4505
 
4479
	function addToCache(url, query, method, http) {
4506
	function addToCache(url, query, method, http) {
4480
		_cache[getCacheKey(url, query, method)] = http;
4507
		_cache[getCacheKey(url, query, method)] = http;
4481
	}
4508
	}
4482
 
4509
 
4483
	function getFromCache(url, query, method) {
4510
	function getFromCache(url, query, method) {
4484
		return _cache[getCacheKey(url, query, method)];
4511
		return _cache[getCacheKey(url, query, method)];
4485
	}
4512
	}
4486
 
4513
 
4487
	this.clearCache = function() {
4514
	this.clearCache = function() {
4488
		_cache = {};
4515
		_cache = {};
4489
	}
4516
	}
4490
 
4517
 
4491
	// moved successful load stuff here
4518
	// moved successful load stuff here
4492
	function doLoad(kwArgs, http, url, query, useCache) {
4519
	function doLoad(kwArgs, http, url, query, useCache) {
4493
		if(	((http.status>=200)&&(http.status<300))|| 	// allow any 2XX response code
4520
		if(	((http.status>=200)&&(http.status<300))|| 	// allow any 2XX response code
4494
			(http.status==304)|| 						// get it out of the cache
4521
			(http.status==304)|| 						// get it out of the cache
-
 
4522
			(http.status==1223)|| 						// Internet Explorer mangled the status code
4495
			(location.protocol=="file:" && (http.status==0 || http.status==undefined))||
4523
			(location.protocol=="file:" && (http.status==0 || http.status==undefined))||
4496
			(location.protocol=="chrome:" && (http.status==0 || http.status==undefined))
4524
			(location.protocol=="chrome:" && (http.status==0 || http.status==undefined))
4497
		){
4525
		){
4498
			var ret;
4526
			var ret;
4499
			if(kwArgs.method.toLowerCase() == "head"){
4527
			if(kwArgs.method.toLowerCase() == "head"){
4500
				var headers = http.getAllResponseHeaders();
4528
				var headers = http.getAllResponseHeaders();
4501
				ret = {};
4529
				ret = {};
4502
				ret.toString = function(){ return headers; }
4530
				ret.toString = function(){ return headers; }
4503
				var values = headers.split(/[\r\n]+/g);
4531
				var values = headers.split(/[\r\n]+/g);
4504
				for(var i = 0; i < values.length; i++) {
4532
				for(var i = 0; i < values.length; i++) {
4505
					var pair = values[i].match(/^([^:]+)\s*:\s*(.+)$/i);
4533
					var pair = values[i].match(/^([^:]+)\s*:\s*(.+)$/i);
4506
					if(pair) {
4534
					if(pair) {
4507
						ret[pair[1]] = pair[2];
4535
						ret[pair[1]] = pair[2];
4508
					}
4536
					}
4509
				}
4537
				}
4510
			}else if(kwArgs.mimetype == "text/javascript"){
4538
			}else if(kwArgs.mimetype == "text/javascript"){
4511
				try{
4539
				try{
4512
					ret = dj_eval(http.responseText);
4540
					ret = dj_eval(http.responseText);
4513
				}catch(e){
4541
				}catch(e){
4514
					dojo.debug(e);
4542
					dojo.debug(e);
4515
					dojo.debug(http.responseText);
4543
					dojo.debug(http.responseText);
4516
					ret = null;
4544
					ret = null;
4517
				}
4545
				}
4518
			}else if(kwArgs.mimetype == "text/json" || kwArgs.mimetype == "application/json"){
4546
			}else if(kwArgs.mimetype.substr(0, 9) == "text/json" || kwArgs.mimetype.substr(0, 16) == "application/json"){
4519
				try{
4547
				try{
4520
					ret = dj_eval("("+http.responseText+")");
4548
					ret = dj_eval("("+kwArgs.jsonFilter(http.responseText)+")");
4521
				}catch(e){
4549
				}catch(e){
4522
					dojo.debug(e);
4550
					dojo.debug(e);
4523
					dojo.debug(http.responseText);
4551
					dojo.debug(http.responseText);
4524
					ret = false;
4552
					ret = false;
4525
				}
4553
				}
4526
			}else if((kwArgs.mimetype == "application/xml")||
4554
			}else if((kwArgs.mimetype == "application/xml")||
4527
						(kwArgs.mimetype == "text/xml")){
4555
						(kwArgs.mimetype == "text/xml")){
4528
				ret = http.responseXML;
4556
				ret = http.responseXML;
4529
				if(!ret || typeof ret == "string" || !http.getResponseHeader("Content-Type")) {
4557
				if(!ret || typeof ret == "string" || !http.getResponseHeader("Content-Type")) {
4530
					ret = dojo.dom.createDocumentFromText(http.responseText);
4558
					ret = dojo.dom.createDocumentFromText(http.responseText);
4531
				}
4559
				}
4532
			}else{
4560
			}else{
4533
				ret = http.responseText;
4561
				ret = http.responseText;
4534
			}
4562
			}
4535
 
4563
 
4536
			if(useCache){ // only cache successful responses
4564
			if(useCache){ // only cache successful responses
4537
				addToCache(url, query, kwArgs.method, http);
4565
				addToCache(url, query, kwArgs.method, http);
4538
			}
4566
			}
4539
			kwArgs[(typeof kwArgs.load == "function") ? "load" : "handle"]("load", ret, http, kwArgs);
4567
			kwArgs[(typeof kwArgs.load == "function") ? "load" : "handle"]("load", ret, http, kwArgs);
4540
		}else{
4568
		}else{
4541
			var errObj = new dojo.io.Error("XMLHttpTransport Error: "+http.status+" "+http.statusText);
4569
			var errObj = new dojo.io.Error("XMLHttpTransport Error: "+http.status+" "+http.statusText);
4542
			kwArgs[(typeof kwArgs.error == "function") ? "error" : "handle"]("error", errObj, http, kwArgs);
4570
			kwArgs[(typeof kwArgs.error == "function") ? "error" : "handle"]("error", errObj, http, kwArgs);
4543
		}
4571
		}
4544
	}
4572
	}
4545
 
4573
 
4546
	// set headers (note: Content-Type will get overriden if kwArgs.contentType is set)
4574
	// set headers (note: Content-Type will get overriden if kwArgs.contentType is set)
4547
	function setHeaders(http, kwArgs){
4575
	function setHeaders(http, kwArgs){
4548
		if(kwArgs["headers"]) {
4576
		if(kwArgs["headers"]) {
4549
			for(var header in kwArgs["headers"]) {
4577
			for(var header in kwArgs["headers"]) {
4550
				if(header.toLowerCase() == "content-type" && !kwArgs["contentType"]) {
4578
				if(header.toLowerCase() == "content-type" && !kwArgs["contentType"]) {
4551
					kwArgs["contentType"] = kwArgs["headers"][header];
4579
					kwArgs["contentType"] = kwArgs["headers"][header];
4552
				} else {
4580
				} else {
4553
					http.setRequestHeader(header, kwArgs["headers"][header]);
4581
					http.setRequestHeader(header, kwArgs["headers"][header]);
4554
				}
4582
				}
4555
			}
4583
			}
4556
		}
4584
		}
4557
	}
4585
	}
4558
 
4586
 
4559
	this.inFlight = [];
4587
	this.inFlight = [];
4560
	this.inFlightTimer = null;
4588
	this.inFlightTimer = null;
4561
 
4589
 
4562
	this.startWatchingInFlight = function(){
4590
	this.startWatchingInFlight = function(){
4563
		//summary: internal method used to trigger a timer to watch all inflight
4591
		//summary: internal method used to trigger a timer to watch all inflight
4564
		//XMLHttpRequests.
4592
		//XMLHttpRequests.
4565
		if(!this.inFlightTimer){
4593
		if(!this.inFlightTimer){
4566
			// setInterval broken in mozilla x86_64 in some circumstances, see
4594
			// setInterval broken in mozilla x86_64 in some circumstances, see
4567
			// https://bugzilla.mozilla.org/show_bug.cgi?id=344439
4595
			// https://bugzilla.mozilla.org/show_bug.cgi?id=344439
4568
			// using setTimeout instead
4596
			// using setTimeout instead
4569
			this.inFlightTimer = setTimeout("dojo.io.XMLHTTPTransport.watchInFlight();", 10);
4597
			this.inFlightTimer = setTimeout("dojo.io.XMLHTTPTransport.watchInFlight();", 10);
4570
		}
4598
		}
4571
	}
4599
	}
4572
 
4600
 
4573
	this.watchInFlight = function(){
4601
	this.watchInFlight = function(){
4574
		//summary: internal method that checks each inflight XMLHttpRequest to see
4602
		//summary: internal method that checks each inflight XMLHttpRequest to see
4575
		//if it has completed or if the timeout situation applies.
4603
		//if it has completed or if the timeout situation applies.
4576
		var now = null;
4604
		var now = null;
4577
		// make sure sync calls stay thread safe, if this callback is called during a sync call
4605
		// make sure sync calls stay thread safe, if this callback is called during a sync call
4578
		// and this results in another sync call before the first sync call ends the browser hangs
4606
		// and this results in another sync call before the first sync call ends the browser hangs
4579
		if(!dojo.hostenv._blockAsync && !_this._blockAsync){
4607
		if(!dojo.hostenv._blockAsync && !_this._blockAsync){
4580
			for(var x=this.inFlight.length-1; x>=0; x--){
4608
			for(var x=this.inFlight.length-1; x>=0; x--){
4581
				try{
4609
				try{
4582
					var tif = this.inFlight[x];
4610
					var tif = this.inFlight[x];
4583
					if(!tif || tif.http._aborted || !tif.http.readyState){
4611
					if(!tif || tif.http._aborted || !tif.http.readyState){
4584
						this.inFlight.splice(x, 1); continue; 
4612
						this.inFlight.splice(x, 1); continue; 
4585
					}
4613
					}
4586
					if(4==tif.http.readyState){
4614
					if(4==tif.http.readyState){
4587
						// remove it so we can clean refs
4615
						// remove it so we can clean refs
4588
						this.inFlight.splice(x, 1);
4616
						this.inFlight.splice(x, 1);
4589
						doLoad(tif.req, tif.http, tif.url, tif.query, tif.useCache);
4617
						doLoad(tif.req, tif.http, tif.url, tif.query, tif.useCache);
4590
					}else if (tif.startTime){
4618
					}else if (tif.startTime){
4591
						//See if this is a timeout case.
4619
						//See if this is a timeout case.
4592
						if(!now){
4620
						if(!now){
4593
							now = (new Date()).getTime();
4621
							now = (new Date()).getTime();
4594
						}
4622
						}
4595
						if(tif.startTime + (tif.req.timeoutSeconds * 1000) < now){
4623
						if(tif.startTime + (tif.req.timeoutSeconds * 1000) < now){
4596
							//Stop the request.
4624
							//Stop the request.
4597
							if(typeof tif.http.abort == "function"){
4625
							if(typeof tif.http.abort == "function"){
4598
								tif.http.abort();
4626
								tif.http.abort();
4599
							}
4627
							}
4600
		
4628
		
4601
							// remove it so we can clean refs
4629
							// remove it so we can clean refs
4602
							this.inFlight.splice(x, 1);
4630
							this.inFlight.splice(x, 1);
4603
							tif.req[(typeof tif.req.timeout == "function") ? "timeout" : "handle"]("timeout", null, tif.http, tif.req);
4631
							tif.req[(typeof tif.req.timeout == "function") ? "timeout" : "handle"]("timeout", null, tif.http, tif.req);
4604
						}
4632
						}
4605
					}
4633
					}
4606
				}catch(e){
4634
				}catch(e){
4607
					try{
4635
					try{
4608
						var errObj = new dojo.io.Error("XMLHttpTransport.watchInFlight Error: " + e);
4636
						var errObj = new dojo.io.Error("XMLHttpTransport.watchInFlight Error: " + e);
4609
						tif.req[(typeof tif.req.error == "function") ? "error" : "handle"]("error", errObj, tif.http, tif.req);
4637
						tif.req[(typeof tif.req.error == "function") ? "error" : "handle"]("error", errObj, tif.http, tif.req);
4610
					}catch(e2){
4638
					}catch(e2){
4611
						dojo.debug("XMLHttpTransport error callback failed: " + e2);
4639
						dojo.debug("XMLHttpTransport error callback failed: " + e2);
4612
					}
4640
					}
4613
				}
4641
				}
4614
			}
4642
			}
4615
		}
4643
		}
4616
 
4644
 
4617
		clearTimeout(this.inFlightTimer);
4645
		clearTimeout(this.inFlightTimer);
4618
		if(this.inFlight.length == 0){
4646
		if(this.inFlight.length == 0){
4619
			this.inFlightTimer = null;
4647
			this.inFlightTimer = null;
4620
			return;
4648
			return;
4621
		}
4649
		}
4622
		this.inFlightTimer = setTimeout("dojo.io.XMLHTTPTransport.watchInFlight();", 10);
4650
		this.inFlightTimer = setTimeout("dojo.io.XMLHTTPTransport.watchInFlight();", 10);
4623
	}
4651
	}
4624
 
4652
 
4625
	var hasXmlHttp = dojo.hostenv.getXmlhttpObject() ? true : false;
4653
	var hasXmlHttp = dojo.hostenv.getXmlhttpObject() ? true : false;
4626
	this.canHandle = function(/*dojo.io.Request*/kwArgs){
4654
	this.canHandle = function(/*dojo.io.Request*/kwArgs){
4627
		//summary: Tells dojo.io.bind() if this is a good transport to
4655
		//summary: Tells dojo.io.bind() if this is a good transport to
4628
		//use for the particular type of request. This type of transport cannot
4656
		//use for the particular type of request. This type of transport cannot
4629
		//handle forms that have an input type="file" element.
4657
		//handle forms that have an input type="file" element.
4630
 
4658
 
4631
		// FIXME: we need to determine when form values need to be
4659
		// FIXME: we need to determine when form values need to be
4632
		// multi-part mime encoded and avoid using this transport for those
4660
		// multi-part mime encoded and avoid using this transport for those
4633
		// requests.
4661
		// requests.
-
 
4662
		var mlc = kwArgs["mimetype"].toLowerCase()||"";
4634
		return hasXmlHttp
4663
		return hasXmlHttp
-
 
4664
			&& (
-
 
4665
				(
-
 
4666
					dojo.lang.inArray([
-
 
4667
						"text/plain", "text/html", "application/xml", 
-
 
4668
						"text/xml", "text/javascript"
-
 
4669
						], mlc
-
 
4670
					)
-
 
4671
				) || (
4635
			&& dojo.lang.inArray(["text/plain", "text/html", "application/xml", "text/xml", "text/javascript", "text/json", "application/json"], (kwArgs["mimetype"].toLowerCase()||""))
4672
					mlc.substr(0, 9) == "text/json" || mlc.substr(0, 16) == "application/json"
-
 
4673
				)
-
 
4674
			)
4636
			&& !( kwArgs["formNode"] && dojo.io.formHasFile(kwArgs["formNode"]) ); //boolean
4675
			&& !( kwArgs["formNode"] && dojo.io.formHasFile(kwArgs["formNode"]) ); //boolean
4637
	}
4676
	}
4638
 
4677
 
4639
	this.multipartBoundary = "45309FFF-BD65-4d50-99C9-36986896A96F";	// unique guid as a boundary value for multipart posts
4678
	this.multipartBoundary = "45309FFF-BD65-4d50-99C9-36986896A96F";	// unique guid as a boundary value for multipart posts
4640
 
4679
 
4641
	this.bind = function(/*dojo.io.Request*/kwArgs){
4680
	this.bind = function(/*dojo.io.Request*/kwArgs){
4642
		//summary: function that sends the request to the server.
4681
		//summary: function that sends the request to the server.
4643
 
4682
 
4644
		//This function will attach an abort() function to the kwArgs dojo.io.Request object,
4683
		//This function will attach an abort() function to the kwArgs dojo.io.Request object,
4645
		//so if you need to abort the request, you can call that method on the request object.
4684
		//so if you need to abort the request, you can call that method on the request object.
4646
		//The following are acceptable properties in kwArgs (in addition to the
4685
		//The following are acceptable properties in kwArgs (in addition to the
4647
		//normal dojo.io.Request object properties).
4686
		//normal dojo.io.Request object properties).
4648
		//url: String: URL the server URL to use for the request.
4687
		//url: String: URL the server URL to use for the request.
4649
		//method: String: the HTTP method to use (GET, POST, etc...).
4688
		//method: String: the HTTP method to use (GET, POST, etc...).
4650
		//mimetype: Specifies what format the result data should be given to the load/handle callback. Valid values are:
4689
		//mimetype: Specifies what format the result data should be given to the load/handle callback. Valid values are:
4651
		//		text/javascript, text/json, application/json, application/xml, text/xml. Any other mimetype will give back a text
4690
		//		text/javascript, text/json, application/json, application/xml, text/xml. Any other mimetype will give back a text
4652
		//		string.
4691
		//		string.
4653
		//transport: String: specify "XMLHTTPTransport" to force the use of this XMLHttpRequest transport.
4692
		//transport: String: specify "XMLHTTPTransport" to force the use of this XMLHttpRequest transport.
4654
		//headers: Object: The object property names and values will be sent as HTTP request header
4693
		//headers: Object: The object property names and values will be sent as HTTP request header
4655
		//		names and values.
4694
		//		names and values.
4656
		//sendTransport: boolean: If true, then dojo.transport=xmlhttp will be added to the request.
4695
		//sendTransport: boolean: If true, then dojo.transport=xmlhttp will be added to the request.
4657
		//encoding: String: The type of encoding to use when dealing with the content kwArgs property.
4696
		//encoding: String: The type of encoding to use when dealing with the content kwArgs property.
4658
		//content: Object: The content object is converted into a name=value&name=value string, by
4697
		//content: Object: The content object is converted into a name=value&name=value string, by
4659
		//		using dojo.io.argsFromMap(). The encoding kwArgs property is passed to dojo.io.argsFromMap()
4698
		//		using dojo.io.argsFromMap(). The encoding kwArgs property is passed to dojo.io.argsFromMap()
4660
		//		for use in encoding the names and values. The resulting string is added to the request.
4699
		//		for use in encoding the names and values. The resulting string is added to the request.
4661
		//formNode: DOMNode: a form element node. This should not normally be used. Use new dojo.io.FormBind() instead.
4700
		//formNode: DOMNode: a form element node. This should not normally be used. Use new dojo.io.FormBind() instead.
4662
		//		If formNode is used, then the names and values of the form elements will be converted
4701
		//		If formNode is used, then the names and values of the form elements will be converted
4663
		//		to a name=value&name=value string and added to the request. The encoding kwArgs property is used
4702
		//		to a name=value&name=value string and added to the request. The encoding kwArgs property is used
4664
		//		to encode the names and values.
4703
		//		to encode the names and values.
4665
		//postContent: String: Raw name=value&name=value string to be included as part of the request.
4704
		//postContent: String: Raw name=value&name=value string to be included as part of the request.
4666
		//back or backButton: Function: A function to be called if the back button is pressed. If this kwArgs property
4705
		//back or backButton: Function: A function to be called if the back button is pressed. If this kwArgs property
4667
		//		is used, then back button support via dojo.undo.browser will be used. See notes for dojo.undo.browser on usage.
4706
		//		is used, then back button support via dojo.undo.browser will be used. See notes for dojo.undo.browser on usage.
4668
		//		You need to set djConfig.preventBackButtonFix = false to enable back button support.
4707
		//		You need to set djConfig.preventBackButtonFix = false to enable back button support.
4669
		//changeUrl: boolean or String: Used as part of back button support. See notes for dojo.undo.browser on usage.
4708
		//changeUrl: boolean or String: Used as part of back button support. See notes for dojo.undo.browser on usage.
4670
		//user: String: The user name. Used in conjuction with password. Passed to XMLHttpRequest.open().
4709
		//user: String: The user name. Used in conjuction with password. Passed to XMLHttpRequest.open().
4671
		//password: String: The user's password. Used in conjuction with user. Passed to XMLHttpRequest.open().
4710
		//password: String: The user's password. Used in conjuction with user. Passed to XMLHttpRequest.open().
4672
		//file: Object or Array of Objects: an object simulating a file to be uploaded. file objects should have the following properties:
4711
		//file: Object or Array of Objects: an object simulating a file to be uploaded. file objects should have the following properties:
4673
		//		name or fileName: the name of the file
4712
		//		name or fileName: the name of the file
4674
		//		contentType: the MIME content type for the file.
4713
		//		contentType: the MIME content type for the file.
4675
		//		content: the actual content of the file.
4714
		//		content: the actual content of the file.
4676
		//multipart: boolean: indicates whether this should be a multipart mime request. If kwArgs.file exists, then this
4715
		//multipart: boolean: indicates whether this should be a multipart mime request. If kwArgs.file exists, then this
4677
		//		property is set to true automatically.
4716
		//		property is set to true automatically.
4678
		//sync: boolean: if true, then a synchronous XMLHttpRequest call is done,
4717
		//sync: boolean: if true, then a synchronous XMLHttpRequest call is done,
4679
		//		if false (the default), then an asynchronous call is used.
4718
		//		if false (the default), then an asynchronous call is used.
4680
		//preventCache: boolean: If true, then a cache busting parameter is added to the request URL.
4719
		//preventCache: boolean: If true, then a cache busting parameter is added to the request URL.
4681
		//		default value is false.
4720
		//		default value is false.
4682
		//useCache: boolean: If true, then XMLHttpTransport will keep an internal cache of the server
4721
		//useCache: boolean: If true, then XMLHttpTransport will keep an internal cache of the server
4683
		//		response and use that response if a similar request is done again.
4722
		//		response and use that response if a similar request is done again.
4684
		//		A similar request is one that has the same URL, query string and HTTP method value.
4723
		//		A similar request is one that has the same URL, query string and HTTP method value.
4685
		//		default is false.
4724
		//		default is false.
4686
		if(!kwArgs["url"]){
4725
		if(!kwArgs["url"]){
4687
			// are we performing a history action?
4726
			// are we performing a history action?
4688
			if( !kwArgs["formNode"]
4727
			if( !kwArgs["formNode"]
4689
				&& (kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"] || kwArgs["watchForURL"])
4728
				&& (kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"] || kwArgs["watchForURL"])
4690
				&& (!djConfig.preventBackButtonFix)) {
4729
				&& (!djConfig.preventBackButtonFix)) {
4691
        dojo.deprecated("Using dojo.io.XMLHTTPTransport.bind() to add to browser history without doing an IO request",
4730
        dojo.deprecated("Using dojo.io.XMLHTTPTransport.bind() to add to browser history without doing an IO request",
4692
        				"Use dojo.undo.browser.addToHistory() instead.", "0.4");
4731
        				"Use dojo.undo.browser.addToHistory() instead.", "0.4");
4693
				dojo.undo.browser.addToHistory(kwArgs);
4732
				dojo.undo.browser.addToHistory(kwArgs);
4694
				return true;
4733
				return true;
4695
			}
4734
			}
4696
		}
4735
		}
4697
 
4736
 
4698
		// build this first for cache purposes
4737
		// build this first for cache purposes
4699
		var url = kwArgs.url;
4738
		var url = kwArgs.url;
4700
		var query = "";
4739
		var query = "";
4701
		if(kwArgs["formNode"]){
4740
		if(kwArgs["formNode"]){
4702
			var ta = kwArgs.formNode.getAttribute("action");
4741
			var ta = kwArgs.formNode.getAttribute("action");
4703
			if((ta)&&(!kwArgs["url"])){ url = ta; }
4742
			if((ta)&&(!kwArgs["url"])){ url = ta; }
4704
			var tp = kwArgs.formNode.getAttribute("method");
4743
			var tp = kwArgs.formNode.getAttribute("method");
4705
			if((tp)&&(!kwArgs["method"])){ kwArgs.method = tp; }
4744
			if((tp)&&(!kwArgs["method"])){ kwArgs.method = tp; }
4706
			query += dojo.io.encodeForm(kwArgs.formNode, kwArgs.encoding, kwArgs["formFilter"]);
4745
			query += dojo.io.encodeForm(kwArgs.formNode, kwArgs.encoding, kwArgs["formFilter"]);
4707
		}
4746
		}
4708
 
4747
 
4709
		if(url.indexOf("#") > -1) {
4748
		if(url.indexOf("#") > -1) {
4710
			dojo.debug("Warning: dojo.io.bind: stripping hash values from url:", url);
4749
			dojo.debug("Warning: dojo.io.bind: stripping hash values from url:", url);
4711
			url = url.split("#")[0];
4750
			url = url.split("#")[0];
4712
		}
4751
		}
4713
 
4752
 
4714
		if(kwArgs["file"]){
4753
		if(kwArgs["file"]){
4715
			// force post for file transfer
4754
			// force post for file transfer
4716
			kwArgs.method = "post";
4755
			kwArgs.method = "post";
4717
		}
4756
		}
4718
 
4757
 
4719
		if(!kwArgs["method"]){
4758
		if(!kwArgs["method"]){
4720
			kwArgs.method = "get";
4759
			kwArgs.method = "get";
4721
		}
4760
		}
4722
 
4761
 
4723
		// guess the multipart value
4762
		// guess the multipart value
4724
		if(kwArgs.method.toLowerCase() == "get"){
4763
		if(kwArgs.method.toLowerCase() == "get"){
4725
			// GET cannot use multipart
4764
			// GET cannot use multipart
4726
			kwArgs.multipart = false;
4765
			kwArgs.multipart = false;
4727
		}else{
4766
		}else{
4728
			if(kwArgs["file"]){
4767
			if(kwArgs["file"]){
4729
				// enforce multipart when sending files
4768
				// enforce multipart when sending files
4730
				kwArgs.multipart = true;
4769
				kwArgs.multipart = true;
4731
			}else if(!kwArgs["multipart"]){
4770
			}else if(!kwArgs["multipart"]){
4732
				// default 
4771
				// default 
4733
				kwArgs.multipart = false;
4772
				kwArgs.multipart = false;
4734
			}
4773
			}
4735
		}
4774
		}
4736
 
4775
 
4737
		if(kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"]){
4776
		if(kwArgs["backButton"] || kwArgs["back"] || kwArgs["changeUrl"]){
4738
			dojo.undo.browser.addToHistory(kwArgs);
4777
			dojo.undo.browser.addToHistory(kwArgs);
4739
		}
4778
		}
4740
 
4779
 
4741
		var content = kwArgs["content"] || {};
4780
		var content = kwArgs["content"] || {};
4742
 
4781
 
4743
		if(kwArgs.sendTransport) {
4782
		if(kwArgs.sendTransport) {
4744
			content["dojo.transport"] = "xmlhttp";
4783
			content["dojo.transport"] = "xmlhttp";
4745
		}
4784
		}
4746
 
4785
 
4747
		do { // break-block
4786
		do { // break-block
4748
			if(kwArgs.postContent){
4787
			if(kwArgs.postContent){
4749
				query = kwArgs.postContent;
4788
				query = kwArgs.postContent;
4750
				break;
4789
				break;
4751
			}
4790
			}
4752
 
4791
 
4753
			if(content) {
4792
			if(content) {
4754
				query += dojo.io.argsFromMap(content, kwArgs.encoding);
4793
				query += dojo.io.argsFromMap(content, kwArgs.encoding);
4755
			}
4794
			}
4756
			
4795
			
4757
			if(kwArgs.method.toLowerCase() == "get" || !kwArgs.multipart){
4796
			if(kwArgs.method.toLowerCase() == "get" || !kwArgs.multipart){
4758
				break;
4797
				break;
4759
			}
4798
			}
4760
 
4799
 
4761
			var	t = [];
4800
			var	t = [];
4762
			if(query.length){
4801
			if(query.length){
4763
				var q = query.split("&");
4802
				var q = query.split("&");
4764
				for(var i = 0; i < q.length; ++i){
4803
				for(var i = 0; i < q.length; ++i){
4765
					if(q[i].length){
4804
					if(q[i].length){
4766
						var p = q[i].split("=");
4805
						var p = q[i].split("=");
4767
						t.push(	"--" + this.multipartBoundary,
4806
						t.push(	"--" + this.multipartBoundary,
4768
								"Content-Disposition: form-data; name=\"" + p[0] + "\"", 
4807
								"Content-Disposition: form-data; name=\"" + p[0] + "\"", 
4769
								"",
4808
								"",
4770
								p[1]);
4809
								p[1]);
4771
					}
4810
					}
4772
				}
4811
				}
4773
			}
4812
			}
4774
 
4813
 
4775
			if(kwArgs.file){
4814
			if(kwArgs.file){
4776
				if(dojo.lang.isArray(kwArgs.file)){
4815
				if(dojo.lang.isArray(kwArgs.file)){
4777
					for(var i = 0; i < kwArgs.file.length; ++i){
4816
					for(var i = 0; i < kwArgs.file.length; ++i){
4778
						var o = kwArgs.file[i];
4817
						var o = kwArgs.file[i];
4779
						t.push(	"--" + this.multipartBoundary,
4818
						t.push(	"--" + this.multipartBoundary,
4780
								"Content-Disposition: form-data; name=\"" + o.name + "\"; filename=\"" + ("fileName" in o ? o.fileName : o.name) + "\"",
4819
								"Content-Disposition: form-data; name=\"" + o.name + "\"; filename=\"" + ("fileName" in o ? o.fileName : o.name) + "\"",
4781
								"Content-Type: " + ("contentType" in o ? o.contentType : "application/octet-stream"),
4820
								"Content-Type: " + ("contentType" in o ? o.contentType : "application/octet-stream"),
4782
								"",
4821
								"",
4783
								o.content);
4822
								o.content);
4784
					}
4823
					}
4785
				}else{
4824
				}else{
4786
					var o = kwArgs.file;
4825
					var o = kwArgs.file;
4787
					t.push(	"--" + this.multipartBoundary,
4826
					t.push(	"--" + this.multipartBoundary,
4788
							"Content-Disposition: form-data; name=\"" + o.name + "\"; filename=\"" + ("fileName" in o ? o.fileName : o.name) + "\"",
4827
							"Content-Disposition: form-data; name=\"" + o.name + "\"; filename=\"" + ("fileName" in o ? o.fileName : o.name) + "\"",
4789
							"Content-Type: " + ("contentType" in o ? o.contentType : "application/octet-stream"),
4828
							"Content-Type: " + ("contentType" in o ? o.contentType : "application/octet-stream"),
4790
							"",
4829
							"",
4791
							o.content);
4830
							o.content);
4792
				}
4831
				}
4793
			}
4832
			}
4794
 
4833
 
4795
			if(t.length){
4834
			if(t.length){
4796
				t.push("--"+this.multipartBoundary+"--", "");
4835
				t.push("--"+this.multipartBoundary+"--", "");
4797
				query = t.join("\r\n");
4836
				query = t.join("\r\n");
4798
			}
4837
			}
4799
		}while(false);
4838
		}while(false);
4800
 
4839
 
4801
		// kwArgs.Connection = "close";
4840
		// kwArgs.Connection = "close";
4802
 
4841
 
4803
		var async = kwArgs["sync"] ? false : true;
4842
		var async = kwArgs["sync"] ? false : true;
4804
 
4843
 
4805
		var preventCache = kwArgs["preventCache"] ||
4844
		var preventCache = kwArgs["preventCache"] ||
4806
			(this.preventCache == true && kwArgs["preventCache"] != false);
4845
			(this.preventCache == true && kwArgs["preventCache"] != false);
4807
		var useCache = kwArgs["useCache"] == true ||
4846
		var useCache = kwArgs["useCache"] == true ||
4808
			(this.useCache == true && kwArgs["useCache"] != false );
4847
			(this.useCache == true && kwArgs["useCache"] != false );
4809
 
4848
 
4810
		// preventCache is browser-level (add query string junk), useCache
4849
		// preventCache is browser-level (add query string junk), useCache
4811
		// is for the local cache. If we say preventCache, then don't attempt
4850
		// is for the local cache. If we say preventCache, then don't attempt
4812
		// to look in the cache, but if useCache is true, we still want to cache
4851
		// to look in the cache, but if useCache is true, we still want to cache
4813
		// the response
4852
		// the response
4814
		if(!preventCache && useCache){
4853
		if(!preventCache && useCache){
4815
			var cachedHttp = getFromCache(url, query, kwArgs.method);
4854
			var cachedHttp = getFromCache(url, query, kwArgs.method);
4816
			if(cachedHttp){
4855
			if(cachedHttp){
4817
				doLoad(kwArgs, cachedHttp, url, query, false);
4856
				doLoad(kwArgs, cachedHttp, url, query, false);
4818
				return;
4857
				return;
4819
			}
4858
			}
4820
		}
4859
		}
4821
 
4860
 
4822
		// much of this is from getText, but reproduced here because we need
4861
		// much of this is from getText, but reproduced here because we need
4823
		// more flexibility
4862
		// more flexibility
4824
		var http = dojo.hostenv.getXmlhttpObject(kwArgs);	
4863
		var http = dojo.hostenv.getXmlhttpObject(kwArgs);	
4825
		var received = false;
4864
		var received = false;
4826
 
4865
 
4827
		// build a handler function that calls back to the handler obj
4866
		// build a handler function that calls back to the handler obj
4828
		if(async){
4867
		if(async){
4829
			var startTime = 
4868
			var startTime = 
4830
			// FIXME: setting up this callback handler leaks on IE!!!
4869
			// FIXME: setting up this callback handler leaks on IE!!!
4831
			this.inFlight.push({
4870
			this.inFlight.push({
4832
				"req":		kwArgs,
4871
				"req":		kwArgs,
4833
				"http":		http,
4872
				"http":		http,
4834
				"url":	 	url,
4873
				"url":	 	url,
4835
				"query":	query,
4874
				"query":	query,
4836
				"useCache":	useCache,
4875
				"useCache":	useCache,
4837
				"startTime": kwArgs.timeoutSeconds ? (new Date()).getTime() : 0
4876
				"startTime": kwArgs.timeoutSeconds ? (new Date()).getTime() : 0
4838
			});
4877
			});
4839
			this.startWatchingInFlight();
4878
			this.startWatchingInFlight();
4840
		}else{
4879
		}else{
4841
			// block async callbacks until sync is in, needed in khtml, others?
4880
			// block async callbacks until sync is in, needed in khtml, others?
4842
			_this._blockAsync = true;
4881
			_this._blockAsync = true;
4843
		}
4882
		}
4844
 
4883
 
4845
		if(kwArgs.method.toLowerCase() == "post"){
4884
		if(kwArgs.method.toLowerCase() == "post"){
4846
			// FIXME: need to hack in more flexible Content-Type setting here!
4885
			// FIXME: need to hack in more flexible Content-Type setting here!
4847
			if (!kwArgs.user) {
4886
			if (!kwArgs.user) {
4848
				http.open("POST", url, async);
4887
				http.open("POST", url, async);
4849
			}else{
4888
			}else{
4850
        http.open("POST", url, async, kwArgs.user, kwArgs.password);
4889
        http.open("POST", url, async, kwArgs.user, kwArgs.password);
4851
			}
4890
			}
4852
			setHeaders(http, kwArgs);
4891
			setHeaders(http, kwArgs);
4853
			http.setRequestHeader("Content-Type", kwArgs.multipart ? ("multipart/form-data; boundary=" + this.multipartBoundary) : 
4892
			http.setRequestHeader("Content-Type", kwArgs.multipart ? ("multipart/form-data; boundary=" + this.multipartBoundary) : 
4854
				(kwArgs.contentType || "application/x-www-form-urlencoded"));
4893
				(kwArgs.contentType || "application/x-www-form-urlencoded"));
4855
			try{
4894
			try{
4856
				http.send(query);
4895
				http.send(query);
4857
			}catch(e){
4896
			}catch(e){
4858
				if(typeof http.abort == "function"){
4897
				if(typeof http.abort == "function"){
4859
					http.abort();
4898
					http.abort();
4860
				}
4899
				}
4861
				doLoad(kwArgs, {status: 404}, url, query, useCache);
4900
				doLoad(kwArgs, {status: 404}, url, query, useCache);
4862
			}
4901
			}
4863
		}else{
4902
		}else{
4864
			var tmpUrl = url;
4903
			var tmpUrl = url;
4865
			if(query != "") {
4904
			if(query != "") {
4866
				tmpUrl += (tmpUrl.indexOf("?") > -1 ? "&" : "?") + query;
4905
				tmpUrl += (tmpUrl.indexOf("?") > -1 ? "&" : "?") + query;
4867
			}
4906
			}
4868
			if(preventCache) {
4907
			if(preventCache) {
4869
				tmpUrl += (dojo.string.endsWithAny(tmpUrl, "?", "&")
4908
				tmpUrl += (dojo.string.endsWithAny(tmpUrl, "?", "&")
4870
					? "" : (tmpUrl.indexOf("?") > -1 ? "&" : "?")) + "dojo.preventCache=" + new Date().valueOf();
4909
					? "" : (tmpUrl.indexOf("?") > -1 ? "&" : "?")) + "dojo.preventCache=" + new Date().valueOf();
4871
			}
4910
			}
4872
			if (!kwArgs.user) {
4911
			if (!kwArgs.user) {
4873
				http.open(kwArgs.method.toUpperCase(), tmpUrl, async);
4912
				http.open(kwArgs.method.toUpperCase(), tmpUrl, async);
4874
			}else{
4913
			}else{
4875
				http.open(kwArgs.method.toUpperCase(), tmpUrl, async, kwArgs.user, kwArgs.password);
4914
				http.open(kwArgs.method.toUpperCase(), tmpUrl, async, kwArgs.user, kwArgs.password);
4876
			}
4915
			}
4877
			setHeaders(http, kwArgs);
4916
			setHeaders(http, kwArgs);
4878
			try {
4917
			try {
4879
				http.send(null);
4918
				http.send(null);
4880
			}catch(e)	{
4919
			}catch(e)	{
4881
				if(typeof http.abort == "function"){
4920
				if(typeof http.abort == "function"){
4882
					http.abort();
4921
					http.abort();
4883
				}
4922
				}
4884
				doLoad(kwArgs, {status: 404}, url, query, useCache);
4923
				doLoad(kwArgs, {status: 404}, url, query, useCache);
4885
			}
4924
			}
4886
		}
4925
		}
4887
 
4926
 
4888
		if( !async ) {
4927
		if( !async ) {
4889
			doLoad(kwArgs, http, url, query, useCache);
4928
			doLoad(kwArgs, http, url, query, useCache);
4890
			_this._blockAsync = false;
4929
			_this._blockAsync = false;
4891
		}
4930
		}
4892
 
4931
 
4893
		kwArgs.abort = function(){
4932
		kwArgs.abort = function(){
4894
			try{// khtml doesent reset readyState on abort, need this workaround
4933
			try{// khtml doesent reset readyState on abort, need this workaround
4895
				http._aborted = true; 
4934
				http._aborted = true; 
4896
			}catch(e){/*squelsh*/}
4935
			}catch(e){/*squelsh*/}
4897
			return http.abort();
4936
			return http.abort();
4898
		}
4937
		}
4899
 
4938
 
4900
		return;
4939
		return;
4901
	}
4940
	}
4902
	dojo.io.transports.addTransport("XMLHTTPTransport");
4941
	dojo.io.transports.addTransport("XMLHTTPTransport");
4903
}
4942
}
4904
 
4943
 
4905
}
4944
}
4906
 
4945
 
4907
dojo.provide("dojo.io.cookie");
4946
dojo.provide("dojo.io.cookie");
4908
 
4947
 
4909
dojo.io.cookie.setCookie = function(/*String*/name, /*String*/value, 
4948
dojo.io.cookie.setCookie = function(/*String*/name, /*String*/value, 
4910
									/*Number?*/days, /*String?*/path, 
4949
									/*Number?*/days, /*String?*/path, 
4911
									/*String?*/domain, /*boolean?*/secure){
4950
									/*String?*/domain, /*boolean?*/secure){
4912
	//summary: sets a cookie.
4951
	//summary: sets a cookie.
4913
	var expires = -1;
4952
	var expires = -1;
4914
	if((typeof days == "number")&&(days >= 0)){
4953
	if((typeof days == "number")&&(days >= 0)){
4915
		var d = new Date();
4954
		var d = new Date();
4916
		d.setTime(d.getTime()+(days*24*60*60*1000));
4955
		d.setTime(d.getTime()+(days*24*60*60*1000));
4917
		expires = d.toGMTString();
4956
		expires = d.toGMTString();
4918
	}
4957
	}
4919
	value = escape(value);
4958
	value = escape(value);
4920
	document.cookie = name + "=" + value + ";"
4959
	document.cookie = name + "=" + value + ";"
4921
		+ (expires != -1 ? " expires=" + expires + ";" : "")
4960
		+ (expires != -1 ? " expires=" + expires + ";" : "")
4922
		+ (path ? "path=" + path : "")
4961
		+ (path ? "path=" + path : "")
4923
		+ (domain ? "; domain=" + domain : "")
4962
		+ (domain ? "; domain=" + domain : "")
4924
		+ (secure ? "; secure" : "");
4963
		+ (secure ? "; secure" : "");
4925
}
4964
}
4926
 
4965
 
4927
dojo.io.cookie.set = dojo.io.cookie.setCookie;
4966
dojo.io.cookie.set = dojo.io.cookie.setCookie;
4928
 
4967
 
4929
dojo.io.cookie.getCookie = function(/*String*/name){
4968
dojo.io.cookie.getCookie = function(/*String*/name){
4930
	//summary: Gets a cookie with the given name.
4969
	//summary: Gets a cookie with the given name.
4931
 
4970
 
4932
	// FIXME: Which cookie should we return?
4971
	// FIXME: Which cookie should we return?
4933
	//        If there are cookies set for different sub domains in the current
4972
	//        If there are cookies set for different sub domains in the current
4934
	//        scope there could be more than one cookie with the same name.
4973
	//        scope there could be more than one cookie with the same name.
4935
	//        I think taking the last one in the list takes the one from the
4974
	//        I think taking the last one in the list takes the one from the
4936
	//        deepest subdomain, which is what we're doing here.
4975
	//        deepest subdomain, which is what we're doing here.
4937
	var idx = document.cookie.lastIndexOf(name+'=');
4976
	var idx = document.cookie.lastIndexOf(name+'=');
4938
	if(idx == -1) { return null; }
4977
	if(idx == -1) { return null; }
4939
	var value = document.cookie.substring(idx+name.length+1);
4978
	var value = document.cookie.substring(idx+name.length+1);
4940
	var end = value.indexOf(';');
4979
	var end = value.indexOf(';');
4941
	if(end == -1) { end = value.length; }
4980
	if(end == -1) { end = value.length; }
4942
	value = value.substring(0, end);
4981
	value = value.substring(0, end);
4943
	value = unescape(value);
4982
	value = unescape(value);
4944
	return value; //String
4983
	return value; //String
4945
}
4984
}
4946
 
4985
 
4947
dojo.io.cookie.get = dojo.io.cookie.getCookie;
4986
dojo.io.cookie.get = dojo.io.cookie.getCookie;
4948
 
4987
 
4949
dojo.io.cookie.deleteCookie = function(/*String*/name){
4988
dojo.io.cookie.deleteCookie = function(/*String*/name){
4950
	//summary: Deletes a cookie with the given name.
4989
	//summary: Deletes a cookie with the given name.
4951
	dojo.io.cookie.setCookie(name, "-", 0);
4990
	dojo.io.cookie.setCookie(name, "-", 0);
4952
}
4991
}
4953
 
4992
 
4954
dojo.io.cookie.setObjectCookie = function(	/*String*/name, /*Object*/obj, 
4993
dojo.io.cookie.setObjectCookie = function(	/*String*/name, /*Object*/obj, 
4955
											/*Number?*/days, /*String?*/path, 
4994
											/*Number?*/days, /*String?*/path, 
4956
											/*String?*/domain, /*boolean?*/secure, 
4995
											/*String?*/domain, /*boolean?*/secure, 
4957
											/*boolean?*/clearCurrent){
4996
											/*boolean?*/clearCurrent){
4958
	//summary: Takes an object, serializes it to a cookie value, and either
4997
	//summary: Takes an object, serializes it to a cookie value, and either
4959
	//sets a cookie with the serialized value.
4998
	//sets a cookie with the serialized value.
4960
	//description: If clearCurrent is true, then any current cookie value
4999
	//description: If clearCurrent is true, then any current cookie value
4961
	//for this object will be replaced with the the new serialized object value.
5000
	//for this object will be replaced with the the new serialized object value.
4962
	//If clearCurrent is false, then the existing cookie value will be modified
5001
	//If clearCurrent is false, then the existing cookie value will be modified
4963
	//with any changes from the new object value.
5002
	//with any changes from the new object value.
4964
	//Objects must be simple name/value pairs where the value is either a string
5003
	//Objects must be simple name/value pairs where the value is either a string
4965
	//or a number. Any other value will be ignored.
5004
	//or a number. Any other value will be ignored.
4966
	if(arguments.length == 5){ // for backwards compat
5005
	if(arguments.length == 5){ // for backwards compat
4967
		clearCurrent = domain;
5006
		clearCurrent = domain;
4968
		domain = null;
5007
		domain = null;
4969
		secure = null;
5008
		secure = null;
4970
	}
5009
	}
4971
	var pairs = [], cookie, value = "";
5010
	var pairs = [], cookie, value = "";
4972
	if(!clearCurrent){
5011
	if(!clearCurrent){
4973
		cookie = dojo.io.cookie.getObjectCookie(name);
5012
		cookie = dojo.io.cookie.getObjectCookie(name);
4974
	}
5013
	}
4975
	if(days >= 0){
5014
	if(days >= 0){
4976
		if(!cookie){ cookie = {}; }
5015
		if(!cookie){ cookie = {}; }
4977
		for(var prop in obj){
5016
		for(var prop in obj){
4978
			if(obj[prop] == null){
5017
			if(obj[prop] == null){
4979
				delete cookie[prop];
5018
				delete cookie[prop];
4980
			}else if((typeof obj[prop] == "string")||(typeof obj[prop] == "number")){
5019
			}else if((typeof obj[prop] == "string")||(typeof obj[prop] == "number")){
4981
				cookie[prop] = obj[prop];
5020
				cookie[prop] = obj[prop];
4982
			}
5021
			}
4983
		}
5022
		}
4984
		prop = null;
5023
		prop = null;
4985
		for(var prop in cookie){
5024
		for(var prop in cookie){
4986
			pairs.push(escape(prop) + "=" + escape(cookie[prop]));
5025
			pairs.push(escape(prop) + "=" + escape(cookie[prop]));
4987
		}
5026
		}
4988
		value = pairs.join("&");
5027
		value = pairs.join("&");
4989
	}
5028
	}
4990
	dojo.io.cookie.setCookie(name, value, days, path, domain, secure);
5029
	dojo.io.cookie.setCookie(name, value, days, path, domain, secure);
4991
}
5030
}
4992
 
5031
 
4993
dojo.io.cookie.getObjectCookie = function(/*String*/name){
5032
dojo.io.cookie.getObjectCookie = function(/*String*/name){
4994
	//summary: Gets an object value for the given cookie name. The complement of
5033
	//summary: Gets an object value for the given cookie name. The complement of
4995
	//dojo.io.cookie.setObjectCookie().
5034
	//dojo.io.cookie.setObjectCookie().
4996
	var values = null, cookie = dojo.io.cookie.getCookie(name);
5035
	var values = null, cookie = dojo.io.cookie.getCookie(name);
4997
	if(cookie){
5036
	if(cookie){
4998
		values = {};
5037
		values = {};
4999
		var pairs = cookie.split("&");
5038
		var pairs = cookie.split("&");
5000
		for(var i = 0; i < pairs.length; i++){
5039
		for(var i = 0; i < pairs.length; i++){
5001
			var pair = pairs[i].split("=");
5040
			var pair = pairs[i].split("=");
5002
			var value = pair[1];
5041
			var value = pair[1];
5003
			if( isNaN(value) ){ value = unescape(pair[1]); }
5042
			if( isNaN(value) ){ value = unescape(pair[1]); }
5004
			values[ unescape(pair[0]) ] = value;
5043
			values[ unescape(pair[0]) ] = value;
5005
		}
5044
		}
5006
	}
5045
	}
5007
	return values;
5046
	return values;
5008
}
5047
}
5009
 
5048
 
5010
dojo.io.cookie.isSupported = function(){
5049
dojo.io.cookie.isSupported = function(){
5011
	//summary: Tests the browser to see if cookies are enabled.
5050
	//summary: Tests the browser to see if cookies are enabled.
5012
	if(typeof navigator.cookieEnabled != "boolean"){
5051
	if(typeof navigator.cookieEnabled != "boolean"){
5013
		dojo.io.cookie.setCookie("__TestingYourBrowserForCookieSupport__",
5052
		dojo.io.cookie.setCookie("__TestingYourBrowserForCookieSupport__",
5014
			"CookiesAllowed", 90, null);
5053
			"CookiesAllowed", 90, null);
5015
		var cookieVal = dojo.io.cookie.getCookie("__TestingYourBrowserForCookieSupport__");
5054
		var cookieVal = dojo.io.cookie.getCookie("__TestingYourBrowserForCookieSupport__");
5016
		navigator.cookieEnabled = (cookieVal == "CookiesAllowed");
5055
		navigator.cookieEnabled = (cookieVal == "CookiesAllowed");
5017
		if(navigator.cookieEnabled){
5056
		if(navigator.cookieEnabled){
5018
			// FIXME: should we leave this around?
5057
			// FIXME: should we leave this around?
5019
			this.deleteCookie("__TestingYourBrowserForCookieSupport__");
5058
			this.deleteCookie("__TestingYourBrowserForCookieSupport__");
5020
		}
5059
		}
5021
	}
5060
	}
5022
	return navigator.cookieEnabled; //boolean
5061
	return navigator.cookieEnabled; //boolean
5023
}
5062
}
5024
 
5063
 
5025
// need to leave this in for backwards-compat from 0.1 for when it gets pulled in by dojo.io.*
5064
// need to leave this in for backwards-compat from 0.1 for when it gets pulled in by dojo.io.*
5026
if(!dojo.io.cookies){ dojo.io.cookies = dojo.io.cookie; }
5065
if(!dojo.io.cookies){ dojo.io.cookies = dojo.io.cookie; }
5027
 
5066
 
5028
dojo.kwCompoundRequire({
5067
dojo.kwCompoundRequire({
5029
	common: ["dojo.io.common"],
5068
	common: ["dojo.io.common"],
5030
	rhino: ["dojo.io.RhinoIO"],
5069
	rhino: ["dojo.io.RhinoIO"],
5031
	browser: ["dojo.io.BrowserIO", "dojo.io.cookie"],
5070
	browser: ["dojo.io.BrowserIO", "dojo.io.cookie"],
5032
	dashboard: ["dojo.io.BrowserIO", "dojo.io.cookie"]
5071
	dashboard: ["dojo.io.BrowserIO", "dojo.io.cookie"]
5033
});
5072
});
5034
dojo.provide("dojo.io.*");
5073
dojo.provide("dojo.io.*");
5035
 
5074
 
5036
dojo.provide("dojo.event.common");
5075
dojo.provide("dojo.event.common");
5037
 
5076
 
5038
 
5077
 
5039
 
5078
 
5040
 
5079
 
5041
 
5080
 
5042
// TODO: connection filter functions
5081
// TODO: connection filter functions
5043
//			these are functions that accept a method invocation (like around
5082
//			these are functions that accept a method invocation (like around
5044
//			advice) and return a boolean based on it. That value determines
5083
//			advice) and return a boolean based on it. That value determines
5045
//			whether or not the connection proceeds. It could "feel" like around
5084
//			whether or not the connection proceeds. It could "feel" like around
5046
//			advice for those who know what it is (calling proceed() or not),
5085
//			advice for those who know what it is (calling proceed() or not),
5047
//			but I think presenting it as a "filter" and/or calling it with the
5086
//			but I think presenting it as a "filter" and/or calling it with the
5048
//			function args and not the MethodInvocation might make it more
5087
//			function args and not the MethodInvocation might make it more
5049
//			palletable to "normal" users than around-advice currently is
5088
//			palletable to "normal" users than around-advice currently is
5050
// TODO: execution scope mangling
5089
// TODO: execution scope mangling
5051
//			YUI's event facility by default executes listeners in the context
5090
//			YUI's event facility by default executes listeners in the context
5052
//			of the source object. This is very odd, but should probably be
5091
//			of the source object. This is very odd, but should probably be
5053
//			supported as an option (both for the source and for the dest). It
5092
//			supported as an option (both for the source and for the dest). It
5054
//			can be thought of as a connection-specific hitch().
5093
//			can be thought of as a connection-specific hitch().
5055
// TODO: more resiliency for 4+ arguments to connect()
5094
// TODO: more resiliency for 4+ arguments to connect()
5056
 
5095
 
5057
dojo.event = new function(){
5096
dojo.event = new function(){
5058
	this._canTimeout = dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);
5097
	this._canTimeout = dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);
5059
 
5098
 
5060
	// FIXME: where should we put this method (not here!)?
5099
	// FIXME: where should we put this method (not here!)?
5061
	function interpolateArgs(args, searchForNames){
5100
	function interpolateArgs(args, searchForNames){
5062
		var dl = dojo.lang;
5101
		var dl = dojo.lang;
5063
		var ao = {
5102
		var ao = {
5064
			srcObj: dj_global,
5103
			srcObj: dj_global,
5065
			srcFunc: null,
5104
			srcFunc: null,
5066
			adviceObj: dj_global,
5105
			adviceObj: dj_global,
5067
			adviceFunc: null,
5106
			adviceFunc: null,
5068
			aroundObj: null,
5107
			aroundObj: null,
5069
			aroundFunc: null,
5108
			aroundFunc: null,
5070
			adviceType: (args.length>2) ? args[0] : "after",
5109
			adviceType: (args.length>2) ? args[0] : "after",
5071
			precedence: "last",
5110
			precedence: "last",
5072
			once: false,
5111
			once: false,
5073
			delay: null,
5112
			delay: null,
5074
			rate: 0,
5113
			rate: 0,
5075
			adviceMsg: false,
5114
			adviceMsg: false,
5076
			maxCalls: -1
5115
			maxCalls: -1
5077
		};
5116
		};
5078
 
5117
 
5079
		switch(args.length){
5118
		switch(args.length){
5080
			case 0: return;
5119
			case 0: return;
5081
			case 1: return;
5120
			case 1: return;
5082
			case 2:
5121
			case 2:
5083
				ao.srcFunc = args[0];
5122
				ao.srcFunc = args[0];
5084
				ao.adviceFunc = args[1];
5123
				ao.adviceFunc = args[1];
5085
				break;
5124
				break;
5086
			case 3:
5125
			case 3:
5087
				if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
5126
				if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
5088
					ao.adviceType = "after";
5127
					ao.adviceType = "after";
5089
					ao.srcObj = args[0];
5128
					ao.srcObj = args[0];
5090
					ao.srcFunc = args[1];
5129
					ao.srcFunc = args[1];
5091
					ao.adviceFunc = args[2];
5130
					ao.adviceFunc = args[2];
5092
				}else if((dl.isString(args[1]))&&(dl.isString(args[2]))){
5131
				}else if((dl.isString(args[1]))&&(dl.isString(args[2]))){
5093
					ao.srcFunc = args[1];
5132
					ao.srcFunc = args[1];
5094
					ao.adviceFunc = args[2];
5133
					ao.adviceFunc = args[2];
5095
				}else if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
5134
				}else if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
5096
					ao.adviceType = "after";
5135
					ao.adviceType = "after";
5097
					ao.srcObj = args[0];
5136
					ao.srcObj = args[0];
5098
					ao.srcFunc = args[1];
5137
					ao.srcFunc = args[1];
5099
					var tmpName  = dl.nameAnonFunc(args[2], ao.adviceObj, searchForNames);
5138
					var tmpName  = dl.nameAnonFunc(args[2], ao.adviceObj, searchForNames);
5100
					ao.adviceFunc = tmpName;
5139
					ao.adviceFunc = tmpName;
5101
				}else if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
5140
				}else if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
5102
					ao.adviceType = "after";
5141
					ao.adviceType = "after";
5103
					ao.srcObj = dj_global;
5142
					ao.srcObj = dj_global;
5104
					var tmpName  = dl.nameAnonFunc(args[0], ao.srcObj, searchForNames);
5143
					var tmpName  = dl.nameAnonFunc(args[0], ao.srcObj, searchForNames);
5105
					ao.srcFunc = tmpName;
5144
					ao.srcFunc = tmpName;
5106
					ao.adviceObj = args[1];
5145
					ao.adviceObj = args[1];
5107
					ao.adviceFunc = args[2];
5146
					ao.adviceFunc = args[2];
5108
				}
5147
				}
5109
				break;
5148
				break;
5110
			case 4:
5149
			case 4:
5111
				if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
5150
				if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
5112
					// we can assume that we've got an old-style "connect" from
5151
					// we can assume that we've got an old-style "connect" from
5113
					// the sigslot school of event attachment. We therefore
5152
					// the sigslot school of event attachment. We therefore
5114
					// assume after-advice.
5153
					// assume after-advice.
5115
					ao.adviceType = "after";
5154
					ao.adviceType = "after";
5116
					ao.srcObj = args[0];
5155
					ao.srcObj = args[0];
5117
					ao.srcFunc = args[1];
5156
					ao.srcFunc = args[1];
5118
					ao.adviceObj = args[2];
5157
					ao.adviceObj = args[2];
5119
					ao.adviceFunc = args[3];
5158
					ao.adviceFunc = args[3];
5120
				}else if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
5159
				}else if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
5121
					ao.adviceType = args[0];
5160
					ao.adviceType = args[0];
5122
					ao.srcObj = dj_global;
5161
					ao.srcObj = dj_global;
5123
					ao.srcFunc = args[1];
5162
					ao.srcFunc = args[1];
5124
					ao.adviceObj = args[2];
5163
					ao.adviceObj = args[2];
5125
					ao.adviceFunc = args[3];
5164
					ao.adviceFunc = args[3];
5126
				}else if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
5165
				}else if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
5127
					ao.adviceType = args[0];
5166
					ao.adviceType = args[0];
5128
					ao.srcObj = dj_global;
5167
					ao.srcObj = dj_global;
5129
					var tmpName  = dl.nameAnonFunc(args[1], dj_global, searchForNames);
5168
					var tmpName  = dl.nameAnonFunc(args[1], dj_global, searchForNames);
5130
					ao.srcFunc = tmpName;
5169
					ao.srcFunc = tmpName;
5131
					ao.adviceObj = args[2];
5170
					ao.adviceObj = args[2];
5132
					ao.adviceFunc = args[3];
5171
					ao.adviceFunc = args[3];
5133
				}else if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
5172
				}else if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
5134
					ao.srcObj = args[1];
5173
					ao.srcObj = args[1];
5135
					ao.srcFunc = args[2];
5174
					ao.srcFunc = args[2];
5136
					var tmpName  = dl.nameAnonFunc(args[3], dj_global, searchForNames);
5175
					var tmpName  = dl.nameAnonFunc(args[3], dj_global, searchForNames);
5137
					ao.adviceObj = dj_global;
5176
					ao.adviceObj = dj_global;
5138
					ao.adviceFunc = tmpName;
5177
					ao.adviceFunc = tmpName;
5139
				}else if(dl.isObject(args[1])){
5178
				}else if(dl.isObject(args[1])){
5140
					ao.srcObj = args[1];
5179
					ao.srcObj = args[1];
5141
					ao.srcFunc = args[2];
5180
					ao.srcFunc = args[2];
5142
					ao.adviceObj = dj_global;
5181
					ao.adviceObj = dj_global;
5143
					ao.adviceFunc = args[3];
5182
					ao.adviceFunc = args[3];
5144
				}else if(dl.isObject(args[2])){
5183
				}else if(dl.isObject(args[2])){
5145
					ao.srcObj = dj_global;
5184
					ao.srcObj = dj_global;
5146
					ao.srcFunc = args[1];
5185
					ao.srcFunc = args[1];
5147
					ao.adviceObj = args[2];
5186
					ao.adviceObj = args[2];
5148
					ao.adviceFunc = args[3];
5187
					ao.adviceFunc = args[3];
5149
				}else{
5188
				}else{
5150
					ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global;
5189
					ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global;
5151
					ao.srcFunc = args[1];
5190
					ao.srcFunc = args[1];
5152
					ao.adviceFunc = args[2];
5191
					ao.adviceFunc = args[2];
5153
					ao.aroundFunc = args[3];
5192
					ao.aroundFunc = args[3];
5154
				}
5193
				}
5155
				break;
5194
				break;
5156
			case 6:
5195
			case 6:
5157
				ao.srcObj = args[1];
5196
				ao.srcObj = args[1];
5158
				ao.srcFunc = args[2];
5197
				ao.srcFunc = args[2];
5159
				ao.adviceObj = args[3]
5198
				ao.adviceObj = args[3]
5160
				ao.adviceFunc = args[4];
5199
				ao.adviceFunc = args[4];
5161
				ao.aroundFunc = args[5];
5200
				ao.aroundFunc = args[5];
5162
				ao.aroundObj = dj_global;
5201
				ao.aroundObj = dj_global;
5163
				break;
5202
				break;
5164
			default:
5203
			default:
5165
				ao.srcObj = args[1];
5204
				ao.srcObj = args[1];
5166
				ao.srcFunc = args[2];
5205
				ao.srcFunc = args[2];
5167
				ao.adviceObj = args[3]
5206
				ao.adviceObj = args[3]
5168
				ao.adviceFunc = args[4];
5207
				ao.adviceFunc = args[4];
5169
				ao.aroundObj = args[5];
5208
				ao.aroundObj = args[5];
5170
				ao.aroundFunc = args[6];
5209
				ao.aroundFunc = args[6];
5171
				ao.once = args[7];
5210
				ao.once = args[7];
5172
				ao.delay = args[8];
5211
				ao.delay = args[8];
5173
				ao.rate = args[9];
5212
				ao.rate = args[9];
5174
				ao.adviceMsg = args[10];
5213
				ao.adviceMsg = args[10];
5175
				ao.maxCalls = (!isNaN(parseInt(args[11]))) ? args[11] : -1;
5214
				ao.maxCalls = (!isNaN(parseInt(args[11]))) ? args[11] : -1;
5176
				break;
5215
				break;
5177
		}
5216
		}
5178
 
5217
 
5179
		if(dl.isFunction(ao.aroundFunc)){
5218
		if(dl.isFunction(ao.aroundFunc)){
5180
			var tmpName  = dl.nameAnonFunc(ao.aroundFunc, ao.aroundObj, searchForNames);
5219
			var tmpName  = dl.nameAnonFunc(ao.aroundFunc, ao.aroundObj, searchForNames);
5181
			ao.aroundFunc = tmpName;
5220
			ao.aroundFunc = tmpName;
5182
		}
5221
		}
5183
 
5222
 
5184
		if(dl.isFunction(ao.srcFunc)){
5223
		if(dl.isFunction(ao.srcFunc)){
5185
			ao.srcFunc = dl.getNameInObj(ao.srcObj, ao.srcFunc);
5224
			ao.srcFunc = dl.getNameInObj(ao.srcObj, ao.srcFunc);
5186
		}
5225
		}
5187
 
5226
 
5188
		if(dl.isFunction(ao.adviceFunc)){
5227
		if(dl.isFunction(ao.adviceFunc)){
5189
			ao.adviceFunc = dl.getNameInObj(ao.adviceObj, ao.adviceFunc);
5228
			ao.adviceFunc = dl.getNameInObj(ao.adviceObj, ao.adviceFunc);
5190
		}
5229
		}
5191
 
5230
 
5192
		if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
5231
		if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
5193
			ao.aroundFunc = dl.getNameInObj(ao.aroundObj, ao.aroundFunc);
5232
			ao.aroundFunc = dl.getNameInObj(ao.aroundObj, ao.aroundFunc);
5194
		}
5233
		}
5195
 
5234
 
5196
		if(!ao.srcObj){
5235
		if(!ao.srcObj){
5197
			dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
5236
			dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
5198
		}
5237
		}
5199
		if(!ao.adviceObj){
5238
		if(!ao.adviceObj){
5200
			dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
5239
			dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
5201
		}
5240
		}
5202
		
5241
		
5203
		if(!ao.adviceFunc){
5242
		if(!ao.adviceFunc){
5204
			dojo.debug("bad adviceFunc for srcFunc: "+ao.srcFunc);
5243
			dojo.debug("bad adviceFunc for srcFunc: "+ao.srcFunc);
5205
			dojo.debugShallow(ao);
5244
			dojo.debugShallow(ao);
5206
		} 
5245
		} 
5207
		
5246
		
5208
		return ao;
5247
		return ao;
5209
	}
5248
	}
5210
 
5249
 
5211
	this.connect = function(/*...*/){
5250
	this.connect = function(/*...*/){
5212
		// summary:
5251
		// summary:
5213
		//		dojo.event.connect is the glue that holds most Dojo-based
5252
		//		dojo.event.connect is the glue that holds most Dojo-based
5214
		//		applications together. Most combinations of arguments are
5253
		//		applications together. Most combinations of arguments are
5215
		//		supported, with the connect() method attempting to disambiguate
5254
		//		supported, with the connect() method attempting to disambiguate
5216
		//		the implied types of positional parameters. The following will
5255
		//		the implied types of positional parameters. The following will
5217
		//		all work:
5256
		//		all work:
5218
		//			dojo.event.connect("globalFunctionName1", "globalFunctionName2");
5257
		//			dojo.event.connect("globalFunctionName1", "globalFunctionName2");
5219
		//			dojo.event.connect(functionReference1, functionReference2);
5258
		//			dojo.event.connect(functionReference1, functionReference2);
5220
		//			dojo.event.connect("globalFunctionName1", functionReference2);
5259
		//			dojo.event.connect("globalFunctionName1", functionReference2);
5221
		//			dojo.event.connect(functionReference1, "globalFunctionName2");
5260
		//			dojo.event.connect(functionReference1, "globalFunctionName2");
5222
		//			dojo.event.connect(scope1, "functionName1", "globalFunctionName2");
5261
		//			dojo.event.connect(scope1, "functionName1", "globalFunctionName2");
5223
		//			dojo.event.connect("globalFunctionName1", scope2, "functionName2");
5262
		//			dojo.event.connect("globalFunctionName1", scope2, "functionName2");
5224
		//			dojo.event.connect(scope1, "functionName1", scope2, "functionName2");
5263
		//			dojo.event.connect(scope1, "functionName1", scope2, "functionName2");
5225
		//			dojo.event.connect("after", scope1, "functionName1", scope2, "functionName2");
5264
		//			dojo.event.connect("after", scope1, "functionName1", scope2, "functionName2");
5226
		//			dojo.event.connect("before", scope1, "functionName1", scope2, "functionName2");
5265
		//			dojo.event.connect("before", scope1, "functionName1", scope2, "functionName2");
5227
		//			dojo.event.connect("around", 	scope1, "functionName1", 
5266
		//			dojo.event.connect("around", 	scope1, "functionName1", 
5228
		//											scope2, "functionName2",
5267
		//											scope2, "functionName2",
5229
		//											aroundFunctionReference);
5268
		//											aroundFunctionReference);
5230
		//			dojo.event.connect("around", 	scope1, "functionName1", 
5269
		//			dojo.event.connect("around", 	scope1, "functionName1", 
5231
		//											scope2, "functionName2",
5270
		//											scope2, "functionName2",
5232
		//											scope3, "aroundFunctionName");
5271
		//											scope3, "aroundFunctionName");
5233
		//			dojo.event.connect("before-around", 	scope1, "functionName1", 
5272
		//			dojo.event.connect("before-around", 	scope1, "functionName1", 
5234
		//													scope2, "functionName2",
5273
		//													scope2, "functionName2",
5235
		//													aroundFunctionReference);
5274
		//													aroundFunctionReference);
5236
		//			dojo.event.connect("after-around", 		scope1, "functionName1", 
5275
		//			dojo.event.connect("after-around", 		scope1, "functionName1", 
5237
		//													scope2, "functionName2",
5276
		//													scope2, "functionName2",
5238
		//													aroundFunctionReference);
5277
		//													aroundFunctionReference);
5239
		//			dojo.event.connect("after-around", 		scope1, "functionName1", 
5278
		//			dojo.event.connect("after-around", 		scope1, "functionName1", 
5240
		//													scope2, "functionName2",
5279
		//													scope2, "functionName2",
5241
		//													scope3, "aroundFunctionName");
5280
		//													scope3, "aroundFunctionName");
5242
		//			dojo.event.connect("around", 	scope1, "functionName1", 
5281
		//			dojo.event.connect("around", 	scope1, "functionName1", 
5243
		//											scope2, "functionName2",
5282
		//											scope2, "functionName2",
5244
		//											scope3, "aroundFunctionName", true, 30);
5283
		//											scope3, "aroundFunctionName", true, 30);
5245
		//			dojo.event.connect("around", 	scope1, "functionName1", 
5284
		//			dojo.event.connect("around", 	scope1, "functionName1", 
5246
		//											scope2, "functionName2",
5285
		//											scope2, "functionName2",
5247
		//											scope3, "aroundFunctionName", null, null, 10);
5286
		//											scope3, "aroundFunctionName", null, null, 10);
5248
		// adviceType: 
5287
		// adviceType: 
5249
		//		Optional. String. One of "before", "after", "around",
5288
		//		Optional. String. One of "before", "after", "around",
5250
		//		"before-around", or "after-around". FIXME
5289
		//		"before-around", or "after-around". FIXME
5251
		// srcObj:
5290
		// srcObj:
5252
		//		the scope in which to locate/execute the named srcFunc. Along
5291
		//		the scope in which to locate/execute the named srcFunc. Along
5253
		//		with srcFunc, this creates a way to dereference the function to
5292
		//		with srcFunc, this creates a way to dereference the function to
5254
		//		call. So if the function in question is "foo.bar", the
5293
		//		call. So if the function in question is "foo.bar", the
5255
		//		srcObj/srcFunc pair would be foo and "bar", where "bar" is a
5294
		//		srcObj/srcFunc pair would be foo and "bar", where "bar" is a
5256
		//		string and foo is an object reference.
5295
		//		string and foo is an object reference.
5257
		// srcFunc:
5296
		// srcFunc:
5258
		//		the name of the function to connect to. When it is executed,
5297
		//		the name of the function to connect to. When it is executed,
5259
		//		the listener being registered with this call will be called.
5298
		//		the listener being registered with this call will be called.
5260
		//		The adviceType defines the call order between the source and
5299
		//		The adviceType defines the call order between the source and
5261
		//		the target functions.
5300
		//		the target functions.
5262
		// adviceObj:
5301
		// adviceObj:
5263
		//		the scope in which to locate/execute the named adviceFunc.
5302
		//		the scope in which to locate/execute the named adviceFunc.
5264
		// adviceFunc:
5303
		// adviceFunc:
5265
		//		the name of the function being conected to srcObj.srcFunc
5304
		//		the name of the function being conected to srcObj.srcFunc
5266
		// aroundObj:
5305
		// aroundObj:
5267
		//		the scope in which to locate/execute the named aroundFunc.
5306
		//		the scope in which to locate/execute the named aroundFunc.
5268
		// aroundFunc:
5307
		// aroundFunc:
5269
		//		the name of, or a reference to, the function that will be used
5308
		//		the name of, or a reference to, the function that will be used
5270
		//		to mediate the advice call. Around advice requires a special
5309
		//		to mediate the advice call. Around advice requires a special
5271
		//		unary function that will be passed a "MethodInvocation" object.
5310
		//		unary function that will be passed a "MethodInvocation" object.
5272
		//		These objects have several important properties, namely:
5311
		//		These objects have several important properties, namely:
5273
		//			- args
5312
		//			- args
5274
		//				a mutable array of arguments to be passed into the
5313
		//				a mutable array of arguments to be passed into the
5275
		//				wrapped function
5314
		//				wrapped function
5276
		//			- proceed
5315
		//			- proceed
5277
		//				a function that "continues" the invocation. The result
5316
		//				a function that "continues" the invocation. The result
5278
		//				of this function is the return of the wrapped function.
5317
		//				of this function is the return of the wrapped function.
5279
		//				You can then manipulate this return before passing it
5318
		//				You can then manipulate this return before passing it
5280
		//				back out (or take further action based on it).
5319
		//				back out (or take further action based on it).
5281
		// once:
5320
		// once:
5282
		//		boolean that determines whether or not this connect() will
5321
		//		boolean that determines whether or not this connect() will
5283
		//		create a new connection if an identical connect() has already
5322
		//		create a new connection if an identical connect() has already
5284
		//		been made. Defaults to "false".
5323
		//		been made. Defaults to "false".
5285
		// delay:
5324
		// delay:
5286
		//		an optional delay (in ms), as an integer, for dispatch of a
5325
		//		an optional delay (in ms), as an integer, for dispatch of a
5287
		//		listener after the source has been fired.
5326
		//		listener after the source has been fired.
5288
		// rate:
5327
		// rate:
5289
		//		an optional rate throttling parameter (integer, in ms). When
5328
		//		an optional rate throttling parameter (integer, in ms). When
5290
		//		specified, this particular connection will not fire more than
5329
		//		specified, this particular connection will not fire more than
5291
		//		once in the interval specified by the rate
5330
		//		once in the interval specified by the rate
5292
		// adviceMsg:
5331
		// adviceMsg:
5293
		//		boolean. Should the listener have all the parameters passed in
5332
		//		boolean. Should the listener have all the parameters passed in
5294
		//		as a single argument?
5333
		//		as a single argument?
5295
 
5334
 
5296
		/*
5335
		/*
5297
				ao.adviceType = args[0];
5336
				ao.adviceType = args[0];
5298
				ao.srcObj = args[1];
5337
				ao.srcObj = args[1];
5299
				ao.srcFunc = args[2];
5338
				ao.srcFunc = args[2];
5300
				ao.adviceObj = args[3]
5339
				ao.adviceObj = args[3]
5301
				ao.adviceFunc = args[4];
5340
				ao.adviceFunc = args[4];
5302
				ao.aroundObj = args[5];
5341
				ao.aroundObj = args[5];
5303
				ao.aroundFunc = args[6];
5342
				ao.aroundFunc = args[6];
5304
				ao.once = args[7];
5343
				ao.once = args[7];
5305
				ao.delay = args[8];
5344
				ao.delay = args[8];
5306
				ao.rate = args[9];
5345
				ao.rate = args[9];
5307
				ao.adviceMsg = args[10];
5346
				ao.adviceMsg = args[10];
5308
				ao.maxCalls = args[11];
5347
				ao.maxCalls = args[11];
5309
		*/
5348
		*/
5310
		if(arguments.length == 1){
5349
		if(arguments.length == 1){
5311
			var ao = arguments[0];
5350
			var ao = arguments[0];
5312
		}else{
5351
		}else{
5313
			var ao = interpolateArgs(arguments, true);
5352
			var ao = interpolateArgs(arguments, true);
5314
		}
5353
		}
5315
		/*
-
 
5316
		if(dojo.lang.isString(ao.srcFunc) && (ao.srcFunc.toLowerCase() == "onkey") ){
5354
		if(dojo.lang.isString(ao.srcFunc) && (ao.srcFunc.toLowerCase() == "onkey") ){
5317
			if(dojo.render.html.ie){
5355
			if(dojo.render.html.ie){
5318
				ao.srcFunc = "onkeydown";
5356
				ao.srcFunc = "onkeydown";
5319
				this.connect(ao);
5357
				this.connect(ao);
5320
			}
5358
			}
5321
			ao.srcFunc = "onkeypress";
5359
			ao.srcFunc = "onkeypress";
5322
		}
5360
		}
5323
		*/
-
 
5324
 
5361
 
5325
		if(dojo.lang.isArray(ao.srcObj) && ao.srcObj!=""){
5362
		if(dojo.lang.isArray(ao.srcObj) && ao.srcObj!=""){
5326
			var tmpAO = {};
5363
			var tmpAO = {};
5327
			for(var x in ao){
5364
			for(var x in ao){
5328
				tmpAO[x] = ao[x];
5365
				tmpAO[x] = ao[x];
5329
			}
5366
			}
5330
			var mjps = [];
5367
			var mjps = [];
5331
			dojo.lang.forEach(ao.srcObj, function(src){
5368
			dojo.lang.forEach(ao.srcObj, function(src){
5332
				if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
5369
				if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
5333
					src = dojo.byId(src);
5370
					src = dojo.byId(src);
5334
					// dojo.debug(src);
5371
					// dojo.debug(src);
5335
				}
5372
				}
5336
				tmpAO.srcObj = src;
5373
				tmpAO.srcObj = src;
5337
				// dojo.debug(tmpAO.srcObj, tmpAO.srcFunc);
5374
				// dojo.debug(tmpAO.srcObj, tmpAO.srcFunc);
5338
				// dojo.debug(tmpAO.adviceObj, tmpAO.adviceFunc);
5375
				// dojo.debug(tmpAO.adviceObj, tmpAO.adviceFunc);
5339
				mjps.push(dojo.event.connect.call(dojo.event, tmpAO));
5376
				mjps.push(dojo.event.connect.call(dojo.event, tmpAO));
5340
			});
5377
			});
5341
			return mjps;
5378
			return mjps;
5342
		}
5379
		}
5343
 
5380
 
5344
		// FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!!
5381
		// FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!!
5345
		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
5382
		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
5346
		if(ao.adviceFunc){
5383
		if(ao.adviceFunc){
5347
			var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc);
5384
			var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc);
5348
		}
5385
		}
5349
 
5386
 
5350
		mjp.kwAddAdvice(ao);
5387
		mjp.kwAddAdvice(ao);
5351
 
5388
 
5352
		// advanced users might want to fsck w/ the join point manually
5389
		// advanced users might want to fsck w/ the join point manually
5353
		return mjp; // a MethodJoinPoint object
5390
		return mjp; // a MethodJoinPoint object
5354
	}
5391
	}
5355
 
5392
 
5356
	this.log = function(/*object or funcName*/ a1, /*funcName*/ a2){
5393
	this.log = function(/*object or funcName*/ a1, /*funcName*/ a2){
5357
		// summary:
5394
		// summary:
5358
		//		a function that will wrap and log all calls to the specified
5395
		//		a function that will wrap and log all calls to the specified
5359
		//		a1.a2() function. If only a1 is passed, it'll be used as a
5396
		//		a1.a2() function. If only a1 is passed, it'll be used as a
5360
		//		function or function name on the global context. Logging will
5397
		//		function or function name on the global context. Logging will
5361
		//		be sent to dojo.debug
5398
		//		be sent to dojo.debug
5362
		// a1:
5399
		// a1:
5363
		//		if a2 is passed, this should be an object. If not, it can be a
5400
		//		if a2 is passed, this should be an object. If not, it can be a
5364
		//		function or function name.
5401
		//		function or function name.
5365
		// a2:
5402
		// a2:
5366
		//		a function name
5403
		//		a function name
5367
		var kwArgs;
5404
		var kwArgs;
5368
		if((arguments.length == 1)&&(typeof a1 == "object")){
5405
		if((arguments.length == 1)&&(typeof a1 == "object")){
5369
			kwArgs = a1;
5406
			kwArgs = a1;
5370
		}else{
5407
		}else{
5371
			kwArgs = {
5408
			kwArgs = {
5372
				srcObj: a1,
5409
				srcObj: a1,
5373
				srcFunc: a2
5410
				srcFunc: a2
5374
			};
5411
			};
5375
		}
5412
		}
5376
		kwArgs.adviceFunc = function(){
5413
		kwArgs.adviceFunc = function(){
5377
			var argsStr = [];
5414
			var argsStr = [];
5378
			for(var x=0; x<arguments.length; x++){
5415
			for(var x=0; x<arguments.length; x++){
5379
				argsStr.push(arguments[x]);
5416
				argsStr.push(arguments[x]);
5380
			}
5417
			}
5381
			dojo.debug("("+kwArgs.srcObj+")."+kwArgs.srcFunc, ":", argsStr.join(", "));
5418
			dojo.debug("("+kwArgs.srcObj+")."+kwArgs.srcFunc, ":", argsStr.join(", "));
5382
		};
5419
		};
5383
		this.kwConnect(kwArgs);
5420
		this.kwConnect(kwArgs);
5384
	}
5421
	}
5385
 
5422
 
5386
	this.connectBefore = function(){
5423
	this.connectBefore = function(){
5387
		// summary:
5424
		// summary:
5388
		//	 	takes the same parameters as dojo.event.connect(), except that
5425
		//	 	takes the same parameters as dojo.event.connect(), except that
5389
		//	 	the advice type will always be "before"
5426
		//	 	the advice type will always be "before"
5390
		var args = ["before"];
5427
		var args = ["before"];
5391
		for(var i = 0; i < arguments.length; i++){ args.push(arguments[i]); }
5428
		for(var i = 0; i < arguments.length; i++){ args.push(arguments[i]); }
5392
		return this.connect.apply(this, args); // a MethodJoinPoint object
5429
		return this.connect.apply(this, args); // a MethodJoinPoint object
5393
	}
5430
	}
5394
 
5431
 
5395
	this.connectAround = function(){
5432
	this.connectAround = function(){
5396
		// summary:
5433
		// summary:
5397
		//	 	takes the same parameters as dojo.event.connect(), except that
5434
		//	 	takes the same parameters as dojo.event.connect(), except that
5398
		//	 	the advice type will always be "around"
5435
		//	 	the advice type will always be "around"
5399
		var args = ["around"];
5436
		var args = ["around"];
5400
		for(var i = 0; i < arguments.length; i++){ args.push(arguments[i]); }
5437
		for(var i = 0; i < arguments.length; i++){ args.push(arguments[i]); }
5401
		return this.connect.apply(this, args); // a MethodJoinPoint object
5438
		return this.connect.apply(this, args); // a MethodJoinPoint object
5402
	}
5439
	}
5403
 
5440
 
5404
	this.connectOnce = function(){
5441
	this.connectOnce = function(){
5405
		// summary:
5442
		// summary:
5406
		//	 	takes the same parameters as dojo.event.connect(), except that
5443
		//	 	takes the same parameters as dojo.event.connect(), except that
5407
		//	 	the "once" flag will always be set to "true"
5444
		//	 	the "once" flag will always be set to "true"
5408
		var ao = interpolateArgs(arguments, true);
5445
		var ao = interpolateArgs(arguments, true);
5409
		ao.once = true;
5446
		ao.once = true;
5410
		return this.connect(ao); // a MethodJoinPoint object
5447
		return this.connect(ao); // a MethodJoinPoint object
5411
	}
5448
	}
5412
 
5449
 
5413
	this.connectRunOnce = function(){
5450
	this.connectRunOnce = function(){
5414
		// summary:
5451
		// summary:
5415
		//	 	takes the same parameters as dojo.event.connect(), except that
5452
		//	 	takes the same parameters as dojo.event.connect(), except that
5416
		//	 	the "maxCalls" flag will always be set to 1
5453
		//	 	the "maxCalls" flag will always be set to 1
5417
		var ao = interpolateArgs(arguments, true);
5454
		var ao = interpolateArgs(arguments, true);
5418
		ao.maxCalls = 1;
5455
		ao.maxCalls = 1;
5419
		return this.connect(ao); // a MethodJoinPoint object
5456
		return this.connect(ao); // a MethodJoinPoint object
5420
	}
5457
	}
5421
 
5458
 
5422
	this._kwConnectImpl = function(kwArgs, disconnect){
5459
	this._kwConnectImpl = function(kwArgs, disconnect){
5423
		var fn = (disconnect) ? "disconnect" : "connect";
5460
		var fn = (disconnect) ? "disconnect" : "connect";
5424
		if(typeof kwArgs["srcFunc"] == "function"){
5461
		if(typeof kwArgs["srcFunc"] == "function"){
5425
			kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
5462
			kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
5426
			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.srcFunc, kwArgs.srcObj, true);
5463
			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.srcFunc, kwArgs.srcObj, true);
5427
			kwArgs.srcFunc = tmpName;
5464
			kwArgs.srcFunc = tmpName;
5428
		}
5465
		}
5429
		if(typeof kwArgs["adviceFunc"] == "function"){
5466
		if(typeof kwArgs["adviceFunc"] == "function"){
5430
			kwArgs.adviceObj = kwArgs["adviceObj"]||dj_global;
5467
			kwArgs.adviceObj = kwArgs["adviceObj"]||dj_global;
5431
			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.adviceFunc, kwArgs.adviceObj, true);
5468
			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.adviceFunc, kwArgs.adviceObj, true);
5432
			kwArgs.adviceFunc = tmpName;
5469
			kwArgs.adviceFunc = tmpName;
5433
		}
5470
		}
5434
		kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
5471
		kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
5435
		kwArgs.adviceObj = kwArgs["adviceObj"]||kwArgs["targetObj"]||dj_global;
5472
		kwArgs.adviceObj = kwArgs["adviceObj"]||kwArgs["targetObj"]||dj_global;
5436
		kwArgs.adviceFunc = kwArgs["adviceFunc"]||kwArgs["targetFunc"];
5473
		kwArgs.adviceFunc = kwArgs["adviceFunc"]||kwArgs["targetFunc"];
5437
		// pass kwargs to avoid unrolling/repacking
5474
		// pass kwargs to avoid unrolling/repacking
5438
		return dojo.event[fn](kwArgs);
5475
		return dojo.event[fn](kwArgs);
5439
	}
5476
	}
5440
 
5477
 
5441
	this.kwConnect = function(/*Object*/ kwArgs){
5478
	this.kwConnect = function(/*Object*/ kwArgs){
5442
		// summary:
5479
		// summary:
5443
		//		A version of dojo.event.connect() that takes a map of named
5480
		//		A version of dojo.event.connect() that takes a map of named
5444
		//		parameters instead of the positional parameters that
5481
		//		parameters instead of the positional parameters that
5445
		//		dojo.event.connect() uses. For many advanced connection types,
5482
		//		dojo.event.connect() uses. For many advanced connection types,
5446
		//		this can be a much more readable (and potentially faster)
5483
		//		this can be a much more readable (and potentially faster)
5447
		//		alternative.
5484
		//		alternative.
5448
		// kwArgs:
5485
		// kwArgs:
5449
		// 		An object that can have the following properties:
5486
		// 		An object that can have the following properties:
5450
		//			- adviceType
5487
		//			- adviceType
5451
		//			- srcObj
5488
		//			- srcObj
5452
		//			- srcFunc
5489
		//			- srcFunc
5453
		//			- adviceObj
5490
		//			- adviceObj
5454
		//			- adviceFunc 
5491
		//			- adviceFunc 
5455
		//			- aroundObj
5492
		//			- aroundObj
5456
		//			- aroundFunc
5493
		//			- aroundFunc
5457
		//			- once
5494
		//			- once
5458
		//			- delay
5495
		//			- delay
5459
		//			- rate
5496
		//			- rate
5460
		//			- adviceMsg
5497
		//			- adviceMsg
5461
		//		As with connect, only srcFunc and adviceFunc are generally
5498
		//		As with connect, only srcFunc and adviceFunc are generally
5462
		//		required
5499
		//		required
5463
 
5500
 
5464
		return this._kwConnectImpl(kwArgs, false); // a MethodJoinPoint object
5501
		return this._kwConnectImpl(kwArgs, false); // a MethodJoinPoint object
5465
 
5502
 
5466
	}
5503
	}
5467
 
5504
 
5468
	this.disconnect = function(){
5505
	this.disconnect = function(){
5469
		// summary:
5506
		// summary:
5470
		//		Takes the same parameters as dojo.event.connect() but destroys
5507
		//		Takes the same parameters as dojo.event.connect() but destroys
5471
		//		an existing connection instead of building a new one. For
5508
		//		an existing connection instead of building a new one. For
5472
		//		multiple identical connections, multiple disconnect() calls
5509
		//		multiple identical connections, multiple disconnect() calls
5473
		//		will unroll one each time it's called.
5510
		//		will unroll one each time it's called.
5474
		if(arguments.length == 1){
5511
		if(arguments.length == 1){
5475
			var ao = arguments[0];
5512
			var ao = arguments[0];
5476
		}else{
5513
		}else{
5477
			var ao = interpolateArgs(arguments, true);
5514
			var ao = interpolateArgs(arguments, true);
5478
		}
5515
		}
5479
		if(!ao.adviceFunc){ return; } // nothing to disconnect
5516
		if(!ao.adviceFunc){ return; } // nothing to disconnect
5480
		if(dojo.lang.isString(ao.srcFunc) && (ao.srcFunc.toLowerCase() == "onkey") ){
5517
		if(dojo.lang.isString(ao.srcFunc) && (ao.srcFunc.toLowerCase() == "onkey") ){
5481
			if(dojo.render.html.ie){
5518
			if(dojo.render.html.ie){
5482
				ao.srcFunc = "onkeydown";
5519
				ao.srcFunc = "onkeydown";
5483
				this.disconnect(ao);
5520
				this.disconnect(ao);
5484
			}
5521
			}
5485
			ao.srcFunc = "onkeypress";
5522
			ao.srcFunc = "onkeypress";
5486
		}
5523
		}
5487
		if(!ao.srcObj[ao.srcFunc]){ return null; } // prevent un-necessaray joinpoint creation
5524
		if(!ao.srcObj[ao.srcFunc]){ return null; } // prevent un-necessaray joinpoint creation
5488
		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc, true);
5525
		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc, true);
5489
		mjp.removeAdvice(ao.adviceObj, ao.adviceFunc, ao.adviceType, ao.once); // a MethodJoinPoint object
5526
		mjp.removeAdvice(ao.adviceObj, ao.adviceFunc, ao.adviceType, ao.once); // a MethodJoinPoint object
5490
		return mjp;
5527
		return mjp;
5491
	}
5528
	}
5492
 
5529
 
5493
	this.kwDisconnect = function(kwArgs){
5530
	this.kwDisconnect = function(kwArgs){
5494
		// summary:
5531
		// summary:
5495
		//		Takes the same parameters as dojo.event.kwConnect() but
5532
		//		Takes the same parameters as dojo.event.kwConnect() but
5496
		//		destroys an existing connection instead of building a new one.
5533
		//		destroys an existing connection instead of building a new one.
5497
		return this._kwConnectImpl(kwArgs, true);
5534
		return this._kwConnectImpl(kwArgs, true);
5498
	}
5535
	}
5499
}
5536
}
5500
 
5537
 
5501
// exactly one of these is created whenever a method with a joint point is run,
5538
// exactly one of these is created whenever a method with a joint point is run,
5502
// if there is at least one 'around' advice.
5539
// if there is at least one 'around' advice.
5503
dojo.event.MethodInvocation = function(/*dojo.event.MethodJoinPoint*/join_point, /*Object*/obj, /*Array*/args){
5540
dojo.event.MethodInvocation = function(/*dojo.event.MethodJoinPoint*/join_point, /*Object*/obj, /*Array*/args){
5504
	// summary:
5541
	// summary:
5505
	//		a class the models the call into a function. This is used under the
5542
	//		a class the models the call into a function. This is used under the
5506
	//		covers for all method invocations on both ends of a
5543
	//		covers for all method invocations on both ends of a
5507
	//		connect()-wrapped function dispatch. This allows us to "pickle"
5544
	//		connect()-wrapped function dispatch. This allows us to "pickle"
5508
	//		calls, such as in the case of around advice.
5545
	//		calls, such as in the case of around advice.
5509
	// join_point:
5546
	// join_point:
5510
	//		a dojo.event.MethodJoinPoint object that represents a connection
5547
	//		a dojo.event.MethodJoinPoint object that represents a connection
5511
	// obj:
5548
	// obj:
5512
	//		the scope the call will execute in
5549
	//		the scope the call will execute in
5513
	// args:
5550
	// args:
5514
	//		an array of parameters that will get passed to the callee
5551
	//		an array of parameters that will get passed to the callee
5515
	this.jp_ = join_point;
5552
	this.jp_ = join_point;
5516
	this.object = obj;
5553
	this.object = obj;
5517
	this.args = [];
5554
	this.args = [];
5518
	// make sure we don't lock into a mutable object which can change under us.
5555
	// make sure we don't lock into a mutable object which can change under us.
5519
	// It's ok if the individual items change, though.
5556
	// It's ok if the individual items change, though.
5520
	for(var x=0; x<args.length; x++){
5557
	for(var x=0; x<args.length; x++){
5521
		this.args[x] = args[x];
5558
		this.args[x] = args[x];
5522
	}
5559
	}
5523
	// the index of the 'around' that is currently being executed.
5560
	// the index of the 'around' that is currently being executed.
5524
	this.around_index = -1;
5561
	this.around_index = -1;
5525
}
5562
}
5526
 
5563
 
5527
dojo.event.MethodInvocation.prototype.proceed = function(){
5564
dojo.event.MethodInvocation.prototype.proceed = function(){
5528
	// summary:
5565
	// summary:
5529
	//		proceed with the method call that's represented by this invocation
5566
	//		proceed with the method call that's represented by this invocation
5530
	//		object
5567
	//		object
5531
	this.around_index++;
5568
	this.around_index++;
5532
	if(this.around_index >= this.jp_.around.length){
5569
	if(this.around_index >= this.jp_.around.length){
5533
		return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args);
5570
		return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args);
5534
		// return this.jp_.run_before_after(this.object, this.args);
5571
		// return this.jp_.run_before_after(this.object, this.args);
5535
	}else{
5572
	}else{
5536
		var ti = this.jp_.around[this.around_index];
5573
		var ti = this.jp_.around[this.around_index];
5537
		var mobj = ti[0]||dj_global;
5574
		var mobj = ti[0]||dj_global;
5538
		var meth = ti[1];
5575
		var meth = ti[1];
5539
		return mobj[meth].call(mobj, this);
5576
		return mobj[meth].call(mobj, this);
5540
	}
5577
	}
5541
} 
5578
} 
5542
 
5579
 
5543
 
5580
 
5544
dojo.event.MethodJoinPoint = function(/*Object*/obj, /*String*/funcName){
5581
dojo.event.MethodJoinPoint = function(/*Object*/obj, /*String*/funcName){
5545
	this.object = obj||dj_global;
5582
	this.object = obj||dj_global;
5546
	this.methodname = funcName;
5583
	this.methodname = funcName;
5547
	this.methodfunc = this.object[funcName];
5584
	this.methodfunc = this.object[funcName];
5548
	this.squelch = false;
5585
	this.squelch = false;
5549
	// this.before = [];
5586
	// this.before = [];
5550
	// this.after = [];
5587
	// this.after = [];
5551
	// this.around = [];
5588
	// this.around = [];
5552
}
5589
}
5553
 
5590
 
5554
dojo.event.MethodJoinPoint.getForMethod = function(/*Object*/obj, /*String*/funcName){
5591
dojo.event.MethodJoinPoint.getForMethod = function(/*Object*/obj, /*String*/funcName){
5555
	// summary:
5592
	// summary:
5556
	//		"static" class function for returning a MethodJoinPoint from a
5593
	//		"static" class function for returning a MethodJoinPoint from a
5557
	//		scoped function. If one doesn't exist, one is created.
5594
	//		scoped function. If one doesn't exist, one is created.
5558
	// obj:
5595
	// obj:
5559
	//		the scope to search for the function in
5596
	//		the scope to search for the function in
5560
	// funcName:
5597
	// funcName:
5561
	//		the name of the function to return a MethodJoinPoint for
5598
	//		the name of the function to return a MethodJoinPoint for
5562
	if(!obj){ obj = dj_global; }
5599
	if(!obj){ obj = dj_global; }
5563
	var ofn = obj[funcName];
5600
	var ofn = obj[funcName];
5564
	if(!ofn){
5601
	if(!ofn){
5565
		// supply a do-nothing method implementation
5602
		// supply a do-nothing method implementation
5566
		ofn = obj[funcName] = function(){};
5603
		ofn = obj[funcName] = function(){};
5567
		if(!obj[funcName]){
5604
		if(!obj[funcName]){
5568
			// e.g. cannot add to inbuilt objects in IE6
5605
			// e.g. cannot add to inbuilt objects in IE6
5569
			dojo.raise("Cannot set do-nothing method on that object "+funcName);
5606
			dojo.raise("Cannot set do-nothing method on that object "+funcName);
5570
		}
5607
		}
5571
	}else if((typeof ofn != "function")&&(!dojo.lang.isFunction(ofn))&&(!dojo.lang.isAlien(ofn))){
5608
	}else if((typeof ofn != "function")&&(!dojo.lang.isFunction(ofn))&&(!dojo.lang.isAlien(ofn))){
5572
		// FIXME: should we throw an exception here instead?
5609
		// FIXME: should we throw an exception here instead?
5573
		return null; 
5610
		return null; 
5574
	}
5611
	}
5575
	// we hide our joinpoint instance in obj[funcName + '$joinpoint']
5612
	// we hide our joinpoint instance in obj[funcName + '$joinpoint']
5576
	var jpname = funcName + "$joinpoint";
5613
	var jpname = funcName + "$joinpoint";
5577
	var jpfuncname = funcName + "$joinpoint$method";
5614
	var jpfuncname = funcName + "$joinpoint$method";
5578
	var joinpoint = obj[jpname];
5615
	var joinpoint = obj[jpname];
5579
	if(!joinpoint){
5616
	if(!joinpoint){
5580
		var isNode = false;
5617
		var isNode = false;
5581
		if(dojo.event["browser"]){
5618
		if(dojo.event["browser"]){
5582
			if( (obj["attachEvent"])||
5619
			if( (obj["attachEvent"])||
5583
				(obj["nodeType"])||
5620
				(obj["nodeType"])||
5584
				(obj["addEventListener"]) ){
5621
				(obj["addEventListener"]) ){
5585
				isNode = true;
5622
				isNode = true;
5586
				dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, funcName]);
5623
				dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, funcName]);
5587
			}
5624
			}
5588
		}
5625
		}
5589
		var origArity = ofn.length;
5626
		var origArity = ofn.length;
5590
		obj[jpfuncname] = ofn;
5627
		obj[jpfuncname] = ofn;
5591
		// joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, funcName);
5628
		// joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, funcName);
5592
		joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname);
5629
		joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname);
5593
 
5630
 
5594
		if(!isNode){
5631
		if(!isNode){
5595
			obj[funcName] = function(){ 
5632
			obj[funcName] = function(){ 
5596
				// var args = [];
5633
				// var args = [];
5597
				// for(var x=0; x<arguments.length; x++){
5634
				// for(var x=0; x<arguments.length; x++){
5598
					// args.push(arguments[x]);
5635
					// args.push(arguments[x]);
5599
				// }
5636
				// }
5600
				// return joinpoint.run.apply(joinpoint, args); 
5637
				// return joinpoint.run.apply(joinpoint, args); 
5601
				return joinpoint.run.apply(joinpoint, arguments); 
5638
				return joinpoint.run.apply(joinpoint, arguments); 
5602
			}
5639
			}
5603
		}else{
5640
		}else{
5604
			obj[funcName] = function(){ 
5641
			obj[funcName] = function(){ 
5605
				var args = [];
5642
				var args = [];
5606
 
5643
 
5607
				if(!arguments.length){
5644
				if(!arguments.length){
5608
					var evt = null;
5645
					var evt = null;
5609
					try{
5646
					try{
5610
						if(obj.ownerDocument){
5647
						if(obj.ownerDocument){
5611
							evt = obj.ownerDocument.parentWindow.event;
5648
							evt = obj.ownerDocument.parentWindow.event;
5612
						}else if(obj.documentElement){
5649
						}else if(obj.documentElement){
5613
							evt = obj.documentElement.ownerDocument.parentWindow.event;
5650
							evt = obj.documentElement.ownerDocument.parentWindow.event;
5614
						}else if(obj.event){ //obj is a window
5651
						}else if(obj.event){ //obj is a window
5615
							evt = obj.event;
5652
							evt = obj.event;
5616
						}else{
5653
						}else{
5617
							evt = window.event;
5654
							evt = window.event;
5618
						}
5655
						}
5619
					}catch(e){
5656
					}catch(e){
5620
						evt = window.event;
5657
						evt = window.event;
5621
					}
5658
					}
5622
 
5659
 
5623
					if(evt){
5660
					if(evt){
5624
						args.push(dojo.event.browser.fixEvent(evt, this));
5661
						args.push(dojo.event.browser.fixEvent(evt, this));
5625
					}
5662
					}
5626
				}else{
5663
				}else{
5627
					for(var x=0; x<arguments.length; x++){
5664
					for(var x=0; x<arguments.length; x++){
5628
						if((x==0)&&(dojo.event.browser.isEvent(arguments[x]))){
5665
						if((x==0)&&(dojo.event.browser.isEvent(arguments[x]))){
5629
							args.push(dojo.event.browser.fixEvent(arguments[x], this));
5666
							args.push(dojo.event.browser.fixEvent(arguments[x], this));
5630
						}else{
5667
						}else{
5631
							args.push(arguments[x]);
5668
							args.push(arguments[x]);
5632
						}
5669
						}
5633
					}
5670
					}
5634
				}
5671
				}
5635
				// return joinpoint.run.apply(joinpoint, arguments); 
5672
				// return joinpoint.run.apply(joinpoint, arguments); 
5636
				return joinpoint.run.apply(joinpoint, args); 
5673
				return joinpoint.run.apply(joinpoint, args); 
5637
			}
5674
			}
5638
		}
5675
		}
5639
		obj[funcName].__preJoinArity = origArity;
5676
		obj[funcName].__preJoinArity = origArity;
5640
	}
5677
	}
5641
	return joinpoint; // dojo.event.MethodJoinPoint
5678
	return joinpoint; // dojo.event.MethodJoinPoint
5642
}
5679
}
5643
 
5680
 
5644
dojo.lang.extend(dojo.event.MethodJoinPoint, {
5681
dojo.lang.extend(dojo.event.MethodJoinPoint, {
5645
	squelch: false,
5682
	squelch: false,
5646
 
5683
 
5647
	unintercept: function(){
5684
	unintercept: function(){
5648
		// summary: 
5685
		// summary: 
5649
		//		destroy the connection to all listeners that may have been
5686
		//		destroy the connection to all listeners that may have been
5650
		//		registered on this joinpoint
5687
		//		registered on this joinpoint
5651
		this.object[this.methodname] = this.methodfunc;
5688
		this.object[this.methodname] = this.methodfunc;
5652
		this.before = [];
5689
		this.before = [];
5653
		this.after = [];
5690
		this.after = [];
5654
		this.around = [];
5691
		this.around = [];
5655
	},
5692
	},
5656
 
5693
 
5657
	disconnect: dojo.lang.forward("unintercept"),
5694
	disconnect: dojo.lang.forward("unintercept"),
5658
 
5695
 
5659
	run: function(){
5696
	run: function(){
5660
		// summary:
5697
		// summary:
5661
		//		execute the connection represented by this join point. The
5698
		//		execute the connection represented by this join point. The
5662
		//		arguments passed to run() will be passed to the function and
5699
		//		arguments passed to run() will be passed to the function and
5663
		//		its listeners.
5700
		//		its listeners.
5664
		var obj = this.object||dj_global;
5701
		var obj = this.object||dj_global;
5665
		var args = arguments;
5702
		var args = arguments;
5666
 
5703
 
5667
		// optimization. We only compute once the array version of the arguments
5704
		// optimization. We only compute once the array version of the arguments
5668
		// pseudo-arr in order to prevent building it each time advice is unrolled.
5705
		// pseudo-arr in order to prevent building it each time advice is unrolled.
5669
		var aargs = [];
5706
		var aargs = [];
5670
		for(var x=0; x<args.length; x++){
5707
		for(var x=0; x<args.length; x++){
5671
			aargs[x] = args[x];
5708
			aargs[x] = args[x];
5672
		}
5709
		}
5673
 
5710
 
5674
		var unrollAdvice  = function(marr){ 
5711
		var unrollAdvice  = function(marr){ 
5675
			if(!marr){
5712
			if(!marr){
5676
				dojo.debug("Null argument to unrollAdvice()");
5713
				dojo.debug("Null argument to unrollAdvice()");
5677
				return;
5714
				return;
5678
			}
5715
			}
5679
		  
5716
		  
5680
			var callObj = marr[0]||dj_global;
5717
			var callObj = marr[0]||dj_global;
5681
			var callFunc = marr[1];
5718
			var callFunc = marr[1];
5682
			
5719
			
5683
			if(!callObj[callFunc]){
5720
			if(!callObj[callFunc]){
5684
				dojo.raise("function \"" + callFunc + "\" does not exist on \"" + callObj + "\"");
5721
				dojo.raise("function \"" + callFunc + "\" does not exist on \"" + callObj + "\"");
5685
			}
5722
			}
5686
			
5723
			
5687
			var aroundObj = marr[2]||dj_global;
5724
			var aroundObj = marr[2]||dj_global;
5688
			var aroundFunc = marr[3];
5725
			var aroundFunc = marr[3];
5689
			var msg = marr[6];
5726
			var msg = marr[6];
5690
			var maxCount = marr[7];
5727
			var maxCount = marr[7];
5691
			if(maxCount > -1){
5728
			if(maxCount > -1){
5692
				if(maxCount == 0){
5729
				if(maxCount == 0){
5693
					return;
5730
					return;
5694
				}
5731
				}
5695
				marr[7]--;
5732
				marr[7]--;
5696
			}
5733
			}
5697
			var undef;
5734
			var undef;
5698
 
5735
 
5699
			var to = {
5736
			var to = {
5700
				args: [],
5737
				args: [],
5701
				jp_: this,
5738
				jp_: this,
5702
				object: obj,
5739
				object: obj,
5703
				proceed: function(){
5740
				proceed: function(){
5704
					return callObj[callFunc].apply(callObj, to.args);
5741
					return callObj[callFunc].apply(callObj, to.args);
5705
				}
5742
				}
5706
			};
5743
			};
5707
			to.args = aargs;
5744
			to.args = aargs;
5708
 
5745
 
5709
			var delay = parseInt(marr[4]);
5746
			var delay = parseInt(marr[4]);
5710
			var hasDelay = ((!isNaN(delay))&&(marr[4]!==null)&&(typeof marr[4] != "undefined"));
5747
			var hasDelay = ((!isNaN(delay))&&(marr[4]!==null)&&(typeof marr[4] != "undefined"));
5711
			if(marr[5]){
5748
			if(marr[5]){
5712
				var rate = parseInt(marr[5]);
5749
				var rate = parseInt(marr[5]);
5713
				var cur = new Date();
5750
				var cur = new Date();
5714
				var timerSet = false;
5751
				var timerSet = false;
5715
				if((marr["last"])&&((cur-marr.last)<=rate)){
5752
				if((marr["last"])&&((cur-marr.last)<=rate)){
5716
					if(dojo.event._canTimeout){
5753
					if(dojo.event._canTimeout){
5717
						if(marr["delayTimer"]){
5754
						if(marr["delayTimer"]){
5718
							clearTimeout(marr.delayTimer);
5755
							clearTimeout(marr.delayTimer);
5719
						}
5756
						}
5720
						var tod = parseInt(rate*2); // is rate*2 naive?
5757
						var tod = parseInt(rate*2); // is rate*2 naive?
5721
						var mcpy = dojo.lang.shallowCopy(marr);
5758
						var mcpy = dojo.lang.shallowCopy(marr);
5722
						marr.delayTimer = setTimeout(function(){
5759
						marr.delayTimer = setTimeout(function(){
5723
							// FIXME: on IE at least, event objects from the
5760
							// FIXME: on IE at least, event objects from the
5724
							// browser can go out of scope. How (or should?) we
5761
							// browser can go out of scope. How (or should?) we
5725
							// deal with it?
5762
							// deal with it?
5726
							mcpy[5] = 0;
5763
							mcpy[5] = 0;
5727
							unrollAdvice(mcpy);
5764
							unrollAdvice(mcpy);
5728
						}, tod);
5765
						}, tod);
5729
					}
5766
					}
5730
					return;
5767
					return;
5731
				}else{
5768
				}else{
5732
					marr.last = cur;
5769
					marr.last = cur;
5733
				}
5770
				}
5734
			}
5771
			}
5735
 
5772
 
5736
			// FIXME: need to enforce rates for a connection here!
5773
			// FIXME: need to enforce rates for a connection here!
5737
 
5774
 
5738
			if(aroundFunc){
5775
			if(aroundFunc){
5739
				// NOTE: around advice can't delay since we might otherwise depend
5776
				// NOTE: around advice can't delay since we might otherwise depend
5740
				// on execution order!
5777
				// on execution order!
5741
				aroundObj[aroundFunc].call(aroundObj, to);
5778
				aroundObj[aroundFunc].call(aroundObj, to);
5742
			}else{
5779
			}else{
5743
				// var tmjp = dojo.event.MethodJoinPoint.getForMethod(obj, methname);
5780
				// var tmjp = dojo.event.MethodJoinPoint.getForMethod(obj, methname);
5744
				if((hasDelay)&&((dojo.render.html)||(dojo.render.svg))){  // FIXME: the render checks are grotty!
5781
				if((hasDelay)&&((dojo.render.html)||(dojo.render.svg))){  // FIXME: the render checks are grotty!
5745
					dj_global["setTimeout"](function(){
5782
					dj_global["setTimeout"](function(){
5746
						if(msg){
5783
						if(msg){
5747
							callObj[callFunc].call(callObj, to); 
5784
							callObj[callFunc].call(callObj, to); 
5748
						}else{
5785
						}else{
5749
							callObj[callFunc].apply(callObj, args); 
5786
							callObj[callFunc].apply(callObj, args); 
5750
						}
5787
						}
5751
					}, delay);
5788
					}, delay);
5752
				}else{ // many environments can't support delay!
5789
				}else{ // many environments can't support delay!
5753
					if(msg){
5790
					if(msg){
5754
						callObj[callFunc].call(callObj, to); 
5791
						callObj[callFunc].call(callObj, to); 
5755
					}else{
5792
					}else{
5756
						callObj[callFunc].apply(callObj, args); 
5793
						callObj[callFunc].apply(callObj, args); 
5757
					}
5794
					}
5758
				}
5795
				}
5759
			}
5796
			}
5760
		};
5797
		};
5761
 
5798
 
5762
		var unRollSquelch = function(){
5799
		var unRollSquelch = function(){
5763
			if(this.squelch){
5800
			if(this.squelch){
5764
				try{
5801
				try{
5765
					return unrollAdvice.apply(this, arguments);
5802
					return unrollAdvice.apply(this, arguments);
5766
				}catch(e){ 
5803
				}catch(e){ 
5767
					dojo.debug(e);
5804
					dojo.debug(e);
5768
				}
5805
				}
5769
			}else{
5806
			}else{
5770
				return unrollAdvice.apply(this, arguments);
5807
				return unrollAdvice.apply(this, arguments);
5771
			}
5808
			}
5772
		};
5809
		};
5773
 
5810
 
5774
		if((this["before"])&&(this.before.length>0)){
5811
		if((this["before"])&&(this.before.length>0)){
5775
			// pass a cloned array, if this event disconnects this event forEach on this.before wont work
5812
			// pass a cloned array, if this event disconnects this event forEach on this.before wont work
5776
			dojo.lang.forEach(this.before.concat(new Array()), unRollSquelch);
5813
			dojo.lang.forEach(this.before.concat(new Array()), unRollSquelch);
5777
		}
5814
		}
5778
 
5815
 
5779
		var result;
5816
		var result;
5780
		try{
5817
		try{
5781
			if((this["around"])&&(this.around.length>0)){
5818
			if((this["around"])&&(this.around.length>0)){
5782
				var mi = new dojo.event.MethodInvocation(this, obj, args);
5819
				var mi = new dojo.event.MethodInvocation(this, obj, args);
5783
				result = mi.proceed();
5820
				result = mi.proceed();
5784
			}else if(this.methodfunc){
5821
			}else if(this.methodfunc){
5785
				result = this.object[this.methodname].apply(this.object, args);
5822
				result = this.object[this.methodname].apply(this.object, args);
5786
			}
5823
			}
5787
		}catch(e){ 
5824
		}catch(e){ 
5788
			if(!this.squelch){ 
5825
			if(!this.squelch){ 
5789
				dojo.debug(e,"when calling",this.methodname,"on",this.object,"with arguments",args);
5826
				dojo.debug(e,"when calling",this.methodname,"on",this.object,"with arguments",args);
5790
				dojo.raise(e);
5827
				dojo.raise(e);
5791
			} 
5828
			} 
5792
		}
5829
		}
5793
 
5830
 
5794
		if((this["after"])&&(this.after.length>0)){
5831
		if((this["after"])&&(this.after.length>0)){
5795
			// see comment on this.before above
5832
			// see comment on this.before above
5796
			dojo.lang.forEach(this.after.concat(new Array()), unRollSquelch);
5833
			dojo.lang.forEach(this.after.concat(new Array()), unRollSquelch);
5797
		}
5834
		}
5798
 
5835
 
5799
		return (this.methodfunc) ? result : null;
5836
		return (this.methodfunc) ? result : null;
5800
	},
5837
	},
5801
 
5838
 
5802
	getArr: function(/*String*/kind){
5839
	getArr: function(/*String*/kind){
5803
		// summary: return a list of listeners of the past "kind"
5840
		// summary: return a list of listeners of the past "kind"
5804
		// kind:
5841
		// kind:
5805
		//		can be one of: "before", "after", "around", "before-around", or
5842
		//		can be one of: "before", "after", "around", "before-around", or
5806
		//		"after-around"
5843
		//		"after-around"
5807
		var type = "after";
5844
		var type = "after";
5808
		// FIXME: we should be able to do this through props or Array.in()
5845
		// FIXME: we should be able to do this through props or Array.in()
5809
		if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){
5846
		if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){
5810
			type = "before";
5847
			type = "before";
5811
		}else if(kind=="around"){
5848
		}else if(kind=="around"){
5812
			type = "around";
5849
			type = "around";
5813
		}
5850
		}
5814
		if(!this[type]){ this[type] = []; }
5851
		if(!this[type]){ this[type] = []; }
5815
		return this[type]; // Array
5852
		return this[type]; // Array
5816
	},
5853
	},
5817
 
5854
 
5818
	kwAddAdvice: function(/*Object*/args){
5855
	kwAddAdvice: function(/*Object*/args){
5819
		// summary:
5856
		// summary:
5820
		//		adds advice to the joinpoint with arguments in a map
5857
		//		adds advice to the joinpoint with arguments in a map
5821
		// args:
5858
		// args:
5822
		// 		An object that can have the following properties:
5859
		// 		An object that can have the following properties:
5823
		//			- adviceType
5860
		//			- adviceType
5824
		//			- adviceObj
5861
		//			- adviceObj
5825
		//			- adviceFunc 
5862
		//			- adviceFunc 
5826
		//			- aroundObj
5863
		//			- aroundObj
5827
		//			- aroundFunc
5864
		//			- aroundFunc
5828
		//			- once
5865
		//			- once
5829
		//			- delay
5866
		//			- delay
5830
		//			- rate
5867
		//			- rate
5831
		//			- adviceMsg
5868
		//			- adviceMsg
5832
		//			- maxCalls
5869
		//			- maxCalls
5833
		this.addAdvice(	args["adviceObj"], args["adviceFunc"], 
5870
		this.addAdvice(	args["adviceObj"], args["adviceFunc"], 
5834
						args["aroundObj"], args["aroundFunc"], 
5871
						args["aroundObj"], args["aroundFunc"], 
5835
						args["adviceType"], args["precedence"], 
5872
						args["adviceType"], args["precedence"], 
5836
						args["once"], args["delay"], args["rate"], 
5873
						args["once"], args["delay"], args["rate"], 
5837
						args["adviceMsg"], args["maxCalls"]);
5874
						args["adviceMsg"], args["maxCalls"]);
5838
	},
5875
	},
5839
 
5876
 
5840
	addAdvice: function(	thisAdviceObj, thisAdvice, 
5877
	addAdvice: function(	thisAdviceObj, thisAdvice, 
5841
							thisAroundObj, thisAround, 
5878
							thisAroundObj, thisAround, 
5842
							adviceType, precedence, 
5879
							adviceType, precedence, 
5843
							once, delay, rate, asMessage,
5880
							once, delay, rate, asMessage,
5844
							maxCalls){
5881
							maxCalls){
5845
		// summary:
5882
		// summary:
5846
		//		add advice to this joinpoint using positional parameters
5883
		//		add advice to this joinpoint using positional parameters
5847
		// thisAdviceObj:
5884
		// thisAdviceObj:
5848
		//		the scope in which to locate/execute the named adviceFunc.
5885
		//		the scope in which to locate/execute the named adviceFunc.
5849
		// thisAdviceFunc:
5886
		// thisAdviceFunc:
5850
		//		the name of the function being conected
5887
		//		the name of the function being conected
5851
		// thisAroundObj:
5888
		// thisAroundObj:
5852
		//		the scope in which to locate/execute the named aroundFunc.
5889
		//		the scope in which to locate/execute the named aroundFunc.
5853
		// thisAroundFunc:
5890
		// thisAroundFunc:
5854
		//		the name of the function that will be used to mediate the
5891
		//		the name of the function that will be used to mediate the
5855
		//		advice call.
5892
		//		advice call.
5856
		// adviceType: 
5893
		// adviceType: 
5857
		//		Optional. String. One of "before", "after", "around",
5894
		//		Optional. String. One of "before", "after", "around",
5858
		//		"before-around", or "after-around". FIXME
5895
		//		"before-around", or "after-around". FIXME
5859
		// once:
5896
		// once:
5860
		//		boolean that determines whether or not this advice will create
5897
		//		boolean that determines whether or not this advice will create
5861
		//		a new connection if an identical advice set has already been
5898
		//		a new connection if an identical advice set has already been
5862
		//		provided. Defaults to "false".
5899
		//		provided. Defaults to "false".
5863
		// delay:
5900
		// delay:
5864
		//		an optional delay (in ms), as an integer, for dispatch of a
5901
		//		an optional delay (in ms), as an integer, for dispatch of a
5865
		//		listener after the source has been fired.
5902
		//		listener after the source has been fired.
5866
		// rate:
5903
		// rate:
5867
		//		an optional rate throttling parameter (integer, in ms). When
5904
		//		an optional rate throttling parameter (integer, in ms). When
5868
		//		specified, this particular connection will not fire more than
5905
		//		specified, this particular connection will not fire more than
5869
		//		once in the interval specified by the rate
5906
		//		once in the interval specified by the rate
5870
		// adviceMsg:
5907
		// adviceMsg:
5871
		//		boolean. Should the listener have all the parameters passed in
5908
		//		boolean. Should the listener have all the parameters passed in
5872
		//		as a single argument?
5909
		//		as a single argument?
5873
		// maxCalls:
5910
		// maxCalls:
5874
		//		Integer. The maximum number of times this connection can be
5911
		//		Integer. The maximum number of times this connection can be
5875
		//		used before being auto-disconnected. -1 signals that the
5912
		//		used before being auto-disconnected. -1 signals that the
5876
		//		connection should never be disconnected.
5913
		//		connection should never be disconnected.
5877
		var arr = this.getArr(adviceType);
5914
		var arr = this.getArr(adviceType);
5878
		if(!arr){
5915
		if(!arr){
5879
			dojo.raise("bad this: " + this);
5916
			dojo.raise("bad this: " + this);
5880
		}
5917
		}
5881
 
5918
 
5882
		var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage, maxCalls];
5919
		var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage, maxCalls];
5883
		
5920
		
5884
		if(once){
5921
		if(once){
5885
			if(this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr) >= 0){
5922
			if(this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr) >= 0){
5886
				return;
5923
				return;
5887
			}
5924
			}
5888
		}
5925
		}
5889
 
5926
 
5890
		if(precedence == "first"){
5927
		if(precedence == "first"){
5891
			arr.unshift(ao);
5928
			arr.unshift(ao);
5892
		}else{
5929
		}else{
5893
			arr.push(ao);
5930
			arr.push(ao);
5894
		}
5931
		}
5895
	},
5932
	},
5896
 
5933
 
5897
	hasAdvice: function(thisAdviceObj, thisAdvice, adviceType, arr){
5934
	hasAdvice: function(thisAdviceObj, thisAdvice, adviceType, arr){
5898
		// summary:
5935
		// summary:
5899
		//		returns the array index of the first existing connection
5936
		//		returns the array index of the first existing connection
5900
		//		betweened the passed advice and this joinpoint. Will be -1 if
5937
		//		betweened the passed advice and this joinpoint. Will be -1 if
5901
		//		none exists.
5938
		//		none exists.
5902
		// thisAdviceObj:
5939
		// thisAdviceObj:
5903
		//		the scope in which to locate/execute the named adviceFunc.
5940
		//		the scope in which to locate/execute the named adviceFunc.
5904
		// thisAdviceFunc:
5941
		// thisAdviceFunc:
5905
		//		the name of the function being conected
5942
		//		the name of the function being conected
5906
		// adviceType: 
5943
		// adviceType: 
5907
		//		Optional. String. One of "before", "after", "around",
5944
		//		Optional. String. One of "before", "after", "around",
5908
		//		"before-around", or "after-around". FIXME
5945
		//		"before-around", or "after-around". FIXME
5909
		// arr:
5946
		// arr:
5910
		//		Optional. The list of advices to search. Will be found via
5947
		//		Optional. The list of advices to search. Will be found via
5911
		//		adviceType if not passed
5948
		//		adviceType if not passed
5912
		if(!arr){ arr = this.getArr(adviceType); }
5949
		if(!arr){ arr = this.getArr(adviceType); }
5913
		var ind = -1;
5950
		var ind = -1;
5914
		for(var x=0; x<arr.length; x++){
5951
		for(var x=0; x<arr.length; x++){
5915
			var aao = (typeof thisAdvice == "object") ? (new String(thisAdvice)).toString() : thisAdvice;
5952
			var aao = (typeof thisAdvice == "object") ? (new String(thisAdvice)).toString() : thisAdvice;
5916
			var a1o = (typeof arr[x][1] == "object") ? (new String(arr[x][1])).toString() : arr[x][1];
5953
			var a1o = (typeof arr[x][1] == "object") ? (new String(arr[x][1])).toString() : arr[x][1];
5917
			if((arr[x][0] == thisAdviceObj)&&(a1o == aao)){
5954
			if((arr[x][0] == thisAdviceObj)&&(a1o == aao)){
5918
				ind = x;
5955
				ind = x;
5919
			}
5956
			}
5920
		}
5957
		}
5921
		return ind; // Integer
5958
		return ind; // Integer
5922
	},
5959
	},
5923
 
5960
 
5924
	removeAdvice: function(thisAdviceObj, thisAdvice, adviceType, once){
5961
	removeAdvice: function(thisAdviceObj, thisAdvice, adviceType, once){
5925
		// summary:
5962
		// summary:
5926
		//		returns the array index of the first existing connection
5963
		//		returns the array index of the first existing connection
5927
		//		betweened the passed advice and this joinpoint. Will be -1 if
5964
		//		betweened the passed advice and this joinpoint. Will be -1 if
5928
		//		none exists.
5965
		//		none exists.
5929
		// thisAdviceObj:
5966
		// thisAdviceObj:
5930
		//		the scope in which to locate/execute the named adviceFunc.
5967
		//		the scope in which to locate/execute the named adviceFunc.
5931
		// thisAdviceFunc:
5968
		// thisAdviceFunc:
5932
		//		the name of the function being conected
5969
		//		the name of the function being conected
5933
		// adviceType: 
5970
		// adviceType: 
5934
		//		Optional. String. One of "before", "after", "around",
5971
		//		Optional. String. One of "before", "after", "around",
5935
		//		"before-around", or "after-around". FIXME
5972
		//		"before-around", or "after-around". FIXME
5936
		// once:
5973
		// once:
5937
		//		Optional. Should this only remove the first occurance of the
5974
		//		Optional. Should this only remove the first occurance of the
5938
		//		connection?
5975
		//		connection?
5939
		var arr = this.getArr(adviceType);
5976
		var arr = this.getArr(adviceType);
5940
		var ind = this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr);
5977
		var ind = this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr);
5941
		if(ind == -1){
5978
		if(ind == -1){
5942
			return false;
5979
			return false;
5943
		}
5980
		}
5944
		while(ind != -1){
5981
		while(ind != -1){
5945
			arr.splice(ind, 1);
5982
			arr.splice(ind, 1);
5946
			if(once){ break; }
5983
			if(once){ break; }
5947
			ind = this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr);
5984
			ind = this.hasAdvice(thisAdviceObj, thisAdvice, adviceType, arr);
5948
		}
5985
		}
5949
		return true;
5986
		return true;
5950
	}
5987
	}
5951
});
5988
});
5952
 
5989
 
5953
 
5990
 
5954
dojo.provide("dojo.event.topic");
5991
dojo.provide("dojo.event.topic");
5955
 
5992
 
5956
dojo.event.topic = new function(){
5993
dojo.event.topic = new function(){
5957
	this.topics = {};
5994
	this.topics = {};
5958
 
5995
 
5959
	this.getTopic = function(/*String*/topic){
5996
	this.getTopic = function(/*String*/topic){
5960
		// summary:
5997
		// summary:
5961
		//		returns a topic implementation object of type
5998
		//		returns a topic implementation object of type
5962
		//		dojo.event.topic.TopicImpl
5999
		//		dojo.event.topic.TopicImpl
5963
		// topic:
6000
		// topic:
5964
		//		a unique, opaque string that names the topic
6001
		//		a unique, opaque string that names the topic
5965
		if(!this.topics[topic]){
6002
		if(!this.topics[topic]){
5966
			this.topics[topic] = new this.TopicImpl(topic);
6003
			this.topics[topic] = new this.TopicImpl(topic);
5967
		}
6004
		}
5968
		return this.topics[topic]; // a dojo.event.topic.TopicImpl object
6005
		return this.topics[topic]; // a dojo.event.topic.TopicImpl object
5969
	}
6006
	}
5970
 
6007
 
5971
	this.registerPublisher = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
6008
	this.registerPublisher = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
5972
		// summary:
6009
		// summary:
5973
		//		registers a function as a publisher on a topic. Subsequent
6010
		//		registers a function as a publisher on a topic. Subsequent
5974
		//		calls to the function will cause a publish event on the topic
6011
		//		calls to the function will cause a publish event on the topic
5975
		//		with the arguments passed to the function passed to registered
6012
		//		with the arguments passed to the function passed to registered
5976
		//		listeners.
6013
		//		listeners.
5977
		// topic: 
6014
		// topic: 
5978
		//		a unique, opaque string that names the topic
6015
		//		a unique, opaque string that names the topic
5979
		// obj:
6016
		// obj:
5980
		//		the scope to locate the function in
6017
		//		the scope to locate the function in
5981
		// funcName:
6018
		// funcName:
5982
		//		the name of the function to register
6019
		//		the name of the function to register
5983
		var topic = this.getTopic(topic);
6020
		var topic = this.getTopic(topic);
5984
		topic.registerPublisher(obj, funcName);
6021
		topic.registerPublisher(obj, funcName);
5985
	}
6022
	}
5986
 
6023
 
5987
	this.subscribe = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
6024
	this.subscribe = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
5988
		// summary:
6025
		// summary:
5989
		//		susbscribes the function to the topic. Subsequent events
6026
		//		susbscribes the function to the topic. Subsequent events
5990
		//		dispached to the topic will create a function call for the
6027
		//		dispached to the topic will create a function call for the
5991
		//		obj.funcName() function.
6028
		//		obj.funcName() function.
5992
		// topic: 
6029
		// topic: 
5993
		//		a unique, opaque string that names the topic
6030
		//		a unique, opaque string that names the topic
5994
		// obj:
6031
		// obj:
5995
		//		the scope to locate the function in
6032
		//		the scope to locate the function in
5996
		// funcName:
6033
		// funcName:
5997
		//		the name of the function to being registered as a listener
6034
		//		the name of the function to being registered as a listener
5998
		var topic = this.getTopic(topic);
6035
		var topic = this.getTopic(topic);
5999
		topic.subscribe(obj, funcName);
6036
		topic.subscribe(obj, funcName);
6000
	}
6037
	}
6001
 
6038
 
6002
	this.unsubscribe = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
6039
	this.unsubscribe = function(/*String*/topic, /*Object*/obj, /*String*/funcName){
6003
		// summary:
6040
		// summary:
6004
		//		unsubscribes the obj.funcName() from the topic
6041
		//		unsubscribes the obj.funcName() from the topic
6005
		// topic: 
6042
		// topic: 
6006
		//		a unique, opaque string that names the topic
6043
		//		a unique, opaque string that names the topic
6007
		// obj:
6044
		// obj:
6008
		//		the scope to locate the function in
6045
		//		the scope to locate the function in
6009
		// funcName:
6046
		// funcName:
6010
		//		the name of the function to being unregistered as a listener
6047
		//		the name of the function to being unregistered as a listener
6011
		var topic = this.getTopic(topic);
6048
		var topic = this.getTopic(topic);
6012
		topic.unsubscribe(obj, funcName);
6049
		topic.unsubscribe(obj, funcName);
6013
	}
6050
	}
6014
 
6051
 
6015
	this.destroy = function(/*String*/topic){
6052
	this.destroy = function(/*String*/topic){
6016
		// summary: 
6053
		// summary: 
6017
		//		destroys the topic and unregisters all listeners
6054
		//		destroys the topic and unregisters all listeners
6018
		// topic:
6055
		// topic:
6019
		//		a unique, opaque string that names the topic
6056
		//		a unique, opaque string that names the topic
6020
		this.getTopic(topic).destroy();
6057
		this.getTopic(topic).destroy();
6021
		delete this.topics[topic];
6058
		delete this.topics[topic];
6022
	}
6059
	}
6023
 
6060
 
6024
	this.publishApply = function(/*String*/topic, /*Array*/args){
6061
	this.publishApply = function(/*String*/topic, /*Array*/args){
6025
		// summary: 
6062
		// summary: 
6026
		//		dispatches an event to the topic using the args array as the
6063
		//		dispatches an event to the topic using the args array as the
6027
		//		source for the call arguments to each listener. This is similar
6064
		//		source for the call arguments to each listener. This is similar
6028
		//		to JavaScript's built-in Function.apply()
6065
		//		to JavaScript's built-in Function.apply()
6029
		// topic:
6066
		// topic:
6030
		//		a unique, opaque string that names the topic
6067
		//		a unique, opaque string that names the topic
6031
		// args:
6068
		// args:
6032
		//		the arguments to be passed into listeners of the topic
6069
		//		the arguments to be passed into listeners of the topic
6033
		var topic = this.getTopic(topic);
6070
		var topic = this.getTopic(topic);
6034
		topic.sendMessage.apply(topic, args);
6071
		topic.sendMessage.apply(topic, args);
6035
	}
6072
	}
6036
 
6073
 
6037
	this.publish = function(/*String*/topic, /*Object*/message){
6074
	this.publish = function(/*String*/topic, /*Object*/message){
6038
		// summary: 
6075
		// summary: 
6039
		//		manually "publish" to the passed topic
6076
		//		manually "publish" to the passed topic
6040
		// topic:
6077
		// topic:
6041
		//		a unique, opaque string that names the topic
6078
		//		a unique, opaque string that names the topic
6042
		// message:
6079
		// message:
6043
		//		can be an array of parameters (similar to publishApply), or
6080
		//		can be an array of parameters (similar to publishApply), or
6044
		//		will be treated as one of many arguments to be passed along in
6081
		//		will be treated as one of many arguments to be passed along in
6045
		//		a "flat" unrolling
6082
		//		a "flat" unrolling
6046
		var topic = this.getTopic(topic);
6083
		var topic = this.getTopic(topic);
6047
		// if message is an array, we treat it as a set of arguments,
6084
		// if message is an array, we treat it as a set of arguments,
6048
		// otherwise, we just pass on the arguments passed in as-is
6085
		// otherwise, we just pass on the arguments passed in as-is
6049
		var args = [];
6086
		var args = [];
6050
		// could we use concat instead here?
6087
		// could we use concat instead here?
6051
		for(var x=1; x<arguments.length; x++){
6088
		for(var x=1; x<arguments.length; x++){
6052
			args.push(arguments[x]);
6089
			args.push(arguments[x]);
6053
		}
6090
		}
6054
		topic.sendMessage.apply(topic, args);
6091
		topic.sendMessage.apply(topic, args);
6055
	}
6092
	}
6056
}
6093
}
6057
 
6094
 
6058
dojo.event.topic.TopicImpl = function(topicName){
6095
dojo.event.topic.TopicImpl = function(topicName){
6059
	// summary: a class to represent topics
6096
	// summary: a class to represent topics
6060
 
6097
 
6061
	this.topicName = topicName;
6098
	this.topicName = topicName;
6062
 
6099
 
6063
	this.subscribe = function(/*Object*/listenerObject, /*Function or String*/listenerMethod){
6100
	this.subscribe = function(/*Object*/listenerObject, /*Function or String*/listenerMethod){
6064
		// summary:
6101
		// summary:
6065
		//		use dojo.event.connect() to attach the passed listener to the
6102
		//		use dojo.event.connect() to attach the passed listener to the
6066
		//		topic represented by this object
6103
		//		topic represented by this object
6067
		// listenerObject:
6104
		// listenerObject:
6068
		//		if a string and listenerMethod is ommitted, this is treated as
6105
		//		if a string and listenerMethod is ommitted, this is treated as
6069
		//		the name of a function in the global namespace. If
6106
		//		the name of a function in the global namespace. If
6070
		//		listenerMethod is provided, this is the scope to find/execute
6107
		//		listenerMethod is provided, this is the scope to find/execute
6071
		//		the function in.
6108
		//		the function in.
6072
		// listenerMethod:
6109
		// listenerMethod:
6073
		//		Optional. The function to register.
6110
		//		Optional. The function to register.
6074
		var tf = listenerMethod||listenerObject;
6111
		var tf = listenerMethod||listenerObject;
6075
		var to = (!listenerMethod) ? dj_global : listenerObject;
6112
		var to = (!listenerMethod) ? dj_global : listenerObject;
6076
		return dojo.event.kwConnect({ // dojo.event.MethodJoinPoint
6113
		return dojo.event.kwConnect({ // dojo.event.MethodJoinPoint
6077
			srcObj:		this, 
6114
			srcObj:		this, 
6078
			srcFunc:	"sendMessage", 
6115
			srcFunc:	"sendMessage", 
6079
			adviceObj:	to,
6116
			adviceObj:	to,
6080
			adviceFunc: tf
6117
			adviceFunc: tf
6081
		});
6118
		});
6082
	}
6119
	}
6083
 
6120
 
6084
	this.unsubscribe = function(/*Object*/listenerObject, /*Function or String*/listenerMethod){
6121
	this.unsubscribe = function(/*Object*/listenerObject, /*Function or String*/listenerMethod){
6085
		// summary:
6122
		// summary:
6086
		//		use dojo.event.disconnect() to attach the passed listener to the
6123
		//		use dojo.event.disconnect() to attach the passed listener to the
6087
		//		topic represented by this object
6124
		//		topic represented by this object
6088
		// listenerObject:
6125
		// listenerObject:
6089
		//		if a string and listenerMethod is ommitted, this is treated as
6126
		//		if a string and listenerMethod is ommitted, this is treated as
6090
		//		the name of a function in the global namespace. If
6127
		//		the name of a function in the global namespace. If
6091
		//		listenerMethod is provided, this is the scope to find the
6128
		//		listenerMethod is provided, this is the scope to find the
6092
		//		function in.
6129
		//		function in.
6093
		// listenerMethod:
6130
		// listenerMethod:
6094
		//		Optional. The function to unregister.
6131
		//		Optional. The function to unregister.
6095
		var tf = (!listenerMethod) ? listenerObject : listenerMethod;
6132
		var tf = (!listenerMethod) ? listenerObject : listenerMethod;
6096
		var to = (!listenerMethod) ? null : listenerObject;
6133
		var to = (!listenerMethod) ? null : listenerObject;
6097
		return dojo.event.kwDisconnect({ // dojo.event.MethodJoinPoint
6134
		return dojo.event.kwDisconnect({ // dojo.event.MethodJoinPoint
6098
			srcObj:		this, 
6135
			srcObj:		this, 
6099
			srcFunc:	"sendMessage", 
6136
			srcFunc:	"sendMessage", 
6100
			adviceObj:	to,
6137
			adviceObj:	to,
6101
			adviceFunc: tf
6138
			adviceFunc: tf
6102
		});
6139
		});
6103
	}
6140
	}
6104
 
6141
 
6105
	this._getJoinPoint = function(){
6142
	this._getJoinPoint = function(){
6106
		return dojo.event.MethodJoinPoint.getForMethod(this, "sendMessage");
6143
		return dojo.event.MethodJoinPoint.getForMethod(this, "sendMessage");
6107
	}
6144
	}
6108
 
6145
 
6109
	this.setSquelch = function(/*Boolean*/shouldSquelch){
6146
	this.setSquelch = function(/*Boolean*/shouldSquelch){
6110
		// summary: 
6147
		// summary: 
6111
		//		determine whether or not exceptions in the calling of a
6148
		//		determine whether or not exceptions in the calling of a
6112
		//		listener in the chain should stop execution of the chain.
6149
		//		listener in the chain should stop execution of the chain.
6113
		this._getJoinPoint().squelch = shouldSquelch;
6150
		this._getJoinPoint().squelch = shouldSquelch;
6114
	}
6151
	}
6115
 
6152
 
6116
	this.destroy = function(){
6153
	this.destroy = function(){
6117
		// summary: disconnects all listeners from this topic
6154
		// summary: disconnects all listeners from this topic
6118
		this._getJoinPoint().disconnect();
6155
		this._getJoinPoint().disconnect();
6119
	}
6156
	}
6120
 
6157
 
6121
	this.registerPublisher = function(	/*Object*/publisherObject, 
6158
	this.registerPublisher = function(	/*Object*/publisherObject, 
6122
										/*Function or String*/publisherMethod){
6159
										/*Function or String*/publisherMethod){
6123
		// summary:
6160
		// summary:
6124
		//		registers the passed function as a publisher on this topic.
6161
		//		registers the passed function as a publisher on this topic.
6125
		//		Each time the function is called, an event will be published on
6162
		//		Each time the function is called, an event will be published on
6126
		//		this topic.
6163
		//		this topic.
6127
		// publisherObject:
6164
		// publisherObject:
6128
		//		if a string and listenerMethod is ommitted, this is treated as
6165
		//		if a string and listenerMethod is ommitted, this is treated as
6129
		//		the name of a function in the global namespace. If
6166
		//		the name of a function in the global namespace. If
6130
		//		listenerMethod is provided, this is the scope to find the
6167
		//		listenerMethod is provided, this is the scope to find the
6131
		//		function in.
6168
		//		function in.
6132
		// publisherMethod:
6169
		// publisherMethod:
6133
		//		Optional. The function to register.
6170
		//		Optional. The function to register.
6134
		dojo.event.connect(publisherObject, publisherMethod, this, "sendMessage");
6171
		dojo.event.connect(publisherObject, publisherMethod, this, "sendMessage");
6135
	}
6172
	}
6136
 
6173
 
6137
	this.sendMessage = function(message){
6174
	this.sendMessage = function(message){
6138
		// summary: a stub to be called when a message is sent to the topic.
6175
		// summary: a stub to be called when a message is sent to the topic.
6139
 
6176
 
6140
		// The message has been propagated
6177
		// The message has been propagated
6141
	}
6178
	}
6142
}
6179
}
6143
 
6180
 
6144
 
6181
 
6145
dojo.provide("dojo.event.browser");
6182
dojo.provide("dojo.event.browser");
6146
 
6183
 
6147
 
6184
 
6148
// FIXME: any particular reason this is in the global scope?
6185
// FIXME: any particular reason this is in the global scope?
6149
dojo._ie_clobber = new function(){
6186
dojo._ie_clobber = new function(){
6150
	this.clobberNodes = [];
6187
	this.clobberNodes = [];
6151
 
6188
 
6152
	function nukeProp(node, prop){
6189
	function nukeProp(node, prop){
6153
		// try{ node.removeAttribute(prop); 	}catch(e){ /* squelch */ }
6190
		// try{ node.removeAttribute(prop); 	}catch(e){ /* squelch */ }
6154
		try{ node[prop] = null; 			}catch(e){ /* squelch */ }
6191
		try{ node[prop] = null; 			}catch(e){ /* squelch */ }
6155
		try{ delete node[prop]; 			}catch(e){ /* squelch */ }
6192
		try{ delete node[prop]; 			}catch(e){ /* squelch */ }
6156
		// FIXME: JotLive needs this, but I'm not sure if it's too slow or not
6193
		// FIXME: JotLive needs this, but I'm not sure if it's too slow or not
6157
		try{ node.removeAttribute(prop);	}catch(e){ /* squelch */ }
6194
		try{ node.removeAttribute(prop);	}catch(e){ /* squelch */ }
6158
	}
6195
	}
6159
 
6196
 
6160
	this.clobber = function(nodeRef){
6197
	this.clobber = function(nodeRef){
6161
		var na;
6198
		var na;
6162
		var tna;
6199
		var tna;
6163
		if(nodeRef){
6200
		if(nodeRef){
6164
			tna = nodeRef.all || nodeRef.getElementsByTagName("*");
6201
			tna = nodeRef.all || nodeRef.getElementsByTagName("*");
6165
			na = [nodeRef];
6202
			na = [nodeRef];
6166
			for(var x=0; x<tna.length; x++){
6203
			for(var x=0; x<tna.length; x++){
6167
				// if we're gonna be clobbering the thing, at least make sure
6204
				// if we're gonna be clobbering the thing, at least make sure
6168
				// we aren't trying to do it twice
6205
				// we aren't trying to do it twice
6169
				if(tna[x]["__doClobber__"]){
6206
				if(tna[x]["__doClobber__"]){
6170
					na.push(tna[x]);
6207
					na.push(tna[x]);
6171
				}
6208
				}
6172
			}
6209
			}
6173
		}else{
6210
		}else{
6174
			try{ window.onload = null; }catch(e){}
6211
			try{ window.onload = null; }catch(e){}
6175
			na = (this.clobberNodes.length) ? this.clobberNodes : document.all;
6212
			na = (this.clobberNodes.length) ? this.clobberNodes : document.all;
6176
		}
6213
		}
6177
		tna = null;
6214
		tna = null;
6178
		var basis = {};
6215
		var basis = {};
6179
		for(var i = na.length-1; i>=0; i=i-1){
6216
		for(var i = na.length-1; i>=0; i=i-1){
6180
			var el = na[i];
6217
			var el = na[i];
6181
			try{
6218
			try{
6182
				if(el && el["__clobberAttrs__"]){
6219
				if(el && el["__clobberAttrs__"]){
6183
					for(var j=0; j<el.__clobberAttrs__.length; j++){
6220
					for(var j=0; j<el.__clobberAttrs__.length; j++){
6184
						nukeProp(el, el.__clobberAttrs__[j]);
6221
						nukeProp(el, el.__clobberAttrs__[j]);
6185
					}
6222
					}
6186
					nukeProp(el, "__clobberAttrs__");
6223
					nukeProp(el, "__clobberAttrs__");
6187
					nukeProp(el, "__doClobber__");
6224
					nukeProp(el, "__doClobber__");
6188
				}
6225
				}
6189
			}catch(e){ /* squelch! */};
6226
			}catch(e){ /* squelch! */};
6190
		}
6227
		}
6191
		na = null;
6228
		na = null;
6192
	}
6229
	}
6193
}
6230
}
6194
 
6231
 
6195
if(dojo.render.html.ie){
6232
if(dojo.render.html.ie){
6196
	dojo.addOnUnload(function(){
6233
	dojo.addOnUnload(function(){
6197
		dojo._ie_clobber.clobber();
6234
		dojo._ie_clobber.clobber();
6198
		try{
6235
		try{
6199
			if((dojo["widget"])&&(dojo.widget["manager"])){
6236
			if((dojo["widget"])&&(dojo.widget["manager"])){
6200
				dojo.widget.manager.destroyAll();
6237
				dojo.widget.manager.destroyAll();
6201
			}
6238
			}
6202
		}catch(e){}
6239
		}catch(e){}
6203
 
6240
 
6204
		// Workaround for IE leak recommended in ticket #1727 by schallm
6241
		// Workaround for IE leak recommended in ticket #1727 by schallm
6205
		if(dojo.widget){
6242
		if(dojo.widget){
6206
			for(var name in dojo.widget._templateCache){
6243
			for(var name in dojo.widget._templateCache){
6207
				if(dojo.widget._templateCache[name].node){
6244
				if(dojo.widget._templateCache[name].node){
6208
					dojo.dom.destroyNode(dojo.widget._templateCache[name].node);
6245
					dojo.dom.destroyNode(dojo.widget._templateCache[name].node);
6209
					dojo.widget._templateCache[name].node = null;
6246
					dojo.widget._templateCache[name].node = null;
6210
					delete dojo.widget._templateCache[name].node;
6247
					delete dojo.widget._templateCache[name].node;
6211
				}
6248
				}
6212
			}
6249
			}
6213
		}
6250
		}
6214
 
6251
 
6215
		try{ window.onload = null; }catch(e){}
6252
		try{ window.onload = null; }catch(e){}
6216
		try{ window.onunload = null; }catch(e){}
6253
		try{ window.onunload = null; }catch(e){}
6217
		dojo._ie_clobber.clobberNodes = [];
6254
		dojo._ie_clobber.clobberNodes = [];
6218
		// CollectGarbage();
6255
		// CollectGarbage();
6219
	});
6256
	});
6220
}
6257
}
6221
 
6258
 
6222
dojo.event.browser = new function(){
6259
dojo.event.browser = new function(){
6223
 
6260
 
6224
	var clobberIdx = 0;
6261
	var clobberIdx = 0;
6225
 
6262
 
6226
	this.normalizedEventName = function(/*String*/eventName){
6263
	this.normalizedEventName = function(/*String*/eventName){
6227
		switch(eventName){
6264
		switch(eventName){
6228
			case "CheckboxStateChange":
6265
			case "CheckboxStateChange":
6229
			case "DOMAttrModified":
6266
			case "DOMAttrModified":
6230
			case "DOMMenuItemActive":
6267
			case "DOMMenuItemActive":
6231
			case "DOMMenuItemInactive":
6268
			case "DOMMenuItemInactive":
6232
			case "DOMMouseScroll":
6269
			case "DOMMouseScroll":
6233
			case "DOMNodeInserted":
6270
			case "DOMNodeInserted":
6234
			case "DOMNodeRemoved":
6271
			case "DOMNodeRemoved":
6235
			case "RadioStateChange":
6272
			case "RadioStateChange":
6236
				return eventName;
6273
				return eventName;
6237
				break;
6274
				break;
6238
			default:
6275
			default:
6239
				var lcn = eventName.toLowerCase();
6276
				var lcn = eventName.toLowerCase();
6240
				return (lcn.indexOf("on") == 0) ? lcn.substr(2) : lcn;
6277
				return (lcn.indexOf("on") == 0) ? lcn.substr(2) : lcn;
6241
				break;
6278
				break;
6242
		}
6279
		}
6243
	}
6280
	}
6244
	
6281
	
6245
	this.clean = function(/*DOMNode*/node){
6282
	this.clean = function(/*DOMNode*/node){
6246
		// summary:
6283
		// summary:
6247
		//		removes native event handlers so that destruction of the node
6284
		//		removes native event handlers so that destruction of the node
6248
		//		will not leak memory. On most browsers this is a no-op, but
6285
		//		will not leak memory. On most browsers this is a no-op, but
6249
		//		it's critical for manual node removal on IE.
6286
		//		it's critical for manual node removal on IE.
6250
		// node:
6287
		// node:
6251
		//		A DOM node. All of it's children will also be cleaned.
6288
		//		A DOM node. All of it's children will also be cleaned.
6252
		if(dojo.render.html.ie){ 
6289
		if(dojo.render.html.ie){ 
6253
			dojo._ie_clobber.clobber(node);
6290
			dojo._ie_clobber.clobber(node);
6254
		}
6291
		}
6255
	}
6292
	}
6256
 
6293
 
6257
	this.addClobberNode = function(/*DOMNode*/node){
6294
	this.addClobberNode = function(/*DOMNode*/node){
6258
		// summary:
6295
		// summary:
6259
		//		register the passed node to support event stripping
6296
		//		register the passed node to support event stripping
6260
		// node:
6297
		// node:
6261
		//		A DOM node
6298
		//		A DOM node
6262
		if(!dojo.render.html.ie){ return; }
6299
		if(!dojo.render.html.ie){ return; }
6263
		if(!node["__doClobber__"]){
6300
		if(!node["__doClobber__"]){
6264
			node.__doClobber__ = true;
6301
			node.__doClobber__ = true;
6265
			dojo._ie_clobber.clobberNodes.push(node);
6302
			dojo._ie_clobber.clobberNodes.push(node);
6266
			// this might not be the most efficient thing to do, but it's
6303
			// this might not be the most efficient thing to do, but it's
6267
			// much less error prone than other approaches which were
6304
			// much less error prone than other approaches which were
6268
			// previously tried and failed
6305
			// previously tried and failed
6269
			node.__clobberAttrs__ = [];
6306
			node.__clobberAttrs__ = [];
6270
		}
6307
		}
6271
	}
6308
	}
6272
 
6309
 
6273
	this.addClobberNodeAttrs = function(/*DOMNode*/node, /*Array*/props){
6310
	this.addClobberNodeAttrs = function(/*DOMNode*/node, /*Array*/props){
6274
		// summary:
6311
		// summary:
6275
		//		register the passed node to support event stripping
6312
		//		register the passed node to support event stripping
6276
		// node:
6313
		// node:
6277
		//		A DOM node to stip properties from later
6314
		//		A DOM node to stip properties from later
6278
		// props:
6315
		// props:
6279
		//		A list of propeties to strip from the node
6316
		//		A list of propeties to strip from the node
6280
		if(!dojo.render.html.ie){ return; }
6317
		if(!dojo.render.html.ie){ return; }
6281
		this.addClobberNode(node);
6318
		this.addClobberNode(node);
6282
		for(var x=0; x<props.length; x++){
6319
		for(var x=0; x<props.length; x++){
6283
			node.__clobberAttrs__.push(props[x]);
6320
			node.__clobberAttrs__.push(props[x]);
6284
		}
6321
		}
6285
	}
6322
	}
6286
 
6323
 
6287
	this.removeListener = function(	/*DOMNode*/ node, 
6324
	this.removeListener = function(	/*DOMNode*/ node, 
6288
									/*String*/	evtName, 
6325
									/*String*/	evtName, 
6289
									/*Function*/fp, 
6326
									/*Function*/fp, 
6290
									/*Boolean*/	capture){
6327
									/*Boolean*/	capture){
6291
		// summary:
6328
		// summary:
6292
		//		clobbers the listener from the node
6329
		//		clobbers the listener from the node
6293
		// evtName:
6330
		// evtName:
6294
		//		the name of the handler to remove the function from
6331
		//		the name of the handler to remove the function from
6295
		// node:
6332
		// node:
6296
		//		DOM node to attach the event to
6333
		//		DOM node to attach the event to
6297
		// fp:
6334
		// fp:
6298
		//		the function to register
6335
		//		the function to register
6299
		// capture:
6336
		// capture:
6300
		//		Optional. should this listener prevent propigation?
6337
		//		Optional. should this listener prevent propigation?
6301
		if(!capture){ var capture = false; }
6338
		if(!capture){ var capture = false; }
6302
		evtName = dojo.event.browser.normalizedEventName(evtName);
6339
		evtName = dojo.event.browser.normalizedEventName(evtName);
6303
		if(evtName == "key"){
6340
		if(evtName == "key"){
6304
			if(dojo.render.html.ie){
6341
			if(dojo.render.html.ie){
6305
				this.removeListener(node, "onkeydown", fp, capture);
6342
				this.removeListener(node, "onkeydown", fp, capture);
6306
			}
6343
			}
6307
			evtName = "keypress";
6344
			evtName = "keypress";
6308
		}
6345
		}
6309
		// FIXME: this is mostly a punt, we aren't actually doing anything on IE
6346
		// FIXME: this is mostly a punt, we aren't actually doing anything on IE
6310
		if(node.removeEventListener){
6347
		if(node.removeEventListener){
6311
			node.removeEventListener(evtName, fp, capture);
6348
			node.removeEventListener(evtName, fp, capture);
6312
		}
6349
		}
6313
	}
6350
	}
6314
 
6351
 
6315
	this.addListener = function(/*DOMNode*/node, /*String*/evtName, /*Function*/fp, /*Boolean*/capture, /*Boolean*/dontFix){
6352
	this.addListener = function(/*DOMNode*/node, /*String*/evtName, /*Function*/fp, /*Boolean*/capture, /*Boolean*/dontFix){
6316
		// summary:
6353
		// summary:
6317
		//		adds a listener to the node
6354
		//		adds a listener to the node
6318
		// evtName:
6355
		// evtName:
6319
		//		the name of the handler to add the listener to can be either of
6356
		//		the name of the handler to add the listener to can be either of
6320
		//		the form "onclick" or "click"
6357
		//		the form "onclick" or "click"
6321
		// node:
6358
		// node:
6322
		//		DOM node to attach the event to
6359
		//		DOM node to attach the event to
6323
		// fp:
6360
		// fp:
6324
		//		the function to register
6361
		//		the function to register
6325
		// capture:
6362
		// capture:
6326
		//		Optional. Should this listener prevent propigation?
6363
		//		Optional. Should this listener prevent propigation?
6327
		// dontFix:
6364
		// dontFix:
6328
		//		Optional. Should we avoid registering a new closure around the
6365
		//		Optional. Should we avoid registering a new closure around the
6329
		//		listener to enable fixEvent for dispatch of the registered
6366
		//		listener to enable fixEvent for dispatch of the registered
6330
		//		function?
6367
		//		function?
6331
		if(!node){ return; } // FIXME: log and/or bail?
6368
		if(!node){ return; } // FIXME: log and/or bail?
6332
		if(!capture){ var capture = false; }
6369
		if(!capture){ var capture = false; }
6333
		evtName = dojo.event.browser.normalizedEventName(evtName);
6370
		evtName = dojo.event.browser.normalizedEventName(evtName);
6334
		if(evtName == "key"){
6371
		if(evtName == "key"){
6335
			if(dojo.render.html.ie){
6372
			if(dojo.render.html.ie){
6336
				this.addListener(node, "onkeydown", fp, capture, dontFix);
6373
				this.addListener(node, "onkeydown", fp, capture, dontFix);
6337
			}
6374
			}
6338
			evtName = "keypress";
6375
			evtName = "keypress";
6339
		}
6376
		}
6340
 
6377
 
6341
		if(!dontFix){
6378
		if(!dontFix){
6342
			// build yet another closure around fp in order to inject fixEvent
6379
			// build yet another closure around fp in order to inject fixEvent
6343
			// around the resulting event
6380
			// around the resulting event
6344
			var newfp = function(evt){
6381
			var newfp = function(evt){
6345
				if(!evt){ evt = window.event; }
6382
				if(!evt){ evt = window.event; }
6346
				var ret = fp(dojo.event.browser.fixEvent(evt, this));
6383
				var ret = fp(dojo.event.browser.fixEvent(evt, this));
6347
				if(capture){
6384
				if(capture){
6348
					dojo.event.browser.stopEvent(evt);
6385
					dojo.event.browser.stopEvent(evt);
6349
				}
6386
				}
6350
				return ret;
6387
				return ret;
6351
			}
6388
			}
6352
		}else{
6389
		}else{
6353
			newfp = fp;
6390
			newfp = fp;
6354
		}
6391
		}
6355
 
6392
 
6356
		if(node.addEventListener){ 
6393
		if(node.addEventListener){ 
6357
			node.addEventListener(evtName, newfp, capture);
6394
			node.addEventListener(evtName, newfp, capture);
6358
			return newfp;
6395
			return newfp;
6359
		}else{
6396
		}else{
6360
			evtName = "on"+evtName;
6397
			evtName = "on"+evtName;
6361
			if(typeof node[evtName] == "function" ){
6398
			if(typeof node[evtName] == "function" ){
6362
				var oldEvt = node[evtName];
6399
				var oldEvt = node[evtName];
6363
				node[evtName] = function(e){
6400
				node[evtName] = function(e){
6364
					oldEvt(e);
6401
					oldEvt(e);
6365
					return newfp(e);
6402
					return newfp(e);
6366
				}
6403
				}
6367
			}else{
6404
			}else{
6368
				node[evtName]=newfp;
6405
				node[evtName]=newfp;
6369
			}
6406
			}
6370
			if(dojo.render.html.ie){
6407
			if(dojo.render.html.ie){
6371
				this.addClobberNodeAttrs(node, [evtName]);
6408
				this.addClobberNodeAttrs(node, [evtName]);
6372
			}
6409
			}
6373
			return newfp;
6410
			return newfp;
6374
		}
6411
		}
6375
	}
6412
	}
6376
 
6413
 
6377
	this.isEvent = function(/*Object*/obj){
6414
	this.isEvent = function(/*Object*/obj){
6378
		// summary: 
6415
		// summary: 
6379
		//		Tries to determine whether or not the object is a DOM event.
6416
		//		Tries to determine whether or not the object is a DOM event.
6380
 
6417
 
6381
		// FIXME: event detection hack ... could test for additional attributes
6418
		// FIXME: event detection hack ... could test for additional attributes
6382
		// if necessary
6419
		// if necessary
6383
		return (typeof obj != "undefined")&&(obj)&&(typeof Event != "undefined")&&(obj.eventPhase); // Boolean
6420
		return (typeof obj != "undefined")&&(obj)&&(typeof Event != "undefined")&&(obj.eventPhase); // Boolean
6384
		// Event does not support instanceof in Opera, otherwise:
6421
		// Event does not support instanceof in Opera, otherwise:
6385
		//return (typeof Event != "undefined")&&(obj instanceof Event);
6422
		//return (typeof Event != "undefined")&&(obj instanceof Event);
6386
	}
6423
	}
6387
 
6424
 
6388
	this.currentEvent = null;
6425
	this.currentEvent = null;
6389
	
6426
	
6390
	this.callListener = function(/*Function*/listener, /*DOMNode*/curTarget){
6427
	this.callListener = function(/*Function*/listener, /*DOMNode*/curTarget){
6391
		// summary:
6428
		// summary:
6392
		//		calls the specified listener in the context of the passed node
6429
		//		calls the specified listener in the context of the passed node
6393
		//		with the current DOM event object as the only parameter
6430
		//		with the current DOM event object as the only parameter
6394
		// listener:
6431
		// listener:
6395
		//		the function to call
6432
		//		the function to call
6396
		// curTarget:
6433
		// curTarget:
6397
		//		the Node to call the function in the scope of
6434
		//		the Node to call the function in the scope of
6398
		if(typeof listener != 'function'){
6435
		if(typeof listener != 'function'){
6399
			dojo.raise("listener not a function: " + listener);
6436
			dojo.raise("listener not a function: " + listener);
6400
		}
6437
		}
6401
		dojo.event.browser.currentEvent.currentTarget = curTarget;
6438
		dojo.event.browser.currentEvent.currentTarget = curTarget;
6402
		return listener.call(curTarget, dojo.event.browser.currentEvent);
6439
		return listener.call(curTarget, dojo.event.browser.currentEvent);
6403
	}
6440
	}
6404
 
6441
 
6405
	this._stopPropagation = function(){
6442
	this._stopPropagation = function(){
6406
		dojo.event.browser.currentEvent.cancelBubble = true; 
6443
		dojo.event.browser.currentEvent.cancelBubble = true; 
6407
	}
6444
	}
6408
 
6445
 
6409
	this._preventDefault = function(){
6446
	this._preventDefault = function(){
6410
		dojo.event.browser.currentEvent.returnValue = false;
6447
		dojo.event.browser.currentEvent.returnValue = false;
6411
	}
6448
	}
6412
 
6449
 
6413
	this.keys = {
6450
	this.keys = {
6414
		KEY_BACKSPACE: 8,
6451
		KEY_BACKSPACE: 8,
6415
		KEY_TAB: 9,
6452
		KEY_TAB: 9,
6416
		KEY_CLEAR: 12,
6453
		KEY_CLEAR: 12,
6417
		KEY_ENTER: 13,
6454
		KEY_ENTER: 13,
6418
		KEY_SHIFT: 16,
6455
		KEY_SHIFT: 16,
6419
		KEY_CTRL: 17,
6456
		KEY_CTRL: 17,
6420
		KEY_ALT: 18,
6457
		KEY_ALT: 18,
6421
		KEY_PAUSE: 19,
6458
		KEY_PAUSE: 19,
6422
		KEY_CAPS_LOCK: 20,
6459
		KEY_CAPS_LOCK: 20,
6423
		KEY_ESCAPE: 27,
6460
		KEY_ESCAPE: 27,
6424
		KEY_SPACE: 32,
6461
		KEY_SPACE: 32,
6425
		KEY_PAGE_UP: 33,
6462
		KEY_PAGE_UP: 33,
6426
		KEY_PAGE_DOWN: 34,
6463
		KEY_PAGE_DOWN: 34,
6427
		KEY_END: 35,
6464
		KEY_END: 35,
6428
		KEY_HOME: 36,
6465
		KEY_HOME: 36,
6429
		KEY_LEFT_ARROW: 37,
6466
		KEY_LEFT_ARROW: 37,
6430
		KEY_UP_ARROW: 38,
6467
		KEY_UP_ARROW: 38,
6431
		KEY_RIGHT_ARROW: 39,
6468
		KEY_RIGHT_ARROW: 39,
6432
		KEY_DOWN_ARROW: 40,
6469
		KEY_DOWN_ARROW: 40,
6433
		KEY_INSERT: 45,
6470
		KEY_INSERT: 45,
6434
		KEY_DELETE: 46,
6471
		KEY_DELETE: 46,
6435
		KEY_HELP: 47,
6472
		KEY_HELP: 47,
6436
		KEY_LEFT_WINDOW: 91,
6473
		KEY_LEFT_WINDOW: 91,
6437
		KEY_RIGHT_WINDOW: 92,
6474
		KEY_RIGHT_WINDOW: 92,
6438
		KEY_SELECT: 93,
6475
		KEY_SELECT: 93,
6439
		KEY_NUMPAD_0: 96,
6476
		KEY_NUMPAD_0: 96,
6440
		KEY_NUMPAD_1: 97,
6477
		KEY_NUMPAD_1: 97,
6441
		KEY_NUMPAD_2: 98,
6478
		KEY_NUMPAD_2: 98,
6442
		KEY_NUMPAD_3: 99,
6479
		KEY_NUMPAD_3: 99,
6443
		KEY_NUMPAD_4: 100,
6480
		KEY_NUMPAD_4: 100,
6444
		KEY_NUMPAD_5: 101,
6481
		KEY_NUMPAD_5: 101,
6445
		KEY_NUMPAD_6: 102,
6482
		KEY_NUMPAD_6: 102,
6446
		KEY_NUMPAD_7: 103,
6483
		KEY_NUMPAD_7: 103,
6447
		KEY_NUMPAD_8: 104,
6484
		KEY_NUMPAD_8: 104,
6448
		KEY_NUMPAD_9: 105,
6485
		KEY_NUMPAD_9: 105,
6449
		KEY_NUMPAD_MULTIPLY: 106,
6486
		KEY_NUMPAD_MULTIPLY: 106,
6450
		KEY_NUMPAD_PLUS: 107,
6487
		KEY_NUMPAD_PLUS: 107,
6451
		KEY_NUMPAD_ENTER: 108,
6488
		KEY_NUMPAD_ENTER: 108,
6452
		KEY_NUMPAD_MINUS: 109,
6489
		KEY_NUMPAD_MINUS: 109,
6453
		KEY_NUMPAD_PERIOD: 110,
6490
		KEY_NUMPAD_PERIOD: 110,
6454
		KEY_NUMPAD_DIVIDE: 111,
6491
		KEY_NUMPAD_DIVIDE: 111,
6455
		KEY_F1: 112,
6492
		KEY_F1: 112,
6456
		KEY_F2: 113,
6493
		KEY_F2: 113,
6457
		KEY_F3: 114,
6494
		KEY_F3: 114,
6458
		KEY_F4: 115,
6495
		KEY_F4: 115,
6459
		KEY_F5: 116,
6496
		KEY_F5: 116,
6460
		KEY_F6: 117,
6497
		KEY_F6: 117,
6461
		KEY_F7: 118,
6498
		KEY_F7: 118,
6462
		KEY_F8: 119,
6499
		KEY_F8: 119,
6463
		KEY_F9: 120,
6500
		KEY_F9: 120,
6464
		KEY_F10: 121,
6501
		KEY_F10: 121,
6465
		KEY_F11: 122,
6502
		KEY_F11: 122,
6466
		KEY_F12: 123,
6503
		KEY_F12: 123,
6467
		KEY_F13: 124,
6504
		KEY_F13: 124,
6468
		KEY_F14: 125,
6505
		KEY_F14: 125,
6469
		KEY_F15: 126,
6506
		KEY_F15: 126,
6470
		KEY_NUM_LOCK: 144,
6507
		KEY_NUM_LOCK: 144,
6471
		KEY_SCROLL_LOCK: 145
6508
		KEY_SCROLL_LOCK: 145
6472
	};
6509
	};
6473
 
6510
 
6474
	// reverse lookup
6511
	// reverse lookup
6475
	this.revKeys = [];
6512
	this.revKeys = [];
6476
	for(var key in this.keys){
6513
	for(var key in this.keys){
6477
		this.revKeys[this.keys[key]] = key;
6514
		this.revKeys[this.keys[key]] = key;
6478
	}
6515
	}
6479
 
6516
 
6480
	this.fixEvent = function(/*Event*/evt, /*DOMNode*/sender){
6517
	this.fixEvent = function(/*Event*/evt, /*DOMNode*/sender){
6481
		// summary:
6518
		// summary:
6482
		//		normalizes properties on the event object including event
6519
		//		normalizes properties on the event object including event
6483
		//		bubbling methods, keystroke normalization, and x/y positions
6520
		//		bubbling methods, keystroke normalization, and x/y positions
6484
		// evt: the native event object
6521
		// evt: the native event object
6485
		// sender: the node to treat as "currentTarget"
6522
		// sender: the node to treat as "currentTarget"
6486
		if(!evt){
6523
		if(!evt){
6487
			if(window["event"]){
6524
			if(window["event"]){
6488
				evt = window.event;
6525
				evt = window.event;
6489
			}
6526
			}
6490
		}
6527
		}
6491
		
6528
		
6492
		if((evt["type"])&&(evt["type"].indexOf("key") == 0)){ // key events
6529
		if((evt["type"])&&(evt["type"].indexOf("key") == 0)){ // key events
6493
			evt.keys = this.revKeys;
6530
			evt.keys = this.revKeys;
6494
			// FIXME: how can we eliminate this iteration?
6531
			// FIXME: how can we eliminate this iteration?
6495
			for(var key in this.keys){
6532
			for(var key in this.keys){
6496
				evt[key] = this.keys[key];
6533
				evt[key] = this.keys[key];
6497
			}
6534
			}
6498
			if(evt["type"] == "keydown" && dojo.render.html.ie){
6535
			if(evt["type"] == "keydown" && dojo.render.html.ie){
6499
				switch(evt.keyCode){
6536
				switch(evt.keyCode){
6500
					case evt.KEY_SHIFT:
6537
					case evt.KEY_SHIFT:
6501
					case evt.KEY_CTRL:
6538
					case evt.KEY_CTRL:
6502
					case evt.KEY_ALT:
6539
					case evt.KEY_ALT:
6503
					case evt.KEY_CAPS_LOCK:
6540
					case evt.KEY_CAPS_LOCK:
6504
					case evt.KEY_LEFT_WINDOW:
6541
					case evt.KEY_LEFT_WINDOW:
6505
					case evt.KEY_RIGHT_WINDOW:
6542
					case evt.KEY_RIGHT_WINDOW:
6506
					case evt.KEY_SELECT:
6543
					case evt.KEY_SELECT:
6507
					case evt.KEY_NUM_LOCK:
6544
					case evt.KEY_NUM_LOCK:
6508
					case evt.KEY_SCROLL_LOCK:
6545
					case evt.KEY_SCROLL_LOCK:
6509
					// I'll get these in keypress after the OS munges them based on numlock
6546
					// I'll get these in keypress after the OS munges them based on numlock
6510
					case evt.KEY_NUMPAD_0:
6547
					case evt.KEY_NUMPAD_0:
6511
					case evt.KEY_NUMPAD_1:
6548
					case evt.KEY_NUMPAD_1:
6512
					case evt.KEY_NUMPAD_2:
6549
					case evt.KEY_NUMPAD_2:
6513
					case evt.KEY_NUMPAD_3:
6550
					case evt.KEY_NUMPAD_3:
6514
					case evt.KEY_NUMPAD_4:
6551
					case evt.KEY_NUMPAD_4:
6515
					case evt.KEY_NUMPAD_5:
6552
					case evt.KEY_NUMPAD_5:
6516
					case evt.KEY_NUMPAD_6:
6553
					case evt.KEY_NUMPAD_6:
6517
					case evt.KEY_NUMPAD_7:
6554
					case evt.KEY_NUMPAD_7:
6518
					case evt.KEY_NUMPAD_8:
6555
					case evt.KEY_NUMPAD_8:
6519
					case evt.KEY_NUMPAD_9:
6556
					case evt.KEY_NUMPAD_9:
6520
					case evt.KEY_NUMPAD_PERIOD:
6557
					case evt.KEY_NUMPAD_PERIOD:
6521
						break; // just ignore the keys that can morph
6558
						break; // just ignore the keys that can morph
6522
					case evt.KEY_NUMPAD_MULTIPLY:
6559
					case evt.KEY_NUMPAD_MULTIPLY:
6523
					case evt.KEY_NUMPAD_PLUS:
6560
					case evt.KEY_NUMPAD_PLUS:
6524
					case evt.KEY_NUMPAD_ENTER:
6561
					case evt.KEY_NUMPAD_ENTER:
6525
					case evt.KEY_NUMPAD_MINUS:
6562
					case evt.KEY_NUMPAD_MINUS:
6526
					case evt.KEY_NUMPAD_DIVIDE:
6563
					case evt.KEY_NUMPAD_DIVIDE:
6527
						break; // I could handle these but just pick them up in keypress
6564
						break; // I could handle these but just pick them up in keypress
6528
					case evt.KEY_PAUSE:
6565
					case evt.KEY_PAUSE:
6529
					case evt.KEY_TAB:
6566
					case evt.KEY_TAB:
6530
					case evt.KEY_BACKSPACE:
6567
					case evt.KEY_BACKSPACE:
6531
					case evt.KEY_ENTER:
6568
					case evt.KEY_ENTER:
6532
					case evt.KEY_ESCAPE:
6569
					case evt.KEY_ESCAPE:
6533
					case evt.KEY_PAGE_UP:
6570
					case evt.KEY_PAGE_UP:
6534
					case evt.KEY_PAGE_DOWN:
6571
					case evt.KEY_PAGE_DOWN:
6535
					case evt.KEY_END:
6572
					case evt.KEY_END:
6536
					case evt.KEY_HOME:
6573
					case evt.KEY_HOME:
6537
					case evt.KEY_LEFT_ARROW:
6574
					case evt.KEY_LEFT_ARROW:
6538
					case evt.KEY_UP_ARROW:
6575
					case evt.KEY_UP_ARROW:
6539
					case evt.KEY_RIGHT_ARROW:
6576
					case evt.KEY_RIGHT_ARROW:
6540
					case evt.KEY_DOWN_ARROW:
6577
					case evt.KEY_DOWN_ARROW:
6541
					case evt.KEY_INSERT:
6578
					case evt.KEY_INSERT:
6542
					case evt.KEY_DELETE:
6579
					case evt.KEY_DELETE:
6543
					case evt.KEY_F1:
6580
					case evt.KEY_F1:
6544
					case evt.KEY_F2:
6581
					case evt.KEY_F2:
6545
					case evt.KEY_F3:
6582
					case evt.KEY_F3:
6546
					case evt.KEY_F4:
6583
					case evt.KEY_F4:
6547
					case evt.KEY_F5:
6584
					case evt.KEY_F5:
6548
					case evt.KEY_F6:
6585
					case evt.KEY_F6:
6549
					case evt.KEY_F7:
6586
					case evt.KEY_F7:
6550
					case evt.KEY_F8:
6587
					case evt.KEY_F8:
6551
					case evt.KEY_F9:
6588
					case evt.KEY_F9:
6552
					case evt.KEY_F10:
6589
					case evt.KEY_F10:
6553
					case evt.KEY_F11:
6590
					case evt.KEY_F11:
6554
					case evt.KEY_F12:
6591
					case evt.KEY_F12:
6555
					case evt.KEY_F12:
6592
					case evt.KEY_F12:
6556
					case evt.KEY_F13:
6593
					case evt.KEY_F13:
6557
					case evt.KEY_F14:
6594
					case evt.KEY_F14:
6558
					case evt.KEY_F15:
6595
					case evt.KEY_F15:
6559
					case evt.KEY_CLEAR:
6596
					case evt.KEY_CLEAR:
6560
					case evt.KEY_HELP:
6597
					case evt.KEY_HELP:
6561
						evt.key = evt.keyCode;
6598
						evt.key = evt.keyCode;
6562
						break;
6599
						break;
6563
					default:
6600
					default:
6564
						if(evt.ctrlKey || evt.altKey){
6601
						if(evt.ctrlKey || evt.altKey){
6565
							var unifiedCharCode = evt.keyCode;
6602
							var unifiedCharCode = evt.keyCode;
6566
							// if lower case but keycode is uppercase, convert it
6603
							// if lower case but keycode is uppercase, convert it
6567
							if(unifiedCharCode >= 65 && unifiedCharCode <= 90 && evt.shiftKey == false){
6604
							if(unifiedCharCode >= 65 && unifiedCharCode <= 90 && evt.shiftKey == false){
6568
								unifiedCharCode += 32;
6605
								unifiedCharCode += 32;
6569
							}
6606
							}
6570
							if(unifiedCharCode >= 1 && unifiedCharCode <= 26 && evt.ctrlKey){
6607
							if(unifiedCharCode >= 1 && unifiedCharCode <= 26 && evt.ctrlKey){
6571
								unifiedCharCode += 96; // 001-032 = ctrl+[a-z]
6608
								unifiedCharCode += 96; // 001-032 = ctrl+[a-z]
6572
							}
6609
							}
6573
							evt.key = String.fromCharCode(unifiedCharCode);
6610
							evt.key = String.fromCharCode(unifiedCharCode);
6574
						}
6611
						}
6575
				}
6612
				}
6576
			} else if(evt["type"] == "keypress"){
6613
			} else if(evt["type"] == "keypress"){
6577
				if(dojo.render.html.opera){
6614
				if(dojo.render.html.opera){
6578
					if(evt.which == 0){
6615
					if(evt.which == 0){
6579
						evt.key = evt.keyCode;
6616
						evt.key = evt.keyCode;
6580
					}else if(evt.which > 0){
6617
					}else if(evt.which > 0){
6581
						switch(evt.which){
6618
						switch(evt.which){
6582
							case evt.KEY_SHIFT:
6619
							case evt.KEY_SHIFT:
6583
							case evt.KEY_CTRL:
6620
							case evt.KEY_CTRL:
6584
							case evt.KEY_ALT:
6621
							case evt.KEY_ALT:
6585
							case evt.KEY_CAPS_LOCK:
6622
							case evt.KEY_CAPS_LOCK:
6586
							case evt.KEY_NUM_LOCK:
6623
							case evt.KEY_NUM_LOCK:
6587
							case evt.KEY_SCROLL_LOCK:
6624
							case evt.KEY_SCROLL_LOCK:
6588
								break;
6625
								break;
6589
							case evt.KEY_PAUSE:
6626
							case evt.KEY_PAUSE:
6590
							case evt.KEY_TAB:
6627
							case evt.KEY_TAB:
6591
							case evt.KEY_BACKSPACE:
6628
							case evt.KEY_BACKSPACE:
6592
							case evt.KEY_ENTER:
6629
							case evt.KEY_ENTER:
6593
							case evt.KEY_ESCAPE:
6630
							case evt.KEY_ESCAPE:
6594
								evt.key = evt.which;
6631
								evt.key = evt.which;
6595
								break;
6632
								break;
6596
							default:
6633
							default:
6597
								var unifiedCharCode = evt.which;
6634
								var unifiedCharCode = evt.which;
6598
								if((evt.ctrlKey || evt.altKey || evt.metaKey) && (evt.which >= 65 && evt.which <= 90 && evt.shiftKey == false)){
6635
								if((evt.ctrlKey || evt.altKey || evt.metaKey) && (evt.which >= 65 && evt.which <= 90 && evt.shiftKey == false)){
6599
									unifiedCharCode += 32;
6636
									unifiedCharCode += 32;
6600
								}
6637
								}
6601
								evt.key = String.fromCharCode(unifiedCharCode);
6638
								evt.key = String.fromCharCode(unifiedCharCode);
6602
						}
6639
						}
6603
					}
6640
					}
6604
				}else if(dojo.render.html.ie){ // catch some IE keys that are hard to get in keyDown
6641
				}else if(dojo.render.html.ie){ // catch some IE keys that are hard to get in keyDown
6605
					// key combinations were handled in onKeyDown
6642
					// key combinations were handled in onKeyDown
6606
					if(!evt.ctrlKey && !evt.altKey && evt.keyCode >= evt.KEY_SPACE){
6643
					if(!evt.ctrlKey && !evt.altKey && evt.keyCode >= evt.KEY_SPACE){
6607
						evt.key = String.fromCharCode(evt.keyCode);
6644
						evt.key = String.fromCharCode(evt.keyCode);
6608
					}
6645
					}
6609
				}else if(dojo.render.html.safari){
6646
				}else if(dojo.render.html.safari){
6610
					switch(evt.keyCode){
6647
					switch(evt.keyCode){
6611
						case 25: evt.key = evt.KEY_TAB; evt.shift = true;break;
6648
						case 25: evt.key = evt.KEY_TAB; evt.shift = true;break;
6612
						case 63232: evt.key = evt.KEY_UP_ARROW; break;
6649
						case 63232: evt.key = evt.KEY_UP_ARROW; break;
6613
						case 63233: evt.key = evt.KEY_DOWN_ARROW; break;
6650
						case 63233: evt.key = evt.KEY_DOWN_ARROW; break;
6614
						case 63234: evt.key = evt.KEY_LEFT_ARROW; break;
6651
						case 63234: evt.key = evt.KEY_LEFT_ARROW; break;
6615
						case 63235: evt.key = evt.KEY_RIGHT_ARROW; break;
6652
						case 63235: evt.key = evt.KEY_RIGHT_ARROW; break;
6616
						case 63236: evt.key = evt.KEY_F1; break;
6653
						case 63236: evt.key = evt.KEY_F1; break;
6617
						case 63237: evt.key = evt.KEY_F2; break;
6654
						case 63237: evt.key = evt.KEY_F2; break;
6618
						case 63238: evt.key = evt.KEY_F3; break;
6655
						case 63238: evt.key = evt.KEY_F3; break;
6619
						case 63239: evt.key = evt.KEY_F4; break;
6656
						case 63239: evt.key = evt.KEY_F4; break;
6620
						case 63240: evt.key = evt.KEY_F5; break;
6657
						case 63240: evt.key = evt.KEY_F5; break;
6621
						case 63241: evt.key = evt.KEY_F6; break;
6658
						case 63241: evt.key = evt.KEY_F6; break;
6622
						case 63242: evt.key = evt.KEY_F7; break;
6659
						case 63242: evt.key = evt.KEY_F7; break;
6623
						case 63243: evt.key = evt.KEY_F8; break;
6660
						case 63243: evt.key = evt.KEY_F8; break;
6624
						case 63244: evt.key = evt.KEY_F9; break;
6661
						case 63244: evt.key = evt.KEY_F9; break;
6625
						case 63245: evt.key = evt.KEY_F10; break;
6662
						case 63245: evt.key = evt.KEY_F10; break;
6626
						case 63246: evt.key = evt.KEY_F11; break;
6663
						case 63246: evt.key = evt.KEY_F11; break;
6627
						case 63247: evt.key = evt.KEY_F12; break;
6664
						case 63247: evt.key = evt.KEY_F12; break;
6628
						case 63250: evt.key = evt.KEY_PAUSE; break;
6665
						case 63250: evt.key = evt.KEY_PAUSE; break;
6629
						case 63272: evt.key = evt.KEY_DELETE; break;
6666
						case 63272: evt.key = evt.KEY_DELETE; break;
6630
						case 63273: evt.key = evt.KEY_HOME; break;
6667
						case 63273: evt.key = evt.KEY_HOME; break;
6631
						case 63275: evt.key = evt.KEY_END; break;
6668
						case 63275: evt.key = evt.KEY_END; break;
6632
						case 63276: evt.key = evt.KEY_PAGE_UP; break;
6669
						case 63276: evt.key = evt.KEY_PAGE_UP; break;
6633
						case 63277: evt.key = evt.KEY_PAGE_DOWN; break;
6670
						case 63277: evt.key = evt.KEY_PAGE_DOWN; break;
6634
						case 63302: evt.key = evt.KEY_INSERT; break;
6671
						case 63302: evt.key = evt.KEY_INSERT; break;
6635
						case 63248://prtscr
6672
						case 63248://prtscr
6636
						case 63249://scrolllock
6673
						case 63249://scrolllock
6637
						case 63289://numlock
6674
						case 63289://numlock
6638
							break;
6675
							break;
6639
						default: 
6676
						default: 
6640
							evt.key = evt.charCode >= evt.KEY_SPACE ? String.fromCharCode(evt.charCode) : evt.keyCode;
6677
							evt.key = evt.charCode >= evt.KEY_SPACE ? String.fromCharCode(evt.charCode) : evt.keyCode;
6641
					}
6678
					}
6642
				}else{
6679
				}else{
6643
					evt.key = evt.charCode > 0 ? String.fromCharCode(evt.charCode) : evt.keyCode;
6680
					evt.key = evt.charCode > 0 ? String.fromCharCode(evt.charCode) : evt.keyCode;
6644
				}
6681
				}
6645
			}
6682
			}
6646
		}
6683
		}
6647
		if(dojo.render.html.ie){
6684
		if(dojo.render.html.ie){
6648
			if(!evt.target){ evt.target = evt.srcElement; }
6685
			if(!evt.target){ evt.target = evt.srcElement; }
6649
			if(!evt.currentTarget){ evt.currentTarget = (sender ? sender : evt.srcElement); }
6686
			if(!evt.currentTarget){ evt.currentTarget = (sender ? sender : evt.srcElement); }
6650
			if(!evt.layerX){ evt.layerX = evt.offsetX; }
6687
			if(!evt.layerX){ evt.layerX = evt.offsetX; }
6651
			if(!evt.layerY){ evt.layerY = evt.offsetY; }
6688
			if(!evt.layerY){ evt.layerY = evt.offsetY; }
6652
			// FIXME: scroll position query is duped from dojo.html to avoid dependency on that entire module
6689
			// FIXME: scroll position query is duped from dojo.html to avoid dependency on that entire module
6653
			// DONOT replace the following to use dojo.body(), in IE, document.documentElement should be used
6690
			// DONOT replace the following to use dojo.body(), in IE, document.documentElement should be used
6654
			// here rather than document.body
6691
			// here rather than document.body
6655
			var doc = (evt.srcElement && evt.srcElement.ownerDocument) ? evt.srcElement.ownerDocument : document;
6692
			var doc = (evt.srcElement && evt.srcElement.ownerDocument) ? evt.srcElement.ownerDocument : document;
6656
			var docBody = ((dojo.render.html.ie55)||(doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
6693
			var docBody = ((dojo.render.html.ie55)||(doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
6657
			if(!evt.pageX){ evt.pageX = evt.clientX + (docBody.scrollLeft || 0) }
6694
			if(!evt.pageX){ evt.pageX = evt.clientX + (docBody.scrollLeft || 0) }
6658
			if(!evt.pageY){ evt.pageY = evt.clientY + (docBody.scrollTop || 0) }
6695
			if(!evt.pageY){ evt.pageY = evt.clientY + (docBody.scrollTop || 0) }
6659
			// mouseover
6696
			// mouseover
6660
			if(evt.type == "mouseover"){ evt.relatedTarget = evt.fromElement; }
6697
			if(evt.type == "mouseover"){ evt.relatedTarget = evt.fromElement; }
6661
			// mouseout
6698
			// mouseout
6662
			if(evt.type == "mouseout"){ evt.relatedTarget = evt.toElement; }
6699
			if(evt.type == "mouseout"){ evt.relatedTarget = evt.toElement; }
6663
			this.currentEvent = evt;
6700
			this.currentEvent = evt;
6664
			evt.callListener = this.callListener;
6701
			evt.callListener = this.callListener;
6665
			evt.stopPropagation = this._stopPropagation;
6702
			evt.stopPropagation = this._stopPropagation;
6666
			evt.preventDefault = this._preventDefault;
6703
			evt.preventDefault = this._preventDefault;
6667
		}
6704
		}
6668
		return evt; // Event
6705
		return evt; // Event
6669
	}
6706
	}
6670
 
6707
 
6671
	this.stopEvent = function(/*Event*/evt){
6708
	this.stopEvent = function(/*Event*/evt){
6672
		// summary:
6709
		// summary:
6673
		//		prevents propigation and clobbers the default action of the
6710
		//		prevents propigation and clobbers the default action of the
6674
		//		passed event
6711
		//		passed event
6675
		// evt: Optional for IE. The native event object.
6712
		// evt: Optional for IE. The native event object.
6676
		if(window.event){
6713
		if(window.event){
6677
			evt.cancelBubble = true;
6714
			evt.cancelBubble = true;
6678
			evt.returnValue = false;
6715
			evt.returnValue = false;
6679
		}else{
6716
		}else{
6680
			evt.preventDefault();
6717
			evt.preventDefault();
6681
			evt.stopPropagation();
6718
			evt.stopPropagation();
6682
		}
6719
		}
6683
	}
6720
	}
6684
}
6721
}
6685
 
6722
 
6686
dojo.kwCompoundRequire({
6723
dojo.kwCompoundRequire({
6687
	common: ["dojo.event.common", "dojo.event.topic"],
6724
	common: ["dojo.event.common", "dojo.event.topic"],
6688
	browser: ["dojo.event.browser"],
6725
	browser: ["dojo.event.browser"],
6689
	dashboard: ["dojo.event.browser"]
6726
	dashboard: ["dojo.event.browser"]
6690
});
6727
});
6691
dojo.provide("dojo.event.*");
6728
dojo.provide("dojo.event.*");
6692
 
6729
 
6693
dojo.provide("dojo.gfx.color");
6730
dojo.provide("dojo.gfx.color");
6694
 
6731
 
6695
 
6732
 
6696
 
6733
 
6697
// TODO: rewrite the "x2y" methods to take advantage of the parsing
6734
// TODO: rewrite the "x2y" methods to take advantage of the parsing
6698
//       abilities of the Color object. Also, beef up the Color
6735
//       abilities of the Color object. Also, beef up the Color
6699
//       object (as possible) to parse most common formats
6736
//       object (as possible) to parse most common formats
6700
 
6737
 
6701
// takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa)
6738
// takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa)
6702
dojo.gfx.color.Color = function(r, g, b, a) {
6739
dojo.gfx.color.Color = function(r, g, b, a) {
6703
	// dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]);
6740
	// dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]);
6704
	if(dojo.lang.isArray(r)){
6741
	if(dojo.lang.isArray(r)){
6705
		this.r = r[0];
6742
		this.r = r[0];
6706
		this.g = r[1];
6743
		this.g = r[1];
6707
		this.b = r[2];
6744
		this.b = r[2];
6708
		this.a = r[3]||1.0;
6745
		this.a = r[3]||1.0;
6709
	}else if(dojo.lang.isString(r)){
6746
	}else if(dojo.lang.isString(r)){
6710
		var rgb = dojo.gfx.color.extractRGB(r);
6747
		var rgb = dojo.gfx.color.extractRGB(r);
6711
		this.r = rgb[0];
6748
		this.r = rgb[0];
6712
		this.g = rgb[1];
6749
		this.g = rgb[1];
6713
		this.b = rgb[2];
6750
		this.b = rgb[2];
6714
		this.a = g||1.0;
6751
		this.a = g||1.0;
6715
	}else if(r instanceof dojo.gfx.color.Color){
6752
	}else if(r instanceof dojo.gfx.color.Color){
6716
		// why does this create a new instance if we were passed one?
6753
		// why does this create a new instance if we were passed one?
6717
		this.r = r.r;
6754
		this.r = r.r;
6718
		this.b = r.b;
6755
		this.b = r.b;
6719
		this.g = r.g;
6756
		this.g = r.g;
6720
		this.a = r.a;
6757
		this.a = r.a;
6721
	}else{
6758
	}else{
6722
		this.r = r;
6759
		this.r = r;
6723
		this.g = g;
6760
		this.g = g;
6724
		this.b = b;
6761
		this.b = b;
6725
		this.a = a;
6762
		this.a = a;
6726
	}
6763
	}
6727
}
6764
}
6728
 
6765
 
6729
dojo.gfx.color.Color.fromArray = function(arr) {
6766
dojo.gfx.color.Color.fromArray = function(arr) {
6730
	return new dojo.gfx.color.Color(arr[0], arr[1], arr[2], arr[3]);
6767
	return new dojo.gfx.color.Color(arr[0], arr[1], arr[2], arr[3]);
6731
}
6768
}
6732
 
6769
 
6733
dojo.extend(dojo.gfx.color.Color, {
6770
dojo.extend(dojo.gfx.color.Color, {
6734
	toRgb: function(includeAlpha) {
6771
	toRgb: function(includeAlpha) {
6735
		if(includeAlpha) {
6772
		if(includeAlpha) {
6736
			return this.toRgba();
6773
			return this.toRgba();
6737
		} else {
6774
		} else {
6738
			return [this.r, this.g, this.b];
6775
			return [this.r, this.g, this.b];
6739
		}
6776
		}
6740
	},
6777
	},
6741
	toRgba: function() {
6778
	toRgba: function() {
6742
		return [this.r, this.g, this.b, this.a];
6779
		return [this.r, this.g, this.b, this.a];
6743
	},
6780
	},
6744
	toHex: function() {
6781
	toHex: function() {
6745
		return dojo.gfx.color.rgb2hex(this.toRgb());
6782
		return dojo.gfx.color.rgb2hex(this.toRgb());
6746
	},
6783
	},
6747
	toCss: function() {
6784
	toCss: function() {
6748
		return "rgb(" + this.toRgb().join() + ")";
6785
		return "rgb(" + this.toRgb().join() + ")";
6749
	},
6786
	},
6750
	toString: function() {
6787
	toString: function() {
6751
		return this.toHex(); // decent default?
6788
		return this.toHex(); // decent default?
6752
	},
6789
	},
6753
	blend: function(color, weight){
6790
	blend: function(color, weight){
6754
		var rgb = null;
6791
		var rgb = null;
6755
		if(dojo.lang.isArray(color)){
6792
		if(dojo.lang.isArray(color)){
6756
			rgb = color;
6793
			rgb = color;
6757
		}else if(color instanceof dojo.gfx.color.Color){
6794
		}else if(color instanceof dojo.gfx.color.Color){
6758
			rgb = color.toRgb();
6795
			rgb = color.toRgb();
6759
		}else{
6796
		}else{
6760
			rgb = new dojo.gfx.color.Color(color).toRgb();
6797
			rgb = new dojo.gfx.color.Color(color).toRgb();
6761
		}
6798
		}
6762
		return dojo.gfx.color.blend(this.toRgb(), rgb, weight);
6799
		return dojo.gfx.color.blend(this.toRgb(), rgb, weight);
6763
	}
6800
	}
6764
});
6801
});
6765
 
6802
 
6766
dojo.gfx.color.named = {
6803
dojo.gfx.color.named = {
6767
	white:      [255,255,255],
6804
	white:      [255,255,255],
6768
	black:      [0,0,0],
6805
	black:      [0,0,0],
6769
	red:        [255,0,0],
6806
	red:        [255,0,0],
6770
	green:	    [0,255,0],
6807
	green:	    [0,255,0],
6771
	lime:	    [0,255,0],
6808
	lime:	    [0,255,0],
6772
	blue:       [0,0,255],
6809
	blue:       [0,0,255],
6773
	navy:       [0,0,128],
6810
	navy:       [0,0,128],
6774
	gray:       [128,128,128],
6811
	gray:       [128,128,128],
6775
	silver:     [192,192,192]
6812
	silver:     [192,192,192]
6776
};
6813
};
6777
 
6814
 
6778
dojo.gfx.color.blend = function(a, b, weight){
6815
dojo.gfx.color.blend = function(a, b, weight){
6779
	// summary: 
6816
	// summary: 
6780
	//		blend colors a and b (both as RGB array or hex strings) with weight
6817
	//		blend colors a and b (both as RGB array or hex strings) with weight
6781
	//		from -1 to +1, 0 being a 50/50 blend
6818
	//		from -1 to +1, 0 being a 50/50 blend
6782
	if(typeof a == "string"){
6819
	if(typeof a == "string"){
6783
		return dojo.gfx.color.blendHex(a, b, weight);
6820
		return dojo.gfx.color.blendHex(a, b, weight);
6784
	}
6821
	}
6785
	if(!weight){
6822
	if(!weight){
6786
		weight = 0;
6823
		weight = 0;
6787
	}
6824
	}
6788
	weight = Math.min(Math.max(-1, weight), 1);
6825
	weight = Math.min(Math.max(-1, weight), 1);
6789
 
6826
 
6790
	// alex: this interface blows.
6827
	// alex: this interface blows.
6791
	// map -1 to 1 to the range 0 to 1
6828
	// map -1 to 1 to the range 0 to 1
6792
	weight = ((weight + 1)/2);
6829
	weight = ((weight + 1)/2);
6793
	
6830
	
6794
	var c = [];
6831
	var c = [];
6795
 
6832
 
6796
	// var stop = (1000*weight);
6833
	// var stop = (1000*weight);
6797
	for(var x = 0; x < 3; x++){
6834
	for(var x = 0; x < 3; x++){
6798
		c[x] = parseInt( b[x] + ( (a[x] - b[x]) * weight) );
6835
		c[x] = parseInt( b[x] + ( (a[x] - b[x]) * weight) );
6799
	}
6836
	}
6800
	return c;
6837
	return c;
6801
}
6838
}
6802
 
6839
 
6803
// very convenient blend that takes and returns hex values
6840
// very convenient blend that takes and returns hex values
6804
// (will get called automatically by blend when blend gets strings)
6841
// (will get called automatically by blend when blend gets strings)
6805
dojo.gfx.color.blendHex = function(a, b, weight) {
6842
dojo.gfx.color.blendHex = function(a, b, weight) {
6806
	return dojo.gfx.color.rgb2hex(dojo.gfx.color.blend(dojo.gfx.color.hex2rgb(a), dojo.gfx.color.hex2rgb(b), weight));
6843
	return dojo.gfx.color.rgb2hex(dojo.gfx.color.blend(dojo.gfx.color.hex2rgb(a), dojo.gfx.color.hex2rgb(b), weight));
6807
}
6844
}
6808
 
6845
 
6809
// get RGB array from css-style color declarations
6846
// get RGB array from css-style color declarations
6810
dojo.gfx.color.extractRGB = function(color) {
6847
dojo.gfx.color.extractRGB = function(color) {
6811
	var hex = "0123456789abcdef";
6848
	var hex = "0123456789abcdef";
6812
	color = color.toLowerCase();
6849
	color = color.toLowerCase();
6813
	if( color.indexOf("rgb") == 0 ) {
6850
	if( color.indexOf("rgb") == 0 ) {
6814
		var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
6851
		var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
6815
		var ret = matches.splice(1, 3);
6852
		var ret = matches.splice(1, 3);
6816
		return ret;
6853
		return ret;
6817
	} else {
6854
	} else {
6818
		var colors = dojo.gfx.color.hex2rgb(color);
6855
		var colors = dojo.gfx.color.hex2rgb(color);
6819
		if(colors) {
6856
		if(colors) {
6820
			return colors;
6857
			return colors;
6821
		} else {
6858
		} else {
6822
			// named color (how many do we support?)
6859
			// named color (how many do we support?)
6823
			return dojo.gfx.color.named[color] || [255, 255, 255];
6860
			return dojo.gfx.color.named[color] || [255, 255, 255];
6824
		}
6861
		}
6825
	}
6862
	}
6826
}
6863
}
6827
 
6864
 
6828
dojo.gfx.color.hex2rgb = function(hex) {
6865
dojo.gfx.color.hex2rgb = function(hex) {
6829
	var hexNum = "0123456789ABCDEF";
6866
	var hexNum = "0123456789ABCDEF";
6830
	var rgb = new Array(3);
6867
	var rgb = new Array(3);
6831
	if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); }
6868
	if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); }
6832
	hex = hex.toUpperCase();
6869
	hex = hex.toUpperCase();
6833
	if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") {
6870
	if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") {
6834
		return null;
6871
		return null;
6835
	}
6872
	}
6836
	if( hex.length == 3 ) {
6873
	if( hex.length == 3 ) {
6837
		rgb[0] = hex.charAt(0) + hex.charAt(0)
6874
		rgb[0] = hex.charAt(0) + hex.charAt(0)
6838
		rgb[1] = hex.charAt(1) + hex.charAt(1)
6875
		rgb[1] = hex.charAt(1) + hex.charAt(1)
6839
		rgb[2] = hex.charAt(2) + hex.charAt(2);
6876
		rgb[2] = hex.charAt(2) + hex.charAt(2);
6840
	} else {
6877
	} else {
6841
		rgb[0] = hex.substring(0, 2);
6878
		rgb[0] = hex.substring(0, 2);
6842
		rgb[1] = hex.substring(2, 4);
6879
		rgb[1] = hex.substring(2, 4);
6843
		rgb[2] = hex.substring(4);
6880
		rgb[2] = hex.substring(4);
6844
	}
6881
	}
6845
	for(var i = 0; i < rgb.length; i++) {
6882
	for(var i = 0; i < rgb.length; i++) {
6846
		rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1));
6883
		rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1));
6847
	}
6884
	}
6848
	return rgb;
6885
	return rgb;
6849
}
6886
}
6850
 
6887
 
6851
dojo.gfx.color.rgb2hex = function(r, g, b) {
6888
dojo.gfx.color.rgb2hex = function(r, g, b) {
6852
	if(dojo.lang.isArray(r)) {
6889
	if(dojo.lang.isArray(r)) {
6853
		g = r[1] || 0;
6890
		g = r[1] || 0;
6854
		b = r[2] || 0;
6891
		b = r[2] || 0;
6855
		r = r[0] || 0;
6892
		r = r[0] || 0;
6856
	}
6893
	}
6857
	var ret = dojo.lang.map([r, g, b], function(x) {
6894
	var ret = dojo.lang.map([r, g, b], function(x) {
6858
		x = new Number(x);
6895
		x = new Number(x);
6859
		var s = x.toString(16);
6896
		var s = x.toString(16);
6860
		while(s.length < 2) { s = "0" + s; }
6897
		while(s.length < 2) { s = "0" + s; }
6861
		return s;
6898
		return s;
6862
	});
6899
	});
6863
	ret.unshift("#");
6900
	ret.unshift("#");
6864
	return ret.join("");
6901
	return ret.join("");
6865
}
6902
}
6866
 
6903
 
6867
dojo.provide("dojo.lfx.Animation");
6904
dojo.provide("dojo.lfx.Animation");
6868
 
6905
 
6869
 
6906
 
6870
 
6907
 
6871
/*
6908
/*
6872
	Animation package based on Dan Pupius' work: http://pupius.co.uk/js/Toolkit.Drawing.js
6909
	Animation package based on Dan Pupius' work: http://pupius.co.uk/js/Toolkit.Drawing.js
6873
*/
6910
*/
6874
dojo.lfx.Line = function(/*int*/ start, /*int*/ end){
6911
dojo.lfx.Line = function(/*int*/ start, /*int*/ end){
6875
	// summary: dojo.lfx.Line is the object used to generate values
6912
	// summary: dojo.lfx.Line is the object used to generate values
6876
	//			from a start value to an end value
6913
	//			from a start value to an end value
6877
	this.start = start;
6914
	this.start = start;
6878
	this.end = end;
6915
	this.end = end;
6879
	if(dojo.lang.isArray(start)){
6916
	if(dojo.lang.isArray(start)){
6880
		/* start: Array
6917
		/* start: Array
6881
		   end: Array
6918
		   end: Array
6882
		   pId: a */
6919
		   pId: a */
6883
		var diff = [];
6920
		var diff = [];
6884
		dojo.lang.forEach(this.start, function(s,i){
6921
		dojo.lang.forEach(this.start, function(s,i){
6885
			diff[i] = this.end[i] - s;
6922
			diff[i] = this.end[i] - s;
6886
		}, this);
6923
		}, this);
6887
		
6924
		
6888
		this.getValue = function(/*float*/ n){
6925
		this.getValue = function(/*float*/ n){
6889
			var res = [];
6926
			var res = [];
6890
			dojo.lang.forEach(this.start, function(s, i){
6927
			dojo.lang.forEach(this.start, function(s, i){
6891
				res[i] = (diff[i] * n) + s;
6928
				res[i] = (diff[i] * n) + s;
6892
			}, this);
6929
			}, this);
6893
			return res; // Array
6930
			return res; // Array
6894
		}
6931
		}
6895
	}else{
6932
	}else{
6896
		var diff = end - start;
6933
		var diff = end - start;
6897
			
6934
			
6898
		this.getValue = function(/*float*/ n){
6935
		this.getValue = function(/*float*/ n){
6899
			//	summary: returns the point on the line
6936
			//	summary: returns the point on the line
6900
			//	n: a floating point number greater than 0 and less than 1
6937
			//	n: a floating point number greater than 0 and less than 1
6901
			return (diff * n) + this.start; // Decimal
6938
			return (diff * n) + this.start; // Decimal
6902
		}
6939
		}
6903
	}
6940
	}
6904
}
6941
}
6905
 
6942
 
6906
if((dojo.render.html.khtml)&&(!dojo.render.html.safari)){
6943
if((dojo.render.html.khtml)&&(!dojo.render.html.safari)){
6907
	// the cool kids are obviously not using konqueror...
6944
	// the cool kids are obviously not using konqueror...
6908
	// found a very wierd bug in floats constants, 1.5 evals as 1
6945
	// found a very wierd bug in floats constants, 1.5 evals as 1
6909
	// seems somebody mixed up ints and floats in 3.5.4 ??
6946
	// seems somebody mixed up ints and floats in 3.5.4 ??
6910
	// FIXME: investigate more and post a KDE bug (Fredrik)
6947
	// FIXME: investigate more and post a KDE bug (Fredrik)
6911
	dojo.lfx.easeDefault = function(/*Decimal?*/ n){
6948
	dojo.lfx.easeDefault = function(/*Decimal?*/ n){
6912
		//	summary: Returns the point for point n on a sin wave.
6949
		//	summary: Returns the point for point n on a sin wave.
6913
		return (parseFloat("0.5")+((Math.sin( (n+parseFloat("1.5")) * Math.PI))/2));
6950
		return (parseFloat("0.5")+((Math.sin( (n+parseFloat("1.5")) * Math.PI))/2));
6914
	}
6951
	}
6915
}else{
6952
}else{
6916
	dojo.lfx.easeDefault = function(/*Decimal?*/ n){
6953
	dojo.lfx.easeDefault = function(/*Decimal?*/ n){
6917
		return (0.5+((Math.sin( (n+1.5) * Math.PI))/2));
6954
		return (0.5+((Math.sin( (n+1.5) * Math.PI))/2));
6918
	}
6955
	}
6919
}
6956
}
6920
 
6957
 
6921
dojo.lfx.easeIn = function(/*Decimal?*/ n){
6958
dojo.lfx.easeIn = function(/*Decimal?*/ n){
6922
	//	summary: returns the point on an easing curve
6959
	//	summary: returns the point on an easing curve
6923
	//	n: a floating point number greater than 0 and less than 1
6960
	//	n: a floating point number greater than 0 and less than 1
6924
	return Math.pow(n, 3);
6961
	return Math.pow(n, 3);
6925
}
6962
}
6926
 
6963
 
6927
dojo.lfx.easeOut = function(/*Decimal?*/ n){
6964
dojo.lfx.easeOut = function(/*Decimal?*/ n){
6928
	//	summary: returns the point on the line
6965
	//	summary: returns the point on the line
6929
	//	n: a floating point number greater than 0 and less than 1
6966
	//	n: a floating point number greater than 0 and less than 1
6930
	return ( 1 - Math.pow(1 - n, 3) );
6967
	return ( 1 - Math.pow(1 - n, 3) );
6931
}
6968
}
6932
 
6969
 
6933
dojo.lfx.easeInOut = function(/*Decimal?*/ n){
6970
dojo.lfx.easeInOut = function(/*Decimal?*/ n){
6934
	//	summary: returns the point on the line
6971
	//	summary: returns the point on the line
6935
	//	n: a floating point number greater than 0 and less than 1
6972
	//	n: a floating point number greater than 0 and less than 1
6936
	return ( (3 * Math.pow(n, 2)) - (2 * Math.pow(n, 3)) );
6973
	return ( (3 * Math.pow(n, 2)) - (2 * Math.pow(n, 3)) );
6937
}
6974
}
6938
 
6975
 
6939
dojo.lfx.IAnimation = function(){
6976
dojo.lfx.IAnimation = function(){
6940
	// summary: dojo.lfx.IAnimation is an interface that implements
6977
	// summary: dojo.lfx.IAnimation is an interface that implements
6941
	//			commonly used functions of animation objects
6978
	//			commonly used functions of animation objects
6942
}
6979
}
6943
dojo.lang.extend(dojo.lfx.IAnimation, {
6980
dojo.lang.extend(dojo.lfx.IAnimation, {
6944
	// public properties
6981
	// public properties
6945
	curve: null,
6982
	curve: null,
6946
	duration: 1000,
6983
	duration: 1000,
6947
	easing: null,
6984
	easing: null,
6948
	repeatCount: 0,
6985
	repeatCount: 0,
6949
	rate: 10,
6986
	rate: 10,
6950
	
6987
	
6951
	// events
6988
	// events
6952
	handler: null,
6989
	handler: null,
6953
	beforeBegin: null,
6990
	beforeBegin: null,
6954
	onBegin: null,
6991
	onBegin: null,
6955
	onAnimate: null,
6992
	onAnimate: null,
6956
	onEnd: null,
6993
	onEnd: null,
6957
	onPlay: null,
6994
	onPlay: null,
6958
	onPause: null,
6995
	onPause: null,
6959
	onStop: null,
6996
	onStop: null,
6960
	
6997
	
6961
	// public methods
6998
	// public methods
6962
	play: null,
6999
	play: null,
6963
	pause: null,
7000
	pause: null,
6964
	stop: null,
7001
	stop: null,
6965
	
7002
	
6966
	connect: function(/*Event*/ evt, /*Object*/ scope, /*Function*/ newFunc){
7003
	connect: function(/*Event*/ evt, /*Object*/ scope, /*Function*/ newFunc){
6967
		// summary: Convenience function.  Quickly connect to an event
7004
		// summary: Convenience function.  Quickly connect to an event
6968
		//			of this object and save the old functions connected to it.
7005
		//			of this object and save the old functions connected to it.
6969
		// evt: The name of the event to connect to.
7006
		// evt: The name of the event to connect to.
6970
		// scope: the scope in which to run newFunc.
7007
		// scope: the scope in which to run newFunc.
6971
		// newFunc: the function to run when evt is fired.
7008
		// newFunc: the function to run when evt is fired.
6972
		if(!newFunc){
7009
		if(!newFunc){
6973
			/* scope: Function
7010
			/* scope: Function
6974
			   newFunc: null
7011
			   newFunc: null
6975
			   pId: f */
7012
			   pId: f */
6976
			newFunc = scope;
7013
			newFunc = scope;
6977
			scope = this;
7014
			scope = this;
6978
		}
7015
		}
6979
		newFunc = dojo.lang.hitch(scope, newFunc);
7016
		newFunc = dojo.lang.hitch(scope, newFunc);
6980
		var oldFunc = this[evt]||function(){};
7017
		var oldFunc = this[evt]||function(){};
6981
		this[evt] = function(){
7018
		this[evt] = function(){
6982
			var ret = oldFunc.apply(this, arguments);
7019
			var ret = oldFunc.apply(this, arguments);
6983
			newFunc.apply(this, arguments);
7020
			newFunc.apply(this, arguments);
6984
			return ret;
7021
			return ret;
6985
		}
7022
		}
6986
		return this; // dojo.lfx.IAnimation
7023
		return this; // dojo.lfx.IAnimation
6987
	},
7024
	},
6988
 
7025
 
6989
	fire: function(/*Event*/ evt, /*Array*/ args){
7026
	fire: function(/*Event*/ evt, /*Array*/ args){
6990
		// summary: Convenience function.  Fire event "evt" and pass it
7027
		// summary: Convenience function.  Fire event "evt" and pass it
6991
		//			the arguments specified in "args".
7028
		//			the arguments specified in "args".
6992
		// evt: The event to fire.
7029
		// evt: The event to fire.
6993
		// args: The arguments to pass to the event.
7030
		// args: The arguments to pass to the event.
6994
		if(this[evt]){
7031
		if(this[evt]){
6995
			this[evt].apply(this, (args||[]));
7032
			this[evt].apply(this, (args||[]));
6996
		}
7033
		}
6997
		return this; // dojo.lfx.IAnimation
7034
		return this; // dojo.lfx.IAnimation
6998
	},
7035
	},
6999
	
7036
	
7000
	repeat: function(/*int*/ count){
7037
	repeat: function(/*int*/ count){
7001
		// summary: Set the repeat count of this object.
7038
		// summary: Set the repeat count of this object.
7002
		// count: How many times to repeat the animation.
7039
		// count: How many times to repeat the animation.
7003
		this.repeatCount = count;
7040
		this.repeatCount = count;
7004
		return this; // dojo.lfx.IAnimation
7041
		return this; // dojo.lfx.IAnimation
7005
	},
7042
	},
7006
 
7043
 
7007
	// private properties
7044
	// private properties
7008
	_active: false,
7045
	_active: false,
7009
	_paused: false
7046
	_paused: false
7010
});
7047
});
7011
 
7048
 
7012
dojo.lfx.Animation = function(	/*Object*/ handlers, 
7049
dojo.lfx.Animation = function(	/*Object*/ handlers, 
7013
								/*int*/ duration, 
7050
								/*int*/ duration, 
7014
								/*dojo.lfx.Line*/ curve, 
7051
								/*dojo.lfx.Line*/ curve, 
7015
								/*function*/ easing, 
7052
								/*function*/ easing, 
7016
								/*int*/ repeatCount, 
7053
								/*int*/ repeatCount, 
7017
								/*int*/ rate){
7054
								/*int*/ rate){
7018
	//	summary
7055
	//	summary
7019
	//		a generic animation object that fires callbacks into it's handlers
7056
	//		a generic animation object that fires callbacks into it's handlers
7020
	//		object at various states
7057
	//		object at various states
7021
	//	handlers: { handler: Function?, onstart: Function?, onstop: Function?, onanimate: Function? }
7058
	//	handlers: { handler: Function?, onstart: Function?, onstop: Function?, onanimate: Function? }
7022
	dojo.lfx.IAnimation.call(this);
7059
	dojo.lfx.IAnimation.call(this);
7023
	if(dojo.lang.isNumber(handlers)||(!handlers && duration.getValue)){
7060
	if(dojo.lang.isNumber(handlers)||(!handlers && duration.getValue)){
7024
		// no handlers argument:
7061
		// no handlers argument:
7025
		rate = repeatCount;
7062
		rate = repeatCount;
7026
		repeatCount = easing;
7063
		repeatCount = easing;
7027
		easing = curve;
7064
		easing = curve;
7028
		curve = duration;
7065
		curve = duration;
7029
		duration = handlers;
7066
		duration = handlers;
7030
		handlers = null;
7067
		handlers = null;
7031
	}else if(handlers.getValue||dojo.lang.isArray(handlers)){
7068
	}else if(handlers.getValue||dojo.lang.isArray(handlers)){
7032
		// no handlers or duration:
7069
		// no handlers or duration:
7033
		rate = easing;
7070
		rate = easing;
7034
		repeatCount = curve;
7071
		repeatCount = curve;
7035
		easing = duration;
7072
		easing = duration;
7036
		curve = handlers;
7073
		curve = handlers;
7037
		duration = null;
7074
		duration = null;
7038
		handlers = null;
7075
		handlers = null;
7039
	}
7076
	}
7040
	if(dojo.lang.isArray(curve)){
7077
	if(dojo.lang.isArray(curve)){
7041
		/* curve: Array
7078
		/* curve: Array
7042
		   pId: a */
7079
		   pId: a */
7043
		this.curve = new dojo.lfx.Line(curve[0], curve[1]);
7080
		this.curve = new dojo.lfx.Line(curve[0], curve[1]);
7044
	}else{
7081
	}else{
7045
		this.curve = curve;
7082
		this.curve = curve;
7046
	}
7083
	}
7047
	if(duration != null && duration > 0){ this.duration = duration; }
7084
	if(duration != null && duration > 0){ this.duration = duration; }
7048
	if(repeatCount){ this.repeatCount = repeatCount; }
7085
	if(repeatCount){ this.repeatCount = repeatCount; }
7049
	if(rate){ this.rate = rate; }
7086
	if(rate){ this.rate = rate; }
7050
	if(handlers){
7087
	if(handlers){
7051
		dojo.lang.forEach([
7088
		dojo.lang.forEach([
7052
				"handler", "beforeBegin", "onBegin", 
7089
				"handler", "beforeBegin", "onBegin", 
7053
				"onEnd", "onPlay", "onStop", "onAnimate"
7090
				"onEnd", "onPlay", "onStop", "onAnimate"
7054
			], function(item){
7091
			], function(item){
7055
				if(handlers[item]){
7092
				if(handlers[item]){
7056
					this.connect(item, handlers[item]);
7093
					this.connect(item, handlers[item]);
7057
				}
7094
				}
7058
			}, this);
7095
			}, this);
7059
	}
7096
	}
7060
	if(easing && dojo.lang.isFunction(easing)){
7097
	if(easing && dojo.lang.isFunction(easing)){
7061
		this.easing=easing;
7098
		this.easing=easing;
7062
	}
7099
	}
7063
}
7100
}
7064
dojo.inherits(dojo.lfx.Animation, dojo.lfx.IAnimation);
7101
dojo.inherits(dojo.lfx.Animation, dojo.lfx.IAnimation);
7065
dojo.lang.extend(dojo.lfx.Animation, {
7102
dojo.lang.extend(dojo.lfx.Animation, {
7066
	// "private" properties
7103
	// "private" properties
7067
	_startTime: null,
7104
	_startTime: null,
7068
	_endTime: null,
7105
	_endTime: null,
7069
	_timer: null,
7106
	_timer: null,
7070
	_percent: 0,
7107
	_percent: 0,
7071
	_startRepeatCount: 0,
7108
	_startRepeatCount: 0,
7072
 
7109
 
7073
	// public methods
7110
	// public methods
7074
	play: function(/*int?*/ delay, /*bool?*/ gotoStart){
7111
	play: function(/*int?*/ delay, /*bool?*/ gotoStart){
7075
		// summary: Start the animation.
7112
		// summary: Start the animation.
7076
		// delay: How many milliseconds to delay before starting.
7113
		// delay: How many milliseconds to delay before starting.
7077
		// gotoStart: If true, starts the animation from the beginning; otherwise,
7114
		// gotoStart: If true, starts the animation from the beginning; otherwise,
7078
		//            starts it from its current position.
7115
		//            starts it from its current position.
7079
		if(gotoStart){
7116
		if(gotoStart){
7080
			clearTimeout(this._timer);
7117
			clearTimeout(this._timer);
7081
			this._active = false;
7118
			this._active = false;
7082
			this._paused = false;
7119
			this._paused = false;
7083
			this._percent = 0;
7120
			this._percent = 0;
7084
		}else if(this._active && !this._paused){
7121
		}else if(this._active && !this._paused){
7085
			return this; // dojo.lfx.Animation
7122
			return this; // dojo.lfx.Animation
7086
		}
7123
		}
7087
		
7124
		
7088
		this.fire("handler", ["beforeBegin"]);
7125
		this.fire("handler", ["beforeBegin"]);
7089
		this.fire("beforeBegin");
7126
		this.fire("beforeBegin");
7090
 
7127
 
7091
		if(delay > 0){
7128
		if(delay > 0){
7092
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
7129
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
7093
			return this; // dojo.lfx.Animation
7130
			return this; // dojo.lfx.Animation
7094
		}
7131
		}
7095
		
7132
		
7096
		this._startTime = new Date().valueOf();
7133
		this._startTime = new Date().valueOf();
7097
		if(this._paused){
7134
		if(this._paused){
7098
			this._startTime -= (this.duration * this._percent / 100);
7135
			this._startTime -= (this.duration * this._percent / 100);
7099
		}
7136
		}
7100
		this._endTime = this._startTime + this.duration;
7137
		this._endTime = this._startTime + this.duration;
7101
 
7138
 
7102
		this._active = true;
7139
		this._active = true;
7103
		this._paused = false;
7140
		this._paused = false;
7104
		
7141
		
7105
		var step = this._percent / 100;
7142
		var step = this._percent / 100;
7106
		var value = this.curve.getValue(step);
7143
		var value = this.curve.getValue(step);
7107
		if(this._percent == 0 ){
7144
		if(this._percent == 0 ){
7108
			if(!this._startRepeatCount){
7145
			if(!this._startRepeatCount){
7109
				this._startRepeatCount = this.repeatCount;
7146
				this._startRepeatCount = this.repeatCount;
7110
			}
7147
			}
7111
			this.fire("handler", ["begin", value]);
7148
			this.fire("handler", ["begin", value]);
7112
			this.fire("onBegin", [value]);
7149
			this.fire("onBegin", [value]);
7113
		}
7150
		}
7114
 
7151
 
7115
		this.fire("handler", ["play", value]);
7152
		this.fire("handler", ["play", value]);
7116
		this.fire("onPlay", [value]);
7153
		this.fire("onPlay", [value]);
7117
 
7154
 
7118
		this._cycle();
7155
		this._cycle();
7119
		return this; // dojo.lfx.Animation
7156
		return this; // dojo.lfx.Animation
7120
	},
7157
	},
7121
 
7158
 
7122
	pause: function(){
7159
	pause: function(){
7123
		// summary: Pauses a running animation.
7160
		// summary: Pauses a running animation.
7124
		clearTimeout(this._timer);
7161
		clearTimeout(this._timer);
7125
		if(!this._active){ return this; /*dojo.lfx.Animation*/}
7162
		if(!this._active){ return this; /*dojo.lfx.Animation*/}
7126
		this._paused = true;
7163
		this._paused = true;
7127
		var value = this.curve.getValue(this._percent / 100);
7164
		var value = this.curve.getValue(this._percent / 100);
7128
		this.fire("handler", ["pause", value]);
7165
		this.fire("handler", ["pause", value]);
7129
		this.fire("onPause", [value]);
7166
		this.fire("onPause", [value]);
7130
		return this; // dojo.lfx.Animation
7167
		return this; // dojo.lfx.Animation
7131
	},
7168
	},
7132
 
7169
 
7133
	gotoPercent: function(/*Decimal*/ pct, /*bool?*/ andPlay){
7170
	gotoPercent: function(/*Decimal*/ pct, /*bool?*/ andPlay){
7134
		// summary: Sets the progress of the animation.
7171
		// summary: Sets the progress of the animation.
7135
		// pct: A percentage in decimal notation (between and including 0.0 and 1.0).
7172
		// pct: A percentage in decimal notation (between and including 0.0 and 1.0).
7136
		// andPlay: If true, play the animation after setting the progress.
7173
		// andPlay: If true, play the animation after setting the progress.
7137
		clearTimeout(this._timer);
7174
		clearTimeout(this._timer);
7138
		this._active = true;
7175
		this._active = true;
7139
		this._paused = true;
7176
		this._paused = true;
7140
		this._percent = pct;
7177
		this._percent = pct;
7141
		if(andPlay){ this.play(); }
7178
		if(andPlay){ this.play(); }
7142
		return this; // dojo.lfx.Animation
7179
		return this; // dojo.lfx.Animation
7143
	},
7180
	},
7144
 
7181
 
7145
	stop: function(/*bool?*/ gotoEnd){
7182
	stop: function(/*bool?*/ gotoEnd){
7146
		// summary: Stops a running animation.
7183
		// summary: Stops a running animation.
7147
		// gotoEnd: If true, the animation will end.
7184
		// gotoEnd: If true, the animation will end.
7148
		clearTimeout(this._timer);
7185
		clearTimeout(this._timer);
7149
		var step = this._percent / 100;
7186
		var step = this._percent / 100;
7150
		if(gotoEnd){
7187
		if(gotoEnd){
7151
			step = 1;
7188
			step = 1;
7152
		}
7189
		}
7153
		var value = this.curve.getValue(step);
7190
		var value = this.curve.getValue(step);
7154
		this.fire("handler", ["stop", value]);
7191
		this.fire("handler", ["stop", value]);
7155
		this.fire("onStop", [value]);
7192
		this.fire("onStop", [value]);
7156
		this._active = false;
7193
		this._active = false;
7157
		this._paused = false;
7194
		this._paused = false;
7158
		return this; // dojo.lfx.Animation
7195
		return this; // dojo.lfx.Animation
7159
	},
7196
	},
7160
 
7197
 
7161
	status: function(){
7198
	status: function(){
7162
		// summary: Returns a string representation of the status of
7199
		// summary: Returns a string representation of the status of
7163
		//			the animation.
7200
		//			the animation.
7164
		if(this._active){
7201
		if(this._active){
7165
			return this._paused ? "paused" : "playing"; // String
7202
			return this._paused ? "paused" : "playing"; // String
7166
		}else{
7203
		}else{
7167
			return "stopped"; // String
7204
			return "stopped"; // String
7168
		}
7205
		}
7169
		return this;
7206
		return this;
7170
	},
7207
	},
7171
 
7208
 
7172
	// "private" methods
7209
	// "private" methods
7173
	_cycle: function(){
7210
	_cycle: function(){
7174
		clearTimeout(this._timer);
7211
		clearTimeout(this._timer);
7175
		if(this._active){
7212
		if(this._active){
7176
			var curr = new Date().valueOf();
7213
			var curr = new Date().valueOf();
7177
			var step = (curr - this._startTime) / (this._endTime - this._startTime);
7214
			var step = (curr - this._startTime) / (this._endTime - this._startTime);
7178
 
7215
 
7179
			if(step >= 1){
7216
			if(step >= 1){
7180
				step = 1;
7217
				step = 1;
7181
				this._percent = 100;
7218
				this._percent = 100;
7182
			}else{
7219
			}else{
7183
				this._percent = step * 100;
7220
				this._percent = step * 100;
7184
			}
7221
			}
7185
			
7222
			
7186
			// Perform easing
7223
			// Perform easing
7187
			if((this.easing)&&(dojo.lang.isFunction(this.easing))){
7224
			if((this.easing)&&(dojo.lang.isFunction(this.easing))){
7188
				step = this.easing(step);
7225
				step = this.easing(step);
7189
			}
7226
			}
7190
 
7227
 
7191
			var value = this.curve.getValue(step);
7228
			var value = this.curve.getValue(step);
7192
			this.fire("handler", ["animate", value]);
7229
			this.fire("handler", ["animate", value]);
7193
			this.fire("onAnimate", [value]);
7230
			this.fire("onAnimate", [value]);
7194
 
7231
 
7195
			if( step < 1 ){
7232
			if( step < 1 ){
7196
				this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate);
7233
				this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate);
7197
			}else{
7234
			}else{
7198
				this._active = false;
7235
				this._active = false;
7199
				this.fire("handler", ["end"]);
7236
				this.fire("handler", ["end"]);
7200
				this.fire("onEnd");
7237
				this.fire("onEnd");
7201
 
7238
 
7202
				if(this.repeatCount > 0){
7239
				if(this.repeatCount > 0){
7203
					this.repeatCount--;
7240
					this.repeatCount--;
7204
					this.play(null, true);
7241
					this.play(null, true);
7205
				}else if(this.repeatCount == -1){
7242
				}else if(this.repeatCount == -1){
7206
					this.play(null, true);
7243
					this.play(null, true);
7207
				}else{
7244
				}else{
7208
					if(this._startRepeatCount){
7245
					if(this._startRepeatCount){
7209
						this.repeatCount = this._startRepeatCount;
7246
						this.repeatCount = this._startRepeatCount;
7210
						this._startRepeatCount = 0;
7247
						this._startRepeatCount = 0;
7211
					}
7248
					}
7212
				}
7249
				}
7213
			}
7250
			}
7214
		}
7251
		}
7215
		return this; // dojo.lfx.Animation
7252
		return this; // dojo.lfx.Animation
7216
	}
7253
	}
7217
});
7254
});
7218
 
7255
 
7219
dojo.lfx.Combine = function(/*dojo.lfx.IAnimation...*/ animations){
7256
dojo.lfx.Combine = function(/*dojo.lfx.IAnimation...*/ animations){
7220
	// summary: An animation object to play animations passed to it at the same time.
7257
	// summary: An animation object to play animations passed to it at the same time.
7221
	dojo.lfx.IAnimation.call(this);
7258
	dojo.lfx.IAnimation.call(this);
7222
	this._anims = [];
7259
	this._anims = [];
7223
	this._animsEnded = 0;
7260
	this._animsEnded = 0;
7224
	
7261
	
7225
	var anims = arguments;
7262
	var anims = arguments;
7226
	if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){
7263
	if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){
7227
		/* animations: dojo.lfx.IAnimation[]
7264
		/* animations: dojo.lfx.IAnimation[]
7228
		   pId: a */
7265
		   pId: a */
7229
		anims = anims[0];
7266
		anims = anims[0];
7230
	}
7267
	}
7231
	
7268
	
7232
	dojo.lang.forEach(anims, function(anim){
7269
	dojo.lang.forEach(anims, function(anim){
7233
		this._anims.push(anim);
7270
		this._anims.push(anim);
7234
		anim.connect("onEnd", dojo.lang.hitch(this, "_onAnimsEnded"));
7271
		anim.connect("onEnd", dojo.lang.hitch(this, "_onAnimsEnded"));
7235
	}, this);
7272
	}, this);
7236
}
7273
}
7237
dojo.inherits(dojo.lfx.Combine, dojo.lfx.IAnimation);
7274
dojo.inherits(dojo.lfx.Combine, dojo.lfx.IAnimation);
7238
dojo.lang.extend(dojo.lfx.Combine, {
7275
dojo.lang.extend(dojo.lfx.Combine, {
7239
	// private members
7276
	// private members
7240
	_animsEnded: 0,
7277
	_animsEnded: 0,
7241
	
7278
	
7242
	// public methods
7279
	// public methods
7243
	play: function(/*int?*/ delay, /*bool?*/ gotoStart){
7280
	play: function(/*int?*/ delay, /*bool?*/ gotoStart){
7244
		// summary: Start the animations.
7281
		// summary: Start the animations.
7245
		// delay: How many milliseconds to delay before starting.
7282
		// delay: How many milliseconds to delay before starting.
7246
		// gotoStart: If true, starts the animations from the beginning; otherwise,
7283
		// gotoStart: If true, starts the animations from the beginning; otherwise,
7247
		//            starts them from their current position.
7284
		//            starts them from their current position.
7248
		if( !this._anims.length ){ return this; /*dojo.lfx.Combine*/}
7285
		if( !this._anims.length ){ return this; /*dojo.lfx.Combine*/}
7249
 
7286
 
7250
		this.fire("beforeBegin");
7287
		this.fire("beforeBegin");
7251
 
7288
 
7252
		if(delay > 0){
7289
		if(delay > 0){
7253
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
7290
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
7254
			return this; // dojo.lfx.Combine
7291
			return this; // dojo.lfx.Combine
7255
		}
7292
		}
7256
		
7293
		
7257
		if(gotoStart || this._anims[0].percent == 0){
7294
		if(gotoStart || this._anims[0].percent == 0){
7258
			this.fire("onBegin");
7295
			this.fire("onBegin");
7259
		}
7296
		}
7260
		this.fire("onPlay");
7297
		this.fire("onPlay");
7261
		this._animsCall("play", null, gotoStart);
7298
		this._animsCall("play", null, gotoStart);
7262
		return this; // dojo.lfx.Combine
7299
		return this; // dojo.lfx.Combine
7263
	},
7300
	},
7264
	
7301
	
7265
	pause: function(){
7302
	pause: function(){
7266
		// summary: Pauses the running animations.
7303
		// summary: Pauses the running animations.
7267
		this.fire("onPause");
7304
		this.fire("onPause");
7268
		this._animsCall("pause"); 
7305
		this._animsCall("pause"); 
7269
		return this; // dojo.lfx.Combine
7306
		return this; // dojo.lfx.Combine
7270
	},
7307
	},
7271
	
7308
	
7272
	stop: function(/*bool?*/ gotoEnd){
7309
	stop: function(/*bool?*/ gotoEnd){
7273
		// summary: Stops the running animations.
7310
		// summary: Stops the running animations.
7274
		// gotoEnd: If true, the animations will end.
7311
		// gotoEnd: If true, the animations will end.
7275
		this.fire("onStop");
7312
		this.fire("onStop");
7276
		this._animsCall("stop", gotoEnd);
7313
		this._animsCall("stop", gotoEnd);
7277
		return this; // dojo.lfx.Combine
7314
		return this; // dojo.lfx.Combine
7278
	},
7315
	},
7279
	
7316
	
7280
	// private methods
7317
	// private methods
7281
	_onAnimsEnded: function(){
7318
	_onAnimsEnded: function(){
7282
		this._animsEnded++;
7319
		this._animsEnded++;
7283
		if(this._animsEnded >= this._anims.length){
7320
		if(this._animsEnded >= this._anims.length){
7284
			this.fire("onEnd");
7321
			this.fire("onEnd");
7285
		}
7322
		}
7286
		return this; // dojo.lfx.Combine
7323
		return this; // dojo.lfx.Combine
7287
	},
7324
	},
7288
	
7325
	
7289
	_animsCall: function(/*String*/ funcName){
7326
	_animsCall: function(/*String*/ funcName){
7290
		var args = [];
7327
		var args = [];
7291
		if(arguments.length > 1){
7328
		if(arguments.length > 1){
7292
			for(var i = 1 ; i < arguments.length ; i++){
7329
			for(var i = 1 ; i < arguments.length ; i++){
7293
				args.push(arguments[i]);
7330
				args.push(arguments[i]);
7294
			}
7331
			}
7295
		}
7332
		}
7296
		var _this = this;
7333
		var _this = this;
7297
		dojo.lang.forEach(this._anims, function(anim){
7334
		dojo.lang.forEach(this._anims, function(anim){
7298
			anim[funcName](args);
7335
			anim[funcName](args);
7299
		}, _this);
7336
		}, _this);
7300
		return this; // dojo.lfx.Combine
7337
		return this; // dojo.lfx.Combine
7301
	}
7338
	}
7302
});
7339
});
7303
 
7340
 
7304
dojo.lfx.Chain = function(/*dojo.lfx.IAnimation...*/ animations) {
7341
dojo.lfx.Chain = function(/*dojo.lfx.IAnimation...*/ animations) {
7305
	// summary: An animation object to play animations passed to it
7342
	// summary: An animation object to play animations passed to it
7306
	//			one after another.
7343
	//			one after another.
7307
	dojo.lfx.IAnimation.call(this);
7344
	dojo.lfx.IAnimation.call(this);
7308
	this._anims = [];
7345
	this._anims = [];
7309
	this._currAnim = -1;
7346
	this._currAnim = -1;
7310
	
7347
	
7311
	var anims = arguments;
7348
	var anims = arguments;
7312
	if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){
7349
	if(anims.length == 1 && (dojo.lang.isArray(anims[0]) || dojo.lang.isArrayLike(anims[0]))){
7313
		/* animations: dojo.lfx.IAnimation[]
7350
		/* animations: dojo.lfx.IAnimation[]
7314
		   pId: a */
7351
		   pId: a */
7315
		anims = anims[0];
7352
		anims = anims[0];
7316
	}
7353
	}
7317
	
7354
	
7318
	var _this = this;
7355
	var _this = this;
7319
	dojo.lang.forEach(anims, function(anim, i, anims_arr){
7356
	dojo.lang.forEach(anims, function(anim, i, anims_arr){
7320
		this._anims.push(anim);
7357
		this._anims.push(anim);
7321
		if(i < anims_arr.length - 1){
7358
		if(i < anims_arr.length - 1){
7322
			anim.connect("onEnd", dojo.lang.hitch(this, "_playNext") );
7359
			anim.connect("onEnd", dojo.lang.hitch(this, "_playNext") );
7323
		}else{
7360
		}else{
7324
			anim.connect("onEnd", dojo.lang.hitch(this, function(){ this.fire("onEnd"); }) );
7361
			anim.connect("onEnd", dojo.lang.hitch(this, function(){ this.fire("onEnd"); }) );
7325
		}
7362
		}
7326
	}, this);
7363
	}, this);
7327
}
7364
}
7328
dojo.inherits(dojo.lfx.Chain, dojo.lfx.IAnimation);
7365
dojo.inherits(dojo.lfx.Chain, dojo.lfx.IAnimation);
7329
dojo.lang.extend(dojo.lfx.Chain, {
7366
dojo.lang.extend(dojo.lfx.Chain, {
7330
	// private members
7367
	// private members
7331
	_currAnim: -1,
7368
	_currAnim: -1,
7332
	
7369
	
7333
	// public methods
7370
	// public methods
7334
	play: function(/*int?*/ delay, /*bool?*/ gotoStart){
7371
	play: function(/*int?*/ delay, /*bool?*/ gotoStart){
7335
		// summary: Start the animation sequence.
7372
		// summary: Start the animation sequence.
7336
		// delay: How many milliseconds to delay before starting.
7373
		// delay: How many milliseconds to delay before starting.
7337
		// gotoStart: If true, starts the sequence from the beginning; otherwise,
7374
		// gotoStart: If true, starts the sequence from the beginning; otherwise,
7338
		//            starts it from its current position.
7375
		//            starts it from its current position.
7339
		if( !this._anims.length ) { return this; /*dojo.lfx.Chain*/}
7376
		if( !this._anims.length ) { return this; /*dojo.lfx.Chain*/}
7340
		if( gotoStart || !this._anims[this._currAnim] ) {
7377
		if( gotoStart || !this._anims[this._currAnim] ) {
7341
			this._currAnim = 0;
7378
			this._currAnim = 0;
7342
		}
7379
		}
7343
 
7380
 
7344
		var currentAnimation = this._anims[this._currAnim];
7381
		var currentAnimation = this._anims[this._currAnim];
7345
 
7382
 
7346
		this.fire("beforeBegin");
7383
		this.fire("beforeBegin");
7347
		if(delay > 0){
7384
		if(delay > 0){
7348
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
7385
			setTimeout(dojo.lang.hitch(this, function(){ this.play(null, gotoStart); }), delay);
7349
			return this; // dojo.lfx.Chain
7386
			return this; // dojo.lfx.Chain
7350
		}
7387
		}
7351
		
7388
		
7352
		if(currentAnimation){
7389
		if(currentAnimation){
7353
			if(this._currAnim == 0){
7390
			if(this._currAnim == 0){
7354
				this.fire("handler", ["begin", this._currAnim]);
7391
				this.fire("handler", ["begin", this._currAnim]);
7355
				this.fire("onBegin", [this._currAnim]);
7392
				this.fire("onBegin", [this._currAnim]);
7356
			}
7393
			}
7357
			this.fire("onPlay", [this._currAnim]);
7394
			this.fire("onPlay", [this._currAnim]);
7358
			currentAnimation.play(null, gotoStart);
7395
			currentAnimation.play(null, gotoStart);
7359
		}
7396
		}
7360
		return this; // dojo.lfx.Chain
7397
		return this; // dojo.lfx.Chain
7361
	},
7398
	},
7362
	
7399
	
7363
	pause: function(){
7400
	pause: function(){
7364
		// summary: Pauses the running animation sequence.
7401
		// summary: Pauses the running animation sequence.
7365
		if( this._anims[this._currAnim] ) {
7402
		if( this._anims[this._currAnim] ) {
7366
			this._anims[this._currAnim].pause();
7403
			this._anims[this._currAnim].pause();
7367
			this.fire("onPause", [this._currAnim]);
7404
			this.fire("onPause", [this._currAnim]);
7368
		}
7405
		}
7369
		return this; // dojo.lfx.Chain
7406
		return this; // dojo.lfx.Chain
7370
	},
7407
	},
7371
	
7408
	
7372
	playPause: function(){
7409
	playPause: function(){
7373
		// summary: If the animation sequence is playing, pause it; otherwise,
7410
		// summary: If the animation sequence is playing, pause it; otherwise,
7374
		//			play it.
7411
		//			play it.
7375
		if(this._anims.length == 0){ return this; }
7412
		if(this._anims.length == 0){ return this; }
7376
		if(this._currAnim == -1){ this._currAnim = 0; }
7413
		if(this._currAnim == -1){ this._currAnim = 0; }
7377
		var currAnim = this._anims[this._currAnim];
7414
		var currAnim = this._anims[this._currAnim];
7378
		if( currAnim ) {
7415
		if( currAnim ) {
7379
			if( !currAnim._active || currAnim._paused ) {
7416
			if( !currAnim._active || currAnim._paused ) {
7380
				this.play();
7417
				this.play();
7381
			} else {
7418
			} else {
7382
				this.pause();
7419
				this.pause();
7383
			}
7420
			}
7384
		}
7421
		}
7385
		return this; // dojo.lfx.Chain
7422
		return this; // dojo.lfx.Chain
7386
	},
7423
	},
7387
	
7424
	
7388
	stop: function(){
7425
	stop: function(){
7389
		// summary: Stops the running animations.
7426
		// summary: Stops the running animations.
7390
		var currAnim = this._anims[this._currAnim];
7427
		var currAnim = this._anims[this._currAnim];
7391
		if(currAnim){
7428
		if(currAnim){
7392
			currAnim.stop();
7429
			currAnim.stop();
7393
			this.fire("onStop", [this._currAnim]);
7430
			this.fire("onStop", [this._currAnim]);
7394
		}
7431
		}
7395
		return currAnim; // dojo.lfx.IAnimation
7432
		return currAnim; // dojo.lfx.IAnimation
7396
	},
7433
	},
7397
	
7434
	
7398
	// private methods
7435
	// private methods
7399
	_playNext: function(){
7436
	_playNext: function(){
7400
		if( this._currAnim == -1 || this._anims.length == 0 ) { return this; }
7437
		if( this._currAnim == -1 || this._anims.length == 0 ) { return this; }
7401
		this._currAnim++;
7438
		this._currAnim++;
7402
		if( this._anims[this._currAnim] ){
7439
		if( this._anims[this._currAnim] ){
7403
			this._anims[this._currAnim].play(null, true);
7440
			this._anims[this._currAnim].play(null, true);
7404
		}
7441
		}
7405
		return this; // dojo.lfx.Chain
7442
		return this; // dojo.lfx.Chain
7406
	}
7443
	}
7407
});
7444
});
7408
 
7445
 
7409
dojo.lfx.combine = function(/*dojo.lfx.IAnimation...*/ animations){
7446
dojo.lfx.combine = function(/*dojo.lfx.IAnimation...*/ animations){
7410
	// summary: Convenience function.  Returns a dojo.lfx.Combine created
7447
	// summary: Convenience function.  Returns a dojo.lfx.Combine created
7411
	//			using the animations passed in.
7448
	//			using the animations passed in.
7412
	var anims = arguments;
7449
	var anims = arguments;
7413
	if(dojo.lang.isArray(arguments[0])){
7450
	if(dojo.lang.isArray(arguments[0])){
7414
		/* animations: dojo.lfx.IAnimation[]
7451
		/* animations: dojo.lfx.IAnimation[]
7415
		   pId: a */
7452
		   pId: a */
7416
		anims = arguments[0];
7453
		anims = arguments[0];
7417
	}
7454
	}
7418
	if(anims.length == 1){ return anims[0]; }
7455
	if(anims.length == 1){ return anims[0]; }
7419
	return new dojo.lfx.Combine(anims); // dojo.lfx.Combine
7456
	return new dojo.lfx.Combine(anims); // dojo.lfx.Combine
7420
}
7457
}
7421
 
7458
 
7422
dojo.lfx.chain = function(/*dojo.lfx.IAnimation...*/ animations){
7459
dojo.lfx.chain = function(/*dojo.lfx.IAnimation...*/ animations){
7423
	// summary: Convenience function.  Returns a dojo.lfx.Chain created
7460
	// summary: Convenience function.  Returns a dojo.lfx.Chain created
7424
	//			using the animations passed in.
7461
	//			using the animations passed in.
7425
	var anims = arguments;
7462
	var anims = arguments;
7426
	if(dojo.lang.isArray(arguments[0])){
7463
	if(dojo.lang.isArray(arguments[0])){
7427
		/* animations: dojo.lfx.IAnimation[]
7464
		/* animations: dojo.lfx.IAnimation[]
7428
		   pId: a */
7465
		   pId: a */
7429
		anims = arguments[0];
7466
		anims = arguments[0];
7430
	}
7467
	}
7431
	if(anims.length == 1){ return anims[0]; }
7468
	if(anims.length == 1){ return anims[0]; }
7432
	return new dojo.lfx.Chain(anims); // dojo.lfx.Combine
7469
	return new dojo.lfx.Chain(anims); // dojo.lfx.Combine
7433
}
7470
}
7434
 
7471
 
7435
dojo.provide("dojo.html.common");
7472
dojo.provide("dojo.html.common");
7436
 
7473
 
7437
 
7474
 
7438
 
7475
 
7439
dojo.lang.mixin(dojo.html, dojo.dom);
7476
dojo.lang.mixin(dojo.html, dojo.dom);
7440
 
7477
 
7441
dojo.html.body = function(){
7478
dojo.html.body = function(){
7442
	dojo.deprecated("dojo.html.body() moved to dojo.body()", "0.5");
7479
	dojo.deprecated("dojo.html.body() moved to dojo.body()", "0.5");
7443
	return dojo.body();
7480
	return dojo.body();
7444
}
7481
}
7445
 
7482
 
7446
// FIXME: we are going to assume that we can throw any and every rendering
7483
// FIXME: we are going to assume that we can throw any and every rendering
7447
// engine into the IE 5.x box model. In Mozilla, we do this w/ CSS.
7484
// engine into the IE 5.x box model. In Mozilla, we do this w/ CSS.
7448
// Need to investigate for KHTML and Opera
7485
// Need to investigate for KHTML and Opera
7449
 
7486
 
7450
dojo.html.getEventTarget = function(/* DOMEvent */evt){
7487
dojo.html.getEventTarget = function(/* DOMEvent */evt){
7451
	//	summary
7488
	//	summary
7452
	//	Returns the target of an event
7489
	//	Returns the target of an event
7453
	if(!evt) { evt = dojo.global().event || {} };
7490
	if(!evt) { evt = dojo.global().event || {} };
7454
	var t = (evt.srcElement ? evt.srcElement : (evt.target ? evt.target : null));
7491
	var t = (evt.srcElement ? evt.srcElement : (evt.target ? evt.target : null));
7455
	while((t)&&(t.nodeType!=1)){ t = t.parentNode; }
7492
	while((t)&&(t.nodeType!=1)){ t = t.parentNode; }
7456
	return t;	//	HTMLElement
7493
	return t;	//	HTMLElement
7457
}
7494
}
7458
 
7495
 
7459
dojo.html.getViewport = function(){
7496
dojo.html.getViewport = function(){
7460
	//	summary
7497
	//	summary
7461
	//	Returns the dimensions of the viewable area of a browser window
7498
	//	Returns the dimensions of the viewable area of a browser window
7462
	var _window = dojo.global();
7499
	var _window = dojo.global();
7463
	var _document = dojo.doc();
7500
	var _document = dojo.doc();
7464
	var w = 0;
7501
	var w = 0;
7465
	var h = 0;
7502
	var h = 0;
7466
 
7503
 
7467
	if(dojo.render.html.mozilla){
7504
	if(dojo.render.html.mozilla){
7468
		// mozilla
7505
		// mozilla
7469
		w = _document.documentElement.clientWidth;
7506
		w = _document.documentElement.clientWidth;
7470
		h = _window.innerHeight;
7507
		h = _window.innerHeight;
7471
	}else if(!dojo.render.html.opera && _window.innerWidth){
7508
	}else if(!dojo.render.html.opera && _window.innerWidth){
7472
		//in opera9, dojo.body().clientWidth should be used, instead
7509
		//in opera9, dojo.body().clientWidth should be used, instead
7473
		//of window.innerWidth/document.documentElement.clientWidth
7510
		//of window.innerWidth/document.documentElement.clientWidth
7474
		//so we have to check whether it is opera
7511
		//so we have to check whether it is opera
7475
		w = _window.innerWidth;
7512
		w = _window.innerWidth;
7476
		h = _window.innerHeight;
7513
		h = _window.innerHeight;
7477
	} else if (!dojo.render.html.opera && dojo.exists(_document, "documentElement.clientWidth")){
7514
	} else if (!dojo.render.html.opera && dojo.exists(_document, "documentElement.clientWidth")){
7478
		// IE6 Strict
7515
		// IE6 Strict
7479
		var w2 = _document.documentElement.clientWidth;
7516
		var w2 = _document.documentElement.clientWidth;
7480
		// this lets us account for scrollbars
7517
		// this lets us account for scrollbars
7481
		if(!w || w2 && w2 < w) {
7518
		if(!w || w2 && w2 < w) {
7482
			w = w2;
7519
			w = w2;
7483
		}
7520
		}
7484
		h = _document.documentElement.clientHeight;
7521
		h = _document.documentElement.clientHeight;
7485
	} else if (dojo.body().clientWidth){
7522
	} else if (dojo.body().clientWidth){
7486
		// IE, Opera
7523
		// IE, Opera
7487
		w = dojo.body().clientWidth;
7524
		w = dojo.body().clientWidth;
7488
		h = dojo.body().clientHeight;
7525
		h = dojo.body().clientHeight;
7489
	}
7526
	}
7490
	return { width: w, height: h };	//	object
7527
	return { width: w, height: h };	//	object
7491
}
7528
}
7492
 
7529
 
7493
dojo.html.getScroll = function(){
7530
dojo.html.getScroll = function(){
7494
	//	summary
7531
	//	summary
7495
	//	Returns the scroll position of the document
7532
	//	Returns the scroll position of the document
7496
	var _window = dojo.global();
7533
	var _window = dojo.global();
7497
	var _document = dojo.doc();
7534
	var _document = dojo.doc();
7498
	var top = _window.pageYOffset || _document.documentElement.scrollTop || dojo.body().scrollTop || 0;
7535
	var top = _window.pageYOffset || _document.documentElement.scrollTop || dojo.body().scrollTop || 0;
7499
	var left = _window.pageXOffset || _document.documentElement.scrollLeft || dojo.body().scrollLeft || 0;
7536
	var left = _window.pageXOffset || _document.documentElement.scrollLeft || dojo.body().scrollLeft || 0;
7500
	return { 
7537
	return { 
7501
		top: top, 
7538
		top: top, 
7502
		left: left, 
7539
		left: left, 
7503
		offset:{ x: left, y: top }	//	note the change, NOT an Array with added properties. 
7540
		offset:{ x: left, y: top }	//	note the change, NOT an Array with added properties. 
7504
	};	//	object
7541
	};	//	object
7505
}
7542
}
7506
 
7543
 
7507
dojo.html.getParentByType = function(/* HTMLElement */node, /* string */type) {
7544
dojo.html.getParentByType = function(/* HTMLElement */node, /* string */type) {
7508
	//	summary
7545
	//	summary
7509
	//	Returns the first ancestor of node with tagName type.
7546
	//	Returns the first ancestor of node with tagName type.
7510
	var _document = dojo.doc();
7547
	var _document = dojo.doc();
7511
	var parent = dojo.byId(node);
7548
	var parent = dojo.byId(node);
7512
	type = type.toLowerCase();
7549
	type = type.toLowerCase();
7513
	while((parent)&&(parent.nodeName.toLowerCase()!=type)){
7550
	while((parent)&&(parent.nodeName.toLowerCase()!=type)){
7514
		if(parent==(_document["body"]||_document["documentElement"])){
7551
		if(parent==(_document["body"]||_document["documentElement"])){
7515
			return null;
7552
			return null;
7516
		}
7553
		}
7517
		parent = parent.parentNode;
7554
		parent = parent.parentNode;
7518
	}
7555
	}
7519
	return parent;	//	HTMLElement
7556
	return parent;	//	HTMLElement
7520
}
7557
}
7521
 
7558
 
7522
dojo.html.getAttribute = function(/* HTMLElement */node, /* string */attr){
7559
dojo.html.getAttribute = function(/* HTMLElement */node, /* string */attr){
7523
	//	summary
7560
	//	summary
7524
	//	Returns the value of attribute attr from node.
7561
	//	Returns the value of attribute attr from node.
7525
	node = dojo.byId(node);
7562
	node = dojo.byId(node);
7526
	// FIXME: need to add support for attr-specific accessors
7563
	// FIXME: need to add support for attr-specific accessors
7527
	if((!node)||(!node.getAttribute)){
7564
	if((!node)||(!node.getAttribute)){
7528
		// if(attr !== 'nwType'){
7565
		// if(attr !== 'nwType'){
7529
		//	alert("getAttr of '" + attr + "' with bad node"); 
7566
		//	alert("getAttr of '" + attr + "' with bad node"); 
7530
		// }
7567
		// }
7531
		return null;
7568
		return null;
7532
	}
7569
	}
7533
	var ta = typeof attr == 'string' ? attr : new String(attr);
7570
	var ta = typeof attr == 'string' ? attr : new String(attr);
7534
 
7571
 
7535
	// first try the approach most likely to succeed
7572
	// first try the approach most likely to succeed
7536
	var v = node.getAttribute(ta.toUpperCase());
7573
	var v = node.getAttribute(ta.toUpperCase());
7537
	if((v)&&(typeof v == 'string')&&(v!="")){ 
7574
	if((v)&&(typeof v == 'string')&&(v!="")){ 
7538
		return v;	//	string 
7575
		return v;	//	string 
7539
	}
7576
	}
7540
 
7577
 
7541
	// try returning the attributes value, if we couldn't get it as a string
7578
	// try returning the attributes value, if we couldn't get it as a string
7542
	if(v && v.value){ 
7579
	if(v && v.value){ 
7543
		return v.value;	//	string 
7580
		return v.value;	//	string 
7544
	}
7581
	}
7545
 
7582
 
7546
	// this should work on Opera 7, but it's a little on the crashy side
7583
	// this should work on Opera 7, but it's a little on the crashy side
7547
	if((node.getAttributeNode)&&(node.getAttributeNode(ta))){
7584
	if((node.getAttributeNode)&&(node.getAttributeNode(ta))){
7548
		return (node.getAttributeNode(ta)).value;	//	string
7585
		return (node.getAttributeNode(ta)).value;	//	string
7549
	}else if(node.getAttribute(ta)){
7586
	}else if(node.getAttribute(ta)){
7550
		return node.getAttribute(ta);	//	string
7587
		return node.getAttribute(ta);	//	string
7551
	}else if(node.getAttribute(ta.toLowerCase())){
7588
	}else if(node.getAttribute(ta.toLowerCase())){
7552
		return node.getAttribute(ta.toLowerCase());	//	string
7589
		return node.getAttribute(ta.toLowerCase());	//	string
7553
	}
7590
	}
7554
	return null;	//	string
7591
	return null;	//	string
7555
}
7592
}
7556
	
7593
	
7557
dojo.html.hasAttribute = function(/* HTMLElement */node, /* string */attr){
7594
dojo.html.hasAttribute = function(/* HTMLElement */node, /* string */attr){
7558
	//	summary
7595
	//	summary
7559
	//	Determines whether or not the specified node carries a value for the attribute in question.
7596
	//	Determines whether or not the specified node carries a value for the attribute in question.
7560
	return dojo.html.getAttribute(dojo.byId(node), attr) ? true : false;	//	boolean
7597
	return dojo.html.getAttribute(dojo.byId(node), attr) ? true : false;	//	boolean
7561
}
7598
}
7562
	
7599
	
7563
dojo.html.getCursorPosition = function(/* DOMEvent */e){
7600
dojo.html.getCursorPosition = function(/* DOMEvent */e){
7564
	//	summary
7601
	//	summary
7565
	//	Returns the mouse position relative to the document (not the viewport).
7602
	//	Returns the mouse position relative to the document (not the viewport).
7566
	//	For example, if you have a document that is 10000px tall,
7603
	//	For example, if you have a document that is 10000px tall,
7567
	//	but your browser window is only 100px tall,
7604
	//	but your browser window is only 100px tall,
7568
	//	if you scroll to the bottom of the document and call this function it
7605
	//	if you scroll to the bottom of the document and call this function it
7569
	//	will return {x: 0, y: 10000}
7606
	//	will return {x: 0, y: 10000}
7570
	//	NOTE: for events delivered via dojo.event.connect() and/or dojoAttachEvent (for widgets),
7607
	//	NOTE: for events delivered via dojo.event.connect() and/or dojoAttachEvent (for widgets),
7571
	//	you can just access evt.pageX and evt.pageY, rather than calling this function.
7608
	//	you can just access evt.pageX and evt.pageY, rather than calling this function.
7572
	e = e || dojo.global().event;
7609
	e = e || dojo.global().event;
7573
	var cursor = {x:0, y:0};
7610
	var cursor = {x:0, y:0};
7574
	if(e.pageX || e.pageY){
7611
	if(e.pageX || e.pageY){
7575
		cursor.x = e.pageX;
7612
		cursor.x = e.pageX;
7576
		cursor.y = e.pageY;
7613
		cursor.y = e.pageY;
7577
	}else{
7614
	}else{
7578
		var de = dojo.doc().documentElement;
7615
		var de = dojo.doc().documentElement;
7579
		var db = dojo.body();
7616
		var db = dojo.body();
7580
		cursor.x = e.clientX + ((de||db)["scrollLeft"]) - ((de||db)["clientLeft"]);
7617
		cursor.x = e.clientX + ((de||db)["scrollLeft"]) - ((de||db)["clientLeft"]);
7581
		cursor.y = e.clientY + ((de||db)["scrollTop"]) - ((de||db)["clientTop"]);
7618
		cursor.y = e.clientY + ((de||db)["scrollTop"]) - ((de||db)["clientTop"]);
7582
	}
7619
	}
7583
	return cursor;	//	object
7620
	return cursor;	//	object
7584
}
7621
}
7585
 
7622
 
7586
dojo.html.isTag = function(/* HTMLElement */node) {
7623
dojo.html.isTag = function(/* HTMLElement */node) {
7587
	//	summary
7624
	//	summary
7588
	//	Like dojo.dom.isTag, except case-insensitive
7625
	//	Like dojo.dom.isTag, except case-insensitive
7589
	node = dojo.byId(node);
7626
	node = dojo.byId(node);
7590
	if(node && node.tagName) {
7627
	if(node && node.tagName) {
7591
		for (var i=1; i<arguments.length; i++){
7628
		for (var i=1; i<arguments.length; i++){
7592
			if (node.tagName.toLowerCase()==String(arguments[i]).toLowerCase()){
7629
			if (node.tagName.toLowerCase()==String(arguments[i]).toLowerCase()){
7593
				return String(arguments[i]).toLowerCase();	//	string
7630
				return String(arguments[i]).toLowerCase();	//	string
7594
			}
7631
			}
7595
		}
7632
		}
7596
	}
7633
	}
7597
	return "";	//	string
7634
	return "";	//	string
7598
}
7635
}
7599
 
7636
 
7600
//define dojo.html.createExternalElement for IE to workaround the annoying activation "feature" in new IE
7637
//define dojo.html.createExternalElement for IE to workaround the annoying activation "feature" in new IE
7601
//details: http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/overview/activating_activex.asp
7638
//details: http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/overview/activating_activex.asp
7602
if(dojo.render.html.ie && !dojo.render.html.ie70){
7639
if(dojo.render.html.ie && !dojo.render.html.ie70){
7603
	//only define createExternalElement for IE in none https to avoid "mixed content" warning dialog
7640
	//only define createExternalElement for IE in none https to avoid "mixed content" warning dialog
7604
	if(window.location.href.substr(0,6).toLowerCase() != "https:"){
7641
	if(window.location.href.substr(0,6).toLowerCase() != "https:"){
7605
		(function(){
7642
		(function(){
7606
			// FIXME: this seems not to work correctly on IE 7!!
7643
			// FIXME: this seems not to work correctly on IE 7!!
7607
 
7644
 
7608
			//The trick is to define a function in a script.src property:
7645
			//The trick is to define a function in a script.src property:
7609
			// <script src="javascript:'function createExternalElement(){...}'"></script>,
7646
			// <script src="javascript:'function createExternalElement(){...}'"></script>,
7610
			//which will be treated as an external javascript file in IE
7647
			//which will be treated as an external javascript file in IE
7611
			var xscript = dojo.doc().createElement('script');
7648
			var xscript = dojo.doc().createElement('script');
7612
			xscript.src = "javascript:'dojo.html.createExternalElement=function(doc, tag){ return doc.createElement(tag); }'";
7649
			xscript.src = "javascript:'dojo.html.createExternalElement=function(doc, tag){ return doc.createElement(tag); }'";
7613
			dojo.doc().getElementsByTagName("head")[0].appendChild(xscript);
7650
			dojo.doc().getElementsByTagName("head")[0].appendChild(xscript);
7614
		})();
7651
		})();
7615
	}
7652
	}
7616
}else{
7653
}else{
7617
	//for other browsers, simply use document.createElement
7654
	//for other browsers, simply use document.createElement
7618
	//is enough
7655
	//is enough
7619
	dojo.html.createExternalElement = function(/* HTMLDocument */doc, /* string */tag){
7656
	dojo.html.createExternalElement = function(/* HTMLDocument */doc, /* string */tag){
7620
		//	summary
7657
		//	summary
7621
		//	Creates an element in the HTML document, here for ActiveX activation workaround.
7658
		//	Creates an element in the HTML document, here for ActiveX activation workaround.
7622
		return doc.createElement(tag);	//	HTMLElement
7659
		return doc.createElement(tag);	//	HTMLElement
7623
	}
7660
	}
7624
}
7661
}
7625
 
7662
 
7626
dojo.html._callDeprecated = function(inFunc, replFunc, args, argName, retValue){
7663
dojo.html._callDeprecated = function(inFunc, replFunc, args, argName, retValue){
7627
	dojo.deprecated("dojo.html." + inFunc,
7664
	dojo.deprecated("dojo.html." + inFunc,
7628
					"replaced by dojo.html." + replFunc + "(" + (argName ? "node, {"+ argName + ": " + argName + "}" : "" ) + ")" + (retValue ? "." + retValue : ""), "0.5");
7665
					"replaced by dojo.html." + replFunc + "(" + (argName ? "node, {"+ argName + ": " + argName + "}" : "" ) + ")" + (retValue ? "." + retValue : ""), "0.5");
7629
	var newArgs = [];
7666
	var newArgs = [];
7630
	if(argName){ var argsIn = {}; argsIn[argName] = args[1]; newArgs.push(args[0]); newArgs.push(argsIn); }
7667
	if(argName){ var argsIn = {}; argsIn[argName] = args[1]; newArgs.push(args[0]); newArgs.push(argsIn); }
7631
	else { newArgs = args }
7668
	else { newArgs = args }
7632
	var ret = dojo.html[replFunc].apply(dojo.html, args);
7669
	var ret = dojo.html[replFunc].apply(dojo.html, args);
7633
	if(retValue){ return ret[retValue]; }
7670
	if(retValue){ return ret[retValue]; }
7634
	else { return ret; }
7671
	else { return ret; }
7635
}
7672
}
7636
 
7673
 
7637
dojo.html.getViewportWidth = function(){
7674
dojo.html.getViewportWidth = function(){
7638
	return dojo.html._callDeprecated("getViewportWidth", "getViewport", arguments, null, "width");
7675
	return dojo.html._callDeprecated("getViewportWidth", "getViewport", arguments, null, "width");
7639
}
7676
}
7640
dojo.html.getViewportHeight = function(){
7677
dojo.html.getViewportHeight = function(){
7641
	return dojo.html._callDeprecated("getViewportHeight", "getViewport", arguments, null, "height");
7678
	return dojo.html._callDeprecated("getViewportHeight", "getViewport", arguments, null, "height");
7642
}
7679
}
7643
dojo.html.getViewportSize = function(){
7680
dojo.html.getViewportSize = function(){
7644
	return dojo.html._callDeprecated("getViewportSize", "getViewport", arguments);
7681
	return dojo.html._callDeprecated("getViewportSize", "getViewport", arguments);
7645
}
7682
}
7646
dojo.html.getScrollTop = function(){
7683
dojo.html.getScrollTop = function(){
7647
	return dojo.html._callDeprecated("getScrollTop", "getScroll", arguments, null, "top");
7684
	return dojo.html._callDeprecated("getScrollTop", "getScroll", arguments, null, "top");
7648
}
7685
}
7649
dojo.html.getScrollLeft = function(){
7686
dojo.html.getScrollLeft = function(){
7650
	return dojo.html._callDeprecated("getScrollLeft", "getScroll", arguments, null, "left");
7687
	return dojo.html._callDeprecated("getScrollLeft", "getScroll", arguments, null, "left");
7651
}
7688
}
7652
dojo.html.getScrollOffset = function(){
7689
dojo.html.getScrollOffset = function(){
7653
	return dojo.html._callDeprecated("getScrollOffset", "getScroll", arguments, null, "offset");
7690
	return dojo.html._callDeprecated("getScrollOffset", "getScroll", arguments, null, "offset");
7654
}
7691
}
7655
 
7692
 
7656
dojo.provide("dojo.uri.Uri");
7693
dojo.provide("dojo.uri.Uri");
7657
 
7694
 
7658
dojo.uri = new function() {
7695
dojo.uri = new function() {
7659
	this.dojoUri = function (/*dojo.uri.Uri||String*/uri) {
7696
	this.dojoUri = function (/*dojo.uri.Uri||String*/uri) {
7660
		// summary: returns a Uri object resolved relative to the dojo root
7697
		// summary: returns a Uri object resolved relative to the dojo root
7661
		return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri);
7698
		return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri);
7662
	}
7699
	}
7663
 
7700
 
7664
	this.moduleUri = function(/*String*/module, /*dojo.uri.Uri||String*/uri){
7701
	this.moduleUri = function(/*String*/module, /*dojo.uri.Uri||String*/uri){
7665
		// summary: returns a Uri object relative to a module
7702
		// summary: returns a Uri object relative to a module
7666
		// description: Examples: dojo.uri.moduleUri("dojo.widget","templates/template.html"), or dojo.uri.moduleUri("acme","images/small.png")
7703
		// description: Examples: dojo.uri.moduleUri("dojo.widget","templates/template.html"), or dojo.uri.moduleUri("acme","images/small.png")
7667
		var loc = dojo.hostenv.getModuleSymbols(module).join('/');
7704
		var loc = dojo.hostenv.getModuleSymbols(module).join('/');
7668
		if(!loc){
7705
		if(!loc){
7669
			return null;
7706
			return null;
7670
		}
7707
		}
7671
		if(loc.lastIndexOf("/") != loc.length-1){
7708
		if(loc.lastIndexOf("/") != loc.length-1){
7672
			loc += "/";
7709
			loc += "/";
7673
		}
7710
		}
7674
		
7711
		
7675
		//If the path is an absolute path (starts with a / or is on another domain/xdomain)
7712
		//If the path is an absolute path (starts with a / or is on another domain/xdomain)
7676
		//then don't add the baseScriptUri.
7713
		//then don't add the baseScriptUri.
7677
		var colonIndex = loc.indexOf(":");
7714
		var colonIndex = loc.indexOf(":");
7678
		var slashIndex = loc.indexOf("/");
7715
		var slashIndex = loc.indexOf("/");
7679
		if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > slashIndex)){
7716
		if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > slashIndex)){
7680
			loc = dojo.hostenv.getBaseScriptUri() + loc;
7717
			loc = dojo.hostenv.getBaseScriptUri() + loc;
7681
		}
7718
		}
7682
 
7719
 
7683
		return new dojo.uri.Uri(loc,uri);
7720
		return new dojo.uri.Uri(loc,uri);
7684
	}
7721
	}
7685
 
7722
 
7686
	this.Uri = function (/*dojo.uri.Uri||String...*/) {
7723
	this.Uri = function (/*dojo.uri.Uri||String...*/) {
7687
		// summary: Constructor to create an object representing a URI.
7724
		// summary: Constructor to create an object representing a URI.
7688
		// description: 
7725
		// description: 
7689
		//  Each argument is evaluated in order relative to the next until
7726
		//  Each argument is evaluated in order relative to the next until
7690
		//  a canonical uri is produced. To get an absolute Uri relative
7727
		//  a canonical uri is produced. To get an absolute Uri relative
7691
		//  to the current document use
7728
		//  to the current document use
7692
		//      new dojo.uri.Uri(document.baseURI, uri)
7729
		//      new dojo.uri.Uri(document.baseURI, uri)
7693
 
7730
 
7694
		// TODO: support for IPv6, see RFC 2732
7731
		// TODO: support for IPv6, see RFC 2732
7695
 
7732
 
7696
		// resolve uri components relative to each other
7733
		// resolve uri components relative to each other
7697
		var uri = arguments[0];
7734
		var uri = arguments[0];
7698
		for (var i = 1; i < arguments.length; i++) {
7735
		for (var i = 1; i < arguments.length; i++) {
7699
			if(!arguments[i]) { continue; }
7736
			if(!arguments[i]) { continue; }
7700
 
7737
 
7701
			// Safari doesn't support this.constructor so we have to be explicit
7738
			// Safari doesn't support this.constructor so we have to be explicit
7702
			var relobj = new dojo.uri.Uri(arguments[i].toString());
7739
			var relobj = new dojo.uri.Uri(arguments[i].toString());
7703
			var uriobj = new dojo.uri.Uri(uri.toString());
7740
			var uriobj = new dojo.uri.Uri(uri.toString());
7704
 
7741
 
7705
			if ((relobj.path=="")&&(relobj.scheme==null)&&(relobj.authority==null)&&(relobj.query==null)) {
7742
			if ((relobj.path=="")&&(relobj.scheme==null)&&(relobj.authority==null)&&(relobj.query==null)) {
7706
				if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; }
7743
				if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; }
7707
				relobj = uriobj;
7744
				relobj = uriobj;
7708
			} else if (relobj.scheme == null) {
7745
			} else if (relobj.scheme == null) {
7709
				relobj.scheme = uriobj.scheme;
7746
				relobj.scheme = uriobj.scheme;
7710
 
7747
 
7711
				if (relobj.authority == null) {
7748
				if (relobj.authority == null) {
7712
					relobj.authority = uriobj.authority;
7749
					relobj.authority = uriobj.authority;
7713
 
7750
 
7714
					if (relobj.path.charAt(0) != "/") {
7751
					if (relobj.path.charAt(0) != "/") {
7715
						var path = uriobj.path.substring(0,
7752
						var path = uriobj.path.substring(0,
7716
							uriobj.path.lastIndexOf("/") + 1) + relobj.path;
7753
							uriobj.path.lastIndexOf("/") + 1) + relobj.path;
7717
 
7754
 
7718
						var segs = path.split("/");
7755
						var segs = path.split("/");
7719
						for (var j = 0; j < segs.length; j++) {
7756
						for (var j = 0; j < segs.length; j++) {
7720
							if (segs[j] == ".") {
7757
							if (segs[j] == ".") {
7721
								if (j == segs.length - 1) { segs[j] = ""; }
7758
								if (j == segs.length - 1) { segs[j] = ""; }
7722
								else { segs.splice(j, 1); j--; }
7759
								else { segs.splice(j, 1); j--; }
7723
							} else if (j > 0 && !(j == 1 && segs[0] == "") &&
7760
							} else if (j > 0 && !(j == 1 && segs[0] == "") &&
7724
								segs[j] == ".." && segs[j-1] != "..") {
7761
								segs[j] == ".." && segs[j-1] != "..") {
7725
 
7762
 
7726
								if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; }
7763
								if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; }
7727
								else { segs.splice(j - 1, 2); j -= 2; }
7764
								else { segs.splice(j - 1, 2); j -= 2; }
7728
							}
7765
							}
7729
						}
7766
						}
7730
						relobj.path = segs.join("/");
7767
						relobj.path = segs.join("/");
7731
					}
7768
					}
7732
				}
7769
				}
7733
			}
7770
			}
7734
 
7771
 
7735
			uri = "";
7772
			uri = "";
7736
			if (relobj.scheme != null) { uri += relobj.scheme + ":"; }
7773
			if (relobj.scheme != null) { uri += relobj.scheme + ":"; }
7737
			if (relobj.authority != null) { uri += "//" + relobj.authority; }
7774
			if (relobj.authority != null) { uri += "//" + relobj.authority; }
7738
			uri += relobj.path;
7775
			uri += relobj.path;
7739
			if (relobj.query != null) { uri += "?" + relobj.query; }
7776
			if (relobj.query != null) { uri += "?" + relobj.query; }
7740
			if (relobj.fragment != null) { uri += "#" + relobj.fragment; }
7777
			if (relobj.fragment != null) { uri += "#" + relobj.fragment; }
7741
		}
7778
		}
7742
 
7779
 
7743
		this.uri = uri.toString();
7780
		this.uri = uri.toString();
7744
 
7781
 
7745
		// break the uri into its main components
7782
		// break the uri into its main components
7746
		var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
7783
		var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
7747
		var r = this.uri.match(new RegExp(regexp));
7784
		var r = this.uri.match(new RegExp(regexp));
7748
 
7785
 
7749
		this.scheme = r[2] || (r[1] ? "" : null);
7786
		this.scheme = r[2] || (r[1] ? "" : null);
7750
		this.authority = r[4] || (r[3] ? "" : null);
7787
		this.authority = r[4] || (r[3] ? "" : null);
7751
		this.path = r[5]; // can never be undefined
7788
		this.path = r[5]; // can never be undefined
7752
		this.query = r[7] || (r[6] ? "" : null);
7789
		this.query = r[7] || (r[6] ? "" : null);
7753
		this.fragment  = r[9] || (r[8] ? "" : null);
7790
		this.fragment  = r[9] || (r[8] ? "" : null);
7754
 
7791
 
7755
		if (this.authority != null) {
7792
		if (this.authority != null) {
7756
			// server based naming authority
7793
			// server based naming authority
7757
			regexp = "^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
7794
			regexp = "^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
7758
			r = this.authority.match(new RegExp(regexp));
7795
			r = this.authority.match(new RegExp(regexp));
7759
 
7796
 
7760
			this.user = r[3] || null;
7797
			this.user = r[3] || null;
7761
			this.password = r[4] || null;
7798
			this.password = r[4] || null;
7762
			this.host = r[5];
7799
			this.host = r[5];
7763
			this.port = r[7] || null;
7800
			this.port = r[7] || null;
7764
		}
7801
		}
7765
 
7802
 
7766
		this.toString = function(){ return this.uri; }
7803
		this.toString = function(){ return this.uri; }
7767
	}
7804
	}
7768
};
7805
};
7769
 
7806
 
7770
dojo.provide("dojo.html.style");
7807
dojo.provide("dojo.html.style");
7771
 
7808
 
7772
 
7809
 
7773
 
7810
 
7774
dojo.html.getClass = function(/* HTMLElement */node){
7811
dojo.html.getClass = function(/* HTMLElement */node){
7775
	//	summary
7812
	//	summary
7776
	//	Returns the string value of the list of CSS classes currently assigned directly 
7813
	//	Returns the string value of the list of CSS classes currently assigned directly 
7777
	//	to the node in question. Returns an empty string if no class attribute is found;
7814
	//	to the node in question. Returns an empty string if no class attribute is found;
7778
	node = dojo.byId(node);
7815
	node = dojo.byId(node);
7779
	if(!node){ return ""; }
7816
	if(!node){ return ""; }
7780
	var cs = "";
7817
	var cs = "";
7781
	if(node.className){
7818
	if(node.className){
7782
		cs = node.className;
7819
		cs = node.className;
7783
	}else if(dojo.html.hasAttribute(node, "class")){
7820
	}else if(dojo.html.hasAttribute(node, "class")){
7784
		cs = dojo.html.getAttribute(node, "class");
7821
		cs = dojo.html.getAttribute(node, "class");
7785
	}
7822
	}
7786
	return cs.replace(/^\s+|\s+$/g, "");	//	string
7823
	return cs.replace(/^\s+|\s+$/g, "");	//	string
7787
}
7824
}
7788
 
7825
 
7789
dojo.html.getClasses = function(/* HTMLElement */node) {
7826
dojo.html.getClasses = function(/* HTMLElement */node) {
7790
	//	summary
7827
	//	summary
7791
	//	Returns an array of CSS classes currently assigned directly to the node in question. 
7828
	//	Returns an array of CSS classes currently assigned directly to the node in question. 
7792
	//	Returns an empty array if no classes are found;
7829
	//	Returns an empty array if no classes are found;
7793
	var c = dojo.html.getClass(node);
7830
	var c = dojo.html.getClass(node);
7794
	return (c == "") ? [] : c.split(/\s+/g);	//	array
7831
	return (c == "") ? [] : c.split(/\s+/g);	//	array
7795
}
7832
}
7796
 
7833
 
7797
dojo.html.hasClass = function(/* HTMLElement */node, /* string */classname){
7834
dojo.html.hasClass = function(/* HTMLElement */node, /* string */classname){
7798
	//	summary
7835
	//	summary
7799
	//	Returns whether or not the specified classname is a portion of the
7836
	//	Returns whether or not the specified classname is a portion of the
7800
	//	class list currently applied to the node. Does not cover cascaded
7837
	//	class list currently applied to the node. Does not cover cascaded
7801
	//	styles, only classes directly applied to the node.
7838
	//	styles, only classes directly applied to the node.
7802
	return (new RegExp('(^|\\s+)'+classname+'(\\s+|$)')).test(dojo.html.getClass(node))	//	boolean
7839
	return (new RegExp('(^|\\s+)'+classname+'(\\s+|$)')).test(dojo.html.getClass(node))	//	boolean
7803
}
7840
}
7804
 
7841
 
7805
dojo.html.prependClass = function(/* HTMLElement */node, /* string */classStr){
7842
dojo.html.prependClass = function(/* HTMLElement */node, /* string */classStr){
7806
	//	summary
7843
	//	summary
7807
	//	Adds the specified class to the beginning of the class list on the
7844
	//	Adds the specified class to the beginning of the class list on the
7808
	//	passed node. This gives the specified class the highest precidence
7845
	//	passed node. This gives the specified class the highest precidence
7809
	//	when style cascading is calculated for the node. Returns true or
7846
	//	when style cascading is calculated for the node. Returns true or
7810
	//	false; indicating success or failure of the operation, respectively.
7847
	//	false; indicating success or failure of the operation, respectively.
7811
	classStr += " " + dojo.html.getClass(node);
7848
	classStr += " " + dojo.html.getClass(node);
7812
	return dojo.html.setClass(node, classStr);	//	boolean
7849
	return dojo.html.setClass(node, classStr);	//	boolean
7813
}
7850
}
7814
 
7851
 
7815
dojo.html.addClass = function(/* HTMLElement */node, /* string */classStr){
7852
dojo.html.addClass = function(/* HTMLElement */node, /* string */classStr){
7816
	//	summary
7853
	//	summary
7817
	//	Adds the specified class to the end of the class list on the
7854
	//	Adds the specified class to the end of the class list on the
7818
	//	passed &node;. Returns &true; or &false; indicating success or failure.
7855
	//	passed &node;. Returns &true; or &false; indicating success or failure.
7819
	if (dojo.html.hasClass(node, classStr)) {
7856
	if (dojo.html.hasClass(node, classStr)) {
7820
	  return false;
7857
	  return false;
7821
	}
7858
	}
7822
	classStr = (dojo.html.getClass(node) + " " + classStr).replace(/^\s+|\s+$/g,"");
7859
	classStr = (dojo.html.getClass(node) + " " + classStr).replace(/^\s+|\s+$/g,"");
7823
	return dojo.html.setClass(node, classStr);	//	boolean
7860
	return dojo.html.setClass(node, classStr);	//	boolean
7824
}
7861
}
7825
 
7862
 
7826
dojo.html.setClass = function(/* HTMLElement */node, /* string */classStr){
7863
dojo.html.setClass = function(/* HTMLElement */node, /* string */classStr){
7827
	//	summary
7864
	//	summary
7828
	//	Clobbers the existing list of classes for the node, replacing it with
7865
	//	Clobbers the existing list of classes for the node, replacing it with
7829
	//	the list given in the 2nd argument. Returns true or false
7866
	//	the list given in the 2nd argument. Returns true or false
7830
	//	indicating success or failure.
7867
	//	indicating success or failure.
7831
	node = dojo.byId(node);
7868
	node = dojo.byId(node);
7832
	var cs = new String(classStr);
7869
	var cs = new String(classStr);
7833
	try{
7870
	try{
7834
		if(typeof node.className == "string"){
7871
		if(typeof node.className == "string"){
7835
			node.className = cs;
7872
			node.className = cs;
7836
		}else if(node.setAttribute){
7873
		}else if(node.setAttribute){
7837
			node.setAttribute("class", classStr);
7874
			node.setAttribute("class", classStr);
7838
			node.className = cs;
7875
			node.className = cs;
7839
		}else{
7876
		}else{
7840
			return false;
7877
			return false;
7841
		}
7878
		}
7842
	}catch(e){
7879
	}catch(e){
7843
		dojo.debug("dojo.html.setClass() failed", e);
7880
		dojo.debug("dojo.html.setClass() failed", e);
7844
	}
7881
	}
7845
	return true;
7882
	return true;
7846
}
7883
}
7847
 
7884
 
7848
dojo.html.removeClass = function(/* HTMLElement */node, /* string */classStr, /* boolean? */allowPartialMatches){
7885
dojo.html.removeClass = function(/* HTMLElement */node, /* string */classStr, /* boolean? */allowPartialMatches){
7849
	//	summary
7886
	//	summary
7850
	//	Removes the className from the node;. Returns true or false indicating success or failure.
7887
	//	Removes the className from the node;. Returns true or false indicating success or failure.
7851
	try{
7888
	try{
7852
		if (!allowPartialMatches) {
7889
		if (!allowPartialMatches) {
7853
			var newcs = dojo.html.getClass(node).replace(new RegExp('(^|\\s+)'+classStr+'(\\s+|$)'), "$1$2");
7890
			var newcs = dojo.html.getClass(node).replace(new RegExp('(^|\\s+)'+classStr+'(\\s+|$)'), "$1$2");
7854
		} else {
7891
		} else {
7855
			var newcs = dojo.html.getClass(node).replace(classStr,'');
7892
			var newcs = dojo.html.getClass(node).replace(classStr,'');
7856
		}
7893
		}
7857
		dojo.html.setClass(node, newcs);
7894
		dojo.html.setClass(node, newcs);
7858
	}catch(e){
7895
	}catch(e){
7859
		dojo.debug("dojo.html.removeClass() failed", e);
7896
		dojo.debug("dojo.html.removeClass() failed", e);
7860
	}
7897
	}
7861
	return true;	//	boolean
7898
	return true;	//	boolean
7862
}
7899
}
7863
 
7900
 
7864
dojo.html.replaceClass = function(/* HTMLElement */node, /* string */newClass, /* string */oldClass) {
7901
dojo.html.replaceClass = function(/* HTMLElement */node, /* string */newClass, /* string */oldClass) {
7865
	//	summary
7902
	//	summary
7866
	//	Replaces 'oldClass' and adds 'newClass' to node
7903
	//	Replaces 'oldClass' and adds 'newClass' to node
7867
	dojo.html.removeClass(node, oldClass);
7904
	dojo.html.removeClass(node, oldClass);
7868
	dojo.html.addClass(node, newClass);
7905
	dojo.html.addClass(node, newClass);
7869
}
7906
}
7870
 
7907
 
7871
// Enum type for getElementsByClass classMatchType arg:
7908
// Enum type for getElementsByClass classMatchType arg:
7872
dojo.html.classMatchType = {
7909
dojo.html.classMatchType = {
7873
	ContainsAll : 0, // all of the classes are part of the node's class (default)
7910
	ContainsAll : 0, // all of the classes are part of the node's class (default)
7874
	ContainsAny : 1, // any of the classes are part of the node's class
7911
	ContainsAny : 1, // any of the classes are part of the node's class
7875
	IsOnly : 2 // only all of the classes are part of the node's class
7912
	IsOnly : 2 // only all of the classes are part of the node's class
7876
}
7913
}
7877
 
7914
 
7878
 
7915
 
7879
dojo.html.getElementsByClass = function(
7916
dojo.html.getElementsByClass = function(
7880
	/* string */classStr, 
7917
	/* string */classStr, 
7881
	/* HTMLElement? */parent, 
7918
	/* HTMLElement? */parent, 
7882
	/* string? */nodeType, 
7919
	/* string? */nodeType, 
7883
	/* integer? */classMatchType, 
7920
	/* integer? */classMatchType, 
7884
	/* boolean? */useNonXpath
7921
	/* boolean? */useNonXpath
7885
){
7922
){
7886
	//	summary
7923
	//	summary
7887
	//	Returns an array of nodes for the given classStr, children of a
7924
	//	Returns an array of nodes for the given classStr, children of a
7888
	//	parent, and optionally of a certain nodeType
7925
	//	parent, and optionally of a certain nodeType
7889
	// FIXME: temporarily set to false because of several dojo tickets related
7926
	// FIXME: temporarily set to false because of several dojo tickets related
7890
	// to the xpath version not working consistently in firefox.
7927
	// to the xpath version not working consistently in firefox.
7891
	useNonXpath = false;
7928
	useNonXpath = false;
7892
	var _document = dojo.doc();
7929
	var _document = dojo.doc();
7893
	parent = dojo.byId(parent) || _document;
7930
	parent = dojo.byId(parent) || _document;
7894
	var classes = classStr.split(/\s+/g);
7931
	var classes = classStr.split(/\s+/g);
7895
	var nodes = [];
7932
	var nodes = [];
7896
	if( classMatchType != 1 && classMatchType != 2 ) classMatchType = 0; // make it enum
7933
	if( classMatchType != 1 && classMatchType != 2 ) classMatchType = 0; // make it enum
7897
	var reClass = new RegExp("(\\s|^)((" + classes.join(")|(") + "))(\\s|$)");
7934
	var reClass = new RegExp("(\\s|^)((" + classes.join(")|(") + "))(\\s|$)");
7898
	var srtLength = classes.join(" ").length;
7935
	var srtLength = classes.join(" ").length;
7899
	var candidateNodes = [];
7936
	var candidateNodes = [];
7900
	
7937
	
7901
	if(!useNonXpath && _document.evaluate) { // supports dom 3 xpath
7938
	if(!useNonXpath && _document.evaluate) { // supports dom 3 xpath
7902
		var xpath = ".//" + (nodeType || "*") + "[contains(";
7939
		var xpath = ".//" + (nodeType || "*") + "[contains(";
7903
		if(classMatchType != dojo.html.classMatchType.ContainsAny){
7940
		if(classMatchType != dojo.html.classMatchType.ContainsAny){
7904
			xpath += "concat(' ',@class,' '), ' " +
7941
			xpath += "concat(' ',@class,' '), ' " +
7905
			classes.join(" ') and contains(concat(' ',@class,' '), ' ") +
7942
			classes.join(" ') and contains(concat(' ',@class,' '), ' ") +
7906
			" ')";
7943
			" ')";
7907
			if (classMatchType == 2) {
7944
			if (classMatchType == 2) {
7908
				xpath += " and string-length(@class)="+srtLength+"]";
7945
				xpath += " and string-length(@class)="+srtLength+"]";
7909
			}else{
7946
			}else{
7910
				xpath += "]";
7947
				xpath += "]";
7911
			}
7948
			}
7912
		}else{
7949
		}else{
7913
			xpath += "concat(' ',@class,' '), ' " +
7950
			xpath += "concat(' ',@class,' '), ' " +
7914
			classes.join(" ') or contains(concat(' ',@class,' '), ' ") +
7951
			classes.join(" ') or contains(concat(' ',@class,' '), ' ") +
7915
			" ')]";
7952
			" ')]";
7916
		}
7953
		}
7917
		var xpathResult = _document.evaluate(xpath, parent, null, XPathResult.ANY_TYPE, null);
7954
		var xpathResult = _document.evaluate(xpath, parent, null, XPathResult.ANY_TYPE, null);
7918
		var result = xpathResult.iterateNext();
7955
		var result = xpathResult.iterateNext();
7919
		while(result){
7956
		while(result){
7920
			try{
7957
			try{
7921
				candidateNodes.push(result);
7958
				candidateNodes.push(result);
7922
				result = xpathResult.iterateNext();
7959
				result = xpathResult.iterateNext();
7923
			}catch(e){ break; }
7960
			}catch(e){ break; }
7924
		}
7961
		}
7925
		return candidateNodes;	//	NodeList
7962
		return candidateNodes;	//	NodeList
7926
	}else{
7963
	}else{
7927
		if(!nodeType){
7964
		if(!nodeType){
7928
			nodeType = "*";
7965
			nodeType = "*";
7929
		}
7966
		}
7930
		candidateNodes = parent.getElementsByTagName(nodeType);
7967
		candidateNodes = parent.getElementsByTagName(nodeType);
7931
 
7968
 
7932
		var node, i = 0;
7969
		var node, i = 0;
7933
		outer:
7970
		outer:
7934
		while(node = candidateNodes[i++]){
7971
		while(node = candidateNodes[i++]){
7935
			var nodeClasses = dojo.html.getClasses(node);
7972
			var nodeClasses = dojo.html.getClasses(node);
7936
			if(nodeClasses.length == 0){ continue outer; }
7973
			if(nodeClasses.length == 0){ continue outer; }
7937
			var matches = 0;
7974
			var matches = 0;
7938
	
7975
	
7939
			for(var j = 0; j < nodeClasses.length; j++){
7976
			for(var j = 0; j < nodeClasses.length; j++){
7940
				if(reClass.test(nodeClasses[j])){
7977
				if(reClass.test(nodeClasses[j])){
7941
					if(classMatchType == dojo.html.classMatchType.ContainsAny){
7978
					if(classMatchType == dojo.html.classMatchType.ContainsAny){
7942
						nodes.push(node);
7979
						nodes.push(node);
7943
						continue outer;
7980
						continue outer;
7944
					}else{
7981
					}else{
7945
						matches++;
7982
						matches++;
7946
					}
7983
					}
7947
				}else{
7984
				}else{
7948
					if(classMatchType == dojo.html.classMatchType.IsOnly){
7985
					if(classMatchType == dojo.html.classMatchType.IsOnly){
7949
						continue outer;
7986
						continue outer;
7950
					}
7987
					}
7951
				}
7988
				}
7952
			}
7989
			}
7953
	
7990
	
7954
			if(matches == classes.length){
7991
			if(matches == classes.length){
7955
				if(	(classMatchType == dojo.html.classMatchType.IsOnly)&&
7992
				if(	(classMatchType == dojo.html.classMatchType.IsOnly)&&
7956
					(matches == nodeClasses.length)){
7993
					(matches == nodeClasses.length)){
7957
					nodes.push(node);
7994
					nodes.push(node);
7958
				}else if(classMatchType == dojo.html.classMatchType.ContainsAll){
7995
				}else if(classMatchType == dojo.html.classMatchType.ContainsAll){
7959
					nodes.push(node);
7996
					nodes.push(node);
7960
				}
7997
				}
7961
			}
7998
			}
7962
		}
7999
		}
7963
		return nodes;	//	NodeList
8000
		return nodes;	//	NodeList
7964
	}
8001
	}
7965
}
8002
}
7966
dojo.html.getElementsByClassName = dojo.html.getElementsByClass;
8003
dojo.html.getElementsByClassName = dojo.html.getElementsByClass;
7967
 
8004
 
7968
dojo.html.toCamelCase = function(/* string */selector){
8005
dojo.html.toCamelCase = function(/* string */selector){
7969
	//	summary
8006
	//	summary
7970
	//	Translates a CSS selector string to a camel-cased one.
8007
	//	Translates a CSS selector string to a camel-cased one.
7971
	var arr = selector.split('-'), cc = arr[0];
8008
	var arr = selector.split('-'), cc = arr[0];
7972
	for(var i = 1; i < arr.length; i++) {
8009
	for(var i = 1; i < arr.length; i++) {
7973
		cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
8010
		cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
7974
	}
8011
	}
7975
	return cc;	//	string
8012
	return cc;	//	string
7976
}
8013
}
7977
 
8014
 
7978
dojo.html.toSelectorCase = function(/* string */selector){
8015
dojo.html.toSelectorCase = function(/* string */selector){
7979
	//	summary
8016
	//	summary
7980
	//	Translates a camel cased string to a selector cased one.
8017
	//	Translates a camel cased string to a selector cased one.
7981
	return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase();	//	string
8018
	return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase();	//	string
7982
}
8019
}
7983
 
8020
 
7984
if (dojo.render.html.ie) {
8021
if (dojo.render.html.ie) {
7985
	// IE branch
8022
	// IE branch
7986
	dojo.html.getComputedStyle = function(/*HTMLElement|String*/node, /*String*/property, /*String*/value) {
8023
	dojo.html.getComputedStyle = function(/*HTMLElement|String*/node, /*String*/property, /*String*/value) {
7987
		// summary
8024
		// summary
7988
		// Get the computed style value for style "property" on "node" (IE).
8025
		// Get the computed style value for style "property" on "node" (IE).
7989
		node = dojo.byId(node);  // FIXME: remove ability to access nodes by id for this time-critical function
8026
		node = dojo.byId(node); // FIXME: remove ability to access nodes by id for this time-critical function
7990
		if(!node || !node.style){return value;}
8027
		if(!node || !node.currentStyle){return value;}
7991
		// FIXME: standardize on camel-case input to improve speed
8028
		// FIXME: standardize on camel-case input to improve speed
7992
		return node.currentStyle[dojo.html.toCamelCase(property)]; // String
8029
		return node.currentStyle[dojo.html.toCamelCase(property)]; // String
7993
	}
8030
	}
7994
	// SJM: getComputedStyle should be abandoned and replaced with the below function.
8031
	// SJM: getComputedStyle should be abandoned and replaced with the below function.
7995
	// All our supported browsers can return CSS2 compliant CssStyleDeclaration objects
8032
	// All our supported browsers can return CSS2 compliant CssStyleDeclaration objects
7996
	// which can be queried directly for multiple styles.
8033
	// which can be queried directly for multiple styles.
7997
	dojo.html.getComputedStyles = function(/*HTMLElement*/node) {
8034
	dojo.html.getComputedStyles = function(/*HTMLElement*/node) {
7998
		// summary
8035
		// summary
7999
		// Get a style object containing computed styles for HTML Element node (IE).
8036
		// Get a style object containing computed styles for HTML Element node (IE).
8000
		return node.currentStyle; // CSSStyleDeclaration
8037
		return node.currentStyle; // CSSStyleDeclaration
8001
	}
8038
	}
8002
} else {
8039
} else {
8003
	// non-IE branch
8040
	// non-IE branch
8004
	dojo.html.getComputedStyle = function(/*HTMLElement|String*/node, /*String*/property, /*Any*/value) {
8041
	dojo.html.getComputedStyle = function(/*HTMLElement|String*/node, /*String*/property, /*Any*/value) {
8005
		// summary
8042
		// summary
8006
		// Get the computed style value for style "property" on "node" (non-IE).
8043
		// Get the computed style value for style "property" on "node" (non-IE).
8007
		node = dojo.byId(node);
8044
		node = dojo.byId(node);
8008
		if(!node || !node.style){return value;}
8045
		if(!node || !node.style){return value;}
8009
		var s = document.defaultView.getComputedStyle(node, null);
8046
		var s = document.defaultView.getComputedStyle(node, null);
8010
		// s may be null on Safari
8047
		// s may be null on Safari
8011
		return (s&&s[dojo.html.toCamelCase(property)])||''; // String
8048
		return (s&&s[dojo.html.toCamelCase(property)])||''; // String
8012
	}	
8049
	}	
8013
	// SJM: getComputedStyle should be abandoned and replaced with the below function.
8050
	// SJM: getComputedStyle should be abandoned and replaced with the below function.
8014
	// All our supported browsers can return CSS2 compliant CssStyleDeclaration objects
8051
	// All our supported browsers can return CSS2 compliant CssStyleDeclaration objects
8015
	// which can be queried directly for multiple styles.
8052
	// which can be queried directly for multiple styles.
8016
	dojo.html.getComputedStyles = function(node) {
8053
	dojo.html.getComputedStyles = function(node) {
8017
		// summary
8054
		// summary
8018
		// Get a style object containing computed styles for HTML Element node (non-IE).
8055
		// Get a style object containing computed styles for HTML Element node (non-IE).
8019
		return document.defaultView.getComputedStyle(node, null); // CSSStyleDeclaration
8056
		return document.defaultView.getComputedStyle(node, null); // CSSStyleDeclaration
8020
	}	
8057
	}	
8021
}
8058
}
8022
 
8059
 
8023
dojo.html.getStyleProperty = function(/* HTMLElement */node, /* string */cssSelector){
8060
dojo.html.getStyleProperty = function(/* HTMLElement */node, /* string */cssSelector){
8024
	//	summary
8061
	//	summary
8025
	//	Returns the value of the passed style
8062
	//	Returns the value of the passed style
8026
	node = dojo.byId(node);
8063
	node = dojo.byId(node);
8027
	return (node && node.style ? node.style[dojo.html.toCamelCase(cssSelector)] : undefined);	//	string
8064
	return (node && node.style ? node.style[dojo.html.toCamelCase(cssSelector)] : undefined);	//	string
8028
}
8065
}
8029
 
8066
 
8030
dojo.html.getStyle = function(/* HTMLElement */node, /* string */cssSelector){
8067
dojo.html.getStyle = function(/* HTMLElement */node, /* string */cssSelector){
8031
	//	summary
8068
	//	summary
8032
	//	Returns the computed value of the passed style
8069
	//	Returns the computed value of the passed style
8033
	var value = dojo.html.getStyleProperty(node, cssSelector);
8070
	var value = dojo.html.getStyleProperty(node, cssSelector);
8034
	return (value ? value : dojo.html.getComputedStyle(node, cssSelector));	//	string || integer
8071
	return (value ? value : dojo.html.getComputedStyle(node, cssSelector));	//	string || integer
8035
}
8072
}
8036
 
8073
 
8037
dojo.html.setStyle = function(/* HTMLElement */node, /* string */cssSelector, /* string */value){
8074
dojo.html.setStyle = function(/* HTMLElement */node, /* string */cssSelector, /* string */value){
8038
	//	summary
8075
	//	summary
8039
	//	Set the value of passed style on node
8076
	//	Set the value of passed style on node
8040
	node = dojo.byId(node);
8077
	node = dojo.byId(node);
8041
	if(node && node.style){
8078
	if(node && node.style){
8042
		var camelCased = dojo.html.toCamelCase(cssSelector);
8079
		var camelCased = dojo.html.toCamelCase(cssSelector);
8043
		node.style[camelCased] = value;
8080
		node.style[camelCased] = value;
8044
	}
8081
	}
8045
}
8082
}
8046
 
8083
 
8047
dojo.html.setStyleText = function (/* HTMLElement */target, /* string */text) {
8084
dojo.html.setStyleText = function (/* HTMLElement */target, /* string */text) {
8048
	//	summary
8085
	//	summary
8049
	//	Try to set the entire cssText property of the passed target; equiv of setting style attribute.
8086
	//	Try to set the entire cssText property of the passed target; equiv of setting style attribute.
8050
	try {
8087
	try {
8051
	 	target.style.cssText = text;
8088
	 	target.style.cssText = text;
8052
	} catch (e) {
8089
	} catch (e) {
8053
		target.setAttribute("style", text);
8090
		target.setAttribute("style", text);
8054
	}
8091
	}
8055
}
8092
}
8056
 
8093
 
8057
dojo.html.copyStyle = function(/* HTMLElement */target, /* HTMLElement */source){
8094
dojo.html.copyStyle = function(/* HTMLElement */target, /* HTMLElement */source){
8058
	//	summary
8095
	//	summary
8059
	// work around for opera which doesn't have cssText, and for IE which fails on setAttribute 
8096
	// work around for opera which doesn't have cssText, and for IE which fails on setAttribute 
8060
	if(!source.style.cssText){ 
8097
	if(!source.style.cssText){ 
8061
		target.setAttribute("style", source.getAttribute("style")); 
8098
		target.setAttribute("style", source.getAttribute("style")); 
8062
	}else{
8099
	}else{
8063
		target.style.cssText = source.style.cssText; 
8100
		target.style.cssText = source.style.cssText; 
8064
	}
8101
	}
8065
	dojo.html.addClass(target, dojo.html.getClass(source));
8102
	dojo.html.addClass(target, dojo.html.getClass(source));
8066
}
8103
}
8067
 
8104
 
8068
dojo.html.getUnitValue = function(/* HTMLElement */node, /* string */cssSelector, /* boolean? */autoIsZero){
8105
dojo.html.getUnitValue = function(/* HTMLElement */node, /* string */cssSelector, /* boolean? */autoIsZero){
8069
	//	summary
8106
	//	summary
8070
	//	Get the value of passed selector, with the specific units used
8107
	//	Get the value of passed selector, with the specific units used
8071
	var s = dojo.html.getComputedStyle(node, cssSelector);
8108
	var s = dojo.html.getComputedStyle(node, cssSelector);
8072
	if((!s)||((s == 'auto')&&(autoIsZero))){ 
8109
	if((!s)||((s == 'auto')&&(autoIsZero))){ 
8073
		return { value: 0, units: 'px' };	//	object 
8110
		return { value: 0, units: 'px' };	//	object 
8074
	}
8111
	}
8075
	// FIXME: is regex inefficient vs. parseInt or some manual test? 
8112
	// FIXME: is regex inefficient vs. parseInt or some manual test? 
8076
	var match = s.match(/(\-?[\d.]+)([a-z%]*)/i);
8113
	var match = s.match(/(\-?[\d.]+)([a-z%]*)/i);
8077
	if (!match){return dojo.html.getUnitValue.bad;}
8114
	if (!match){return dojo.html.getUnitValue.bad;}
8078
	return { value: Number(match[1]), units: match[2].toLowerCase() };	//	object
8115
	return { value: Number(match[1]), units: match[2].toLowerCase() };	//	object
8079
}
8116
}
8080
dojo.html.getUnitValue.bad = { value: NaN, units: '' };
8117
dojo.html.getUnitValue.bad = { value: NaN, units: '' };
8081
 
8118
 
8082
if (dojo.render.html.ie) {
8119
if (dojo.render.html.ie) {
8083
	// IE branch
8120
	// IE branch
8084
	dojo.html.toPixelValue = function(/* HTMLElement */element, /* String */styleValue){
8121
	dojo.html.toPixelValue = function(/* HTMLElement */element, /* String */styleValue){
8085
		// summary
8122
		// summary
8086
		//  Extract value in pixels from styleValue (IE version).
8123
		//  Extract value in pixels from styleValue (IE version).
8087
		//  If a value cannot be extracted, zero is returned.
8124
		//  If a value cannot be extracted, zero is returned.
8088
		if(!styleValue){return 0;}
8125
		if(!styleValue){return 0;}
8089
		if(styleValue.slice(-2) == 'px'){return parseFloat(styleValue);}
8126
		if(styleValue.slice(-2) == 'px'){return parseFloat(styleValue);}
8090
		var pixelValue = 0;
8127
		var pixelValue = 0;
8091
		with(element){
8128
		with(element){
8092
			var sLeft = style.left;
8129
			var sLeft = style.left;
8093
			var rsLeft = runtimeStyle.left;
8130
			var rsLeft = runtimeStyle.left;
8094
			runtimeStyle.left = currentStyle.left;
8131
			runtimeStyle.left = currentStyle.left;
8095
			try {
8132
			try {
8096
				style.left = styleValue || 0;
8133
				style.left = styleValue || 0;
8097
				pixelValue = style.pixelLeft;
8134
				pixelValue = style.pixelLeft;
8098
				style.left = sLeft;
8135
				style.left = sLeft;
8099
				runtimeStyle.left = rsLeft;
8136
				runtimeStyle.left = rsLeft;
8100
			}catch(e){
8137
			}catch(e){
8101
				// FIXME: it's possible for styleValue to be incompatible with
8138
				// FIXME: it's possible for styleValue to be incompatible with
8102
				// style.left. In particular, border width values of 
8139
				// style.left. In particular, border width values of 
8103
				// "thick", "medium", or "thin" will provoke an exception.
8140
				// "thick", "medium", or "thin" will provoke an exception.
8104
			}
8141
			}
8105
		}
8142
		}
8106
		return pixelValue; // Number
8143
		return pixelValue; // Number
8107
	}
8144
	}
8108
} else {
8145
} else {
8109
	// non-IE branch
8146
	// non-IE branch
8110
	dojo.html.toPixelValue = function(/* HTMLElement */element, /* String */styleValue){
8147
	dojo.html.toPixelValue = function(/* HTMLElement */element, /* String */styleValue){
8111
		// summary
8148
		// summary
8112
		//  Extract value in pixels from styleValue (non-IE version).
8149
		//  Extract value in pixels from styleValue (non-IE version).
8113
		//  If a value cannot be extracted, zero is returned.
8150
		//  If a value cannot be extracted, zero is returned.
8114
		return (styleValue && (styleValue.slice(-2)=='px') ? parseFloat(styleValue) : 0); // Number
8151
		return (styleValue && (styleValue.slice(-2)=='px') ? parseFloat(styleValue) : 0); // Number
8115
	}
8152
	}
8116
}
8153
}
8117
 
8154
 
8118
dojo.html.getPixelValue = function(/* HTMLElement */node, /* string */styleProperty, /* boolean? */autoIsZero){
8155
dojo.html.getPixelValue = function(/* HTMLElement */node, /* string */styleProperty, /* boolean? */autoIsZero){
8119
	// summary
8156
	// summary
8120
	//  Get a computed style value, in pixels.
8157
	//  Get a computed style value, in pixels.
8121
	// node: HTMLElement
8158
	// node: HTMLElement
8122
	//  Node to interrogate
8159
	//  Node to interrogate
8123
	// styleProperty: String
8160
	// styleProperty: String
8124
	//  Style property to query, in either css-selector or camelCase (property) format.
8161
	//  Style property to query, in either css-selector or camelCase (property) format.
8125
	// autoIsZero: Boolean
8162
	// autoIsZero: Boolean
8126
	//  Deprecated. Any value that cannot be converted to pixels is returned as zero.
8163
	//  Deprecated. Any value that cannot be converted to pixels is returned as zero.
8127
	// 
8164
	// 
8128
	//  summary
8165
	//  summary
8129
	//  Get the value of passed selector in pixels.
8166
	//  Get the value of passed selector in pixels.
8130
	//
8167
	//
8131
	return dojo.html.toPixelValue(node, dojo.html.getComputedStyle(node, styleProperty));
8168
	return dojo.html.toPixelValue(node, dojo.html.getComputedStyle(node, styleProperty));
8132
} 
8169
} 
8133
 
8170
 
8134
dojo.html.setPositivePixelValue = function(/* HTMLElement */node, /* string */selector, /* integer */value){
8171
dojo.html.setPositivePixelValue = function(/* HTMLElement */node, /* string */selector, /* integer */value){
8135
	//	summary
8172
	//	summary
8136
	//	Attempt to set the value of selector on node as a positive pixel value.
8173
	//	Attempt to set the value of selector on node as a positive pixel value.
8137
	if(isNaN(value)){return false;}
8174
	if(isNaN(value)){return false;}
8138
	node.style[selector] = Math.max(0, value) + 'px'; 
8175
	node.style[selector] = Math.max(0, value) + 'px'; 
8139
	return true;	//	boolean
8176
	return true;	//	boolean
8140
}
8177
}
8141
 
8178
 
8142
dojo.html.styleSheet = null;
8179
dojo.html.styleSheet = null;
8143
 
8180
 
8144
// FIXME: this is a really basic stub for adding and removing cssRules, but
8181
// FIXME: this is a really basic stub for adding and removing cssRules, but
8145
// it assumes that you know the index of the cssRule that you want to add 
8182
// it assumes that you know the index of the cssRule that you want to add 
8146
// or remove, making it less than useful.  So we need something that can 
8183
// or remove, making it less than useful.  So we need something that can 
8147
// search for the selector that you you want to remove.
8184
// search for the selector that you you want to remove.
8148
dojo.html.insertCssRule = function(/* string */selector, /* string */declaration, /* integer? */index) {
8185
dojo.html.insertCssRule = function(/* string */selector, /* string */declaration, /* integer? */index) {
8149
	//	summary
8186
	//	summary
8150
	//	Attempt to insert declaration as selector on the internal stylesheet; if index try to set it there.
8187
	//	Attempt to insert declaration as selector on the internal stylesheet; if index try to set it there.
8151
	if (!dojo.html.styleSheet) {
8188
	if (!dojo.html.styleSheet) {
8152
		if (document.createStyleSheet) { // IE
8189
		if (document.createStyleSheet) { // IE
8153
			dojo.html.styleSheet = document.createStyleSheet();
8190
			dojo.html.styleSheet = document.createStyleSheet();
8154
		} else if (document.styleSheets[0]) { // rest
8191
		} else if (document.styleSheets[0]) { // rest
8155
			// FIXME: should create a new style sheet here
8192
			// FIXME: should create a new style sheet here
8156
			// fall back on an exsiting style sheet
8193
			// fall back on an exsiting style sheet
8157
			dojo.html.styleSheet = document.styleSheets[0];
8194
			dojo.html.styleSheet = document.styleSheets[0];
8158
		} else { 
8195
		} else { 
8159
			return null;	//	integer 
8196
			return null;	//	integer 
8160
		} // fail
8197
		} // fail
8161
	}
8198
	}
8162
 
8199
 
8163
	if (arguments.length < 3) { // index may == 0
8200
	if (arguments.length < 3) { // index may == 0
8164
		if (dojo.html.styleSheet.cssRules) { // W3
8201
		if (dojo.html.styleSheet.cssRules) { // W3
8165
			index = dojo.html.styleSheet.cssRules.length;
8202
			index = dojo.html.styleSheet.cssRules.length;
8166
		} else if (dojo.html.styleSheet.rules) { // IE
8203
		} else if (dojo.html.styleSheet.rules) { // IE
8167
			index = dojo.html.styleSheet.rules.length;
8204
			index = dojo.html.styleSheet.rules.length;
8168
		} else { 
8205
		} else { 
8169
			return null;	//	integer 
8206
			return null;	//	integer 
8170
		} // fail
8207
		} // fail
8171
	}
8208
	}
8172
 
8209
 
8173
	if (dojo.html.styleSheet.insertRule) { // W3
8210
	if (dojo.html.styleSheet.insertRule) { // W3
8174
		var rule = selector + " { " + declaration + " }";
8211
		var rule = selector + " { " + declaration + " }";
8175
		return dojo.html.styleSheet.insertRule(rule, index);	//	integer
8212
		return dojo.html.styleSheet.insertRule(rule, index);	//	integer
8176
	} else if (dojo.html.styleSheet.addRule) { // IE
8213
	} else if (dojo.html.styleSheet.addRule) { // IE
8177
		return dojo.html.styleSheet.addRule(selector, declaration, index);	//	integer
8214
		return dojo.html.styleSheet.addRule(selector, declaration, index);	//	integer
8178
	} else { 
8215
	} else { 
8179
		return null; // integer
8216
		return null; // integer
8180
	} // fail
8217
	} // fail
8181
}
8218
}
8182
 
8219
 
8183
dojo.html.removeCssRule = function(/* integer? */index){
8220
dojo.html.removeCssRule = function(/* integer? */index){
8184
	//	summary
8221
	//	summary
8185
	//	Attempt to remove the rule at index.
8222
	//	Attempt to remove the rule at index.
8186
	if(!dojo.html.styleSheet){
8223
	if(!dojo.html.styleSheet){
8187
		dojo.debug("no stylesheet defined for removing rules");
8224
		dojo.debug("no stylesheet defined for removing rules");
8188
		return false;
8225
		return false;
8189
	}
8226
	}
8190
	if(dojo.render.html.ie){
8227
	if(dojo.render.html.ie){
8191
		if(!index){
8228
		if(!index){
8192
			index = dojo.html.styleSheet.rules.length;
8229
			index = dojo.html.styleSheet.rules.length;
8193
			dojo.html.styleSheet.removeRule(index);
8230
			dojo.html.styleSheet.removeRule(index);
8194
		}
8231
		}
8195
	}else if(document.styleSheets[0]){
8232
	}else if(document.styleSheets[0]){
8196
		if(!index){
8233
		if(!index){
8197
			index = dojo.html.styleSheet.cssRules.length;
8234
			index = dojo.html.styleSheet.cssRules.length;
8198
		}
8235
		}
8199
		dojo.html.styleSheet.deleteRule(index);
8236
		dojo.html.styleSheet.deleteRule(index);
8200
	}
8237
	}
8201
	return true;	//	boolean
8238
	return true;	//	boolean
8202
}
8239
}
8203
 
8240
 
8204
dojo.html._insertedCssFiles = []; // cache container needed because IE reformats cssText when added to DOM
8241
dojo.html._insertedCssFiles = []; // cache container needed because IE reformats cssText when added to DOM
8205
dojo.html.insertCssFile = function(/* string */URI, /* HTMLDocument? */doc, /* boolean? */checkDuplicates, /* boolean */fail_ok){
8242
dojo.html.insertCssFile = function(/* string */URI, /* HTMLDocument? */doc, /* boolean? */checkDuplicates, /* boolean */fail_ok){
8206
	//	summary
8243
	//	summary
8207
	// calls css by XmlHTTP and inserts it into DOM as <style [widgetType="widgetType"]> *downloaded cssText*</style>
8244
	// calls css by XmlHTTP and inserts it into DOM as <style [widgetType="widgetType"]> *downloaded cssText*</style>
8208
	if(!URI){ return; }
8245
	if(!URI){ return; }
8209
	if(!doc){ doc = document; }
8246
	if(!doc){ doc = document; }
8210
	var cssStr = dojo.hostenv.getText(URI, false, fail_ok);
8247
	var cssStr = dojo.hostenv.getText(URI, false, fail_ok);
8211
	if(cssStr===null){ return; }
8248
	if(cssStr===null){ return; }
8212
	cssStr = dojo.html.fixPathsInCssText(cssStr, URI);
8249
	cssStr = dojo.html.fixPathsInCssText(cssStr, URI);
8213
 
8250
 
8214
	if(checkDuplicates){
8251
	if(checkDuplicates){
8215
		var idx = -1, node, ent = dojo.html._insertedCssFiles;
8252
		var idx = -1, node, ent = dojo.html._insertedCssFiles;
8216
		for(var i = 0; i < ent.length; i++){
8253
		for(var i = 0; i < ent.length; i++){
8217
			if((ent[i].doc == doc) && (ent[i].cssText == cssStr)){
8254
			if((ent[i].doc == doc) && (ent[i].cssText == cssStr)){
8218
				idx = i; node = ent[i].nodeRef;
8255
				idx = i; node = ent[i].nodeRef;
8219
				break;
8256
				break;
8220
			}
8257
			}
8221
		}
8258
		}
8222
		// make sure we havent deleted our node
8259
		// make sure we havent deleted our node
8223
		if(node){
8260
		if(node){
8224
			var styles = doc.getElementsByTagName("style");
8261
			var styles = doc.getElementsByTagName("style");
8225
			for(var i = 0; i < styles.length; i++){
8262
			for(var i = 0; i < styles.length; i++){
8226
				if(styles[i] == node){
8263
				if(styles[i] == node){
8227
					return;
8264
					return;
8228
				}
8265
				}
8229
			}
8266
			}
8230
			// delete this entry
8267
			// delete this entry
8231
			dojo.html._insertedCssFiles.shift(idx, 1);
8268
			dojo.html._insertedCssFiles.shift(idx, 1);
8232
		}
8269
		}
8233
	}
8270
	}
8234
 
8271
 
8235
	var style = dojo.html.insertCssText(cssStr, doc);
8272
	var style = dojo.html.insertCssText(cssStr, doc);
8236
	dojo.html._insertedCssFiles.push({'doc': doc, 'cssText': cssStr, 'nodeRef': style});
8273
	dojo.html._insertedCssFiles.push({'doc': doc, 'cssText': cssStr, 'nodeRef': style});
8237
 
8274
 
8238
	// insert custom attribute ex dbgHref="../foo.css" usefull when debugging in DOM inspectors, no?
8275
	// insert custom attribute ex dbgHref="../foo.css" usefull when debugging in DOM inspectors, no?
8239
	if(style && djConfig.isDebug){
8276
	if(style && djConfig.isDebug){
8240
		style.setAttribute("dbgHref", URI);
8277
		style.setAttribute("dbgHref", URI);
8241
	}
8278
	}
8242
	return style;	//	HTMLStyleElement
8279
	return style;	//	HTMLStyleElement
8243
}
8280
}
8244
 
8281
 
8245
dojo.html.insertCssText = function(/* string */cssStr, /* HTMLDocument? */doc, /* string? */URI){
8282
dojo.html.insertCssText = function(/* string */cssStr, /* HTMLDocument? */doc, /* string? */URI){
8246
	//	summary
8283
	//	summary
8247
	//	Attempt to insert CSS rules into the document through inserting a style element
8284
	//	Attempt to insert CSS rules into the document through inserting a style element
8248
	// DomNode Style  = insertCssText(String ".dojoMenu {color: green;}"[, DomDoc document, dojo.uri.Uri Url ])
8285
	// DomNode Style  = insertCssText(String ".dojoMenu {color: green;}"[, DomDoc document, dojo.uri.Uri Url ])
8249
	if(!cssStr){ 
8286
	if(!cssStr){ 
8250
		return; //	HTMLStyleElement
8287
		return; //	HTMLStyleElement
8251
	}
8288
	}
8252
	if(!doc){ doc = document; }
8289
	if(!doc){ doc = document; }
8253
	if(URI){// fix paths in cssStr
8290
	if(URI){// fix paths in cssStr
8254
		cssStr = dojo.html.fixPathsInCssText(cssStr, URI);
8291
		cssStr = dojo.html.fixPathsInCssText(cssStr, URI);
8255
	}
8292
	}
8256
	var style = doc.createElement("style");
8293
	var style = doc.createElement("style");
8257
	style.setAttribute("type", "text/css");
8294
	style.setAttribute("type", "text/css");
8258
	// IE is b0rken enough to require that we add the element to the doc
8295
	// IE is b0rken enough to require that we add the element to the doc
8259
	// before changing it's properties
8296
	// before changing it's properties
8260
	var head = doc.getElementsByTagName("head")[0];
8297
	var head = doc.getElementsByTagName("head")[0];
8261
	if(!head){ // must have a head tag 
8298
	if(!head){ // must have a head tag 
8262
		dojo.debug("No head tag in document, aborting styles");
8299
		dojo.debug("No head tag in document, aborting styles");
8263
		return;	//	HTMLStyleElement
8300
		return;	//	HTMLStyleElement
8264
	}else{
8301
	}else{
8265
		head.appendChild(style);
8302
		head.appendChild(style);
8266
	}
8303
	}
8267
	if(style.styleSheet){// IE
8304
	if(style.styleSheet){// IE
8268
		var setFunc = function(){ 
8305
		var setFunc = function(){ 
8269
			try{
8306
			try{
8270
				style.styleSheet.cssText = cssStr;
8307
				style.styleSheet.cssText = cssStr;
8271
			}catch(e){ dojo.debug(e); }
8308
			}catch(e){ dojo.debug(e); }
8272
		};
8309
		};
8273
		if(style.styleSheet.disabled){
8310
		if(style.styleSheet.disabled){
8274
			setTimeout(setFunc, 10);
8311
			setTimeout(setFunc, 10);
8275
		}else{
8312
		}else{
8276
			setFunc();
8313
			setFunc();
8277
		}
8314
		}
8278
	}else{ // w3c
8315
	}else{ // w3c
8279
		var cssText = doc.createTextNode(cssStr);
8316
		var cssText = doc.createTextNode(cssStr);
8280
		style.appendChild(cssText);
8317
		style.appendChild(cssText);
8281
	}
8318
	}
8282
	return style;	//	HTMLStyleElement
8319
	return style;	//	HTMLStyleElement
8283
}
8320
}
8284
 
8321
 
8285
dojo.html.fixPathsInCssText = function(/* string */cssStr, /* string */URI){
8322
dojo.html.fixPathsInCssText = function(/* string */cssStr, /* string */URI){
8286
	//	summary
8323
	//	summary
8287
	// usage: cssText comes from dojoroot/src/widget/templates/Foobar.css
8324
	// usage: cssText comes from dojoroot/src/widget/templates/Foobar.css
8288
	// 	it has .dojoFoo { background-image: url(images/bar.png);} then uri should point to dojoroot/src/widget/templates/
8325
	// 	it has .dojoFoo { background-image: url(images/bar.png);} then uri should point to dojoroot/src/widget/templates/
8289
	if(!cssStr || !URI){ return; }
8326
	if(!cssStr || !URI){ return; }
8290
	var match, str = "", url = "", urlChrs = "[\\t\\s\\w\\(\\)\\/\\.\\\\'\"-:#=&?~]+";
8327
	var match, str = "", url = "", urlChrs = "[\\t\\s\\w\\(\\)\\/\\.\\\\'\"-:#=&?~]+";
8291
	var regex = new RegExp('url\\(\\s*('+urlChrs+')\\s*\\)');
8328
	var regex = new RegExp('url\\(\\s*('+urlChrs+')\\s*\\)');
8292
	var regexProtocol = /(file|https?|ftps?):\/\//;
8329
	var regexProtocol = /(file|https?|ftps?):\/\//;
8293
	regexTrim = new RegExp("^[\\s]*(['\"]?)("+urlChrs+")\\1[\\s]*?$");
8330
	regexTrim = new RegExp("^[\\s]*(['\"]?)("+urlChrs+")\\1[\\s]*?$");
8294
	if(dojo.render.html.ie55 || dojo.render.html.ie60){
8331
	if(dojo.render.html.ie55 || dojo.render.html.ie60){
8295
		var regexIe = new RegExp("AlphaImageLoader\\((.*)src\=['\"]("+urlChrs+")['\"]");
8332
		var regexIe = new RegExp("AlphaImageLoader\\((.*)src\=['\"]("+urlChrs+")['\"]");
8296
		// TODO: need to decide how to handle relative paths and AlphaImageLoader see #1441
8333
		// TODO: need to decide how to handle relative paths and AlphaImageLoader see #1441
8297
		// current implementation breaks on build with intern_strings
8334
		// current implementation breaks on build with intern_strings
8298
		while(match = regexIe.exec(cssStr)){
8335
		while(match = regexIe.exec(cssStr)){
8299
			url = match[2].replace(regexTrim, "$2");
8336
			url = match[2].replace(regexTrim, "$2");
8300
			if(!regexProtocol.exec(url)){
8337
			if(!regexProtocol.exec(url)){
8301
				url = (new dojo.uri.Uri(URI, url).toString());
8338
				url = (new dojo.uri.Uri(URI, url).toString());
8302
			}
8339
			}
8303
			str += cssStr.substring(0, match.index) + "AlphaImageLoader(" + match[1] + "src='" + url + "'";
8340
			str += cssStr.substring(0, match.index) + "AlphaImageLoader(" + match[1] + "src='" + url + "'";
8304
			cssStr = cssStr.substr(match.index + match[0].length);
8341
			cssStr = cssStr.substr(match.index + match[0].length);
8305
		}
8342
		}
8306
		cssStr = str + cssStr;
8343
		cssStr = str + cssStr;
8307
		str = "";
8344
		str = "";
8308
	}
8345
	}
8309
 
8346
 
8310
	while(match = regex.exec(cssStr)){
8347
	while(match = regex.exec(cssStr)){
8311
		url = match[1].replace(regexTrim, "$2");
8348
		url = match[1].replace(regexTrim, "$2");
8312
		if(!regexProtocol.exec(url)){
8349
		if(!regexProtocol.exec(url)){
8313
			url = (new dojo.uri.Uri(URI, url).toString());
8350
			url = (new dojo.uri.Uri(URI, url).toString());
8314
		}
8351
		}
8315
		str += cssStr.substring(0, match.index) + "url(" + url + ")";
8352
		str += cssStr.substring(0, match.index) + "url(" + url + ")";
8316
		cssStr = cssStr.substr(match.index + match[0].length);
8353
		cssStr = cssStr.substr(match.index + match[0].length);
8317
	}
8354
	}
8318
	return str + cssStr;	//	string
8355
	return str + cssStr;	//	string
8319
}
8356
}
8320
 
8357
 
8321
dojo.html.setActiveStyleSheet = function(/* string */title){
8358
dojo.html.setActiveStyleSheet = function(/* string */title){
8322
	//	summary
8359
	//	summary
8323
	//	Activate style sheet with specified title.
8360
	//	Activate style sheet with specified title.
8324
	var i = 0, a, els = dojo.doc().getElementsByTagName("link");
8361
	var i = 0, a, els = dojo.doc().getElementsByTagName("link");
8325
	while (a = els[i++]) {
8362
	while (a = els[i++]) {
8326
		if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")){
8363
		if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")){
8327
			a.disabled = true;
8364
			a.disabled = true;
8328
			if (a.getAttribute("title") == title) { a.disabled = false; }
8365
			if (a.getAttribute("title") == title) { a.disabled = false; }
8329
		}
8366
		}
8330
	}
8367
	}
8331
}
8368
}
8332
 
8369
 
8333
dojo.html.getActiveStyleSheet = function(){
8370
dojo.html.getActiveStyleSheet = function(){
8334
	//	summary
8371
	//	summary
8335
	//	return the title of the currently active stylesheet
8372
	//	return the title of the currently active stylesheet
8336
	var i = 0, a, els = dojo.doc().getElementsByTagName("link");
8373
	var i = 0, a, els = dojo.doc().getElementsByTagName("link");
8337
	while (a = els[i++]) {
8374
	while (a = els[i++]) {
8338
		if (a.getAttribute("rel").indexOf("style") != -1 
8375
		if (a.getAttribute("rel").indexOf("style") != -1 
8339
			&& a.getAttribute("title") 
8376
			&& a.getAttribute("title") 
8340
			&& !a.disabled
8377
			&& !a.disabled
8341
		){
8378
		){
8342
			return a.getAttribute("title");	//	string 
8379
			return a.getAttribute("title");	//	string 
8343
		}
8380
		}
8344
	}
8381
	}
8345
	return null;	//	string
8382
	return null;	//	string
8346
}
8383
}
8347
 
8384
 
8348
dojo.html.getPreferredStyleSheet = function(){
8385
dojo.html.getPreferredStyleSheet = function(){
8349
	//	summary
8386
	//	summary
8350
	//	Return the preferred stylesheet title (i.e. link without alt attribute)
8387
	//	Return the preferred stylesheet title (i.e. link without alt attribute)
8351
	var i = 0, a, els = dojo.doc().getElementsByTagName("link");
8388
	var i = 0, a, els = dojo.doc().getElementsByTagName("link");
8352
	while (a = els[i++]) {
8389
	while (a = els[i++]) {
8353
		if(a.getAttribute("rel").indexOf("style") != -1
8390
		if(a.getAttribute("rel").indexOf("style") != -1
8354
			&& a.getAttribute("rel").indexOf("alt") == -1
8391
			&& a.getAttribute("rel").indexOf("alt") == -1
8355
			&& a.getAttribute("title")
8392
			&& a.getAttribute("title")
8356
		){ 
8393
		){ 
8357
			return a.getAttribute("title"); 	//	string
8394
			return a.getAttribute("title"); 	//	string
8358
		}
8395
		}
8359
	}
8396
	}
8360
	return null;	//	string
8397
	return null;	//	string
8361
}
8398
}
8362
 
8399
 
8363
dojo.html.applyBrowserClass = function(/* HTMLElement */node){
8400
dojo.html.applyBrowserClass = function(/* HTMLElement */node){
8364
	//	summary
8401
	//	summary
8365
	//	Applies pre-set class names based on browser & version to the passed node.
8402
	//	Applies pre-set class names based on browser & version to the passed node.
8366
	//	Modified version of Morris' CSS hack.
8403
	//	Modified version of Morris' CSS hack.
8367
	var drh=dojo.render.html;
8404
	var drh=dojo.render.html;
8368
	var classes = {
8405
	var classes = {
8369
		dj_ie: drh.ie,
8406
		dj_ie: drh.ie,
8370
		dj_ie55: drh.ie55,
8407
		dj_ie55: drh.ie55,
8371
		dj_ie6: drh.ie60,
8408
		dj_ie6: drh.ie60,
8372
		dj_ie7: drh.ie70,
8409
		dj_ie7: drh.ie70,
8373
		dj_iequirks: drh.ie && drh.quirks,
8410
		dj_iequirks: drh.ie && drh.quirks,
8374
		dj_opera: drh.opera,
8411
		dj_opera: drh.opera,
8375
		dj_opera8: drh.opera && (Math.floor(dojo.render.version)==8),
8412
		dj_opera8: drh.opera && (Math.floor(dojo.render.version)==8),
8376
		dj_opera9: drh.opera && (Math.floor(dojo.render.version)==9),
8413
		dj_opera9: drh.opera && (Math.floor(dojo.render.version)==9),
8377
		dj_khtml: drh.khtml,
8414
		dj_khtml: drh.khtml,
8378
		dj_safari: drh.safari,
8415
		dj_safari: drh.safari,
8379
		dj_gecko: drh.mozilla
8416
		dj_gecko: drh.mozilla
8380
	}; // no dojo unsupported browsers
8417
	}; // no dojo unsupported browsers
8381
	for(var p in classes){
8418
	for(var p in classes){
8382
		if(classes[p]){
8419
		if(classes[p]){
8383
			dojo.html.addClass(node, p);
8420
			dojo.html.addClass(node, p);
8384
		}
8421
		}
8385
	}
8422
	}
8386
};
8423
};
8387
 
8424
 
8388
dojo.provide("dojo.html.display");
8425
dojo.provide("dojo.html.display");
8389
 
8426
 
8390
 
8427
 
8391
dojo.html._toggle = function(node, tester, setter){
8428
dojo.html._toggle = function(node, tester, setter){
8392
	node = dojo.byId(node);
8429
	node = dojo.byId(node);
8393
	setter(node, !tester(node));
8430
	setter(node, !tester(node));
8394
	return tester(node);
8431
	return tester(node);
8395
}
8432
}
8396
 
8433
 
8397
dojo.html.show = function(/* HTMLElement */node){
8434
dojo.html.show = function(/* HTMLElement */node){
8398
	//	summary
8435
	//	summary
8399
	//	Show the passed element by reverting display property set by dojo.html.hide
8436
	//	Show the passed element by reverting display property set by dojo.html.hide
8400
	node = dojo.byId(node);
8437
	node = dojo.byId(node);
8401
	if(dojo.html.getStyleProperty(node, 'display')=='none'){
8438
	if(dojo.html.getStyleProperty(node, 'display')=='none'){
8402
		dojo.html.setStyle(node, 'display', (node.dojoDisplayCache||''));
8439
		dojo.html.setStyle(node, 'display', (node.dojoDisplayCache||''));
8403
		node.dojoDisplayCache = undefined;	// cannot use delete on a node in IE6
8440
		node.dojoDisplayCache = undefined;	// cannot use delete on a node in IE6
8404
	}
8441
	}
8405
}
8442
}
8406
 
8443
 
8407
dojo.html.hide = function(/* HTMLElement */node){
8444
dojo.html.hide = function(/* HTMLElement */node){
8408
	//	summary
8445
	//	summary
8409
	//	Hide the passed element by setting display:none
8446
	//	Hide the passed element by setting display:none
8410
	node = dojo.byId(node);
8447
	node = dojo.byId(node);
8411
	if(typeof node["dojoDisplayCache"] == "undefined"){ // it could == '', so we cannot say !node.dojoDisplayCount
8448
	if(typeof node["dojoDisplayCache"] == "undefined"){ // it could == '', so we cannot say !node.dojoDisplayCount
8412
		var d = dojo.html.getStyleProperty(node, 'display')
8449
		var d = dojo.html.getStyleProperty(node, 'display')
8413
		if(d!='none'){
8450
		if(d!='none'){
8414
			node.dojoDisplayCache = d;
8451
			node.dojoDisplayCache = d;
8415
		}
8452
		}
8416
	}
8453
	}
8417
	dojo.html.setStyle(node, 'display', 'none');
8454
	dojo.html.setStyle(node, 'display', 'none');
8418
}
8455
}
8419
 
8456
 
8420
dojo.html.setShowing = function(/* HTMLElement */node, /* boolean? */showing){
8457
dojo.html.setShowing = function(/* HTMLElement */node, /* boolean? */showing){
8421
	//	summary
8458
	//	summary
8422
	// Calls show() if showing is true, hide() otherwise
8459
	// Calls show() if showing is true, hide() otherwise
8423
	dojo.html[(showing ? 'show' : 'hide')](node);
8460
	dojo.html[(showing ? 'show' : 'hide')](node);
8424
}
8461
}
8425
 
8462
 
8426
dojo.html.isShowing = function(/* HTMLElement */node){
8463
dojo.html.isShowing = function(/* HTMLElement */node){
8427
	//	summary
8464
	//	summary
8428
	//	Returns whether the element is displayed or not.
8465
	//	Returns whether the element is displayed or not.
8429
	// FIXME: returns true if node is bad, isHidden would be easier to make correct
8466
	// FIXME: returns true if node is bad, isHidden would be easier to make correct
8430
	return (dojo.html.getStyleProperty(node, 'display') != 'none');	//	boolean
8467
	return (dojo.html.getStyleProperty(node, 'display') != 'none');	//	boolean
8431
}
8468
}
8432
 
8469
 
8433
dojo.html.toggleShowing = function(/* HTMLElement */node){
8470
dojo.html.toggleShowing = function(/* HTMLElement */node){
8434
	//	summary
8471
	//	summary
8435
	// Call setShowing() on node with the complement of isShowing(), then return the new value of isShowing()
8472
	// Call setShowing() on node with the complement of isShowing(), then return the new value of isShowing()
8436
	return dojo.html._toggle(node, dojo.html.isShowing, dojo.html.setShowing);	//	boolean
8473
	return dojo.html._toggle(node, dojo.html.isShowing, dojo.html.setShowing);	//	boolean
8437
}
8474
}
8438
 
8475
 
8439
// Simple mapping of tag names to display values
8476
// Simple mapping of tag names to display values
8440
// FIXME: simplistic 
8477
// FIXME: simplistic 
8441
dojo.html.displayMap = { tr: '', td: '', th: '', img: 'inline', span: 'inline', input: 'inline', button: 'inline' };
8478
dojo.html.displayMap = { tr: '', td: '', th: '', img: 'inline', span: 'inline', input: 'inline', button: 'inline' };
8442
 
8479
 
8443
dojo.html.suggestDisplayByTagName = function(/* HTMLElement */node){
8480
dojo.html.suggestDisplayByTagName = function(/* HTMLElement */node){
8444
	//	summary
8481
	//	summary
8445
	// Suggest a value for the display property that will show 'node' based on it's tag
8482
	// Suggest a value for the display property that will show 'node' based on it's tag
8446
	node = dojo.byId(node);
8483
	node = dojo.byId(node);
8447
	if(node && node.tagName){
8484
	if(node && node.tagName){
8448
		var tag = node.tagName.toLowerCase();
8485
		var tag = node.tagName.toLowerCase();
8449
		return (tag in dojo.html.displayMap ? dojo.html.displayMap[tag] : 'block');	//	string
8486
		return (tag in dojo.html.displayMap ? dojo.html.displayMap[tag] : 'block');	//	string
8450
	}
8487
	}
8451
}
8488
}
8452
 
8489
 
8453
dojo.html.setDisplay = function(/* HTMLElement */node, /* string */display){
8490
dojo.html.setDisplay = function(/* HTMLElement */node, /* string */display){
8454
	//	summary
8491
	//	summary
8455
	// 	Sets the value of style.display to value of 'display' parameter if it is a string.
8492
	// 	Sets the value of style.display to value of 'display' parameter if it is a string.
8456
	// 	Otherwise, if 'display' is false, set style.display to 'none'.
8493
	// 	Otherwise, if 'display' is false, set style.display to 'none'.
8457
	// 	Finally, set 'display' to a suggested display value based on the node's tag
8494
	// 	Finally, set 'display' to a suggested display value based on the node's tag
8458
	dojo.html.setStyle(node, 'display', ((display instanceof String || typeof display == "string") ? display : (display ? dojo.html.suggestDisplayByTagName(node) : 'none')));
8495
	dojo.html.setStyle(node, 'display', ((display instanceof String || typeof display == "string") ? display : (display ? dojo.html.suggestDisplayByTagName(node) : 'none')));
8459
}
8496
}
8460
 
8497
 
8461
dojo.html.isDisplayed = function(/* HTMLElement */node){
8498
dojo.html.isDisplayed = function(/* HTMLElement */node){
8462
	//	summary
8499
	//	summary
8463
	// 	Is true if the the computed display style for node is not 'none'
8500
	// 	Is true if the the computed display style for node is not 'none'
8464
	// 	FIXME: returns true if node is bad, isNotDisplayed would be easier to make correct
8501
	// 	FIXME: returns true if node is bad, isNotDisplayed would be easier to make correct
8465
	return (dojo.html.getComputedStyle(node, 'display') != 'none');	//	boolean
8502
	return (dojo.html.getComputedStyle(node, 'display') != 'none');	//	boolean
8466
}
8503
}
8467
 
8504
 
8468
dojo.html.toggleDisplay = function(/* HTMLElement */node){
8505
dojo.html.toggleDisplay = function(/* HTMLElement */node){
8469
	//	summary
8506
	//	summary
8470
	// 	Call setDisplay() on node with the complement of isDisplayed(), then
8507
	// 	Call setDisplay() on node with the complement of isDisplayed(), then
8471
	// 	return the new value of isDisplayed()
8508
	// 	return the new value of isDisplayed()
8472
	return dojo.html._toggle(node, dojo.html.isDisplayed, dojo.html.setDisplay);	//	boolean
8509
	return dojo.html._toggle(node, dojo.html.isDisplayed, dojo.html.setDisplay);	//	boolean
8473
}
8510
}
8474
 
8511
 
8475
dojo.html.setVisibility = function(/* HTMLElement */node, /* string */visibility){
8512
dojo.html.setVisibility = function(/* HTMLElement */node, /* string */visibility){
8476
	//	summary
8513
	//	summary
8477
	// 	Sets the value of style.visibility to value of 'visibility' parameter if it is a string.
8514
	// 	Sets the value of style.visibility to value of 'visibility' parameter if it is a string.
8478
	// 	Otherwise, if 'visibility' is false, set style.visibility to 'hidden'. Finally, set style.visibility to 'visible'.
8515
	// 	Otherwise, if 'visibility' is false, set style.visibility to 'hidden'. Finally, set style.visibility to 'visible'.
8479
	dojo.html.setStyle(node, 'visibility', ((visibility instanceof String || typeof visibility == "string") ? visibility : (visibility ? 'visible' : 'hidden')));
8516
	dojo.html.setStyle(node, 'visibility', ((visibility instanceof String || typeof visibility == "string") ? visibility : (visibility ? 'visible' : 'hidden')));
8480
}
8517
}
8481
 
8518
 
8482
dojo.html.isVisible = function(/* HTMLElement */node){
8519
dojo.html.isVisible = function(/* HTMLElement */node){
8483
	//	summary
8520
	//	summary
8484
	// 	Returns true if the the computed visibility style for node is not 'hidden'
8521
	// 	Returns true if the the computed visibility style for node is not 'hidden'
8485
	// 	FIXME: returns true if node is bad, isInvisible would be easier to make correct
8522
	// 	FIXME: returns true if node is bad, isInvisible would be easier to make correct
8486
	return (dojo.html.getComputedStyle(node, 'visibility') != 'hidden');	//	boolean
8523
	return (dojo.html.getComputedStyle(node, 'visibility') != 'hidden');	//	boolean
8487
}
8524
}
8488
 
8525
 
8489
dojo.html.toggleVisibility = function(node){
8526
dojo.html.toggleVisibility = function(node){
8490
	//	summary
8527
	//	summary
8491
	// Call setVisibility() on node with the complement of isVisible(), then return the new value of isVisible()
8528
	// Call setVisibility() on node with the complement of isVisible(), then return the new value of isVisible()
8492
	return dojo.html._toggle(node, dojo.html.isVisible, dojo.html.setVisibility);	//	boolean
8529
	return dojo.html._toggle(node, dojo.html.isVisible, dojo.html.setVisibility);	//	boolean
8493
}
8530
}
8494
 
8531
 
8495
dojo.html.setOpacity = function(/* HTMLElement */node, /* float */opacity, /* boolean? */dontFixOpacity){
8532
dojo.html.setOpacity = function(/* HTMLElement */node, /* float */opacity, /* boolean? */dontFixOpacity){
8496
	//	summary
8533
	//	summary
8497
	//	Sets the opacity of node in a cross-browser way.
8534
	//	Sets the opacity of node in a cross-browser way.
8498
	//	float between 0.0 (transparent) and 1.0 (opaque)
8535
	//	float between 0.0 (transparent) and 1.0 (opaque)
8499
	node = dojo.byId(node);
8536
	node = dojo.byId(node);
8500
	var h = dojo.render.html;
8537
	var h = dojo.render.html;
8501
	if(!dontFixOpacity){
8538
	if(!dontFixOpacity){
8502
		if( opacity >= 1.0){
8539
		if( opacity >= 1.0){
8503
			if(h.ie){
8540
			if(h.ie){
8504
				dojo.html.clearOpacity(node);
8541
				dojo.html.clearOpacity(node);
8505
				return;
8542
				return;
8506
			}else{
8543
			}else{
8507
				opacity = 0.999999;
8544
				opacity = 0.999999;
8508
			}
8545
			}
8509
		}else if( opacity < 0.0){ opacity = 0; }
8546
		}else if( opacity < 0.0){ opacity = 0; }
8510
	}
8547
	}
8511
	if(h.ie){
8548
	if(h.ie){
8512
		if(node.nodeName.toLowerCase() == "tr"){
8549
		if(node.nodeName.toLowerCase() == "tr"){
8513
			// FIXME: is this too naive? will we get more than we want?
8550
			// FIXME: is this too naive? will we get more than we want?
8514
			var tds = node.getElementsByTagName("td");
8551
			var tds = node.getElementsByTagName("td");
8515
			for(var x=0; x<tds.length; x++){
8552
			for(var x=0; x<tds.length; x++){
8516
				tds[x].style.filter = "Alpha(Opacity="+opacity*100+")";
8553
				tds[x].style.filter = "Alpha(Opacity="+opacity*100+")";
8517
			}
8554
			}
8518
		}
8555
		}
8519
		node.style.filter = "Alpha(Opacity="+opacity*100+")";
8556
		node.style.filter = "Alpha(Opacity="+opacity*100+")";
8520
	}else if(h.moz){
8557
	}else if(h.moz){
8521
		node.style.opacity = opacity; // ffox 1.0 directly supports "opacity"
8558
		node.style.opacity = opacity; // ffox 1.0 directly supports "opacity"
8522
		node.style.MozOpacity = opacity;
8559
		node.style.MozOpacity = opacity;
8523
	}else if(h.safari){
8560
	}else if(h.safari){
8524
		node.style.opacity = opacity; // 1.3 directly supports "opacity"
8561
		node.style.opacity = opacity; // 1.3 directly supports "opacity"
8525
		node.style.KhtmlOpacity = opacity;
8562
		node.style.KhtmlOpacity = opacity;
8526
	}else{
8563
	}else{
8527
		node.style.opacity = opacity;
8564
		node.style.opacity = opacity;
8528
	}
8565
	}
8529
}
8566
}
8530
 
8567
 
8531
dojo.html.clearOpacity = function(/* HTMLElement */node){
8568
dojo.html.clearOpacity = function(/* HTMLElement */node){
8532
	//	summary
8569
	//	summary
8533
	//	Clears any opacity setting on the passed element.
8570
	//	Clears any opacity setting on the passed element.
8534
	node = dojo.byId(node);
8571
	node = dojo.byId(node);
8535
	var ns = node.style;
8572
	var ns = node.style;
8536
	var h = dojo.render.html;
8573
	var h = dojo.render.html;
8537
	if(h.ie){
8574
	if(h.ie){
8538
		try {
8575
		try {
8539
			if( node.filters && node.filters.alpha ){
8576
			if( node.filters && node.filters.alpha ){
8540
				ns.filter = ""; // FIXME: may get rid of other filter effects
8577
				ns.filter = ""; // FIXME: may get rid of other filter effects
8541
			}
8578
			}
8542
		} catch(e) {
8579
		} catch(e) {
8543
			/*
8580
			/*
8544
			 * IE7 gives error if node.filters not set;
8581
			 * IE7 gives error if node.filters not set;
8545
			 * don't know why or how to workaround (other than this)
8582
			 * don't know why or how to workaround (other than this)
8546
			 */
8583
			 */
8547
		}
8584
		}
8548
	}else if(h.moz){
8585
	}else if(h.moz){
8549
		ns.opacity = 1;
8586
		ns.opacity = 1;
8550
		ns.MozOpacity = 1;
8587
		ns.MozOpacity = 1;
8551
	}else if(h.safari){
8588
	}else if(h.safari){
8552
		ns.opacity = 1;
8589
		ns.opacity = 1;
8553
		ns.KhtmlOpacity = 1;
8590
		ns.KhtmlOpacity = 1;
8554
	}else{
8591
	}else{
8555
		ns.opacity = 1;
8592
		ns.opacity = 1;
8556
	}
8593
	}
8557
}
8594
}
8558
 
8595
 
8559
dojo.html.getOpacity = function(/* HTMLElement */node){
8596
dojo.html.getOpacity = function(/* HTMLElement */node){
8560
	//	summary
8597
	//	summary
8561
	//	Returns the opacity of the passed element
8598
	//	Returns the opacity of the passed element
8562
	node = dojo.byId(node);
8599
	node = dojo.byId(node);
8563
	var h = dojo.render.html;
8600
	var h = dojo.render.html;
8564
	if(h.ie){
8601
	if(h.ie){
8565
		var opac = (node.filters && node.filters.alpha &&
8602
		var opac = (node.filters && node.filters.alpha &&
8566
			typeof node.filters.alpha.opacity == "number"
8603
			typeof node.filters.alpha.opacity == "number"
8567
			? node.filters.alpha.opacity : 100) / 100;
8604
			? node.filters.alpha.opacity : 100) / 100;
8568
	}else{
8605
	}else{
8569
		var opac = node.style.opacity || node.style.MozOpacity ||
8606
		var opac = node.style.opacity || node.style.MozOpacity ||
8570
			node.style.KhtmlOpacity || 1;
8607
			node.style.KhtmlOpacity || 1;
8571
	}
8608
	}
8572
	return opac >= 0.999999 ? 1.0 : Number(opac);	//	float
8609
	return opac >= 0.999999 ? 1.0 : Number(opac);	//	float
8573
}
8610
}
8574
 
8611
 
8575
 
8612
 
8576
dojo.provide("dojo.html.color");
8613
dojo.provide("dojo.html.color");
8577
 
8614
 
8578
 
8615
 
8579
 
8616
 
8580
 
8617
 
8581
dojo.html.getBackgroundColor = function(/* HTMLElement */node){
8618
dojo.html.getBackgroundColor = function(/* HTMLElement */node){
8582
	//	summary
8619
	//	summary
8583
	//	returns the background color of the passed node as a 32-bit color (RGBA)
8620
	//	returns the background color of the passed node as a 32-bit color (RGBA)
8584
	node = dojo.byId(node);
8621
	node = dojo.byId(node);
8585
	var color;
8622
	var color;
8586
	do{
8623
	do{
8587
		color = dojo.html.getStyle(node, "background-color");
8624
		color = dojo.html.getStyle(node, "background-color");
8588
		// Safari doesn't say "transparent"
8625
		// Safari doesn't say "transparent"
8589
		if(color.toLowerCase() == "rgba(0, 0, 0, 0)") { color = "transparent"; }
8626
		if(color.toLowerCase() == "rgba(0, 0, 0, 0)") { color = "transparent"; }
8590
		if(node == document.getElementsByTagName("body")[0]) { node = null; break; }
8627
		if(node == document.getElementsByTagName("body")[0]) { node = null; break; }
8591
		node = node.parentNode;
8628
		node = node.parentNode;
8592
	}while(node && dojo.lang.inArray(["transparent", ""], color));
8629
	}while(node && dojo.lang.inArray(["transparent", ""], color));
8593
	if(color == "transparent"){
8630
	if(color == "transparent"){
8594
		color = [255, 255, 255, 0];
8631
		color = [255, 255, 255, 0];
8595
	}else{
8632
	}else{
8596
		color = dojo.gfx.color.extractRGB(color);
8633
		color = dojo.gfx.color.extractRGB(color);
8597
	}
8634
	}
8598
	return color;	//	array
8635
	return color;	//	array
8599
}
8636
}
8600
 
8637
 
8601
dojo.provide("dojo.html.layout");
8638
dojo.provide("dojo.html.layout");
8602
 
8639
 
8603
 
8640
 
8604
 
8641
 
8605
 
8642
 
8606
 
8643
 
8607
dojo.html.sumAncestorProperties = function(/* HTMLElement */node, /* string */prop){
8644
dojo.html.sumAncestorProperties = function(/* HTMLElement */node, /* string */prop){
8608
	//	summary
8645
	//	summary
8609
	//	Returns the sum of the passed property on all ancestors of node.
8646
	//	Returns the sum of the passed property on all ancestors of node.
8610
	node = dojo.byId(node);
8647
	node = dojo.byId(node);
8611
	if(!node){ return 0; } // FIXME: throw an error?
8648
	if(!node){ return 0; } // FIXME: throw an error?
8612
	
8649
	
8613
	var retVal = 0;
8650
	var retVal = 0;
8614
	while(node){
8651
	while(node){
8615
		if(dojo.html.getComputedStyle(node, 'position') == 'fixed'){
8652
		if(dojo.html.getComputedStyle(node, 'position') == 'fixed'){
8616
			return 0;
8653
			return 0;
8617
		}
8654
		}
8618
		var val = node[prop];
8655
		var val = node[prop];
8619
		if(val){
8656
		if(val){
8620
			retVal += val - 0;
8657
			retVal += val - 0;
8621
			if(node==dojo.body()){ break; }// opera and khtml #body & #html has the same values, we only need one value
8658
			if(node==dojo.body()){ break; }// opera and khtml #body & #html has the same values, we only need one value
8622
		}
8659
		}
8623
		node = node.parentNode;
8660
		node = node.parentNode;
8624
	}
8661
	}
8625
	return retVal;	//	integer
8662
	return retVal;	//	integer
8626
}
8663
}
8627
 
8664
 
8628
dojo.html.setStyleAttributes = function(/* HTMLElement */node, /* string */attributes) { 
8665
dojo.html.setStyleAttributes = function(/* HTMLElement */node, /* string */attributes) { 
8629
	//	summary
8666
	//	summary
8630
	//	allows a dev to pass a string similar to what you'd pass in style="", and apply it to a node.
8667
	//	allows a dev to pass a string similar to what you'd pass in style="", and apply it to a node.
8631
	node = dojo.byId(node);
8668
	node = dojo.byId(node);
8632
	var splittedAttribs=attributes.replace(/(;)?\s*$/, "").split(";"); 
8669
	var splittedAttribs=attributes.replace(/(;)?\s*$/, "").split(";"); 
8633
	for(var i=0; i<splittedAttribs.length; i++){ 
8670
	for(var i=0; i<splittedAttribs.length; i++){ 
8634
		var nameValue=splittedAttribs[i].split(":"); 
8671
		var nameValue=splittedAttribs[i].split(":"); 
8635
		var name=nameValue[0].replace(/\s*$/, "").replace(/^\s*/, "").toLowerCase();
8672
		var name=nameValue[0].replace(/\s*$/, "").replace(/^\s*/, "").toLowerCase();
8636
		var value=nameValue[1].replace(/\s*$/, "").replace(/^\s*/, "");
8673
		var value=nameValue[1].replace(/\s*$/, "").replace(/^\s*/, "");
8637
		switch(name){
8674
		switch(name){
8638
			case "opacity":
8675
			case "opacity":
8639
				dojo.html.setOpacity(node, value); 
8676
				dojo.html.setOpacity(node, value); 
8640
				break; 
8677
				break; 
8641
			case "content-height":
8678
			case "content-height":
8642
				dojo.html.setContentBox(node, {height: value}); 
8679
				dojo.html.setContentBox(node, {height: value}); 
8643
				break; 
8680
				break; 
8644
			case "content-width":
8681
			case "content-width":
8645
				dojo.html.setContentBox(node, {width: value}); 
8682
				dojo.html.setContentBox(node, {width: value}); 
8646
				break; 
8683
				break; 
8647
			case "outer-height":
8684
			case "outer-height":
8648
				dojo.html.setMarginBox(node, {height: value}); 
8685
				dojo.html.setMarginBox(node, {height: value}); 
8649
				break; 
8686
				break; 
8650
			case "outer-width":
8687
			case "outer-width":
8651
				dojo.html.setMarginBox(node, {width: value}); 
8688
				dojo.html.setMarginBox(node, {width: value}); 
8652
				break; 
8689
				break; 
8653
			default:
8690
			default:
8654
				node.style[dojo.html.toCamelCase(name)]=value; 
8691
				node.style[dojo.html.toCamelCase(name)]=value; 
8655
		}
8692
		}
8656
	} 
8693
	} 
8657
}
8694
}
8658
 
8695
 
8659
dojo.html.boxSizing = {
8696
dojo.html.boxSizing = {
8660
	MARGIN_BOX: "margin-box",
8697
	MARGIN_BOX: "margin-box",
8661
	BORDER_BOX: "border-box",
8698
	BORDER_BOX: "border-box",
8662
	PADDING_BOX: "padding-box",
8699
	PADDING_BOX: "padding-box",
8663
	CONTENT_BOX: "content-box"
8700
	CONTENT_BOX: "content-box"
8664
};
8701
};
8665
 
8702
 
8666
dojo.html.getAbsolutePosition = dojo.html.abs = function(/* HTMLElement */node, /* boolean? */includeScroll, /* string? */boxType){
8703
dojo.html.getAbsolutePosition = dojo.html.abs = function(/* HTMLElement */node, /* boolean? */includeScroll, /* string? */boxType){
8667
	//	summary
8704
	//	summary
8668
	//	Gets the absolute position of the passed element based on the document itself.
8705
	//	Gets the absolute position of the passed element based on the document itself.
8669
	node = dojo.byId(node, node.ownerDocument);
8706
	node = dojo.byId(node, node.ownerDocument);
8670
	var ret = {
8707
	var ret = {
8671
		x: 0,
8708
		x: 0,
8672
		y: 0
8709
		y: 0
8673
	};
8710
	};
8674
 
8711
 
8675
	var bs = dojo.html.boxSizing;
8712
	var bs = dojo.html.boxSizing;
8676
	if(!boxType) { boxType = bs.CONTENT_BOX; }
8713
	if(!boxType) { boxType = bs.CONTENT_BOX; }
8677
	var nativeBoxType = 2; //BORDER box
8714
	var nativeBoxType = 2; //BORDER box
8678
	var targetBoxType;
8715
	var targetBoxType;
8679
	switch(boxType){
8716
	switch(boxType){
8680
		case bs.MARGIN_BOX:
8717
		case bs.MARGIN_BOX:
8681
			targetBoxType = 3;
8718
			targetBoxType = 3;
8682
			break;
8719
			break;
8683
		case bs.BORDER_BOX:
8720
		case bs.BORDER_BOX:
8684
			targetBoxType = 2;
8721
			targetBoxType = 2;
8685
			break;
8722
			break;
8686
		case bs.PADDING_BOX:
8723
		case bs.PADDING_BOX:
8687
		default:
8724
		default:
8688
			targetBoxType = 1;
8725
			targetBoxType = 1;
8689
			break;
8726
			break;
8690
		case bs.CONTENT_BOX:
8727
		case bs.CONTENT_BOX:
8691
			targetBoxType = 0;
8728
			targetBoxType = 0;
8692
			break;
8729
			break;
8693
	}
8730
	}
8694
 
8731
 
8695
	var h = dojo.render.html;
8732
	var h = dojo.render.html;
8696
	var db = document["body"]||document["documentElement"];
8733
	var db = document["body"]||document["documentElement"];
8697
 
8734
 
8698
	if(h.ie){
8735
	if(h.ie){
8699
		with(node.getBoundingClientRect()){
8736
		with(node.getBoundingClientRect()){
8700
			ret.x = left-2;
8737
			ret.x = left-2;
8701
			ret.y = top-2;
8738
			ret.y = top-2;
8702
		}
8739
		}
8703
	}else if(document.getBoxObjectFor){
8740
	}else if(document.getBoxObjectFor){
8704
		// mozilla
8741
		// mozilla
8705
		nativeBoxType = 1; //getBoxObjectFor return padding box coordinate
8742
		nativeBoxType = 1; //getBoxObjectFor return padding box coordinate
8706
		try{
8743
		try{
8707
			var bo = document.getBoxObjectFor(node);
8744
			var bo = document.getBoxObjectFor(node);
8708
			ret.x = bo.x - dojo.html.sumAncestorProperties(node, "scrollLeft");
8745
			ret.x = bo.x - dojo.html.sumAncestorProperties(node, "scrollLeft");
8709
			ret.y = bo.y - dojo.html.sumAncestorProperties(node, "scrollTop");
8746
			ret.y = bo.y - dojo.html.sumAncestorProperties(node, "scrollTop");
8710
		}catch(e){
8747
		}catch(e){
8711
			// squelch
8748
			// squelch
8712
		}
8749
		}
8713
	}else{
8750
	}else{
8714
		if(node["offsetParent"]){
8751
		if(node["offsetParent"]){
8715
			var endNode;
8752
			var endNode;
8716
			// in Safari, if the node is an absolutely positioned child of
8753
			// in Safari, if the node is an absolutely positioned child of
8717
			// the body and the body has a margin the offset of the child
8754
			// the body and the body has a margin the offset of the child
8718
			// and the body contain the body's margins, so we need to end
8755
			// and the body contain the body's margins, so we need to end
8719
			// at the body
8756
			// at the body
8720
			if(	(h.safari)&&
8757
			if(	(h.safari)&&
8721
				(node.style.getPropertyValue("position") == "absolute")&&
8758
				(node.style.getPropertyValue("position") == "absolute")&&
8722
				(node.parentNode == db)){
8759
				(node.parentNode == db)){
8723
				endNode = db;
8760
				endNode = db;
8724
			}else{
8761
			}else{
8725
				endNode = db.parentNode;
8762
				endNode = db.parentNode;
8726
			}
8763
			}
8727
 
8764
 
8728
			//TODO: set correct nativeBoxType for safari/konqueror
8765
			//TODO: set correct nativeBoxType for safari/konqueror
8729
 
8766
 
8730
			if(node.parentNode != db){
8767
			if(node.parentNode != db){
8731
				var nd = node;
8768
				var nd = node;
8732
				if(dojo.render.html.opera){ nd = db; }
8769
				if(dojo.render.html.opera){ nd = db; }
8733
				ret.x -= dojo.html.sumAncestorProperties(nd, "scrollLeft");
8770
				ret.x -= dojo.html.sumAncestorProperties(nd, "scrollLeft");
8734
				ret.y -= dojo.html.sumAncestorProperties(nd, "scrollTop");
8771
				ret.y -= dojo.html.sumAncestorProperties(nd, "scrollTop");
8735
			}
8772
			}
8736
			var curnode = node;
8773
			var curnode = node;
8737
			do{
8774
			do{
8738
				var n = curnode["offsetLeft"];
8775
				var n = curnode["offsetLeft"];
8739
				//FIXME: ugly hack to workaround the submenu in 
8776
				//FIXME: ugly hack to workaround the submenu in 
8740
				//popupmenu2 does not shown up correctly in opera. 
8777
				//popupmenu2 does not shown up correctly in opera. 
8741
				//Someone have a better workaround?
8778
				//Someone have a better workaround?
8742
				if(!h.opera || n>0){
8779
				if(!h.opera || n>0){
8743
					ret.x += isNaN(n) ? 0 : n;
8780
					ret.x += isNaN(n) ? 0 : n;
8744
				}
8781
				}
8745
				var m = curnode["offsetTop"];
8782
				var m = curnode["offsetTop"];
8746
				ret.y += isNaN(m) ? 0 : m;
8783
				ret.y += isNaN(m) ? 0 : m;
8747
				curnode = curnode.offsetParent;
8784
				curnode = curnode.offsetParent;
8748
			}while((curnode != endNode)&&(curnode != null));
8785
			}while((curnode != endNode)&&(curnode != null));
8749
		}else if(node["x"]&&node["y"]){
8786
		}else if(node["x"]&&node["y"]){
8750
			ret.x += isNaN(node.x) ? 0 : node.x;
8787
			ret.x += isNaN(node.x) ? 0 : node.x;
8751
			ret.y += isNaN(node.y) ? 0 : node.y;
8788
			ret.y += isNaN(node.y) ? 0 : node.y;
8752
		}
8789
		}
8753
	}
8790
	}
8754
 
8791
 
8755
	// account for document scrolling!
8792
	// account for document scrolling!
8756
	if(includeScroll){
8793
	if(includeScroll){
8757
		var scroll = dojo.html.getScroll();
8794
		var scroll = dojo.html.getScroll();
8758
		ret.y += scroll.top;
8795
		ret.y += scroll.top;
8759
		ret.x += scroll.left;
8796
		ret.x += scroll.left;
8760
	}
8797
	}
8761
 
8798
 
8762
	var extentFuncArray=[dojo.html.getPaddingExtent, dojo.html.getBorderExtent, dojo.html.getMarginExtent];
8799
	var extentFuncArray=[dojo.html.getPaddingExtent, dojo.html.getBorderExtent, dojo.html.getMarginExtent];
8763
	if(nativeBoxType > targetBoxType){
8800
	if(nativeBoxType > targetBoxType){
8764
		for(var i=targetBoxType;i<nativeBoxType;++i){
8801
		for(var i=targetBoxType;i<nativeBoxType;++i){
8765
			ret.y += extentFuncArray[i](node, 'top');
8802
			ret.y += extentFuncArray[i](node, 'top');
8766
			ret.x += extentFuncArray[i](node, 'left');
8803
			ret.x += extentFuncArray[i](node, 'left');
8767
		}
8804
		}
8768
	}else if(nativeBoxType < targetBoxType){
8805
	}else if(nativeBoxType < targetBoxType){
8769
		for(var i=targetBoxType;i>nativeBoxType;--i){
8806
		for(var i=targetBoxType;i>nativeBoxType;--i){
8770
			ret.y -= extentFuncArray[i-1](node, 'top');
8807
			ret.y -= extentFuncArray[i-1](node, 'top');
8771
			ret.x -= extentFuncArray[i-1](node, 'left');
8808
			ret.x -= extentFuncArray[i-1](node, 'left');
8772
		}
8809
		}
8773
	}
8810
	}
8774
	ret.top = ret.y;
8811
	ret.top = ret.y;
8775
	ret.left = ret.x;
8812
	ret.left = ret.x;
8776
	return ret;	//	object
8813
	return ret;	//	object
8777
}
8814
}
8778
 
8815
 
8779
dojo.html.isPositionAbsolute = function(/* HTMLElement */node){
8816
dojo.html.isPositionAbsolute = function(/* HTMLElement */node){
8780
	//	summary
8817
	//	summary
8781
	//	Returns true if the element is absolutely positioned.
8818
	//	Returns true if the element is absolutely positioned.
8782
	return (dojo.html.getComputedStyle(node, 'position') == 'absolute');	//	boolean
8819
	return (dojo.html.getComputedStyle(node, 'position') == 'absolute');	//	boolean
8783
}
8820
}
8784
 
8821
 
8785
dojo.html._sumPixelValues = function(/* HTMLElement */node, selectors, autoIsZero){
8822
dojo.html._sumPixelValues = function(/* HTMLElement */node, selectors, autoIsZero){
8786
	var total = 0;
8823
	var total = 0;
8787
	for(var x=0; x<selectors.length; x++){
8824
	for(var x=0; x<selectors.length; x++){
8788
		total += dojo.html.getPixelValue(node, selectors[x], autoIsZero);
8825
		total += dojo.html.getPixelValue(node, selectors[x], autoIsZero);
8789
	}
8826
	}
8790
	return total;
8827
	return total;
8791
}
8828
}
8792
 
8829
 
8793
dojo.html.getMargin = function(/* HTMLElement */node){
8830
dojo.html.getMargin = function(/* HTMLElement */node){
8794
	//	summary
8831
	//	summary
8795
	//	Returns the width and height of the passed node's margin
8832
	//	Returns the width and height of the passed node's margin
8796
	return {
8833
	return {
8797
		width: dojo.html._sumPixelValues(node, ["margin-left", "margin-right"], (dojo.html.getComputedStyle(node, 'position') == 'absolute')),
8834
		width: dojo.html._sumPixelValues(node, ["margin-left", "margin-right"], (dojo.html.getComputedStyle(node, 'position') == 'absolute')),
8798
		height: dojo.html._sumPixelValues(node, ["margin-top", "margin-bottom"], (dojo.html.getComputedStyle(node, 'position') == 'absolute'))
8835
		height: dojo.html._sumPixelValues(node, ["margin-top", "margin-bottom"], (dojo.html.getComputedStyle(node, 'position') == 'absolute'))
8799
	};	//	object
8836
	};	//	object
8800
}
8837
}
8801
 
8838
 
8802
dojo.html.getBorder = function(/* HTMLElement */node){
8839
dojo.html.getBorder = function(/* HTMLElement */node){
8803
	//	summary
8840
	//	summary
8804
	//	Returns the width and height of the passed node's border
8841
	//	Returns the width and height of the passed node's border
8805
	return {
8842
	return {
8806
		width: dojo.html.getBorderExtent(node, 'left') + dojo.html.getBorderExtent(node, 'right'),
8843
		width: dojo.html.getBorderExtent(node, 'left') + dojo.html.getBorderExtent(node, 'right'),
8807
		height: dojo.html.getBorderExtent(node, 'top') + dojo.html.getBorderExtent(node, 'bottom')
8844
		height: dojo.html.getBorderExtent(node, 'top') + dojo.html.getBorderExtent(node, 'bottom')
8808
	};	//	object
8845
	};	//	object
8809
}
8846
}
8810
 
8847
 
8811
dojo.html.getBorderExtent = function(/* HTMLElement */node, /* string */side){
8848
dojo.html.getBorderExtent = function(/* HTMLElement */node, /* string */side){
8812
	//	summary
8849
	//	summary
8813
	//	returns the width of the requested border
8850
	//	returns the width of the requested border
8814
	return (dojo.html.getStyle(node, 'border-' + side + '-style') == 'none' ? 0 : dojo.html.getPixelValue(node, 'border-' + side + '-width'));	// integer
8851
	return (dojo.html.getStyle(node, 'border-' + side + '-style') == 'none' ? 0 : dojo.html.getPixelValue(node, 'border-' + side + '-width'));	// integer
8815
}
8852
}
8816
 
8853
 
8817
dojo.html.getMarginExtent = function(/* HTMLElement */node, /* string */side){
8854
dojo.html.getMarginExtent = function(/* HTMLElement */node, /* string */side){
8818
	//	summary
8855
	//	summary
8819
	//	returns the width of the requested margin
8856
	//	returns the width of the requested margin
8820
	return dojo.html._sumPixelValues(node, ["margin-" + side], dojo.html.isPositionAbsolute(node));	//	integer
8857
	return dojo.html._sumPixelValues(node, ["margin-" + side], dojo.html.isPositionAbsolute(node));	//	integer
8821
}
8858
}
8822
 
8859
 
8823
dojo.html.getPaddingExtent = function(/* HTMLElement */node, /* string */side){
8860
dojo.html.getPaddingExtent = function(/* HTMLElement */node, /* string */side){
8824
	//	summary
8861
	//	summary
8825
	//	Returns the width of the requested padding 
8862
	//	Returns the width of the requested padding 
8826
	return dojo.html._sumPixelValues(node, ["padding-" + side], true);	//	integer
8863
	return dojo.html._sumPixelValues(node, ["padding-" + side], true);	//	integer
8827
}
8864
}
8828
 
8865
 
8829
dojo.html.getPadding = function(/* HTMLElement */node){
8866
dojo.html.getPadding = function(/* HTMLElement */node){
8830
	//	summary
8867
	//	summary
8831
	//	Returns the width and height of the passed node's padding
8868
	//	Returns the width and height of the passed node's padding
8832
	return {
8869
	return {
8833
		width: dojo.html._sumPixelValues(node, ["padding-left", "padding-right"], true),
8870
		width: dojo.html._sumPixelValues(node, ["padding-left", "padding-right"], true),
8834
		height: dojo.html._sumPixelValues(node, ["padding-top", "padding-bottom"], true)
8871
		height: dojo.html._sumPixelValues(node, ["padding-top", "padding-bottom"], true)
8835
	};	//	object
8872
	};	//	object
8836
}
8873
}
8837
 
8874
 
8838
dojo.html.getPadBorder = function(/* HTMLElement */node){
8875
dojo.html.getPadBorder = function(/* HTMLElement */node){
8839
	//	summary
8876
	//	summary
8840
	//	Returns the width and height of the passed node's padding and border
8877
	//	Returns the width and height of the passed node's padding and border
8841
	var pad = dojo.html.getPadding(node);
8878
	var pad = dojo.html.getPadding(node);
8842
	var border = dojo.html.getBorder(node);
8879
	var border = dojo.html.getBorder(node);
8843
	return { width: pad.width + border.width, height: pad.height + border.height };	//	object
8880
	return { width: pad.width + border.width, height: pad.height + border.height };	//	object
8844
}
8881
}
8845
 
8882
 
8846
dojo.html.getBoxSizing = function(/* HTMLElement */node){
8883
dojo.html.getBoxSizing = function(/* HTMLElement */node){
8847
	//	summary
8884
	//	summary
8848
	//	Returns which box model the passed element is working with
8885
	//	Returns which box model the passed element is working with
8849
	var h = dojo.render.html;
8886
	var h = dojo.render.html;
8850
	var bs = dojo.html.boxSizing;
8887
	var bs = dojo.html.boxSizing;
8851
	if(((h.ie)||(h.opera)) && node.nodeName.toLowerCase() != "img"){ 
8888
	if(((h.ie)||(h.opera)) && node.nodeName.toLowerCase() != "img"){ 
8852
		var cm = document["compatMode"];
8889
		var cm = document["compatMode"];
8853
		if((cm == "BackCompat")||(cm == "QuirksMode")){
8890
		if((cm == "BackCompat")||(cm == "QuirksMode")){
8854
			return bs.BORDER_BOX; 	//	string
8891
			return bs.BORDER_BOX; 	//	string
8855
		}else{
8892
		}else{
8856
			return bs.CONTENT_BOX; 	//	string
8893
			return bs.CONTENT_BOX; 	//	string
8857
		}
8894
		}
8858
	}else{
8895
	}else{
8859
		if(arguments.length == 0){ node = document.documentElement; }
8896
		if(arguments.length == 0){ node = document.documentElement; }
8860
		var sizing;
8897
		var sizing;
8861
		if(!h.ie){
8898
		if(!h.ie){
8862
			sizing = dojo.html.getStyle(node, "-moz-box-sizing");
8899
			sizing = dojo.html.getStyle(node, "-moz-box-sizing");
8863
			if(!sizing){ 
8900
			if(!sizing){ 
8864
				sizing = dojo.html.getStyle(node, "box-sizing");
8901
				sizing = dojo.html.getStyle(node, "box-sizing");
8865
			}
8902
			}
8866
		}
8903
		}
8867
		return (sizing ? sizing : bs.CONTENT_BOX);	//	string
8904
		return (sizing ? sizing : bs.CONTENT_BOX);	//	string
8868
	}
8905
	}
8869
}
8906
}
8870
 
8907
 
8871
dojo.html.isBorderBox = function(/* HTMLElement */node){
8908
dojo.html.isBorderBox = function(/* HTMLElement */node){
8872
	//	summary
8909
	//	summary
8873
	//	returns whether the passed element is using border box sizing or not.
8910
	//	returns whether the passed element is using border box sizing or not.
8874
	return (dojo.html.getBoxSizing(node) == dojo.html.boxSizing.BORDER_BOX);	//	boolean
8911
	return (dojo.html.getBoxSizing(node) == dojo.html.boxSizing.BORDER_BOX);	//	boolean
8875
}
8912
}
8876
 
8913
 
8877
dojo.html.getBorderBox = function(/* HTMLElement */node){
8914
dojo.html.getBorderBox = function(/* HTMLElement */node){
8878
	//	summary
8915
	//	summary
8879
	//	Returns the dimensions of the passed element based on border-box sizing.
8916
	//	Returns the dimensions of the passed element based on border-box sizing.
8880
	node = dojo.byId(node);
8917
	node = dojo.byId(node);
8881
	return { width: node.offsetWidth, height: node.offsetHeight };	//	object
8918
	return { width: node.offsetWidth, height: node.offsetHeight };	//	object
8882
}
8919
}
8883
 
8920
 
8884
dojo.html.getPaddingBox = function(/* HTMLElement */node){
8921
dojo.html.getPaddingBox = function(/* HTMLElement */node){
8885
	//	summary
8922
	//	summary
8886
	//	Returns the dimensions of the padding box (see http://www.w3.org/TR/CSS21/box.html)
8923
	//	Returns the dimensions of the padding box (see http://www.w3.org/TR/CSS21/box.html)
8887
	var box = dojo.html.getBorderBox(node);
8924
	var box = dojo.html.getBorderBox(node);
8888
	var border = dojo.html.getBorder(node);
8925
	var border = dojo.html.getBorder(node);
8889
	return {
8926
	return {
8890
		width: box.width - border.width,
8927
		width: box.width - border.width,
8891
		height:box.height - border.height
8928
		height:box.height - border.height
8892
	};	//	object
8929
	};	//	object
8893
}
8930
}
8894
 
8931
 
8895
dojo.html.getContentBox = function(/* HTMLElement */node){
8932
dojo.html.getContentBox = function(/* HTMLElement */node){
8896
	//	summary
8933
	//	summary
8897
	//	Returns the dimensions of the content box (see http://www.w3.org/TR/CSS21/box.html)
8934
	//	Returns the dimensions of the content box (see http://www.w3.org/TR/CSS21/box.html)
8898
	node = dojo.byId(node);
8935
	node = dojo.byId(node);
8899
	var padborder = dojo.html.getPadBorder(node);
8936
	var padborder = dojo.html.getPadBorder(node);
8900
	return {
8937
	return {
8901
		width: node.offsetWidth - padborder.width,
8938
		width: node.offsetWidth - padborder.width,
8902
		height: node.offsetHeight - padborder.height
8939
		height: node.offsetHeight - padborder.height
8903
	};	//	object
8940
	};	//	object
8904
}
8941
}
8905
 
8942
 
8906
dojo.html.setContentBox = function(/* HTMLElement */node, /* object */args){
8943
dojo.html.setContentBox = function(/* HTMLElement */node, /* object */args){
8907
	//	summary
8944
	//	summary
8908
	//	Sets the dimensions of the passed node according to content sizing.
8945
	//	Sets the dimensions of the passed node according to content sizing.
8909
	node = dojo.byId(node);
8946
	node = dojo.byId(node);
8910
	var width = 0; var height = 0;
8947
	var width = 0; var height = 0;
8911
	var isbb = dojo.html.isBorderBox(node);
8948
	var isbb = dojo.html.isBorderBox(node);
8912
	var padborder = (isbb ? dojo.html.getPadBorder(node) : { width: 0, height: 0});
8949
	var padborder = (isbb ? dojo.html.getPadBorder(node) : { width: 0, height: 0});
8913
	var ret = {};
8950
	var ret = {};
8914
	if(typeof args.width != "undefined"){
8951
	if(typeof args.width != "undefined"){
8915
		width = args.width + padborder.width;
8952
		width = args.width + padborder.width;
8916
		ret.width = dojo.html.setPositivePixelValue(node, "width", width);
8953
		ret.width = dojo.html.setPositivePixelValue(node, "width", width);
8917
	}
8954
	}
8918
	if(typeof args.height != "undefined"){
8955
	if(typeof args.height != "undefined"){
8919
		height = args.height + padborder.height;
8956
		height = args.height + padborder.height;
8920
		ret.height = dojo.html.setPositivePixelValue(node, "height", height);
8957
		ret.height = dojo.html.setPositivePixelValue(node, "height", height);
8921
	}
8958
	}
8922
	return ret;	//	object
8959
	return ret;	//	object
8923
}
8960
}
8924
 
8961
 
8925
dojo.html.getMarginBox = function(/* HTMLElement */node){
8962
dojo.html.getMarginBox = function(/* HTMLElement */node){
8926
	//	summary
8963
	//	summary
8927
	//	returns the dimensions of the passed node including any margins.
8964
	//	returns the dimensions of the passed node including any margins.
8928
	var borderbox = dojo.html.getBorderBox(node);
8965
	var borderbox = dojo.html.getBorderBox(node);
8929
	var margin = dojo.html.getMargin(node);
8966
	var margin = dojo.html.getMargin(node);
8930
	return { width: borderbox.width + margin.width, height: borderbox.height + margin.height };	//	object
8967
	return { width: borderbox.width + margin.width, height: borderbox.height + margin.height };	//	object
8931
}
8968
}
8932
 
8969
 
8933
dojo.html.setMarginBox = function(/* HTMLElement */node, /* object */args){
8970
dojo.html.setMarginBox = function(/* HTMLElement */node, /* object */args){
8934
	//	summary
8971
	//	summary
8935
	//	Sets the dimensions of the passed node using margin box calcs.
8972
	//	Sets the dimensions of the passed node using margin box calcs.
8936
	node = dojo.byId(node);
8973
	node = dojo.byId(node);
8937
	var width = 0; var height = 0;
8974
	var width = 0; var height = 0;
8938
	var isbb = dojo.html.isBorderBox(node);
8975
	var isbb = dojo.html.isBorderBox(node);
8939
	var padborder = (!isbb ? dojo.html.getPadBorder(node) : { width: 0, height: 0 });
8976
	var padborder = (!isbb ? dojo.html.getPadBorder(node) : { width: 0, height: 0 });
8940
	var margin = dojo.html.getMargin(node);
8977
	var margin = dojo.html.getMargin(node);
8941
	var ret = {};
8978
	var ret = {};
8942
	if(typeof args.width != "undefined"){
8979
	if(typeof args.width != "undefined"){
8943
		width = args.width - padborder.width;
8980
		width = args.width - padborder.width;
8944
		width -= margin.width;
8981
		width -= margin.width;
8945
		ret.width = dojo.html.setPositivePixelValue(node, "width", width);
8982
		ret.width = dojo.html.setPositivePixelValue(node, "width", width);
8946
	}
8983
	}
8947
	if(typeof args.height != "undefined"){
8984
	if(typeof args.height != "undefined"){
8948
		height = args.height - padborder.height;
8985
		height = args.height - padborder.height;
8949
		height -= margin.height;
8986
		height -= margin.height;
8950
		ret.height = dojo.html.setPositivePixelValue(node, "height", height);
8987
		ret.height = dojo.html.setPositivePixelValue(node, "height", height);
8951
	}
8988
	}
8952
	return ret;	//	object
8989
	return ret;	//	object
8953
}
8990
}
8954
 
8991
 
8955
dojo.html.getElementBox = function(/* HTMLElement */node, /* string */type){
8992
dojo.html.getElementBox = function(/* HTMLElement */node, /* string */type){
8956
	//	summary
8993
	//	summary
8957
	//	return dimesions of a node based on the passed box model type.
8994
	//	return dimesions of a node based on the passed box model type.
8958
	var bs = dojo.html.boxSizing;
8995
	var bs = dojo.html.boxSizing;
8959
	switch(type){
8996
	switch(type){
8960
		case bs.MARGIN_BOX:
8997
		case bs.MARGIN_BOX:
8961
			return dojo.html.getMarginBox(node);	//	object
8998
			return dojo.html.getMarginBox(node);	//	object
8962
		case bs.BORDER_BOX:
8999
		case bs.BORDER_BOX:
8963
			return dojo.html.getBorderBox(node);	//	object
9000
			return dojo.html.getBorderBox(node);	//	object
8964
		case bs.PADDING_BOX:
9001
		case bs.PADDING_BOX:
8965
			return dojo.html.getPaddingBox(node);	//	object
9002
			return dojo.html.getPaddingBox(node);	//	object
8966
		case bs.CONTENT_BOX:
9003
		case bs.CONTENT_BOX:
8967
		default:
9004
		default:
8968
			return dojo.html.getContentBox(node);	//	object
9005
			return dojo.html.getContentBox(node);	//	object
8969
	}
9006
	}
8970
}
9007
}
8971
// in: coordinate array [x,y,w,h] or dom node
9008
// in: coordinate array [x,y,w,h] or dom node
8972
// return: coordinate object
9009
// return: coordinate object
8973
dojo.html.toCoordinateObject = dojo.html.toCoordinateArray = function(/* array */coords, /* boolean? */includeScroll, /* string? */boxtype) {
9010
dojo.html.toCoordinateObject = dojo.html.toCoordinateArray = function(/* array */coords, /* boolean? */includeScroll, /* string? */boxtype) {
8974
	//	summary
9011
	//	summary
8975
	//	Converts an array of coordinates into an object of named arguments.
9012
	//	Converts an array of coordinates into an object of named arguments.
8976
	if(coords instanceof Array || typeof coords == "array"){
9013
	if(coords instanceof Array || typeof coords == "array"){
8977
		dojo.deprecated("dojo.html.toCoordinateArray", "use dojo.html.toCoordinateObject({left: , top: , width: , height: }) instead", "0.5");
9014
		dojo.deprecated("dojo.html.toCoordinateArray", "use dojo.html.toCoordinateObject({left: , top: , width: , height: }) instead", "0.5");
8978
		// coords is already an array (of format [x,y,w,h]), just return it
9015
		// coords is already an array (of format [x,y,w,h]), just return it
8979
		while ( coords.length < 4 ) { coords.push(0); }
9016
		while ( coords.length < 4 ) { coords.push(0); }
8980
		while ( coords.length > 4 ) { coords.pop(); }
9017
		while ( coords.length > 4 ) { coords.pop(); }
8981
		var ret = {
9018
		var ret = {
8982
			left: coords[0],
9019
			left: coords[0],
8983
			top: coords[1],
9020
			top: coords[1],
8984
			width: coords[2],
9021
			width: coords[2],
8985
			height: coords[3]
9022
			height: coords[3]
8986
		};
9023
		};
8987
	}else if(!coords.nodeType && !(coords instanceof String || typeof coords == "string") &&
9024
	}else if(!coords.nodeType && !(coords instanceof String || typeof coords == "string") &&
8988
			 ('width' in coords || 'height' in coords || 'left' in coords ||
9025
			 ('width' in coords || 'height' in coords || 'left' in coords ||
8989
			  'x' in coords || 'top' in coords || 'y' in coords)){
9026
			  'x' in coords || 'top' in coords || 'y' in coords)){
8990
		// coords is a coordinate object or at least part of one
9027
		// coords is a coordinate object or at least part of one
8991
		var ret = {
9028
		var ret = {
8992
			left: coords.left||coords.x||0,
9029
			left: coords.left||coords.x||0,
8993
			top: coords.top||coords.y||0,
9030
			top: coords.top||coords.y||0,
8994
			width: coords.width||0,
9031
			width: coords.width||0,
8995
			height: coords.height||0
9032
			height: coords.height||0
8996
		};
9033
		};
8997
	}else{
9034
	}else{
8998
		// coords is an dom object (or dom object id); return it's coordinates
9035
		// coords is an dom object (or dom object id); return it's coordinates
8999
		var node = dojo.byId(coords);
9036
		var node = dojo.byId(coords);
9000
		var pos = dojo.html.abs(node, includeScroll, boxtype);
9037
		var pos = dojo.html.abs(node, includeScroll, boxtype);
9001
		var marginbox = dojo.html.getMarginBox(node);
9038
		var marginbox = dojo.html.getMarginBox(node);
9002
		var ret = {
9039
		var ret = {
9003
			left: pos.left,
9040
			left: pos.left,
9004
			top: pos.top,
9041
			top: pos.top,
9005
			width: marginbox.width,
9042
			width: marginbox.width,
9006
			height: marginbox.height
9043
			height: marginbox.height
9007
		};
9044
		};
9008
	}
9045
	}
9009
	ret.x = ret.left;
9046
	ret.x = ret.left;
9010
	ret.y = ret.top;
9047
	ret.y = ret.top;
9011
	return ret;	//	object
9048
	return ret;	//	object
9012
}
9049
}
9013
 
9050
 
9014
dojo.html.setMarginBoxWidth = dojo.html.setOuterWidth = function(node, width){
9051
dojo.html.setMarginBoxWidth = dojo.html.setOuterWidth = function(node, width){
9015
	return dojo.html._callDeprecated("setMarginBoxWidth", "setMarginBox", arguments, "width");
9052
	return dojo.html._callDeprecated("setMarginBoxWidth", "setMarginBox", arguments, "width");
9016
}
9053
}
9017
dojo.html.setMarginBoxHeight = dojo.html.setOuterHeight = function(){
9054
dojo.html.setMarginBoxHeight = dojo.html.setOuterHeight = function(){
9018
	return dojo.html._callDeprecated("setMarginBoxHeight", "setMarginBox", arguments, "height");
9055
	return dojo.html._callDeprecated("setMarginBoxHeight", "setMarginBox", arguments, "height");
9019
}
9056
}
9020
dojo.html.getMarginBoxWidth = dojo.html.getOuterWidth = function(){
9057
dojo.html.getMarginBoxWidth = dojo.html.getOuterWidth = function(){
9021
	return dojo.html._callDeprecated("getMarginBoxWidth", "getMarginBox", arguments, null, "width");
9058
	return dojo.html._callDeprecated("getMarginBoxWidth", "getMarginBox", arguments, null, "width");
9022
}
9059
}
9023
dojo.html.getMarginBoxHeight = dojo.html.getOuterHeight = function(){
9060
dojo.html.getMarginBoxHeight = dojo.html.getOuterHeight = function(){
9024
	return dojo.html._callDeprecated("getMarginBoxHeight", "getMarginBox", arguments, null, "height");
9061
	return dojo.html._callDeprecated("getMarginBoxHeight", "getMarginBox", arguments, null, "height");
9025
}
9062
}
9026
dojo.html.getTotalOffset = function(node, type, includeScroll){
9063
dojo.html.getTotalOffset = function(node, type, includeScroll){
9027
	return dojo.html._callDeprecated("getTotalOffset", "getAbsolutePosition", arguments, null, type);
9064
	return dojo.html._callDeprecated("getTotalOffset", "getAbsolutePosition", arguments, null, type);
9028
}
9065
}
9029
dojo.html.getAbsoluteX = function(node, includeScroll){
9066
dojo.html.getAbsoluteX = function(node, includeScroll){
9030
	return dojo.html._callDeprecated("getAbsoluteX", "getAbsolutePosition", arguments, null, "x");
9067
	return dojo.html._callDeprecated("getAbsoluteX", "getAbsolutePosition", arguments, null, "x");
9031
}
9068
}
9032
dojo.html.getAbsoluteY = function(node, includeScroll){
9069
dojo.html.getAbsoluteY = function(node, includeScroll){
9033
	return dojo.html._callDeprecated("getAbsoluteY", "getAbsolutePosition", arguments, null, "y");
9070
	return dojo.html._callDeprecated("getAbsoluteY", "getAbsolutePosition", arguments, null, "y");
9034
}
9071
}
9035
dojo.html.totalOffsetLeft = function(node, includeScroll){
9072
dojo.html.totalOffsetLeft = function(node, includeScroll){
9036
	return dojo.html._callDeprecated("totalOffsetLeft", "getAbsolutePosition", arguments, null, "left");
9073
	return dojo.html._callDeprecated("totalOffsetLeft", "getAbsolutePosition", arguments, null, "left");
9037
}
9074
}
9038
dojo.html.totalOffsetTop = function(node, includeScroll){
9075
dojo.html.totalOffsetTop = function(node, includeScroll){
9039
	return dojo.html._callDeprecated("totalOffsetTop", "getAbsolutePosition", arguments, null, "top");
9076
	return dojo.html._callDeprecated("totalOffsetTop", "getAbsolutePosition", arguments, null, "top");
9040
}
9077
}
9041
dojo.html.getMarginWidth = function(node){
9078
dojo.html.getMarginWidth = function(node){
9042
	return dojo.html._callDeprecated("getMarginWidth", "getMargin", arguments, null, "width");
9079
	return dojo.html._callDeprecated("getMarginWidth", "getMargin", arguments, null, "width");
9043
}
9080
}
9044
dojo.html.getMarginHeight = function(node){
9081
dojo.html.getMarginHeight = function(node){
9045
	return dojo.html._callDeprecated("getMarginHeight", "getMargin", arguments, null, "height");
9082
	return dojo.html._callDeprecated("getMarginHeight", "getMargin", arguments, null, "height");
9046
}
9083
}
9047
dojo.html.getBorderWidth = function(node){
9084
dojo.html.getBorderWidth = function(node){
9048
	return dojo.html._callDeprecated("getBorderWidth", "getBorder", arguments, null, "width");
9085
	return dojo.html._callDeprecated("getBorderWidth", "getBorder", arguments, null, "width");
9049
}
9086
}
9050
dojo.html.getBorderHeight = function(node){
9087
dojo.html.getBorderHeight = function(node){
9051
	return dojo.html._callDeprecated("getBorderHeight", "getBorder", arguments, null, "height");
9088
	return dojo.html._callDeprecated("getBorderHeight", "getBorder", arguments, null, "height");
9052
}
9089
}
9053
dojo.html.getPaddingWidth = function(node){
9090
dojo.html.getPaddingWidth = function(node){
9054
	return dojo.html._callDeprecated("getPaddingWidth", "getPadding", arguments, null, "width");
9091
	return dojo.html._callDeprecated("getPaddingWidth", "getPadding", arguments, null, "width");
9055
}
9092
}
9056
dojo.html.getPaddingHeight = function(node){
9093
dojo.html.getPaddingHeight = function(node){
9057
	return dojo.html._callDeprecated("getPaddingHeight", "getPadding", arguments, null, "height");
9094
	return dojo.html._callDeprecated("getPaddingHeight", "getPadding", arguments, null, "height");
9058
}
9095
}
9059
dojo.html.getPadBorderWidth = function(node){
9096
dojo.html.getPadBorderWidth = function(node){
9060
	return dojo.html._callDeprecated("getPadBorderWidth", "getPadBorder", arguments, null, "width");
9097
	return dojo.html._callDeprecated("getPadBorderWidth", "getPadBorder", arguments, null, "width");
9061
}
9098
}
9062
dojo.html.getPadBorderHeight = function(node){
9099
dojo.html.getPadBorderHeight = function(node){
9063
	return dojo.html._callDeprecated("getPadBorderHeight", "getPadBorder", arguments, null, "height");
9100
	return dojo.html._callDeprecated("getPadBorderHeight", "getPadBorder", arguments, null, "height");
9064
}
9101
}
9065
dojo.html.getBorderBoxWidth = dojo.html.getInnerWidth = function(){
9102
dojo.html.getBorderBoxWidth = dojo.html.getInnerWidth = function(){
9066
	return dojo.html._callDeprecated("getBorderBoxWidth", "getBorderBox", arguments, null, "width");
9103
	return dojo.html._callDeprecated("getBorderBoxWidth", "getBorderBox", arguments, null, "width");
9067
}
9104
}
9068
dojo.html.getBorderBoxHeight = dojo.html.getInnerHeight = function(){
9105
dojo.html.getBorderBoxHeight = dojo.html.getInnerHeight = function(){
9069
	return dojo.html._callDeprecated("getBorderBoxHeight", "getBorderBox", arguments, null, "height");
9106
	return dojo.html._callDeprecated("getBorderBoxHeight", "getBorderBox", arguments, null, "height");
9070
}
9107
}
9071
dojo.html.getContentBoxWidth = dojo.html.getContentWidth = function(){
9108
dojo.html.getContentBoxWidth = dojo.html.getContentWidth = function(){
9072
	return dojo.html._callDeprecated("getContentBoxWidth", "getContentBox", arguments, null, "width");
9109
	return dojo.html._callDeprecated("getContentBoxWidth", "getContentBox", arguments, null, "width");
9073
}
9110
}
9074
dojo.html.getContentBoxHeight = dojo.html.getContentHeight = function(){
9111
dojo.html.getContentBoxHeight = dojo.html.getContentHeight = function(){
9075
	return dojo.html._callDeprecated("getContentBoxHeight", "getContentBox", arguments, null, "height");
9112
	return dojo.html._callDeprecated("getContentBoxHeight", "getContentBox", arguments, null, "height");
9076
}
9113
}
9077
dojo.html.setContentBoxWidth = dojo.html.setContentWidth = function(node, width){
9114
dojo.html.setContentBoxWidth = dojo.html.setContentWidth = function(node, width){
9078
	return dojo.html._callDeprecated("setContentBoxWidth", "setContentBox", arguments, "width");
9115
	return dojo.html._callDeprecated("setContentBoxWidth", "setContentBox", arguments, "width");
9079
}
9116
}
9080
dojo.html.setContentBoxHeight = dojo.html.setContentHeight = function(node, height){
9117
dojo.html.setContentBoxHeight = dojo.html.setContentHeight = function(node, height){
9081
	return dojo.html._callDeprecated("setContentBoxHeight", "setContentBox", arguments, "height");
9118
	return dojo.html._callDeprecated("setContentBoxHeight", "setContentBox", arguments, "height");
9082
}
9119
}
9083
 
9120
 
9084
dojo.provide("dojo.lfx.html");
9121
dojo.provide("dojo.lfx.html");
9085
 
9122
 
9086
 
9123
 
9087
 
9124
 
9088
 
9125
 
9089
 
9126
 
9090
 
9127
 
9091
 
9128
 
9092
 
9129
 
9093
dojo.lfx.html._byId = function(nodes){
9130
dojo.lfx.html._byId = function(nodes){
9094
	if(!nodes){ return []; }
9131
	if(!nodes){ return []; }
9095
	if(dojo.lang.isArrayLike(nodes)){
9132
	if(dojo.lang.isArrayLike(nodes)){
9096
		if(!nodes.alreadyChecked){
9133
		if(!nodes.alreadyChecked){
9097
			var n = [];
9134
			var n = [];
9098
			dojo.lang.forEach(nodes, function(node){
9135
			dojo.lang.forEach(nodes, function(node){
9099
				n.push(dojo.byId(node));
9136
				n.push(dojo.byId(node));
9100
			});
9137
			});
9101
			n.alreadyChecked = true;
9138
			n.alreadyChecked = true;
9102
			return n;
9139
			return n;
9103
		}else{
9140
		}else{
9104
			return nodes;
9141
			return nodes;
9105
		}
9142
		}
9106
	}else{
9143
	}else{
9107
		var n = [];
9144
		var n = [];
9108
		n.push(dojo.byId(nodes));
9145
		n.push(dojo.byId(nodes));
9109
		n.alreadyChecked = true;
9146
		n.alreadyChecked = true;
9110
		return n;
9147
		return n;
9111
	}
9148
	}
9112
}
9149
}
9113
 
9150
 
9114
dojo.lfx.html.propertyAnimation = function(	/*DOMNode[]*/ nodes, 
9151
dojo.lfx.html.propertyAnimation = function(	/*DOMNode[]*/ nodes, 
9115
											/*Object[]*/ propertyMap, 
9152
											/*Object[]*/ propertyMap, 
9116
											/*int*/ duration,
9153
											/*int*/ duration,
9117
											/*function*/ easing,
9154
											/*function*/ easing,
9118
											/*Object*/ handlers){
9155
											/*Object*/ handlers){
9119
	// summary: Returns an animation that will transition the properties of "nodes"
9156
	// summary: Returns an animation that will transition the properties of "nodes"
9120
	//			depending how they are defined in "propertyMap".
9157
	//			depending how they are defined in "propertyMap".
9121
	// nodes: An array of DOMNodes or one DOMNode.
9158
	// nodes: An array of DOMNodes or one DOMNode.
9122
	// propertyMap: { property: String, start: Decimal?, end: Decimal?, units: String? }
9159
	// propertyMap: { property: String, start: Decimal?, end: Decimal?, units: String? }
9123
	//				An array of objects defining properties to change.
9160
	//				An array of objects defining properties to change.
9124
	// duration: Duration of the animation in milliseconds.
9161
	// duration: Duration of the animation in milliseconds.
9125
	// easing: An easing function.
9162
	// easing: An easing function.
9126
	// handlers: { handler: Function?, onstart: Function?, onstop: Function?, onanimate: Function? }
9163
	// handlers: { handler: Function?, onstart: Function?, onstop: Function?, onanimate: Function? }
9127
	nodes = dojo.lfx.html._byId(nodes);
9164
	nodes = dojo.lfx.html._byId(nodes);
9128
 
9165
 
9129
	var targs = {
9166
	var targs = {
9130
		"propertyMap": propertyMap,
9167
		"propertyMap": propertyMap,
9131
		"nodes": nodes,
9168
		"nodes": nodes,
9132
		"duration": duration,
9169
		"duration": duration,
9133
		"easing": easing||dojo.lfx.easeDefault
9170
		"easing": easing||dojo.lfx.easeDefault
9134
	};
9171
	};
9135
	
9172
	
9136
	var setEmUp = function(args){
9173
	var setEmUp = function(args){
9137
		if(args.nodes.length==1){
9174
		if(args.nodes.length==1){
9138
			// FIXME: we're only supporting start-value filling when one node is
9175
			// FIXME: we're only supporting start-value filling when one node is
9139
			// passed
9176
			// passed
9140
			
9177
			
9141
			var pm = args.propertyMap;
9178
			var pm = args.propertyMap;
9142
			if(!dojo.lang.isArray(args.propertyMap)){
9179
			if(!dojo.lang.isArray(args.propertyMap)){
9143
				// it's stupid to have to pack an array with a set of objects
9180
				// it's stupid to have to pack an array with a set of objects
9144
				// when you can just pass in an object list
9181
				// when you can just pass in an object list
9145
				var parr = [];
9182
				var parr = [];
9146
				for(var pname in pm){
9183
				for(var pname in pm){
9147
					pm[pname].property = pname;
9184
					pm[pname].property = pname;
9148
					parr.push(pm[pname]);
9185
					parr.push(pm[pname]);
9149
				}
9186
				}
9150
				pm = args.propertyMap = parr;
9187
				pm = args.propertyMap = parr;
9151
			}
9188
			}
9152
			dojo.lang.forEach(pm, function(prop){
9189
			dojo.lang.forEach(pm, function(prop){
9153
				if(dj_undef("start", prop)){
9190
				if(dj_undef("start", prop)){
9154
					if(prop.property != "opacity"){
9191
					if(prop.property != "opacity"){
9155
						prop.start = parseInt(dojo.html.getComputedStyle(args.nodes[0], prop.property));
9192
						prop.start = parseInt(dojo.html.getComputedStyle(args.nodes[0], prop.property));
9156
					}else{
9193
					}else{
9157
						prop.start = dojo.html.getOpacity(args.nodes[0]);
9194
						prop.start = dojo.html.getOpacity(args.nodes[0]);
9158
					}
9195
					}
9159
				}
9196
				}
9160
			});
9197
			});
9161
		}
9198
		}
9162
	}
9199
	}
9163
 
9200
 
9164
	var coordsAsInts = function(coords){
9201
	var coordsAsInts = function(coords){
9165
		var cints = [];
9202
		var cints = [];
9166
		dojo.lang.forEach(coords, function(c){ 
9203
		dojo.lang.forEach(coords, function(c){ 
9167
			cints.push(Math.round(c));
9204
			cints.push(Math.round(c));
9168
		});
9205
		});
9169
		return cints;
9206
		return cints;
9170
	}
9207
	}
9171
 
9208
 
9172
	var setStyle = function(n, style){
9209
	var setStyle = function(n, style){
9173
		n = dojo.byId(n);
9210
		n = dojo.byId(n);
9174
		if(!n || !n.style){ return; }
9211
		if(!n || !n.style){ return; }
9175
		for(var s in style){
9212
		for(var s in style){
9176
			try{
9213
			try{
9177
				if(s == "opacity"){
9214
				if(s == "opacity"){
9178
					dojo.html.setOpacity(n, style[s]);
9215
					dojo.html.setOpacity(n, style[s]);
9179
				}else{
9216
				}else{
9180
						n.style[s] = style[s];
9217
						n.style[s] = style[s];
9181
				}
9218
				}
9182
			}catch(e){ dojo.debug(e); }
9219
			}catch(e){ dojo.debug(e); }
9183
		}
9220
		}
9184
	}
9221
	}
9185
 
9222
 
9186
	var propLine = function(properties){
9223
	var propLine = function(properties){
9187
		this._properties = properties;
9224
		this._properties = properties;
9188
		this.diffs = new Array(properties.length);
9225
		this.diffs = new Array(properties.length);
9189
		dojo.lang.forEach(properties, function(prop, i){
9226
		dojo.lang.forEach(properties, function(prop, i){
9190
			// calculate the end - start to optimize a bit
9227
			// calculate the end - start to optimize a bit
9191
			if(dojo.lang.isFunction(prop.start)){
9228
			if(dojo.lang.isFunction(prop.start)){
9192
				prop.start = prop.start(prop, i);
9229
				prop.start = prop.start(prop, i);
9193
			}
9230
			}
9194
			if(dojo.lang.isFunction(prop.end)){
9231
			if(dojo.lang.isFunction(prop.end)){
9195
				prop.end = prop.end(prop, i);
9232
				prop.end = prop.end(prop, i);
9196
			}
9233
			}
9197
			if(dojo.lang.isArray(prop.start)){
9234
			if(dojo.lang.isArray(prop.start)){
9198
				// don't loop through the arrays
9235
				// don't loop through the arrays
9199
				this.diffs[i] = null;
9236
				this.diffs[i] = null;
9200
			}else if(prop.start instanceof dojo.gfx.color.Color){
9237
			}else if(prop.start instanceof dojo.gfx.color.Color){
9201
				// save these so we don't have to call toRgb() every getValue() call
9238
				// save these so we don't have to call toRgb() every getValue() call
9202
				prop.startRgb = prop.start.toRgb();
9239
				prop.startRgb = prop.start.toRgb();
9203
				prop.endRgb = prop.end.toRgb();
9240
				prop.endRgb = prop.end.toRgb();
9204
			}else{
9241
			}else{
9205
				this.diffs[i] = prop.end - prop.start;
9242
				this.diffs[i] = prop.end - prop.start;
9206
			}
9243
			}
9207
		}, this);
9244
		}, this);
9208
 
9245
 
9209
		this.getValue = function(n){
9246
		this.getValue = function(n){
9210
			var ret = {};
9247
			var ret = {};
9211
			dojo.lang.forEach(this._properties, function(prop, i){
9248
			dojo.lang.forEach(this._properties, function(prop, i){
9212
				var value = null;
9249
				var value = null;
9213
				if(dojo.lang.isArray(prop.start)){
9250
				if(dojo.lang.isArray(prop.start)){
9214
					// FIXME: what to do here?
9251
					// FIXME: what to do here?
9215
				}else if(prop.start instanceof dojo.gfx.color.Color){
9252
				}else if(prop.start instanceof dojo.gfx.color.Color){
9216
					value = (prop.units||"rgb") + "(";
9253
					value = (prop.units||"rgb") + "(";
9217
					for(var j = 0 ; j < prop.startRgb.length ; j++){
9254
					for(var j = 0 ; j < prop.startRgb.length ; j++){
9218
						value += Math.round(((prop.endRgb[j] - prop.startRgb[j]) * n) + prop.startRgb[j]) + (j < prop.startRgb.length - 1 ? "," : "");
9255
						value += Math.round(((prop.endRgb[j] - prop.startRgb[j]) * n) + prop.startRgb[j]) + (j < prop.startRgb.length - 1 ? "," : "");
9219
					}
9256
					}
9220
					value += ")";
9257
					value += ")";
9221
				}else{
9258
				}else{
9222
					value = ((this.diffs[i]) * n) + prop.start + (prop.property != "opacity" ? prop.units||"px" : "");
9259
					value = ((this.diffs[i]) * n) + prop.start + (prop.property != "opacity" ? prop.units||"px" : "");
9223
				}
9260
				}
9224
				ret[dojo.html.toCamelCase(prop.property)] = value;
9261
				ret[dojo.html.toCamelCase(prop.property)] = value;
9225
			}, this);
9262
			}, this);
9226
			return ret;
9263
			return ret;
9227
		}
9264
		}
9228
	}
9265
	}
9229
	
9266
	
9230
	var anim = new dojo.lfx.Animation({
9267
	var anim = new dojo.lfx.Animation({
9231
			beforeBegin: function(){ 
9268
			beforeBegin: function(){ 
9232
				setEmUp(targs); 
9269
				setEmUp(targs); 
9233
				anim.curve = new propLine(targs.propertyMap);
9270
				anim.curve = new propLine(targs.propertyMap);
9234
			},
9271
			},
9235
			onAnimate: function(propValues){
9272
			onAnimate: function(propValues){
9236
				dojo.lang.forEach(targs.nodes, function(node){
9273
				dojo.lang.forEach(targs.nodes, function(node){
9237
					setStyle(node, propValues);
9274
					setStyle(node, propValues);
9238
				});
9275
				});
9239
			}
9276
			}
9240
		},
9277
		},
9241
		targs.duration, 
9278
		targs.duration, 
9242
		null,
9279
		null,
9243
		targs.easing
9280
		targs.easing
9244
	);
9281
	);
9245
	if(handlers){
9282
	if(handlers){
9246
		for(var x in handlers){
9283
		for(var x in handlers){
9247
			if(dojo.lang.isFunction(handlers[x])){
9284
			if(dojo.lang.isFunction(handlers[x])){
9248
				anim.connect(x, anim, handlers[x]);
9285
				anim.connect(x, anim, handlers[x]);
9249
			}
9286
			}
9250
		}
9287
		}
9251
	}
9288
	}
9252
	
9289
	
9253
	return anim; // dojo.lfx.Animation
9290
	return anim; // dojo.lfx.Animation
9254
}
9291
}
9255
 
9292
 
9256
dojo.lfx.html._makeFadeable = function(nodes){
9293
dojo.lfx.html._makeFadeable = function(nodes){
9257
	var makeFade = function(node){
9294
	var makeFade = function(node){
9258
		if(dojo.render.html.ie){
9295
		if(dojo.render.html.ie){
9259
			// only set the zoom if the "tickle" value would be the same as the
9296
			// only set the zoom if the "tickle" value would be the same as the
9260
			// default
9297
			// default
9261
			if( (node.style.zoom.length == 0) &&
9298
			if( (node.style.zoom.length == 0) &&
9262
				(dojo.html.getStyle(node, "zoom") == "normal") ){
9299
				(dojo.html.getStyle(node, "zoom") == "normal") ){
9263
				// make sure the node "hasLayout"
9300
				// make sure the node "hasLayout"
9264
				// NOTE: this has been tested with larger and smaller user-set text
9301
				// NOTE: this has been tested with larger and smaller user-set text
9265
				// sizes and works fine
9302
				// sizes and works fine
9266
				node.style.zoom = "1";
9303
				node.style.zoom = "1";
9267
				// node.style.zoom = "normal";
9304
				// node.style.zoom = "normal";
9268
			}
9305
			}
9269
			// don't set the width to auto if it didn't already cascade that way.
9306
			// don't set the width to auto if it didn't already cascade that way.
9270
			// We don't want to f anyones designs
9307
			// We don't want to f anyones designs
9271
			if(	(node.style.width.length == 0) &&
9308
			if(	(node.style.width.length == 0) &&
9272
				(dojo.html.getStyle(node, "width") == "auto") ){
9309
				(dojo.html.getStyle(node, "width") == "auto") ){
9273
				node.style.width = "auto";
9310
				node.style.width = "auto";
9274
			}
9311
			}
9275
		}
9312
		}
9276
	}
9313
	}
9277
	if(dojo.lang.isArrayLike(nodes)){
9314
	if(dojo.lang.isArrayLike(nodes)){
9278
		dojo.lang.forEach(nodes, makeFade);
9315
		dojo.lang.forEach(nodes, makeFade);
9279
	}else{
9316
	}else{
9280
		makeFade(nodes);
9317
		makeFade(nodes);
9281
	}
9318
	}
9282
}
9319
}
9283
 
9320
 
9284
dojo.lfx.html.fade = function(/*DOMNode[]*/ nodes,
9321
dojo.lfx.html.fade = function(/*DOMNode[]*/ nodes,
9285
							  /*Object*/values,
9322
							  /*Object*/values,
9286
							  /*int?*/ duration,
9323
							  /*int?*/ duration,
9287
							  /*Function?*/ easing,
9324
							  /*Function?*/ easing,
9288
							  /*Function?*/ callback){
9325
							  /*Function?*/ callback){
9289
	// summary:Returns an animation that will fade the "nodes" from the start to end values passed.
9326
	// summary:Returns an animation that will fade the "nodes" from the start to end values passed.
9290
	// nodes: An array of DOMNodes or one DOMNode.
9327
	// nodes: An array of DOMNodes or one DOMNode.
9291
	// values: { start: Decimal?, end: Decimal? }
9328
	// values: { start: Decimal?, end: Decimal? }
9292
	// duration: Duration of the animation in milliseconds.
9329
	// duration: Duration of the animation in milliseconds.
9293
	// easing: An easing function.
9330
	// easing: An easing function.
9294
	// callback: Function to run at the end of the animation.
9331
	// callback: Function to run at the end of the animation.
9295
	nodes = dojo.lfx.html._byId(nodes);
9332
	nodes = dojo.lfx.html._byId(nodes);
9296
	var props = { property: "opacity" };
9333
	var props = { property: "opacity" };
9297
	if(!dj_undef("start", values)){
9334
	if(!dj_undef("start", values)){
9298
		props.start = values.start;
9335
		props.start = values.start;
9299
	}else{
9336
	}else{
9300
		props.start = function(){ return dojo.html.getOpacity(nodes[0]); };
9337
		props.start = function(){ return dojo.html.getOpacity(nodes[0]); };
9301
	}
9338
	}
9302
 
9339
 
9303
	if(!dj_undef("end", values)){
9340
	if(!dj_undef("end", values)){
9304
		props.end = values.end;
9341
		props.end = values.end;
9305
	}else{
9342
	}else{
9306
		dojo.raise("dojo.lfx.html.fade needs an end value");
9343
		dojo.raise("dojo.lfx.html.fade needs an end value");
9307
	}
9344
	}
9308
 
9345
 
9309
	var anim = dojo.lfx.propertyAnimation(nodes, [ props ], duration, easing);
9346
	var anim = dojo.lfx.propertyAnimation(nodes, [ props ], duration, easing);
9310
	anim.connect("beforeBegin", function(){
9347
	anim.connect("beforeBegin", function(){
9311
		dojo.lfx.html._makeFadeable(nodes);
9348
		dojo.lfx.html._makeFadeable(nodes);
9312
	});
9349
	});
9313
	if(callback){
9350
	if(callback){
9314
		anim.connect("onEnd", function(){ callback(nodes, anim); });
9351
		anim.connect("onEnd", function(){ callback(nodes, anim); });
9315
	}
9352
	}
9316
 
9353
 
9317
	return anim; // dojo.lfx.Animation
9354
	return anim; // dojo.lfx.Animation
9318
}
9355
}
9319
 
9356
 
9320
dojo.lfx.html.fadeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9357
dojo.lfx.html.fadeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9321
	// summary: Returns an animation that will fade "nodes" from its current opacity to fully opaque.
9358
	// summary: Returns an animation that will fade "nodes" from its current opacity to fully opaque.
9322
	// nodes: An array of DOMNodes or one DOMNode.
9359
	// nodes: An array of DOMNodes or one DOMNode.
9323
	// duration: Duration of the animation in milliseconds.
9360
	// duration: Duration of the animation in milliseconds.
9324
	// easing: An easing function.
9361
	// easing: An easing function.
9325
	// callback: Function to run at the end of the animation.
9362
	// callback: Function to run at the end of the animation.
9326
	return dojo.lfx.html.fade(nodes, { end: 1 }, duration, easing, callback); // dojo.lfx.Animation
9363
	return dojo.lfx.html.fade(nodes, { end: 1 }, duration, easing, callback); // dojo.lfx.Animation
9327
}
9364
}
9328
 
9365
 
9329
dojo.lfx.html.fadeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9366
dojo.lfx.html.fadeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9330
	// summary: Returns an animation that will fade "nodes" from its current opacity to fully transparent.
9367
	// summary: Returns an animation that will fade "nodes" from its current opacity to fully transparent.
9331
	// nodes: An array of DOMNodes or one DOMNode.
9368
	// nodes: An array of DOMNodes or one DOMNode.
9332
	// duration: Duration of the animation in milliseconds.
9369
	// duration: Duration of the animation in milliseconds.
9333
	// easing: An easing function.
9370
	// easing: An easing function.
9334
	// callback: Function to run at the end of the animation.	
9371
	// callback: Function to run at the end of the animation.	
9335
	return dojo.lfx.html.fade(nodes, { end: 0 }, duration, easing, callback); // dojo.lfx.Animation
9372
	return dojo.lfx.html.fade(nodes, { end: 0 }, duration, easing, callback); // dojo.lfx.Animation
9336
}
9373
}
9337
 
9374
 
9338
dojo.lfx.html.fadeShow = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9375
dojo.lfx.html.fadeShow = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9339
	// summary: Returns an animation that will fade "nodes" from transparent to opaque and shows
9376
	// summary: Returns an animation that will fade "nodes" from transparent to opaque and shows
9340
	//			"nodes" at the end if it is hidden.
9377
	//			"nodes" at the end if it is hidden.
9341
	// nodes: An array of DOMNodes or one DOMNode.
9378
	// nodes: An array of DOMNodes or one DOMNode.
9342
	// duration: Duration of the animation in milliseconds.
9379
	// duration: Duration of the animation in milliseconds.
9343
	// easing: An easing function.
9380
	// easing: An easing function.
9344
	// callback: Function to run at the end of the animation.	
9381
	// callback: Function to run at the end of the animation.	
9345
	nodes=dojo.lfx.html._byId(nodes);
9382
	nodes=dojo.lfx.html._byId(nodes);
9346
	dojo.lang.forEach(nodes, function(node){
9383
	dojo.lang.forEach(nodes, function(node){
9347
		dojo.html.setOpacity(node, 0.0);
9384
		dojo.html.setOpacity(node, 0.0);
9348
	});
9385
	});
9349
 
9386
 
9350
	var anim = dojo.lfx.html.fadeIn(nodes, duration, easing, callback);
9387
	var anim = dojo.lfx.html.fadeIn(nodes, duration, easing, callback);
9351
	anim.connect("beforeBegin", function(){ 
9388
	anim.connect("beforeBegin", function(){ 
9352
		if(dojo.lang.isArrayLike(nodes)){
9389
		if(dojo.lang.isArrayLike(nodes)){
9353
			dojo.lang.forEach(nodes, dojo.html.show);
9390
			dojo.lang.forEach(nodes, dojo.html.show);
9354
		}else{
9391
		}else{
9355
			dojo.html.show(nodes);
9392
			dojo.html.show(nodes);
9356
		}
9393
		}
9357
	});
9394
	});
9358
 
9395
 
9359
	return anim; // dojo.lfx.Animation
9396
	return anim; // dojo.lfx.Animation
9360
}
9397
}
9361
 
9398
 
9362
dojo.lfx.html.fadeHide = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9399
dojo.lfx.html.fadeHide = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9363
	// summary: Returns an animation that will fade "nodes" from its current opacity to opaque and hides
9400
	// summary: Returns an animation that will fade "nodes" from its current opacity to opaque and hides
9364
	//			"nodes" at the end.
9401
	//			"nodes" at the end.
9365
	// nodes: An array of DOMNodes or one DOMNode.
9402
	// nodes: An array of DOMNodes or one DOMNode.
9366
	// duration: Duration of the animation in milliseconds.
9403
	// duration: Duration of the animation in milliseconds.
9367
	// easing: An easing function.
9404
	// easing: An easing function.
9368
	// callback: Function to run at the end of the animation.
9405
	// callback: Function to run at the end of the animation.
9369
	var anim = dojo.lfx.html.fadeOut(nodes, duration, easing, function(){
9406
	var anim = dojo.lfx.html.fadeOut(nodes, duration, easing, function(){
9370
		if(dojo.lang.isArrayLike(nodes)){
9407
		if(dojo.lang.isArrayLike(nodes)){
9371
			dojo.lang.forEach(nodes, dojo.html.hide);
9408
			dojo.lang.forEach(nodes, dojo.html.hide);
9372
		}else{
9409
		}else{
9373
			dojo.html.hide(nodes);
9410
			dojo.html.hide(nodes);
9374
		}
9411
		}
9375
		if(callback){ callback(nodes, anim); }
9412
		if(callback){ callback(nodes, anim); }
9376
	});
9413
	});
9377
	
9414
	
9378
	return anim; // dojo.lfx.Animation
9415
	return anim; // dojo.lfx.Animation
9379
}
9416
}
9380
 
9417
 
9381
dojo.lfx.html.wipeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9418
dojo.lfx.html.wipeIn = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9382
	// summary: Returns an animation that will show and wipe in "nodes".
9419
	// summary: Returns an animation that will show and wipe in "nodes".
9383
	// nodes: An array of DOMNodes or one DOMNode.
9420
	// nodes: An array of DOMNodes or one DOMNode.
9384
	// duration: Duration of the animation in milliseconds.
9421
	// duration: Duration of the animation in milliseconds.
9385
	// easing: An easing function.
9422
	// easing: An easing function.
9386
	// callback: Function to run at the end of the animation.
9423
	// callback: Function to run at the end of the animation.
9387
	nodes = dojo.lfx.html._byId(nodes);
9424
	nodes = dojo.lfx.html._byId(nodes);
9388
	var anims = [];
9425
	var anims = [];
9389
 
9426
 
9390
	dojo.lang.forEach(nodes, function(node){
9427
	dojo.lang.forEach(nodes, function(node){
9391
		var oprop = {  };	// old properties of node (before we mucked w/them)
9428
		var oprop = {  };	// old properties of node (before we mucked w/them)
9392
		
9429
		
9393
		// get node height, either it's natural height or it's height specified via style or class attributes
9430
		// get node height, either it's natural height or it's height specified via style or class attributes
9394
		// (for FF, the node has to be (temporarily) rendered to measure height)
9431
		// (for FF, the node has to be (temporarily) rendered to measure height)
9395
		// TODO: should this offscreen code be part of dojo.html, so that getBorderBox() works on hidden nodes?
9432
		// TODO: should this offscreen code be part of dojo.html, so that getBorderBox() works on hidden nodes?
9396
		var origTop, origLeft, origPosition;
9433
		var origTop, origLeft, origPosition;
9397
		with(node.style){
9434
		with(node.style){
9398
			origTop=top; origLeft=left; origPosition=position;
9435
			origTop=top; origLeft=left; origPosition=position;
9399
			top="-9999px"; left="-9999px"; position="absolute";
9436
			top="-9999px"; left="-9999px"; position="absolute";
9400
			display="";
9437
			display="";
9401
		}
9438
		}
9402
		var nodeHeight = dojo.html.getBorderBox(node).height;
9439
		var nodeHeight = dojo.html.getBorderBox(node).height;
9403
		with(node.style){
9440
		with(node.style){
9404
			top=origTop; left=origLeft; position=origPosition;
9441
			top=origTop; left=origLeft; position=origPosition;
9405
			display="none";
9442
			display="none";
9406
		}
9443
		}
9407
 
9444
 
9408
		var anim = dojo.lfx.propertyAnimation(node,
9445
		var anim = dojo.lfx.propertyAnimation(node,
9409
			{	"height": {
9446
			{	"height": {
9410
					start: 1, // 0 causes IE to display the whole panel
9447
					start: 1, // 0 causes IE to display the whole panel
9411
					end: function(){ return nodeHeight; } 
9448
					end: function(){ return nodeHeight; } 
9412
				}
9449
				}
9413
			}, 
9450
			}, 
9414
			duration, 
9451
			duration, 
9415
			easing);
9452
			easing);
9416
	
9453
	
9417
		anim.connect("beforeBegin", function(){
9454
		anim.connect("beforeBegin", function(){
9418
			oprop.overflow = node.style.overflow;
9455
			oprop.overflow = node.style.overflow;
9419
			oprop.height = node.style.height;
9456
			oprop.height = node.style.height;
9420
			with(node.style){
9457
			with(node.style){
9421
				overflow = "hidden";
9458
				overflow = "hidden";
9422
				height = "1px"; // 0 causes IE to display the whole panel
9459
				height = "1px"; // 0 causes IE to display the whole panel
9423
			}
9460
			}
9424
			dojo.html.show(node);
9461
			dojo.html.show(node);
9425
		});
9462
		});
9426
		
9463
		
9427
		anim.connect("onEnd", function(){ 
9464
		anim.connect("onEnd", function(){ 
9428
			with(node.style){
9465
			with(node.style){
9429
				overflow = oprop.overflow;
9466
				overflow = oprop.overflow;
9430
				height = oprop.height;
9467
				height = oprop.height;
9431
			}
9468
			}
9432
			if(callback){ callback(node, anim); }
9469
			if(callback){ callback(node, anim); }
9433
		});
9470
		});
9434
		anims.push(anim);
9471
		anims.push(anim);
9435
	});
9472
	});
9436
	
9473
	
9437
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9474
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9438
}
9475
}
9439
 
9476
 
9440
dojo.lfx.html.wipeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9477
dojo.lfx.html.wipeOut = function(/*DOMNode[]*/ nodes, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9441
	// summary: Returns an animation that will wipe out and hide "nodes".
9478
	// summary: Returns an animation that will wipe out and hide "nodes".
9442
	// nodes: An array of DOMNodes or one DOMNode.
9479
	// nodes: An array of DOMNodes or one DOMNode.
9443
	// duration: Duration of the animation in milliseconds.
9480
	// duration: Duration of the animation in milliseconds.
9444
	// easing: An easing function.
9481
	// easing: An easing function.
9445
	// callback: Function to run at the end of the animation.
9482
	// callback: Function to run at the end of the animation.
9446
	nodes = dojo.lfx.html._byId(nodes);
9483
	nodes = dojo.lfx.html._byId(nodes);
9447
	var anims = [];
9484
	var anims = [];
9448
	
9485
	
9449
	dojo.lang.forEach(nodes, function(node){
9486
	dojo.lang.forEach(nodes, function(node){
9450
		var oprop = {  };	// old properties of node (before we mucked w/them)
9487
		var oprop = {  };	// old properties of node (before we mucked w/them)
9451
		var anim = dojo.lfx.propertyAnimation(node,
9488
		var anim = dojo.lfx.propertyAnimation(node,
9452
			{	"height": {
9489
			{	"height": {
9453
					start: function(){ return dojo.html.getContentBox(node).height; },
9490
					start: function(){ return dojo.html.getContentBox(node).height; },
9454
					end: 1 // 0 causes IE to display the whole panel
9491
					end: 1 // 0 causes IE to display the whole panel
9455
				} 
9492
				} 
9456
			},
9493
			},
9457
			duration,
9494
			duration,
9458
			easing,
9495
			easing,
9459
			{
9496
			{
9460
				"beforeBegin": function(){
9497
				"beforeBegin": function(){
9461
					oprop.overflow = node.style.overflow;
9498
					oprop.overflow = node.style.overflow;
9462
					oprop.height = node.style.height;
9499
					oprop.height = node.style.height;
9463
					with(node.style){
9500
					with(node.style){
9464
						overflow = "hidden";
9501
						overflow = "hidden";
9465
					}
9502
					}
9466
					dojo.html.show(node);
9503
					dojo.html.show(node);
9467
				},
9504
				},
9468
				
9505
				
9469
				"onEnd": function(){ 
9506
				"onEnd": function(){ 
9470
					dojo.html.hide(node);
9507
					dojo.html.hide(node);
9471
					with(node.style){
9508
					with(node.style){
9472
						overflow = oprop.overflow;
9509
						overflow = oprop.overflow;
9473
						height = oprop.height;
9510
						height = oprop.height;
9474
					}
9511
					}
9475
					if(callback){ callback(node, anim); }
9512
					if(callback){ callback(node, anim); }
9476
				}
9513
				}
9477
			}
9514
			}
9478
		);
9515
		);
9479
		anims.push(anim);
9516
		anims.push(anim);
9480
	});
9517
	});
9481
 
9518
 
9482
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9519
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9483
}
9520
}
9484
 
9521
 
9485
dojo.lfx.html.slideTo = function(/*DOMNode*/ nodes,
9522
dojo.lfx.html.slideTo = function(/*DOMNode*/ nodes,
9486
								 /*Object*/ coords,
9523
								 /*Object*/ coords,
9487
								 /*int?*/ duration,
9524
								 /*int?*/ duration,
9488
								 /*Function?*/ easing,
9525
								 /*Function?*/ easing,
9489
								 /*Function?*/ callback){
9526
								 /*Function?*/ callback){
9490
	// summary: Returns an animation that will slide "nodes" from its current position to
9527
	// summary: Returns an animation that will slide "nodes" from its current position to
9491
	//			the position defined in "coords".
9528
	//			the position defined in "coords".
9492
	// nodes: An array of DOMNodes or one DOMNode.
9529
	// nodes: An array of DOMNodes or one DOMNode.
9493
	// coords: { top: Decimal?, left: Decimal? }
9530
	// coords: { top: Decimal?, left: Decimal? }
9494
	// duration: Duration of the animation in milliseconds.
9531
	// duration: Duration of the animation in milliseconds.
9495
	// easing: An easing function.
9532
	// easing: An easing function.
9496
	// callback: Function to run at the end of the animation.
9533
	// callback: Function to run at the end of the animation.
9497
	nodes = dojo.lfx.html._byId(nodes);
9534
	nodes = dojo.lfx.html._byId(nodes);
9498
	var anims = [];
9535
	var anims = [];
9499
	var compute = dojo.html.getComputedStyle;
9536
	var compute = dojo.html.getComputedStyle;
9500
	
9537
	
9501
	if(dojo.lang.isArray(coords)){
9538
	if(dojo.lang.isArray(coords)){
9502
		/* coords: Array
9539
		/* coords: Array
9503
		   pId: a */
9540
		   pId: a */
9504
		dojo.deprecated('dojo.lfx.html.slideTo(node, array)', 'use dojo.lfx.html.slideTo(node, {top: value, left: value});', '0.5');
9541
		dojo.deprecated('dojo.lfx.html.slideTo(node, array)', 'use dojo.lfx.html.slideTo(node, {top: value, left: value});', '0.5');
9505
		coords = { top: coords[0], left: coords[1] };
9542
		coords = { top: coords[0], left: coords[1] };
9506
	}
9543
	}
9507
	dojo.lang.forEach(nodes, function(node){
9544
	dojo.lang.forEach(nodes, function(node){
9508
		var top = null;
9545
		var top = null;
9509
		var left = null;
9546
		var left = null;
9510
		
9547
		
9511
		var init = (function(){
9548
		var init = (function(){
9512
			var innerNode = node;
9549
			var innerNode = node;
9513
			return function(){
9550
			return function(){
9514
				var pos = compute(innerNode, 'position');
9551
				var pos = compute(innerNode, 'position');
9515
				top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0);
9552
				top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0);
9516
				left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0);
9553
				left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0);
9517
 
9554
 
9518
				if (!dojo.lang.inArray(['absolute', 'relative'], pos)) {
9555
				if (!dojo.lang.inArray(['absolute', 'relative'], pos)) {
9519
					var ret = dojo.html.abs(innerNode, true);
9556
					var ret = dojo.html.abs(innerNode, true);
9520
					dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
9557
					dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
9521
					top = ret.y;
9558
					top = ret.y;
9522
					left = ret.x;
9559
					left = ret.x;
9523
				}
9560
				}
9524
			}
9561
			}
9525
		})();
9562
		})();
9526
		init();
9563
		init();
9527
		
9564
		
9528
		var anim = dojo.lfx.propertyAnimation(node,
9565
		var anim = dojo.lfx.propertyAnimation(node,
9529
			{	"top": { start: top, end: (coords.top||0) },
9566
			{	"top": { start: top, end: (coords.top||0) },
9530
				"left": { start: left, end: (coords.left||0)  }
9567
				"left": { start: left, end: (coords.left||0)  }
9531
			},
9568
			},
9532
			duration,
9569
			duration,
9533
			easing,
9570
			easing,
9534
			{ "beforeBegin": init }
9571
			{ "beforeBegin": init }
9535
		);
9572
		);
9536
 
9573
 
9537
		if(callback){
9574
		if(callback){
9538
			anim.connect("onEnd", function(){ callback(nodes, anim); });
9575
			anim.connect("onEnd", function(){ callback(nodes, anim); });
9539
		}
9576
		}
9540
 
9577
 
9541
		anims.push(anim);
9578
		anims.push(anim);
9542
	});
9579
	});
9543
	
9580
	
9544
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9581
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9545
}
9582
}
9546
 
9583
 
9547
dojo.lfx.html.slideBy = function(/*DOMNode*/ nodes, /*Object*/ coords, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9584
dojo.lfx.html.slideBy = function(/*DOMNode*/ nodes, /*Object*/ coords, /*int?*/ duration, /*Function?*/ easing, /*Function?*/ callback){
9548
	// summary: Returns an animation that will slide "nodes" from its current position
9585
	// summary: Returns an animation that will slide "nodes" from its current position
9549
	//			to its current position plus the numbers defined in "coords".
9586
	//			to its current position plus the numbers defined in "coords".
9550
	// nodes: An array of DOMNodes or one DOMNode.
9587
	// nodes: An array of DOMNodes or one DOMNode.
9551
	// coords: { top: Decimal?, left: Decimal? }
9588
	// coords: { top: Decimal?, left: Decimal? }
9552
	// duration: Duration of the animation in milliseconds.
9589
	// duration: Duration of the animation in milliseconds.
9553
	// easing: An easing function.
9590
	// easing: An easing function.
9554
	// callback: Function to run at the end of the animation.
9591
	// callback: Function to run at the end of the animation.
9555
	nodes = dojo.lfx.html._byId(nodes);
9592
	nodes = dojo.lfx.html._byId(nodes);
9556
	var anims = [];
9593
	var anims = [];
9557
	var compute = dojo.html.getComputedStyle;
9594
	var compute = dojo.html.getComputedStyle;
9558
 
9595
 
9559
	if(dojo.lang.isArray(coords)){
9596
	if(dojo.lang.isArray(coords)){
9560
		/* coords: Array
9597
		/* coords: Array
9561
		   pId: a */
9598
		   pId: a */
9562
		dojo.deprecated('dojo.lfx.html.slideBy(node, array)', 'use dojo.lfx.html.slideBy(node, {top: value, left: value});', '0.5');
9599
		dojo.deprecated('dojo.lfx.html.slideBy(node, array)', 'use dojo.lfx.html.slideBy(node, {top: value, left: value});', '0.5');
9563
		coords = { top: coords[0], left: coords[1] };
9600
		coords = { top: coords[0], left: coords[1] };
9564
	}
9601
	}
9565
 
9602
 
9566
	dojo.lang.forEach(nodes, function(node){
9603
	dojo.lang.forEach(nodes, function(node){
9567
		var top = null;
9604
		var top = null;
9568
		var left = null;
9605
		var left = null;
9569
		
9606
		
9570
		var init = (function(){
9607
		var init = (function(){
9571
			var innerNode = node;
9608
			var innerNode = node;
9572
			return function(){
9609
			return function(){
9573
				var pos = compute(innerNode, 'position');
9610
				var pos = compute(innerNode, 'position');
9574
				top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0);
9611
				top = (pos == 'absolute' ? node.offsetTop : parseInt(compute(node, 'top')) || 0);
9575
				left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0);
9612
				left = (pos == 'absolute' ? node.offsetLeft : parseInt(compute(node, 'left')) || 0);
9576
 
9613
 
9577
				if (!dojo.lang.inArray(['absolute', 'relative'], pos)) {
9614
				if (!dojo.lang.inArray(['absolute', 'relative'], pos)) {
9578
					var ret = dojo.html.abs(innerNode, true);
9615
					var ret = dojo.html.abs(innerNode, true);
9579
					dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
9616
					dojo.html.setStyleAttributes(innerNode, "position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
9580
					top = ret.y;
9617
					top = ret.y;
9581
					left = ret.x;
9618
					left = ret.x;
9582
				}
9619
				}
9583
			}
9620
			}
9584
		})();
9621
		})();
9585
		init();
9622
		init();
9586
		
9623
		
9587
		var anim = dojo.lfx.propertyAnimation(node,
9624
		var anim = dojo.lfx.propertyAnimation(node,
9588
			{
9625
			{
9589
				"top": { start: top, end: top+(coords.top||0) },
9626
				"top": { start: top, end: top+(coords.top||0) },
9590
				"left": { start: left, end: left+(coords.left||0) }
9627
				"left": { start: left, end: left+(coords.left||0) }
9591
			},
9628
			},
9592
			duration,
9629
			duration,
9593
			easing).connect("beforeBegin", init);
9630
			easing).connect("beforeBegin", init);
9594
 
9631
 
9595
		if(callback){
9632
		if(callback){
9596
			anim.connect("onEnd", function(){ callback(nodes, anim); });
9633
			anim.connect("onEnd", function(){ callback(nodes, anim); });
9597
		}
9634
		}
9598
 
9635
 
9599
		anims.push(anim);
9636
		anims.push(anim);
9600
	});
9637
	});
9601
 
9638
 
9602
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9639
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9603
}
9640
}
9604
 
9641
 
9605
dojo.lfx.html.explode = function(/*DOMNode*/ start,
9642
dojo.lfx.html.explode = function(/*DOMNode*/ start,
9606
								 /*DOMNode*/ endNode,
9643
								 /*DOMNode*/ endNode,
9607
								 /*int?*/ duration,
9644
								 /*int?*/ duration,
9608
								 /*Function?*/ easing,
9645
								 /*Function?*/ easing,
9609
								 /*Function?*/ callback){
9646
								 /*Function?*/ callback){
9610
	// summary: Returns an animation that will 
9647
	// summary: Returns an animation that will 
9611
	// start:
9648
	// start:
9612
	// endNode:
9649
	// endNode:
9613
	// duration: Duration of the animation in milliseconds.
9650
	// duration: Duration of the animation in milliseconds.
9614
	// easing: An easing function.
9651
	// easing: An easing function.
9615
	// callback: Function to run at the end of the animation.
9652
	// callback: Function to run at the end of the animation.
9616
	var h = dojo.html;
9653
	var h = dojo.html;
9617
	start = dojo.byId(start);
9654
	start = dojo.byId(start);
9618
	endNode = dojo.byId(endNode);
9655
	endNode = dojo.byId(endNode);
9619
	var startCoords = h.toCoordinateObject(start, true);
9656
	var startCoords = h.toCoordinateObject(start, true);
9620
	var outline = document.createElement("div");
9657
	var outline = document.createElement("div");
9621
	h.copyStyle(outline, endNode);
9658
	h.copyStyle(outline, endNode);
9622
	if(endNode.explodeClassName){ outline.className = endNode.explodeClassName; }
9659
	if(endNode.explodeClassName){ outline.className = endNode.explodeClassName; }
9623
	with(outline.style){
9660
	with(outline.style){
9624
		position = "absolute";
9661
		position = "absolute";
9625
		display = "none";
9662
		display = "none";
9626
		// border = "1px solid black";
9663
		// border = "1px solid black";
9627
		var backgroundStyle = h.getStyle(start, "background-color");
9664
		var backgroundStyle = h.getStyle(start, "background-color");
9628
		backgroundColor = backgroundStyle ? backgroundStyle.toLowerCase() : "transparent";
9665
		backgroundColor = backgroundStyle ? backgroundStyle.toLowerCase() : "transparent";
9629
		backgroundColor = (backgroundColor == "transparent") ? "rgb(221, 221, 221)" : backgroundColor;
9666
		backgroundColor = (backgroundColor == "transparent") ? "rgb(221, 221, 221)" : backgroundColor;
9630
	}
9667
	}
9631
	dojo.body().appendChild(outline);
9668
	dojo.body().appendChild(outline);
9632
 
9669
 
9633
	with(endNode.style){
9670
	with(endNode.style){
9634
		visibility = "hidden";
9671
		visibility = "hidden";
9635
		display = "block";
9672
		display = "block";
9636
	}
9673
	}
9637
	var endCoords = h.toCoordinateObject(endNode, true);
9674
	var endCoords = h.toCoordinateObject(endNode, true);
9638
	with(endNode.style){
9675
	with(endNode.style){
9639
		display = "none";
9676
		display = "none";
9640
		visibility = "visible";
9677
		visibility = "visible";
9641
	}
9678
	}
9642
 
9679
 
9643
	var props = { opacity: { start: 0.5, end: 1.0 } };
9680
	var props = { opacity: { start: 0.5, end: 1.0 } };
9644
	dojo.lang.forEach(["height", "width", "top", "left"], function(type){
9681
	dojo.lang.forEach(["height", "width", "top", "left"], function(type){
9645
		props[type] = { start: startCoords[type], end: endCoords[type] }
9682
		props[type] = { start: startCoords[type], end: endCoords[type] }
9646
	});
9683
	});
9647
	
9684
	
9648
	var anim = new dojo.lfx.propertyAnimation(outline, 
9685
	var anim = new dojo.lfx.propertyAnimation(outline, 
9649
		props,
9686
		props,
9650
		duration,
9687
		duration,
9651
		easing,
9688
		easing,
9652
		{
9689
		{
9653
			"beforeBegin": function(){
9690
			"beforeBegin": function(){
9654
				h.setDisplay(outline, "block");
9691
				h.setDisplay(outline, "block");
9655
			},
9692
			},
9656
			"onEnd": function(){
9693
			"onEnd": function(){
9657
				h.setDisplay(endNode, "block");
9694
				h.setDisplay(endNode, "block");
9658
				outline.parentNode.removeChild(outline);
9695
				outline.parentNode.removeChild(outline);
9659
			}
9696
			}
9660
		}
9697
		}
9661
	);
9698
	);
9662
 
9699
 
9663
	if(callback){
9700
	if(callback){
9664
		anim.connect("onEnd", function(){ callback(endNode, anim); });
9701
		anim.connect("onEnd", function(){ callback(endNode, anim); });
9665
	}
9702
	}
9666
	return anim; // dojo.lfx.Animation
9703
	return anim; // dojo.lfx.Animation
9667
}
9704
}
9668
 
9705
 
9669
dojo.lfx.html.implode = function(/*DOMNode*/ startNode,
9706
dojo.lfx.html.implode = function(/*DOMNode*/ startNode,
9670
								 /*DOMNode*/ end,
9707
								 /*DOMNode*/ end,
9671
								 /*int?*/ duration,
9708
								 /*int?*/ duration,
9672
								 /*Function?*/ easing,
9709
								 /*Function?*/ easing,
9673
								 /*Function?*/ callback){
9710
								 /*Function?*/ callback){
9674
	// summary: Returns an animation that will 
9711
	// summary: Returns an animation that will 
9675
	// startNode:
9712
	// startNode:
9676
	// end:
9713
	// end:
9677
	// duration: Duration of the animation in milliseconds.
9714
	// duration: Duration of the animation in milliseconds.
9678
	// easing: An easing function.
9715
	// easing: An easing function.
9679
	// callback: Function to run at the end of the animation.
9716
	// callback: Function to run at the end of the animation.
9680
	var h = dojo.html;
9717
	var h = dojo.html;
9681
	startNode = dojo.byId(startNode);
9718
	startNode = dojo.byId(startNode);
9682
	end = dojo.byId(end);
9719
	end = dojo.byId(end);
9683
	var startCoords = dojo.html.toCoordinateObject(startNode, true);
9720
	var startCoords = dojo.html.toCoordinateObject(startNode, true);
9684
	var endCoords = dojo.html.toCoordinateObject(end, true);
9721
	var endCoords = dojo.html.toCoordinateObject(end, true);
9685
 
9722
 
9686
	var outline = document.createElement("div");
9723
	var outline = document.createElement("div");
9687
	dojo.html.copyStyle(outline, startNode);
9724
	dojo.html.copyStyle(outline, startNode);
9688
	if (startNode.explodeClassName) { outline.className = startNode.explodeClassName; }
9725
	if (startNode.explodeClassName) { outline.className = startNode.explodeClassName; }
9689
	dojo.html.setOpacity(outline, 0.3);
9726
	dojo.html.setOpacity(outline, 0.3);
9690
	with(outline.style){
9727
	with(outline.style){
9691
		position = "absolute";
9728
		position = "absolute";
9692
		display = "none";
9729
		display = "none";
9693
		backgroundColor = h.getStyle(startNode, "background-color").toLowerCase();
9730
		backgroundColor = h.getStyle(startNode, "background-color").toLowerCase();
9694
	}
9731
	}
9695
	dojo.body().appendChild(outline);
9732
	dojo.body().appendChild(outline);
9696
 
9733
 
9697
	var props = { opacity: { start: 1.0, end: 0.5 } };
9734
	var props = { opacity: { start: 1.0, end: 0.5 } };
9698
	dojo.lang.forEach(["height", "width", "top", "left"], function(type){
9735
	dojo.lang.forEach(["height", "width", "top", "left"], function(type){
9699
		props[type] = { start: startCoords[type], end: endCoords[type] }
9736
		props[type] = { start: startCoords[type], end: endCoords[type] }
9700
	});
9737
	});
9701
	
9738
	
9702
	var anim = new dojo.lfx.propertyAnimation(outline,
9739
	var anim = new dojo.lfx.propertyAnimation(outline,
9703
		props,
9740
		props,
9704
		duration,
9741
		duration,
9705
		easing,
9742
		easing,
9706
		{
9743
		{
9707
			"beforeBegin": function(){
9744
			"beforeBegin": function(){
9708
				dojo.html.hide(startNode);
9745
				dojo.html.hide(startNode);
9709
				dojo.html.show(outline);
9746
				dojo.html.show(outline);
9710
			},
9747
			},
9711
			"onEnd": function(){
9748
			"onEnd": function(){
9712
				outline.parentNode.removeChild(outline);
9749
				outline.parentNode.removeChild(outline);
9713
			}
9750
			}
9714
		}
9751
		}
9715
	);
9752
	);
9716
 
9753
 
9717
	if(callback){
9754
	if(callback){
9718
		anim.connect("onEnd", function(){ callback(startNode, anim); });
9755
		anim.connect("onEnd", function(){ callback(startNode, anim); });
9719
	}
9756
	}
9720
	return anim; // dojo.lfx.Animation
9757
	return anim; // dojo.lfx.Animation
9721
}
9758
}
9722
 
9759
 
9723
dojo.lfx.html.highlight = function(/*DOMNode[]*/ nodes,
9760
dojo.lfx.html.highlight = function(/*DOMNode[]*/ nodes,
9724
								   /*dojo.gfx.color.Color*/ startColor,
9761
								   /*dojo.gfx.color.Color*/ startColor,
9725
								   /*int?*/ duration,
9762
								   /*int?*/ duration,
9726
								   /*Function?*/ easing,
9763
								   /*Function?*/ easing,
9727
								   /*Function?*/ callback){
9764
								   /*Function?*/ callback){
9728
	// summary: Returns an animation that will set the background color
9765
	// summary: Returns an animation that will set the background color
9729
	//			of "nodes" to startColor and transition it to "nodes"
9766
	//			of "nodes" to startColor and transition it to "nodes"
9730
	//			original color.
9767
	//			original color.
9731
	// startColor: Color to transition from.
9768
	// startColor: Color to transition from.
9732
	// duration: Duration of the animation in milliseconds.
9769
	// duration: Duration of the animation in milliseconds.
9733
	// easing: An easing function.
9770
	// easing: An easing function.
9734
	// callback: Function to run at the end of the animation.
9771
	// callback: Function to run at the end of the animation.
9735
	nodes = dojo.lfx.html._byId(nodes);
9772
	nodes = dojo.lfx.html._byId(nodes);
9736
	var anims = [];
9773
	var anims = [];
9737
 
9774
 
9738
	dojo.lang.forEach(nodes, function(node){
9775
	dojo.lang.forEach(nodes, function(node){
9739
		var color = dojo.html.getBackgroundColor(node);
9776
		var color = dojo.html.getBackgroundColor(node);
9740
		var bg = dojo.html.getStyle(node, "background-color").toLowerCase();
9777
		var bg = dojo.html.getStyle(node, "background-color").toLowerCase();
9741
		var bgImage = dojo.html.getStyle(node, "background-image");
9778
		var bgImage = dojo.html.getStyle(node, "background-image");
9742
		var wasTransparent = (bg == "transparent" || bg == "rgba(0, 0, 0, 0)");
9779
		var wasTransparent = (bg == "transparent" || bg == "rgba(0, 0, 0, 0)");
9743
		while(color.length > 3) { color.pop(); }
9780
		while(color.length > 3) { color.pop(); }
9744
 
9781
 
9745
		var rgb = new dojo.gfx.color.Color(startColor);
9782
		var rgb = new dojo.gfx.color.Color(startColor);
9746
		var endRgb = new dojo.gfx.color.Color(color);
9783
		var endRgb = new dojo.gfx.color.Color(color);
9747
 
9784
 
9748
		var anim = dojo.lfx.propertyAnimation(node, 
9785
		var anim = dojo.lfx.propertyAnimation(node, 
9749
			{ "background-color": { start: rgb, end: endRgb } }, 
9786
			{ "background-color": { start: rgb, end: endRgb } }, 
9750
			duration, 
9787
			duration, 
9751
			easing,
9788
			easing,
9752
			{
9789
			{
9753
				"beforeBegin": function(){ 
9790
				"beforeBegin": function(){ 
9754
					if(bgImage){
9791
					if(bgImage){
9755
						node.style.backgroundImage = "none";
9792
						node.style.backgroundImage = "none";
9756
					}
9793
					}
9757
					node.style.backgroundColor = "rgb(" + rgb.toRgb().join(",") + ")";
9794
					node.style.backgroundColor = "rgb(" + rgb.toRgb().join(",") + ")";
9758
				},
9795
				},
9759
				"onEnd": function(){ 
9796
				"onEnd": function(){ 
9760
					if(bgImage){
9797
					if(bgImage){
9761
						node.style.backgroundImage = bgImage;
9798
						node.style.backgroundImage = bgImage;
9762
					}
9799
					}
9763
					if(wasTransparent){
9800
					if(wasTransparent){
9764
						node.style.backgroundColor = "transparent";
9801
						node.style.backgroundColor = "transparent";
9765
					}
9802
					}
9766
					if(callback){
9803
					if(callback){
9767
						callback(node, anim);
9804
						callback(node, anim);
9768
					}
9805
					}
9769
				}
9806
				}
9770
			}
9807
			}
9771
		);
9808
		);
9772
 
9809
 
9773
		anims.push(anim);
9810
		anims.push(anim);
9774
	});
9811
	});
9775
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9812
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9776
}
9813
}
9777
 
9814
 
9778
dojo.lfx.html.unhighlight = function(/*DOMNode[]*/ nodes,
9815
dojo.lfx.html.unhighlight = function(/*DOMNode[]*/ nodes,
9779
									 /*dojo.gfx.color.Color*/ endColor,
9816
									 /*dojo.gfx.color.Color*/ endColor,
9780
									 /*int?*/ duration,
9817
									 /*int?*/ duration,
9781
									 /*Function?*/ easing,
9818
									 /*Function?*/ easing,
9782
									 /*Function?*/ callback){
9819
									 /*Function?*/ callback){
9783
	// summary: Returns an animation that will transition "nodes" background color
9820
	// summary: Returns an animation that will transition "nodes" background color
9784
	//			from its current color to "endColor".
9821
	//			from its current color to "endColor".
9785
	// endColor: Color to transition to.
9822
	// endColor: Color to transition to.
9786
	// duration: Duration of the animation in milliseconds.
9823
	// duration: Duration of the animation in milliseconds.
9787
	// easing: An easing function.
9824
	// easing: An easing function.
9788
	// callback: Function to run at the end of the animation.
9825
	// callback: Function to run at the end of the animation.
9789
	nodes = dojo.lfx.html._byId(nodes);
9826
	nodes = dojo.lfx.html._byId(nodes);
9790
	var anims = [];
9827
	var anims = [];
9791
 
9828
 
9792
	dojo.lang.forEach(nodes, function(node){
9829
	dojo.lang.forEach(nodes, function(node){
9793
		var color = new dojo.gfx.color.Color(dojo.html.getBackgroundColor(node));
9830
		var color = new dojo.gfx.color.Color(dojo.html.getBackgroundColor(node));
9794
		var rgb = new dojo.gfx.color.Color(endColor);
9831
		var rgb = new dojo.gfx.color.Color(endColor);
9795
 
9832
 
9796
		var bgImage = dojo.html.getStyle(node, "background-image");
9833
		var bgImage = dojo.html.getStyle(node, "background-image");
9797
		
9834
		
9798
		var anim = dojo.lfx.propertyAnimation(node, 
9835
		var anim = dojo.lfx.propertyAnimation(node, 
9799
			{ "background-color": { start: color, end: rgb } },
9836
			{ "background-color": { start: color, end: rgb } },
9800
			duration, 
9837
			duration, 
9801
			easing,
9838
			easing,
9802
			{
9839
			{
9803
				"beforeBegin": function(){ 
9840
				"beforeBegin": function(){ 
9804
					if(bgImage){
9841
					if(bgImage){
9805
						node.style.backgroundImage = "none";
9842
						node.style.backgroundImage = "none";
9806
					}
9843
					}
9807
					node.style.backgroundColor = "rgb(" + color.toRgb().join(",") + ")";
9844
					node.style.backgroundColor = "rgb(" + color.toRgb().join(",") + ")";
9808
				},
9845
				},
9809
				"onEnd": function(){ 
9846
				"onEnd": function(){ 
9810
					if(callback){
9847
					if(callback){
9811
						callback(node, anim);
9848
						callback(node, anim);
9812
					}
9849
					}
9813
				}
9850
				}
9814
			}
9851
			}
9815
		);
9852
		);
9816
		anims.push(anim);
9853
		anims.push(anim);
9817
	});
9854
	});
9818
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9855
	return dojo.lfx.combine(anims); // dojo.lfx.Combine
9819
}
9856
}
9820
 
9857
 
9821
dojo.lang.mixin(dojo.lfx, dojo.lfx.html);
9858
dojo.lang.mixin(dojo.lfx, dojo.lfx.html);
9822
 
9859
 
9823
dojo.kwCompoundRequire({
9860
dojo.kwCompoundRequire({
9824
	browser: ["dojo.lfx.html"],
9861
	browser: ["dojo.lfx.html"],
9825
	dashboard: ["dojo.lfx.html"]
9862
	dashboard: ["dojo.lfx.html"]
9826
});
9863
});
9827
dojo.provide("dojo.lfx.*");
9864
dojo.provide("dojo.lfx.*");
9828
 
9865