001package org.gwtbootstrap3.client.ui;
002
003/*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 GwtBootstrap3
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import org.gwtbootstrap3.client.shared.event.AlertCloseEvent;
024import org.gwtbootstrap3.client.shared.event.AlertCloseHandler;
025import org.gwtbootstrap3.client.shared.event.AlertClosedEvent;
026import org.gwtbootstrap3.client.shared.event.AlertClosedHandler;
027import org.gwtbootstrap3.client.ui.base.HasResponsiveness;
028import org.gwtbootstrap3.client.ui.base.HasType;
029import org.gwtbootstrap3.client.ui.base.button.CloseButton;
030import org.gwtbootstrap3.client.ui.base.helper.StyleHelper;
031import org.gwtbootstrap3.client.ui.constants.AlertType;
032import org.gwtbootstrap3.client.ui.constants.ButtonDismiss;
033import org.gwtbootstrap3.client.ui.constants.Styles;
034import org.gwtbootstrap3.client.ui.html.Div;
035import org.gwtbootstrap3.client.ui.html.Text;
036
037import com.google.gwt.dom.client.Element;
038import com.google.gwt.user.client.Event;
039import com.google.gwt.user.client.ui.HasText;
040import com.google.gwt.user.client.ui.HasWidgets;
041import com.google.web.bindery.event.shared.HandlerRegistration;
042
043/**
044 * Alert block.
045 * <p/>
046 * Use {@link #setDismissable(boolean)} to add a close ("x") button.
047 *
048 * @author Sven Jacobs
049 * @author Joshua Godi
050 * @see org.gwtbootstrap3.client.shared.event.AlertCloseEvent
051 * @see org.gwtbootstrap3.client.shared.event.AlertClosedEvent
052 */
053public class Alert extends Div implements HasWidgets, HasText, HasType<AlertType>, HasResponsiveness {
054    private static final String CLOSE = "close";
055
056    private final Text text = new Text();
057    private final CloseButton closeButton = new CloseButton();
058
059    private final HandlerRegistration closedHandlerReg;
060
061    /**
062     * Builds a default alert
063     */
064    public Alert() {
065        setStyleName(Styles.ALERT);
066        setType(AlertType.WARNING);
067        closeButton.setDataDismiss(ButtonDismiss.ALERT);
068        closedHandlerReg = addCloseHandler(new AlertCloseHandler() {
069            @Override
070            public void onClose(AlertCloseEvent evt) {
071                // Do logical detach
072                removeFromParent();
073                closedHandlerReg.removeHandler();
074            }
075        });
076    }
077
078    /**
079     * Builds a default alert with the desired text
080     *
081     * @param text text for the alert
082     */
083    public Alert(final String text) {
084        this();
085        setText(text);
086    }
087
088    /**
089     * Builds an alert with the desired text and type
090     *
091     * @param text text for the alert
092     * @param type type for the alert
093     */
094    public Alert(final String text, final AlertType type) {
095        this(text);
096        setType(type);
097    }
098
099    @Override
100    protected void onLoad() {
101        super.onLoad();
102
103        // Bind the events
104        bindJavaScriptEvents(getElement());
105    }
106
107    @Override
108    protected void onUnload() {
109        super.onUnload();
110
111        // Unbind the events
112        unbindJavaScriptEvents(getElement());
113    }
114
115    /**
116     * {@inheritDoc}
117     */
118    @Override
119    public String getText() {
120        return text.getText();
121    }
122
123    /**
124     * {@inheritDoc}
125     */
126    @Override
127    public void setText(final String text) {
128        this.text.setText(text);
129        insert(this.text, 0);
130    }
131
132    /**
133     * {@inheritDoc}
134     */
135    @Override
136    public void setType(final AlertType type) {
137        StyleHelper.addUniqueEnumStyleName(this, AlertType.class, type);
138    }
139
140    /**
141     * {@inheritDoc}
142     */
143    @Override
144    public AlertType getType() {
145        return AlertType.fromStyleName(getStyleName());
146    }
147
148    /**
149     * Adds a close button to the alert
150     *
151     * @param dismissable Adds close button when {@code true}
152     */
153    public void setDismissable(final boolean dismissable) {
154        if (dismissable) {
155            insert(closeButton, (Element) getElement(), 0, true);
156            addStyleName(Styles.ALERT_DISMISSABLE);
157        } else {
158            closeButton.removeFromParent();
159            removeStyleName(Styles.ALERT_DISMISSABLE);
160        }
161    }
162
163    /**
164     * Returns if the alert can be closed or not
165     *
166     * @return true = alert can be closed, false = alert cannot be closed
167     */
168    public boolean isDismissable() {
169        return closeButton.getParent() != null;
170    }
171
172    /**
173     * Sets whether the Alert should fade out before it is removed
174     *
175     * @param fade The alert will fade on close before it is removed when {@code true}
176     */
177    public void setFade(final boolean fade) {
178        if (fade) {
179            addStyleName(Styles.FADE);
180            addStyleName(Styles.IN);
181        } else {
182            removeStyleName(Styles.FADE);
183            removeStyleName(Styles.IN);
184        }
185    }
186
187    /**
188     * Returns if the alert will fade out before it is removed
189     *
190     * @return true = alert will fade out, false = alert won't fade out
191     */
192    public boolean isFade() {
193        return StyleHelper.containsStyle(getStyleName(), Styles.FADE);
194    }
195
196    /**
197     * Closes alert.
198     */
199    public void close() {
200        alert(getElement(), CLOSE);
201    }
202
203    /**
204     * Event fired when the close is initiated on the alert
205     *
206     * @param evt event
207     */
208    protected void onClose(final Event evt) {
209        fireEvent(new AlertCloseEvent(evt));
210    }
211
212    /**
213     * Event fired when the alert is fully closed (will wait for CSS transitions)
214     *
215     * @param evt event
216     */
217    protected void onClosed(final Event evt) {
218        fireEvent(new AlertClosedEvent(evt));
219    }
220
221    /**
222     * Add a handler to be used when the close event is fired
223     *
224     * @param handler handler for event
225     * @return handler registration for the handler
226     */
227    public HandlerRegistration addCloseHandler(final AlertCloseHandler handler) {
228        return addHandler(handler, AlertCloseEvent.getType());
229    }
230
231    /**
232     * Add a handler to be used when the closed event is fired
233     *
234     * @param handler handler for event
235     * @return handler registration for the handler
236     */
237    public HandlerRegistration addClosedHandler(final AlertClosedHandler handler) {
238        return addHandler(handler, AlertClosedEvent.getType());
239    }
240
241    // @formatter:off
242    private native void alert(final Element e, final String arg) /*-{
243        $wnd.jQuery(e).alert(arg);
244    }-*/;
245
246    private native void bindJavaScriptEvents(final Element e) /*-{
247        var target = this;
248        var $alert = $wnd.jQuery(e);
249
250        $alert.on('close.bs.alert', function (evt) {
251            target.@org.gwtbootstrap3.client.ui.Alert::onClose(Lcom/google/gwt/user/client/Event;)(evt);
252        });
253
254        $alert.on('closed.bs.alert', function (evt) {
255            target.@org.gwtbootstrap3.client.ui.Alert::onClosed(Lcom/google/gwt/user/client/Event;)(evt);
256        });
257    }-*/;
258
259    private native void unbindJavaScriptEvents(final Element e) /*-{
260        $wnd.jQuery(e).off('close.bs.alert');
261        $wnd.jQuery(e).off('closed.bs.alert');
262    }-*/;
263}