def select = {attrs ->
def messageSource = grailsAttributes.getApplicationContext().getBean("messageSource")
def locale = RCU.getLocale(request)
def writer = out
attrs.id = attrs.id ? attrs.id : attrs.name
def from = attrs.remove('from')
def keys = attrs.remove('keys')
def optionKey = attrs.remove('optionKey')
def optionValue = attrs.remove('optionValue')
def value = attrs.remove('value')
if (value instanceof Collection && attrs.multiple == null) {
attrs.multiple = 'multiple'
}
if (value instanceof StreamCharBuffer) {
value = value.toString()
}
def valueMessagePrefix = attrs.remove('valueMessagePrefix')
def noSelection = attrs.remove('noSelection')
if (noSelection != null) {
noSelection = noSelection.entrySet().iterator().next()
}
def disabled = attrs.remove('disabled')
if (disabled && Boolean.valueOf(disabled)) {
attrs.disabled = 'disabled'
} writer << "<select name=\"${attrs.remove('name')?.encodeAsHTML()}\" "
// process remaining attributes
outputAttributes(attrs) writer << '>'
writer.println() if (noSelection) {
renderNoSelectionOptionImpl(writer, noSelection.key, noSelection.value, value)
writer.println()
} // create options from list
if (from) {
from.eachWithIndex {el, i ->
def keyValue = null
writer << '<option '
if (keys) {
keyValue = keys[i]
writeValueAndCheckIfSelected(keyValue, value, writer)
}
else if (optionKey) {
def keyValueObject = null
if (optionKey instanceof Closure) {
keyValue = optionKey(el)
}
else if (el != null && optionKey == 'id' && grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, el.getClass().name)) {
keyValue = el.ident()
keyValueObject = el
}
else {
keyValue = el[optionKey]
keyValueObject = el
}
writeValueAndCheckIfSelected(keyValue, value, writer, keyValueObject)
}
else {
keyValue = el
writeValueAndCheckIfSelected(keyValue, value, writer)
}
writer << '>'
if (optionValue) {
if (optionValue instanceof Closure) {
writer << optionValue(el).toString().encodeAsHTML()
}
else {
writer << el[optionValue].toString().encodeAsHTML()
}
}
else if (valueMessagePrefix) {
def message = messageSource.getMessage("${valueMessagePrefix}.${keyValue}", null, null, locale)
if (message != null) {
writer << message.encodeAsHTML()
}
else if (keyValue) {
writer << keyValue.encodeAsHTML()
}
else {
def s = el.toString()
if (s) writer << s.encodeAsHTML()
}
}
else {
def s = el.toString()
if (s) writer << s.encodeAsHTML()
}
writer << '</option>'
writer.println()
}
}
// close tag
writer << '</select>'
} def typeConverter = new SimpleTypeConverter()
private writeValueAndCheckIfSelected(keyValue, value, writer) {
writeValueAndCheckIfSelected(keyValue, value, writer, null)
} private writeValueAndCheckIfSelected(keyValue, value, writer, el) { boolean selected = false
def keyClass = keyValue?.getClass()
if (keyClass.isInstance(value)) {
selected = (keyValue == value)
}
else if (value instanceof Collection) {
// first try keyValue
selected = value.contains(keyValue)
if (! selected && el != null) {
selected = value.contains(el)
}
}
else if (keyClass && value) {
try {
value = typeConverter.convertIfNecessary(value, keyClass)
selected = (keyValue == value)
} catch (Exception) {
// ignore
}
}
writer << "value=\"${keyValue}\" "
if (selected) {
writer << 'selected="selected" '
}
}