package er.ajax;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WOElement;
import com.webobjects.appserver.WOResponse;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSMutableDictionary;
import er.extensions.appserver.ERXBrowser;
import er.extensions.appserver.ERXBrowserFactory;
import er.extensions.components._private.ERXWOForm;
/**
* Invisible form submit button that can be included as the first element in an Ajax submitted form so that hitting
* enter performs the action bound to this button.
*
* @binding name the HTML name of this submit button (optional)
* @binding value the HTML value of this submit button (optional)
* @binding action the action to execute when this button is pressed
* @binding id the HTML ID of this submit button
* @binding class the HTML class of this submit button
* @binding onClick arbitrary Javascript to execute when the client clicks the button
* @binding onClickBefore if the given function returns true, the onClick is executed. This is to support confirm(..) dialogs.
* @binding onServerClick if the action defined in the action binding returns null, the value of this binding will be returned as javascript from the server
* @binding onComplete JavaScript function to evaluate when the request has finished.
* @binding onSuccess javascript to execute in response to the Ajax onSuccess event
* @binding onFailure javascript to execute in response to the Ajax onFailure event
* @binding onLoading javascript to execute when loading
* @binding evalScripts evaluate scripts on the result
* @binding updateContainerID the id of the AjaxUpdateContainer to update after performing this action
* @binding formSerializer the name of the javascript function to call to serialize the form
* @binding asynchronous boolean defining if the request is sent asynchronously or synchronously, defaults to true
*
* // PROTOTYPE EFFECTS
* @binding effect synonym of afterEffect except it always applies to updateContainerID
* @binding effectDuration synonym of afterEffectDuration except it always applies to updateContainerID
* // PROTOTYPE EFFECTS
* @binding beforeEffect the Scriptaculous effect to apply onSuccess ("highlight", "slideIn", "blindDown", etc);
* @binding beforeEffectID the ID of the container to apply the "before" effect to (blank = try nearest container, then try updateContainerID)
* @binding beforeEffectDuration the duration of the effect to apply before
* // PROTOTYPE EFFECTS
* @binding afterEffect the Scriptaculous effect to apply onSuccess ("highlight", "slideIn", "blindDown", etc);
* @binding afterEffectID the ID of the container to apply the "after" effect to (blank = try nearest container, then try updateContainerID)
* @binding afterEffectDuration the duration of the effect to apply after
*
* // PROTOTYPE EFFECTS
* @binding insertion JavaScript function to evaluate when the update takes place (or effect shortcuts like "Effect.blind", or "Effect.BlindUp")
* @binding insertionDuration the duration of the before and after insertion animation (if using insertion)
* @binding beforeInsertionDuration the duration of the before insertion animation (if using insertion)
* @binding afterInsertionDuration the duration of the after insertion animation (if using insertion)
*
* @property er.ajax.formSerializer the default form serializer to use for all ajax submits
*
* @author Chuck (with heavy theft from Anjo's AjaxSubmitButton)
*/
public class AjaxDefaultSubmitButton extends AjaxSubmitButton
{
public AjaxDefaultSubmitButton(String name, NSDictionary associations, WOElement children) {
super(name, associations, children);
}
@Override
public void appendToResponse(WOResponse response, WOContext context) {
WOComponent component = context.component();
String formName = (String)valueForBinding("formName", component);
String formReference = "this.form";
if (formName != null) {
formReference = "document." + formName;
}
StringBuilder onClickBuffer = new StringBuilder();
String onClickBefore = (String)valueForBinding("onClickBefore", component);
if (onClickBefore != null) {
onClickBuffer.append("if (");
onClickBuffer.append(onClickBefore);
onClickBuffer.append(") {");
}
// PROTOTYPE EFFECTS
String updateContainerID = AjaxUpdateContainer.updateContainerID(this, component);
String beforeEffect = (String) valueForBinding("beforeEffect", component);
if (beforeEffect != null) {
onClickBuffer.append("new ");
onClickBuffer.append(AjaxUpdateLink.fullEffectName(beforeEffect));
onClickBuffer.append("('");
String beforeEffectID = (String) valueForBinding("beforeEffectID", component);
if (beforeEffectID == null) {
beforeEffectID = AjaxUpdateContainer.currentUpdateContainerID();
if (beforeEffectID == null) {
beforeEffectID = updateContainerID;
}
}
onClickBuffer.append(beforeEffectID);
onClickBuffer.append("', { ");
String beforeEffectDuration = (String) valueForBinding("beforeEffectDuration", component);
if (beforeEffectDuration != null) {
onClickBuffer.append("duration: ");
onClickBuffer.append(beforeEffectDuration);
onClickBuffer.append(", ");
}
onClickBuffer.append("queue:'end', afterFinish: function() {");
}
if (updateContainerID != null) {
onClickBuffer.append("ASB.update('" + updateContainerID + "',");
}
else {
onClickBuffer.append("ASB.request(");
}
onClickBuffer.append(formReference);
onClickBuffer.append(",null,");
NSMutableDictionary options = createAjaxOptions(component);
AjaxUpdateLink.addEffect(options, (String) valueForBinding("effect", component), updateContainerID, (String) valueForBinding("effectDuration", component));
String afterEffectID = (String) valueForBinding("afterEffectID", component);
if (afterEffectID == null) {
afterEffectID = AjaxUpdateContainer.currentUpdateContainerID();
if (afterEffectID == null) {
afterEffectID = updateContainerID;
}
}
AjaxUpdateLink.addEffect(options, (String) valueForBinding("afterEffect", component), afterEffectID, (String) valueForBinding("afterEffectDuration", component));
AjaxOptions.appendToBuffer(options, onClickBuffer, context);
onClickBuffer.append(')');
String onClick = (String) valueForBinding("onClick", component);
if (onClick != null) {
onClickBuffer.append(';');
onClickBuffer.append(onClick);
}
if (beforeEffect != null) {
onClickBuffer.append("}});");
}
if (onClickBefore != null) {
onClickBuffer.append('}');
}
onClickBuffer.append("; return false;");
response.appendContentString("<input ");
appendTagAttributeToResponse(response, "tabindex", "");
appendTagAttributeToResponse(response, "type", "submit");
String name = nameInContext(context, component);
appendTagAttributeToResponse(response, "name", name);
appendTagAttributeToResponse(response, "value", valueForBinding("value", component));
appendTagAttributeToResponse(response, "accesskey", valueForBinding("accesskey", component));
// Suppress modal box focus ring if used inside of modal dialog
if (AjaxModalDialog.isInDialog(context)) {
StringBuilder sb = new StringBuilder("MB_notFocusable ");
Object cssClass = valueForBinding("class", component);
if (cssClass != null) {
sb.append(cssClass);
}
appendTagAttributeToResponse(response, "class", sb.toString());
}
else {
appendTagAttributeToResponse(response, "class", valueForBinding("class", component));
}
appendTagAttributeToResponse(response, "style", "position:absolute;left:-10000px");
appendTagAttributeToResponse(response, "id", valueForBinding("id", component));
appendTagAttributeToResponse(response, "onclick", onClickBuffer.toString());
response.appendContentString(" />");
// fix for IE < 9 that deactivates the standard submit routine of the form and
// triggers the onClick handler of this submit element instead if the return key
// is pressed within a textfield, radiobutton, checkbox or select
ERXBrowser browser = ERXBrowserFactory.factory().browserMatchingRequest(context.request());
if (browser.isIE() && browser.majorVersion().compareTo(Integer.valueOf(9)) < 0) {
if (!hasBinding("formName")) {
formName = ERXWOForm.formName(context, "");
}
AjaxUtils.appendScriptHeader(response);
response.appendContentString("\nEvent.observe(document." + formName + ", 'keypress', function(e){");
response.appendContentString("if(e.keyCode==13){"); // return key
response.appendContentString("var shouldFire=false;var t=e.target;var tn=t.tagName.toLowerCase();");
response.appendContentString("if(tn==='select'){shouldFire=true;}");
response.appendContentString("else if(tn==='input'){var ty=t.type.toLowerCase();");
response.appendContentString("if(ty==='text' || ty==='radio' || ty==='checkbox'){shouldFire=true;}}");
response.appendContentString("if(shouldFire){$$('[name=" + name + "]')[0].fireEvent('onClick');e.returnValue=false;}");
response.appendContentString("}});");
AjaxUtils.appendScriptFooter(response);
}
}
}