ISIS-349, ISIS-350: jgrowl integration, error page for exceptions implemented.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/345f22fb Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/345f22fb Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/345f22fb Branch: refs/heads/dan/ISIS-233-ro Commit: 345f22fbfb56de82b41721fbb49d4fc0fcdc7f23 Parents: 4ad06ff Author: Dan Haywood <[email protected]> Authored: Thu Feb 21 19:30:10 2013 +0000 Committer: Dan Haywood <[email protected]> Committed: Thu Feb 21 19:30:10 2013 +0000 ---------------------------------------------------------------------- .../integration/wicket/WebRequestCycleForIsis.java | 38 +- .../viewer/wicket/model/models/ActionModel.java | 29 ++- .../ui/components/widgets/cssmenu/CssMenuItem.java | 7 +- .../viewer/wicket/ui/feedback/JGrowlBehavior.java | 101 ++++ .../isis/viewer/wicket/ui/pages/PageAbstract.css | 37 ++ .../isis/viewer/wicket/ui/pages/PageAbstract.html | 20 +- .../isis/viewer/wicket/ui/pages/PageAbstract.java | 38 ++- .../viewer/wicket/ui/pages/action/ActionPage.java | 1 + .../viewer/wicket/ui/pages/error/ErrorPage.css | 81 ++++ .../viewer/wicket/ui/pages/error/ErrorPage.html | 60 +++ .../viewer/wicket/ui/pages/error/ErrorPage.java | 71 +++ .../isis/viewer/wicket/ui/pages/jquery.jgrowl.css | 136 ++++++ .../isis/viewer/wicket/ui/pages/jquery.jgrowl.js | 352 +++++++++++++++ 13 files changed, 934 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java index a135449..debf3ff 100644 --- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java +++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java @@ -19,16 +19,19 @@ package org.apache.isis.viewer.wicket.viewer.integration.wicket; -import org.apache.log4j.Logger; -import org.apache.wicket.protocol.http.WebSession; -import org.apache.wicket.request.cycle.AbstractRequestCycleListener; -import org.apache.wicket.request.cycle.RequestCycle; - import org.apache.isis.core.commons.authentication.AuthenticationSession; import org.apache.isis.core.runtime.system.context.IsisContext; import org.apache.isis.core.runtime.system.session.IsisSession; import org.apache.isis.core.runtime.system.transaction.IsisTransaction; import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager; +import org.apache.isis.viewer.wicket.ui.pages.error.ErrorPage; +import org.apache.log4j.Logger; +import org.apache.wicket.core.request.handler.PageProvider; +import org.apache.wicket.core.request.handler.RenderPageRequestHandler; +import org.apache.wicket.protocol.http.WebSession; +import org.apache.wicket.request.IRequestHandler; +import org.apache.wicket.request.cycle.AbstractRequestCycleListener; +import org.apache.wicket.request.cycle.RequestCycle; /** * Isis-specific implementation of the Wicket's {@link WebRequestCycle}, @@ -39,18 +42,6 @@ public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends Abstract private static final Logger LOG = Logger.getLogger(WebRequestCycleForIsis.class); -// public WebRequestCycleForIsis(final WebApplication application, final WebRequest request, final Response response) { -// super(application, request, response); -// } -// -// /** -// * Convenience, downcasts. -// */ -// @Override -// public AuthenticatedWebSessionForIsis getWebSession() { -// return (AuthenticatedWebSessionForIsis) super.getWebSession(); -// } - private AuthenticatedWebSessionForIsis getWebSession() { return (AuthenticatedWebSessionForIsis) WebSession.get(); } @@ -82,7 +73,6 @@ public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends Abstract commitTransactionIfAny(); getIsisContext().closeSessionInstance(); } - //super.onEndRequest(); } private void commitTransactionIfAny() { @@ -96,6 +86,11 @@ public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends Abstract } } + @Override + public IRequestHandler onException(RequestCycle cycle, Exception ex) { + return new RenderPageRequestHandler(new PageProvider(new ErrorPage(ex))); + } + /** * Factored out so can be overridden in testing. */ @@ -103,13 +98,6 @@ public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends Abstract return IsisContext.getInstance(); } -// /** -// * Simply downcasts superclass' implementation, for convenience of callers. -// */ -// @Override -// protected WebClientInfo newClientInfo() { -// return (WebClientInfo) super.newClientInfo(); -// } protected IsisTransactionManager getTransactionManager() { return IsisContext.getTransactionManager(); http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java index 0fbe844..aed3834 100644 --- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java +++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java @@ -19,18 +19,24 @@ package org.apache.isis.viewer.wicket.model.models; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.google.common.base.Predicate; +import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import org.apache.wicket.Component; import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.isis.applib.ApplicationException; import org.apache.isis.applib.Identifier; +import org.apache.isis.core.commons.exceptions.IsisApplicationException; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking; import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller; @@ -433,12 +439,31 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> { return results; } + + // TODO: hacky!! + public static ThreadLocal<String> applicationError = new ThreadLocal<String>(); + private ObjectAdapter executeAction() { final ObjectAdapter targetAdapter = getTargetAdapter(); final ObjectAdapter[] arguments = getArgumentsAsArray(); final ObjectAction action = getActionMemento().getAction(); - final ObjectAdapter results = action.execute(targetAdapter, arguments); - return results; + try { + final ObjectAdapter results = action.execute(targetAdapter, arguments); + return results; + } catch(RuntimeException ex) { + final ApplicationException appEx = getApplicationExceptionIfAny(ex); + if(appEx != null) { + applicationError.set(appEx.getMessage()); + return null; + } + throw ex; + } + } + + private ApplicationException getApplicationExceptionIfAny(Exception ex) { + Iterable<ApplicationException> appEx = Iterables.filter(Throwables.getCausalChain(ex), ApplicationException.class); + Iterator<ApplicationException> iterator = appEx.iterator(); + return iterator.hasNext() ? iterator.next() : null; } public String getReasonInvalidIfAny() { http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java index 541c5f9..3a1e3f0 100644 --- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java @@ -48,6 +48,7 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAction; import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacet; import org.apache.isis.viewer.wicket.model.links.LinkAndLabel; import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento; +import org.apache.isis.viewer.wicket.ui.feedback.JGrowlBehavior; import org.apache.isis.viewer.wicket.ui.pages.PageAbstract; import org.apache.isis.viewer.wicket.ui.util.Components; import org.apache.isis.viewer.wicket.ui.util.CssClassAppender; @@ -229,6 +230,8 @@ public class CssMenuItem implements Serializable { final LinkAndLabel linkAndLabel = cssMenuLinkFactory.newLink(null, objectAction, PageAbstract.ID_MENU_LINK); + linkAndLabel.getLink().add(new JGrowlBehavior()); + final AbstractLink link = linkAndLabel.getLink(); final String actionLabel = linkAndLabel.getLabel(); @@ -262,8 +265,8 @@ public class CssMenuItem implements Serializable { // hide link... Components.permanentlyHide(markupContainer, ID_MENU_LINK); // ... and show label, along with disabled reason - label.add(new AttributeModifier("title", true, Model.of(this.getDisabledReason()))); - label.add(new AttributeModifier("class", true, Model.of("disabled"))); + label.add(new AttributeModifier("title", Model.of(this.getDisabledReason()))); + label.add(new AttributeModifier("class", Model.of("disabled"))); markupContainer.add(label); return label; http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/feedback/JGrowlBehavior.java ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/feedback/JGrowlBehavior.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/feedback/JGrowlBehavior.java new file mode 100644 index 0000000..24fdb98 --- /dev/null +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/feedback/JGrowlBehavior.java @@ -0,0 +1,101 @@ +package org.apache.isis.viewer.wicket.ui.feedback; + +import org.apache.commons.lang.StringUtils; +import org.apache.isis.core.runtime.system.context.IsisContext; +import org.apache.isis.viewer.wicket.model.models.ActionModel; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.feedback.FeedbackMessage; +import org.apache.wicket.markup.head.IHeaderResponse; +import org.apache.wicket.markup.head.OnDomReadyHeaderItem; + +/** + * Attach to any component to display jGrowl messages. + * + * Displays only session-level messages. If you need component-level messages, + * see http://pastebin.com/f6db2ec0e for an example. Basically, instead of + * Session.get().getFeedbackMessages(), you would call + * getComponent().getFeedbackMessage(). + * + * Requires the following be included: "jquery.js", "jquery.ui.all.js", + * "jquery.jgrowl.js", "jquery.jgrowl.css". These can be downloaded from + * http://plugins.jquery.com/files/jGrowl-1.2.0.tgz. + * + * @author jsinai Based on an example by Alex Objelean, see the above link. + */ +public class JGrowlBehavior extends AbstractDefaultAjaxBehavior { + + private static final long serialVersionUID = 1L; + + /** + * Displays an info message that is sticky. The default is non-sticky. + * Sample usage: session.getFeedbackMessages().add(new FeedbackMessage(null, + * "my message", JGrowlBehavior.INFO_STICKY)); + */ + public static final int INFO_STICKY = 250; + + @Override + protected void respond(AjaxRequestTarget target) { + final String feedbackMsg = renderFeedback(); + if (!StringUtils.isEmpty(feedbackMsg)) { + target.appendJavaScript(feedbackMsg); + } + } + + @Override + public void renderHead(Component component, IHeaderResponse response) { + super.renderHead(component, response); + final String feedbackMsg = renderFeedback(); + if (!StringUtils.isEmpty(feedbackMsg)) { + response.render(OnDomReadyHeaderItem.forScript(feedbackMsg)); + } + } + + private String renderFeedback() { + + final StringBuilder buf = new StringBuilder(); + + for (String info : IsisContext.getMessageBroker().getMessages()) { + addJGrowlCall(info, "INFO", false, buf); + } + + for (String warning : IsisContext.getMessageBroker().getWarnings()) { + addJGrowlCall(warning, "WARNING", true, buf); + } + + try { + final String error = ActionModel.applicationError.get(); + if(error!=null) { + addJGrowlCall(error, "ERROR", true, buf); + } + } finally { + ActionModel.applicationError.remove(); + } + + return buf.toString(); + } + + void addJGrowlCall(final String msg, final String cssClassSuffix, boolean sticky, final StringBuilder buf) { + buf.append("$.jGrowl(\"").append(msg).append('\"'); + buf.append(", {"); + buf.append("theme: \'jgrowl-").append(cssClassSuffix).append("\'"); + if (sticky) { + buf.append(", sticky: true"); + } + buf.append("}"); + buf.append(");"); + } + + boolean isSticky(final FeedbackMessage message) { + return message.getLevel() > FeedbackMessage.INFO; + } + + String messageFor(final FeedbackMessage message) { + return (message.getMessage() == null) ? StringUtils.EMPTY : message.getMessage().toString(); + } + + String levelFor(final FeedbackMessage message) { + return (message.getLevel() == INFO_STICKY) ? "INFO" : message.getLevelAsString(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css index e24076b..1cdadb5 100644 --- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css @@ -689,3 +689,40 @@ div.actionPanelHeaderNew .actions { +div#jGrowl { + margin-top: 55px; + margin-right: 25px; + color: white; + font-size: larger; + opacity: .90; + filter: alpha(opacity = 90); +} + +div#jGrowl div.jgrowl-ERROR { + background-color: #BF0B0B; +} +div#jGrowl div.jgrowl-WARNING { + background-color: orange; +} +div#jGrowl div.jgrowl-INFO { + background-color: #20B5C2; +} +div#jGrowl div.jgrowl-WARNING { + background-color: orange; +} +div#jGrowl div.jGrowl-closer { + background-color: #F0EFEA; + color: #46423C; + font-size: small; +} + +/* +colors +#413D37 - dark banner +#46423C - dark (writing?) +#E4E4DB - page background +#20B5C2 - accent +#BF0B0B - jgrowl error +#00477F - dark blue +#F0EFEA - bookmark background +*/ http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html index d3da481..f5bbc65 100644 --- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.html @@ -22,13 +22,14 @@ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" xml:lang="en" lang="en"> - <head> + <wicket:head> + <wicket:link> + <link href="cssreset.css" rel="stylesheet" type="text/css"/> + <link href="PageAbstract.css" rel="stylesheet" type="text/css"/> + <link href="jquery.jgrowl.css" rel="stylesheet" type="text/css"/> + </wicket:link> <title wicket:id="pageTitle"></title> - <wicket:link> - <link href="cssreset.css" rel="stylesheet" type="text/css"/> - <link href="PageAbstract.css" rel="stylesheet" type="text/css"/> - </wicket:link> - </head> + </wicket:head> <body> <div id="container" class="page"> @@ -60,7 +61,12 @@ <div class="clear"/> </div> - + + <form wicket:id="form"> + <input type="submit" value="Normal OK"/> + <input type="submit" value="Ajax OK" wicket:id="ajaxbutton"/> + </form> + <div id="footer"> <div class="links"> powered by: <a href="http://isis.apache.org">Apache Isis</a> http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java index d4d59da..5c283a3 100644 --- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java @@ -36,20 +36,26 @@ import org.apache.isis.viewer.wicket.ui.ComponentFactory; import org.apache.isis.viewer.wicket.ui.ComponentType; import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry; import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor; +import org.apache.isis.viewer.wicket.ui.feedback.JGrowlBehavior; import org.apache.isis.viewer.wicket.ui.pages.about.AboutPage; import org.apache.isis.viewer.wicket.ui.pages.login.WicketSignInPage; - import org.apache.log4j.Logger; import org.apache.wicket.RestartResponseAtInterceptPageException; +import org.apache.wicket.Session; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.feedback.FeedbackMessage; import org.apache.wicket.markup.head.CssReferenceHeaderItem; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.model.IModel; import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.request.resource.JavaScriptResourceReference; import com.google.inject.Inject; import com.google.inject.name.Named; @@ -99,6 +105,7 @@ public abstract class PageAbstract extends WebPage { @Named("applicationJs") private String applicationJs; + public PageAbstract(final PageParameters pageParameters, final ComponentType... childComponentIds) { try { addApplicationActionsComponent(); @@ -106,6 +113,7 @@ public abstract class PageAbstract extends WebPage { this.pageParameters = pageParameters; addHomePageLinkAndApplicationName(); addUserName(); + addNotificationPanel(); addLogoutLink(); addAboutLink(); add(new Label(ID_PAGE_TITLE, PageParameterNames.PAGE_TITLE.getStringFrom(pageParameters, applicationName))); @@ -118,9 +126,12 @@ public abstract class PageAbstract extends WebPage { } } + private static final JavaScriptResourceReference JQUERY_JGROWL_JS = new JavaScriptResourceReference(PageAbstract.class, "jquery.jgrowl.js"); + @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); + response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_JGROWL_JS)); if(applicationCss != null) { response.render(CssReferenceHeaderItem.forUrl(applicationCss)); } @@ -164,6 +175,31 @@ public abstract class PageAbstract extends WebPage { }); } + private void addNotificationPanel() { + Form<?> form = new Form("form") { + + @Override + protected void onSubmit() { + Session.get().error("Test error"); + Session.get().warn("Test warning"); + Session.get().info("Test info"); + Session.get().getFeedbackMessages().add(new FeedbackMessage(null, "Test sticky info", JGrowlBehavior.INFO_STICKY)); + } + }; + add(form); + + AjaxButton b = new AjaxButton("ajaxbutton", form) { + + @Override + protected void onSubmit(AjaxRequestTarget target, Form<?> form) { + target.add(form); + } + }; + form.add(b); + form.add(new JGrowlBehavior()); + + } + /** * As provided in the {@link #PageAbstract(ComponentType) constructor}. http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/action/ActionPage.java ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/action/ActionPage.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/action/ActionPage.java index 8aaddd0..bfbb8fe 100644 --- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/action/ActionPage.java +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/action/ActionPage.java @@ -27,6 +27,7 @@ import org.apache.isis.applib.annotation.ActionSemantics; import org.apache.isis.viewer.wicket.model.models.ActionModel; import org.apache.isis.viewer.wicket.model.models.ActionModel.Mode; import org.apache.isis.viewer.wicket.ui.ComponentType; +import org.apache.isis.viewer.wicket.ui.feedback.JGrowlBehavior; import org.apache.isis.viewer.wicket.ui.pages.PageAbstract; /** http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css new file mode 100644 index 0000000..1685bf1 --- /dev/null +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +.errorPage { + margin-left: 50px; + margin-right: 50px; + margin-top: 50px; +} + +.errorPage #message { + background:#FFFFFF; + border-radius:4px; + -moz-border-radius:4px; + -webkit-border-radius:4px; + padding: 15px; + display: block; + text-align:center; + font-size:1.2em; +} + + .errorPage .errorDetail { + margin-top: 30px; +} + +.errorPage .heading { + border-radius:4px; + -moz-border-radius:4px; + -webkit-border-radius:4px; + background-color:#F0EFEA; + + display:block; + font-style:normal !important; + + padding:1px 6px 1px 6px; +} + +.errorPage .heading span { + display:block; + font-style:normal !important; + padding:3px 3px 3px 3px; + text-transform: uppercase; + font-size: 0.8em; + text-transform:uppercase; + font-weight:bold; +} + +.errorPage .heading:hover { + background-color:#FFFFFF; + cursor: pointer; +} + +.errorPage h3 { + font-size: larger; +} + +.errorPage .exceptionMessage { + margin-top: 30px; +} + + .errorPage .exceptionStackTrace { + margin-top: 30px; +} + + http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html new file mode 100644 index 0000000..76adce9 --- /dev/null +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" + xml:lang="en" + lang="en"> + <wicket:head> + <wicket:link> + <link href="ErrorPage.css" rel="stylesheet" type="text/css"/> + </wicket:link> +<script type="text/javascript"> + jQuery(document).ready(function() { + jQuery(".errorPage .content").hide(); + //toggle the componenet with class msg_body + jQuery(".errorPage .heading").click(function() + { + jQuery(this).next(".errorPage .content").slideToggle(500); + }); + }); +</script> + </wicket:head> + <body> + <wicket:extend> + <div class="errorPage"> + <span id="message">Sorry, an unexpected error occurred.</span> + <div class="errorDetail"> + <div class="heading"><span>Show detail</span></div> + <div class="content"> + <div class="exceptionMessage"> + <h3>Message:</h3> + <p wicket:id="message">Message goes here</p> + </div> + <div class="exceptionStackTrace"> + <h3>Stack trace:</h3> + <p wicket:id="stackTrace">Stacktrace goes here</p> + </div> + </div> + </div> + </div> + </wicket:extend> + </body> +</html> http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java new file mode 100644 index 0000000..3147f8d --- /dev/null +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.isis.viewer.wicket.ui.pages.error; + +import org.apache.isis.viewer.wicket.ui.pages.PageAbstract; +import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +import com.google.common.base.Throwables; + +/** + * Web page representing the home page (showing a welcome message). + */ +@AuthorizeInstantiation("org.apache.isis.viewer.wicket.roles.USER") +public class ErrorPage extends PageAbstract { + + private static final long serialVersionUID = 1L; + + private static final String ID_MESSAGE = "message"; + private static final String ID_STACK_TRACE = "stackTrace"; + + public ErrorPage(Exception ex) { + super(new PageParameters()); + add(new Label(ID_MESSAGE, ex.getMessage())); + add(new Label(ID_STACK_TRACE, stackTraceAsString(ex))); + } + + private static String stackTraceAsString(Throwable ex) { + StringBuilder buf = new StringBuilder(); + appendStackTrace(ex, buf); + Throwable cause = ex.getCause(); + while(cause != null) { + buf.append("\n\nCaused by:\n"); + appendStackTrace(cause, buf); + cause = cause.getCause(); + } + return buf.toString(); + } + + private static void appendStackTrace(Throwable ex, StringBuilder buf) { + for (StackTraceElement el : ex.getStackTrace()) { + buf. append(el.getClassName()) + .append(el.getMethodName()) + .append("(") + .append(el.getFileName()) + .append(":") + .append(el.getLineNumber()) + .append(")\n") + ; + } + } + +} http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.jgrowl.css ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.jgrowl.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.jgrowl.css new file mode 100644 index 0000000..dbfde23 --- /dev/null +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.jgrowl.css @@ -0,0 +1,136 @@ + +div.jGrowl { + z-index: 9999; + color: #fff; + font-size: 12px; +} + +/** Special IE6 Style Positioning **/ +div.ie6 { + position: absolute; +} + +div.ie6.top-right { + right: auto; + bottom: auto; + left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); +} + +div.ie6.top-left { + left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); +} + +div.ie6.bottom-right { + left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); +} + +div.ie6.bottom-left { + left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); +} + +div.ie6.center { + left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); + width: 100%; +} + +/** Normal Style Positions **/ +div.jGrowl { + position: absolute; +} + +body > div.jGrowl { + position: fixed; +} + +div.jGrowl.top-left { + left: 0px; + top: 0px; +} + +div.jGrowl.top-right { + right: 0px; + top: 0px; +} + +div.jGrowl.bottom-left { + left: 0px; + bottom: 0px; +} + +div.jGrowl.bottom-right { + right: 0px; + bottom: 0px; +} + +div.jGrowl.center { + top: 0px; + width: 50%; + left: 25%; +} + +/** Cross Browser Styling **/ +div.center div.jGrowl-notification, div.center div.jGrowl-closer { + margin-left: auto; + margin-right: auto; +} + +div.jGrowl div.jGrowl-notification, div.jGrowl div.jGrowl-closer { + background-color: #000; + opacity: .85; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=85); + zoom: 1; + width: 235px; + padding: 10px; + margin-top: 5px; + margin-bottom: 5px; + font-family: Tahoma, Arial, Helvetica, sans-serif; + font-size: 1em; + text-align: left; + display: none; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +div.jGrowl div.jGrowl-notification { + min-height: 40px; +} + +div.jGrowl div.jGrowl-notification, +div.jGrowl div.jGrowl-closer { + margin: 10px; +} + +div.jGrowl div.jGrowl-notification div.jGrowl-header { + font-weight: bold; + font-size: .85em; +} + +div.jGrowl div.jGrowl-notification div.jGrowl-close { + z-index: 99; + float: right; + font-weight: bold; + font-size: 1em; + cursor: pointer; +} + +div.jGrowl div.jGrowl-closer { + padding-top: 4px; + padding-bottom: 4px; + cursor: pointer; + font-size: .9em; + font-weight: bold; + text-align: center; +} + +/** Hide jGrowl when printing **/ +@media print { + div.jGrowl { + display: none; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/isis/blob/345f22fb/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.jgrowl.js ---------------------------------------------------------------------- diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.jgrowl.js b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.jgrowl.js new file mode 100644 index 0000000..cd15d4a --- /dev/null +++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/jquery.jgrowl.js @@ -0,0 +1,352 @@ +/** + * jGrowl 1.2.10 + * + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. + * + * Written by Stan Lemon <[email protected]> + * Last updated: 2013.02.14 + * + * jGrowl is a jQuery plugin implementing unobtrusive userland notifications. These + * notifications function similarly to the Growl Framework available for + * Mac OS X (http://growl.info). + * + * To Do: + * - Move library settings to containers and allow them to be changed per container + * + * Changes in 1.2.10 + * - Fix beforeClose to be called in click event + * + * Changes in 1.2.9 + * - Fixed BC break in jQuery 2.0 beta + * + * Changes in 1.2.8 + * - Fixes for jQuery 1.9 and the MSIE6 check, note that with jQuery 2.0 support + * jGrowl intends to drop support for IE6 altogether + * + * Changes in 1.2.6 + * - Fixed js error when a notification is opening and closing at the same time + * + * Changes in 1.2.5 + * - Changed wrapper jGrowl's options usage to "o" instead of $.jGrowl.defaults + * - Added themeState option to control 'highlight' or 'error' for jQuery UI + * - Ammended some CSS to provide default positioning for nested usage. + * - Changed some CSS to be prefixed with jGrowl- to prevent namespacing issues + * - Added two new options - openDuration and closeDuration to allow + * better control of notification open and close speeds, respectively + * Patch contributed by Jesse Vincet. + * - Added afterOpen callback. Patch contributed by Russel Branca. + * + * Changes in 1.2.4 + * - Fixed IE bug with the close-all button + * - Fixed IE bug with the filter CSS attribute (special thanks to gotwic) + * - Update IE opacity CSS + * - Changed font sizes to use "em", and only set the base style + * + * Changes in 1.2.3 + * - The callbacks no longer use the container as context, instead they use the actual notification + * - The callbacks now receive the container as a parameter after the options parameter + * - beforeOpen and beforeClose now check the return value, if it's false - the notification does + * not continue. The open callback will also halt execution if it returns false. + * - Fixed bug where containers would get confused + * - Expanded the pause functionality to pause an entire container. + * + * Changes in 1.2.2 + * - Notification can now be theme rolled for jQuery UI, special thanks to Jeff Chan! + * + * Changes in 1.2.1 + * - Fixed instance where the interval would fire the close method multiple times. + * - Added CSS to hide from print media + * - Fixed issue with closer button when div { position: relative } is set + * - Fixed leaking issue with multiple containers. Special thanks to Matthew Hanlon! + * + * Changes in 1.2.0 + * - Added message pooling to limit the number of messages appearing at a given time. + * - Closing a notification is now bound to the notification object and triggered by the close button. + * + * Changes in 1.1.2 + * - Added iPhone styled example + * - Fixed possible IE7 bug when determining if the ie6 class shoudl be applied. + * - Added template for the close button, so that it's content could be customized. + * + * Changes in 1.1.1 + * - Fixed CSS styling bug for ie6 caused by a mispelling + * - Changes height restriction on default notifications to min-height + * - Added skinned examples using a variety of images + * - Added the ability to customize the content of the [close all] box + * - Added jTweet, an example of using jGrowl + Twitter + * + * Changes in 1.1.0 + * - Multiple container and instances. + * - Standard $.jGrowl() now wraps $.fn.jGrowl() by first establishing a generic jGrowl container. + * - Instance methods of a jGrowl container can be called by $.fn.jGrowl(methodName) + * - Added glue preferenced, which allows notifications to be inserted before or after nodes in the container + * - Added new log callback which is called before anything is done for the notification + * - Corner's attribute are now applied on an individual notification basis. + * + * Changes in 1.0.4 + * - Various CSS fixes so that jGrowl renders correctly in IE6. + * + * Changes in 1.0.3 + * - Fixed bug with options persisting across notifications + * - Fixed theme application bug + * - Simplified some selectors and manipulations. + * - Added beforeOpen and beforeClose callbacks + * - Reorganized some lines of code to be more readable + * - Removed unnecessary this.defaults context + * - If corners plugin is present, it's now customizable. + * - Customizable open animation. + * - Customizable close animation. + * - Customizable animation easing. + * - Added customizable positioning (top-left, top-right, bottom-left, bottom-right, center) + * + * Changes in 1.0.2 + * - All CSS styling is now external. + * - Added a theme parameter which specifies a secondary class for styling, such + * that notifications can be customized in appearance on a per message basis. + * - Notification life span is now customizable on a per message basis. + * - Added the ability to disable the global closer, enabled by default. + * - Added callbacks for when a notification is opened or closed. + * - Added callback for the global closer. + * - Customizable animation speed. + * - jGrowl now set itself up and tears itself down. + * + * Changes in 1.0.1: + * - Removed dependency on metadata plugin in favor of .data() + * - Namespaced all events + */ +(function($) { + /** Compatibility holdover for 1.9 to check IE6 **/ + var $ie6 = (function(){ + return false === $.support.boxModel && $.support.objectAll && $support.leadingWhitespace; + })(); + + /** jGrowl Wrapper - Establish a base jGrowl Container for compatibility with older releases. **/ + $.jGrowl = function( m , o ) { + // To maintain compatibility with older version that only supported one instance we'll create the base container. + if ( $('#jGrowl').size() == 0 ) + $('<div id="jGrowl"></div>').addClass( (o && o.position) ? o.position : $.jGrowl.defaults.position ).appendTo('body'); + + // Create a notification on the container. + $('#jGrowl').jGrowl(m,o); + }; + + + /** Raise jGrowl Notification on a jGrowl Container **/ + $.fn.jGrowl = function( m , o ) { + if ( $.isFunction(this.each) ) { + var args = arguments; + + return this.each(function() { + var self = this; + + /** Create a jGrowl Instance on the Container if it does not exist **/ + if ( $(this).data('jGrowl.instance') == undefined ) { + $(this).data('jGrowl.instance', $.extend( new $.fn.jGrowl(), { notifications: [], element: null, interval: null } )); + $(this).data('jGrowl.instance').startup( this ); + } + + /** Optionally call jGrowl instance methods, or just raise a normal notification **/ + if ( $.isFunction($(this).data('jGrowl.instance')[m]) ) { + $(this).data('jGrowl.instance')[m].apply( $(this).data('jGrowl.instance') , $.makeArray(args).slice(1) ); + } else { + $(this).data('jGrowl.instance').create( m , o ); + } + }); + }; + }; + + $.extend( $.fn.jGrowl.prototype , { + + /** Default JGrowl Settings **/ + defaults: { + pool: 0, + header: '', + group: '', + sticky: false, + position: 'top-right', + glue: 'after', + theme: 'default', + themeState: 'highlight', + corners: '10px', + check: 250, + life: 3000, + closeDuration: 'normal', + openDuration: 'normal', + easing: 'swing', + closer: true, + closeTemplate: '×', + closerTemplate: '<div>[ close all ]</div>', + log: function(e,m,o) {}, + beforeOpen: function(e,m,o) {}, + afterOpen: function(e,m,o) {}, + open: function(e,m,o) {}, + beforeClose: function(e,m,o) {}, + close: function(e,m,o) {}, + animateOpen: { + opacity: 'show' + }, + animateClose: { + opacity: 'hide' + } + }, + + notifications: [], + + /** jGrowl Container Node **/ + element: null, + + /** Interval Function **/ + interval: null, + + /** Create a Notification **/ + create: function( message , o ) { + var o = $.extend({}, this.defaults, o); + + /* To keep backward compatibility with 1.24 and earlier, honor 'speed' if the user has set it */ + if (typeof o.speed !== 'undefined') { + o.openDuration = o.speed; + o.closeDuration = o.speed; + } + + this.notifications.push({ message: message , options: o }); + + o.log.apply( this.element , [this.element,message,o] ); + }, + + render: function( notification ) { + var self = this; + var message = notification.message; + var o = notification.options; + + // Support for jQuery theme-states, if this is not used it displays a widget header + o.themeState = (o.themeState == '') ? '' : 'ui-state-' + o.themeState; + + var notification = $('<div/>') + .addClass('jGrowl-notification ' + o.themeState + ' ui-corner-all' + ((o.group != undefined && o.group != '') ? ' ' + o.group : '')) + .append($('<div/>').addClass('jGrowl-close').html(o.closeTemplate)) + .append($('<div/>').addClass('jGrowl-header').html(o.header)) + .append($('<div/>').addClass('jGrowl-message').html(message)) + .data("jGrowl", o).addClass(o.theme).children('div.jGrowl-close').bind("click.jGrowl", function() { + $(this).parent().trigger('jGrowl.beforeClose'); + }) + .parent(); + + + /** Notification Actions **/ + $(notification).bind("mouseover.jGrowl", function() { + $('div.jGrowl-notification', self.element).data("jGrowl.pause", true); + }).bind("mouseout.jGrowl", function() { + $('div.jGrowl-notification', self.element).data("jGrowl.pause", false); + }).bind('jGrowl.beforeOpen', function() { + if ( o.beforeOpen.apply( notification , [notification,message,o,self.element] ) != false ) { + $(this).trigger('jGrowl.open'); + } + }).bind('jGrowl.open', function() { + if ( o.open.apply( notification , [notification,message,o,self.element] ) != false ) { + if ( o.glue == 'after' ) { + $('div.jGrowl-notification:last', self.element).after(notification); + } else { + $('div.jGrowl-notification:first', self.element).before(notification); + } + + $(this).animate(o.animateOpen, o.openDuration, o.easing, function() { + // Fixes some anti-aliasing issues with IE filters. + if ($.support.opacity === false) + this.style.removeAttribute('filter'); + + if ( $(this).data("jGrowl") != null ) // Happens when a notification is closing before it's open. + $(this).data("jGrowl").created = new Date(); + + $(this).trigger('jGrowl.afterOpen'); + }); + } + }).bind('jGrowl.afterOpen', function() { + o.afterOpen.apply( notification , [notification,message,o,self.element] ); + }).bind('jGrowl.beforeClose', function() { + if ( o.beforeClose.apply( notification , [notification,message,o,self.element] ) != false ) + $(this).trigger('jGrowl.close'); + }).bind('jGrowl.close', function() { + // Pause the notification, lest during the course of animation another close event gets called. + $(this).data('jGrowl.pause', true); + $(this).animate(o.animateClose, o.closeDuration, o.easing, function() { + if ( $.isFunction(o.close) ) { + if ( o.close.apply( notification , [notification,message,o,self.element] ) !== false ) + $(this).remove(); + } else { + $(this).remove(); + } + }); + }).trigger('jGrowl.beforeOpen'); + + /** Optional Corners Plugin **/ + if ( o.corners != '' && $.fn.corner != undefined ) $(notification).corner( o.corners ); + + /** Add a Global Closer if more than one notification exists **/ + if ( $('div.jGrowl-notification:parent', self.element).size() > 1 && + $('div.jGrowl-closer', self.element).size() == 0 && this.defaults.closer != false ) { + $(this.defaults.closerTemplate).addClass('jGrowl-closer ' + this.defaults.themeState + ' ui-corner-all').addClass(this.defaults.theme) + .appendTo(self.element).animate(this.defaults.animateOpen, this.defaults.speed, this.defaults.easing) + .bind("click.jGrowl", function() { + $(this).siblings().trigger("jGrowl.beforeClose"); + + if ( $.isFunction( self.defaults.closer ) ) { + self.defaults.closer.apply( $(this).parent()[0] , [$(this).parent()[0]] ); + } + }); + }; + }, + + /** Update the jGrowl Container, removing old jGrowl notifications **/ + update: function() { + $(this.element).find('div.jGrowl-notification:parent').each( function() { + if ( $(this).data("jGrowl") != undefined && $(this).data("jGrowl").created != undefined && + ($(this).data("jGrowl").created.getTime() + parseInt($(this).data("jGrowl").life)) < (new Date()).getTime() && + $(this).data("jGrowl").sticky != true && + ($(this).data("jGrowl.pause") == undefined || $(this).data("jGrowl.pause") != true) ) { + + // Pause the notification, lest during the course of animation another close event gets called. + $(this).trigger('jGrowl.beforeClose'); + } + }); + + if ( this.notifications.length > 0 && + (this.defaults.pool == 0 || $(this.element).find('div.jGrowl-notification:parent').size() < this.defaults.pool) ) + this.render( this.notifications.shift() ); + + if ( $(this.element).find('div.jGrowl-notification:parent').size() < 2 ) { + $(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose, this.defaults.speed, this.defaults.easing, function() { + $(this).remove(); + }); + } + }, + + /** Setup the jGrowl Notification Container **/ + startup: function(e) { + this.element = $(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>'); + this.interval = setInterval( function() { + $(e).data('jGrowl.instance').update(); + }, parseInt(this.defaults.check)); + + if ($ie6) { + $(this.element).addClass('ie6'); + } + }, + + /** Shutdown jGrowl, removing it and clearing the interval **/ + shutdown: function() { + $(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove(); + clearInterval( this.interval ); + }, + + close: function() { + $(this.element).find('div.jGrowl-notification').each(function(){ + $(this).trigger('jGrowl.beforeClose'); + }); + } + }); + + /** Reference the Defaults Object for compatibility with older versions of jGrowl **/ + $.jGrowl.defaults = $.fn.jGrowl.prototype.defaults; + +})(jQuery);
