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.ModalHiddenEvent; 024import org.gwtbootstrap3.client.shared.event.ModalHiddenHandler; 025import org.gwtbootstrap3.client.shared.event.ModalHideEvent; 026import org.gwtbootstrap3.client.shared.event.ModalHideHandler; 027import org.gwtbootstrap3.client.shared.event.ModalShowEvent; 028import org.gwtbootstrap3.client.shared.event.ModalShowHandler; 029import org.gwtbootstrap3.client.shared.event.ModalShownEvent; 030import org.gwtbootstrap3.client.shared.event.ModalShownHandler; 031import org.gwtbootstrap3.client.ui.base.helper.StyleHelper; 032import org.gwtbootstrap3.client.ui.base.modal.ModalContent; 033import org.gwtbootstrap3.client.ui.base.modal.ModalDialog; 034import org.gwtbootstrap3.client.ui.constants.Attributes; 035import org.gwtbootstrap3.client.ui.constants.ModalBackdrop; 036import org.gwtbootstrap3.client.ui.constants.Styles; 037import org.gwtbootstrap3.client.ui.html.Div; 038 039import com.google.gwt.dom.client.Element; 040import com.google.gwt.user.client.Event; 041import com.google.gwt.user.client.ui.RootPanel; 042import com.google.gwt.user.client.ui.Widget; 043import com.google.web.bindery.event.shared.HandlerRegistration; 044 045/** 046 * Modal dialog. 047 * <p/> 048 * <h3>UiBinder example</h3> 049 * <p/> 050 * <pre> 051 * {@code 052 * <b:Modal title="Important information" b:id="modal1"> 053 * <b:ModalBody> 054 * <g:HTML>Lorem ipsum...</g:HTML> 055 * </b:ModalBody> 056 * <b:ModalFooter> 057 * <b:Button type="PRIMARY">Do something</b:Button> 058 * <b:Button type="DANGER" dismiss="MODAL">Close</b:Button> 059 * </b:ModalFooter> 060 * </b:Modal> 061 * <b:Button target="#modal1" toggle="MODAL">Show modal</b:Button> 062 * } 063 * </pre> 064 * <p/> 065 * It's also possible to specify a custom modal header: 066 * <p/> 067 * <pre> 068 * {@code 069 * <b:Modal> 070 * <b:ModalHeader> 071 * <g:HTML> 072 * <h4>Custom header</h4> 073 * </g:HTML> 074 * </b:ModalHeader> 075 * ... 076 * </b:Modal> 077 * } 078 * </pre> 079 * 080 * @author Sven Jacobs 081 * @author Joshua Godi 082 * @see ModalHeader 083 * @see ModalBody 084 * @see ModalFooter 085 * @see org.gwtbootstrap3.client.shared.event.ModalShowEvent 086 * @see org.gwtbootstrap3.client.shared.event.ModalShownEvent 087 * @see org.gwtbootstrap3.client.shared.event.ModalHideEvent 088 * @see org.gwtbootstrap3.client.shared.event.ModalHiddenEvent 089 */ 090public class Modal extends Div implements IsClosable { 091 092 private final static String TOGGLE = "toggle"; 093 private final static String HIDE = "hide"; 094 private final static String SHOW = "show"; 095 096 private final ModalContent content = new ModalContent(); 097 private final ModalDialog dialog = new ModalDialog(); 098 private ModalHeader header = new ModalHeader(); 099 100 private HandlerRegistration removeOnHideHandlerReg = null; 101 102 private boolean hideOtherModals = false; 103 104 public Modal() { 105 setStyleName(Styles.MODAL); 106 107 // Set the z-index to match bootstrap's .modal 108 getElement().getStyle().setZIndex(1050); 109 110 content.add(header); 111 dialog.add(content); 112 113 add(dialog); 114 } 115 116 @Override 117 public void setWidth(final String width) { 118 dialog.setWidth(width); 119 } 120 121 public void setSize(ModalSize size) { 122 StyleHelper.addUniqueEnumStyleName(dialog, ModalSize.class, size); 123 } 124 125 @Override 126 protected void onLoad() { 127 super.onLoad(); 128 bindJavaScriptEvents(getElement()); 129 } 130 131 @Override 132 protected void onUnload() { 133 super.onUnload(); 134 unbindAllHandlers(getElement()); 135 } 136 137 @Override 138 public void add(final Widget w) { 139 // User can supply own ModalHeader 140 if (w instanceof ModalHeader) { 141 header.removeFromParent(); 142 header = (ModalHeader) w; 143 } 144 145 if (w instanceof ModalComponent) { 146 content.add(w); 147 } else { 148 super.add(w); 149 } 150 } 151 152 @Override 153 public void setTitle(final String title) { 154 header.setTitle(title); 155 } 156 157 @Override 158 public void setClosable(final boolean closable) { 159 header.setClosable(closable); 160 } 161 162 @Override 163 public boolean isClosable() { 164 return header.isClosable(); 165 } 166 167 /** 168 * If set to true, when the modal is shown it will force hide all other modals 169 * 170 * @param hideOtherModals - true to force hide other modals, false to keep them shown 171 */ 172 public void setHideOtherModals(final boolean hideOtherModals) { 173 this.hideOtherModals = hideOtherModals; 174 } 175 176 /** 177 * If set to true, will remove the modal from the DOM completely and unbind any events to the modal 178 * 179 * @param removeOnHide - true to remove modal and unbind events on hide, false to keep it in the DOM 180 */ 181 public void setRemoveOnHide(final boolean removeOnHide) { 182 if (removeOnHideHandlerReg != null) { 183 removeOnHideHandlerReg.removeHandler(); 184 removeOnHideHandlerReg = null; 185 } 186 if (removeOnHide) { 187 removeOnHideHandlerReg = addHiddenHandler(new ModalHiddenHandler() { 188 @Override 189 public void onHidden(final ModalHiddenEvent evt) { 190 // Do logical detach 191 removeFromParent(); 192 } 193 }); 194 } 195 } 196 197 /** 198 * If set Modal will fade in/out. 199 * 200 * @param fade If {@code true} modal will fade in/out 201 */ 202 public void setFade(final boolean fade) { 203 if (fade) { 204 addStyleName(Styles.FADE); 205 } else { 206 removeStyleName(Styles.FADE); 207 } 208 } 209 210 /** 211 * Sets backdrop of modal. 212 * 213 * @param backdrop Backdrop of modal 214 * @see org.gwtbootstrap3.client.ui.constants.ModalBackdrop 215 */ 216 public void setDataBackdrop(final ModalBackdrop backdrop) { 217 if (backdrop != null) { 218 getElement().setAttribute(Attributes.DATA_BACKDROP, backdrop.getBackdrop()); 219 } else { 220 getElement().removeAttribute(Attributes.DATA_BACKDROP); 221 } 222 } 223 224 public void setDataKeyboard(final boolean keyboard) { 225 getElement().setAttribute(Attributes.DATA_KEYBOARD, Boolean.toString(keyboard)); 226 227 // tabindex must be set to -1 for ESC key to work 228 if (keyboard) { 229 getElement().setAttribute(Attributes.TABINDEX, "-1"); 230 } 231 } 232 233 public void toggle() { 234 modal(getElement(), TOGGLE); 235 } 236 237 public void show() { 238 checkIsAttached(); 239 modal(getElement(), SHOW); 240 } 241 242 public void hide() { 243 modal(getElement(), HIDE); 244 } 245 246 public HandlerRegistration addShowHandler(final ModalShowHandler modalShowHandler) { 247 return addHandler(modalShowHandler, ModalShowEvent.getType()); 248 } 249 250 public HandlerRegistration addShownHandler(final ModalShownHandler modalShownHandler) { 251 return addHandler(modalShownHandler, ModalShownEvent.getType()); 252 } 253 254 public HandlerRegistration addHideHandler(final ModalHideHandler modalHideHandler) { 255 return addHandler(modalHideHandler, ModalHideEvent.getType()); 256 } 257 258 public HandlerRegistration addHiddenHandler(final ModalHiddenHandler modalHiddenHandler) { 259 return addHandler(modalHiddenHandler, ModalHiddenEvent.getType()); 260 } 261 262 /** 263 * Can be override by subclasses to handle Modal's "show" event however it's 264 * recommended to add an event handler to the modal. 265 * 266 * @param evt Event 267 * @see org.gwtbootstrap3.client.shared.event.ModalShowEvent 268 */ 269 protected void onShow(final Event evt) { 270 if (hideOtherModals) { 271 hideOtherModals(); 272 } 273 fireEvent(new ModalShowEvent(this, evt)); 274 } 275 276 /** 277 * Can be override by subclasses to handle Modal's "shown" event however 278 * it's recommended to add an event handler to the modal. 279 * 280 * @param evt Event 281 * @see org.gwtbootstrap3.client.shared.event.ModalShownEvent 282 */ 283 protected void onShown(final Event evt) { 284 fireEvent(new ModalShownEvent(this, evt)); 285 } 286 287 /** 288 * Can be override by subclasses to handle Modal's "hide" event however it's 289 * recommended to add an event handler to the modal. 290 * 291 * @param evt Event 292 * @see org.gwtbootstrap3.client.shared.event.ModalHideEvent 293 */ 294 protected void onHide(final Event evt) { 295 fireEvent(new ModalHideEvent(this, evt)); 296 } 297 298 /** 299 * Can be override by subclasses to handle Modal's "hidden" event however 300 * it's recommended to add an event handler to the modal. 301 * 302 * @param evt Event 303 * @see org.gwtbootstrap3.client.shared.event.ModalHiddenEvent 304 */ 305 protected void onHidden(final Event evt) { 306 fireEvent(new ModalHiddenEvent(this, evt)); 307 } 308 309 private void checkIsAttached() { 310 if (!this.isAttached()) { 311 RootPanel.get().add(this); 312 } 313 } 314 315 private native void bindJavaScriptEvents(final Element e) /*-{ 316 var target = this; 317 var $modal = $wnd.jQuery(e); 318 319 $modal.on('show.bs.modal', function (evt) { 320 target.@org.gwtbootstrap3.client.ui.Modal::onShow(Lcom/google/gwt/user/client/Event;)(evt); 321 }); 322 323 $modal.on('shown.bs.modal', function (evt) { 324 target.@org.gwtbootstrap3.client.ui.Modal::onShown(Lcom/google/gwt/user/client/Event;)(evt); 325 }); 326 327 $modal.on('hide.bs.modal', function (evt) { 328 target.@org.gwtbootstrap3.client.ui.Modal::onHide(Lcom/google/gwt/user/client/Event;)(evt); 329 }); 330 331 $modal.on('hidden.bs.modal', function (evt) { 332 target.@org.gwtbootstrap3.client.ui.Modal::onHidden(Lcom/google/gwt/user/client/Event;)(evt); 333 }); 334 }-*/; 335 336 private native void modal(final Element e, final String arg) /*-{ 337 $wnd.jQuery(e).modal(arg); 338 }-*/; 339 340 // Will iterate over all the modals, if they are visible it will hide them 341 private native void hideOtherModals() /*-{ 342 $wnd.jQuery('.modal.in').modal('hide'); 343 }-*/; 344 345 // Unbinds all the handlers 346 private native void unbindAllHandlers(final Element e) /*-{ 347 var $e = $wnd.jQuery(e); 348 $e.off('show.bs.modal'); 349 $e.off('shown.bs.modal'); 350 $e.off('hide.bs.modal'); 351 $e.off('hidden.bs.modal'); 352 }-*/; 353}