package com.webobjects.appserver._private; import com.webobjects.appserver.WOAssociation; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WOElement; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSDictionary; import er.extensions.foundation.ERXKeyValueCodingUtilities; import er.extensions.foundation.ERXPatcher.DynamicElementsPatches.PopUpButton; import er.extensions.foundation.ERXValueUtilities; /** * Quick hack at extending WOPopUpButton to use HTML 4 optgroups. It adds two bindings: * group and label. group is required. When this value changes, a new optgroup is created. * label is optional. This is used as the label for an option group. If label is not * bound, an empty string is used as the option group label. * * Also adds bindings to style or disable individual items. * * @binding group Object, required - keyPath to value that changes when the group of options changes * @binding label String, optional - String used as label for an option group * @binding itemClass, optional - String CSS class name for this item, browser support is inconsistent * @binding itemStyle, optional - String CSS style for this item, browser support is inconsistent * @binding itemDisabled, optional - boolean indicating if the current item should be disabled or not. * Browser support is inconsistent. Be prepared to handle the case where the user selects * a disabled option! */ public class ERXOptGroupPopupButton extends PopUpButton { protected WOAssociation group; protected WOAssociation label; protected WOAssociation itemStyle; protected WOAssociation itemClass; protected WOAssociation itemDisabled; public ERXOptGroupPopupButton(String name, NSDictionary associations, WOElement template) { super(name, associations, template); group = _associations.removeObjectForKey("group"); label = _associations.removeObjectForKey("label"); itemStyle = _associations.removeObjectForKey("itemStyle"); itemClass = _associations.removeObjectForKey("itemClass"); itemDisabled = _associations.removeObjectForKey("itemDisabled"); if (group == null) { throw new RuntimeException("Group is a required binding"); } } @Override public void appendChildrenToResponse(WOResponse response, WOContext context) { WOComponent parent = context.component(); if (_noSelectionString != null) { Object noSelectionString = _noSelectionString.valueInComponent(parent); if (noSelectionString != null) { response.appendContentString("\n<option value=\"WONoSelectionString\">"); response.appendContentHTMLString(noSelectionString.toString()); response._appendContentAsciiString("</option>"); } } Object selectionValue = null; Object selectedValue = null; if (_selection != null) { selectionValue = _selection.valueInComponent(parent); } else if (_selectedValue != null) { selectedValue = _selectedValue.valueInComponent(parent); } NSArray list = (NSArray) _list.valueInComponent(parent); Object previousGroup = null; boolean didOpenOptionGroup = false; boolean shouldEscapeHTML = _escapeHTML != null ? _escapeHTML.booleanValueInComponent(parent) : true; for(int i = 0; i < list.count(); i++) { Object listItem = list.objectAtIndex(i); _item.setValue(listItem, parent); Object currentGroup = group.valueInComponent(parent); if ( ! currentGroup.equals(previousGroup)) { previousGroup = currentGroup; if (didOpenOptionGroup) { response._appendContentAsciiString("\n</optgroup>"); } response._appendContentAsciiString("\n<optgroup label=\""); if (label != null) { if (shouldEscapeHTML) { response.appendContentHTMLString(label.valueInComponent(parent).toString()); } else { response.appendContentString(label.valueInComponent(parent).toString()); } } response._appendContentAsciiString("\">"); didOpenOptionGroup = true; } response._appendContentAsciiString("\n<option"); if (itemStyle != null) { String style = (String) itemStyle.valueInComponent(parent); if (style != null) { response._appendTagAttributeAndValue("style", style, true); } } if (itemClass != null) { String cssClass = (String) itemClass.valueInComponent(parent); if (cssClass != null) { response._appendTagAttributeAndValue("class", cssClass, true); } } String valueAsString = null; String displayStringAsString = null; WOAssociation displayStringAssociation = null; if(ERXKeyValueCodingUtilities.fieldForKey(this, "_string") != null) { displayStringAssociation = (WOAssociation) ERXKeyValueCodingUtilities.privateValueForKey(this, "_string"); } else { displayStringAssociation = (WOAssociation) ERXKeyValueCodingUtilities.privateValueForKey(this, "_displayString"); } if (displayStringAssociation != null || _value != null) { if (displayStringAssociation != null) { Object displayString = displayStringAssociation.valueInComponent(parent); if (displayString != null) { displayStringAsString = displayString.toString(); if (_value != null) { Object value = _value.valueInComponent(parent); if (value != null) { valueAsString = value.toString(); } } else { valueAsString = displayStringAsString; } } } else { Object value = _value.valueInComponent(parent); if (value != null) { valueAsString = value.toString(); displayStringAsString = valueAsString; } } } else { displayStringAsString = listItem.toString(); valueAsString = displayStringAsString; } boolean isSelectedItem = false; if (_selection != null) { isSelectedItem = selectionValue == null ? false : selectionValue.equals(listItem); } else if (_selectedValue != null) { if (_value != null) { isSelectedItem = selectedValue == null ? false : selectedValue.equals(valueAsString); } } if (isSelectedItem) { response.appendContentCharacter(' '); response._appendContentAsciiString("selected"); } if (_value != null) { response._appendTagAttributeAndValue("value", valueAsString, true); } else { String indexAsValue = WOShared.unsignedIntString(i); response._appendTagAttributeAndValue("value", indexAsValue, false); } if(itemDisabled != null) { if(ERXValueUtilities.booleanValue(itemDisabled.valueInComponent(parent))) { response._appendTagAttributeAndValue("disabled", "disabled", false); } } response.appendContentCharacter('>'); if (shouldEscapeHTML) { response.appendContentHTMLString(displayStringAsString); } else { response.appendContentString(displayStringAsString); } response._appendContentAsciiString("</option>"); } if (didOpenOptionGroup) { response._appendContentAsciiString("\n</optgroup>"); } } }