001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of 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,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.markup.html.link;
018:
019: import org.apache.wicket.Component;
020: import org.apache.wicket.IClusterable;
021: import org.apache.wicket.IPageMap;
022: import org.apache.wicket.Page;
023: import org.apache.wicket.PageMap;
024: import org.slf4j.Logger;
025: import org.slf4j.LoggerFactory;
026:
027: /**
028: * A popup specification can be used as a property of the {@link Link}classes
029: * to specify that the link should be rendered with an onClick javascript event
030: * handler that opens a new window with the links' URL.
031: * <p>
032: * You can 'or' display flags together like this:
033: *
034: * <pre>
035: * new PopupSettings(PopupSettings.RESIZABLE | PopupSettings.SCROLLBARS);
036: * </pre>
037: *
038: * </p>
039: *
040: * @author Jonathan Locke
041: * @author Eelco Hillenius
042: */
043: public class PopupSettings implements IClusterable {
044: /** The log. */
045: private static final Logger log = LoggerFactory
046: .getLogger(PopupSettings.class);
047:
048: private static final long serialVersionUID = 1L;
049:
050: /** Flag to include location bar */
051: public static final int LOCATION_BAR = 1;
052:
053: /** Flag to include menu bar */
054: public static final int MENU_BAR = 2;
055:
056: /** Flag to make popup resizable */
057: public static final int RESIZABLE = 4;
058:
059: /** Flag to include scrollbars */
060: public static final int SCROLLBARS = 8;
061:
062: /** Flag to include status bar */
063: public static final int STATUS_BAR = 16;
064:
065: /** Flag to include location bar */
066: public static final int TOOL_BAR = 32;
067:
068: /** Display flags */
069: private int displayFlags;
070:
071: /** Height of popup window. */
072: private int height = -1;
073:
074: /** Left position of popup window. */
075: private int left = -1;
076:
077: /**
078: * The target to put in JavaScript. This implementation simply refers to the
079: * href element, but clients may want to override this (e.g. when the HTML
080: * element is not an anchor).
081: */
082: private String target = "href";
083:
084: /** Top position of popup window. */
085: private int top = -1;
086:
087: /** Width of popup window. */
088: private int width = -1;
089:
090: /**
091: * The logical name of the window. This can be anything you want, although
092: * you should use alphanumeric characters only (no spaces or punctuation).
093: * If you have a window already open and call window.open a second time
094: * using the same windowName, the first window will be reused rather than
095: * opening a second window.
096: */
097: private String windowName = null;
098:
099: /**
100: * The pagemap name where the page that will be created by this popuplink
101: * will be created in.
102: */
103: private String pageMapName;
104:
105: /**
106: * Construct. If you are not using these popup settings with an external
107: * link - in which case we don't need to know about a page map - you should
108: * use one of the constructors with a {@link PageMap} argument. Typically,
109: * you should put any popup in a seperate page map as Wicket holds
110: * references to a limited number of pages/ versions only. If you don't put
111: * your popup in a seperate page map, the user might get page expired
112: * exceptions when getting back to the main window again.
113: */
114: public PopupSettings() {
115: }
116:
117: /**
118: * Construct.
119: *
120: * @param displayFlags
121: * Display flags
122: */
123: public PopupSettings(final int displayFlags) {
124: this .displayFlags = displayFlags;
125: }
126:
127: /**
128: * Construct.
129: *
130: * @param pagemap
131: * The pagemap where this popup must be in. Typically, you should
132: * put any popup in a seperate page map as Wicket holds
133: * references to a limited number of pages/ versions only. If you
134: * don't put your popup in a seperate page map, the user might
135: * get page expired exceptions when getting back to the main
136: * window again.
137: */
138: public PopupSettings(IPageMap pagemap) {
139: this .pageMapName = pagemap.getName();
140: this .windowName = pageMapName;
141: }
142:
143: /**
144: * Construct.
145: *
146: * @param pagemap
147: * The pagemap where this popup must be in. Typically, you should
148: * put any popup in a seperate page map as Wicket holds
149: * references to a limited number of pages/ versions only. If you
150: * don't put your popup in a seperate page map, the user might
151: * get page expired exceptions when getting back to the main
152: * window again.
153: * @param displayFlags
154: * Display flags
155: */
156: public PopupSettings(IPageMap pagemap, final int displayFlags) {
157: this .displayFlags = displayFlags;
158: this .pageMapName = pagemap.getName();
159: this .windowName = pageMapName;
160: }
161:
162: /**
163: * Get the onClick javascript event handler.
164: *
165: * @return the onClick javascript event handler
166: */
167: public String getPopupJavaScript() {
168: String windowTitle = windowName;
169:
170: if (windowTitle == null) {
171: windowTitle = "";
172: } else {
173: // Fix for IE bug.
174: windowTitle = windowTitle.replace(':', '_');
175: }
176:
177: StringBuffer script = new StringBuffer("var w = window.open("
178: + target + ", '").append(windowTitle).append("', '");
179:
180: script.append("scrollbars=").append(flagToString(SCROLLBARS));
181: script.append(",location=").append(flagToString(LOCATION_BAR));
182: script.append(",menuBar=").append(flagToString(MENU_BAR));
183: script.append(",resizable=").append(flagToString(RESIZABLE));
184: script.append(",status=").append(flagToString(STATUS_BAR));
185: script.append(",toolbar=").append(flagToString(TOOL_BAR));
186:
187: if (width != -1) {
188: script.append(",width=").append(width);
189: }
190:
191: if (height != -1) {
192: script.append(",height=").append(height);
193: }
194:
195: if (left != -1) {
196: script.append(",left=").append(left);
197: }
198:
199: if (top != -1) {
200: script.append(",top=").append(top);
201: }
202:
203: script.append("'); if(w.blur) w.focus();").append(
204: " return false;");
205:
206: return script.toString();
207: }
208:
209: /**
210: * Sets the popup window height.
211: *
212: * @param popupHeight
213: * the popup window height.
214: * @return This
215: */
216: public PopupSettings setHeight(int popupHeight) {
217: this .height = popupHeight;
218: return this ;
219: }
220:
221: /**
222: * Sets the left position of the popup window.
223: *
224: * @param popupPositionLeft
225: * the left position of the popup window.
226: * @return This
227: */
228: public PopupSettings setLeft(int popupPositionLeft) {
229: this .left = popupPositionLeft;
230: return this ;
231: }
232:
233: /**
234: * Sets the target of the link. The default implementation simply refers to
235: * the href element, but clients may want to override this (e.g. when the
236: * HTML element is not an anchor) by setting the target explicitly.
237: *
238: * @param target
239: * the target of the link
240: */
241: public void setTarget(String target) {
242: this .target = target;
243: }
244:
245: /**
246: * Sets the top position of the popup window.
247: *
248: * @param popupPositionTop
249: * the top position of the popup window.
250: * @return This
251: */
252: public PopupSettings setTop(int popupPositionTop) {
253: this .top = popupPositionTop;
254: return this ;
255: }
256:
257: /**
258: * Sets the popup window width.
259: *
260: * @param popupWidth
261: * the popup window width.
262: * @return This
263: */
264: public PopupSettings setWidth(int popupWidth) {
265: this .width = popupWidth;
266: return this ;
267: }
268:
269: /**
270: * Sets the window name. The logical name of the window. This can be
271: * anything you want, although you should use alphanumeric characters only
272: * (no spaces or punctuation). If you have a window already open and call
273: * window.open a second time using the same windowName, the first window
274: * will be reused rather than opening a second window
275: *
276: * @param popupWindowName
277: * window name.
278: * @return This
279: */
280: public PopupSettings setWindowName(String popupWindowName) {
281: if (popupWindowName != null) {
282: this .windowName = popupWindowName;
283: if (pageMapName != null
284: && (!pageMapName.equals(popupWindowName))) {
285: log
286: .warn("the page map and window name should be the same. The page map was "
287: + pageMapName
288: + ", and the requested window name is "
289: + popupWindowName
290: + "; changing the page map to "
291: + popupWindowName);
292: }
293: this .pageMapName = popupWindowName;
294: }
295: return this ;
296: }
297:
298: /**
299: * @param flag
300: * The flag to test
301: * @return Yes or no depending on whether the flag is set
302: */
303: private String flagToString(final int flag) {
304: return (this .displayFlags & flag) != 0 ? "yes" : "no";
305: }
306:
307: /**
308: * Gets the pagemap where the popup page must be created in.
309: *
310: * @return The pagemap where the popup page must be created in
311: * @deprecated will be removed in Wicket 2.0; use
312: * {@link #getPageMap(Component)} instead
313: */
314: public IPageMap getPageMap() {
315: if (pageMapName != null) {
316: return PageMap.forName(pageMapName);
317: } else {
318: throw new UnsupportedOperationException(
319: "this method can only work when a page map is set. Either call"
320: + " getPageMap(Component) or set the page map");
321: }
322: }
323:
324: /**
325: * Gets the pagemap where the popup page must be created in.
326: *
327: * @param callee
328: * Calling component
329: * @return The pagemap where the popup page must be created in
330: */
331: public IPageMap getPageMap(Component callee) {
332: if (pageMapName != null) {
333: return PageMap.forName(pageMapName);
334: } else {
335: if (callee == null) {
336: throw new IllegalArgumentException(
337: "when the page map is not set, argument callee may not be null");
338: }
339: Page page = callee.getPage();
340: if (page == null) {
341: throw new IllegalStateException(
342: callee
343: + " is not yet set on a page; if you want to use this method "
344: + "without a page map being set, argument callee must be not null "
345: + "and added to a page");
346: }
347: return page.getPageMap();
348: }
349: }
350: }
|