0001: /*
0002: * MyGWT Widget Library
0003: * Copyright(c) 2007, MyGWT.
0004: * licensing@mygwt.net
0005: *
0006: * http://mygwt.net/license
0007: */
0008: package net.mygwt.ui.client;
0009:
0010: import net.mygwt.ui.client.MyGWT;
0011: import net.mygwt.ui.client.Style;
0012: import net.mygwt.ui.client.impl.MyDOMImpl;
0013: import net.mygwt.ui.client.util.Point;
0014: import net.mygwt.ui.client.util.Rectangle;
0015: import net.mygwt.ui.client.util.Region;
0016: import net.mygwt.ui.client.util.Size;
0017: import net.mygwt.ui.client.widget.WidgetContainer;
0018:
0019: import com.google.gwt.core.client.GWT;
0020: import com.google.gwt.user.client.DOM;
0021: import com.google.gwt.user.client.Element;
0022: import com.google.gwt.user.client.Window;
0023: import com.google.gwt.user.client.ui.HTML;
0024: import com.google.gwt.user.client.ui.RootPanel;
0025:
0026: /**
0027: * Provides additional static methods that allow you to manipulate the browser's
0028: * Document Object Model (DOM).
0029: *
0030: * @see DOM
0031: */
0032: public class MyDOM {
0033:
0034: private static final MyDOMImpl impl = (MyDOMImpl) GWT
0035: .create(MyDOMImpl.class);
0036: private static boolean isVisibleBox;
0037: private static int scrollBarHeight = Style.DEFAULT;
0038: private static int AUTO_ID = 0;
0039: private static int Z_INDEX = 1000;
0040:
0041: static {
0042: MyGWT.init();
0043: init();
0044: isVisibleBox = isVisibleBoxInternal();
0045: }
0046:
0047: /**
0048: * Adds the event type to the element's sunk events.
0049: *
0050: * @param elem the element
0051: * @param event the events to add
0052: */
0053: public static void addEventsSunk(Element elem, int event) {
0054: int bits = DOM.getEventsSunk(elem);
0055: DOM.sinkEvents(elem, bits | event);
0056: }
0057:
0058: /**
0059: * Adds a style name to the element.
0060: *
0061: * @param elem the element
0062: * @param style the style to be added
0063: */
0064: public static void addStyleName(Element elem, String style) {
0065: if (style != null) {
0066: setStyleName(elem, style, true);
0067: }
0068: }
0069:
0070: /**
0071: * Aligns the element with another element relative to the specified anchor
0072: * points. Two values from the table below should be passed separated by a
0073: * dash, the first value is used as the element's anchor point, and the second
0074: * value is used as the target's anchor point.
0075: * <p>
0076: * In addition to the anchor points, the position parameter also supports the
0077: * "?" character. If "?" is passed at the end of the position string, the
0078: * element will attempt to align as specified, but the position will be
0079: * adjusted to constrain to the viewport if necessary. Note that the element
0080: * being aligned might be swapped to align to a different position than that
0081: * specified in order to enforce the viewport constraints.
0082: * </p>
0083: * <dl>
0084: * <dt>Following are all of the supported anchor positions:</dt>
0085: * </dl>
0086: * <code><pre>
0087: * Value Description
0088: * ----- -----------------------------
0089: * tl The top left corner (default)
0090: * t The center of the top edge
0091: * tr The top right corner
0092: * l The center of the left edge
0093: * c In the center of the element
0094: * r The center of the right edge
0095: * bl The bottom left corner
0096: * b The center of the bottom edge
0097: * br The bottom right corner
0098: * </code></pre>
0099: *
0100: * @param elem the element to be aligned
0101: * @param align the element to align to
0102: * @param pos the position to align to
0103: * @param offsets the offsets or <code>null</code>
0104: */
0105: public static void alignTo(Element elem, Element align, String pos,
0106: int[] offsets) {
0107: Point p = getAlignToXY(elem, align, pos, offsets);
0108: setXY(elem, p);
0109: }
0110:
0111: /**
0112: * Sets multiple style on the given element.
0113: *
0114: * @param elem the element
0115: * @param styles the styles
0116: */
0117: public native static void applyStyles(Element elem, String styles) /*-{
0118: var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
0119: var matches;
0120: while ((matches = re.exec(styles)) != null){
0121: elem.style[matches[1]] = matches[2];
0122: }
0123: }-*/;
0124:
0125: /**
0126: * Centers the element.
0127: *
0128: * @param elem the element
0129: */
0130: public static void center(Element elem) {
0131: Size size = getViewportSize();
0132: int width = size.width;
0133: int height = size.height;
0134: int w = getWidth(elem);
0135: int h = getHeight(elem);
0136: int left = (width / 2) - (w / 2);
0137: int top = (height / 2) - (h / 2);
0138: Element p = DOM.getParent(elem);
0139: if (p != null) {
0140: left += getScrollLeft(p);
0141: top += getScrollTop(p);
0142: }
0143: setLeft(elem, left);
0144: setTop(elem, top);
0145: }
0146:
0147: /**
0148: * Clips overflow on the element.
0149: */
0150: public static void clip(Element elem) {
0151: DOM.setStyleAttribute(elem, "overflow", "hidden");
0152: DOM.setStyleAttribute(elem, "overflowX", "hidden");
0153: DOM.setStyleAttribute(elem, "overflowY", "hidden");
0154: }
0155:
0156: /**
0157: * Creates an element form the given markup.
0158: *
0159: * @param html the markup
0160: * @return the new element
0161: */
0162: public static Element create(String html) {
0163: Element div = DOM.createDiv();
0164: MyDOM.setInnerHTML(div, html);
0165: Element firstChild = DOM.getFirstChild(div);
0166: // support text node creation
0167: return (firstChild != null) ? firstChild : div;
0168: }
0169:
0170: /**
0171: * Disable the element.
0172: */
0173: public native static void disable(Element elem) /*-{
0174: elem.disabled = true;
0175: }-*/;
0176:
0177: /**
0178: * Enables and disables the browsers default context menu for the specified
0179: * element.A circular reference will be created when disabling text selection.
0180: * Disabling should be cleared when the element is detached. See the
0181: * <code>Component</code> source for an example.
0182: *
0183: * @param elem the element
0184: * @param disable <code>true</code> to disable
0185: */
0186: public static native void disableContextMenu(Element elem,
0187: boolean disable) /*-{
0188: if (disable) {
0189: elem.oncontextmenu = function() { return false};
0190: } else {
0191: elem.oncontextmenu = null;
0192: }
0193: }-*/;
0194:
0195: /**
0196: * Enables or disables text selection for the element. A circular reference
0197: * will be created when disabling text selection. Disabling should be cleared
0198: * when the element is detached. See the <code>Component</code> source for
0199: * an example.
0200: *
0201: * @param elem the element
0202: * @param disable <code>true</code> to disable
0203: */
0204: public static void disableTextSelection(Element elem,
0205: boolean disable) {
0206: setStyleName(elem, "my-no-selection", disable);
0207: disableTextSelectInternal(elem, disable);
0208: }
0209:
0210: /**
0211: * Enable the element.
0212: *
0213: * @param elem the element
0214: */
0215: public native static void enable(Element elem) /*-{
0216: elem.disabled = false;
0217: }-*/;
0218:
0219: /**
0220: * Removes script and javascript code from the given html markup.
0221: *
0222: * @param html the html
0223: * @return the updated html
0224: */
0225: public native static String escapeHTML(String html) /*-{
0226: return $wnd.escapeHTML(html);
0227: }-*/;
0228:
0229: /**
0230: * Returns the first child with a matching style name.
0231: *
0232: * @param style the style
0233: * @param elem the element
0234: * @return the matching element or <code>null</code>
0235: */
0236: public native static Element findChild(String style, Element elem) /*-{
0237: var n = elem.getElementsByTagName("*");
0238: for (var i=0; i < n.length; i++) {
0239: var e = n[i];
0240: if ((" " + e.className + " ").indexOf(" " + style + " ")>-1) {
0241: return e;
0242: }
0243: }
0244: return null;
0245: }-*/;
0246:
0247: /**
0248: * Finds the first parent element with the given style name.
0249: *
0250: * @param style the style name
0251: * @param elem the start element
0252: * @param maxDepth the max amount of parent to search
0253: * @return the matching element
0254: */
0255: public static Element findParent(String style, Element elem,
0256: int maxDepth) {
0257: Element p = elem;
0258: int depth = 0;
0259: while (p != null && depth < maxDepth) {
0260: String cls = DOM.getElementProperty(p, "className");
0261: String[] classes = cls.split(" ");
0262: for (int i = 0; i < classes.length; i++) {
0263: if (style.equals(classes[i])) {
0264: return p;
0265: }
0266: }
0267: depth++;
0268: p = DOM.getParent(p);
0269: }
0270: return null;
0271:
0272: }
0273:
0274: /**
0275: * Finds the first parent element with an id.
0276: *
0277: * @param elem the start element
0278: * @param maxDepth the max amount of parent to search
0279: * @return the matching element
0280: */
0281: public static Element findParentWithId(Element elem, int maxDepth) {
0282: Element p = elem;
0283: int depth = 0;
0284: while (p != null && depth < maxDepth) {
0285: String id = DOM.getElementProperty(p, "id");
0286: if (id != null && !id.equals("")) {
0287: return p;
0288: }
0289: depth++;
0290: p = DOM.getParent(p);
0291: }
0292: return null;
0293:
0294: }
0295:
0296: /**
0297: * Returns the x,y coordinates to align this element with another element. See
0298: * {@link #alignTo} for more info on the supported position values.
0299: *
0300: * @param elem the align to be aligned
0301: * @param align the element to align to
0302: * @param pos the position, see alignTo
0303: * @param offsets the optional offsets
0304: * @return the the point
0305: */
0306: public static Point getAlignToXY(Element elem, Element align,
0307: String pos, int[] offsets) {
0308: if (pos == null) {
0309: pos = "tl-bl";
0310: }
0311:
0312: String[] m = pos.split("-");
0313:
0314: String p1 = m[0];
0315: String p2 = m[1];
0316:
0317: Point a1 = getAnchorXY(elem, p1, true);
0318: Point a2 = getAnchorXY(align, p2, false);
0319:
0320: if (offsets == null) {
0321: offsets = new int[] { 0, 0 };
0322: }
0323:
0324: int x = a2.x - a1.x + offsets[0];
0325: int y = a2.y - a1.y + offsets[1];
0326:
0327: if (m.length == 3) {
0328: int w = getComputedWidth(elem);
0329: int h = getHeight(elem);
0330:
0331: int dw = Window.getClientWidth() - 5;
0332: int dh = Window.getClientHeight() - 5;
0333:
0334: Region r = getRegion(elem);
0335:
0336: char p1y = p1.charAt(0), p1x = p1.charAt(p1.length() - 1);
0337: char p2y = p2.charAt(0), p2x = p2.charAt(p2.length() - 1);
0338: boolean swapY = ((p1y == 't' && p2y == 'b') || (p1y == 'b' && p2y == 't'));
0339: boolean swapX = ((p1x == 'r' && p2x == 'l') || (p1x == 'l' && p2x == 'r'));
0340:
0341: int scrollX = getBodyScrollLeft();
0342: int scrollY = getBodyScrollTop();
0343:
0344: if ((x + w) > dw + scrollX) {
0345: x = swapX ? r.left - w : dw + scrollX - w;
0346: }
0347: if (x < scrollX) {
0348: x = swapX ? r.right : scrollX;
0349: }
0350: if ((y + h) > dh + scrollY) {
0351: y = swapY ? r.top - h : dh + scrollY - h;
0352: }
0353: if (y < scrollY) {
0354: y = swapY ? r.bottom : scrollY;
0355: }
0356: }
0357:
0358: return new Point(x, y);
0359: }
0360:
0361: /**
0362: * Returns the x,y coordinates specified by the anchor position on the
0363: * element.
0364: *
0365: * @param elem the element
0366: * @param anchor the specified anchor position (defaults to "c"). See
0367: * {@link #alignTo} for details on supported anchor positions.
0368: * @param local <code>true</code> to get the local (element
0369: * top/left-relative) anchor position instead of page coordinates
0370: * @return the position
0371: */
0372: public static Point getAnchorXY(Element elem, String anchor,
0373: boolean local) {
0374: int w = getWidth(elem);
0375: int h = getHeight(elem);
0376:
0377: int x = 0;
0378: int y = 0;
0379:
0380: if (anchor == null) {
0381: anchor = "c";
0382: }
0383:
0384: if (anchor.equalsIgnoreCase("c")) {
0385: x = (int) Math.round(x * .5);
0386: y = (int) Math.round(h * .5);
0387: } else if (anchor.equalsIgnoreCase("t")) {
0388: x = (int) Math.round(x * .5);
0389: y = 0;
0390: } else if (anchor.equalsIgnoreCase("l")) {
0391: x = 0;
0392: y = (int) Math.round(h * .5);
0393: } else if (anchor.equalsIgnoreCase("r")) {
0394: x = w;
0395: y = (int) Math.round(h * .5);
0396: } else if (anchor.equalsIgnoreCase("b")) {
0397: x = (int) Math.round(x * .5);
0398: y = h;
0399: } else if (anchor.equalsIgnoreCase("tl")) {
0400: x = 0;
0401: y = 0;
0402: } else if (anchor.equalsIgnoreCase("bl")) {
0403: x = 0;
0404: y = h;
0405: } else if (anchor.equalsIgnoreCase("br")) {
0406: x = w;
0407: y = h;
0408: } else if (anchor.equalsIgnoreCase("tr")) {
0409: x = w;
0410: y = 0;
0411: }
0412:
0413: if (local) {
0414: return new Point(x, y);
0415: }
0416:
0417: Point p = getXY(elem);
0418: p.x += x;
0419: p.y += y;
0420: return p;
0421: }
0422:
0423: /**
0424: * Gets any named property from an element, as a string.
0425: *
0426: * @param elem the element whose attribute is to be retrieved
0427: * @param property the name of the property
0428: * @return the property value
0429: */
0430: public static native String getAnyElementProperty(Element elem,
0431: String property)/*-{
0432: return elem.getAttribute(property);
0433: }-*/;
0434:
0435: /**
0436: * Returns the body element.
0437: *
0438: * @return the body
0439: */
0440: public static native Element getBody() /*-{
0441: return $doc.body;
0442: }-*/;
0443:
0444: /**
0445: * Returns the body elements horizontal scroll.
0446: *
0447: * @return the scroll amount in pixels
0448: */
0449: public static native int getBodyScrollLeft() /*-{
0450: return $doc.body.scrollLeft;
0451: }-*/;
0452:
0453: /**
0454: * Return the body elements vertical scroll.
0455: *
0456: * @return the scroll amount in pixels
0457: */
0458: public static native int getBodyScrollTop() /*-{
0459: return $doc.body.scrollTop;
0460: }-*/;
0461:
0462: /**
0463: * Returns the total border width of the specified sides.
0464: *
0465: * @param elem the element
0466: * @param sides can be any combination of LEFT, RIGHT, TOP, BOTTOM
0467: * @return the width of the sides passed added together
0468: */
0469: public static int getBorderWidth(Element elem, int sides) {
0470: int width = 0;
0471: if ((sides & Style.LEFT) != 0) {
0472: width += getIntStyleAttribute(elem, "borderLeftWidth");
0473: }
0474: if ((sides & Style.RIGHT) != 0) {
0475: width += getIntStyleAttribute(elem, "borderRightWidth");
0476: }
0477: if ((sides & Style.TOP) != 0) {
0478: width += getIntStyleAttribute(elem, "borderTopWidth");
0479: }
0480: if ((sides & Style.BOTTOM) != 0) {
0481: width += getIntStyleAttribute(elem, "borderBottomWidth");
0482: }
0483: return width;
0484: }
0485:
0486: /**
0487: * Returns the bottom Y coordinate of the element (element Y position +
0488: * element height).
0489: *
0490: * @param elem the element
0491: * @param local <code>true</code> to get the local css position instead of
0492: * page coordinate
0493: * @return the bottom value
0494: */
0495: public static int getBottom(Element elem, boolean local) {
0496: if (!local) {
0497: return getY(elem) + getHeight(elem);
0498: } else {
0499: return getTop(elem) + getHeight(elem);
0500: }
0501: }
0502:
0503: /**
0504: * Returns the element's bounds.
0505: *
0506: * @param elem the element
0507: * @return the elements bounds
0508: */
0509: public static Rectangle getBounds(Element elem) {
0510: return getBounds(elem, false);
0511: }
0512:
0513: /**
0514: * Returns the element's bounds.
0515: *
0516: * @param elem the element
0517: * @param content <code>true</code> to adjust for box model issues
0518: * @return the elements bounds
0519: */
0520: public static Rectangle getBounds(Element elem, boolean content) {
0521: int x = DOM.getAbsoluteLeft(elem);
0522: int y = DOM.getAbsoluteTop(elem);
0523: int width = getWidth(elem);
0524: int height = getHeight(elem);
0525: if (content) {
0526: x += getBorderWidth(elem, Style.LEFT);
0527: y += getBorderWidth(elem, Style.TOP);
0528: width -= getDecorationWidth(elem, Style.LEFT | Style.RIGHT);
0529: height -= getDecorationWidth(elem, Style.TOP | Style.BOTTOM);
0530: }
0531: width = Math.max(0, width);
0532: height = Math.max(0, height);
0533: return new Rectangle(x, y, width, height);
0534: }
0535:
0536: /**
0537: * Returns either the offsetHeight or the height of this element based on it's
0538: * CSS height.
0539: *
0540: * @param elem the element
0541: * @return the height
0542: */
0543: public static int getComputedHeight(Element elem) {
0544: int h = getHeight(elem);
0545: if (h == 0) {
0546: h = DOM.getIntStyleAttribute(elem, "height");
0547: }
0548: return h;
0549: }
0550:
0551: /**
0552: * Returns either the offsetWidth or the width of this element based on it's
0553: * CSS width.
0554: *
0555: * @param elem the element
0556: * @return the width
0557: */
0558: public static int getComputedWidth(Element elem) {
0559: int w = getWidth(elem);
0560: if (w == 0) {
0561: w = DOM.getIntStyleAttribute(elem, "width");
0562: }
0563: return w;
0564: }
0565:
0566: /**
0567: * Returns the total width of borders and padding for the specified sides.
0568: *
0569: * @param elem the element
0570: * @param sides can be any combination of LEFT, RIGHT, TOP, BOTTOM
0571: * @return the width in pixels
0572: */
0573: public static int getDecorationWidth(Element elem, int sides) {
0574: int width = 0;
0575: width += getBorderWidth(elem, sides);
0576: width += getPaddingWidth(elem, sides);
0577: return width;
0578: }
0579:
0580: /**
0581: * Returns the document element.
0582: *
0583: * @return the docuemnt
0584: */
0585: public static native Element getDocument() /*-{
0586: return $doc;
0587: }-*/;
0588:
0589: public static native Element getHead() /*-{
0590: return $doc.getElementsByTagName('head')[0];
0591: }-*/;
0592:
0593: /**
0594: * Returns the element's offset height in pixels. This is the total height of
0595: * the object, including decorations such as border, margin, and padding.
0596: *
0597: * @param elem the element
0598: * @return the element's offset height
0599: */
0600: public static int getHeight(Element elem) {
0601: return DOM.getElementPropertyInt(elem, "offsetHeight");
0602: }
0603:
0604: /**
0605: * Returns the element's height.
0606: *
0607: * @param elem the element
0608: * @param contentHeight <code>true</code> to get the height minus borders
0609: * and padding
0610: * @return the element's height
0611: */
0612: public static int getHeight(Element elem, boolean contentHeight) {
0613: int h = DOM.getElementPropertyInt(elem, "offsetHeight");
0614: if (contentHeight & !isVisibleBox) {
0615: h -= getDecorationWidth(elem, Style.TOP | Style.BOTTOM);
0616: }
0617: return h;
0618: }
0619:
0620: /**
0621: * Returns the element's id.
0622: *
0623: * @param elem the element
0624: *
0625: * @return the id
0626: */
0627: public static String getId(Element elem) {
0628: return DOM.getElementProperty(elem, "id");
0629: }
0630:
0631: /**
0632: * Returns the element's style attribute value.
0633: *
0634: * @param elem the element
0635: * @param attr the attribute name
0636: * @return the attribute value
0637: */
0638: public static int getIntStyleAttribute(Element elem, String attr) {
0639: String s = impl.getStyle(elem, attr);
0640: try {
0641: if (s.indexOf("px") != -1) {
0642: s = s.substring(0, s.indexOf("px"));
0643: }
0644: int i = Integer.parseInt(s);
0645: return i;
0646: } catch (Exception e) {
0647: }
0648: return 0;
0649: }
0650:
0651: /**
0652: * Returns the left X coordinate.
0653: *
0654: * @param elem the element
0655: * @return the left value
0656: */
0657: public static int getLeft(Element elem) {
0658: return DOM.getIntStyleAttribute(elem, "left");
0659: }
0660:
0661: /**
0662: * Returns the total padding width of the given sides.
0663: *
0664: * @param elem the element
0665: * @param sides can be any combination of LEFT, RIGHT, TOP, BOTTOM
0666: * @return the padding
0667: */
0668: public static int getPaddingWidth(Element elem, int sides) {
0669: int width = 0;
0670: if ((sides & Style.LEFT) != 0) {
0671: width += DOM.getIntStyleAttribute(elem, "paddingLeft");
0672: }
0673: if ((sides & Style.RIGHT) != 0) {
0674: width += DOM.getIntStyleAttribute(elem, "paddingRight");
0675: }
0676: if ((sides & Style.TOP) != 0) {
0677: width += DOM.getIntStyleAttribute(elem, "paddingTop");
0678: }
0679: if ((sides & Style.BOTTOM) != 0) {
0680: width += DOM.getIntStyleAttribute(elem, "paddingBottom");
0681: }
0682: return width;
0683: }
0684:
0685: /**
0686: * Returns the region of the given element. The element must be part of the
0687: * DOM tree to have a region.
0688: *
0689: * @param elem the element
0690: * @return a region containing top, left, bottom, right
0691: */
0692: public static Region getRegion(Element elem) {
0693: Rectangle bounds = getBounds(elem, false);
0694: Region r = new Region();
0695: r.left = bounds.x;
0696: r.top = bounds.y;
0697: r.right = r.left + bounds.width;
0698: r.bottom = r.top + bounds.height;
0699: return r;
0700: }
0701:
0702: /**
0703: * Returns the right X coordinate of the element (element X position + element
0704: * width).
0705: *
0706: * @param elem the element
0707: * @param local <code>true</code> to get the local css position instead of
0708: * page coordinate
0709: * @return the right value
0710: */
0711: public static int getRight(Element elem, boolean local) {
0712: if (!local) {
0713: return getX(elem) + getWidth(elem);
0714: } else {
0715: return getLeft(elem) + getWidth(elem);
0716: }
0717: }
0718:
0719: /**
0720: * Returns the width of the scroll bar.
0721: *
0722: * @return the scroll bar width
0723: */
0724: public static int getScrollBarWidth() {
0725: if (scrollBarHeight == Style.DEFAULT) {
0726: scrollBarHeight = getScrollBarWidthInternal();
0727: }
0728: return scrollBarHeight;
0729: }
0730:
0731: /**
0732: * Returns the element's scroll height.
0733: *
0734: * @param elem the element
0735: * @return the scroll height
0736: */
0737: public native static int getScrollHeight(Element elem) /*-{
0738: return elem.scrollHeight;
0739: }-*/;
0740:
0741: /**
0742: * Returns the element's horizontal scroll position.
0743: *
0744: * @param elem the element
0745: * @return the scroll amount in pixels
0746: */
0747: public static int getScrollLeft(Element elem) {
0748: return DOM.getElementPropertyInt(elem, "scrollLeft");
0749: }
0750:
0751: /**
0752: * Returns the element's vertical scroll position.
0753: *
0754: * @param elem the element
0755: * @return the scroll amount in pixel
0756: */
0757: public static int getScrollTop(Element elem) {
0758: return DOM.getElementPropertyInt(elem, "scrollTop");
0759: }
0760:
0761: /**
0762: * Returns the element's scroll width.
0763: *
0764: * @param elem the element
0765: * @return the scroll width
0766: */
0767: public native static int getScrollWidth(Element elem) /*-{
0768: return elem.scrollWidth;
0769: }-*/;
0770:
0771: /**
0772: * Returns the elements size.
0773: *
0774: * @param elem the element
0775: * @return the size
0776: */
0777: public static Size getSize(Element elem) {
0778: return new Size(getWidth(elem), getHeight(elem));
0779: }
0780:
0781: public static String getStyleName(Element elem) {
0782: return DOM.getElementProperty(elem, "className");
0783: }
0784:
0785: /**
0786: * Returns the element's sub child.
0787: *
0788: * @param elem the element
0789: * @param depth the child node depth
0790: * @return the child element
0791: */
0792: public static Element getSubChild(Element elem, int depth) {
0793: Element child = elem;
0794: while (depth-- > 0) {
0795: child = DOM.getChild(child, 0);
0796: }
0797: return child;
0798: }
0799:
0800: /**
0801: * Returns the top Y coordinate.
0802: *
0803: * @param elem the element
0804: * @return the top value
0805: */
0806: public static int getTop(Element elem) {
0807: return DOM.getIntStyleAttribute(elem, "top");
0808: }
0809:
0810: /**
0811: * Returns an unique id.
0812: *
0813: * @return the id
0814: */
0815: public static String getUniqueID() {
0816: return "my-" + AUTO_ID++;
0817: }
0818:
0819: /**
0820: * Returns the the "value" attribute.
0821: *
0822: * @param elem the element
0823: * @return the value
0824: */
0825: public static String getValue(Element elem) {
0826: return DOM.getElementProperty(elem, "value");
0827: }
0828:
0829: /**
0830: * Returns the viewports size.
0831: *
0832: * @return the size
0833: */
0834: public static native Size getViewportSize() /*-{
0835: var vw;
0836: var vh;
0837: if (typeof $wnd.innerWidth != 'undefined') {
0838: vw = $wnd.innerWidth;
0839: vh = $wnd.innerHeight;
0840: } else if (typeof $doc.documentElement != 'undefined'
0841: && typeof $doc.documentElement.clientWidth !=
0842: 'undefined' && $doc.documentElement.clientWidth != 0) {
0843: vw = document.documentElement.clientWidth;
0844: vh = $wnd.innerHeight;
0845: } else {
0846: vw = $doc.getElementsByTagName('body')[0].clientWidth;
0847: vh = $doc.getElementsByTagName('body')[0].clientHeight;
0848: }
0849: var size = @net.mygwt.ui.client.util.Size::newInstance(II)(vw, vh);
0850: return size;
0851:
0852: }-*/;
0853:
0854: /**
0855: * Returns the element's offset width in pixels. This is the total width of
0856: * the element, including decorations such as border, margin, and padding.
0857: *
0858: * @param elem the element
0859: * @return the element's offset width
0860: */
0861: public static int getWidth(Element elem) {
0862: return DOM.getElementPropertyInt(elem, "offsetWidth");
0863: }
0864:
0865: /**
0866: * Returns the element's width.
0867: *
0868: * @param elem the element
0869: * @param contentWidth <code>true</code> to get the width minus borders and
0870: * padding
0871: * @return the element's width
0872: */
0873: public static int getWidth(Element elem, boolean contentWidth) {
0874: int w = getWidth(elem);
0875: if (contentWidth) {
0876: w -= getDecorationWidth(elem, Style.LEFT | Style.RIGHT);
0877: }
0878: return w;
0879: }
0880:
0881: /**
0882: * Gets the current X position of the element based on page coordinates.
0883: * Element must be part of the DOM tree to have page coordinates.
0884: *
0885: * @param elem the element
0886: * @return the x coordinate
0887: */
0888: public static int getX(Element elem) {
0889: return DOM.getAbsoluteLeft(elem);
0890: }
0891:
0892: /**
0893: * Returns the current position of the element based on page coordinates.
0894: * Element must be part of the DOM tree to have page coordinates.
0895: *
0896: * @param elem the element
0897: * @return the current location
0898: */
0899: public static Point getXY(Element elem) {
0900: return new Point(getX(elem), getY(elem));
0901: }
0902:
0903: /**
0904: * Returns the current Y position of the element based on page coordinates.
0905: * Element must be part of the DOM tree to have page coordinates.
0906: *
0907: * @param elem the element
0908: * @return the y coordinate
0909: */
0910: public static int getY(Element elem) {
0911: return DOM.getAbsoluteTop(elem);
0912: }
0913:
0914: /**
0915: * Returns the current max z-index.
0916: *
0917: * @return the z-index
0918: */
0919: public static int getZIndex() {
0920: return ++Z_INDEX;
0921: }
0922:
0923: /**
0924: * Checks if the specified CSS class exists on this element's DOM node.
0925: *
0926: * @param elem the element
0927: * @param className the CSS class to check for
0928: * @return <code>true</code> if the class exists, else <code>false</code>
0929: */
0930: public static boolean hasClass(Element elem, String className) {
0931: String[] classes = getStyleName(elem).split(" ");
0932: for (int i = 0; i < classes.length; i++) {
0933: if (className.equals(classes[i])) {
0934: return true;
0935: }
0936: }
0937: return false;
0938: }
0939:
0940: /**
0941: * Inserts this element after the passed element in the DOM.
0942: *
0943: * @param elem the element
0944: * @param after the element to insert after
0945: */
0946: public native static void insertAfter(Element elem, Element after) /*-{
0947: after.parentNode.insertBefore(elem, after.nextSibling);
0948: }-*/;
0949:
0950: /**
0951: * Inserts the element before the passed element in the DOM.
0952: *
0953: * @param elem the element to be inserted
0954: * @param before the element to insert before
0955: */
0956: public native static void insertBefore(Element elem, Element before) /*-{
0957: before.parentNode.insertBefore(elem, before);
0958: }-*/;
0959:
0960: /**
0961: * Returns <code>true</code> if the horizontal scroll bar is present
0962: *
0963: * @param container the container element
0964: * @return the vertical scroll bar state
0965: */
0966: public static boolean isHScrollBarShowing(Element container) {
0967: int orig = MyDOM.getScrollTop(container);
0968: if (orig > 0) {
0969: return true;
0970: }
0971: setScrollLeft(container, 10);
0972: if (MyDOM.getScrollLeft(container) > 0) {
0973: setScrollLeft(container, orig);
0974: return true;
0975: }
0976: setScrollLeft(container, orig);
0977: return false;
0978: }
0979:
0980: /**
0981: * Returns <code>true</code> if the element is visible using the css
0982: * 'visibiliy' attribute.
0983: *
0984: * @param elem the element
0985: * @return the visible state
0986: */
0987: public static boolean isVisibility(Element elem) {
0988: return !DOM.getStyleAttribute(elem, "visibility").equals(
0989: "hidden");
0990: }
0991:
0992: /**
0993: * Checks whether the element is currently visible using both visibility and
0994: * display properties.
0995: *
0996: * @return <code>true</code> if the element is currently visible, else
0997: * <code>false</code>
0998: */
0999: public static boolean isVisible(Element elem) {
1000: if (DOM.getStyleAttribute(elem, "visibility").equals("hidden")) {
1001: return false;
1002: } else if (DOM.getStyleAttribute(elem, "display")
1003: .equals("none")) {
1004: return false;
1005: } else {
1006: return true;
1007: }
1008: }
1009:
1010: /**
1011: * Determines if the visible box or content area is set when sizing elements.
1012: *
1013: * @return <code>true</code> for visible box sizing
1014: */
1015: public static boolean isVisibleBox() {
1016: return isVisibleBox;
1017: }
1018:
1019: /**
1020: * Returns <code>true</code> if the vertical scroll bar is present
1021: *
1022: * @param container the container element
1023: * @return the vertical scroll bar state
1024: */
1025: public static boolean isVScrollBarShowing(Element container) {
1026: int orig = MyDOM.getScrollLeft(container);
1027: if (orig > 0) {
1028: return true;
1029: }
1030: setScrollLeft(container, 10);
1031: if (MyDOM.getScrollLeft(container) > 0) {
1032: setScrollLeft(container, orig);
1033: return true;
1034: }
1035: setScrollLeft(container, orig);
1036: return false;
1037: }
1038:
1039: /**
1040: * Makes an element positionable.
1041: *
1042: * @param elem the element
1043: */
1044: public static void makePositionable(Element elem) {
1045: String position = DOM.getStyleAttribute(elem, "position");
1046: if (position.equals("") || position.equals("static")) {
1047: DOM.setStyleAttribute(elem, "position", "relative");
1048: }
1049: }
1050:
1051: /**
1052: * Makes an element positionable.
1053: *
1054: * @param elem the element
1055: * @param absolute <code>true</code> to position absolute
1056: */
1057: public static void makePositionable(Element elem, boolean absolute) {
1058: if (absolute) {
1059: DOM.setStyleAttribute(elem, "position", "absolute");
1060: } else {
1061: makePositionable(elem);
1062: }
1063: }
1064:
1065: /**
1066: * Returns the offsets between two elements. Both element must be part of the
1067: * DOM tree and not have display:none to have page coordinates.
1068: *
1069: * @param elem the element
1070: * @param to the to element
1071: * @return the xy page offsets
1072: */
1073: public static Point offsetsTo(Element elem, Element to) {
1074: Point o = getXY(elem);
1075: Point e = getXY(to);
1076: return new Point(o.x - e.x, o.y - e.y);
1077: }
1078:
1079: /**
1080: * Removes all the elements children.
1081: *
1082: * @param elem the element
1083: */
1084: public static void removeChildren(Element elem) {
1085: while (DOM.getChildCount(elem) > 0) {
1086: DOM.removeChild(elem, DOM.getChild(elem, 0));
1087: }
1088: }
1089:
1090: /**
1091: * Removes the element from it's parent.
1092: *
1093: * @param elem the element
1094: */
1095: public static void removeFromParent(Element elem) {
1096: Element p = DOM.getParent(elem);
1097: if (p != null) {
1098: DOM.removeChild(p, elem);
1099: }
1100: }
1101:
1102: /**
1103: * Removes a style name.
1104: *
1105: * @param elem the element
1106: * @param style the style to be removed
1107: */
1108: public static void removeStyleName(Element elem, String style) {
1109: if (style != null) {
1110: setStyleName(elem, style, false);
1111: }
1112: }
1113:
1114: /**
1115: * Scrolls the element into view.
1116: *
1117: * @param elem the element to scroll
1118: * @param container the container element
1119: * @param hscroll <code>false</code> to disable horizontal scrolling.
1120: */
1121: public static native void scrollIntoView(Element elem,
1122: Element container, boolean hscroll) /*-{
1123: var c = container || $doc.body;
1124: var o = @net.mygwt.ui.client.MyDOM::offsetsTo(Lcom/google/gwt/user/client/Element;Lcom/google/gwt/user/client/Element;)(elem, container);
1125: var l = o.@net.mygwt.ui.client.util.Point::x;
1126: var t = o.@net.mygwt.ui.client.util.Point::y;
1127: l = l + c.scrollLeft;
1128: t = t + c.scrollTop;
1129: var b = t + elem.offsetHeight;
1130: var r = l + elem.offsetWidth;
1131:
1132: var ch = c.clientHeight;
1133: var ct = parseInt(c.scrollTop, 10);
1134: var cl = parseInt(c.scrollLeft, 10);
1135: var cb = ct + ch;
1136: var cr = cl + c.clientWidth;
1137:
1138: if (t < ct){
1139: c.scrollTop = t;
1140: }else if(b > cb){
1141: c.scrollTop = b-ch;
1142: }
1143: c.scrollTop = c.scrollTop;
1144:
1145: if(hscroll !== false){
1146: if(l < cl){
1147: c.scrollLeft = l;
1148: } else if(r > cr){
1149: c.scrollLeft = r-c.clientWidth;
1150: }
1151: c.scrollLeft = c.scrollLeft;
1152: }
1153: }-*/;
1154:
1155: /**
1156: * Adds or removes a border. The style name 'my-border' is added to the widget
1157: * to display a border.
1158: *
1159: * @param elem the element
1160: * @param show the show state
1161: */
1162: public static void setBorders(Element elem, boolean show) {
1163: if (show) {
1164: addStyleName(elem, "my-border");
1165: } else {
1166: setStyleAttribute(elem, "border", "none");
1167: }
1168: }
1169:
1170: public static void setBounds(Element elem, int x, int y, int width,
1171: int height) {
1172: setBounds(elem, x, y, width, height, false);
1173: }
1174:
1175: /**
1176: * Sets the widgets size and location to the rectangular area specified by the
1177: * arguments.
1178: *
1179: * @param elem the element
1180: * @param x the x coordinate
1181: * @param y the y coordinate
1182: * @param width the width
1183: * @param height the height
1184: * @param adjust <code>true</code> to adjust for box model issues
1185: */
1186: public static void setBounds(Element elem, int x, int y, int width,
1187: int height, boolean adjust) {
1188: Rectangle rect = new Rectangle(x, y, width, height);
1189: setBounds(elem, rect, adjust);
1190: }
1191:
1192: /**
1193: * Sets the elements size and location to the specified rectangle.
1194: *
1195: * @param elem the element
1196: * @param rect the rectangle
1197: */
1198: public static void setBounds(Element elem, Rectangle rect) {
1199: setLocation(elem, rect.x, rect.y);
1200: setSize(elem, rect.width, rect.height);
1201: }
1202:
1203: /**
1204: * Sets the widgets size and location to the specified rectangle.
1205: *
1206: * @param elem the element
1207: * @param adjust <code>true</code> to adjust for box model issues
1208: * @param rect the rectangle
1209: */
1210: public static void setBounds(Element elem, Rectangle rect,
1211: boolean adjust) {
1212: setLocation(elem, rect.x, rect.y);
1213: setSize(elem, rect.width, rect.height, adjust);
1214: }
1215:
1216: /**
1217: * Sets the elements style attribute.
1218: *
1219: * @param elem the element
1220: * @param style the style
1221: * @param value the new double value
1222: */
1223: public static void setDoubleStyleAttribute(Element elem,
1224: String style, double value) {
1225: setStyleAttribute(elem, style, "" + value);
1226: }
1227:
1228: /**
1229: * Sets the focus state of the element.
1230: *
1231: * @param focused the new focus state
1232: */
1233: public native static void setFocus(Element elem, boolean focused) /*-{
1234: try {
1235: if (focused)
1236: elem.focus();
1237: else
1238: elem.blur();
1239: }
1240: catch(err) {
1241: }
1242: }-*/;
1243:
1244: /**
1245: * Sets the element's height.
1246: *
1247: * @param elem the element
1248: * @param height the new height
1249: */
1250: public static void setHeight(Element elem, int height) {
1251: setHeight(elem, height, false);
1252: }
1253:
1254: /**
1255: * Sets the element's height.
1256: *
1257: * @param elem the element
1258: * @param height the new height
1259: * @param adjust <code>true</code> to adjust for box model issue
1260: */
1261: public static void setHeight(Element elem, int height,
1262: boolean adjust) {
1263: if (height == Style.DEFAULT || height < 1) {
1264: return;
1265: }
1266: if (adjust && !isVisibleBox) {
1267: height -= getDecorationWidth(elem, Style.TOP | Style.BOTTOM);
1268: }
1269: DOM.setStyleAttribute(elem, "height", height + "px");
1270: }
1271:
1272: /**
1273: * Sets the HTML contained within an element. The specified html will be
1274: * escaped for XSS exploits if {@link MyGWT#enableEscapeHTML(boolean)} has
1275: * been enabled.
1276: *
1277: * @param elem the element
1278: * @param html the html
1279: */
1280: public native static void setInnerHTML(Element elem, String html) /*-{
1281: if (!html) {
1282: html = '';
1283: }
1284: if ($wnd.escapeFlag === true) {
1285: html = $wnd.escapeHTML(html);
1286: }
1287: elem.innerHTML = html;
1288: }-*/;
1289:
1290: /**
1291: * Sets the HTML contained within an element. The specified html will be
1292: * escaped for XSS exploits if {@link MyGWT#enableEscapeHTML(boolean)} has
1293: * been enabled.
1294: *
1295: * @param elem the element
1296: * @param html the html
1297: * @param escape <code>true</code> to escape html for XSS exploits.
1298: */
1299: public native static void setInnerHTML(Element elem, String html,
1300: boolean escape) /*-{
1301: if (!html) {
1302: html = '';
1303: }
1304: html = $wnd.escapeHTML(html);
1305: elem.innerHTML = html;
1306: }-*/;
1307:
1308: /**
1309: * Sets the element's left position directly using CSS style (instead of
1310: * {@link #setX}).
1311: *
1312: * @param elem the element
1313: * @param left the left value
1314: */
1315: public static void setLeft(Element elem, int left) {
1316: DOM.setStyleAttribute(elem, "left", left + "px");
1317: }
1318:
1319: /**
1320: * Sets the element's left position directly using CSS style.
1321: *
1322: * @param elem the element
1323: * @param left the left value
1324: * @param top the top value
1325: */
1326: public static void setLeftTop(Element elem, int left, int top) {
1327: setLeft(elem, left);
1328: setTop(elem, top);
1329: }
1330:
1331: /**
1332: * Sets the element position using page coordinates.
1333: *
1334: * @param elem the element
1335: * @param x the x coordinate value
1336: * @param y the y coordinate value
1337: */
1338: public static void setLocation(Element elem, int x, int y) {
1339: setX(elem, x);
1340: setY(elem, y);
1341: }
1342:
1343: /**
1344: * Sets the element's scroll left value.
1345: *
1346: * @param elem the element
1347: * @param left the value
1348: */
1349: public static void setScrollLeft(Element elem, int left) {
1350: DOM.setElementPropertyInt(elem, "scrollLeft", left);
1351: }
1352:
1353: /**
1354: * Sets the element's scroll top value.
1355: *
1356: * @param elem the element
1357: * @param top the value
1358: */
1359: public static void setScrollTop(Element elem, int top) {
1360: DOM.setElementPropertyInt(elem, "scrollTop", top);
1361: }
1362:
1363: /**
1364: * Set the size of the element. Values equal to My.DEFAULT are ignored.
1365: *
1366: * @param elem the element
1367: * @param width the new width
1368: * @param height the new height
1369: */
1370: public static void setSize(Element elem, int width, int height) {
1371: setSize(elem, width, height, false);
1372: }
1373:
1374: /**
1375: * Set the size of the element. Values equal to My.DEFAULT are ignored.
1376: *
1377: * @param elem the element
1378: * @param width the new width
1379: * @param height the new height
1380: * @param adjust <code>true</code> to adjust for box model issues
1381: */
1382: public static void setSize(Element elem, int width, int height,
1383: boolean adjust) {
1384: if (width != Style.DEFAULT) {
1385: setWidth(elem, width, adjust);
1386: }
1387: if (height != Style.DEFAULT) {
1388: setHeight(elem, height, adjust);
1389: }
1390: }
1391:
1392: /**
1393: * Sets the element's style attribute.
1394: *
1395: * @param elem the element
1396: * @param attr the attribute
1397: * @param value the value
1398: */
1399: public static void setStyleAttribute(Element elem, String attr,
1400: String value) {
1401: impl.setStyle(elem, attr, value);
1402: }
1403:
1404: /**
1405: * Sets the element's style name.
1406: *
1407: * @param elem the element
1408: * @param style the style name
1409: */
1410: public static void setStyleName(Element elem, String style) {
1411: DOM.setElementProperty(elem, "className", style);
1412: }
1413:
1414: /**
1415: * This convenience method adds or removes a style name for a given element.
1416: * This method is typically used to add and remove secondary style names, but
1417: * it can be used to remove primary stylenames as well, but that is not
1418: * recommended.
1419: *
1420: * @param elem the element whose style is to be modified
1421: * @param style the secondary style name to be added or removed
1422: * @param add <code>true</code> to add the given style, <code>false</code>
1423: * to remove it
1424: */
1425: public static void setStyleName(Element elem, String style,
1426: boolean add) {
1427: if (style == null)
1428: return;
1429: style = style.trim();
1430: if (style.length() == 0) {
1431: throw new IllegalArgumentException("EMPTY STRING");
1432: }
1433:
1434: // Get the current style string.
1435: String oldStyle = DOM.getElementProperty(elem, "className");
1436: int idx = oldStyle.indexOf(style);
1437:
1438: // Calculate matching index.
1439: while (idx != -1) {
1440: if (idx == 0 || oldStyle.charAt(idx - 1) == ' ') {
1441: int last = idx + style.length();
1442: int lastPos = oldStyle.length();
1443: if ((last == lastPos)
1444: || ((last < lastPos) && (oldStyle.charAt(last) == ' '))) {
1445: break;
1446: }
1447: }
1448: idx = oldStyle.indexOf(style, idx + 1);
1449: }
1450:
1451: if (add) {
1452: // Only add the style if it's not already present.
1453: if (idx == -1) {
1454: if (oldStyle.length() > 0) {
1455: oldStyle += " ";
1456: }
1457: DOM.setElementProperty(elem, "className", oldStyle
1458: + style);
1459: }
1460: } else {
1461: // Don't try to remove the style if it's not there.
1462: if (idx != -1) {
1463: // Get the leading and trailing parts, without the removed name.
1464: String begin = oldStyle.substring(0, idx).trim();
1465: String end = oldStyle.substring(idx + style.length())
1466: .trim();
1467:
1468: // Some contortions to make sure we don't leave extra spaces.
1469: String newClassName;
1470: if (begin.length() == 0) {
1471: newClassName = end;
1472: } else if (end.length() == 0) {
1473: newClassName = begin;
1474: } else {
1475: newClassName = begin + " " + end;
1476: }
1477:
1478: DOM.setElementProperty(elem, "className", newClassName);
1479: }
1480: }
1481: }
1482:
1483: /**
1484: * Sets the element's top position directly using CSS style (instead of
1485: * {@link #setY}).
1486: *
1487: * @param elem the element
1488: * @param top the top value
1489: */
1490: public static void setTop(Element elem, int top) {
1491: DOM.setStyleAttribute(elem, "top", top + "px");
1492: }
1493:
1494: /**
1495: * Sets the element's value property.
1496: *
1497: * @param elem the element
1498: * @param value the value
1499: */
1500: public static void setValue(Element elem, String value) {
1501: DOM.setElementAttribute(elem, "value", value);
1502: }
1503:
1504: /**
1505: * Sets the elements css 'visibility' property. Behavior is different than
1506: * using the 'display' property.
1507: *
1508: * @param elem the element
1509: * @param visible <code>true</code> to show, <code>false</code> to hide
1510: */
1511: public static void setVisibility(Element elem, boolean visible) {
1512: String value = visible ? "" : "hidden";
1513: DOM.setStyleAttribute(elem, "visibility", value);
1514: }
1515:
1516: /**
1517: * Sets the element's css 'display' property.
1518: *
1519: * @param elem the element
1520: * @param visible <code>true</code> to show, <code>false</code> to hide
1521: */
1522: public static void setVisible(Element elem, boolean visible) {
1523: String value = visible ? "" : "none";
1524: DOM.setStyleAttribute(elem, "display", value);
1525: }
1526:
1527: /**
1528: * Sets the element's width.
1529: *
1530: * @param elem the element
1531: * @param width the new width value
1532: */
1533: public static void setWidth(Element elem, int width) {
1534: setWidth(elem, width, false);
1535: }
1536:
1537: /**
1538: * Sets the element's width.
1539: *
1540: * @param elem the element
1541: * @param adjust <code>true</code> to adjust for box model issues
1542: * @param width the new width value
1543: */
1544: public static void setWidth(Element elem, int width, boolean adjust) {
1545: if (width == Style.DEFAULT || width < 1) {
1546: return;
1547: }
1548: if (adjust && !isVisibleBox) {
1549: width -= getDecorationWidth(elem, Style.LEFT | Style.RIGHT);
1550: }
1551: DOM.setStyleAttribute(elem, "width", width + "px");
1552: }
1553:
1554: /**
1555: * Set the x position of the element.
1556: *
1557: * @param elem the element
1558: * @param x the x coordinate
1559: */
1560: public static void setX(Element elem, int x) {
1561: makePositionable(elem);
1562: int l = DOM.getIntStyleAttribute(elem, "left");
1563: x = x - DOM.getAbsoluteLeft(elem) + l;
1564: DOM.setStyleAttribute(elem, "left", x + "px");
1565: }
1566:
1567: /**
1568: * Sets the position of the element.
1569: *
1570: * @param elem the element
1571: * @param point the position
1572: */
1573: public static void setXY(Element elem, Point point) {
1574: setX(elem, point.x);
1575: setY(elem, point.y);
1576: }
1577:
1578: /**
1579: * Set the y position of an html element in page coordinates, regardless of
1580: * how the element is positioned. The element must be part of the DOM tree to
1581: * have page coordinates.
1582: *
1583: * @param elem the element
1584: * @param y the y coordinate
1585: */
1586: public static void setY(Element elem, int y) {
1587: makePositionable(elem);
1588: int t = DOM.getIntStyleAttribute(elem, "top");
1589: y = y - DOM.getAbsoluteTop(elem) + t;
1590: DOM.setStyleAttribute(elem, "top", y + "px");
1591: }
1592:
1593: /**
1594: * Sets the element's z-index.
1595: *
1596: * @param elem the element
1597: * @param index the z-index
1598: */
1599: public static void setZIndex(Element elem, int index) {
1600: DOM.setIntStyleAttribute(elem, "zIndex", index);
1601: }
1602:
1603: /**
1604: * Unwraps the child element.
1605: *
1606: * @param wrapper the wrapper element
1607: * @param child the child element
1608: * @param bounds the size
1609: */
1610: public static void unwrap(Element wrapper, Element child,
1611: Rectangle bounds) {
1612: MyDOM.setTop(child, bounds.y);
1613: MyDOM.setLeft(child, bounds.x);
1614:
1615: Element p = DOM.getParent(wrapper);
1616: DOM.removeChild(p, wrapper);
1617: DOM.appendChild(p, child);
1618: }
1619:
1620: /**
1621: * Unwraps the child element.
1622: *
1623: * @param wrapper the wrapper element
1624: * @param child the child element
1625: * @param bounds the size
1626: * @param index the insert location
1627: */
1628: public static void unwrap(Element wrapper, Element child,
1629: Rectangle bounds, int index) {
1630: MyDOM.setTop(child, bounds.y);
1631: MyDOM.setLeft(child, bounds.x);
1632:
1633: Element p = DOM.getParent(wrapper);
1634: DOM.removeChild(p, wrapper);
1635: DOM.insertChild(p, child, index);
1636: }
1637:
1638: /**
1639: * Wraps the element with the specified wrapper. The wrapper will have the
1640: * same size and position of the element. The original bounds can be used to
1641: * 'unwrap' the element.
1642: *
1643: * @param wrapper the wrapper element
1644: * @return the original bounds
1645: */
1646: public static Rectangle wrap(Element elem, Element wrapper) {
1647: MyDOM.setVisible(wrapper, false);
1648:
1649: String pos = DOM.getStyleAttribute(elem, "position");
1650: MyDOM.setStyleAttribute(wrapper, "position", pos);
1651:
1652: int l = MyDOM.getLeft(elem);
1653: int t = MyDOM.getTop(elem);
1654:
1655: MyDOM.setLeft(elem, 5000);
1656: MyDOM.setVisible(elem, true);
1657:
1658: int h = getComputedHeight(elem);
1659: int w = getComputedWidth(elem);
1660:
1661: MyDOM.setLeft(elem, 1);
1662: MyDOM.setStyleAttribute(elem, "overflow", "hidden");
1663: MyDOM.setVisible(elem, false);
1664:
1665: MyDOM.insertBefore(wrapper, elem);
1666: DOM.appendChild(wrapper, elem);
1667:
1668: MyDOM.setStyleAttribute(wrapper, "overflow", "hidden");
1669:
1670: MyDOM.setLeft(wrapper, l);
1671: MyDOM.setTop(wrapper, t);
1672:
1673: MyDOM.setTop(elem, 0);
1674: MyDOM.setLeft(elem, 0);
1675:
1676: return new Rectangle(l, t, w, h);
1677:
1678: }
1679:
1680: /**
1681: * This function can be replaced to plugin an alternate function to handle XSS exploits.
1682: */
1683: native static void init() /*-{
1684: $wnd.escapeHTML = function(html) {
1685: html = html.replace(/[\"\'][\s]*javascript:(.*)[\"\']/g, "\"\"");
1686: html = html.replace(/<script(.*)/g, "");
1687: html = html.replace(/eval\((.*)\)/g, "");
1688: return html;
1689: }
1690: }-*/;
1691:
1692: private native static void disableTextSelectInternal(Element e,
1693: boolean disable)/*-{
1694: if (disable) {
1695: e.ondrag = function () { return false; };
1696: e.onselectstart = function () { return false; };
1697: } else {
1698: e.ondrag = null;
1699: e.onselectstart = null;
1700: }
1701: }-*/;
1702:
1703: private static int getScrollBarWidthInternal() {
1704: WidgetContainer wc = new WidgetContainer();
1705: MyDOM.setVisibility(wc.getElement(), false);
1706: wc.setScrollEnabled(true);
1707: wc.setSize(300, 300);
1708:
1709: HTML html = new HTML("sdff");
1710: html.setHeight("284");
1711: html.setWidth("500");
1712:
1713: wc.add(html);
1714:
1715: RootPanel.get().add(wc);
1716:
1717: int height = 17;
1718:
1719: for (int i = 280; i < 300; i++) {
1720: html.setHeight("" + i);
1721: wc.setVScrollPosition(20);
1722: if (wc.getVScrollPosition() == 1) {
1723: height = 300 - i + 1;
1724: }
1725: }
1726: RootPanel.get().remove(wc);
1727: return height;
1728: }
1729:
1730: private static native boolean isVisibleBoxInternal() /*-{
1731: if (!$wnd.isVisibleBox) {
1732: var d = $wnd.document;
1733: var test = d.createElement('div');
1734: d.body.appendChild(test);
1735: test.style.position = "absolute";
1736: test.style.border = "2px solid";
1737: test.style.height = "50";
1738: $wnd.isVisibleValue = test.offsetHeight == 50 ? true : false;
1739: $wnd.isVisibleBox = true;
1740: d.body.removeChild(test);
1741: }
1742: return $wnd.isVisibleValue;
1743: }-*/;
1744:
1745: private MyDOM() {
1746:
1747: }
1748:
1749: }
|