package er.extensions.components._private;
import com.webobjects.appserver.WOActionResults;
import com.webobjects.appserver.WOAssociation;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WOElement;
import com.webobjects.appserver.WORequest;
import com.webobjects.appserver.WOResponse;
import com.webobjects.appserver._private.WOConstantValueAssociation;
import com.webobjects.appserver._private.WODynamicElementCreationException;
import com.webobjects.appserver._private.WOInput;
import com.webobjects.foundation.NSDictionary;
import er.extensions.appserver.ERXBrowser;
import er.extensions.appserver.ERXBrowserFactory;
import er.extensions.appserver.ERXWOContext;
import er.extensions.foundation.ERXKeyValueCodingUtilities;
import er.extensions.foundation.ERXProperties;
/**
* Clone of WOSubmitButton that should emit <code><button></code> tags instead of
* <code><input></code> tags. This allows you to use HTML content and superior style
* features.
* <p>
* Unfortunately, IE is totally broken and always submits all buttons on a page,
* which makes it unusable for actions. So this component inserts some javascript to fix this.
* Of course, this means your button is only usable with scripting turned on in IE.
* <p>
* You can add this class via ERXPatcher.setClassForName(ERXSubmitButton.class, "WOSubmitButton");
* and see how this works out or use it explicitely. If you just patch it into the system,
* the value is used as the content, otherwise you can put any html you like into it.
* @author ak
*
* @property er.extensions.components._private.ERXSubmitButton.useIEFix opt-out
*/
public class ERXSubmitButton extends WOInput {
public static final String STYLE_PREFIX = "ERXSubmitButton-";
private static boolean useIEFix = ERXProperties.booleanForKeyWithDefault("er.extensions.components._private.ERXSubmitButton.useIEFix", true);
protected WOAssociation _action;
protected WOAssociation _actionClass;
protected WOAssociation _directActionName;
protected WOAssociation _shouldSubmitForm;
private static String ieFix = "<script>window.btnunload = window.onload;\n" +
"window.onload = function() {\n" +
" var btns = document.getElementsByTagName('button');\n" +
" for(var i=0;i<btns.length;i++) {\n" +
" btns[i].btnonclick = btns[i].onclick;\n" +
" btns[i].onclick = function() {\n" +
" var bs = document.getElementsByTagName('button');\n" +
" var disabledbs = new Array();\n" +
" for (var i=0;i<bs.length;i++) {\n" +
" if (bs[i] != this && ! bs[i].disabled) { \n" +
" bs[i].disabled = true;\n" +
" disabledbs[disabledbs.length] = bs[i];\n" +
" }\n" +
" }\n" +
" var savedInnerHTML = this.innerHTML;\n" +
" this.innerHTML = this.value;\n" +
" if(this.btnonclick) {\n" +
" var result = this.btnonclick();\n" +
" if ( ! result) {\n" +
" this.innerHTML = savedInnerHTML;\n" +
" for (var i=0;i<disabledbs.length;i++) {\n" +
" disabledbs[i].disabled = false;\n" +
" }\n" +
" }\n" +
" return result;\n" +
" }\n" +
" return true;\n" +
" }\n" +
" }\n" +
" if(window.btnunload) return window.btnunload();\n" +
"};</script>";
public static void appendIEButtonFixToResponse(WOContext wocontext, WOResponse woresponse) {
if(!ERXWOContext.contextDictionary().containsKey("ERXWOSubmit.ieFixed")) {
ERXBrowser browser = ERXBrowserFactory.factory().browserMatchingRequest(wocontext.request());
if (browser.isIE()) {
woresponse._appendContentAsciiString(ieFix);
}
ERXWOContext.contextDictionary().setObjectForKey(Boolean.TRUE, "ERXWOSubmit.ieFixed");
}
}
public ERXSubmitButton(String arg0, NSDictionary<String, WOAssociation> nsdictionary, WOElement arg2) {
super("button", nsdictionary, arg2);
if(_value == null)
_value = new WOConstantValueAssociation("Submit");
_shouldSubmitForm = _associations.removeObjectForKey("shouldSubmitForm");
_action = _associations.removeObjectForKey("action");
_actionClass = _associations.removeObjectForKey("actionClass");
_directActionName = _associations.removeObjectForKey("directActionName");
if(_action != null && _action.isValueConstant())
throw new WODynamicElementCreationException("<" + getClass().getName() + ">'action' is a constant.");
if(_action != null && _directActionName != null || _action != null && _actionClass != null)
throw new WODynamicElementCreationException("<" + getClass().getName() + "> Either 'action' and 'directActionName' both exist, or 'action' and 'actionClass' both exist ");
}
@Override
protected boolean isDisabledInContext(WOContext context) {
WOAssociation disabled = (WOAssociation) ERXKeyValueCodingUtilities.privateValueForKey(this, "_disabled");
return disabled != null && disabled.booleanValueInComponent(context.component());
}
@Override
protected String type() {
return "submit";
}
@Override
public String toString() {
return "<ERXSubmitButton action: " + (_action == null ? "null" : _action.toString()) + " actionClass: " + (_actionClass == null ? "null" : _actionClass.toString()) + ">";
}
public void takeValuesFromRequest(WORequest worequest, WOContext wocontext) {
// ignore
}
protected String elementName(WOContext wocontext) {
return elementName();
}
@Override
protected void _appendOpenTagToResponse(WOResponse woresponse, WOContext wocontext) {
if (useIEFix) appendIEButtonFixToResponse(wocontext, woresponse);
woresponse.appendContentCharacter('<');
woresponse._appendContentAsciiString(elementName(wocontext));
appendAttributesToResponse(woresponse, wocontext);
woresponse.appendContentCharacter('>');
}
@Override
public void appendAttributesToResponse(WOResponse woresponse, WOContext wocontext) {
appendConstantAttributesToResponse(woresponse, wocontext);
appendNonURLAttributesToResponse(woresponse, wocontext);
appendURLAttributesToResponse(woresponse, wocontext);
String css = "";
if (_class != null) {
css = (String) _class.valueInComponent(wocontext.component());
}
if(_action != null) {
css += " " + STYLE_PREFIX + _action.keyPath().replaceAll("\\W+", "");
} else if(_directActionName != null) {
css += " " + STYLE_PREFIX + _directActionName.valueInComponent(wocontext.component());
}
// log.info(css);
if(css.length() > 0) {
woresponse._appendTagAttributeAndValue("class", css, false);
}
if (_id != null) {
woresponse._appendTagAttributeAndValue("id", (String) _id.valueInComponent(wocontext.component()), false);
}
boolean shouldSubmitForm = (_shouldSubmitForm != null ? _shouldSubmitForm.booleanValueInComponent(wocontext.component()) : true);
if(isDisabledInContext(wocontext)) {
woresponse.appendContentCharacter(' ');
woresponse._appendContentAsciiString("disabled=\"disabled\"");
}
_appendTypeAttributeToResponse(woresponse, wocontext);
_appendValueAttributeToResponse(woresponse, wocontext);
_appendNameAttributeToResponse(woresponse, wocontext);
if(!shouldSubmitForm) {
String action = wocontext.componentActionURL();
woresponse._appendTagAttributeAndValue("onclick", "document.location.href='" + action + "'; return false;", false);
}
}
@Override
protected void _appendTypeAttributeToResponse(WOResponse response, WOContext context) {
if(type() != null && type().length() > 0)
response._appendTagAttributeAndValue("type", type(), false);
}
@Override
protected void _appendCloseTagToResponse(WOResponse woresponse, WOContext wocontext) {
woresponse._appendContentAsciiString("</");
woresponse._appendContentAsciiString(elementName(wocontext));
woresponse.appendContentCharacter('>');
}
@Override
public WOActionResults invokeAction(WORequest worequest, WOContext wocontext) {
Object obj = null;
WOComponent wocomponent = wocontext.component();
if(!isDisabledInContext(wocontext) && wocontext.wasFormSubmitted()) {
if(wocontext.isMultipleSubmitForm()) {
if(worequest.formValueForKey(nameInContext(wocontext, wocomponent)) != null) {
wocontext.setActionInvoked(true);
if(_action != null)
obj = _action.valueInComponent(wocomponent);
if(obj == null)
obj = wocontext.page();
}
} else {
wocontext.setActionInvoked(true);
if(_action != null)
obj = _action.valueInComponent(wocomponent);
if(obj == null)
obj = wocontext.page();
}
}
return ((WOActionResults) (obj));
}
private String _actionClassAndName(WOContext wocontext) {
String s = computeActionStringInContext(_actionClass, _directActionName, wocontext);
return s;
}
@Override
public void appendChildrenToResponse(WOResponse woresponse, WOContext wocontext) {
if(hasChildrenElements()) {
super.appendChildrenToResponse(woresponse, wocontext);
} else {
String value = (String) _value.valueInComponent(wocontext.component());
if(value == null) {
value = "Submit";
}
woresponse._appendContentAsciiString(value);
}
}
@Override
protected void _appendNameAttributeToResponse(WOResponse woresponse, WOContext wocontext) {
if(_directActionName != null || _actionClass != null)
woresponse._appendTagAttributeAndValue("name", _actionClassAndName(wocontext), false);
else
super._appendNameAttributeToResponse(woresponse, wocontext);
}
@Override
public void appendToResponse(WOResponse woresponse, WOContext wocontext) {
if(wocontext == null || woresponse == null) {
return;
}
//System.out.println(useButton + ": " + userAgent);
// useButton = !useButton;
String s = elementName();
if(s != null) {
_appendOpenTagToResponse(woresponse, wocontext);
}
appendChildrenToResponse(woresponse, wocontext);
if(s != null) {
_appendCloseTagToResponse(woresponse, wocontext);
}
if(_directActionName != null || _actionClass != null) {
woresponse._appendContentAsciiString("<input type=\"hidden\" name=\"WOSubmitAction\"");
woresponse._appendTagAttributeAndValue("value", _actionClassAndName(wocontext), false);
woresponse.appendContentString(" />");
}
}
}