PageRenderTime 319ms CodeModel.GetById 108ms app.highlight 7ms RepoModel.GetById 94ms app.codeStats 1ms

/wheels/view/formsobject.cfm

http://cfwheels.googlecode.com/
ColdFusion | 618 lines | 603 code | 15 blank | 0 comment | 163 complexity | 31bb358538bb9b73bfdd2b66d3b41c8f MD5 | raw file
  1<cffunction name="textField" returntype="string" access="public" output="false" hint="Builds and returns a string containing a text field form control based on the supplied `objectName` and `property`. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
  2	examples=
  3	'
  4		<!--- Provide a `label` and the required `objectName` and `property` --->
  5		<cfoutput>
  6		    ##textField(label="First Name", objectName="user", property="firstName")##
  7		</cfoutput>
  8
  9		<!--- Display fields for phone numbers provided by the `phoneNumbers` association and nested properties --->
 10		<fieldset>
 11			<legend>Phone Numbers</legend>
 12			<cfloop from="1" to="##ArrayLen(contact.phoneNumbers)##" index="i">
 13				##textField(label="Phone ####i##", objectName="contact", association="phoneNumbers", position=i, property="phoneNumber")##
 14			</cfloop>
 15		</fieldset>
 16	'
 17	categories="view-helper,forms-object" chapters="form-helpers-and-showing-errors,nested-properties" functions="URLFor,startFormTag,endFormTag,submitTag,radioButton,checkBox,passwordField,hiddenField,textArea,fileField,select,dateTimeSelect,dateSelect,timeSelect">
 18	<cfargument name="objectName" type="any" required="true" hint="The variable name of the object to build the form control for.">
 19	<cfargument name="property" type="string" required="true" hint="The name of the property to use in the form control.">
 20	<cfargument name="association" type="string" required="false" hint="The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.">
 21	<cfargument name="position" type="string" required="false" hint="The position used when referencing a `hasMany` relationship in the `association` argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.">
 22	<cfargument name="label" type="string" required="false" hint="The label text to use in the form control.">
 23	<cfargument name="labelPlacement" type="string" required="false" hint="Whether to place the label `before`, `after`, or wrapped `around` the form control.">
 24	<cfargument name="prepend" type="string" required="false" hint="String to prepend to the form control. Useful to wrap the form control with HTML tags.">
 25	<cfargument name="append" type="string" required="false" hint="String to append to the form control. Useful to wrap the form control with HTML tags.">
 26	<cfargument name="prependToLabel" type="string" required="false" hint="String to prepend to the form control's `label`. Useful to wrap the form control with HTML tags.">
 27	<cfargument name="appendToLabel" type="string" required="false" hint="String to append to the form control's `label`. Useful to wrap the form control with HTML tags.">
 28	<cfargument name="errorElement" type="string" required="false" hint="HTML tag to wrap the form control with when the object contains errors.">
 29	<cfargument name="errorClass" type="string" required="false" hint="The class name of the HTML tag that wraps the form control when there are errors.">
 30	<cfscript>
 31		var loc = {};
 32		$args(name="textField", reserved="name,value", args=arguments);
 33		arguments.objectName = $objectName(argumentCollection=arguments);
 34		if (!StructKeyExists(arguments, "id"))
 35			arguments.id = $tagId(arguments.objectName, arguments.property);
 36		loc.before = $formBeforeElement(argumentCollection=arguments);
 37		loc.after = $formAfterElement(argumentCollection=arguments);
 38		if (!StructKeyExists(arguments, "type"))
 39			arguments.type = "text";
 40		arguments.name = $tagName(arguments.objectName, arguments.property);
 41		loc.maxlength = $maxLength(argumentCollection=arguments);
 42		if (StructKeyExists(loc, "maxlength"))
 43			arguments.maxlength = loc.maxlength;
 44		arguments.value = $formValue(argumentCollection=arguments);
 45		loc.returnValue = loc.before & $tag(name="input", close=true, skip="objectName,property,label,labelPlacement,prepend,append,prependToLabel,appendToLabel,errorElement,errorClass,association,position", skipStartingWith="label", attributes=arguments) & loc.after;
 46	</cfscript>
 47	<cfreturn loc.returnValue>
 48</cffunction>
 49
 50<cffunction name="passwordField" returntype="string" access="public" output="false" hint="Builds and returns a string containing a password field form control based on the supplied `objectName` and `property`. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
 51	examples=
 52	'
 53		<!--- Provide a `label` and the required `objectName` and `property` --->
 54		<cfoutput>
 55		    ##passwordField(label="Password", objectName="user", property="password")##
 56		</cfoutput>
 57
 58		<!--- Display fields for passwords provided by the `passwords` association and nested properties --->
 59		<fieldset>
 60			<legend>Passwords</legend>
 61			<cfloop from="1" to="##ArrayLen(user.passwords)##" index="i">
 62				##passwordField(label="Password ####i##", objectName="user", association="passwords", position=i, property="password")##
 63			</cfloop>
 64		</fieldset>
 65	'
 66	categories="view-helper,forms-object" chapter="form-helpers-and-showing-errors,nested-properties" functions="URLFor,startFormTag,endFormTag,submitTag,textField,radioButton,checkBox,hiddenField,textArea,fileField,select,dateTimeSelect,dateSelect,timeSelect">
 67	<cfargument name="objectName" type="any" required="true" hint="See documentation for @textField.">
 68	<cfargument name="property" type="string" required="true" hint="See documentation for @textField.">
 69	<cfargument name="association" type="string" required="false" hint="See documentation for @textfield.">
 70	<cfargument name="position" type="string" required="false" hint="See documentation for @textfield.">
 71	<cfargument name="label" type="string" required="false" hint="See documentation for @textField">
 72	<cfargument name="labelPlacement" type="string" required="false" hint="See documentation for @textField.">
 73	<cfargument name="prepend" type="string" required="false" hint="See documentation for @textField.">
 74	<cfargument name="append" type="string" required="false" hint="See documentation for @textField.">
 75	<cfargument name="prependToLabel" type="string" required="false" hint="See documentation for @textField.">
 76	<cfargument name="appendToLabel" type="string" required="false" hint="See documentation for @textField.">
 77	<cfargument name="errorElement" type="string" required="false" hint="See documentation for @textField.">
 78	<cfargument name="errorClass" type="string" required="false" hint="See documentation for @textField.">
 79	<cfscript>
 80		var loc = {};
 81		$args(name="passwordField", reserved="type,name,value", args=arguments);
 82		arguments.objectName = $objectName(argumentCollection=arguments);
 83		if (!StructKeyExists(arguments, "id"))
 84			arguments.id = $tagId(arguments.objectName, arguments.property);
 85		loc.before = $formBeforeElement(argumentCollection=arguments);
 86		loc.after = $formAfterElement(argumentCollection=arguments);
 87		arguments.type = "password";
 88		arguments.name = $tagName(arguments.objectName, arguments.property);
 89		loc.maxlength = $maxLength(argumentCollection=arguments);
 90		if (StructKeyExists(loc, "maxlength"))
 91			arguments.maxlength = loc.maxlength;
 92		arguments.value = $formValue(argumentCollection=arguments);
 93		loc.returnValue = loc.before & $tag(name="input", close=true, skip="objectName,property,label,labelPlacement,prepend,append,prependToLabel,appendToLabel,errorElement,errorClass,association,position", skipStartingWith="label", attributes=arguments) & loc.after;
 94	</cfscript>
 95	<cfreturn loc.returnValue>
 96</cffunction>
 97
 98<cffunction name="hiddenField" returntype="string" access="public" output="false" hint="Builds and returns a string containing a hidden field form control based on the supplied `objectName` and `property`. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
 99	examples=
100	'
101		<!--- Provide an `objectName` and `property` --->
102		<cfoutput>
103		    ##hiddenField(objectName="user", property="id")##
104		</cfoutput>
105	'
106	categories="view-helper,forms-object" chapters="form-helpers-and-showing-errors,nested-properties" functions="URLFor,startFormTag,endFormTag,submitTag,textField,radioButton,checkBox,passwordField,textArea,fileField,select,dateTimeSelect,dateSelect,timeSelect">
107	<cfargument name="objectName" type="any" required="true" hint="See documentation for @textField.">
108	<cfargument name="property" type="string" required="true" hint="See documentation for @textField.">
109	<cfargument name="association" type="string" required="false" hint="See documentation for @textfield.">
110	<cfargument name="position" type="string" required="false" hint="See documentation for @textfield.">
111	<cfscript>
112		var loc = {};
113		$args(name="hiddenField", reserved="type,name,value", args=arguments);
114		arguments.objectName = $objectName(argumentCollection=arguments);
115		arguments.type = "hidden";
116		arguments.name = $tagName(arguments.objectName, arguments.property);
117		if (!StructKeyExists(arguments, "id"))
118			arguments.id = $tagId(arguments.objectName, arguments.property);
119		arguments.value = $formValue(argumentCollection=arguments);
120		if (application.wheels.obfuscateUrls && StructKeyExists(request.wheels, "currentFormMethod") && request.wheels.currentFormMethod == "get")
121			arguments.value = obfuscateParam(arguments.value);
122		loc.returnValue = $tag(name="input", close=true, skip="objectName,property,association,position", attributes=arguments);
123	</cfscript>
124	<cfreturn loc.returnValue>
125</cffunction>
126
127<cffunction name="fileField" returntype="string" access="public" output="false" hint="Builds and returns a string containing a file field form control based on the supplied `objectName` and `property`. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
128	examples=
129	'
130		<!--- Provide a `label` and the required `objectName` and `property` --->
131		<cfoutput>
132		    ##fileField(label="Photo", objectName="photo", property="imageFile")##
133		</cfoutput>
134
135		<!--- Display fields for photos provided by the `screenshots` association and nested properties --->
136		<fieldset>
137			<legend>Screenshots</legend>
138			<cfloop from="1" to="##ArrayLen(site.screenshots)##" index="i">
139				##fileField(label="File ####i##", objectName="site", association="screenshots", position=i, property="file")##
140				##textField(label="Caption ####i##", objectName="site", association="screenshots", position=i, property="caption")##
141			</cfloop>
142		</fieldset>
143	'
144	categories="view-helper,forms-object" chapters="form-helpers-and-showing-errors,nested-properties" functions="URLFor,startFormTag,endFormTag,submitTag,textField,radioButton,checkBox,passwordField,hiddenField,textArea,select,dateTimeSelect,dateSelect,timeSelect">
145	<cfargument name="objectName" type="any" required="true" hint="See documentation for @textField.">
146	<cfargument name="property" type="string" required="true" hint="See documentation for @textField.">
147	<cfargument name="association" type="string" required="false" hint="See documentation for @textfield.">
148	<cfargument name="position" type="string" required="false" hint="See documentation for @textfield.">
149	<cfargument name="label" type="string" required="false" hint="See documentation for @textField.">
150	<cfargument name="labelPlacement" type="string" required="false" hint="See documentation for @textField.">
151	<cfargument name="prepend" type="string" required="false" hint="See documentation for @textField.">
152	<cfargument name="append" type="string" required="false" hint="See documentation for @textField.">
153	<cfargument name="prependToLabel" type="string" required="false" hint="See documentation for @textField.">
154	<cfargument name="appendToLabel" type="string" required="false" hint="See documentation for @textField.">
155	<cfargument name="errorElement" type="string" required="false" hint="See documentation for @textField.">
156	<cfargument name="errorClass" type="string" required="false" hint="See documentation for @textField.">
157	<cfscript>
158		var loc = {};
159		$args(name="fileField", reserved="type,name", args=arguments);
160		arguments.objectName = $objectName(argumentCollection=arguments);
161		if (!StructKeyExists(arguments, "id"))
162			arguments.id = $tagId(arguments.objectName, arguments.property);
163		loc.before = $formBeforeElement(argumentCollection=arguments);
164		loc.after = $formAfterElement(argumentCollection=arguments);
165		arguments.type = "file";
166		arguments.name = $tagName(arguments.objectName, arguments.property);
167		loc.returnValue = loc.before & $tag(name="input", close=true, skip="objectName,property,label,labelPlacement,prepend,append,prependToLabel,appendToLabel,errorElement,errorClass,association,position", skipStartingWith="label", attributes=arguments) & loc.after;
168	</cfscript>
169	<cfreturn loc.returnValue>
170</cffunction>
171
172<cffunction name="textArea" returntype="string" access="public" output="false" hint="Builds and returns a string containing a text area field form control based on the supplied `objectName` and `property`. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
173	examples=
174	'
175		<!--- Provide `label` and required `objectName` and `property` --->
176		<cfoutput>
177		    ##textArea(label="Overview", objectName="article", property="overview")##
178		</cfoutput>
179
180		<!--- Display fields for photos provided by the `screenshots` association and nested properties --->
181		<fieldset>
182			<legend>Screenshots</legend>
183			<cfloop from="1" to="##ArrayLen(site.screenshots)##" index="i">
184				##fileField(label="File ####i##", objectName="site", association="screenshots", position=i, property="file")##
185				##textArea(label="Caption ####i##", objectName="site", association="screenshots", position=i, property="caption")##
186			</cfloop>
187		</fieldset>
188	'
189	categories="view-helper,forms-object" chapters="form-helpers-and-showing-errors" functions="URLFor,startFormTag,endFormTag,submitTag,textField,radioButton,checkBox,passwordField,hiddenField,fileField,select,dateTimeSelect,dateSelect,timeSelect">
190	<cfargument name="objectName" type="any" required="true" hint="See documentation for @textField.">
191	<cfargument name="property" type="string" required="true" hint="See documentation for @textField.">
192	<cfargument name="association" type="string" required="false" hint="See documentation for @textfield.">
193	<cfargument name="position" type="string" required="false" hint="See documentation for @textfield.">
194	<cfargument name="label" type="string" required="false" hint="See documentation for @textField.">
195	<cfargument name="labelPlacement" type="string" required="false" hint="See documentation for @textField.">
196	<cfargument name="prepend" type="string" required="false" hint="See documentation for @textField.">
197	<cfargument name="append" type="string" required="false" hint="See documentation for @textField.">
198	<cfargument name="prependToLabel" type="string" required="false" hint="See documentation for @textField.">
199	<cfargument name="appendToLabel" type="string" required="false" hint="See documentation for @textField.">
200	<cfargument name="errorElement" type="string" required="false" hint="See documentation for @textField.">
201	<cfargument name="errorClass" type="string" required="false" hint="See documentation for @textField.">
202	<cfscript>
203		var loc = {};
204		$args(name="textArea", reserved="name", args=arguments);
205		arguments.objectName = $objectName(argumentCollection=arguments);
206		if (!StructKeyExists(arguments, "id"))
207			arguments.id = $tagId(arguments.objectName, arguments.property);
208		loc.before = $formBeforeElement(argumentCollection=arguments);
209		loc.after = $formAfterElement(argumentCollection=arguments);
210		arguments.name = $tagName(arguments.objectName, arguments.property);
211		loc.content = $formValue(argumentCollection=arguments);
212		loc.returnValue = loc.before & $element(name="textarea", skip="objectName,property,label,labelPlacement,prepend,append,prependToLabel,appendToLabel,errorElement,errorClass,association,position", skipStartingWith="label", content=loc.content, attributes=arguments) & loc.after;
213	</cfscript>
214	<cfreturn loc.returnValue>
215</cffunction>
216
217<cffunction name="radioButton" returntype="string" access="public" output="false" hint="Builds and returns a string containing a radio button form control based on the supplied `objectName` and `property`. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
218	examples=
219	'
220		<!--- Basic example view code --->
221		<cfoutput>
222			<fieldset>
223				<legend>Gender</legend>
224			    ##radioButton(objectName="user", property="gender", tagValue="m", label="Male")##<br />
225		        ##radioButton(objectName="user", property="gender", tagValue="f", label="Female")##
226			</fieldset>
227		</cfoutput>
228
229		<!--- Shows radio buttons for selecting the genders for all committee members provided by the `members` association and nested properties --->
230		<cfoutput>
231			<cfloop from="1" to="##ArrayLen(committee.members)##" index="i">
232				<div>
233					<h3>##committee.members[i].fullName##:</h3>
234					<div>
235						##radioButton(objectName="committee", association="members", position=i, property="gender", tagValue="m", label="Male")##<br />
236						##radioButton(objectName="committee", association="members", position=i, property="gender", tagValue="f", label="Female")##
237					</div>
238				</div>
239			</cfloop>
240		</cfoutput>
241	'
242	categories="view-helper,forms-object" chapters="form-helpers-and-showing-errors,nested-properties" functions="URLFor,startFormTag,endFormTag,textField,submitTag,checkBox,passwordField,hiddenField,textArea,fileField,select,dateTimeSelect,dateSelect,timeSelect">
243	<cfargument name="objectName" type="any" required="true" hint="See documentation for @textField.">
244	<cfargument name="property" type="string" required="true" hint="See documentation for @textField.">
245	<cfargument name="association" type="string" required="false" hint="See documentation for @textfield.">
246	<cfargument name="position" type="string" required="false" hint="See documentation for @textfield.">
247	<cfargument name="tagValue" type="string" required="true" hint="The value of the radio button when `selected`.">
248	<cfargument name="label" type="string" required="false" hint="See documentation for @textField.">
249	<cfargument name="labelPlacement" type="string" required="false" hint="See documentation for @textField.">
250	<cfargument name="prepend" type="string" required="false" hint="See documentation for @textField.">
251	<cfargument name="append" type="string" required="false" hint="See documentation for @textField.">
252	<cfargument name="prependToLabel" type="string" required="false" hint="See documentation for @textField.">
253	<cfargument name="appendToLabel" type="string" required="false" hint="See documentation for @textField.">
254	<cfargument name="errorElement" type="string" required="false" hint="See documentation for @textField.">
255	<cfargument name="errorClass" type="string" required="false" hint="See documentation for @textField.">
256	<cfscript>
257		var loc = {};
258		$args(name="radioButton", reserved="type,name,value,checked", args=arguments);
259		arguments.objectName = $objectName(argumentCollection=arguments);
260		loc.valueToAppend = LCase(Replace(ReReplaceNoCase(arguments.tagValue, "[^a-z0-9- ]", "", "all"), " ", "-", "all"));
261		if (!StructKeyExists(arguments, "id"))
262		{
263			arguments.id = $tagId(arguments.objectName, arguments.property);
264			if (len(loc.valueToAppend))
265				arguments.id = arguments.id & "-" & loc.valueToAppend;
266		}
267		loc.before = $formBeforeElement(argumentCollection=arguments);
268		loc.after = $formAfterElement(argumentCollection=arguments);
269		arguments.type = "radio";
270		arguments.name = $tagName(arguments.objectName, arguments.property);
271		arguments.value = arguments.tagValue;
272		if (arguments.tagValue == $formValue(argumentCollection=arguments))
273			arguments.checked = "checked";
274		loc.returnValue = loc.before & $tag(name="input", close=true, skip="objectName,property,tagValue,label,labelPlacement,prepend,append,prependToLabel,appendToLabel,errorElement,errorClass,association,position", skipStartingWith="label", attributes=arguments) & loc.after;
275	</cfscript>
276	<cfreturn loc.returnValue>
277</cffunction>
278
279<cffunction name="checkBox" returntype="string" access="public" output="false" hint="Builds and returns a string containing a check box form control based on the supplied `objectName` and `property`. In most cases, this function generates a form field that should represent a `boolean` style field in your data. Use @checkBoxTag or @hasManyCheckBox to generate check boxes for selecting multiple values. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
280	examples=
281	'
282		<!--- Basic example of a check box for a boolean field --->
283		<cfoutput>
284		    ##checkBox(objectName="photo", property="isPublic", label="Display this photo publicly.")##
285		</cfoutput>
286
287		<!--- Shows check boxes for selecting public access for all photos provided by the `photos` association and nested properties --->
288		<cfoutput>
289			<cfloop from="1" to="##ArrayLen(user.photos)##" index="i">
290				<div>
291					<h3>##user.photos[i].title##:</h3>
292					<div>
293						##checkBox(objectName="user", association="photos", position=i, property="isPublic", label="Display this photo publicly.")##
294					</div>
295				</div>
296			</cfloop>
297		</cfoutput>
298	'
299	categories="view-helper,forms-object" chapters="form-helpers-and-showing-errors,nested-properties" functions="URLFor,startFormTag,endFormTag,submitTag,textField,radioButton,passwordField,hiddenField,textArea,fileField,select,dateTimeSelect,dateSelect,timeSelect">
300	<cfargument name="objectName" type="any" required="true" hint="See documentation for @textField.">
301	<cfargument name="property" type="string" required="true" hint="See documentation for @textField.">
302	<cfargument name="association" type="string" required="false" hint="See documentation for @textfield.">
303	<cfargument name="position" type="string" required="false" hint="See documentation for @textfield.">
304	<cfargument name="checkedValue" type="string" required="false" hint="The value of the check box when it's in the `checked` state.">
305	<cfargument name="uncheckedValue" type="string" required="false" hint="The value of the check box when it's in the `unchecked` state.">
306	<cfargument name="label" type="string" required="false" hint="See documentation for @textField.">
307	<cfargument name="labelPlacement" type="string" required="false" hint="See documentation for @textField.">
308	<cfargument name="prepend" type="string" required="false" hint="See documentation for @textField.">
309	<cfargument name="append" type="string" required="false" hint="See documentation for @textField.">
310	<cfargument name="prependToLabel" type="string" required="false" hint="See documentation for @textField.">
311	<cfargument name="appendToLabel" type="string" required="false" hint="See documentation for @textField.">
312	<cfargument name="errorElement" type="string" required="false" hint="See documentation for @textField.">
313	<cfargument name="errorClass" type="string" required="false" hint="See documentation for @textField.">
314	<cfscript>
315		var loc = {};
316		$args(name="checkBox", reserved="type,name,value,checked", args=arguments);
317		arguments.objectName = $objectName(argumentCollection=arguments);
318		if (!StructKeyExists(arguments, "id"))
319			arguments.id = $tagId(arguments.objectName, arguments.property);
320		loc.before = $formBeforeElement(argumentCollection=arguments);
321		loc.after = $formAfterElement(argumentCollection=arguments);
322		arguments.type = "checkbox";
323		arguments.name = $tagName(arguments.objectName, arguments.property);
324		arguments.value = arguments.checkedValue;
325		loc.value = $formValue(argumentCollection=arguments);
326		if (loc.value == arguments.value || IsNumeric(loc.value) && loc.value == 1 || !IsNumeric(loc.value) && IsBoolean(loc.value) && loc.value)
327			arguments.checked = "checked";
328		loc.returnValue = loc.before & $tag(name="input", close=true, skip="objectName,property,checkedValue,uncheckedValue,label,labelPlacement,prepend,append,prependToLabel,appendToLabel,errorElement,errorClass,association,position", skipStartingWith="label", attributes=arguments);
329		if (Len(arguments.uncheckedValue))
330		{
331			loc.hiddenAttributes = {};
332			loc.hiddenAttributes.type = "hidden";
333			loc.hiddenAttributes.id = arguments.id & "-checkbox";
334			loc.hiddenAttributes.name = arguments.name & "($checkbox)";
335			loc.hiddenAttributes.value = arguments.uncheckedValue;
336			loc.returnValue = loc.returnValue & $tag(name="input", close=true, attributes=loc.hiddenAttributes);
337		}
338		loc.returnValue = loc.returnValue & loc.after;
339	</cfscript>
340	<cfreturn loc.returnValue>
341</cffunction>
342
343<cffunction name="select" returntype="string" access="public" output="false" hint="Builds and returns a string containing a `select` form control based on the supplied `objectName` and `property`. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
344	examples=
345	'
346		<!--- Example 1: Basic `select` field with `label` and required `objectName` and `property` arguments --->
347		<!--- - Controller code --->
348		<cfset authors = model("author").findAll()>
349
350		<!--- - View code --->
351		<cfoutput>
352		    <p>##select(objectName="book", property="authorId", options=authors)##</p>
353		</cfoutput>
354
355		<!--- Example 2: Shows `select` fields for selecting order statuses for all shipments provided by the `orders` association and nested properties --->
356		<!--- - Controller code --->
357		<cfset shipment = model("shipment").findByKey(key=params.key, where="shipments.statusId=##application.NEW_STATUS_ID##", include="order")>
358		<cfset statuses = model("status").findAll(order="name")>
359
360		<!--- - View code --->
361		<cfoutput>
362			<cfloop from="1" to="##ArrayLen(shipments.orders)##" index="i">
363				##select(label="Order ####shipments.orders[i].orderNum##", objectName="shipment", association="orders", position=i, property="statusId", options=statuses)##
364			</cfloop>
365		</cfoutput>
366	'
367	categories="view-helper,forms-object" chapters="form-helpers-and-showing-errors,nested-properties" functions="URLFor,startFormTag,endFormTag,submitTag,textField,radioButton,checkBox,passwordField,hiddenField,textArea,fileField,dateTimeSelect,dateSelect,timeSelect">
368	<cfargument name="objectName" type="any" required="true" hint="See documentation for @textField.">
369	<cfargument name="property" type="string" required="true" hint="See documentation for @textField.">
370	<cfargument name="association" type="string" required="false" hint="See documentation for @textfield.">
371	<cfargument name="position" type="string" required="false" hint="See documentation for @textfield.">
372	<cfargument name="options" type="any" required="true" hint="A collection to populate the select form control with. Can be a query recordset or an array of objects.">
373	<cfargument name="includeBlank" type="any" required="false" hint="Whether to include a blank option in the select form control. Pass `true` to include a blank line or a string that should represent what display text should appear for the empty value (for example, ""- Select One -"").">
374	<cfargument name="valueField" type="string" required="false" hint="The column or property to use for the value of each list element. Used only when a query or array of objects has been supplied in the `options` argument.">
375	<cfargument name="textField" type="string" required="false" hint="The column or property to use for the value of each list element that the end user will see. Used only when a query or array of objects has been supplied in the `options` argument.">
376	<cfargument name="label" type="string" required="false" hint="See documentation for @textField.">
377	<cfargument name="labelPlacement" type="string" required="false" hint="See documentation for @textField.">
378	<cfargument name="prepend" type="string" required="false" hint="See documentation for @textField.">
379	<cfargument name="append" type="string" required="false" hint="See documentation for @textField.">
380	<cfargument name="prependToLabel" type="string" required="false" hint="See documentation for @textField.">
381	<cfargument name="appendToLabel" type="string" required="false" hint="See documentation for @textField.">
382	<cfargument name="errorElement" type="string" required="false" hint="See documentation for @textField.">
383	<cfargument name="errorClass" type="string" required="false" hint="See documentation for @textField.">
384	<cfscript>
385		var loc = {};
386		$args(name="select", reserved="name", args=arguments);
387		arguments.objectName = $objectName(argumentCollection=arguments);
388		if (!StructKeyExists(arguments, "id"))
389			arguments.id = $tagId(arguments.objectName, arguments.property);
390		loc.before = $formBeforeElement(argumentCollection=arguments);
391		loc.after = $formAfterElement(argumentCollection=arguments);
392		arguments.name = $tagName(arguments.objectName, arguments.property);
393		if (StructKeyExists(arguments, "multiple") and IsBoolean(arguments.multiple))
394		{
395			if (arguments.multiple)
396				arguments.multiple = "multiple";
397			else
398				StructDelete(arguments, "multiple");
399		}
400		loc.content = $optionsForSelect(argumentCollection=arguments);
401		if (!IsBoolean(arguments.includeBlank) || arguments.includeBlank)
402		{
403			if (!IsBoolean(arguments.includeBlank))
404				loc.blankOptionText = arguments.includeBlank;
405			else
406				loc.blankOptionText = "";
407			loc.blankOptionAttributes = {value=""};
408			loc.content = $element(name="option", content=loc.blankOptionText, attributes=loc.blankOptionAttributes) & loc.content;
409		}
410		loc.returnValue = loc.before & $element(name="select", skip="objectName,property,options,includeBlank,valueField,textField,label,labelPlacement,prepend,append,prependToLabel,appendToLabel,errorElement,errorClass,association,position", skipStartingWith="label", content=loc.content, attributes=arguments) & loc.after;
411	</cfscript>
412	<cfreturn loc.returnValue>
413</cffunction>
414
415<cffunction name="$optionsForSelect" returntype="string" access="public" output="false">
416	<cfargument name="options" type="any" required="true">
417	<cfargument name="valueField" type="string" required="true">
418	<cfargument name="textField" type="string" required="true">
419	<cfscript>
420		var loc = {};
421
422		loc.returnValue = [];
423		loc.value = $formValue(argumentCollection=arguments);
424
425		if (IsSimpleValue(arguments.options))
426		{
427			arguments.options = ListToArray(arguments.options);
428			$optionsForSelect(argumentCollection=arguments);
429		}
430		else if (IsQuery(arguments.options))
431		{
432			arguments.options = $optionsForSelectConvertQuery(argumentCollection=arguments);
433			$optionsForSelect(argumentCollection=arguments);
434		}
435		else if (IsStruct(arguments.options))
436		{
437			arguments.options = $optionsForSelectConvertStruct(argumentCollection=arguments);
438			$optionsForSelect(argumentCollection=arguments);
439		}
440
441		loc.iEnd = ArrayLen(arguments.options);
442		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
443		{
444			loc.optionValue = "";
445			loc.optionText = "";
446
447			// see if the value in the array cell is an array, which means the programmer is using multidimensional arrays. if it is, use the first dimension for the key and the second for the value if it exists.
448			if (IsSimpleValue(arguments.options[loc.i]))
449			{
450				loc.optionValue = arguments.options[loc.i];
451				loc.optionText = humanize(arguments.options[loc.i]);
452			}
453			else if (IsArray(arguments.options[loc.i]) && ArrayLen(arguments.options[loc.i]) >= 2)
454			{
455				loc.optionValue = arguments.options[loc.i][1];
456				loc.optionText = arguments.options[loc.i][2];
457			}
458			else if (IsObject(arguments.options[loc.i]))
459			{
460				loc.object = arguments.options[loc.i];
461				if (!Len(arguments.valueField) || !Len(arguments.textField))
462				{
463					loc.propertyNames = loc.object.propertyNames();
464					loc.jEnd = ListLen(loc.propertyNames);
465					for (loc.j=1; loc.j <= loc.jEnd; loc.j++)
466					{
467						loc.propertyName = ListGetAt(loc.propertyNames, loc.j);
468						if (StructKeyExists(loc.object, loc.propertyName))
469						{
470							loc.propertyValue = loc.object[loc.propertyName];
471							if (!Len(arguments.valueField) && IsNumeric(loc.propertyValue))
472							{
473								arguments.valueField = loc.propertyName;
474							}
475							if (!Len(arguments.textField) && !IsNumeric(loc.propertyValue))
476							{
477								arguments.textField = loc.propertyName;
478							}
479						}
480					}
481
482				}
483				if (StructKeyExists(loc.object, arguments.valueField))
484				{
485					loc.optionValue = loc.object[arguments.valueField];
486				}
487				if (StructKeyExists(loc.object, arguments.textField))
488				{
489					loc.optionText = loc.object[arguments.textField];
490				}
491			}
492			else if (IsStruct(arguments.options[loc.i]))
493			{
494				loc.object = arguments.options[loc.i];
495				// if the struct only has one elment then use the key/value pair
496				if(StructCount(loc.object) eq 1)
497				{
498					loc.key = StructKeyList(loc.object);
499					loc.optionValue = loc.object[loc.key];
500					loc.optionText = LCase(loc.key);
501				}
502				else
503				{
504					if (StructKeyExists(loc.object, arguments.valueField))
505					{
506						loc.optionValue = loc.object[arguments.valueField];
507					}
508					if (StructKeyExists(loc.object, arguments.textField))
509					{
510						loc.optionText = loc.object[arguments.textField];
511					}
512				}
513			}
514			ArrayAppend(loc.returnValue, $option(objectValue=loc.value, optionValue=loc.optionValue, optionText=loc.optionText));
515		}
516	</cfscript>
517	<cfreturn ArrayToList(loc.returnValue, "")>
518</cffunction>
519
520<cffunction name="$optionsForSelectConvertStruct" returntype="array" access="public" output="false"
521			hint="converts the struct to array of arrays">
522	<cfargument name="options" type="any" required="true">
523	<cfargument name="valueField" type="string" required="true">
524	<cfargument name="textField" type="string" required="true">
525	<cfscript>
526		var loc = {};
527		loc.returnValue = [];
528		loc.sortedKeys = ListSort(StructKeyList(arguments.options), "textnocase"); // sort struct keys alphabetically
529		loc.iEnd = ListLen(loc.sortedKeys);
530		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
531		{
532			loc.key = ListGetAt(loc.sortedKeys, loc.i);
533			loc.returnValue[loc.i] = [LCase(loc.key), arguments.options[loc.key]];
534		}
535	</cfscript>
536	<cfreturn loc.returnValue>
537</cffunction>
538
539<cffunction name="$optionsForSelectConvertQuery" returntype="array" access="public" output="false"
540			hint="converts the query to array of arrays">
541	<cfargument name="options" type="any" required="true">
542	<cfargument name="valueField" type="string" required="true">
543	<cfargument name="textField" type="string" required="true">
544	<cfscript>
545		var loc = {};
546		loc.returnValue = [];
547		if (!Len(arguments.valueField) || !Len(arguments.textField))
548		{
549			// order the columns according to their ordinal position in the database table
550			loc.info = GetMetaData(arguments.options);
551			loc.iEnd = ArrayLen(loc.info);
552			loc.columns = "";
553			for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
554			{
555				loc.columns = ListAppend(loc.columns, loc.info[loc.i].name);
556			}
557			if (!Len(loc.columns))
558			{
559				arguments.valueField = "";
560				arguments.textField = "";
561			}
562			else if (ListLen(loc.columns) == 1)
563			{
564				arguments.valueField = ListGetAt(loc.columns, 1);
565				arguments.textField = ListGetAt(loc.columns, 1);
566			}
567			else
568			{
569				// take the first numeric field in the query as the value field and the first non numeric as the text field
570				loc.iEnd = arguments.options.RecordCount;
571				for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
572				{
573					loc.jEnd = ListLen(loc.columns);
574					for (loc.j=1; loc.j <= loc.jEnd; loc.j++)
575					{
576						if (!Len(arguments.valueField) && IsNumeric(arguments.options[ListGetAt(loc.columns, loc.j)][loc.i]))
577						{
578							arguments.valueField = ListGetAt(loc.columns, loc.j);
579						}
580						if (!Len(arguments.textField) && !IsNumeric(arguments.options[ListGetAt(loc.columns, loc.j)][loc.i]))
581						{
582							arguments.textField = ListGetAt(loc.columns, loc.j);
583						}
584					}
585				}
586				if (!Len(arguments.valueField) || !Len(arguments.textField))
587				{
588					// the query does not contain both a numeric and a text column so we'll just use the first and second column instead
589					arguments.valueField = ListGetAt(loc.columns, 1);
590					arguments.textField = ListGetAt(loc.columns, 2);
591				}
592			}
593		}
594
595		loc.iEnd = arguments.options.RecordCount;
596		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
597		{
598			loc.returnValue[loc.i] = [arguments.options[arguments.valueField][loc.i], arguments.options[arguments.textField][loc.i]];
599		}
600	</cfscript>
601	<cfreturn loc.returnValue>
602</cffunction>
603
604<cffunction name="$option" returntype="string" access="public" output="false">
605	<cfargument name="objectValue" type="string" required="true">
606	<cfargument name="optionValue" type="string" required="true">
607	<cfargument name="optionText" type="string" required="true">
608	<cfscript>
609		var loc = {};
610		loc.optionAttributes = {value=arguments.optionValue};
611		if (arguments.optionValue == arguments.objectValue || ListFindNoCase(arguments.objectValue, arguments.optionValue))
612			loc.optionAttributes.selected = "selected";
613		if (application.wheels.obfuscateUrls && StructKeyExists(request.wheels, "currentFormMethod") && request.wheels.currentFormMethod == "get")
614			loc.optionAttributes.value = obfuscateParam(loc.optionAttributes.value);
615		loc.returnValue = $element(name="option", content=arguments.optionText, attributes=loc.optionAttributes);
616	</cfscript>
617	<cfreturn loc.returnValue>
618</cffunction>