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    }