/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.eas.core; import java.util.ArrayList; import java.util.List; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NodeList; import com.google.gwt.dom.client.Style; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.dom.client.Node; /** * * @author mg */ public class XElement extends Element { public interface Observer { public void observe(Element anElement); } protected XElement() { super(); } public final native Style getComputedStyle()/*-{ if (typeof this.currentStyle != 'undefined'){ return this.currentStyle; } else { return document.defaultView.getComputedStyle(this, null); } }-*/; public final double getComputedWidth(){ String swidth = getComputedStyle().getWidth(); return swidth.endsWith("px") ? Double.valueOf(swidth.substring(0, swidth.length() - 2)) : -1; } public final double getComputedHeight(){ String sheight = getComputedStyle().getHeight(); return sheight.endsWith("px") ? Double.valueOf(sheight.substring(0, sheight.length() - 2)) : -1; } public final int getContentWidth() { Element ruler = DOM.createDiv(); ruler.getStyle().setMargin(0, Style.Unit.PX); ruler.getStyle().setPadding(0, Style.Unit.PX); ruler.getStyle().setBorderWidth(0, Style.Unit.PX); ruler.getStyle().setPosition(Style.Position.RELATIVE); ruler.getStyle().setWidth(100, Style.Unit.PCT); insertFirst(ruler); try { String swidth = ruler.<XElement> cast().getComputedStyle().getWidth(); double computedWidth = swidth.endsWith("px") ? Double.valueOf(swidth.substring(0, swidth.length() - 2)) : -1; if (computedWidth != -1) { return (int) Math.floor(computedWidth); } else return ruler.getOffsetWidth(); } finally { ruler.removeFromParent(); } } public final int getContentHeight() { Element ruler = DOM.createDiv(); ruler.getStyle().setMargin(0, Style.Unit.PX); ruler.getStyle().setPadding(0, Style.Unit.PX); ruler.getStyle().setBorderWidth(0, Style.Unit.PX); ruler.getStyle().setPosition(Style.Position.RELATIVE); ruler.getStyle().setHeight(100, Style.Unit.PCT); insertFirst(ruler); try { String sheight = ruler.<XElement> cast().getComputedStyle().getHeight(); double computedHeight = sheight.endsWith("px") ? Double.valueOf(sheight.substring(0, sheight.length() - 2)) : -1; if (computedHeight != -1) { return (int) Math.floor(computedHeight); } else return ruler.getOffsetHeight(); } finally { ruler.removeFromParent(); } } /** * Selects a single child at any depth below this element based on the * passed CSS selector. * * @param aClassName * the css selector * @return the child element */ public final XElement child(String aClassName) { Element child = childElement(aClassName); return child == null ? null : child.<XElement> cast(); } /** * Selects a single child at any depth below this element based on the * passed CSS selector. * * @param aClassName * the css selector * @return the child element */ public final Element childElement(String aClassName) { List<Element> result = select(aClassName); return result != null && !result.isEmpty() ? result.get(0) : null; } /** * Selects child nodes based on the passed CSS selector (the selector should * not contain an id). * * @param aClassName * the selector/xpath query * @return the matching elements */ public final List<Element> select(final String aClassName) { final List<Element> result = new ArrayList<>(); iterate(this, new Observer() { @Override public void observe(Element anElement) { if ("*".equals(aClassName)) { result.add(anElement); } else { if (anElement.getClassName() != null && anElement.hasClassName(aClassName)) result.add(anElement); } } }); return result; } /** * Selects child nodes based on the passed CSS selector (the selector should * not contain an id). * * @param aTagName * the selector/xpath query * @return the matching elements */ public final Element firstChildByTagName(final String aTagName) { final List<Element> result = new ArrayList<>(); iterate(this, new Observer() { @Override public void observe(Element anElement) { if(anElement.getTagName().equalsIgnoreCase(aTagName)) result.add(anElement); } }); return result.isEmpty() ? null : result.get(0); } public final List<Element> selectByPrefix(final String aClassNamePrefix) { final List<Element> result = new ArrayList<>(); iterate(this, new Observer() { @Override public void observe(Element anElement) { String classesNames = anElement.getClassName(); if (classesNames != null) { String[] classes = classesNames.split(" "); for (int i = 0; i < classes.length; i++) { if (classes[i].startsWith(aClassNamePrefix)) { result.add(anElement); break; } } } } }); return result; } protected static void iterate(Element aRoot, Observer aTask) { if (aRoot != null) { aTask.observe(aRoot); NodeList<Node> nl = aRoot.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node n = nl.getItem(i); if (n instanceof Element) { iterate((Element) n, aTask); } } } } /** * Puts a mask over this element to disable user interaction. * * @param message * a message to display in the mask */ public final void errorMask(String message) { mask("p-mask-loading-error"); } public final void loadMask() { mask("p-mask-loading-start"); } public final void disabledMask() { mask("p-mask-disabled"); } public final void mask(String aClassName) { Element mask = Document.get().createDivElement(); mask.getStyle().setLeft(0, Style.Unit.PX); mask.getStyle().setTop(0, Style.Unit.PX); mask.getStyle().setRight(0, Style.Unit.PX); mask.getStyle().setBottom(0, Style.Unit.PX); mask.getStyle().setPosition(Style.Position.ABSOLUTE); mask.getStyle().setDisplay(Style.Display.INLINE_BLOCK); mask.setClassName("p-mask"); Element maskInner = Document.get().createDivElement(); maskInner.getStyle().setLeft(0, Style.Unit.PX); maskInner.getStyle().setTop(0, Style.Unit.PX); maskInner.getStyle().setRight(0, Style.Unit.PX); maskInner.getStyle().setBottom(0, Style.Unit.PX); maskInner.getStyle().setPosition(Style.Position.ABSOLUTE); maskInner.getStyle().setDisplay(Style.Display.INLINE_BLOCK); maskInner.setClassName(aClassName); mask.appendChild(maskInner); appendChild(mask); } /** * Removes a mask over this element to disable user interaction. * */ public final void unmask() { NodeList<Node> nl = getChildNodes(); for (int i = nl.getLength() - 1; i >= 0; i--) { Node n = nl.getItem(i); if (Element.is(n) && Element.as(n).getClassName() != null && Element.as(n).hasClassName("p-mask")) { n.removeFromParent(); } } } public final int getChildIndex(Element aChild) { NodeList<Node> nl = getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { if (nl.getItem(i) == aChild) { return i; } } return -1; } /** * Generates a native dom click on the element. */ public final native void click() /*-{ var el = this; if (el.click) { el.click(); } else { var event = $doc.createEvent("MouseEvents"); event.initEvent('click', true, true, $wnd, 0, 0, 0, 0, 0, false, false, false, false, 1, el); el.dispatchEvent(event); } }-*/; public final native JavaScriptObject addResizingTransitionEnd(RequiresResize aTarget)/*-{ var handler = function(aEvent) { if (aEvent.propertyName == "width" || aEvent.propertyName == "height" || aEvent.propertyName == "left" || aEvent.propertyName == "top" || aEvent.propertyName == "right" || aEvent.propertyName == "bottom") { aEvent.stopPropagation(); aTarget.@com.google.gwt.user.client.ui.RequiresResize::onResize()(); } }; this.addEventListener("transitionend", handler, false); this.addEventListener("webkitTransitionEnd", handler, false); return handler; }-*/; public final native void removeTransitionEndListener(JavaScriptObject aListener)/*-{ this.removeEventListener("transitionend", aListener, false); this.removeEventListener("webkitTransitionEnd", aListener, false); }-*/; }