001: /*
002: * $Id$ $Revision$ $Date$
003: *
004: * ==============================================================================
005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
006: * use this file except in compliance with the License. You may obtain a copy of
007: * the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations under
015: * the License.
016: */
017: package wicket.extensions.ajax.markup.html.modal;
018:
019: import java.io.Serializable;
020:
021: import wicket.Application;
022: import wicket.Component;
023: import wicket.Page;
024: import wicket.PageMap;
025: import wicket.RequestCycle;
026: import wicket.ResourceReference;
027: import wicket.Session;
028: import wicket.WicketRuntimeException;
029: import wicket.ajax.AbstractDefaultAjaxBehavior;
030: import wicket.ajax.AjaxRequestTarget;
031: import wicket.ajax.IAjaxCallDecorator;
032: import wicket.ajax.calldecorator.CancelEventIfNoAjaxDecorator;
033: import wicket.behavior.HeaderContributor;
034: import wicket.markup.ComponentTag;
035: import wicket.markup.html.WebMarkupContainer;
036: import wicket.markup.html.panel.Panel;
037: import wicket.markup.html.resources.CompressedResourceReference;
038: import wicket.request.RequestParameters;
039: import wicket.settings.IPageSettings;
040: import wicket.util.lang.EnumeratedType;
041: import wicket.util.string.AppendingStringBuffer;
042: import wicket.util.string.Strings;
043:
044: /**
045: * Modal window component.
046: * <p>
047: * Modal window is a draggable window (with either div or iframe content) that
048: * prevent user from interacting the rest of page (using a mask) until the
049: * window is closed.
050: * <p>
051: * The window is draggable and optionally resizable. The content can be either
052: * <ul>
053: * <li><b>a component</b> - you need to add the component to modal window
054: * (with id obtained using <code>{@link #getContentId()}</code>, or
055: * <li><b>a page</b> - you need to pass a <code>{@link PageCreator}</code>
056: * instance to a <code>{@link #setPageCreator(ModalWindow.PageCreator)}</code>
057: * method.
058: * </ul>
059: * In case the content is a component, it is not rendered until the window is
060: * shown (method <code>{@link #show(AjaxRequestTarget)})</code>. In case the
061: * content is another page, you can set the desired pagemap name using
062: * <code>{@link #setPageMapName(String)}</code>. Setting pagemap is only
063: * needed when wicket multiwindow support is on.
064: * <p>
065: * The window can be made visible from an ajax handler using
066: * <code>{@link #show(AjaxRequestTarget)}</code>.
067: * <p>
068: * To close the window there are multiple options. Static method
069: * <code>{@link #close(AjaxRequestTarget)}</code> can be used to close the
070: * window from a handler of ajax link inside the window. By default the close
071: * button in the upper right corner of the window closes it. This behavior can
072: * be altered using
073: * <code>{@link #setCloseButtonCallback(ModalWindow.CloseButtonCallback)}</code>.
074: * If you want to be notified when the window is closed (either using the close
075: * button or calling <code>{@link #close(AjaxRequestTarget)})</code>, you
076: * can use
077: * <code>{@link #setWindowClosedCallback(ModalWindow.WindowClosedCallback)}</code>.
078: * <p>
079: * Title is specified using {@link #setTitle(String)}. If the content is a page
080: * (iframe), the title can remain unset, in that case title from the page inside
081: * window will be shown.
082: * <p>
083: * There are several options to specify the visual properties of the window. In
084: * all methods where size is expected, width refers to width of entire window
085: * (including frame), height refers to the height of window content (without
086: * frame).
087: * <p>
088: * <ul>
089: * <li><code>{@link #setResizable(boolean)}</code> specifies, whether the
090: * window can be resized.
091: * <li><code>{@link #setInitialWidth(int)}</code> and
092: * <code>{@link #setInitialHeight(int)}</code> specify the initial width and
093: * height of window. If the window is resizable, the unit of these dimensions is
094: * always "px". If the window is not resizable, the unit can be specified using
095: * <code>{@link #setWidthUnit(String)}</code> and
096: * <code>{@link #setHeightUnit(String)}</code>. If the window is not
097: * resizable and the content is a component (not a page), the initial height
098: * value can be ignored and the actual height can be determined from the height
099: * of the content. To enable this behavior use
100: * <code>{@link #setUseInitialHeight(boolean)}</code>.
101: * <li>The window position (and size if the window is resizable) can be stored
102: * in a cookie, so that it is preserved when window is close. The name of the
103: * cookie is specified via <code>{@link #setCookieName(String)}</code>. If
104: * the name is <code>null</code>, position is not stored (initial width and
105: * height are always used). Default cookie name is null (position is not stored).
106: * <li><code>{@link #setMinimalWidth(int)}</code> and
107: * <code>{@link #setMinimalHeight(int)}</code> set the minimal dimensions of
108: * resizable window.
109: * <li>Modal window can chose between two colors of frame.
110: * <code>{@link #setCssClassName(String)}</code> sets the dialog css class,
111: * possible values are <code>{@link #CSS_CLASS_BLUE}</code> for blue frame and
112: * <code>{@link #CSS_CLASS_GRAY}</code> for gray frame.
113: * <li>Mask (element that prevents user from interacting the rest of the page)
114: * can be either transparent or semitransparent.
115: * <code>{@link #setMaskType(ModalWindow.MaskType)}</code> alters this.
116: * </ul>
117: *
118: * @see IPageSettings#setAutomaticMultiWindowSupport(boolean)
119: * @author Matej Knopp
120: */
121: public class ModalWindow extends Panel {
122: private static final long serialVersionUID = 1L;
123:
124: private static ResourceReference JAVASCRIPT = new CompressedResourceReference(
125: ModalWindow.class, "res/modal.js");
126:
127: private static ResourceReference CSS = new CompressedResourceReference(
128: ModalWindow.class, "res/modal.css");
129:
130: /**
131: * Creates a new modal window component.
132: *
133: * @param id
134: * Id of component
135: */
136: public ModalWindow(String id) {
137: super (id);
138: setVersioned(false);
139: this .cookieName = null;
140: add(empty = new WebMarkupContainer(getContentId()));
141:
142: add(new CloseButtonBehavior());
143: add(new WindowClosedBehavior());
144: add(HeaderContributor.forJavaScript(JAVASCRIPT));
145: add(HeaderContributor.forCss(CSS));
146: }
147:
148: /**
149: * Interface for lazy page creation. The advantage of creating page using
150: * this interface over just passing a page instance is that page created in
151: * <code>{@link #createPage()}</code> will have the pagemap automatically
152: * set to the pagemap specified for <code>{@link ModalWindow}</code>.
153: *
154: * @author Matej Knopp
155: */
156: public static interface PageCreator extends Serializable {
157: /**
158: * Creates a new instance of content page.
159: *
160: * @return new page instance
161: */
162: public Page createPage();
163: }
164:
165: /**
166: * Callback for close button that contains a method that is invoked after
167: * the button has been clicked. If no callback instance is specified using
168: * <code>{@link #setCloseButtonCallback(ModalWindow.CloseButtonCallback)}</code>,
169: * no ajax request will be fired. Clicking the button will just close the
170: * window.
171: *
172: * @author Matej Knopp
173: */
174: public static interface CloseButtonCallback extends Serializable {
175: /**
176: * Methods invoked after the button has been clicked. The invokation is
177: * done using an ajax call, so <code>{@link AjaxRequestTarget}</code>
178: * instance is available.
179: *
180: * @param target
181: * <code>{@link AjaxRequestTarget}</code> instance bound
182: * with the ajax reuqest.
183: *
184: * @return True if the window can be closed (will close the window),
185: * false otherwise
186: */
187: public boolean onCloseButtonClicked(AjaxRequestTarget target);
188: }
189:
190: /**
191: * Callback called after the window has been closed. If no callback instance
192: * is specified using
193: * {@link ModalWindow#setWindowClosedCallback(ModalWindow.WindowClosedCallback)},
194: * no ajax request will be fired.
195: *
196: * @author Matej Knopp
197: */
198: public static interface WindowClosedCallback extends Serializable {
199: /**
200: * Called after the window has been closed.
201: *
202: * @param target
203: * <code>{@link AjaxRequestTarget}</code> instance bound
204: * with the ajax reuqest.
205: */
206: public void onClose(AjaxRequestTarget target);
207: }
208:
209: /**
210: * Sets the name of the page ma for the content page. This makes only sense
211: * when the content is a page, not a component and if wicket multiwindow
212: * support is turned on.
213: *
214: * @param pageMapName
215: * Name of the page map
216: */
217: public void setPageMapName(String pageMapName) {
218: this .pageMapName = pageMapName;
219: }
220:
221: /**
222: * Returns the page map name.
223: *
224: * @return The page map name.
225: */
226: public String getPageMapName() {
227: return pageMapName;
228: }
229:
230: /**
231: * Sets the <code>{@link PageCreator}</code> instance. The instance is
232: * only used when no custom component has been added to the dialog.
233: *
234: * @param creator
235: * <code>{@link PageCreator}</code> instance
236: */
237: public void setPageCreator(PageCreator creator) {
238: this .pageCreator = creator;
239: }
240:
241: /**
242: * Sets the <code>{@link CloseButtonCallback}</code> instance.
243: *
244: * @param callback
245: * Callback instance
246: */
247: public void setCloseButtonCallback(CloseButtonCallback callback) {
248: this .closeButtonCallback = callback;
249: }
250:
251: /**
252: * Sets the <code>@{link {@link WindowClosedCallback}</code> instance.
253: *
254: * @param callback
255: * Callback instance
256: */
257: public void setWindowClosedCallback(WindowClosedCallback callback) {
258: this .windowClosedCallback = callback;
259: }
260:
261: /**
262: * Shows the modal window.
263: *
264: * @param target
265: * Request target associated with current ajax request.
266: */
267: public void show(AjaxRequestTarget target) {
268: target.addComponent(this );
269: target.appendJavascript(getWindowOpenJavascript());
270: shown = true;
271: }
272:
273: /**
274: * Hides the modal window.
275: *
276: * @param target
277: * Request target associated with current ajax request.
278: */
279: public static final void close(AjaxRequestTarget target) {
280: target.appendJavascript(getCloseJavacript());
281: }
282:
283: /**
284: * @return javascript that closes current modal window
285: */
286: private static String getCloseJavacript() {
287: return "var win;\n" //
288: + "try {\n"
289: + " win = window.parent.Wicket.Window;\n"
290: + "} catch (ignore) {\n"
291: + "}\n"
292: + "if (typeof(win) == \"undefined\" || typeof(win.current) == \"undefined\") {\n"
293: + " try {\n"
294: + " win = window.Wicket.Window;\n"
295: + " } catch (ignore) {\n"
296: + " }\n"
297: + "}\n"
298: + "if (typeof(win) != \"undefined\" && typeof(win.current) != \"undefined\") {\n"
299: + " window.parent.setTimeout(function() {\n"
300: + " win.current.close();\n" + " }, 0);\n" + "}";
301: }
302:
303: /**
304: * Returns the id of content component.
305: *
306: * <pre>
307: * ModalWindow window = new ModalWindow(parent, "window");
308: * new MyPanel(window, window.getContentId());
309: * </pre>
310: *
311: * @return Id of content component.
312: */
313: public String getContentId() {
314: return "content";
315: }
316:
317: /**
318: * Sets the minimal width of window. This value is only used if the window
319: * is resizable. The width is specified in pixels and it is the width of
320: * entire window (including frame).
321: *
322: * @param minimalWidth
323: * Minimal window width.
324: */
325: public void setMinimalWidth(int minimalWidth) {
326: this .minimalWidth = minimalWidth;
327: }
328:
329: /**
330: * Returns the minimal width of window (in pixels).
331: *
332: * @return Minimal width of window
333: */
334: public int getMinimalWidth() {
335: return minimalWidth;
336: }
337:
338: /**
339: * Sets the minimal height of window. This value is only used if window is
340: * resizable. The height is specified in pixels and it is the height of
341: * window content (without frame).
342: *
343: * @param minimalHeight
344: * Minimal height
345: */
346: public void setMinimalHeight(int minimalHeight) {
347: this .minimalHeight = minimalHeight;
348: }
349:
350: /**
351: * Returns the minimal height of window (in pixels).
352: *
353: * @return Minimal height of window
354: */
355: public int getMinimalHeight() {
356: return minimalHeight;
357: }
358:
359: /**
360: * CSS class for window with blue border.
361: */
362: public final static String CSS_CLASS_BLUE = "w_blue";
363:
364: /**
365: * CSS class for window with gray border.
366: */
367: public final static String CSS_CLASS_GRAY = "w_silver";
368:
369: /**
370: * Sets the CSS class name for this window. This class affects the look of
371: * window frame. Possible values (if you don't make your style sheet) are
372: * <code>{@link #CSS_CLASS_BLUE}</code> and
373: * <code>{@link #CSS_CLASS_GRAY}</code>.
374: *
375: * @param cssClassName
376: */
377: public void setCssClassName(String cssClassName) {
378: this .cssClassName = cssClassName;
379: }
380:
381: /**
382: * Returns the CSS class name for this window.
383: *
384: * @return CSS class name
385: */
386: public String getCssClassName() {
387: return cssClassName;
388: }
389:
390: /**
391: * Sets the initial width of the window. The width refers to the width of
392: * entire window (including frame). If the window is resizable, the width
393: * unit is always "px". If the window is not resizable, the unit can be
394: * specified using {@link #setWidthUnit(String)}. If cookie name is set and
395: * window is resizable, the initial width may be ignored in favor of width
396: * stored in cookie.
397: *
398: * @param initialWidth
399: * Initial width of the window
400: */
401: public void setInitialWidth(int initialWidth) {
402: this .initialWidth = initialWidth;
403: }
404:
405: /**
406: * Returns the initial width of the window.
407: *
408: * @return Initial height of the window
409: */
410: public int getInitialWidth() {
411: return initialWidth;
412: }
413:
414: /**
415: * Sets the initial height of the window. The height refers to the height of
416: * window content (without frame). If the window is resizable, the height
417: * unit is always "px". If the window is not resizable, the unit can be
418: * specified using {@link #setHeightUnit(String)}. If cookie name is set
419: * and window is resizable, the initial height may be ignred in favor of
420: * height stored in cookie.
421: *
422: * @param initialHeight
423: * Initial height of the window
424: */
425: public void setInitialHeight(int initialHeight) {
426: this .initialHeight = initialHeight;
427: }
428:
429: /**
430: * Returns the initial height of the window.
431: *
432: * @return Initial height of the window
433: */
434: public int getInitialHeight() {
435: return initialHeight;
436: }
437:
438: /**
439: * Sets whether to use initial height or preserve the real content height.
440: * This can only be used if the content is a component (not a page) and the
441: * window is not resizable.
442: *
443: * @param useInitialHeight
444: * Whether to use initial height instead of preserving content
445: * height instead of using initial height
446: */
447: public void setUseInitialHeight(boolean useInitialHeight) {
448: this .useInitialHeight = useInitialHeight;
449: }
450:
451: /**
452: * Returns true if the initial height should be used (in favour of
453: * preserving real content height).
454: *
455: * @return True if initial height should be used, false is real content
456: * height should be preserved (valid only if the window is not
457: * resizable and the content is a component (not a page)
458: */
459: public boolean isUseInitialHeight() {
460: return useInitialHeight;
461: }
462:
463: /**
464: * Sets whether the user will be able to resize the window.
465: *
466: * @param resizable
467: * Whether the window is resizable
468: */
469: public void setResizable(boolean resizable) {
470: this .resizable = resizable;
471: }
472:
473: /**
474: * Returns whether the window is resizable.
475: *
476: * @return True if the window is resizable, false otherwise
477: */
478: public boolean isResizable() {
479: return resizable;
480: }
481:
482: /**
483: * Sets the CSS unit used for initial window width. This is only applicable
484: * when the window is not resizable.
485: *
486: * @param widthUnit
487: * CSS unit for initial window width.
488: */
489: public void setWidthUnit(String widthUnit) {
490: this .widthUnit = widthUnit;
491: }
492:
493: /**
494: * Returns the CSS unit for initial window width.
495: *
496: * @return CSS unit for initial window width.
497: */
498: public String getWidthUnit() {
499: return widthUnit;
500: }
501:
502: /**
503: * Sets the CSS unit used for initial window height. This is only applicable
504: * when the window is not resizable.
505: *
506: * @param heightUnit
507: * CSS unit for initial window height.
508: */
509: public void setHeightUnit(String heightUnit) {
510: this .heightUnit = heightUnit;
511: }
512:
513: /**
514: * Retrns the CSS unit for initial window height.
515: *
516: * @return CSS unit for initial window height.
517: */
518: public String getHeightUnit() {
519: return heightUnit;
520: }
521:
522: /**
523: * Sets the name of the cookie that is used to remeber window position (and
524: * size if the window is resizable).
525: *
526: * @param cookieName
527: * Name of the cookie
528: */
529: public void setCookieName(String cookieName) {
530: this .cookieName = cookieName;
531: }
532:
533: /**
534: * Returns the name of cookie that is used to remebember window position
535: * (and size if the window is resizable).
536: *
537: * @return Name of the cookie
538: */
539: public String getCookieName() {
540: return cookieName;
541: }
542:
543: /**
544: * Sets the title of window. If the window is a page, title can be
545: * <code>null</code>. In that case it will display the title document
546: * inside the window.
547: *
548: * @param title
549: * Title of the window
550: */
551: public void setTitle(String title) {
552: this .title = title;
553: }
554:
555: /**
556: * Returns the title of the window.
557: *
558: * @return Title of the window
559: */
560: public String getTitle() {
561: return title;
562: }
563:
564: /**
565: * Mask is the element behind the window, that prevents user from
566: * interacting the rest of page. Mask can be either
567: * <ul>
568: * <li><code>{@link #TRANSPARENT}</code> - the mask is invisible
569: * <li><code>{@link #SEMI_TRANSPARENT}</code> - the mask is black with
570: * small opacity (10%)
571: * </ul>
572: *
573: * @author Matej Knopp
574: */
575: public static final class MaskType extends EnumeratedType {
576:
577: private static final long serialVersionUID = 1L;
578:
579: /**
580: * Transparent mask (not visible).
581: */
582: public static final MaskType TRANSPARENT = new MaskType(
583: "TRANSPARENT");
584:
585: /**
586: * Visible mask (black with low opacity).
587: */
588: public static final MaskType SEMI_TRANSPARENT = new MaskType(
589: "SEMI_TRANSPARENT");
590:
591: /**
592: * Constructor.
593: *
594: * @param name
595: */
596: public MaskType(String name) {
597: super (name);
598: }
599: };
600:
601: /**
602: * Sets the mask type of the window.
603: *
604: * @param mask
605: * The mask type
606: */
607: public void setMaskType(MaskType mask) {
608: this .maskType = mask;
609: }
610:
611: /**
612: * Returns the mask type of the window
613: *
614: * @return The mask type
615: */
616: public MaskType getMaskType() {
617: return maskType;
618: }
619:
620: /**
621: * Creates the page.
622: *
623: * @return Page instance or null if page couldn't be created.
624: */
625: private Page createPage() {
626: if (pageCreator == null) {
627: return null;
628: } else {
629: RequestParameters parameters = RequestCycle.get()
630: .getRequest().getRequestParameters();
631: String oldPageMapName = parameters.getPageMapName();
632:
633: // if there is a pagemap name specified and multiwindow support is
634: // on
635: if (getPageMapName() != null
636: && Application.get().getPageSettings()
637: .getAutomaticMultiWindowSupport() == true) {
638: // try to find out whether the pagemap already exists
639: Session session = Session.get();
640: if (session.pageMapForName(getPageMapName(), false) == null) {
641: deletePageMap = true;
642: }
643: parameters.setPageMapName(getPageMapName());
644: }
645: try {
646: Page page = pageCreator.createPage();
647: return page;
648: } finally {
649: parameters.setPageMapName(oldPageMapName);
650: }
651: }
652: }
653:
654: /**
655: * @see wicket.Component#onAttach()
656: */
657: protected void onAttach() {
658: getContent().setOutputMarkupId(true);
659: getContent().setVisible(shown);
660: }
661:
662: /**
663: * @see wicket.markup.html.panel.Panel#onComponentTag(wicket.markup.ComponentTag)
664: */
665: protected void onComponentTag(ComponentTag tag) {
666: super .onComponentTag(tag);
667: tag.put("style", "display:none");
668: }
669:
670: /**
671: * Returns a content component. In case user haven't specified any content
672: * component, it returns an empty WebMarkupContainer.
673: *
674: * @return Content component
675: */
676: private Component getContent() {
677: return get(getContentId());
678: }
679:
680: /**
681: * Returns true if user has added own component to the window.
682: *
683: * @return True if user has added own component to the window, false
684: * otherwise.
685: */
686: private boolean isCustomComponent() {
687: return getContent() != empty;
688: }
689:
690: /**
691: * @see wicket.MarkupContainer#remove(wicket.Component)
692: */
693: public void remove(Component component) {
694: super .remove(component);
695: if (component.getId().equals(getContentId())) {
696: add(empty = new WebMarkupContainer(getContentId()));
697: }
698: }
699:
700: /**
701: * Sets the content of the modal window.
702: *
703: * @param component
704: */
705: public void setContent(Component component) {
706: if (component.getId().equals(getContentId()) == false) {
707: throw new WicketRuntimeException(
708: "Modal window content id is wrong.");
709: }
710: replace(component);
711: }
712:
713: /**
714: * @author Matej Knopp
715: */
716: private class WindowClosedBehavior extends
717: AbstractDefaultAjaxBehavior {
718: private static final long serialVersionUID = 1L;
719:
720: protected void respond(AjaxRequestTarget target) {
721: shown = false;
722:
723: // should we cleanup the pagemap?
724: if (deletePageMap == true) {
725: // get the pagemap
726: Session session = Session.get();
727: PageMap pageMap = session.pageMapForName(
728: getPageMapName(), false);
729:
730: // if there is any remove it
731: if (pageMap != null) {
732: session.removePageMap(pageMap);
733: deletePageMap = false;
734: }
735: }
736:
737: if (windowClosedCallback != null) {
738: windowClosedCallback.onClose(target);
739: }
740: }
741:
742: protected CharSequence getCallbackScript() {
743: return super .getCallbackScript();
744: }
745: };
746:
747: /**
748: * @author Matej Knopp
749: */
750: private class CloseButtonBehavior extends
751: AbstractDefaultAjaxBehavior {
752: private static final long serialVersionUID = 1L;
753:
754: protected void respond(AjaxRequestTarget target) {
755: if (closeButtonCallback == null
756: || closeButtonCallback.onCloseButtonClicked(target) == true) {
757: target.appendJavascript("Wicket.Window.get().close();");
758: }
759: }
760:
761: protected IAjaxCallDecorator getAjaxCallDecorator() {
762: return new CancelEventIfNoAjaxDecorator(super
763: .getAjaxCallDecorator());
764: }
765:
766: protected CharSequence getCallbackScript() {
767: return super .getCallbackScript();
768: }
769: }
770:
771: /**
772: * Returns the markup id of the component.
773: *
774: * @return component id
775: */
776: private String getContentMarkupId() {
777: return getContent().getMarkupId();
778: }
779:
780: /**
781: * Replaces all occurences of " in string with \".
782: *
783: * @param string
784: * String to be escaped.
785: *
786: * @return escaped string
787: */
788: private String escapeQuotes(String string) {
789: if (string.indexOf('"') != -1) {
790: string = Strings.replaceAll(string, "\"", "\\\"")
791: .toString();
792: }
793: return string;
794: }
795:
796: /**
797: * Returns the javascript used to open the window.
798: *
799: * @return javascript that opens the window
800: */
801: private String getWindowOpenJavascript() {
802: AppendingStringBuffer buffer = new AppendingStringBuffer();
803:
804: if (isCustomComponent() == true) {
805: buffer.append("var element = document.getElementById(\""
806: + getContentMarkupId() + "\");\n");
807: }
808:
809: buffer.append("var settings = new Object();\n");
810: buffer.append("settings.minWidth=" + getMinimalWidth() + ";\n");
811: buffer.append("settings.minHeight=" + getMinimalHeight()
812: + ";\n");
813: buffer.append("settings.className=\"" + getCssClassName()
814: + "\";\n");
815: buffer
816: .append("settings.width=\"" + getInitialWidth()
817: + "\";\n");
818:
819: if (isUseInitialHeight() == true
820: || isCustomComponent() == false)
821: buffer.append("settings.height=\"" + getInitialHeight()
822: + "\";\n");
823: else
824: buffer.append("settings.height=null;\n");
825:
826: buffer.append("settings.resizable="
827: + Boolean.toString(isResizable()) + ";\n");
828:
829: if (isResizable() == false) {
830: buffer.append("settings.widthUnit=\"" + getWidthUnit()
831: + "\";\n");
832: buffer.append("settings.heightUnit=\"" + getHeightUnit()
833: + "\";\n");
834: }
835:
836: if (isCustomComponent() == false) {
837: Page page = createPage();
838: if (page == null) {
839: throw new WicketRuntimeException(
840: "Error creating page for modal dialog.");
841: }
842: buffer.append("settings.src=\""
843: + RequestCycle.get().urlFor(page) + "\";\n");
844:
845: if (getPageMapName() != null) {
846: buffer.append("settings.iframeName=\""
847: + getPageMapName() + "\";\n");
848: }
849: } else {
850: buffer.append("settings.element = element;\n");
851: }
852:
853: if (getCookieName() != null) {
854: buffer.append("settings.cookieId=\"" + getCookieName()
855: + "\";\n");
856: }
857:
858: if (getTitle() != null) {
859: buffer.append("settings.title=\""
860: + escapeQuotes(getTitle()) + "\";\n");
861: }
862:
863: if (getMaskType() == MaskType.TRANSPARENT) {
864: buffer.append("settings.mask=\"transparent\";\n");
865: } else if (getMaskType() == MaskType.SEMI_TRANSPARENT) {
866: buffer.append("settings.mask=\"semi-transparent\";\n");
867: }
868:
869: if (closeButtonCallback != null) {
870: CloseButtonBehavior behavior = (CloseButtonBehavior) getBehaviors(
871: CloseButtonBehavior.class).get(0);
872: buffer.append("settings.onCloseButton = function() { "
873: + behavior.getCallbackScript() + "};\n");
874: }
875:
876: WindowClosedBehavior behavior = (WindowClosedBehavior) getBehaviors(
877: WindowClosedBehavior.class).get(0);
878: buffer.append("settings.onClose = function() { "
879: + behavior.getCallbackScript() + " };\n");
880:
881: buffer.append("Wicket.Window.create(settings).show();\n");
882:
883: return buffer.toString();
884: }
885:
886: private boolean deletePageMap = false;
887: private boolean shown = false;
888:
889: // empty container - used when no component is added
890: private WebMarkupContainer empty;
891:
892: private int minimalWidth = 200;
893: private int minimalHeight = 200;
894: private String cssClassName = CSS_CLASS_BLUE;
895: private int initialWidth = 600;
896: private int initialHeight = 400;
897: private boolean useInitialHeight = true;
898: private boolean resizable = true;
899: private String widthUnit = "px";
900: private String heightUnit = "px";
901: private String cookieName;
902: private String title = null;
903: private MaskType maskType = MaskType.SEMI_TRANSPARENT;
904:
905: private String pageMapName = "modal-dialog-pagemap";
906:
907: private PageCreator pageCreator = null;
908: private CloseButtonCallback closeButtonCallback = null;
909: private WindowClosedCallback windowClosedCallback = null;
910: }
|