From: <tc...@us...> - 2008-10-01 23:53:36
|
Revision: 8374 http://wonder.svn.sourceforge.net/wonder/?rev=8374&view=rev Author: tcripps Date: 2008-10-01 23:53:24 +0000 (Wed, 01 Oct 2008) Log Message: ----------- More ajax updates from trunk Modified Paths: -------------- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxFlickrBatchNavigation.wo/AjaxFlickrBatchNavigation.html branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxFlickrBatchNavigation.wo/AjaxFlickrBatchNavigation.wod branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxInPlaceEditor.api branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxSubmitButton.api branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxComponent.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxDynamicElement.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxExpansion.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxInPlaceEditor.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxModalContainer.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxObserveField.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxOption.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxSubmitButton.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxTabbedPanel.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxUtils.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/wonder.js branches/Wonder_2_0_0_Branch/Wonder/Common/Frameworks/ERExtensions/Components/Nonlocalized.lproj/ERXFlickrBatchNavigation.wo/ERXFlickrBatchNavigation.html branches/Wonder_2_0_0_Branch/Wonder/Common/Frameworks/ERExtensions/Components/Nonlocalized.lproj/ERXFlickrBatchNavigation.wo/ERXFlickrBatchNavigation.wod Added Paths: ----------- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.api branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.html branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.wod branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxModalDialog.java branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.css branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.js branches/Wonder_2_0_0_Branch/Wonder/Common/Frameworks/ERExtensions/Sources/er/extensions/ERXResponseComponent.java Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxFlickrBatchNavigation.wo/AjaxFlickrBatchNavigation.html =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxFlickrBatchNavigation.wo/AjaxFlickrBatchNavigation.html 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxFlickrBatchNavigation.wo/AjaxFlickrBatchNavigation.html 2008-10-01 23:53:24 UTC (rev 8374) @@ -20,5 +20,5 @@ <webobject name = "HasNoNextPageConditional"><span class="paginatorAtEnd"><webobject name="NextLabel"/>></span></webobject> </div> </webobject> - <div class="paginatorResults">(<webobject name = "ShowPageRange"><webobject name = "FirstIndex"/>–<webobject name = "LastIndex"/> of </webobject><webobject name = "DisplayName"/>)</div> + <div class="paginatorResults">(<webobject name = "ShowPageRange"><webobject name = "FirstIndex"/>–<webobject name = "LastIndex"/> <webobject name = "OfLabel"/> </webobject><webobject name = "DisplayName"/>)</div> </div> \ No newline at end of file Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxFlickrBatchNavigation.wo/AjaxFlickrBatchNavigation.wod =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxFlickrBatchNavigation.wo/AjaxFlickrBatchNavigation.wod 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxFlickrBatchNavigation.wo/AjaxFlickrBatchNavigation.wod 2008-10-01 23:53:24 UTC (rev 8374) @@ -88,3 +88,7 @@ PreviousLabel : ERXLocalizedString { value = "ERXFlickrBatchNavigation.previous"; } + +OfLabel : ERXLocalizedString { + value = "ERXFlickrBatchNavigation.of"; +} Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxInPlaceEditor.api =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxInPlaceEditor.api 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxInPlaceEditor.api 2008-10-01 23:53:24 UTC (rev 8374) @@ -33,8 +33,9 @@ <binding name="ajaxOptions"/> <binding name="valueWhenEmpty"/> <binding defaults="Actions" name="action"/> - <validation message="'value' is a required binding"> + <validation message="'value' is a required binding"> <unbound name="value"/> </validation> - </wo> + <binding name="cancelControl"/> + </wo> </wodefinitions> \ No newline at end of file Added: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.api =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.api (rev 0) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.api 2008-10-01 23:53:24 UTC (rev 8374) @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<wodefinitions> + <wo wocomponentcontent="false" class="AjaxModalDialogComponent.java"> + <binding name = "action" defaults="Actions" /> + <binding name = "label" /> + <binding name = "title" /> + <binding name = "width" /> + <binding name = "height" /> + <binding name = "onOpen" defaults="Actions" /> + <binding name = "onClose" defaults="Actions" /> + <binding name = "id" /> + <binding name = "class" /> + <binding name = "style" /> + <binding name = "overlayClose" defaults = "Boolean" /> + <binding name = "method" /> + <binding name = "params" /> + <binding name = "loadingString" /> + <binding name = "closeString" /> + <binding name = "closeValue" /> + <binding name = "overlayOpacity" /> + <binding name = "overlayDuration" /> + <binding name = "slideDownDuration" /> + <binding name = "slideUpDuration" /> + <binding name = "resizeDuration" /> + <binding name = "inactiveFade" defaults = "Boolean" /> + <binding name = "transitions" defaults = "Boolean" /> + <binding name = "autoFocusing" defaults = "Boolean" /> + <binding name = "beforeLoad" /> + <binding name = "afterLoad" /> + <binding name = "beforeHide" /> + <binding name = "afterHide" /> + <binding name = "afterResize" /> + <binding name = "onShow" /> + <binding name = "onUpdate" /> + </wo> +</wodefinitions> \ No newline at end of file Added: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.html =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.html (rev 0) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.html 2008-10-01 23:53:24 UTC (rev 8374) @@ -0,0 +1 @@ +<webobject name = "DialogUpdater"><webobject name = "Content"/></webobject> \ No newline at end of file Property changes on: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.html ___________________________________________________________________ Added: svn:mime-type + text/html Added: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.wod =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.wod (rev 0) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxModalDialog.wo/AjaxModalDialog.wod 2008-10-01 23:53:24 UTC (rev 8374) @@ -0,0 +1,8 @@ +Content: ERXWOComponentContent { + templateName = templateName; +} + +DialogUpdater: AjaxUpdateContainer { + id = updateContainerID; + onComplete = "function() { Modalbox.resizeToContent(); }"; +} \ No newline at end of file Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxSubmitButton.api =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxSubmitButton.api 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Components/AjaxSubmitButton.api 2008-10-01 23:53:24 UTC (rev 8374) @@ -42,5 +42,7 @@ <unbound name="updateContainerID"/> </validation> <binding name="elementName"/> + <binding defaults="Boolean" name="asynchronous"/> + <binding name="accesskey"/> </wo> </wodefinitions> Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxComponent.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxComponent.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxComponent.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -104,6 +104,13 @@ addRequiredWebResources(res); } + + public void appendTagAttributeToResponse(WOResponse response, String name, Object object) { + if (object != null) { + response._appendTagAttributeAndValue(name, object.toString(), true); + } + } + /** * Override this method to append the needed scripts for this component. * @param res Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxDynamicElement.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxDynamicElement.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxDynamicElement.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -3,6 +3,7 @@ import org.apache.log4j.Logger; 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; @@ -11,6 +12,8 @@ import com.webobjects.appserver._private.WODynamicGroup; import com.webobjects.foundation.NSDictionary; +import er.extensions.ERXAjaxApplication; + public abstract class AjaxDynamicElement extends WODynamicGroup implements IAjaxElement { protected Logger log = Logger.getLogger(getClass()); private WOElement _children; @@ -26,20 +29,32 @@ return _associations; } + public boolean hasBinding(String name) { + return AjaxUtils.hasBinding(name, associations()); + } + + public WOAssociation bindingNamed(String name) { + return (WOAssociation) associations().objectForKey(name); + } + public Object valueForBinding(String name, Object defaultValue, WOComponent component) { - return AjaxUtils.valueForBinding(name, defaultValue, _associations, component); + return AjaxUtils.valueForBinding(name, defaultValue, associations(), component); } public Object valueForBinding(String name, WOComponent component) { - return AjaxUtils.valueForBinding(name, _associations, component); + return AjaxUtils.valueForBinding(name, associations(), component); } + public String stringValueForBinding(String name, WOComponent component) { + return AjaxUtils.stringValueForBinding(name, associations(), component); + } + public boolean booleanValueForBinding(String name, boolean defaultValue, WOComponent component) { - return AjaxUtils.booleanValueForBinding(name, defaultValue, _associations, component); + return AjaxUtils.booleanValueForBinding(name, defaultValue, associations(), component); } public void setValueForBinding(Object value, String name, WOComponent component) { - AjaxUtils.setValueForBinding(value, name, _associations, component); + AjaxUtils.setValueForBinding(value, name, associations(), component); } protected void addScriptResourceInHead(WOContext context, WOResponse response, String framework, String fileName) { Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxExpansion.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxExpansion.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxExpansion.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -103,11 +103,12 @@ } public void setExpanded(boolean expanded) { + Boolean e = Boolean.valueOf(expanded); if (hasBinding("expanded")) { - setValueForBinding(_expanded, "expanded"); + setValueForBinding(e, "expanded"); } else { - _expanded = Boolean.valueOf(expanded); + _expanded = e; } } Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxInPlaceEditor.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxInPlaceEditor.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxInPlaceEditor.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -57,6 +57,7 @@ ajaxOptionsArray.addObject(new AjaxOption("okText", AjaxOption.STRING)); ajaxOptionsArray.addObject(new AjaxOption("cancelLink", AjaxOption.BOOLEAN)); ajaxOptionsArray.addObject(new AjaxOption("cancelText", AjaxOption.STRING)); + ajaxOptionsArray.addObject(new AjaxOption("cancelControl", AjaxOption.STRING)); ajaxOptionsArray.addObject(new AjaxOption("savingText", AjaxOption.STRING)); ajaxOptionsArray.addObject(new AjaxOption("clickToEditText", AjaxOption.STRING)); ajaxOptionsArray.addObject(new AjaxOption("formId", AjaxOption.STRING)); Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxModalContainer.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxModalContainer.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxModalContainer.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -27,7 +27,7 @@ * @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 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 + * @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 * Added: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxModalDialog.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxModalDialog.java (rev 0) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxModalDialog.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -0,0 +1,426 @@ +package er.ajax; + +import com.webobjects.appserver.WOActionResults; +import com.webobjects.appserver.WOComponent; +import com.webobjects.appserver.WOContext; +import com.webobjects.appserver.WORequest; +import com.webobjects.appserver.WOResponse; +import com.webobjects.foundation.NSMutableArray; +import com.webobjects.foundation.NSMutableDictionary; + +import er.extensions.ERXWOContext; + + + +/** + * <p>AjaxModalDialog is a modal dialog window based on ModalBox (see below for link). It differs from AjaxModalContainer + * in that it handles submitting forms and updating the container contents. It also looks more like an OS X modal + * dialog if you consider that to be a benefit.</p> + * + * <p>The links shown to open the dialog can some from three sources: + * <ul> + * <li>the label binding</li> + * <li>an in-line ERXWOTemplate named "link". This allows for images etc to be used to open the dialog</li> + * </ul></p> + * + * <p>The contents for the modal dialog can some from three sources: + * <ul> + * <li>in-line, between the open in close tags</li> + * <li>externally (i.e. from another template), from an in-line WOComponent</li> + * <li>externally (i.e. from another template), from an action method</li> + * </ul></p> + * + * <p>To cause the dialog to be closed in an Ajax action method, use this: + * <code> + * AjaxModalDialog.close(context()); + * </code> + * </p> + * + * <p>To cause the contents of the dialog to be updated in an Ajax action method, use this: + * <code> + * AjaxModalDialog.update(context()); + * </code> + * <br /><b>NOTE: this does not work if you use the action binding. You must manage your own updating if you use this binding.</b> + * </p> + * + * @binding action returns the contents of the dialog box + * @binding label the text for the link that opens the dialog box + * @binding title Title to be displayed in the ModalBox window header, also used as title attribute of link opening dialog + * + * @binding width integer Width in pixels. Default is + * @binding height integer Height in pixels. Then set Modalbox will operate in 'fixed-height' mode. + * Otherwise the height will be calculated to fit content. + * + * @binding onOpen server side method that runs before the dialog is opened, the return value is discarded + * @binding onClose server side method that runs before the dialog is opened, the return value is discarded. + * This will be executed if the page is reloaded, but not if the user navigates elsewhere. + * + * @binding id HTML id for the link activating the modal dialog + * @binding class CSS class for the link activating the modal dialog + * @binding style CSS style for the link activating the modal dialog + * + * @binding overlayClose true | false Close modal box by clicking on overlay. Default is true. + * @binding method get | post. Method of passing variables to a server. Default is 'get'. + * @binding params {} Collection of parameters to pass on AJAX request. Should be URL-encoded. See PassingFormValues for details. + * + * @binding loadingString string The message to show during loading. Default is "Please wait. Loading...". + * @binding closeString Defines title attribute for close window link. Default is "Close window". + * @binding closeValue Defines the string for close link in the header. Default is '×' + * + * @binding overlayOpacity Overlay opacity. Must be between 0-1. Default is .65. + * @binding overlayDuration Overlay fade in/out duration in seconds. + * @binding slideDownDuration Modalbox appear slide down effect in seconds. + * @binding slideUpDuration Modalbox hiding slide up effect in seconds. + * @binding resizeDuration Modalbox resize duration in seconds. + * @binding inactiveFade true | false, Toggles Modalbox window fade on inactive state. + * @binding transitions true | false, Toggles transition effects. Transitions are enabled by default. + * @binding autoFocusing true | false, Toggles auto-focusing for form elements. Disable it for long text pages. + * + * @binding beforeLoad client side method, fires right before loading contents into the ModalBox. If the callback function returns false, content loading will skipped. This can be used for redirecting user to another MB-page for authorization purposes for example. + * @binding afterLoad client side method, fires after loading content into the ModalBox (i.e. after showing or updating existing window). + * @binding beforeHide client side method, fires right before removing elements from the DOM. Might be useful to get form values before hiding modalbox. + * @binding afterHide client side method, fires after hiding ModalBox from the screen. + * @binding afterResize client side method, fires after calling resize method. + * @binding onShow client side method, fires on first appearing of ModalBox before the contents are being loaded. + * @binding onUpdate client side method, fires on updating the content of ModalBox (on call of Modalbox.show method from active ModalBox instance). + * + * @see <a href="http://www.wildbit.com/labs/modalbox"/>Modalbox Page</a> + * @see <a href="http://code.google.com/p/modalbox/">Google Group</a> + * @author chill + * + * TODO handle href to static content + * TODO make dialog draggable + * TODO lock dialog open unless closed by content + * TODO add transitioning to other contents without closing dialog + */ +public class AjaxModalDialog extends AjaxComponent { + + /** JavaScript to execute on the client to close the modal dialog */ + public static final String Close = "Modalbox.hide();"; + private boolean isOpen; + private WOComponent actionResults; + private String id; + + + public AjaxModalDialog(WOContext context) { + super(context); + } + + + public boolean synchronizesVariablesWithBindings() { + return false; + } + + + /** + * Call this method to have a JavaScript response returned that closes the modal dialog. + * + * @param context the current WOContext + */ + public static void close(WOContext context) { + AjaxUtils.javascriptResponse(AjaxModalDialog.Close, context); + } + + + /** + * Call this method to have a JavaScript response returned that updates the contents of the modal dialog. + * Note that this does not work with the action binding. You need to manage your own AjaxUpdateContainer + * if you use an action method for the contents of the dialog. + * + * @param context the current WOContext + */ + public static void update(WOContext context) { + AjaxModalDialog thisDialog = (AjaxModalDialog) ERXWOContext.contextDictionary().objectForKey(AjaxModalDialog.class.getName()); + AjaxUtils.javascriptResponse(thisDialog.updateContainerID() + "Update();", context); + } + + + /** + * Start of R-R loop. awakes the components from action if action is bound. + * + * @see com.webobjects.appserver.WOComponent#awake() + */ + public void awake() { + super.awake(); + if (actionResults != null) { + actionResults._awakeInContext(context()); + } + } + + + /** + * Overridden to include result returned by action binding if bound. + * + * @see com.webobjects.appserver.WOComponent#takeValuesFromRequest(com.webobjects.appserver.WORequest, com.webobjects.appserver.WOContext) + */ + public void takeValuesFromRequest(WORequest request, WOContext context) { + if (actionResults != null) { + context._setCurrentComponent(actionResults); + actionResults.takeValuesFromRequest(request, context); + } else { + super.takeValuesFromRequest(request, context); + } + } + + + /** + * Overridden to include result returned by action binding if bound. + * + * @see #close(WOContext) + * @see #update(WOContext) + * @see com.webobjects.appserver.WOComponent#takeValuesFromRequest(com.webobjects.appserver.WORequest, com.webobjects.appserver.WOContext) + */ + public WOActionResults invokeAction(WORequest request, WOContext context) { + try { + // Stash this component in the context so we can access it from the static methods. + ERXWOContext.contextDictionary().setObjectForKey(this, AjaxModalDialog.class.getName()); + + WOActionResults result = null; + if ( ! (context.elementID().equals(context.senderID()) || actionResults == null)) { + context._setCurrentComponent(actionResults); + result = actionResults.invokeAction(request, context); + } else { + result = super.invokeAction(request, context); + } + return result; + + } finally { + // Remove this component from the context + ERXWOContext.contextDictionary().removeObjectForKey(AjaxModalDialog.class.getName()); + } + + } + + + /** + * Handles the open and close dialog actions. + * + * @see er.ajax.AjaxComponent#handleRequest(com.webobjects.appserver.WORequest, com.webobjects.appserver.WOContext) + * + * @return null or dialog contents + */ + public WOActionResults handleRequest(WORequest request, WOContext context) { + WOActionResults response = null; + String modalBoxAction = request.stringFormValueForKey("modalBoxAction"); + if ("open".equals(modalBoxAction) || modalBoxAction == null) { + openDialog(); + + // Register the id of this component on the page in the request so that when + // it comes time to cache the context, it knows that this area is an Ajax updating area + AjaxUtils.setPageReplacementCacheKey(context, _containerID(context)); + + // If there is an action binding, we need to cache the result of calling that so that + // the awake, takeValues, etc. messages can get passed onto it + response = AjaxUtils.createResponse(request, context); + if (hasBinding("action")) { + if (actionResults == null) { + actionResults = (WOComponent) valueForBinding("action"); + } + context._setCurrentComponent(actionResults); + actionResults.appendToResponse((WOResponse)response, context); + } else { + // This loads the content from the default ERWOTemplate (our component contents that are not + // in the "link" template. + super.appendToResponse((WOResponse)response, context); + } + } else if ("close".equals(modalBoxAction)) { + closeDialog(); + } + + return response; + } + + + /** + * This has two modes. One is to generate the link that opens the dialog. The other is to return the contents + * of the dialog (the result returned by action binding is handled in handleRequest, not here). + * + * @see er.ajax.AjaxComponent#appendToResponse(com.webobjects.appserver.WOResponse, com.webobjects.appserver.WOContext) + */ + public void appendToResponse(WOResponse response, WOContext context) { + + // If this is not an Ajax request, the page has been reloaded. Try to recover state + if ( ! context().request().requestHandlerKey().equals(AjaxRequestHandler.AjaxRequestHandlerKey)) { + closeDialog(); + } + + if (isOpen) { + if (actionResults != null) { + throw new RuntimeException("Unexpected call to appendToResponse"); + } + super.appendToResponse(response, context); + } else { + response.appendContentString("<a href=\"javascript:void(0)\""); + + WOComponent component = context.component(); + + appendTagAttributeToResponse(response, "id", id()); + appendTagAttributeToResponse(response, "class", valueForBinding("class", component)); + appendTagAttributeToResponse(response, "style", valueForBinding("style", component)); + appendTagAttributeToResponse(response, "title", valueForBinding("title", component)); + + response.appendContentString(" onclick=\"Modalbox.show('"); + response.appendContentString(AjaxUtils.ajaxComponentActionUrl(component.context())); + response.appendContentString("?modalBoxAction=open"); + response.appendContentString("', "); + AjaxOptions.appendToResponse(createModalBoxOptions(), response, context); + response.appendContentString("); return false;\" >"); + + if (hasBinding("label")) { + response.appendContentString((String)valueForBinding("label")); + } else { + // This will append the contents of the ERXWOTemplate named "link" + super.appendToResponse(response, context); + } + + response.appendContentString("</a>"); + } + } + + + /** + * End of R-R loop. Puts the components from action to sleep if action is bound. + * + * @see com.webobjects.appserver.WOComponent#sleep() + */ + public void sleep() { + super.sleep(); + if (actionResults != null) { + actionResults._sleepInContext(context()); + } + } + + + /** + * Calls the method bound to onOpen (if any), and marks the dialog state as open. + */ + public void openDialog() { + if (hasBinding("onOpen")) { + valueForBinding("onOpen"); + } + + isOpen = true; + } + + + /** + * Calls the method bound to onClose (if any), and marks the dialog state as closed. + */ + public void closeDialog() { + if (hasBinding("onClose")) { + valueForBinding("onClose"); + } + + isOpen = false; + actionResults = null; + } + + + /** + * @see er.ajax.AjaxComponent#_containerID(com.webobjects.appserver.WOContext) + * + * @return id() + */ + protected String _containerID(WOContext context) { + return id(); + } + + + /** + * @return the value bound to id or an manufactured string if id is not bound + */ + public String id() { + if (id == null) { + id = hasBinding("id") ? (String) valueForBinding("id") : ERXWOContext.safeIdentifierName(context(), true); + } + return id; + } + + + /** + * Returns the ID of the AjaxUpdateContainer that wraps the in-line contents of this dialog. + * + * @return id() + "Updater" + */ + public String updateContainerID() { + return id() + "Updater"; + } + + + /** + * Returns the template name for the ERXWOComponentContent: null to show the dialog (default) contents + * and "link" to show the link contents + * + * @return null or "link" + */ + public String templateName() { + return ! isOpen && ! hasBinding("label") ? "link" : null; + } + + + /** + * @return binding values converted into Ajax options for ModalBox + */ + protected NSMutableDictionary createModalBoxOptions() { + NSMutableArray ajaxOptionsArray = new NSMutableArray(); + ajaxOptionsArray.addObject(new AjaxOption("title", AjaxOption.STRING)); + ajaxOptionsArray.addObject(new AjaxOption("width", AjaxOption.NUMBER)); + ajaxOptionsArray.addObject(new AjaxOption("overlayClose", AjaxOption.BOOLEAN)); + ajaxOptionsArray.addObject(new AjaxOption("height", AjaxOption.NUMBER)); + ajaxOptionsArray.addObject(new AjaxOption("method", AjaxOption.STRING)); + ajaxOptionsArray.addObject(new AjaxOption("params", AjaxOption.DICTIONARY)); + ajaxOptionsArray.addObject(new AjaxOption("loadingString", AjaxOption.STRING)); + ajaxOptionsArray.addObject(new AjaxOption("closeString", AjaxOption.STRING)); + ajaxOptionsArray.addObject(new AjaxOption("closeValue", AjaxOption.STRING)); + ajaxOptionsArray.addObject(new AjaxOption("overlayOpacity", AjaxOption.NUMBER)); + ajaxOptionsArray.addObject(new AjaxOption("overlayDuration", AjaxOption.NUMBER)); + ajaxOptionsArray.addObject(new AjaxOption("slideDownDuration", AjaxOption.NUMBER)); + ajaxOptionsArray.addObject(new AjaxOption("slideUpDuration", AjaxOption.NUMBER)); + ajaxOptionsArray.addObject(new AjaxOption("resizeDuration", AjaxOption.NUMBER)); + ajaxOptionsArray.addObject(new AjaxOption("inactiveFade", AjaxOption.BOOLEAN)); + ajaxOptionsArray.addObject(new AjaxOption("transitions", AjaxOption.BOOLEAN)); + ajaxOptionsArray.addObject(new AjaxOption("autoFocusing", AjaxOption.BOOLEAN)); + + // IMPORTANT NOTICE. Each callback gets removed from options of the ModalBox after execution + ajaxOptionsArray.addObject(new AjaxOption("beforeLoad", AjaxOption.SCRIPT)); + ajaxOptionsArray.addObject(new AjaxOption("afterLoad", AjaxOption.SCRIPT)); + ajaxOptionsArray.addObject(new AjaxOption("beforeHide", AjaxOption.SCRIPT)); + ajaxOptionsArray.addObject(new AjaxOption("afterResize", AjaxOption.SCRIPT)); + ajaxOptionsArray.addObject(new AjaxOption("onShow", AjaxOption.SCRIPT)); + ajaxOptionsArray.addObject(new AjaxOption("onUpdate", AjaxOption.SCRIPT)); + + // JS to notify server when the dialog box is closed. This needs to be added to anything + // bound to afterHide + String serverUpdate = " new Ajax.Request('"+ AjaxUtils.ajaxComponentActionUrl(context()) + + "', {asynchronous:1, evalScripts:true, parameters: 'modalBoxAction=close'});"; + if(hasBinding("afterHide")) { + String afterHide = (String) valueForBinding("afterHide"); + int closingBraceIndex = afterHide.lastIndexOf('}'); + if (closingBraceIndex > -1) { + serverUpdate = afterHide.substring(0, closingBraceIndex) + serverUpdate + '}'; + } + else throw new RuntimeException("Don't know how to handle afterHide value '" + afterHide + + "', did you forget to wrap it in function() { ...}?"); + } else { + serverUpdate = "function(v) { " + serverUpdate + '}'; + } + ajaxOptionsArray.addObject(new AjaxOption("afterHide", serverUpdate, AjaxOption.SCRIPT)); + + NSMutableDictionary options = AjaxOption.createAjaxOptionsDictionary(ajaxOptionsArray, this); + + return options; + } + + + /** + * @see er.ajax.AjaxComponent#addRequiredWebResources(com.webobjects.appserver.WOResponse) + */ + protected void addRequiredWebResources(WOResponse response) { + addScriptResourceInHead(response, "prototype.js"); + addScriptResourceInHead(response, "wonder.js"); + addScriptResourceInHead(response, "effects.js"); + addScriptResourceInHead(response, "modalbox.js"); + addStylesheetResourceInHead(response, "modalbox.css"); + } + +} Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxObserveField.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxObserveField.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxObserveField.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -137,7 +137,8 @@ String nameInContext = nameInContext(wocontext, wocomponent, this); boolean shouldHandleRequest = !wocontext._wasActionInvoked() && wocontext._wasFormSubmitted() && nameInContext.equals(ERXAjaxApplication.ajaxSubmitButtonName(worequest)); if (shouldHandleRequest) { - AjaxUpdateContainer.setUpdateContainerID(worequest, (String) valueForBinding("updateContainerID", wocomponent)); + String updateContainerID = AjaxUpdateContainer.updateContainerID(this, wocomponent); + AjaxUpdateContainer.setUpdateContainerID(worequest, updateContainerID); wocontext._setActionInvoked(true); result = (WOActionResults)valueForBinding("action", wocomponent); if (result == null) { Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxOption.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxOption.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxOption.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -26,6 +26,7 @@ } private String _name; + private Object _constantValue; private AjaxOption.Type _type; public AjaxOption(String name) { @@ -35,7 +36,14 @@ public AjaxOption(String name, AjaxOption.Type type) { _name = name; _type = type; + _constantValue = null; } + + public AjaxOption(String name, Object value, AjaxOption.Type type) { + _name = name; + _type = type; + _constantValue = value; + } public String name() { return _name; @@ -54,10 +62,13 @@ } public void addToDictionary(String bindingName, WOComponent component, NSMutableDictionary dictionary) { - Object value = component.valueForBinding(bindingName); - if (value instanceof WOAssociation) { - WOAssociation association = (WOAssociation) value; - value = association.valueInComponent(component); + Object value = _constantValue; + if (value == null) { + value = component.valueForBinding(bindingName); + if (value instanceof WOAssociation) { + WOAssociation association = (WOAssociation) value; + value = association.valueInComponent(component); + } } String strValue = valueForObject(value).javascriptValue(); if (strValue != null) { @@ -70,17 +81,19 @@ } public void addToDictionary(String bindingName, WOComponent component, NSDictionary associations, NSMutableDictionary dictionary) { - if (associations != null) { - Object value = associations.objectForKey(bindingName); + Object value = _constantValue; + if (value == null && associations != null) { + value = associations.objectForKey(bindingName); if (value instanceof WOAssociation) { WOAssociation association = (WOAssociation) value; value = association.valueInComponent(component); } - String strValue = valueForObject(value).javascriptValue(); - if (strValue != null) { - dictionary.setObjectForKey(strValue, _name); - } } + + String strValue = valueForObject(value).javascriptValue(); + if (strValue != null) { + dictionary.setObjectForKey(strValue, _name); + } } public static NSMutableDictionary createAjaxOptionsDictionary(NSArray ajaxOptions, WOComponent component) { Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxSubmitButton.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxSubmitButton.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxSubmitButton.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -38,6 +38,9 @@ * @binding showUI if functionName is set, the UI defaults to hidden; showUI re-enables it * @binding formSerializer the name of the javascript function to call to serialize the form * @binding elementName the element name to use (defaults to "a") + * @binding asynchronous boolean defining if the request is sent asynchronously or synchronously, defaults to true + * @binding accesskey hot key that should trigger the button (optional) + * @binding disabled if true, the button will be disabled (defaults to false) * * // PROTOTYPE EFFECTS * @binding effect synonym of afterEffect except it always applies to updateContainerID @@ -247,7 +250,9 @@ String name = nameInContext(context, component); appendTagAttributeToResponse(response, "name", name); appendTagAttributeToResponse(response, "value", valueForBinding("value", component)); - + String accesskey = (String) valueForBinding("accesskey", component); + if(accesskey != null) + appendTagAttributeToResponse(response, "accesskey", accesskey); if (disabled) { appendTagAttributeToResponse(response, "disabled", "disabled"); } @@ -308,16 +313,20 @@ } public WOActionResults handleRequest(WORequest worequest, WOContext wocontext) { - WOResponse response = AjaxUtils.createResponse(worequest, wocontext); WOComponent wocomponent = wocontext.component(); - Object obj = valueForBinding("action", wocomponent); - String onClickServer = (String) valueForBinding("onClickServer", wocomponent); - if (onClickServer != null) { - AjaxUtils.appendScriptHeaderIfNecessary(worequest, response); - response.appendContentString(onClickServer); - AjaxUtils.appendScriptFooterIfNecessary(worequest, response); + WOActionResults result = (WOActionResults) valueForBinding("action", wocomponent); + if (result == null) { + WOResponse response = AjaxUtils.createResponse(worequest, wocontext); + String onClickServer = (String) valueForBinding("onClickServer", wocomponent); + if (onClickServer != null) { + AjaxUtils.appendScriptHeaderIfNecessary(worequest, response); + response.appendContentString(onClickServer); + AjaxUtils.appendScriptFooterIfNecessary(worequest, response); + result = response; + } } - return response; + + return result; } } Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxTabbedPanel.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxTabbedPanel.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxTabbedPanel.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -44,7 +44,7 @@ * <td>ajaxTabbedPanelPane-unselected</td> * <td>The LI representing the unselected panel(s).</td> * </tr> - * </table + * </table> * * @binding id required, String the id of the UL that wraps the tabs * @binding busyDiv optional, String the id of a div that should be shown when a Modified: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxUtils.java =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxUtils.java 2008-10-01 20:43:57 UTC (rev 8373) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/Sources/er/ajax/AjaxUtils.java 2008-10-01 23:53:24 UTC (rev 8374) @@ -70,6 +70,7 @@ } if (response == null) { response = new AjaxResponse(request, context); + response.setHeader("text/plain; charset=utf-8", "content-type"); } if (context != null) { context._setResponse(response); @@ -79,7 +80,7 @@ // efficient for foreign character sets but it is needed to support // naughty browsers such as Konqueror and Safari which do not honour the // charset set in the response - response.setHeader("text/plain; charset=utf-8", "content-type"); + response.setHeader("Connection", "keep-alive"); response.setHeader(ERXAjaxSession.DONT_STORE_PAGE, ERXAjaxSession.DONT_STORE_PAGE); return response; @@ -269,6 +270,14 @@ response.appendContentString("</script>"); } + public static boolean hasBinding(String name, NSDictionary associations) { + return associations.objectForKey(name) != null; + } + + public static WOAssociation bindingNamed(String name, NSDictionary associations) { + return (WOAssociation) associations.objectForKey(name); + } + public static Object valueForBinding(String name, Object defaultValue, NSDictionary associations, WOComponent component) { Object value = AjaxUtils.valueForBinding(name, associations, component); if (value != null) { Added: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.css =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.css (rev 0) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.css 2008-10-01 23:53:24 UTC (rev 8374) @@ -0,0 +1,95 @@ +#MB_overlay { + position: absolute; + margin: auto; + top: 0; left: 0; + width: 100%; height: 100%; + z-index: 9999; + background-color: #000!important; +} +#MB_overlay[id] { position: fixed; } + +#MB_window { + position: absolute; + top: 0; + border: 0 solid; + text-align: left; + z-index: 10000; +} +#MB_window[id] { position: fixed!important; } + +#MB_frame { + position: relative; + background-color: #EFEFEF; + height: 100%; +} + +#MB_header { + margin: 0; + padding: 0; +} + +#MB_content { + padding: 6px .75em; + overflow: auto; +} + +#MB_caption { + font: bold 100% "Lucida Grande", Arial, sans-serif; + text-shadow: #FFF 0 1px 0; + padding: .5em 2em .5em .75em; + margin: 0; + text-align: left; +} + +#MB_close { + display: block; + position: absolute; + right: 5px; top: 4px; + padding: 2px 3px; + font-weight: bold; + text-decoration: none; + font-size: 13px; +} +#MB_close:hover { + background: transparent; +} + +#MB_loading { + padding: 1.5em; + text-indent: -10000px; + background: transparent url(busyBigSpinner.gif) 50% 0 no-repeat; +} + +/* Color scheme */ +#MB_frame { + padding-bottom: 7px; + -webkit-border-radius: 7px; + -moz-border-radius: 7px; + border-radius: 7px; +} +#MB_window { + background-color: #EFEFEF; + color: #000; + -webkit-box-shadow: 0 8px 64px #000; + -moz-box-shadow: 0 0 64px #000; + box-shadow: 0 0 64px #000; + + -webkit-border-radius: 7px; + -moz-border-radius: 7px; + border-radius: 7px; +} +#MB_content { border-top: 1px solid #F9F9F9; } +#MB_header { + background-color: #DDD; + border-bottom: 1px solid #CCC; +} +#MB_caption { color: #000 } +#MB_close { color: #777 } +#MB_close:hover { color: #000 } + + +/* Alert message */ +.MB_alert { + margin: 10px 0; + text-align: center; +} \ No newline at end of file Property changes on: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.css ___________________________________________________________________ Added: svn:mime-type + text/css Added: branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.js =================================================================== --- branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.js (rev 0) +++ branches/Wonder_2_0_0_Branch/Wonder/Ajax/Ajax/WebServerResources/modalbox.js 2008-10-01 23:53:24 UTC (rev 8374) @@ -0,0 +1,572 @@ +/* +ModalBox - The pop-up window thingie with AJAX, based on prototype and script.aculo.us. + +Copyright Andrey Okonetchnikov (and...@gm...), 2006-2007 +All rights reserved. + +VERSION 1.6.0 +Last Modified: 12/13/2007 +*/ + +if (!window.Modalbox) + var Modalbox = new Object(); + +Modalbox.Methods = { + overrideAlert: false, // Override standard browser alert message with ModalBox + focusableElements: new Array, + currFocused: 0, + initialized: false, + active: true, + options: { + title: "ModalBox Window", // Title of the ModalBox window + overlayClose: true, // Close modal box by clicking on overlay + width: 500, // Default width in px + height: 90, // Default height in px + overlayOpacity: .65, // Default overlay opacity + overlayDuration: .25, // Default overlay fade in/out duration in seconds + slideDownDuration: .5, // Default Modalbox appear slide down effect in seconds + slideUpDuration: .5, // Default Modalbox hiding slide up effect in seconds + resizeDuration: .25, // Default resize duration seconds + inactiveFade: true, // Fades MB window on inactive state + transitions: true, // Toggles transition effects. Transitions are enabled by default + loadingString: "Please wait. Loading...", // Default loading string message + closeString: "Close window", // Default title attribute for close window link + closeValue: "×", // Default string for close link in the header + params: {}, + method: 'get', // Default Ajax request method + autoFocusing: true, // Toggles auto-focusing for form elements. Disable for long text pages. + aspnet: false // Should be use then using with ASP.NET costrols. Then true Modalbox window will be injected into the first form element. + }, + _options: new Object, + + setOptions: function(options) { + Object.extend(this.options, options || {}); + }, + + _init: function(options) { + // Setting up original options with default options + Object.extend(this._options, this.options); + this.setOptions(options); + + //Create the overlay + this.MBoverlay = new Element("div", { id: "MB_overlay", opacity: "0" }); + + //Create DOm for the window + this.MBwindow = new Element("div", {id: "MB_window", style: "display: none"}).update( + this.MBframe = new Element("div", {id: "MB_frame"}).update( + this.MBheader = new Element("div", {id: "MB_header"}).update( + this.MBcaption = new Element("div", {id: "MB_caption"}) + ) + ) + ); + this.MBclose = new Element("a", {id: "MB_close", title: this.options.closeString, href: "#"}).update("<span>" + this.options.closeValue + "</span>"); + this.MBheader.insert({'bottom':this.MBclose}); + + this.MBcontent = new Element("div", {id: "MB_content"}).update( + this.MBloading = new Element("div", {id: "MB_loading"}).update(this.options.loadingString) + ); + this.MBframe.insert({'bottom':this.MBcontent}); + + // Inserting into DOM. If parameter set and form element have been found will inject into it. Otherwise will inject into body as topmost element. + // Be sure to set padding and marging to null via CSS for both body and (in case of asp.net) form elements. + var injectToEl = this.options.aspnet ? $(document.body).down('form') : $(document.body); + injectToEl.insert({'top':this.MBwindow}); + injectToEl.insert({'top':this.MBoverlay}); + + // Initial scrolling position of the window. To be used for remove scrolling effect during ModalBox appearing + this.initScrollX = window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft; + this.initScrollY = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop; + + //Adding event observers + this.hideObserver = this._hide.bindAsEventListener(this); + this.kbdObserver = this._kbdHandler.bindAsEventListener(this); + this._initObservers(); + + this.initialized = true; // Mark as initialized + }, + + show: function(content, options) { + if(!this.initialized) this._init(options); // Check for is already initialized + + this.content = content; + this.setOptions(options); + + if(this.options.title) // Updating title of the MB + $(this.MBcaption).update(this.options.title); + else { // If title isn't given, the header will not displayed + $(this.MBheader).hide(); + $(this.MBcaption).hide(); + } + + if(this.MBwindow.style.display == "none") { // First modal box appearing + this._appear(); + this.event("onShow"); // Passing onShow callback + } + else { // If MB already on the screen, update it + this._update(); + this.event("onUpdate"); // Passing onUpdate callback + } + }, + + hide: function(options) { // External hide method to use from external HTML and JS + if(this.initialized) { + // Reading for options/callbacks except if event given as a pararmeter + if(options && typeof options.element != 'function') Object.extend(this.options, options); + // Passing beforeHide callback + this.event("beforeHide"); + if(this.options.transitions) + Effect.SlideUp(this.MBwindow, { duration: this.options.slideUpDuration, transition: Effect.Transitions.sinoidal, afterFinish: this._deinit.bind(this) } ); + else { + $(this.MBwindow).hide(); + this._deinit(); + } + } else throw("Modalbox is not initialized."); + }, + + _hide: function(event) { // Internal hide method to use with overlay and close link + event.stop(); // Stop event propaganation for link elements + /* Then clicked on overlay we'll check the option and in case of overlayClose == false we'll break hiding execution [Fix for #139] */ + if(event.element().id == 'MB_overlay' && !this.options.overlayClose) return false; + this.hide(); + }, + + alert: function(message){ + var html = '<div class="MB_alert"><p>' + message + '</p><input type="button" onclick="Modalbox.hide()" value="OK" /></div>'; + Modalbox.show(html, {title: 'Alert: ' + document.title, width: 300}); + }, + + _appear: function() { // First appearing of MB + if(Prototype.Browser.IE && !navigator.appVersion.match(/\b7.0\b/)) { // Preparing IE 6 for showing modalbox + window.scrollTo(0,0); + this._prepareIE("100%", "hidden"); + } + this._setWidth(); + this._setPosition(); + if(this.options.transitions) { + $(this.MBoverlay).setStyle({opacity: 0}); + new Effect.Fade(this.MBoverlay, { + from: 0, + to: this.options.overlayOpacity, + duration: this.options.overlayDuration, + afterFinish: function() { + new Effect.SlideDown(this.MBwindow, { + duration: this.options.slideDownDuration, + transition: Effect.Transitions.sinoidal, + afterFinish: function(){ + this._setPosition(); + this.loadContent(); + }.bind(this) + }); + }.bind(this) + }); + } else { + $(this.MBoverlay).setStyle({opacity: this.options.overlayOpacity}); + $(this.MBwindow).show(); + this._setPosition(); + this.loadContent(); + } + this._setWidthAndPosition = this._setWidthAndPosition.bindAsEventListener(this); + Event.observe(window, "resize", this._setWidthAndPosition); + }, + + resize: function(byWidth, byHeight, options) { // Change size of MB without loading content + var wHeight = $(this.MBwindow).getHeight(); + var wWidth = $(this.MBwindow).getWidth(); + var hHeight = $(this.MBheader).getHeight(); + var cHeight = $(this.MBcontent).getHeight(); + var newHeight = ((wHeight - hHeight + byHeight) < cHeight) ? (cHeight + hHeight - wHeight) : byHeight; + if(options) this.setOptions(options); // Passing callbacks + if(this.options.transitions) { + new Effect.ScaleBy(this.MBwindow, byWidth, newHeight, { + duration: this.options.resizeDuration, + afterFinish: function() { + this.event("_afterResize"); // Passing internal callback + this.event("afterResize"); // Passing callback + }.bind(this) + }); + } else { + this.MBwindow.setStyle({width: wWidth + byWidth + "px", height: wHeight + newHeight + "px"}); + setTimeout(function() { + this.event("_afterResize"); // Passing internal callback + this.event("afterResize"); // Passing callback + }.bind(this), 1); + + } + + }, + + resizeToContent: function(options){ + // Resizes the modalbox window to the actual content height. + // This might be useful to resize modalbox after some content modifications which were changed ccontent height. + + var byHeight = this.options.height - this.MBwindow.offsetHeight; + if(byHeight != 0) { + if(options) this.setOptions(options); // Passing callbacks + Modalbox.resize(0, byHeight); + } + }, + + resizeToInclude: function(element, options){ + + // Resizes the modalbox window to the camulative height of element. Calculations are using CSS properties for margins and border. + // This method might be useful to resize modalbox before including or updating content. + + var el = $(element); + var elHeight = el.getHeight() + parseInt(el.getStyle('margin-top')) + parseInt(el.getStyle('margin-bottom')) + parseInt(el.getStyle('border-top-width')) + parseInt(el.getStyle('border-bottom-width')); + if(elHeight > 0) { + if(options) this.setOptions(options); // Passing callbacks + Modalbox.resize(0, elHeight); + } + }, + + _update: function() { // Updating MB in case of wizards + $(this.MBcontent).update(""); + this.MBcontent.appendChild(this.MBloading); + $(this.MBloading).update(this.options.loadingString); + this.currentDims = [this.MBwindow.offsetWidth, this.MBwindow.offsetHeight]; + Modalbox.resize((this.options.width - this.currentDims[0]), (this.options.height - this.currentDims[1]), {_afterResize: this._loadAfterResize.bind(this) }); + }, + + loadContent: function () { + if(this.event("beforeLoad") != false) { // If callback passed false, skip loading of the content + if(typeof this.content == 'string') { + var htmlRegExp = new RegExp(/<\/?[^>]+>/gi); + if(htmlRegExp.test(this.content)) { // Plain HTML given as a parameter + this._insertContent(this.content.stripScripts()); + this._putContent(function(){ + this.content.extractScripts().map(function(script) { + return eval(script.replace("<!--", "").replace("// -->", "")); + }.bind(window)); + }.bind(this)); + } else // URL given as a parameter. We'll request it via Ajax + new Ajax.Request( this.content, { method: this.options.method.toLowerCase(), parameters: this.options.params, + onSuccess: function(transport) { + var response = new String(transport.responseText); + this._insertContent(transport.responseText.stripScripts()); + this._putContent(function(){ + response.extractScripts().map(function(script) { + return eval(script.replace("<!--", "").replace("// -->", "")); + }.bind(window)); + }); + }.bind(this), + onException: function(instance, exception){ + Modalbox.hide(); + throw('Modalbox Loading Error: ' + exception); + } + }); + + } else if (typeof this.content == 'object') {// HTML Object is given + this._insertContent(this.content); + this._putContent(); + } else { + Modalbox.hide(); + throw('Modalbox Parameters Error: Please specify correct URL or HTML element (plain HTML or object)'); + } + } + }, + + _insertContent: function(content){ + $(this.MBcontent).hide().update(""); + if(typeof content == 'string') { + setTimeout(function() { // Hack to disable content flickering in Firefox + this.MBcontent.update(content); + }.bind(this), 1); + } else if (typeof content == 'object') { // HTML Object is given + var _htmlObj = content.cloneNode(true); // If node already a part of DOM we'll clone it + // If clonable element has ID attribute defined, modifying it to prevent duplicates + if(content.id) content.id = "MB_" + content.id; + /* Add prefix for IDs on all elements inside the DOM node */ + $(content).select('*[id]').each(function(el){ el.id = "MB_" + el.id; }); + this.MBcontent.appendChild(_htmlObj); + this.MBcontent.down().show(); // Toggle visibility for hidden nodes + if(Prototype.Browser.IE) // Toggling back visibility for hidden selects in IE + $$("#MB_content select").invoke('setStyle', {'visibility': ''}); + } + }, + + _putContent: function(callback){ + // Prepare and resize modal box for content + if(this.options.height == this._options.height) { + setTimeout(function() { // MSIE sometimes doesn't display content correctly + Modalbox.resize(0, $(this.MBcontent).getHeight() - $(this.MBwindow).getHeight() + $(this.MBheader).getHeight(), { + afterResize: function(){ + this.MBcontent.show().makePositioned(); + this.focusableElements = this._findFocusableElements(); + this._setFocus(); // Setting focus on first 'focusable' element in content (input, select, textarea, link or button) + setTimeout(function(){ // MSIE fix + if(callback != undefined) + callback(); // Executing internal JS from loaded content + this.event("afterLoad"); // Passing callback + }.bind(this),1); + }.bind(this) + }); + }.bind(this), 1); + } else { // Height is defined. Creating a scrollable window + this._setWidth(); + this.MBcontent.setStyle({overflow: 'auto', height: $(this.MBwindow).getHeight() - $(this.MBheader).getHeight() - 13 + 'px'}); + this.MBcontent.show(); + this.focusableElements = this._findFocusableElements(); + this._setFocus(); // Setting focus on first 'focusable' element in content (input, select, textarea, link or button) + setTimeout(function(){ // MSIE fix + if(callback != undefined) + callback(); // Executing internal JS from loaded content + this.event("afterLoad"); // Passing callback + }.bind(this),1); + } + }, + + activate: function(options){ + this.setOptions(options); + this.active = true; + $(this.MBclose).observe("click", this.hideObserver); + if(this.options.overlayClose) + $(this.MBoverlay).observe("click", this.hideObserver); + $(this.MBclose).show(); + if(this.options.transitions && this.options.inactiveFade) + new Effect.Appear(this.MBwindow, {duration: this.options.slideUpDuration}); + }, + + deactivate: function(options) { + this.setOptions(options); + this.active = false; + $(this.MBclose).stopObserving("click", this.hideObserver); + if(this.options.overlayClose) + $(this.MBoverlay).stopObserving("click", this.hideObserver); + $(this.MBclose).hide(); + if(this.options.transitions && this.options.inactiveFade) + new Effect.Fade(this.MBwindow, {duration: this.options.slideUpDuration, to: .75}); + }, + + _initObservers: function(){ + $(this.MBclose).observe("click", this.hideObserver); + if(this.options.overlayClose) + $(this.MBoverlay).observe("click", this.hideObserver); + if(Prototype.Browser.IE) + Event.observe(document, "keydow... [truncated message content] |