    001    // Copyright 2011, 2012 The Apache Software Foundation
    002    //
    003    // Licensed under the Apache License, Version 2.0 (the "License");
    004    // you may not use this file except in compliance with the License.
    005    // You may obtain a copy of the License at
    006    //
    007    //     http://www.apache.org/licenses/LICENSE-2.0
    008    //
    009    // Unless required by applicable law or agreed to in writing, software
    010    // distributed under the License is distributed on an "AS IS" BASIS,
    011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012    // See the License for the specific language governing permissions and
    013    // limitations under the License.
    014
    015    package org.apache.tapestry5.corelib.components;
    016
    017    import org.apache.tapestry5.BindingConstants;
    018    import org.apache.tapestry5.ClientElement;
    019    import org.apache.tapestry5.ComponentResources;
    020    import org.apache.tapestry5.MarkupWriter;
    021    import org.apache.tapestry5.alerts.Alert;
    022    import org.apache.tapestry5.alerts.AlertStorage;
    023    import org.apache.tapestry5.annotations.*;
    024    import org.apache.tapestry5.ioc.annotations.Inject;
    025    import org.apache.tapestry5.json.JSONObject;
    026    import org.apache.tapestry5.services.javascript.InitializationPriority;
    027    import org.apache.tapestry5.services.javascript.JavaScriptSupport;
    028
    029    /**
    030     * Renders out an empty {@code <div>} element and provides JavaScript initialization to make the element
    031     * the container for alerts. After rendering markup (and initialization JavaScript), it
    032     * {@linkplain org.apache.tapestry5.alerts.AlertStorage#dismissNonPersistent() removes all non-persistent alerts}.
    033     *
    034     * @tapestrydoc
    035     * @since 5.3
    036     */
    037    @SupportsInformalParameters
    038    public class Alerts implements ClientElement
    039    {
    040
    041        @Parameter(value="message:dismiss-label", defaultPrefix=BindingConstants.LITERAL)
    042        private String dismissText;
    043
    044        @Inject
    045        private ComponentResources resources;
    046
    047        @Environmental
    048        private JavaScriptSupport javaScriptSupport;
    049
    050        @SessionState(create = false)
    051        private AlertStorage storage;
    052
    053        private String clientId;
    054
    055        public String getClientId()
    056        {
    057            return clientId;
    058        }
    059
    060        boolean beginRender(MarkupWriter writer)
    061        {
    062            clientId = javaScriptSupport.allocateClientId(resources);
    063
    064            writer.element("div", "id", clientId);
    065            resources.renderInformalParameters(writer);
    066            writer.end();
    067
    068            JSONObject spec = new JSONObject("id", clientId,
    069                    "dismissURL", resources.createEventLink("dismiss").toURI(),
    070                    "dismissText", dismissText);
    071
    072            javaScriptSupport.addInitializerCall(InitializationPriority.EARLY, "alertManager", spec);
    073
    074            if (storage != null)
    075            {
    076                addAlertsFromStorage();
    077            }
    078
    079
    080            return false;
    081        }
    082
    083        Object onDismiss(@RequestParameter(value = "id", allowBlank = true) Long alertId)
    084        {
    085            // If the alert was created inside an Ajax request and AlertStorage did not previously
    086            // exist, it can be null when the dismiss event comes up from the client.
    087            if (storage != null)
    088            {
    089                if (alertId != null)
    090                {
    091                    storage.dismiss(alertId);
    092                } else
    093                {
    094                    storage.dismissAll();
    095                }
    096            }
    097
    098            return new JSONObject();
    099        }
    100
    101        @HeartbeatDeferred
    102        void addAlertsFromStorage()
    103        {
    104            for (Alert alert : storage.getAlerts())
    105            {
    106                javaScriptSupport.addInitializerCall("addAlert", alert.toJSON());
    107            }
    108
    109            storage.dismissNonPersistent();
    110        }
    111    }