[Dojo-checkins] toonetown - r17740 - in dojox/trunk/form: . tests

dojo-checkins-admin at dojotoolkit.org dojo-checkins-admin at dojotoolkit.org
Fri Jun 5 16:59:19 EDT 2009


Author: toonetown
Date: Fri Jun  5 13:59:15 2009
New Revision: 17740

Modified:
   dojox/trunk/form/DropDownSelect.js
   dojox/trunk/form/_FormSelectWidget.js
   dojox/trunk/form/tests/test_CheckedMultiSelect.html
   dojox/trunk/form/tests/test_DropDownSelect.html
Log:
Fixes #6652 Add support for dojo.data stores to _FormSelectWidget (which, in turn, enables that support in DropDownSelect and CheckedMultiSelect).  Also update the test cases for DDS and CMS. !strict

Modified: dojox/trunk/form/DropDownSelect.js
==============================================================================
--- dojox/trunk/form/DropDownSelect.js	(original)
+++ dojox/trunk/form/DropDownSelect.js	Fri Jun  5 13:59:15 2009
@@ -151,7 +151,10 @@
 			this.attr("disabled", (len === 0));
 			delete this._iDisabled;
 		}
-		this._setValueAttr(this.value);
+		if(!this._loadingStore){
+			// Don't call this if we are loading - since we will handle it later
+			this._setValueAttr(this.value);
+		}
 	},
 	
 	_setValueAttr: function(value){

Modified: dojox/trunk/form/_FormSelectWidget.js
==============================================================================
--- dojox/trunk/form/_FormSelectWidget.js	(original)
+++ dojox/trunk/form/_FormSelectWidget.js	Fri Jun  5 13:59:15 2009
@@ -1,6 +1,7 @@
 dojo.provide("dojox.form._FormSelectWidget");
 
 dojo.require("dijit.form._FormWidget");
+dojo.require("dojo.data.util.sorter");
 
 /*=====
 dojox.form.__SelectOption = function(){
@@ -21,6 +22,12 @@
 =====*/
 
 dojo.declare("dojox.form._FormSelectWidget", dijit.form._FormValueWidget, {
+	// summary:
+	//		Extends _FormValueWidget in order to provide "select-specific"
+	//		values - i.e., those values that are unique to <select> elements.
+	//		This also provides the mechanism for reading the elements from
+	//		a store, if desired.
+
 	// multiple: Boolean
 	//		Matches the select's "multiple=" value
 	multiple: "",
@@ -34,6 +41,38 @@
 	//      the html <option> tag.
 	options: null,
 	
+	// store: dojo.data.api.Identity
+	//		A store which, at the very least impelements dojo.data.api.Identity
+	//		to use for getting our list of options - rather than reading them
+	//		from the <option> html tags.
+	store: null,
+
+	// query: object
+	//		A query to use when fetching items from our store
+	query: null,
+
+	// queryOptions: object
+	//		Query options to use when fetching from the store
+	queryOptions: null,
+
+	// onFetch: Function
+	//		A callback to do with an onFetch - but before any items are actually
+	//		iterated over (i.e. to filter even futher what you want to add)
+	onFetch: null,
+
+	// sortByLabel: boolean
+	//		Flag to sort the options returned from a store by the label of
+	//		the store.
+	sortByLabel: true,
+
+	
+	// loadChildrenOnOpen: boolean
+	//		By default loadChildren is called when the items are fetched from the
+	//		store.  This property allows delaying loadChildren (and the creation
+	//		of the options/menuitems) until the user opens the click the button.
+	//		dropdown
+	loadChildrenOnOpen: false,
+
 	getOptions: function(/* anything */ valueOrIdx){
 		// summary:
 		//		Returns a given option (or options).
@@ -150,9 +189,98 @@
 		this._loadChildren();
 	},
 
+	setStore: function(/* dojo.data.api.Identity */ store, 
+						/* anything? */ selectedValue, 
+						/* Object? */ fetchArgs){
+		// summary:
+		//		Sets the store you would like to use with this select widget.
+		//		The selected value is the value of the new store to set.  This 
+		//		function returns the original store, in case you want to reuse 
+		//		it or something.
+		// store: dojo.data.api.Identity
+		//		The store you would like to use - it MUST implement Identity,
+		//		and MAY implement Notification.
+		// selectedValue: anything?
+		//		The value that this widget should set itself to *after* the store
+		//		has been loaded
+		// fetchArgs: Object?
+		//		The arguments that will be passed to the store's fetch() function
+		var oStore = this.store;
+		fetchArgs = fetchArgs || {};
+		if(oStore !== store){
+			// Our store has changed, so update our notifications
+			dojo.forEach(this._notifyConnections||[], dojo.disconnect);
+			delete this._notifyConnections;
+			if(store && store.getFeatures()["dojo.data.api.Notification"]){
+				this._notifyConnections = [
+					dojo.connect(store, "onNew", this, "_onNewItem"),
+					dojo.connect(store, "onDelete", this, "_onDeleteItem"),
+					dojo.connect(store, "onSet", this, "_onSetItem")
+				];
+			}
+			this.store = store;
+		}
+		
+		// Turn off change notifications while we make all these changes
+		this._onChangeActive = false;
+		
+		// Remove existing options (if there are any)
+		if(this.options && this.options.length){
+			this.removeOption(this.options);
+		}
+		
+		// Add our new options
+		if(store){
+			var cb = function(items){
+				if(this.sortByLabel && !fetchArgs.sort && items.length){
+					items.sort(dojo.data.util.sorter.createSortFunction([{
+						attribute: store.getLabelAttributes(items[0])[0]
+					}], store));
+				}
+				
+				if(fetchArgs.onFetch){
+					items = fetchArgs.onFetch(items);
+				}
+				// TODO: Add these guys as a batch, instead of separately
+				dojo.forEach(items, function(i){
+					this._addOptionForItem(i);
+				}, this);
+				
+				// Set our value (which might be undefined), and then tweak
+				// it to send a change event with the real value
+				this._loadingStore = false;
+				this.attr("value", (("_pendingValue" in this) ? this._pendingValue : selectedValue));
+				delete this._pendingValue;
+
+				if(!this.loadChildrenOnOpen){
+					this._loadChildren();
+				}else{
+					this._pseudoLoadChildren(items);
+				}
+				this._fetchedWith = opts;
+				this._lastValueReported = this._multiValue ? [] : null;
+				this._onChangeActive = true;
+				this.onSetStore();
+				this._handleOnChange(this.value);
+			};
+			var opts = dojo.mixin({onComplete:cb, scope: this}, fetchArgs);
+			this._loadingStore = true;
+			store.fetch(opts);
+		}else{
+			delete this._fetchedWith;
+		}
+		return oStore;	// dojo.data.api.Identity
+	},
+
 	_setValueAttr: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
 		// summary: set the value of the widget.
 		// If a string is passed, then we set our value from looking it up.
+		if(this._loadingStore){
+			// Our store is loading - so save our value, and we'll set it when
+			// we're done
+			this._pendingValue = newValue;
+			return;
+		}
 		var opts = this.getOptions() || [];
 		if(!dojo.isArray(newValue)){
 			newValue = [newValue];
@@ -217,6 +345,7 @@
 		// summary: 
 		//		Loads the children represented by this widget's optiosn.
 		// reset the menu to make it "populatable on the next click
+		if(this._loadingStore){ return; }
 		dojo.forEach(this._getChildren(), function(child){
 			child.destroyRecursive();
 		});	
@@ -274,6 +403,55 @@
 		return "";
 	},
 	
+	// Internal functions to call when we have store notifications come in
+	_onNewItem: function(/* item */ item, /* Object? */ parentInfo){
+		if(!parentInfo || !parentInfo.parent){
+			// Only add it if we are top-level
+			this._addOptionForItem(item);
+		}
+	},
+	_onDeleteItem: function(/* item */ item){
+		var store = this.store;
+		this.removeOption(store.getIdentity(item));
+	},
+	_onSetItem: function(/* item */ item){
+		this.updateOption(this._getOptionObjForItem(item));
+	},
+
+	_getOptionObjForItem: function(item){
+		// summary:
+		//		Returns an option object based off the given item.  The "value"
+		//		of the option item will be the identity of the item, the "label"
+		//		of the option will be the label of the item.  If the item contains
+		//		children, the children value of the item will be set 
+		var store = this.store, label = store.getLabel(item), 
+			value = (label ? store.getIdentity(item) : null);
+		return {value: value, label: label, item:item}; // dojox.form.__SelectOption
+	},
+
+	_addOptionForItem: function(/* item */ item){
+		// summary:
+		//		Creates (and adds) the option for the given item
+		var store = this.store;
+		if(!store.isItemLoaded(item)){
+			// We are not loaded - so let's load it and add later
+			store.loadItem({item: item, onComplete: function(i){
+				this._addOptionForItem(item);
+			},
+			scope: this});
+			return;
+		}
+		var newOpt = this._getOptionObjForItem(item);
+		this.addOption(newOpt);
+	},	
+
+	constructor: function(/* Object */ keywordArgs){
+		// summary:
+		//		Saves off our value, if we have an initial one set so we
+		//		can use it if we have a store as well (see startup())
+		this._oValue = (keywordArgs||{}).value || null;
+	},
+	
 	postMixInProperties: function(){
 		this._multiValue = (this.multiple.toLowerCase() === "true");
 		this.inherited(arguments);
@@ -317,6 +495,32 @@
 		this._setValueAttr(this.value, null);
 	},
 	
+	startup: function(){
+		// summary:
+		//		Connects in our store, if we have one defined
+		this.inherited(arguments);
+		var store = this.store, fetchArgs = {};
+		dojo.forEach(["query", "queryOptions", "onFetch"], function(i){
+			if(this[i]){
+				fetchArgs[i] = this[i];
+			}
+			delete this[i];
+		}, this);
+		if(store && store.getFeatures()["dojo.data.api.Identity"]){
+			// Temporarily set our store to null so that it will get set
+			// and connected appropriately
+			this.store = null;
+			this.setStore(store, this._oValue, fetchArgs);
+		}
+	},
+	
+	destroy: function(){
+		// summary:
+		//		Clean up our connections
+		dojo.forEach(this._notifyConnections||[], dojo.disconnect);
+		this.inherited(arguments);
+	},
+	
 	_addOptionItem: function(/* dojox.form.__SelectOption */ option){
 		// summary:
 		//		User-overridable function which, for the given option, adds an 
@@ -348,6 +552,18 @@
 		// summary: hooks into this.attr to provide a mechanism for getting the
 		//			option items for the current value of the widget.
 		return this.getOptions(this.attr("value"));
+	},
+	
+	_pseudoLoadChildren: function(/* item[] */ items){
+		// summary: a function that will "fake" loading children, if needed, and
+		//			if we have set to not load children until the widget opens.
+		// items: item[]
+		//			An array of items that will be loaded, when needed
+	},
+	
+	onSetStore: function(){
+		// summary: a function that can be connected to in order to receive a
+		//		notification that the store has finished loading and all options
+		//		from that store are available
 	}
-
 });

Modified: dojox/trunk/form/tests/test_CheckedMultiSelect.html
==============================================================================
--- dojox/trunk/form/tests/test_CheckedMultiSelect.html	(original)
+++ dojox/trunk/form/tests/test_CheckedMultiSelect.html	Fri Jun  5 13:59:15 2009
@@ -10,9 +10,30 @@
 			dojo.require("dojox.form.CheckedMultiSelect");
 			dojo.require("dijit.form.Button");
 			dojo.require("dijit.form.Form");
+			dojo.require("dojo.data.ItemFileWriteStore");
+		
+			var data = {
+				identifier: "value",
+				label: "label",
+				items: [
+					{value: "AL", label: "Alabama"},
+					{value: "AK", label: "Alaska"},
+					{value: "AZ", label: "Arizona"},
+					{value: "AR", label: "Arkansas"},
+					{value: "CA", label: "California"},
+					{value: "CO", label: "Colorado"},
+					{value: "CT", label: "Connecticut"}
+				]
+			};
+			
+			var readStore = new dojo.data.ItemFileReadStore({data:dojo.clone(data)});
+			var writeStore = new dojo.data.ItemFileWriteStore({data:dojo.clone(data)});
 			
-			var perfNum = 100;
 			var numOptions = 0;
+			var addNum = 10;
+			var testType;
+			// Uncomment below line to run perf tests - note SLOW to run
+			//testType = "perf";
 		
 			dojo.addOnLoad(function(){
 				doh.register("tests",
@@ -34,20 +55,6 @@
 							ms1.invertSelection();
 							t.is(["TN","CA"], form.attr("value").ms1);
 						},
-						function test_performance(t){
-							var i, start, add, del, opts = [];
-							for(i = 0; i < perfNum; i++){
-								opts.push({value: i + "", label: "Option " + (i + 1)});
-							}
-							start = new Date();
-							ms3.addOption(opts);
-							add = new Date();
-							ms3.removeOption(opts);
-							del = new Date();
-							console.log("Create (" + perfNum + "): " + (add.getTime() - start.getTime()) +
-										"ms, Remove: " + (del.getTime() - add.getTime()) + "ms");
-							t.t(true);
-						},
 						function delete_selected(t){
 							t.is(["TN","CA"], ms1.getValue());
 							var d = new doh.Deferred();
@@ -59,6 +66,141 @@
 								}catch(e){ d.errback(e); }
 							}, 100);
 							return d;
+						},
+						function test_storeBased(t){
+							t.is([], ms4.attr("value"));
+							ms4.attr("value", ["CA","AL"]);
+							t.is(["AL","CA"], ms4.attr("value"));
+						},
+						function test_changeSelected(t){
+							t.is([], ms5.attr("value"));
+							ms5.attr("value", ["AL", "AK"]);
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									writeStore.setValue(item, "label", "North Pole");
+									try{
+										t.is(["AL","AK"], ms5.attr("value"));
+										t.is(writeStore.getValue(item, "label"), 
+												dojo.filter(ms5._getChildren(), function(n){return n.option.value==="AK";})[0].labelNode.innerHTML);
+										d.callback(true);
+									}catch(e){ d.errback(e);}
+								}
+								catch(e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AK", onItem: cb});
+							return d;
+						},
+						function test_deleteNonSelected(t){
+							t.is(["AL","AK"], ms5.attr("value"));
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									t.is(7, ms5._getChildren().length);
+									writeStore.deleteItem(item);
+									try{
+										t.is(["AL","AK"], ms5.attr("value"));
+										t.is(6, ms5._getChildren().length);
+										d.callback(true);
+									}catch(e){ d.errback(e);}
+								}catch (e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AZ", onItem: cb});
+							return d;
+						},
+						function test_deleteSelected(t){
+							t.is(["AL","AK"], ms5.attr("value"));
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									t.is(6, ms5._getChildren().length);
+									writeStore.deleteItem(item);
+									try{
+										t.is(["AL"], ms5.attr("value"));
+										t.is(5, ms5._getChildren().length);
+										d.callback(true);
+									}catch(e){ d.errback(e);}
+								}catch (e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AK", onItem: cb});
+							return d;
+						},
+						function test_newItem(t){
+							t.is(["AL"], ms5.attr("value"));
+							t.is(5, ms5._getChildren().length);
+							ms5.attr("value", ["AL","NY"]);
+							t.is(["AL"], ms5.attr("value"));
+							var d = new doh.Deferred();
+							writeStore.newItem({value: "NY", label: "New York"});
+							try{
+								t.is(6, ms5._getChildren().length);
+								ms5.attr("value", ["AL","NY"]);
+								t.is(["AL","NY"], ms5.attr("value"));
+								d.callback(true);
+							}catch(e){d.errback(e);}
+							return d;
+						},
+						{
+							name: "test_performance_single",
+							testType: testType,
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							runTest: function(t){
+								var opt = {value: "Test", label: "Test Option"};
+								ms3.addOption(opt);
+								ms3.removeOption(opt);
+							}
+						},
+						{
+							name: "test_performance_separate",
+							testType: testType,
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							setUp: function(t){
+								var opts = t.options = [];
+								for(var i = 0; i < addNum; i++){
+									opts.push({value: i + "", label: "Option " + (i + 1)});
+								}
+							},
+							runTest: function(t){
+								dojo.forEach(t.options, function(opt){
+									ms3.addOption(opt);
+								});
+								dojo.forEach(t.options, function(opt){
+									ms3.removeOption(opt);
+								});
+							},
+							tearDown: function(t){
+								delete t.options;
+							}
+						},
+						{
+							name: "test_performance_batch",
+							testType: testType,
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							setUp: function(t){
+								var opts = t.options = [];
+								for(var i = 0; i < addNum; i++){
+									opts.push({value: i + "", label: "Option " + (i + 1)});
+								}
+							},
+							runTest: function(t){
+								ms3.addOption(t.options);
+								ms3.removeOption(t.options);
+							},
+							tearDown: function(t){
+								delete t.options;
+							}
 						}
 					]
 				);
@@ -124,6 +266,12 @@
 			<select jsId="ss3" name="ss3" dojoType="dojox.form.CheckedMultiSelect">
 			</select>
 		<hr>
+			<h4 class="testSubtitle">Store-based</h4>
+			<select jsId="ms4" multiple="true" size="5" name="ms4" store="readStore" dojoType="dojox.form.CheckedMultiSelect">
+			</select>
+			<select jsId="ms5" multiple="true" size="5" name="ms5" store="writeStore" dojoType="dojox.form.CheckedMultiSelect">
+			</select>
+		<hr>
 			<button dojoType="dijit.form.Button">
 				<script type="dojo/method" event="onClick">
 					console.dir(form.attr("value"));

Modified: dojox/trunk/form/tests/test_DropDownSelect.html
==============================================================================
--- dojox/trunk/form/tests/test_DropDownSelect.html	(original)
+++ dojox/trunk/form/tests/test_DropDownSelect.html	Fri Jun  5 13:59:15 2009
@@ -21,6 +21,7 @@
 			dojo.require("dijit.form.Button");
 			dojo.require("dijit.form.Form");
             dojo.require("dojox.form.CheckedMultiSelect");
+			dojo.require("dojo.data.ItemFileWriteStore");
 			
 			var numOptions = 0;
 			var numChanges = 0;
@@ -29,6 +30,42 @@
 			// Uncomment below line to run perf tests - note SLOW to run
 			// testType = "perf";
 			
+			// Data and stores here for store-based selects
+			var data = {
+				identifier: "value",
+				label: "label",
+				items: [
+					{value: "AL", label: "Alabama"},
+					{value: "AK", label: "Alaska"},
+					{value: "AZ", label: "Arizona"},
+					{value: "AR", label: "Arkansas"},
+					{value: "CA", label: "California"},
+					{value: "CO", label: "Colorado"},
+					{value: "CT", label: "Connecticut"}
+				]
+			};
+			var data2 = {
+				identifier: "value",
+				label: "label",
+				items: [
+					{value: "DE", label: "Deleware"},
+					{value: "FL", label: "Florida"},
+					{value: "GA", label: "Georgia"},
+					{value: "HI", label: "Hawaii"},
+					{value: "ID", label: "Idaho"},
+					{value: "IL", label: "Illinois"},
+					{value: "IN", label: "Indiana"}
+				]
+			};
+			
+			var readStore = new dojo.data.ItemFileReadStore({data:dojo.clone(data)});
+			var store2 = new dojo.data.ItemFileReadStore({data:dojo.clone(data2)});
+			var writeStore = new dojo.data.ItemFileWriteStore({data:dojo.clone(data)});			
+			
+			function wrapLabel(expected){
+				return ("<span class=\"dijitReset dijitInline dojoxDropDownSelectLabel\">" + expected + "</span>").toLowerCase().replace(/ */g, "");
+			}
+
 			dojo.addOnLoad(function(){
 				dojo.connect(s1, "onChange", function(val){
 					console.log("First Select Changed to " + val);
@@ -37,13 +74,110 @@
 				doh.register("tests",
 					[
 						function test_setValue(t){
-							t.is({s1:"VA", s2:"CA", s3:"AL", s4: "AK", s5: "move", s7:"NY", s8:"AL"}, form.attr("value"));
+							t.is({s1:"VA", s2:"CA", s3:"AL", s4: "AK", s5: "move", s7:"NY", s8:"AL",
+								s9:"CT", s10:"AL", s11:"AL", s12: "AL"}, form.attr("value"));
 							s1.attr("value", "WA");
 							t.is("WA", s1.value);
 							s1.attr("value", "UT");
 							t.is("TN", s1.value);
 							t.is(2, numChanges);
 						},
+						function test_changeSelected(t){
+							t.is("AL", s11.value);
+							t.is(wrapLabel("Alabama"), s11.containerNode.innerHTML.toLowerCase().replace(/ */g, ""));
+							s11.attr("value", "AK");
+							t.is("AK", s11.value);
+							t.is(wrapLabel("Alaska"), s11.containerNode.innerHTML.toLowerCase().replace(/ */g, ""));
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									writeStore.setValue(item, "label", "North Pole");
+									s11.loadDropDown(function(){
+										try{
+											t.is("AK", s11.value);
+											t.is(wrapLabel("North Pole"), s11.containerNode.innerHTML.toLowerCase().replace(/ */g, ""));
+											d.callback(true);
+										}catch(e){ d.errback(e);}
+									});
+								}
+								catch(e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AK", onItem: cb});
+							return d;
+						},
+						function test_deleteNonSelected(t){
+							t.is(7, s11._getChildren().length);
+							t.is("AK", s11.value);
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									t.is(7, s11._getChildren().length);
+									writeStore.deleteItem(item);
+									s11.loadDropDown(function(){
+										try{
+											t.is("AK", s11.value);
+											t.is(6, s11._getChildren().length);
+											d.callback(true);
+										}catch(e){ d.errback(e);}										
+									});
+								}catch (e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AZ", onItem: cb});
+							return d;
+						},
+						function test_deleteSelected(t){
+							t.is(6, s11._getChildren().length);
+							t.is("AK", s11.value);
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									writeStore.deleteItem(item);
+									window.setTimeout(function(){
+										try{
+											t.is("AL", s11.value);
+											d.callback(true);
+										}catch(e){d.errback(e);}
+									}, 100);
+								}catch (e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AK", onItem: cb});
+							return d;
+						},
+						function test_newItem(t){
+							t.is(5, s11._getChildren().length);
+							t.is("AL", s11.value);
+							s11.attr("value", "NY");
+							t.is("AL", s11.value);
+							var d = new doh.Deferred();
+							writeStore.newItem({value: "NY", label: "New York"});
+							window.setTimeout(function(){
+								try{
+									t.is(6, s11._getChildren().length);
+									s11.attr("value", "NY");
+									t.is("NY", s11.value);
+									d.callback(true);
+								} catch (e) {
+									d.errback(e);
+								}
+							}, 100);
+							return d;
+						},
+						function test_setStore(t){
+							t.is("AL", s12.value);
+							s12.setStore(store2, "FL");
+							t.is("FL", s12.value);
+							s12.setStore(readStore, "CA");
+							t.is("CA", s12.value);
+							s12.setStore(store2);
+							t.is("DE", s12.value);
+							t.is(7, s12._getChildren().length);
+						},
 						{
 							name: "test_performance_single",
 							testType: testType,
@@ -99,7 +233,7 @@
 							tearDown: function(t){
 								delete t.options;
 							}
-						},
+						}
 					]
 				);
 				doh.run();
@@ -214,13 +348,24 @@
 				<option value="WI">Wisconsin</option>
 				<option value="WY">Wyoming</option>
 			</select>
+			<hr>
+			<h4 class="testSubtitle">Store-based</h4>
+			<select jsId="s9" name="s9" store="readStore" value="CT" dojoType="dojox.form.DropDownSelect">
+			</select>
+			<select jsId="s10" name="s10" store="readStore" dojoType="dojox.form.DropDownSelect">
+			</select>
+			<select jsId="s11" name="s11" store="writeStore" dojoType="dojox.form.DropDownSelect">
+			</select>
+			<select jsId="s12" name="s12" store="readStore" dojoType="dojox.form.DropDownSelect">
+			</select>
+			<hr>
 			<h4 class="testSubtitle">Inlined with text (all IE modes except for IE8 Standards)</h4>
 			Text Prompt:
 			<select dojoType="dojox.form.DropDownSelect">
 				<option value="SEL" selected="selected">DropDownSelect</option>
 				<option value="OTHER">Other</option>
 			</select>
-
+			<hr>
             <h4 class="testSubtitle">DropDownSelect.updateOptions</h4>
             <div>Click on the DropDownSelect to open the DropDown.  While the DropDown is opened, click on a checkbox.</div>
             <select id="updateOptions" dojoType="dojox.form.DropDownSelect">
@@ -238,8 +383,7 @@
                 <option value="FL">Florida</option>
                 <option value="CA">California</option>
             </select>
-
-            <hr>
+			<hr>
 			<button dojoType="dijit.form.Button">
 				<script type="dojo/method" event="onClick">
 					console.dir(form.getValues());


More information about the Dojo-checkins mailing list