package er.ajax;
//http://jquery.com/demo/thickbox/
import java.net.MalformedURLException;
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.foundation.NSDictionary;
import com.webobjects.foundation.NSForwardException;
import com.webobjects.foundation.NSMutableDictionary;
import er.extensions.appserver.ERXRequest;
import er.extensions.appserver.ERXWOContext;
import er.extensions.foundation.ERXMutableURL;
import er.extensions.foundation.ERXStringUtilities;
/**
* Shows a link and wraps an area that is later presented as a modal window. Alternately, when you bind <b>action</b> then the content is used as the link.
*
* @binding label label for the link
* @binding class class for the link
* @binding style style for the link
* @binding value value for the link (??)
* @binding id id for the link
* @binding containerID container ID for non-Ajax WOComponentContent
* @binding closeLabel string for the close link
* @binding title title string for the link label and the window
* @binding href when it is bound, the content of the url will be fetched into an iframe.
* @binding directActionName the direct action to fetch
* @binding action when it is bound, the content of the url will be fetched into a div
* @binding ajax (optional) when true, the contents are only rendered during the Ajax request, using ajax=true is the preferred way to use this
* @binding open if true, the container is rendered already opened (currently only workings, i think, with ajax=true)
* @binding locked if true, the container will be "locked" and will not close unless you explicitly close it
* @binding secure (only applicable for directAtionName) if true, the generated url will be https
* @binding skin the name of the skin to use (lightbox or darkbox right now)
*
* If your content changes height and you want to autosize your iBox, you can add <script>iBox.contentChanged()</script> into your
* AjaxUpdateContainer to trigger an iBox resize.
*
* @author timo
* @author ak
*/
public class AjaxModalContainer extends AjaxDynamicElement {
public AjaxModalContainer(String name, NSDictionary associations, WOElement children) {
super(name, associations, children);
}
public boolean shouldHandle(WOContext context) {
return context.elementID().equals(context.senderID());
}
@Override
public WOActionResults invokeAction(WORequest worequest, WOContext wocontext) {
WOComponent component = wocontext.component();
if (!booleanValueForBinding("ajax", false, component)) {
WOAssociation action = associations().objectForKey("action");
if(action != null && wocontext.elementID().equals(wocontext.senderID())) {
return (WOActionResults) action.valueInComponent(component);
}
}
return super.invokeAction(worequest, wocontext);
}
@Override
public void appendToResponse(WOResponse response, WOContext context) {
WOComponent component = context.component();
String linkID = (String)valueForBinding("id", component);
if (linkID == null) {
linkID=ERXWOContext.safeIdentifierName(context, false);
}
String containerID = (String)valueForBinding("containerID", linkID + "Container", component);
response.appendContentString("<a");
String href = (String) valueForBinding("href", component);
if (href == null) {
String directActionName = stringValueForBinding("directActionName", component);
if (directActionName != null) {
NSDictionary queryDictionary = (NSDictionary)valueForBinding("queryDictionary", component);
boolean secure = booleanValueForBinding("secure", ERXRequest.isRequestSecure(context.request()), component);
if (secure) {
boolean generatingCompleteURLs = context.doesGenerateCompleteURLs();
if (!generatingCompleteURLs) {
context.generateCompleteURLs();
}
try {
href = context._directActionURL(directActionName, queryDictionary, secure, 0, false);
ERXMutableURL u = new ERXMutableURL(href);
u.addQueryParameter(String.valueOf(System.currentTimeMillis()), null);
href = u.toExternalForm();
}
catch (MalformedURLException e) {
throw new NSForwardException(e);
}
finally {
if (!generatingCompleteURLs) {
context.generateRelativeURLs();
}
}
}
else {
href = context.directActionURLForActionNamed(directActionName, queryDictionary);
}
}
}
boolean isAjax = booleanValueForBinding("ajax", false, component);
if(href == null) {
if (isAjax) {
if (valueForBinding("id", component) == null) {
throw new IllegalArgumentException("If ajax = 'true', you must also bind 'id'.");
}
href = AjaxUtils.ajaxComponentActionUrl(context);
}
else if(associations().objectForKey("action") != null) {
// don't use ajax request handler here
href = context.componentActionURL();
}
if(href == null) {
href = "#" + containerID;
}
}
appendTagAttributeToResponse(response, "href", href);
String relAttributeValue = "ibox";
Object height = valueForBinding("height", component);
Object width = valueForBinding("width", component);
Object closeLabel = valueForBinding("closeLabel", component);
if (height != null) {
relAttributeValue += "&height=" + ERXStringUtilities.urlEncode(height.toString());
}
if (width != null) {
relAttributeValue += "&width=" + ERXStringUtilities.urlEncode(width.toString());
}
if (closeLabel != null) {
relAttributeValue += "&closeLabel=" + ERXStringUtilities.urlEncode(closeLabel.toString());
}
if (booleanValueForBinding("locked", false, component)) {
relAttributeValue += "&locked=true";
}
response._appendTagAttributeAndValue("rel", relAttributeValue, false); // don't escape the ampersands
appendTagAttributeToResponse(response, "title", valueForBinding("title", component));
appendTagAttributeToResponse(response, "value", valueForBinding("value", component));
appendTagAttributeToResponse(response, "class", valueForBinding("class", component));
appendTagAttributeToResponse(response, "style", valueForBinding("style", component));
appendTagAttributeToResponse(response, "id", linkID);
response.appendContentString(">");
if(!href.startsWith("#") && !isAjax && childrenElements() != null && childrenElements().count() > 0) {
appendChildrenToResponse(response, context);
} else {
Object label = valueForBinding("label", "", component);
response.appendContentString(label.toString());
}
response.appendContentString("</a>");
if (AjaxUtils.isAjaxRequest(context.request())) {
NSMutableDictionary userInfo = ERXWOContext.contextDictionary();
if (!userInfo.containsKey("er.ajax.AjaxModalContainer.init")) {
AjaxUtils.appendScriptHeader(response);
response.appendContentString("iBox.init()");
AjaxUtils.appendScriptFooter(response);
userInfo.setObjectForKey(Boolean.TRUE, "er.ajax.AjaxModalContainer.init");
}
}
if (booleanValueForBinding("open", false, component)) {
if (AjaxUtils.isAjaxRequest(context.request())) {
// PROTOTYPE FUNCTIONS
response.appendContentString("<script>iBox.handleTag.bind($wi('" + linkID + "'))()</script>");
}
else {
// PROTOTYPE FUNCTIONS
response.appendContentString("<script>Event.observe(window, 'load', iBox.handleTag.bind($wi('" + linkID + "')))</script>");
}
}
if(href.startsWith("#")) {
response.appendContentString("<div");
appendTagAttributeToResponse(response, "id", containerID);
appendTagAttributeToResponse(response, "style", "display:none;");
response.appendContentString(">");
appendChildrenToResponse(response, context);
response.appendContentString("</div>");
}
super.appendToResponse(response, context);
}
@Override
protected void addRequiredWebResources(WOResponse response, WOContext context) {
addScriptResourceInHead(context, response, "prototype.js");
addScriptResourceInHead(context, response, "ibox/ibox.js");
String skinName = stringValueForBinding("skin", context.component());
String skinCSS;
if (skinName == null) {
skinCSS = "ibox/ibox.css";
}
else {
skinCSS = "ibox/skins/" + skinName + "/" + skinName + ".css";
}
addStylesheetResourceInHead(context, response, skinCSS);
}
@Override
protected String _containerID(WOContext context) {
String id = (String) valueForBinding("id", context.component());
return id;
}
@Override
public WOActionResults handleRequest(WORequest request, WOContext context) {
WOComponent component = context.component();
WOResponse response = null;
WOAssociation action = associations().objectForKey("action");
if(action != null) {
action.valueInComponent(component);
}
if (booleanValueForBinding("ajax", false, component) && hasChildrenElements()) {
response = AjaxUtils.createResponse(request, context);
AjaxUtils.setPageReplacementCacheKey(context, _containerID(context));
appendChildrenToResponse(response, context);
}
return response;
}
}