package er.ajax; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WORequest; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSKeyValueCoding; import com.webobjects.foundation.NSMutableArray; import er.extensions.appserver.ERXWOContext; import er.extensions.components.ERXComponentUtilities; /** * AjaxSelectionList provides a list component that supports keyboard navigation and component renderers. Externally, * the component behaves like a form field, similar to WOPopUpButton except that it uses its component content as the * renderer for each item instead of taking a displayString. * * The javascript wrapper exposes events of the selection changing, the item being selected (via double-click or the * enter key), and an item being deleted (with the delete key). * * @author mschrag * @binding elementName (optional) the type of the list element inside the selection list (ul, ol, table) * @binding elementName (optional) the type of element for the wrapper (default to "a" to support tabbing, but presents some styling complexities in IE) * @binding list (required) the list to render * @binding item (required) bound for each item of the list * @binding selection (optional) the current selection * @binding mandatory (optional) if false, a null value will be prepended to the list. It is up to your component * content to handle the null value to show a "No Selection" value. mandatory defaults to true. Mandatory does * not imply any validation, it is the semantic equivalent of noSelectionString when compared to WOPopUpButton. * @binding id (optional) the id of the list * @binding class (optional) the css class of the list * @binding style (optional) the css style of the list * @binding name (optional) the form field name * @binding onchange (optional) the javascript to execute when the selection changes * @binding onselect (optional) the javascript to execute when the user presses enter or double-clicks * @binding ondelete (optional) the javascript to execute when backspace or delete is pressed * @binding focus (optional) if true, the selection list will be focused * @binding containerElementName the container element for this component, which is "a" */ public class AjaxSelectionList extends AjaxComponent { /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; private String _id; private String _value; private NSArray _list; public AjaxSelectionList(WOContext context) { super(context); } @Override public boolean synchronizesVariablesWithBindings() { return false; } public String containerElementName() { return (String) valueForBinding("containerElementName", "a"); } public void setItem(Object item) { if (item instanceof NSKeyValueCoding.Null) { setValueForBinding(null, "item"); } else { setValueForBinding(item, "item"); } } public Object item() { return valueForBinding("item"); } @Override public void sleep() { super.sleep(); _list = null; } public NSArray list() { NSArray list = (NSArray) valueForBinding("list"); if (_list == null || !_list.equals(list)) { _list = list; if (!ERXComponentUtilities.booleanValueForBinding(this, "mandatory", true)) { NSMutableArray optionList = _list.mutableClone(); optionList.insertObjectAtIndex(NSKeyValueCoding.NullValue, 0); _list = optionList; } } return _list; } public String elementName() { String elementName = (String) valueForBinding("elementName"); if (elementName == null) { elementName = "ul"; } return elementName; } public String containerID() { return id() + "_Container"; } public String fieldID() { return id() + "_Field"; } public String id() { if (_id == null) { _id = (String) valueForBinding("id"); if (_id == null) { _id = ERXWOContext.safeIdentifierName(context(), true); } } return _id; } public Object selection() { return valueForBinding("selection"); } public void setSelection(Object selection) { setValueForBinding(selection, "selection"); } public void setValue(String value) { _value = value; } public String value() { if (_value == null) { _value = String.valueOf(selectedIndex()); } return _value; } public int selectedIndex() { NSArray list = list(); int selectedIndex; Object selection = selection(); if (selection == null) { selectedIndex = -1; } else { selectedIndex = list.indexOfObject(selection); } return selectedIndex; } @Override public void takeValuesFromRequest(WORequest request, WOContext context) { super.takeValuesFromRequest(request, context); if (context.wasFormSubmitted()) { if (_value == null) { setSelection(null); } else { int index = Integer.parseInt(_value); NSArray list = list(); Object selection = null; if (index >= 0 && index < list.count()) { selection = list.objectAtIndex(index); } if (selection instanceof NSKeyValueCoding.Null || selection == null) { selection = null; } setSelection(selection); } } } @Override protected void addRequiredWebResources(WOResponse res) { addScriptResourceInHead(res, "prototype.js"); addScriptResourceInHead(res, "AjaxSelectionList.js"); addStylesheetResourceInHead(res, "AjaxSelectionList.css"); } @Override public WOActionResults handleRequest(WORequest request, WOContext context) { return null; } }