View Javadoc

1   /*
2    * Ext GWT 2.2.0 - Ext for GWT
3    * Copyright(c) 2007-2010, Ext JS, LLC.
4    * licensing@extjs.com
5    * 
6    * http://extjs.com/license
7    */
8   package com.extjs.gxt.ui.client.core;
9   
10  import java.util.ArrayList;
11  import java.util.Arrays;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.Set;
15  
16  import com.extjs.gxt.ui.client.GXT;
17  import com.extjs.gxt.ui.client.Style;
18  import com.extjs.gxt.ui.client.Style.Direction;
19  import com.extjs.gxt.ui.client.Style.ScrollDir;
20  import com.extjs.gxt.ui.client.core.impl.ComputedStyleImpl;
21  import com.extjs.gxt.ui.client.fx.BaseEffect;
22  import com.extjs.gxt.ui.client.fx.Fx;
23  import com.extjs.gxt.ui.client.fx.FxConfig;
24  import com.extjs.gxt.ui.client.fx.Move;
25  import com.extjs.gxt.ui.client.util.Format;
26  import com.extjs.gxt.ui.client.util.Margins;
27  import com.extjs.gxt.ui.client.util.Markup;
28  import com.extjs.gxt.ui.client.util.Padding;
29  import com.extjs.gxt.ui.client.util.Point;
30  import com.extjs.gxt.ui.client.util.Rectangle;
31  import com.extjs.gxt.ui.client.util.Region;
32  import com.extjs.gxt.ui.client.util.Scroll;
33  import com.extjs.gxt.ui.client.util.Size;
34  import com.extjs.gxt.ui.client.util.TextMetrics;
35  import com.extjs.gxt.ui.client.util.Util;
36  import com.google.gwt.core.client.GWT;
37  import com.google.gwt.core.client.JavaScriptObject;
38  import com.google.gwt.dom.client.Document;
39  import com.google.gwt.dom.client.NodeList;
40  import com.google.gwt.http.client.Request;
41  import com.google.gwt.http.client.RequestBuilder;
42  import com.google.gwt.http.client.RequestCallback;
43  import com.google.gwt.http.client.Response;
44  import com.google.gwt.user.client.Command;
45  import com.google.gwt.user.client.DOM;
46  import com.google.gwt.user.client.DeferredCommand;
47  import com.google.gwt.user.client.Element;
48  
49  /**
50   * Represents an Element in the DOM.
51   */
52  public class El {
53  
54    /**
55     * VisMode enumeration. Specifies the the element should hidden using the CSS
56     * display or visibility style.
57     * 
58     */
59    public enum VisMode {
60      DISPLAY, VISIBILITY
61    }
62  
63    private static Map<String, Boolean> borderBoxMap = new FastMap<Boolean>();
64  
65    /**
66     * The globally shared El instance.
67     */
68    private static Map<String, El> flyweights = new FastMap<El>();
69  
70    private static ComputedStyleImpl computedStyle = GWT.create(ComputedStyleImpl.class);
71    private static JavaScriptObject leftRightTest;
72    private static JavaScriptObject removeStyleNameReCache;
73  
74    static {
75      GXT.init();
76    }
77  
78    /**
79     * Tests to see if the value has units, otherwise appends the default (px).
80     * 
81     * @param v the value
82     * @return the value with units
83     */
84    public native static String addUnits(String v, String defaultUnit) /*-{
85      if(v === "" || v == "auto"){
86      return v;
87      }
88      if(v === undefined){
89      return '';
90      }
91      if(typeof v == "number" || !/\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i.test(v)){
92      return v + (defaultUnit || 'px');
93      }
94      return v;
95    }-*/;
96  
97    public static El fly(com.google.gwt.dom.client.Element element) {
98      return fly(element, "_global");
99    }
100 
101   /**
102    * Gets the globally shared flyweight El, with the passed node as the active
103    * element. Do not store a reference to this element - the dom node can be
104    * overwritten by other code.
105    * 
106    * @param element the element
107    * @return the el instance
108    */
109   public static El fly(com.google.gwt.dom.client.Element element, String s) {
110     assert element != null : "Element my not be null";
111     El g = flyweights.get(s);
112     if (g == null) {
113       g = new El(DOM.createDiv());
114       flyweights.put(s, g);
115     }
116     g.dom = (Element) element;
117     return g;
118   }
119 
120   public static El fly(Element element) {
121     return fly(element, "_global");
122   }
123 
124   /**
125    * Gets the globally shared flyweight El, with the passed node as the active
126    * element. Do not store a reference to this element - the dom node can be
127    * overwritten by other code.
128    * 
129    * @param element the element to be wrapped
130    * @return the global El object
131    */
132   public static El fly(Element element, String s) {
133     assert element != null : "Element my not be null";
134     El g = flyweights.get(s);
135     if (g == null) {
136       g = new El(DOM.createDiv());
137       flyweights.put(s, g);
138     }
139     g.dom = (Element) element;
140     return g;
141   }
142 
143   /**
144    * Returns true if the passed element has a border box.
145    * 
146    * @param element the element to test
147    * @return true if the passed element has a border box
148    */
149   public static boolean isBorderBox(Element element) {
150     assert element != null : "Element may not be null";
151     String tag = element.getTagName().toLowerCase();
152     Boolean r = borderBoxMap.get(tag);
153     if (r == null) {
154       Element testElement = (Element) Document.get().createElement(tag);
155       testElement.getStyle().setPropertyPx("padding", 1);
156       testElement.getStyle().setPropertyPx("width", 100);
157       testElement.getStyle().setProperty("visibility", "hidden");
158       testElement.getStyle().setProperty("position", "absolute");
159       XDOM.getBody().appendChild(testElement);
160       r = testElement.getOffsetWidth() == 100;
161       XDOM.getBody().removeChild(testElement);
162       borderBoxMap.put(tag, r);
163     }
164     return r;
165   }
166 
167   private native static void disableTextSelectInternal(Element e, boolean disable)/*-{
168     if (disable) {
169     e.ondrag = function (evt) {
170     var targ;
171     if (!evt) evt = $wnd.event;
172     if (evt.target) targ = evt.target;
173     else if (evt.srcElement) targ = evt.srcElement;
174     if (targ.nodeType == 3) // defeat Safari bug
175     targ = targ.parentNode;
176     if (targ.tagName == 'INPUT' || targ.tagName == 'TEXTAREA') {
177     return true;
178     }
179     return false; 
180     };
181     e.onselectstart = function (evt) { 
182     var targ;
183     if (!evt) evt = $wnd.event;
184     if (evt.target) targ = evt.target;
185     else if (evt.srcElement) targ = evt.srcElement;
186     if (targ.nodeType == 3) // defeat Safari bug
187     targ = targ.parentNode;
188     if (targ.tagName == 'INPUT' || targ.tagName == 'TEXTAREA') {
189     return true;
190     }
191     return false; 
192     };
193     } else {
194     e.ondrag = null;
195     e.onselectstart = null;
196     }
197   }-*/;
198 
199   /**
200    * The wrapped dom element.
201    */
202   public Element dom;
203 
204   private VisMode visiblityMode = VisMode.DISPLAY;
205 
206   private String originalDisplay = "block";
207   private El _mask;
208   private El _maskMsg;
209   private boolean isClipped;
210   private String[] originalClipped;
211 
212   /**
213    * Creates a new el instance.
214    * 
215    * @param element the element to be wrapped
216    */
217   public El(Element element) {
218     assert element != null : "The element may not be null";
219     this.dom = element;
220   }
221 
222   /**
223    * Creates a new El instance from the HTML fragment.
224    * 
225    * @param html the html
226    */
227   public El(String html) {
228     this(XDOM.create(html));
229   }
230 
231   /**
232    * Adds the event type to the element's sunk events.
233    * 
234    * @param event the events to add
235    * @return this
236    */
237   public El addEventsSunk(int event) {
238     int bits = DOM.getEventsSunk(dom);
239     DOM.sinkEvents(dom, bits | event);
240     return this;
241   }
242 
243   /**
244    * Adds the style name to the element. Duplicate styles are automatically
245    * filtered out.
246    * 
247    * @param styleNames the new style names
248    * @return this
249    */
250   public El addStyleName(String... styleNames) {
251     if (styleNames != null) {
252       for (String styleName : styleNames) {
253         if (styleName != null && !hasStyleName(styleName)) {
254           styleName = styleName.trim();
255           /* begin laaglu */
256 //        dom.setClassName(dom.getClassName() + " " + styleName);
257           setClassName(dom, getClassName(dom) + " " + styleName);
258           /* end laaglu */
259         }
260       }
261     }
262     return this;
263   }
264 
265 /**
266    * Toggles the given style name, adding if not already present, removing if
267    * present.
268    * 
269    * @param styleName the style name to toggle
270    * @return this
271    */
272   public El toggleStyleName(String styleName) {
273     if (hasStyleName(styleName)) {
274       removeStyleName(styleName);
275     } else {
276       addStyleName(styleName);
277     }
278     return this;
279   }
280 
281   /**
282    * Ensures the element is within the browser viewport.
283    * 
284    * @param p the target destination
285    * @return the new location
286    */
287   public Point adjustForConstraints(Point p) {
288     return getConstrainToXY(XDOM.getBody(), p);
289   }
290 
291   /**
292    * Aligns the element with another element relative to the specified anchor
293    * points. Two values from the table below should be passed separated by a
294    * dash, the first value is used as the element's anchor point, and the second
295    * value is used as the target's anchor point.
296    * <p>
297    * In addition to the anchor points, the position parameter also supports the
298    * "?" character. If "?" is passed at the end of the position string, the
299    * element will attempt to align as specified, but the position will be
300    * adjusted to constrain to the viewport if necessary. Note that the element
301    * being aligned might be swapped to align to a different position than that
302    * specified in order to enforce the viewport constraints. Following are all
303    * of the supported anchor positions:
304    * </p>
305    * <dl>
306    * <dt>Following are all of the supported anchor positions:</dt>
307    * </dl>
308    * <code><pre>
309    *  Value  Description
310    *  -----  -----------------------------
311    *  tl     The top left corner (default)
312    *  t      The center of the top edge
313    *  tr     The top right corner
314    *  l      The center of the left edge
315    *  c      In the center of the element
316    *  r      The center of the right edge
317    *  bl     The bottom left corner
318    *  b      The center of the bottom edge
319    *  br     The bottom right corner
320    * </code></pre>
321    * 
322    * @param align the element to align to
323    * @param pos the position to align to
324    * @param offsets the offsets or <code>null</code>
325    * @return this
326    */
327   public El alignTo(Element align, String pos, int[] offsets) {
328     if (offsets == null) {
329       offsets = new int[] {0, 0};
330     }
331     Point p = getAlignToXY(align, pos, offsets);
332     setXY(p);
333     return this;
334   }
335 
336   /**
337    * Appends a element.
338    * 
339    * @param child the element to add
340    * @return the child element
341    */
342   public El appendChild(Element child) {
343     dom.appendChild(child);
344     return new El(child);
345   }
346 
347   /**
348    * More flexible version of {@link #setStyleAttribute} for setting style
349    * properties. Style attribute names must be in lower camel case, e.g.
350    * "backgroundColor:white"
351    * 
352    * @param styles a style specification string
353    * @return this
354    */
355   public native El applyStyles(String styles) /*-{
356     var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
357     var matches;
358     while ((matches = re.exec(styles)) != null){
359     this.@com.extjs.gxt.ui.client.core.El::setStyleAttribute(Ljava/lang/String;Ljava/lang/Object;)(matches[1], matches[2]);
360     }
361     return this;
362   }-*/;
363 
364   /**
365    * Blinks the element.
366    * 
367    * @param config the fx config
368    * @return this
369    */
370   public El blink(FxConfig config) {
371     BaseEffect.blink(this, config, 50);
372     return this;
373   }
374 
375   /**
376    * Removes focus.
377    * 
378    * @return this
379    */
380   public El blur() {
381     return setFocus(false);
382   }
383 
384   /**
385    * Wraps the specified element with a special markup/CSS block.
386    * 
387    * @param style a base CSS class to apply to the containing wrapper element
388    *          (defaults to 'x-box').
389    * @return this
390    */
391   public El boxWrap(String style) {
392     String s = style != null ? style : "x-box";
393     El temp = insertHtml("beforeBegin", Format.substitute("<div class={0}>" + Markup.BBOX, s) + "</div>");
394     temp.child("." + s + "-mc").appendChild(dom);
395     return temp;
396   }
397 
398   /**
399    * Centers the element in the viewport.
400    * 
401    * @return this
402    */
403   public El center() {
404     return center(null);
405   }
406 
407   /**
408    * Centers the element.
409    * 
410    * @param constrainViewport true to constrain the element position to the
411    *          viewport.
412    * @return this
413    */
414   public El center(boolean constrainViewport) {
415     return alignTo(XDOM.getBody(), "c-c" + (constrainViewport ? "?" : ""), null);
416   }
417 
418   /**
419    * Centers an element.
420    * 
421    * @param container the container element
422    * @return this
423    */
424   public El center(Element container) {
425     if (container == null) {
426       container = XDOM.getBody();
427     }
428     return alignTo(container, "c-c", null);
429   }
430 
431   /**
432    * Selects a single child at any depth below this element based on the passed
433    * CSS selector.
434    * 
435    * @param selector the css selector
436    * @return the child element
437    */
438   public El child(String selector) {
439     Element child = childElement(selector);
440     return child == null ? null : new El(child);
441   }
442 
443   /**
444    * Selects a single child at any depth below this element based on the passed
445    * CSS selector.
446    * 
447    * @param selector the css selector
448    * @return the child element
449    */
450   public Element childElement(String selector) {
451     return DomQuery.selectNode(selector, dom);
452   }
453 
454   /**
455    * Returns the element's child.
456    * 
457    * @param index the index of the child element
458    * @return the child element
459    */
460   public El childNode(int index) {
461     Element e = DOM.getChild(dom, index);
462     return e == null ? null : new El(e);
463   }
464 
465   /**
466    * Clears the set opacity correctly. This is mostly needed only on IE.
467    * 
468    * @return this
469    */
470   public native El clearOpacity() /*-{
471     var dom = this.@com.extjs.gxt.ui.client.core.El::dom;
472     var style = dom.style;
473     if(@com.extjs.gxt.ui.client.GXT::isIE){
474       dom.style.filter = (dom.style.filter || '').replace(/alpha\([^\)]*\)/gi,"");
475     }else{
476       style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
477     }
478     return this;
479   }-*/;
480 
481   /**
482    * Generators a native dom click on the element.
483    * 
484    * @return this
485    */
486   public native El click() /*-{
487     var dom = this.@com.extjs.gxt.ui.client.core.El::dom;
488     if (dom.click) {
489     dom.click();
490     }
491     else {
492     var event = $doc.createEvent("MouseEvents");
493     event.initEvent('click', true, true, $wnd, 0, 0, 0, 0, 0, false, false, false, false, 1, dom);
494     dom.dispatchEvent(event);    
495     }
496     return this;
497   }-*/;
498 
499   /**
500    * Clips overflow on the element.
501    * 
502    * @return this
503    */
504   public El clip() {
505     if (!isClipped) {
506       isClipped = true;
507       originalClipped = new String[3];
508       originalClipped[0] = getStyleAttribute("overflow");
509       originalClipped[1] = getStyleAttribute("overflowX");
510       originalClipped[2] = getStyleAttribute("overflowY");
511       setStyleAttribute("overflow", "hidden");
512       setStyleAttribute("overflowX", "hidden");
513       setStyleAttribute("overflowY", "hidden");
514     }
515     return this;
516   }
517 
518   /**
519    * Clones the element.
520    * 
521    * @param deep true to clone children
522    * @return the new element
523    */
524   public Element cloneNode(boolean deep) {
525     return (Element) dom.cloneNode(deep);
526   }
527 
528   /**
529    * Creates and adds a child using the HTML fragment.
530    * 
531    * @param html the html fragment
532    * @return the new child
533    */
534   public El createChild(String html) {
535     return appendChild(XDOM.create(html));
536   }
537 
538   /**
539    * Creates and inserts a child using the HTML fragment.
540    * 
541    * @param html the html fragment
542    * @param insertBefore a child element of this element
543    * @return the new child
544    */
545   public El createChild(String html, Element insertBefore) {
546     Element element = XDOM.create(html);
547     int idx = DOM.getChildIndex(dom, insertBefore);
548     insertChild(element, idx);
549     return new El(element);
550   }
551 
552   /**
553    * Disables the element.
554    * 
555    * @return this
556    */
557   public El disable() {
558     dom.setPropertyBoolean("disabled", true);
559     return this;
560   }
561 
562   /**
563    * Enables and disables the browsers default context menu for the specified
564    * element.A circular reference will be created when disabling text selection.
565    * Disabling should be cleared when the element is detached. See the
566    * <code>Component</code> source for an example.
567    * 
568    * @param disable true to disable, false to enable
569    * @return this
570    */
571   public native El disableContextMenu(boolean disable) /*-{
572     var e = this.@com.extjs.gxt.ui.client.core.El::dom;
573     e.oncontextmenu = disable ? function() {return false} : null;
574     return this;
575   }-*/;
576 
577   /**
578    * Enables or disables text selection for the element. A circular reference
579    * will be created when disabling text selection. Disabling should be cleared
580    * when the element is detached. See the <code>Component</code> source for an
581    * example.
582    * 
583    * @param disable true to disable, false to enable
584    * @return this
585    */
586   public El disableTextSelection(boolean disable) {
587     setStyleName("x-unselectable", disable);
588     setElementAttribute("unselectable", disable ? "on" : "");
589     disableTextSelectInternal(dom, disable);
590     return this;
591   }
592 
593   /**
594    * Selects a single *direct* child based on the passed CSS selector (the
595    * selector should not contain an id).
596    * 
597    * @param selector the CSS selector
598    * @return the child element
599    */
600   public El down(String selector) {
601     Element elem = DomQuery.selectNode(" > " + selector, dom);
602     if (elem != null) {
603       return new El(elem);
604     }
605     return null;
606   }
607 
608   /**
609    * Enables the element.
610    * 
611    * @return this
612    */
613   public El enable() {
614     dom.setPropertyBoolean("disabled", false);
615     return this;
616   }
617 
618   /**
619    * Convenience method for setVisibilityMode(VisibilityMode.DISPLAY).
620    * 
621    * @param display what to set display to when visible
622    * @return this
623    */
624   public El enableDisplayMode(String display) {
625     setVisibilityMode(VisMode.DISPLAY);
626     if (display != null) {
627       originalDisplay = display;
628     }
629     return this;
630   }
631 
632   @Override
633   public boolean equals(Object obj) {
634     if (obj instanceof El) {
635       return getId().equals(((El) obj).getId());
636     }
637     return super.equals(obj);
638   }
639 
640   /**
641    * Fades in the element.
642    * 
643    * @param config the fx config
644    * @return this
645    */
646   public El fadeIn(FxConfig config) {
647     BaseEffect.fadeIn(this, config);
648     return this;
649   }
650 
651   /**
652    * Fades out the element.
653    * 
654    * @param config the fx config
655    * @return this
656    */
657   public El fadeOut(FxConfig config) {
658     BaseEffect.fadeOut(this, config);
659     return this;
660   }
661 
662   /**
663    * Toggles the element visibility using a fade effect.
664    * 
665    * @param config the fx config
666    * @return this
667    */
668   public El fadeToggle(FxConfig config) {
669     if (!isVisible()) {
670       BaseEffect.fadeIn(this, config);
671     } else {
672       BaseEffect.fadeOut(this, config);
673     }
674     return this;
675   }
676 
677   /**
678    * Looks at this node and then at parent nodes for a match of the passed
679    * simple selector (e.g. div.some-class or span:first-child).
680    * 
681    * @param selector the simple selector to test
682    * @return the matching element
683    */
684   public El findParent(String selector, int maxDepth) {
685     Element elem = findParentElement(selector, maxDepth);
686     if (elem == null) {
687       return null;
688     }
689     return new El(elem);
690   }
691 
692   /**
693    * Looks at this node and then at parent nodes for a match of the passed
694    * simple selector (e.g. div.some-class or span:first-child).
695    * 
696    * @param selector the simple selector to test
697    * @param maxDepth the max depth
698    * @return the matching element
699    */
700   public Element findParentElement(String selector, int maxDepth) {
701     Element p = dom;
702     Element b = XDOM.getBody();
703     int depth = 0;
704     while (p != null && p.getNodeType() == 1 && (maxDepth == -1 || depth < maxDepth) && p != b) {
705       if (DomQuery.is(p, selector)) {
706         return p;
707       }
708       depth++;
709       p = (Element) p.getParentElement();
710     }
711     return null;
712   }
713 
714   /**
715    * Returns the element's first child.
716    * 
717    * @return the first child
718    */
719   public El firstChild() {
720     Element firstChild = DOM.getFirstChild(dom);
721     return firstChild == null ? null : new El(firstChild);
722   }
723 
724   /**
725    * Tries to focus the element.
726    * 
727    * @return this
728    */
729   public El focus() {
730     return setFocus(true);
731   }
732 
733   public Point getAlignToXY(Element elem, String p, int ox, int oy) {
734     El el = new El(elem);
735 
736     if (p == null) {
737       p = "tl-bl";
738     } else if (p.equals("?")) {
739       p = "tl-bl?";
740     } else if (p.indexOf("-") == -1) {
741       p = "tl-" + p;
742     }
743     p = p.toLowerCase();
744     boolean c = false;
745     String p1 = p.substring(0, p.indexOf("-"));
746     String p2 = p.substring(p.indexOf("-") + 1, ((c = p.contains("?")) ? p.indexOf("?") : p.length()));
747     // Subtract the aligned el's internal xy from the target's offset xy
748     // plus custom offset to get the aligned el's new offset xy
749     Point a1 = getAnchorXY(p1, true);
750     Point a2 = el.getAnchorXY(p2, false);
751 
752     int x = a2.x - a1.x + ox;
753     int y = a2.y - a1.y + oy;
754 
755     if (c) {
756       // constrain the aligned el to viewport if necessary
757       int w = getWidth();
758       int h = getHeight();
759       Region r = el.getRegion();
760       // 5px of margin for ie
761       int dw = XDOM.getViewWidth(false) - 10;
762       int dh = XDOM.getViewHeight(false) - 10;
763 
764       // If we are at a viewport boundary and the aligned el is anchored on a
765       // target border that is
766       // perpendicular to the vp border, allow the aligned el to slide on that
767       // border,
768       // otherwise swap the aligned el to the opposite border of the target.
769       char p1y = p1.charAt(0), p1x = p1.charAt(p1.length() - 1);
770       char p2y = p2.charAt(0), p2x = p2.charAt(p2.length() - 1);
771 
772       boolean swapY = ((p1y == 't' && p2y == 'b') || (p1y == 'b' && p2y == 't'));
773       boolean swapX = ((p1x == 'r' && p2x == 'l') || (p1x == 'l' && p2x == 'r'));
774 
775       int scrollX = XDOM.getBodyScrollLeft() + 5;
776       int scrollY = XDOM.getBodyScrollTop() + 5;
777 
778       if ((x + w) > dw + scrollX) {
779         x = swapX ? r.left - w : dw + scrollX - w;
780       }
781       if (x < scrollX) {
782         x = swapX ? r.right : scrollX;
783       }
784 
785       if ((y + h) > (dh + scrollY)) {
786         y = swapY ? r.top - h : dh + scrollY - h;
787       }
788       if (y < scrollY) {
789         y = swapY ? r.bottom : scrollY;
790       }
791     }
792 
793     return new Point(x, y);
794   }
795 
796   /**
797    * Gets the x,y coordinates to align this element with another element. See
798    * {@link #alignTo} for more info on the supported position values.
799    * 
800    * @param align the element to align to
801    * @param pos the position to align to
802    * @param offsets the offsets or <code>null</code>
803    * @return the point
804    */
805   public Point getAlignToXY(Element align, String pos, int[] offsets) {
806     if (offsets == null) {
807       offsets = new int[] {0, 0};
808     }
809     return getAlignToXY(align, pos, offsets[0], offsets[1]);
810   }
811 
812   /**
813    * Returns the x,y coordinates specified by the anchor position on the
814    * element.
815    * 
816    * @param anchor the specified anchor position (defaults to "c"). See
817    *          {@link #alignTo} for details on supported anchor positions.
818    * @param local <code>true</code> to get the local (element top/left-relative)
819    *          anchor position instead of page coordinates
820    * @return the position
821    */
822   public Point getAnchorXY(String anchor, boolean local) {
823     if (anchor == null) {
824       return null;
825     }
826     boolean vp = false;
827     int w;
828     int h;
829     if (dom == XDOM.getBody() || dom == XDOM.getDocument()) {
830       vp = true;
831       w = XDOM.getViewWidth(false);
832       h = XDOM.getViewHeight(false);
833     } else {
834       w = getWidth();
835       h = getHeight();
836     }
837 
838     int x = 0, y = 0;
839     if (anchor.length() == 1) {
840       if ("c".equalsIgnoreCase(anchor)) {
841         x = (int) Math.round(w * .5);
842         y = (int) Math.round(h * .5);
843       } else if ("t".equalsIgnoreCase(anchor)) {
844         x = (int) Math.round(w * .5);
845         y = 0;
846       } else if ("l".equalsIgnoreCase(anchor)) {
847         x = 0;
848         y = (int) Math.round(h * .5);
849       } else if ("r".equalsIgnoreCase(anchor)) {
850         x = w;
851         y = (int) Math.round(h * .5);
852       } else if ("b".equalsIgnoreCase(anchor)) {
853         x = (int) Math.round(w * .5);
854         y = h;
855       }
856     } else {
857       if ("tl".equalsIgnoreCase(anchor)) {
858         x = 0;
859         y = 0;
860       } else if ("bl".equalsIgnoreCase(anchor)) {
861         x = 0;
862         y = h;
863       } else if ("br".equalsIgnoreCase(anchor)) {
864         x = w;
865         y = h;
866       } else if ("tr".equalsIgnoreCase(anchor)) {
867         x = w;
868         y = 0;
869       }
870     }
871 
872     if (local) {
873       return new Point(x, y);
874     }
875     if (vp) {
876       Scroll sc = getScroll();
877       return new Point(x + sc.getScrollLeft(), y + sc.getScrollTop());
878     }
879     // Add the element's offset xy
880 
881     Point o = getXY();
882     return new Point(x + o.x, y + o.y);
883   }
884 
885   /**
886    * Returns the width of the border(s) for the specified side(s).
887    * 
888    * @param sides can be t, l, r, b or any combination of those to add multiple
889    *          values. For example, passing lr would get the border (l)eft width
890    *          + the border (r)ight width.
891    * @return the width of the sides passed added together
892    */
893   public int getBorderWidth(String sides) {
894     int borderWidth = 0;
895     List<String> list = new ArrayList<String>();
896     if (sides.contains("l")) {
897       list.add("borderLeftWidth");
898     }
899     if (sides.contains("r")) {
900       list.add("borderRightWidth");
901     }
902     if (sides.contains("t")) {
903       list.add("borderTopWidth");
904     }
905     if (sides.contains("b")) {
906       list.add("borderBottomWidth");
907     }
908     FastMap<String> map = getStyleAttribute(list);
909     for (String s : map.keySet()) {
910       borderWidth += Util.parseInt(map.get(s), 0);
911     }
912     return borderWidth;
913   }
914 
915   /**
916    * Returns the bottom Y coordinate of the element (element Y position +
917    * element height).
918    * 
919    * @param local
920    * @return the bottom value
921    */
922   public int getBottom(boolean local) {
923     return getHeight() + (local ? getTop() : getY());
924   }
925 
926   /**
927    * Returns the elements bounds in page coordinates.
928    * 
929    * @return the bounds
930    */
931   public Rectangle getBounds() {
932     return getBounds(false, false);
933   }
934 
935   /**
936    * Returns the elements bounds in page coordinates.
937    * 
938    * @param local if true the element's left and top are returned instead of
939    *          page coordinates
940    * 
941    * @return the bounds
942    */
943   public Rectangle getBounds(boolean local) {
944     return getBounds(local, false);
945   }
946 
947   /**
948    * Returns the element's bounds in page coordinates.
949    * 
950    * @param local if true the element's left and top are returned instead of
951    *          page coordinates
952    * @param adjust if true sizes get adjusted
953    * 
954    * @return the element's bounds
955    */
956   public Rectangle getBounds(boolean local, boolean adjust) {
957     Size s = getSize(adjust);
958     Rectangle rect = new Rectangle();
959     rect.width = s.width;
960     rect.height = s.height;
961     if (local) {
962       rect.x = getLeft(true);
963       rect.y = getTop(true);
964     } else {
965       Point p = getXY();
966       rect.x = p.x;
967       rect.y = p.y;
968     }
969     return rect;
970   }
971 
972   /**
973    * Returns a child element.
974    * 
975    * @param index the child index
976    * @return the child
977    */
978   public El getChild(int index) {
979     Element child = getChildElement(index);
980     return child == null ? null : new El(child);
981   }
982 
983   /**
984    * Returns a child element.
985    * 
986    * @param index the child index
987    * @return the child
988    */
989   public Element getChildElement(int index) {
990     return DOM.getChild(dom, index);
991   }
992 
993   /**
994    * Returns the index of the child element.
995    * 
996    * @return the index
997    */
998   public int getChildIndex(Element child) {
999     return DOM.getChildIndex(dom, child);
1000   }
1001 
1002   /**
1003    * Returns the element's client height property.
1004    * 
1005    * @return the client width value
1006    */
1007   public int getClientHeight() {
1008     return DOM.getElementPropertyInt(dom, "clientHeight");
1009   }
1010 
1011   /**
1012    * Returns the element's client width property.
1013    * 
1014    * @return the client width value
1015    */
1016   public int getClientWidth() {
1017     return DOM.getElementPropertyInt(dom, "clientWidth");
1018   }
1019 
1020   /**
1021    * Returns either the offsetHeight or the height of this element based on it's
1022    * CSS height.
1023    * 
1024    * @return the height
1025    */
1026   public int getComputedHeight() {
1027     int h = getHeight();
1028     if (h == 0) {
1029       h = getIntStyleAttribute("height");
1030     }
1031     return h;
1032   }
1033 
1034   /**
1035    * Returns either the offsetWidth or the width of this element based on it's
1036    * CSS width.
1037    * 
1038    * @return the width
1039    */
1040   public int getComputedWidth() {
1041     int w = getWidth();
1042     if (w == 0) {
1043       w = getIntStyleAttribute("width");
1044     }
1045     return w;
1046   }
1047 
1048   /**
1049    * Returns the sum width of the padding and borders for all "sides". See
1050    * #getBorderWidth() for more information about the sides.
1051    * 
1052    * @return the frame size
1053    */
1054   public Size getFrameSize() {
1055     int width = 0;
1056     int height = 0;
1057     List<String> list = new ArrayList<String>();
1058     list.add("paddingLeft");
1059     list.add("borderLeftWidth");
1060 
1061     list.add("paddingRight");
1062     list.add("borderRightWidth");
1063 
1064     list.add("paddingTop");
1065     list.add("borderTopWidth");
1066 
1067     list.add("paddingBottom");
1068     list.add("borderBottomWidth");
1069 
1070     FastMap<String> map = getStyleAttribute(list);
1071     for (String s : map.keySet()) {
1072       if (isLeftorRight(s)) {
1073         width += Util.parseInt(map.get(s), 0);
1074       } else {
1075         height += Util.parseInt(map.get(s), 0);
1076       }
1077     }
1078     return new Size(width, height);
1079   }
1080 
1081   /**
1082    * Returns the sum width of the padding and borders for the passed "sides".
1083    * See #getBorderWidth() for more information about the sides.
1084    * 
1085    * @param sides sides
1086    * @return the width
1087    */
1088   public int getFrameWidth(String sides) {
1089     int frameWidth = 0;
1090     List<String> list = new ArrayList<String>();
1091     if (sides.contains("l")) {
1092       list.add("paddingLeft");
1093       list.add("borderLeftWidth");
1094     }
1095     if (sides.contains("r")) {
1096       list.add("paddingRight");
1097       list.add("borderRightWidth");
1098     }
1099     if (sides.contains("t")) {
1100       list.add("paddingTop");
1101       list.add("borderTopWidth");
1102     }
1103     if (sides.contains("b")) {
1104       list.add("paddingBottom");
1105       list.add("borderBottomWidth");
1106     }
1107     FastMap<String> map = getStyleAttribute(list);
1108     for (String s : map.keySet()) {
1109       frameWidth += Util.parseInt(map.get(s), 0);
1110     }
1111     return frameWidth;
1112   }
1113 
1114   /**
1115    * Returns the offset height of the element.
1116    * 
1117    * @return the height
1118    */
1119   public int getHeight() {
1120     return dom.getOffsetHeight();
1121   }
1122 
1123   /**
1124    * Returns the element's height.
1125    * 
1126    * @param content true to get the height minus borders and padding
1127    * @return the element's height
1128    */
1129   public int getHeight(boolean content) {
1130     int h = getHeight();
1131     if (content) {
1132       h -= getFrameWidth("tb");
1133     }
1134     return Math.max(0,h);
1135   }
1136 
1137   /**
1138    * Returns the element's id.
1139    * 
1140    * @return the id
1141    */
1142   public String getId() {
1143     String id = DOM.getElementProperty(dom, "id");
1144     if (id == null || (id != null && id.length() == 0)) {
1145       id = XDOM.getUniqueId();
1146       setId(id);
1147     }
1148     return id;
1149   }
1150 
1151   /**
1152    * Returns the element's inner HTML.
1153    * 
1154    * @return the inner html
1155    */
1156   public String getInnerHtml() {
1157     return DOM.getInnerHTML(dom);
1158   }
1159 
1160   /**
1161    * Returns the element's style value.
1162    * 
1163    * @param attr the attribute name
1164    * @return the value
1165    */
1166   public int getIntStyleAttribute(String attr) {
1167     String v = DOM.getStyleAttribute(dom, attr);
1168     if (v == null || v.equals("")) {
1169       return 0;
1170     }
1171     return Util.parseInt(v, 0);
1172   }
1173 
1174   /**
1175    * Returns the element's content area bounds.
1176    * 
1177    * @return the bounds
1178    */
1179   public Rectangle getLayoutBounds() {
1180     Rectangle r = getBounds();
1181     r.width -= getFrameWidth("lr");
1182     r.height -= getFrameWidth("tb");
1183     return r;
1184   }
1185 
1186   /**
1187    * Returns the top Y coordinate.
1188    * 
1189    * @return the top value
1190    */
1191   public int getLeft() {
1192     return getLeft(true);
1193   }
1194 
1195   /**
1196    * Gets the left X coordinate.
1197    * 
1198    * @param local true to get the local css position instead of page coordinate
1199    * @return the left value
1200    */
1201   public int getLeft(boolean local) {
1202     return local ? Util.parseInt(getStyleAttribute("left"), 0) : getX();
1203   }
1204 
1205   /**
1206    * Returns an object with properties top, left, right and bottom representing
1207    * the margins of this element unless sides is passed, then it returns the
1208    * calculated width of the sides (see #getPadding).
1209    * 
1210    * @param sides any combination of l, r, t, b to get the sum of those sides
1211    * @return the margins
1212    */
1213   public int getMargins(String sides) {
1214     int margin = 0;
1215     List<String> list = new ArrayList<String>();
1216     if (sides.contains("l")) {
1217       list.add("marginLeft");
1218     }
1219     if (sides.contains("r")) {
1220       list.add("marginRight");
1221     }
1222     if (sides.contains("t")) {
1223       list.add("marginTop");
1224     }
1225     if (sides.contains("b")) {
1226       list.add("marginBottom");
1227     }
1228     FastMap<String> map = getStyleAttribute(list);
1229     for (String s : map.keySet()) {
1230       margin += Util.parseInt(map.get(s), 0);
1231     }
1232     return margin;
1233   }
1234 
1235   /**
1236    * Returns the offsets between two elements. Both element must be part of the
1237    * DOM tree and not have display:none to have page coordinates.
1238    * 
1239    * @param to the to element
1240    * @return the xy page offsets
1241    */
1242   public Point getOffsetsTo(Element to) {
1243     Point o = getXY();
1244     Point e = El.fly(to, "_internal").getXY();
1245     return new Point(o.x - e.x, o.y - e.y);
1246   }
1247 
1248   /**
1249    * Returns the element's outer HTML.
1250    * 
1251    * @return the inner html
1252    */
1253   public String getOuterHtml() {
1254     return dom.getAttribute("outerHTML");
1255   }
1256 
1257   /**
1258    * Gets the width of the padding(s) for the specified side(s).
1259    * 
1260    * @param sides can be t, l, r, b or any combination of those to add multiple
1261    *          values. For example, passing lr would get the border (l)eft width
1262    *          + the border (r)ight width.
1263    * @return the width of the sides passed added together
1264    */
1265   public int getPadding(String sides) {
1266     int padding = 0;
1267     List<String> list = new ArrayList<String>();
1268     if (sides.contains("l")) {
1269       list.add("paddingLeft");
1270     }
1271     if (sides.contains("r")) {
1272       list.add("paddingRight");
1273     }
1274     if (sides.contains("t")) {
1275       list.add("paddingTop");
1276     }
1277     if (sides.contains("b")) {
1278       list.add("paddingBottom");
1279     }
1280     FastMap<String> map = getStyleAttribute(list);
1281     for (String s : map.keySet()) {
1282       padding += Util.parseInt(map.get(s), 0);
1283     }
1284     return padding;
1285   }
1286 
1287   /**
1288    * Returns the element's parent.
1289    * 
1290    * @return the parent
1291    */
1292   public El getParent() {
1293     Element e = DOM.getParent(dom);
1294     return e == null ? null : new El(e);
1295   }
1296 
1297   /**
1298    * Returns the region of the given element. The element must be part of the
1299    * DOM tree to have a region.
1300    * 
1301    * @return a region containing top, left, bottom, right
1302    */
1303   public Region getRegion() {
1304     Rectangle bounds = getBounds();
1305     Region r = new Region();
1306     r.left = bounds.x;
1307     r.top = bounds.y;
1308     r.right = r.left + bounds.width;
1309     r.bottom = r.top + bounds.height;
1310     return r;
1311   }
1312 
1313   /**
1314    * Returns the right X coordinate of the element (element X position + element
1315    * width).
1316    * 
1317    * @param local <code>true</code> to get the local css position instead of
1318    *          page coordinate
1319    * @return the right value
1320    */
1321   public int getRight(boolean local) {
1322     return getWidth() + (local ? getLeft(true) : getX());
1323   }
1324 
1325   /**
1326    * Returns the body elements current scroll position.
1327    * 
1328    * @return the scroll position
1329    */
1330   public Scroll getScroll() {
1331     if (dom == XDOM.getBody() || dom == XDOM.getDocument()) {
1332       return new Scroll(XDOM.getBodyScrollLeft(), XDOM.getBodyScrollTop());
1333     } else {
1334       return new Scroll(getScrollLeft(), getScrollTop());
1335     }
1336   }
1337 
1338   /**
1339    * Returns the horizontal scroll position.
1340    * 
1341    * @return the scroll position
1342    */
1343   public int getScrollLeft() {
1344     return DOM.getElementPropertyInt(dom, "scrollLeft");
1345   }
1346 
1347   /**
1348    * Returns the current vertical scroll position.
1349    * 
1350    * @return the scroll position
1351    */
1352   public int getScrollTop() {
1353     return DOM.getElementPropertyInt(dom, "scrollTop");
1354   }
1355 
1356   /**
1357    * Returns the size of the element.
1358    * 
1359    * @return the size
1360    */
1361   public Size getSize() {
1362     return getSize(false);
1363   }
1364 
1365   /**
1366    * Returns the element's size.
1367    * 
1368    * @param content true to get the size minus borders and padding
1369    * @return the size
1370    */
1371   public Size getSize(boolean content) {
1372     int w = getWidth();
1373     int h = getHeight();
1374     if (content) {
1375       Size frameWidth = getFrameSize();
1376       w -= frameWidth.width;
1377       h -= frameWidth.height;
1378     }
1379     return new Size(Math.max(0,w),Math.max(0,h));
1380   }
1381 
1382   public FastMap<String> getStyleAttribute(List<String> attr) {
1383     return computedStyle.getStyleAttribute(dom, attr);
1384   }
1385 
1386   /**
1387    * Normalizes currentStyle and computedStyle.
1388    * 
1389    * @param attr the style attribute whose value is returned.
1390    * @return the current value of the style attribute for this element.
1391    */
1392   public String getStyleAttribute(String attr) {
1393     return getStyleAttribute(Arrays.asList(attr)).get(attr);
1394   }
1395 
1396   /**
1397    * Returns the style width.
1398    * 
1399    * @return the style width
1400    */
1401   public int getStyleHeight() {
1402     String h = dom.getStyle().getProperty("height");
1403     if (h == null || h.equals("")) return 0;
1404     if (h.matches("(auto|em|%|en|ex|pt|in|cm|mm|pc)")) {
1405       return 0;
1406     }
1407     return Util.parseInt(h, 0);
1408   }
1409 
1410   /**
1411    * Returns the element's style name.
1412    * 
1413    * @return the style name
1414    */
1415   public String getStyleName() {
1416 	  /* begin laaglu */
1417 //    return dom.getClassName();
1418 	  return getClassName(dom);
1419 	  /* end laaglu */
1420   }
1421 
1422   public Size getStyleSize() {
1423     return getStyleSize(true);
1424   }
1425 
1426   /**
1427    * Returns the element's size, using style attribute before offsets.
1428    * 
1429    * @return the size
1430    */
1431   public Size getStyleSize(boolean contentOnly) {
1432     int h = Util.parseInt(dom.getStyle().getProperty("height"), Style.DEFAULT);
1433     int w = Util.parseInt(dom.getStyle().getProperty("width"), Style.DEFAULT);
1434     
1435     boolean isBorderBox = isBorderBox();
1436 
1437     if (isBorderBox && contentOnly && w != Style.DEFAULT) {
1438       w -= getFrameWidth("lr");
1439       if (w < 0) {
1440         w = Style.DEFAULT;
1441       }
1442     } else if (!isBorderBox && !contentOnly && w != Style.DEFAULT) {
1443       w += getFrameWidth("lr");
1444     }
1445     if (isBorderBox && contentOnly && h != Style.DEFAULT) {
1446       h -= getFrameWidth("tb");
1447       if (h < 0) {
1448         h = Style.DEFAULT;
1449       }
1450     } else if (!isBorderBox && !contentOnly && h != Style.DEFAULT) {
1451       h += getFrameWidth("tb");
1452     }
1453 
1454     int offsetWidth = Style.DEFAULT;
1455     int offsetHeight = Style.DEFAULT;
1456     if (w == Style.DEFAULT && h == Style.DEFAULT) {
1457       Size s = getSize(contentOnly);
1458       offsetWidth = s.width;
1459       offsetHeight = s.height;
1460       if (s.width > 0) {
1461         w = s.width;
1462       }
1463       if (s.height > 0) {
1464         h = s.height;
1465       }
1466     } else if (w == Style.DEFAULT) {
1467       offsetWidth = getWidth(contentOnly);
1468       if (offsetWidth > 0) {
1469         w = offsetWidth;
1470       }
1471     } else if (h == Style.DEFAULT) {
1472       offsetHeight = getHeight(contentOnly);
1473       if (offsetHeight > 0) {
1474         h = offsetHeight;
1475       }
1476     }
1477 
1478     List<String> l = new ArrayList<String>();
1479     if (w == Style.DEFAULT) {
1480       l.add("width");
1481     }
1482     if (h == Style.DEFAULT) {
1483       l.add("height");
1484     }
1485     Map<String, String> map = getStyleAttribute(l);
1486     if (map != null) {
1487       String wid = map.get("width");
1488       if (wid != null) {
1489         w = Util.parseInt(wid, Style.DEFAULT);
1490         if (offsetWidth == 0 &&isBorderBox  && contentOnly && w != Style.DEFAULT && !GXT.isIE) {
1491           w -= getFrameWidth("lr");
1492         } else if(GXT.isIE && isBorderBox && w != Style.DEFAULT && contentOnly){
1493           w-= getFrameWidth("lr");
1494         } else if(offsetWidth == 0 && !isBorderBox && !contentOnly && w != Style.DEFAULT){
1495           w += getFrameWidth("lr");
1496         }
1497       }
1498       String hei = map.get("height");
1499       if (hei != null) {
1500         h = Util.parseInt(hei, Style.DEFAULT);
1501         if (offsetHeight == 0 && isBorderBox && contentOnly && h != Style.DEFAULT && !GXT.isIE) {
1502           h -= getFrameWidth("tb");
1503         } else if(GXT.isIE && isBorderBox && h != Style.DEFAULT && contentOnly){
1504           h-= getFrameWidth("tb");
1505         } else if(offsetHeight == 0 && !isBorderBox && !contentOnly && h != Style.DEFAULT ){
1506           h+= getFrameWidth("tb");
1507         }
1508       }
1509     }
1510     if (w == Style.DEFAULT && h == Style.DEFAULT) {
1511       return new Size(offsetWidth, offsetHeight);
1512     }
1513     return new Size(w != Style.DEFAULT ? w : offsetWidth, h != Style.DEFAULT ? h : offsetHeight);
1514   }
1515 
1516   /**
1517    * Returns the style width. A value is only returned if the specified style is
1518    * in pixels.
1519    * 
1520    * @return the style width
1521    */
1522   public int getStyleWidth() {
1523     String w = dom.getStyle().getProperty("width");
1524     if (w == null || w.equals("")) return 0;
1525     if (w.matches("(auto|em|%|en|ex|pt|in|cm|mm|pc)")) {
1526       return 0;
1527     }
1528     return Util.parseInt(w, 0);
1529   }
1530 
1531   /**
1532    * Returns the element's sub child.
1533    * 
1534    * @param depth the child node depth
1535    * @return the child element
1536    */
1537   public Element getSubChild(int depth) {
1538     Element child = dom;
1539     while (depth-- > 0) {
1540       child = DOM.getChild(child, 0);
1541     }
1542     return child;
1543   }
1544 
1545   /**
1546    * Returns the measured width of the element's text.
1547    * 
1548    * @return the width
1549    */
1550   public int getTextWidth() {
1551     String html = getInnerHtml();
1552     TextMetrics metrics = TextMetrics.get();
1553     metrics.bind(dom);
1554     return metrics.getWidth(html);
1555   }
1556 
1557   /**
1558    * Returns the top Y coordinate.
1559    * 
1560    * @return the top value
1561    */
1562   public int getTop() {
1563     return getTop(true);
1564   }
1565 
1566   /**
1567    * Gets the top Y coordinate.
1568    * 
1569    * @param local true to get the local css position instead of page coordinate
1570    * @return the top value
1571    */
1572   public int getTop(boolean local) {
1573     return local ? Util.parseInt(getStyleAttribute("top"), 0) : getY();
1574   }
1575 
1576   /**
1577    * Returns the the "value" attribute.
1578    * 
1579    * @return the value
1580    */
1581   public String getValue() {
1582     return DOM.getElementProperty(dom, "value");
1583   }
1584 
1585   /**
1586    * Returns the offset width.
1587    * 
1588    * @return the width
1589    */
1590   public int getWidth() {
1591     return dom.getOffsetWidth();
1592   }
1593 
1594   /**
1595    * Returns the element's width.
1596    * 
1597    * @param content true to get the width minus borders and padding
1598    * @return the width
1599    */
1600   public int getWidth(boolean content) {
1601     int w = getWidth();
1602     if (content) {
1603       w -= getFrameWidth("lr");
1604     }
1605     return Math.max(0,w);
1606   }
1607 
1608   /**
1609    * Gets the current X position of the element based on page coordinates.
1610    * Element must be part of the DOM tree to have page coordinates.
1611    * 
1612    * @return the x position of the element
1613    */
1614   public int getX() {
1615     return dom.getAbsoluteLeft();
1616   }
1617 
1618   /**
1619    * Gets the current position of the element based on page coordinates. Element
1620    * must be part of the DOM tree to have page coordinates.
1621    * 
1622    * @return the location
1623    */
1624   public Point getXY() {
1625     return new Point(getX(), getY());
1626   }
1627 
1628   /**
1629    * Gets the current Y position of the element based on page coordinates.
1630    * 
1631    * @return the y position of the element
1632    */
1633   public int getY() {
1634     return dom.getAbsoluteTop();
1635   }
1636 
1637   /**
1638    * Returns the element's z-index.
1639    * 
1640    * @return the z-index
1641    */
1642   public int getZIndex() {
1643     return Util.parseInt(getStyleAttribute("zIndex"), 0);
1644   }
1645 
1646   /**
1647    * Checks if the specified CSS style name exists on this element's DOM node.
1648    * 
1649    * @param style the style name
1650    * @return true if the style name exists, else false
1651    */
1652   public boolean hasStyleName(String style) {
1653 	  /* begin laaglu */
1654 //	    String cls = dom.getClassName();
1655 	    String cls = getClassName(dom);
1656 	  /* end laaglu */
1657     return (" " + cls + " ").indexOf(" " + style + " ") != -1 ? true : false;
1658   }
1659 
1660   /**
1661    * Hides this element
1662    * 
1663    * @return this
1664    */
1665   public El hide() {
1666     return setVisible(false);
1667   }
1668 
1669   /**
1670    * Inserts this element before the passed element.
1671    * 
1672    * @param before the element to insert before
1673    * @return this
1674    */
1675   public El insertBefore(Element before) {
1676     before.getParentElement().insertBefore(dom, before);
1677     return this;
1678   }
1679 
1680   /**
1681    * Inserts the element as a child before the given element.
1682    * 
1683    * @param child the element to insert
1684    * @param before the element the child will be inserted before
1685    * @return this
1686    */
1687   public El insertBefore(Element child, Element before) {
1688     dom.insertBefore(child, before);
1689     return this;
1690   }
1691 
1692   /**
1693    * Inserts the elements as a child before the given element.
1694    * 
1695    * @param elements the elements to insert
1696    * @param before the element the children will be inserted before
1697    * @return this
1698    */
1699   public El insertBefore(Element[] elements, Element before) {
1700     for (int i = 0; i < elements.length; i++) {
1701       insertBefore(elements[i], before);
1702     }
1703     return this;
1704   }
1705 
1706   /**
1707    * Inserts an element at the specified index.
1708    * 
1709    * @param child the child element
1710    * @param index the insert location
1711    * @return this
1712    */
1713   public El insertChild(Element child, int index) {
1714     DOM.insertChild(dom, child, index);
1715     return this;
1716   }
1717 
1718   /**
1719    * Inserts the children at the specified index.
1720    * 
1721    * @param children the children to add
1722    * @param index the insert location
1723    * @return this
1724    */
1725   public El insertChild(Element[] children, int index) {
1726     for (int i = children.length - 1; i >= 0; i--) {
1727       DOM.insertChild(dom, children[i], index);
1728     }
1729     return this;
1730   }
1731 
1732   /**
1733    * Inserts an element as the first child.
1734    * 
1735    * @param element the child element
1736    * @return this
1737    */
1738   public El insertFirst(Element element) {
1739     DOM.insertChild(dom, element, 0);
1740     return this;
1741   }
1742 
1743   /**
1744    * Inserts the children.
1745    * 
1746    * @param elems the child elements
1747    * @return this
1748    */
1749   public El insertFirst(Element[] elems) {
1750     for (int i = 0; i < elems.length; i++) {
1751       DOM.appendChild(dom, elems[i]);
1752     }
1753     return this;
1754   }
1755 
1756   /**
1757    * Creates and inserts a child element.
1758    * 
1759    * @param html the HTML fragment
1760    * @return the new child
1761    */
1762   public El insertFirst(String html) {
1763     return new El(DomHelper.insertFirst(dom, html));
1764   }
1765 
1766   /**
1767    * Inserts an html fragment into this element
1768    * 
1769    * @param where where to insert the html in relation to el - beforeBegin,
1770    *          afterBegin, beforeEnd, afterEnd.
1771    * @param html the HTML fragment
1772    * @return the inserted node (or nearest related if more than 1 inserted)
1773    */
1774   public El insertHtml(String where, String html) {
1775     return new El(DomHelper.insertHtml(where, dom, html));
1776   }
1777 
1778   /**
1779    * Inserts the element into the given parent.
1780    * 
1781    * @param parent the parent element
1782    * @return this
1783    */
1784   public El insertInto(Element parent) {
1785     fly(parent, "_internal").appendChild(dom);
1786     return this;
1787   }
1788 
1789   /**
1790    * Inserts a element.
1791    * 
1792    * @param parent the parent element
1793    * @param index the insert index
1794    * @return this
1795    */
1796   public El insertInto(Element parent, int index) {
1797     fly(parent, "_internal").insertChild(dom, index);
1798     return this;
1799   }
1800 
1801   /**
1802    * Inserts the child element as the last child.
1803    * 
1804    * @param child the element to insert
1805    * @return this
1806    */
1807   public El insertLast(Element child) {
1808     int idx = dom.getChildNodes().getLength();
1809     insertChild(child, idx);
1810     return this;
1811   }
1812 
1813   /**
1814    * Inserts the passed element as a sibling of this element.
1815    * 
1816    * @param elem the element to insert
1817    * @param where 'before' or 'after'
1818    * @return the inserted element
1819    */
1820   public Element insertSibling(Element elem, String where) {
1821     Element refNode = where.equals("before") ? dom : nextSibling();
1822     if (refNode == null) {
1823       DOM.appendChild(DOM.getParent(dom), elem);
1824     } else {
1825       DOM.insertBefore(getParent().dom, elem, refNode);
1826     }
1827     return elem;
1828   }
1829 
1830   /**
1831    * Inserts the passed elements as a sibling of this element.
1832    * 
1833    * @param elems the elements to insert
1834    * @param where where 'before' or 'after'
1835    * @return this
1836    */
1837   public El insertSibling(Element[] elems, String where) {
1838     for (int i = 0; i < elems.length; i++) {
1839       insertSibling(elems[i], where);
1840     }
1841     return this;
1842   }
1843 
1844   /**
1845    * Returns true if this element matches the passed simple selector (e.g.
1846    * div.some-class or span:first-child).
1847    * 
1848    * @param selector selector
1849    * @return true if the element matches the selector, else false
1850    */
1851   public boolean is(String selector) {
1852     return DomQuery.is(dom, selector);
1853   }
1854 
1855   /**
1856    * Returns true if the element is a border box.
1857    * 
1858    * @return true for border box
1859    */
1860   public boolean isBorderBox() {
1861     return isBorderBox(dom);
1862   }
1863 
1864   /**
1865    * Returns true if the element is part of the browser's DOM.
1866    * 
1867    * @return the dom state
1868    */
1869   public boolean isConnected() {
1870     return Document.get().getBody().isOrHasChild(dom);
1871   }
1872 
1873   /**
1874    * Returns true if this element is masked.
1875    * 
1876    * @return the masked state
1877    */
1878   public boolean isMasked() {
1879     return _mask != null && _mask.isVisible();
1880   }
1881 
1882   /**
1883    * Returns true if the child element is or a child of this element.
1884    * 
1885    * @param child the child element
1886    * @return true if is or child of element
1887    */
1888   public boolean isOrHasChild(Element child) {
1889     return DOM.isOrHasChild(dom, child);
1890   }
1891 
1892   /**
1893    * Returns whether the element is scrollable (x or y).
1894    * 
1895    * @return true if scrollable
1896    */
1897   public boolean isScrollable() {
1898     return isScrollableX() || isScrollableY();
1899   }
1900 
1901   /**
1902    * Returns whether the element is scrollable on the x-axis.
1903    * 
1904    * @return true if scrollable on the x-axis
1905    */
1906   public boolean isScrollableX() {
1907     return dom.getScrollWidth() > dom.getClientWidth();
1908   }
1909 
1910   /**
1911    * Returns whether the element is scrollable on the y-axis.
1912    * 
1913    * @return true if scrollable on the y-axis
1914    */
1915   public boolean isScrollableY() {
1916     return dom.getScrollHeight() > dom.getClientHeight();
1917   }
1918 
1919   public boolean isStyleAttribute(Map<String, String> map, boolean matchAll) {
1920     Set<String> collection = map.keySet();
1921     FastMap<String> a = getStyleAttribute(new ArrayList<String>(collection));
1922     for (String s : collection) {
1923       if (map.get(s).equals(a.get(s))) {
1924         if (!matchAll) {
1925           return true;
1926         }
1927       } else {
1928         if (matchAll) {
1929           return false;
1930         }
1931       }
1932     }
1933     return false;
1934   }
1935 
1936   public boolean isStyleAttribute(String attr, String value) {
1937     String a = getStyleAttribute(attr);
1938     return a != null && a.equals(value);
1939   }
1940 
1941   /**
1942    * Returns <code>true</code> if the element is visible using the css
1943    * 'visibiliy' attribute.
1944    * 
1945    * @return the visible state
1946    */
1947   public boolean isVisibility() {
1948     return isStyleAttribute("visibility", "hidden");
1949   }
1950 
1951   /**
1952    * Returns whether the element is currently visible.
1953    * 
1954    * @return true if visible
1955    */
1956   public boolean isVisible() {
1957     return isVisible(false);
1958   }
1959 
1960   /**
1961    * Returns whether the element is currently visible.
1962    * 
1963    * @param deep true to deep test
1964    * 
1965    * @return true if visible
1966    */
1967   public boolean isVisible(boolean deep) {
1968     Map<String, String> map = new FastMap<String>();
1969     map.put("visibility", "hidden");
1970     map.put("display", "none");
1971     boolean vis = !isStyleAttribute(map, false);
1972     El parent = getParent();
1973     Element p = parent != null ? parent.dom : null;
1974     if (p == null) {
1975       return false;
1976     }
1977     if (!deep || !vis) {
1978       return vis;
1979     }
1980     while (p != null && p != XDOM.getBody()) {
1981       if (!fly(p, "_isVisible").isVisible()) {
1982         return false;
1983       }
1984       p = (Element) p.getParentElement();
1985     }
1986 
1987     return true;
1988 
1989   }
1990 
1991   /**
1992    * Returns the element's last child.
1993    * 
1994    * @return the last child
1995    */
1996   public El lastChild() {
1997     Element e = DOM.getChild(dom, DOM.getChildCount(dom) - 1);
1998     return e == null ? null : new El(e);
1999   }
2000 
2001   /**
2002    * Retrieves the data using the request builder and updates the element'c
2003    * contents.
2004    * <p>
2005    * This method is subject to change.
2006    * 
2007    * @param builder the request builder
2008    */
2009   public Request load(RequestBuilder builder) {
2010     try {
2011       builder.setCallback(new RequestCallback() {
2012 
2013         public void onError(Request request, Throwable exception) {
2014           setInnerHtml(exception.getMessage());
2015         }
2016 
2017         public void onResponseReceived(Request request, Response response) {
2018           setInnerHtml(response.getText());
2019         }
2020 
2021       });
2022       return builder.send();
2023     } catch (Exception e) {
2024       setInnerHtml(e.getMessage());
2025       return null;
2026     }
2027   }
2028 
2029   /**
2030    * Makes an element positionable.
2031    */
2032   public El makePositionable() {
2033     return makePositionable(false);
2034   }
2035 
2036   /**
2037    * Makes an element positionable.
2038    * 
2039    * @param absolute <code>true</code> to position absolutely
2040    * @return this
2041    */
2042   public El makePositionable(boolean absolute) {
2043     if (absolute) {
2044       setStyleAttribute("position", "absolute");
2045     } else if ("static".equals(getStyleAttribute("position"))) {
2046       setStyleAttribute("position", "relative");
2047     }
2048     return this;
2049   }
2050 
2051   /**
2052    * Puts a mask over this element to disable user interaction.
2053    * 
2054    * @return the mask element
2055    */
2056   public El mask() {
2057     return mask(null, null);
2058   }
2059 
2060   /**
2061    * Puts a mask over this element to disable user interaction.
2062    * 
2063    * @param message a message to display in the mask
2064    * @return the mask element
2065    */
2066   public El mask(String message) {
2067     return mask(message, null);
2068   }
2069 
2070   /**
2071    * Puts a mask over this element to disable user interaction.
2072    * 
2073    * @param message a message to display in the mask
2074    * @param messageStyleName a CSS style name to be applied to the message text
2075    * @return the mask element
2076    */
2077   public El mask(String message, String messageStyleName) {
2078     if ("static".equals(getStyleAttribute("position"))) {
2079       addStyleName("x-masked-relative");
2080     }
2081     if (_maskMsg != null) {
2082       _maskMsg.remove();
2083     }
2084     if (_mask != null) {
2085       _mask.remove();
2086     }
2087 
2088     _mask = new El("<div class='ext-el-mask'></div>");
2089 
2090     addStyleName("x-masked");
2091     _mask.setDisplayed(true);
2092 
2093     appendChild(_mask.dom);
2094     if (message != null) {
2095       _maskMsg = new El("<div class='ext-el-mask-msg'><div></div></div>");
2096       if (messageStyleName != null) {
2097         _maskMsg.addStyleName(messageStyleName);
2098       }
2099       _maskMsg.firstChild().setInnerHtml(message);
2100       _maskMsg.setDisplayed(true);
2101 
2102       appendChild(_maskMsg.dom);
2103       _maskMsg.center(dom);
2104     }
2105     if (GXT.isIE && !(GXT.isIE7 && GXT.isStrict) && "auto".equals(getStyleAttribute("height"))) {
2106       _mask.setSize(getWidth(), getHeight());
2107     }
2108 
2109     return _mask;
2110   }
2111 
2112   /**
2113    * Returns the elements next sibling.
2114    * 
2115    * @return the sibling element
2116    */
2117   public Element nextSibling() {
2118     return DOM.getNextSibling(dom);
2119   }
2120 
2121   /**
2122    * Returns the elements previous sibling.
2123    * 
2124    * @return the previous sibling
2125    */
2126   public Element previousSibling() {
2127     return dom.getPreviousSibling().cast();
2128   }
2129 
2130   /**
2131    * Removes this element from the DOM
2132    */
2133   public El remove() {
2134     return removeFromParent();
2135   }
2136 
2137   /**
2138    * Removes a child.
2139    * 
2140    * @param child the child to remove
2141    * @return this
2142    */
2143   public El removeChild(Element child) {
2144     dom.removeChild(child);
2145     return this;
2146   }
2147 
2148   /**
2149    * Removes all the elements children.
2150    */
2151   public El removeChildren() {
2152     El child = null;
2153     while ((child = firstChild()) != null) {
2154       dom.removeChild(child.dom);
2155     }
2156     setInnerHtml("");
2157     return this;
2158   }
2159 
2160   /**
2161    * Removes the element from it's parent.
2162    */
2163   public El removeFromParent() {
2164     com.google.gwt.dom.client.Element p = dom.getParentElement();
2165     if (p != null) {
2166       p.removeChild(dom);
2167     }
2168     return this;
2169   }
2170 
2171   /**
2172    * Removes the style names(s) from the element.
2173    * 
2174    * @param styleNames the style names
2175    * @return this
2176    */
2177   public El removeStyleName(String... styleNames) {
2178     for (String s : styleNames) {
2179       removeStyleName(s);
2180     }
2181     return this;
2182   }
2183 
2184   /**
2185    * Removes a style name.
2186    * 
2187    * @param styleName the style names to remove
2188    * @return this
2189    */
2190   public native El removeStyleName(String styleName) /*-{
2191     var dom = this.@com.extjs.gxt.ui.client.core.El::dom;
2192     if(!@com.extjs.gxt.ui.client.core.El::removeStyleNameReCache){
2193       @com.extjs.gxt.ui.client.core.El::removeStyleNameReCache = {};
2194     }
2195     if(styleName && dom.className){
2196       var s = @com.extjs.gxt.ui.client.core.El::removeStyleNameReCache[styleName] = @com.extjs.gxt.ui.client.core.El::removeStyleNameReCache[styleName] || new RegExp('(?:^|\\s+)' + styleName + '(?:\\s+|$)', "g"); 
2197       dom.className = dom.className.replace(s," ");
2198     }
2199     return this;
2200   }-*/;
2201 
2202   /**
2203    * Forces the Browser to repaint this element.
2204    * 
2205    * @return this
2206    */
2207   public El repaint() {
2208     addStyleName("x-repaint");
2209     DeferredCommand.addCommand(new Command() {
2210       public void execute() {
2211         removeStyleName("x-repaint");
2212       }
2213     });
2214     return this;
2215   }
2216 
2217   /**
2218    * Replaces a style name on the element with another. If the old name does not
2219    * exist, the new name will simply be added.
2220    * 
2221    * @param oldStyle the style to replace
2222    * @param newStyle the new style
2223    * @return this
2224    */
2225   public El replaceStyleName(String oldStyle, String newStyle) {
2226     return removeStyleName(oldStyle).addStyleName(newStyle);
2227   }
2228 
2229   public El scrollIntoView(Element container, boolean hscroll) {
2230     return scrollIntoView(container, hscroll, null);
2231   }
2232 
2233   /**
2234    * Scrolls the element into view.
2235    * 
2236    * @param container the container element
2237    * @param hscroll <code>false</code> to disable horizontal scrolling.
2238    */
2239   public El scrollIntoView(Element container, boolean hscroll, int[] offsets) {
2240     if (offsets == null) {
2241       offsets = new int[] {0, 0};
2242     }
2243     Element c = container != null ? container : XDOM.getBody();
2244 
2245     Point o = getOffsetsTo(c);
2246     int l = o.x;
2247     int t = o.y;
2248     l = l + c.getScrollLeft();
2249     t = t + c.getScrollTop();
2250     int b = t + getHeight() + offsets[0];
2251     int r = l + getWidth() + offsets[1];
2252 
2253     int ch = c.getClientHeight();
2254     int ct = c.getScrollTop();
2255     int cb = ct + ch;
2256 
2257     if (getHeight() > ch || t < ct) {
2258       c.setScrollTop(t);
2259     } else if (b > cb) {
2260       c.setScrollTop(b - ch);
2261     }
2262 
2263     if (hscroll) {
2264       int cl = c.getScrollLeft();
2265       int cw = c.getClientWidth();
2266       int cr = cl + cw;
2267 
2268       if (getWidth() > cw || l < cl) {
2269         c.setScrollLeft(l);
2270       } else if (r > cr) {
2271         c.setScrollLeft(r - cw);
2272       }
2273     }
2274     return this;
2275   }
2276 
2277   /**
2278    * Scrolls this element the specified scroll point.
2279    * 
2280    * @param side either "left" for scrollLeft values or "top" for scrollTop
2281    *          values.
2282    * @param value the new scroll value
2283    * @return this
2284    */
2285   public El scrollTo(String side, int value) {
2286     if ("left".equalsIgnoreCase(side)) {
2287       setScrollLeft(value);
2288     } else if ("top".equalsIgnoreCase(side)) {
2289       setScrollTop(value);
2290     }
2291     return this;
2292   }
2293 
2294   /**
2295    * Scrolls this element the specified scroll point.
2296    * 
2297    * @param side side either "left" for scrollLeft values or "top" for scrollTop
2298    *          values.
2299    * @param value the new scroll value
2300    * @param config the fx config
2301    * @return this
2302    */
2303   public El scrollTo(String side, int value, FxConfig config) {
2304     ScrollDir dir = ScrollDir.VERTICAL;
2305     if (side.equalsIgnoreCase("left")) {
2306       dir = ScrollDir.HORIZONTAL;
2307     }
2308     BaseEffect.scroll(this, config, dir, value);
2309     return this;
2310   }
2311 
2312   /**
2313    * Selects child nodes based on the passed CSS selector (the selector should
2314    * not contain an id).
2315    * 
2316    * @param selector the selector/xpath query
2317    * @return the matching elements
2318    */
2319   public NodeList<Element> select(String selector) {
2320     return DomQuery.select(selector, dom);
2321   }
2322 
2323   /**
2324    * Selects a single element.
2325    * 
2326    * @param selector the CSS selector
2327    * @return the matching element
2328    */
2329   public El selectNode(String selector) {
2330     Element el = DomQuery.selectNode(selector, dom);
2331     if (el != null) {
2332       return new El(el);
2333     }
2334     return null;
2335   }
2336 
2337   /**
2338    * Adds or removes a border. The style name 'x-border' is added to the widget
2339    * to display a border.
2340    * 
2341    * @param show the show state
2342    * @return this
2343    */
2344   public El setBorders(boolean show) {
2345     if (show) {
2346       addStyleName("x-border");
2347       setStyleAttribute("borderWidth", "1px");
2348     } else {
2349       removeStyleName("x-border");
2350       setStyleAttribute("borderWidth", "0px");
2351     }
2352     return this;
2353   }
2354 
2355   /**
2356    * Sets the element's bounds.
2357    * 
2358    * @param x the x coordinate
2359    * @param y the y coordinate
2360    * @param width the new width
2361    * @param height the new height
2362    * @return this
2363    */
2364   public El setBounds(int x, int y, int width, int height) {
2365     return setBounds(x, y, width, height, false);
2366   }
2367 
2368   /**
2369    * Sets the element's bounds.
2370    * 
2371    * @param x the x coordinate
2372    * @param y the y coordinate
2373    * @param width the new width
2374    * @param height the new height
2375    * @param adjust true to adjust for box model issues
2376    * @return this
2377    */
2378   public El setBounds(int x, int y, int width, int height, boolean adjust) {
2379     setPagePosition(x, y);
2380     setSize(width, height, adjust);
2381     return this;
2382   }
2383 
2384   /**
2385    * Sets the element's bounds.
2386    * 
2387    * @param bounds the new bounds
2388    * @return this
2389    */
2390   public El setBounds(Rectangle bounds) {
2391     setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
2392     return this;
2393   }
2394 
2395   /**
2396    * Sets the element's bounds.
2397    * 
2398    * @param bounds the new bounds
2399    * @param content <code>true</code> to adjust for box model issues
2400    * @return this
2401    */
2402   public El setBounds(Rectangle bounds, boolean content) {
2403     setBounds(bounds.x, bounds.y, bounds.width, bounds.height, content);
2404     return this;
2405   }
2406 
2407   /**
2408    * Sets the CSS display property.
2409    * 
2410    * @param display true to display the element using its default display
2411    * @return this
2412    */
2413   public El setDisplayed(boolean display) {
2414     String value = display ? originalDisplay : "none";
2415     setStyleAttribute("display", value);
2416     return this;
2417   }
2418 
2419   /**
2420    * Sets the CSS display property.
2421    * 
2422    * @param display the display value
2423    * @return this
2424    */
2425   public El setDisplayed(String display) {
2426     setStyleAttribute("display", display);
2427     return this;
2428   }
2429 
2430   /**
2431    * Sets an element's attribute.
2432    * 
2433    * @param attr the attribute name
2434    * @param value the value
2435    * @return this
2436    */
2437   public El setElementAttribute(String attr, boolean value) {
2438     DOM.setElementPropertyBoolean(dom, attr, value);
2439     return this;
2440   }
2441 
2442   /**
2443    * Sets an element's attribute.
2444    * 
2445    * @param attr the attribute name
2446    * @param value the value
2447    * @return this
2448    */
2449   public El setElementAttribute(String attr, int value) {
2450     return setElementAttribute(attr, "" + value);
2451   }
2452 
2453   /**
2454    * Sets an element's attribute.
2455    * 
2456    * @param attr the attribute name
2457    * @param value the value
2458    * @return this
2459    */
2460   public El setElementAttribute(String attr, String value) {
2461     DOM.setElementAttribute(dom, attr, value);
2462     return this;
2463   }
2464 
2465   /**
2466    * Convenience function for setting disabled/enabled by boolean.
2467    * 
2468    * @param enabled the enabled state
2469    */
2470   public void setEnabled(boolean enabled) {
2471     if (!enabled) {
2472       disable();
2473     } else {
2474       enable();
2475     }
2476   }
2477 
2478   /**
2479    * True to focus, false to blur.
2480    * 
2481    * @param focus the new focus state
2482    */
2483   public native El setFocus(boolean focus) /*-{
2484     var dom = this.@com.extjs.gxt.ui.client.core.El::dom;
2485     try {
2486     if (focus) {
2487     dom.focus();
2488     } else {
2489     dom.blur();
2490     }
2491     } 
2492     catch(err) {
2493     }
2494     return this;
2495   }-*/;
2496 
2497   /**
2498    * Sets the elements height.
2499    * 
2500    * @param height the height
2501    * @return this
2502    */
2503   public El setHeight(int height) {
2504     return setHeight(height, false);
2505   }
2506 
2507   /**
2508    * Sets the elements height.
2509    * 
2510    * @param height the height
2511    * @param adjust <code>true</code> to adjust for box model issues
2512    * @return this
2513    */
2514   public El setHeight(int height, boolean adjust) {
2515     if (adjust && !isBorderBox()) {
2516       height -= getFrameWidth("tb");
2517     }
2518     if (height >= 0) {
2519       dom.getStyle().setPropertyPx("height", height);
2520     }
2521     return this;
2522   }
2523 
2524   /**
2525    * Sets the elements height.
2526    * 
2527    * @param height the height
2528    * @return this
2529    */
2530   public El setHeight(String height) {
2531     DOM.setStyleAttribute(dom, "height", addUnits(height, "px"));
2532     return this;
2533   }
2534 
2535   /**
2536    * Sets the the icon for an element either as a CSS style name or image path.
2537    * 
2538    * @param style the style are image path
2539    */
2540   public El setIconStyle(String style) {
2541     if (Util.isImagePath(style)) {
2542       setStyleAttribute("backgroundImage", "url(" + style + ")");
2543     } else {
2544       dom.setClassName(style);
2545     }
2546     return this;
2547   }
2548 
2549   /**
2550    * Sets the element's id.
2551    * 
2552    * @param id the new id
2553    * @return this
2554    */
2555   public El setId(String id) {
2556     if (id == null) {
2557       id = XDOM.getUniqueId();
2558     }
2559     dom.setId(id);
2560     return this;
2561   }
2562 
2563   /**
2564    * Sets the element's inner html.
2565    * 
2566    * @param html the new HTML
2567    * @return this
2568    */
2569   public El setInnerHtml(String html) {
2570     DOM.setInnerHTML(dom, html);
2571     return this;
2572   }
2573 
2574   /**
2575    * Sets an element's property.
2576    * 
2577    * @param property the property name
2578    * @param value the value
2579    * @return this
2580    */
2581   public El setIntElementProperty(String property, int value) {
2582     DOM.setElementPropertyInt(dom, property, value);
2583     return this;
2584   }
2585 
2586   /**
2587    * Sets the element's left position directly using CSS style (instead of
2588    * {@link #setX}).
2589    * 
2590    * @param left the left value
2591    * @return this
2592    */
2593   public El setLeft(int left) {
2594     dom.getStyle().setPropertyPx("left", left);
2595     return this;
2596   }
2597 
2598   /**
2599    * Quick set left and top adding default units.
2600    * 
2601    * @param left the left value
2602    * @param top the top value
2603    * @return this
2604    */
2605   public El setLeftTop(int left, int top) {
2606     setLeft(left);
2607     setTop(top);
2608     return this;
2609   }
2610 
2611   /**
2612    * Sets the elements's margin.
2613    * 
2614    * @param margin the margin
2615    * @return this
2616    */
2617   public El setMargins(Margins margin) {
2618     if (margin != null) {
2619       setStyleAttribute("marginLeft", margin.left + "px");
2620       setStyleAttribute("marginTop", margin.top + "px");
2621       setStyleAttribute("marginRight", margin.right + "px");
2622       setStyleAttribute("marginBottom", margin.bottom + "px");
2623     }
2624     return this;
2625   }
2626 
2627   /**
2628    * Sets the elements's padding.
2629    * 
2630    * @param padding the padding
2631    * @return this
2632    */
2633   public El setPadding(Padding padding) {
2634     if (padding != null) {
2635       setStyleAttribute("paddingLeft", padding.left + "px");
2636       setStyleAttribute("paddingTop", padding.top + "px");
2637       setStyleAttribute("paddingRight", padding.right + "px");
2638       setStyleAttribute("paddingBottom", padding.bottom + "px");
2639     }
2640     return this;
2641   }
2642 
2643   /**
2644    * Sets the element's position in page coordinates.
2645    * 
2646    * @param x the x coordinate
2647    * @param y the y coordinate
2648    * @return this
2649    */
2650   public El setPagePosition(int x, int y) {
2651     setX(x);
2652     setY(y);
2653     return this;
2654   }
2655 
2656   /**
2657    * Sets the element's horizontal scroll position.
2658    * 
2659    * @param left the left value
2660    * @return this
2661    */
2662   public El setScrollLeft(int left) {
2663     DOM.setElementPropertyInt(dom, "scrollLeft", left);
2664     return this;
2665   }
2666 
2667   /**
2668    * Sets the element's vertical scroll position.
2669    * 
2670    * @param top the top value
2671    * @return this
2672    */
2673   public El setScrollTop(int top) {
2674     DOM.setElementPropertyInt(dom, "scrollTop", top);
2675     return this;
2676   }
2677 
2678   /**
2679    * Sets the element's size.
2680    * 
2681    * @param width the new width
2682    * @param height the new height
2683    * @return this
2684    */
2685   public El setSize(int width, int height) {
2686     setSize(width, height, false);
2687     return this;
2688   }
2689 
2690   /**
2691    * Set the size of the element.
2692    * 
2693    * @param width the new width
2694    * @param height the new height
2695    * @param adjust <code>true</code> to adjust for box model issues
2696    * @return this
2697    */
2698   public El setSize(int width, int height, boolean adjust) {
2699     if (adjust && !isBorderBox()) {
2700       Size frameWidth = getFrameSize();
2701       width -= frameWidth.width;
2702       height -= frameWidth.height;
2703     }
2704     if (width >= 0) {
2705       dom.getStyle().setPropertyPx("width", width);
2706     }
2707     if (height >= 0) {
2708       dom.getStyle().setPropertyPx("height", height);
2709     }
2710     return this;
2711   }
2712 
2713   /**
2714    * Sets the element's size.
2715    * 
2716    * @param size the size
2717    * @return this
2718    */
2719   public El setSize(Size size) {
2720     setSize(size.width, size.height);
2721     return this;
2722   }
2723 
2724   /**
2725    * Sets the element's size.
2726    * 
2727    * @param width the new size
2728    * @param height the new height
2729    * @return this
2730    */
2731   public El setSize(String width, String height) {
2732     setWidth(width);
2733     setHeight(height);
2734     return this;
2735   }
2736 
2737   /**
2738    * Sets a style attribute.
2739    * 
2740    * @param attr the attribute name
2741    * @param value the int value
2742    * @return this
2743    */
2744   public El setStyleAttribute(String attr, Object value) {
2745     computedStyle.setStyleAttribute(dom, attr, value);
2746     return this;
2747   }
2748 
2749   /**
2750    * Sets the element's style name.
2751    * 
2752    * @param style the style name
2753    * @return this
2754    */
2755   public El setStyleName(String style) {
2756     dom.setClassName(style);
2757     return this;
2758   }
2759 
2760   /**
2761    * Adds or removes the style name.
2762    * 
2763    * @param style the style name
2764    * @param add true to add, false to remove
2765    * @return this
2766    */
2767   public El setStyleName(String style, boolean add) {
2768     if (add) {
2769       addStyleName(style);
2770     } else {
2771       removeStyleName(style);
2772     }
2773     return this;
2774   }
2775 
2776   /**
2777    * Sets the element's size using style attributes.
2778    * 
2779    * @param width the width
2780    * @param height the height
2781    * @return this
2782    */
2783   public El setStyleSize(int width, int height) {
2784     setStyleAttribute("width", width);
2785     setStyleAttribute("height", height);
2786     return this;
2787   }
2788 
2789   /**
2790    * Sets the element's tab index.
2791    * 
2792    * @param index the tab index
2793    * @return this
2794    */
2795   public El setTabIndex(int index) {
2796     DOM.setElementPropertyInt(dom, "tabIndex", index);
2797     return null;
2798   }
2799 
2800   /**
2801    * Sets the element's title property.
2802    * 
2803    * @param title the new title
2804    * @return this
2805    */
2806   public El setTitle(String title) {
2807     dom.setTitle(title);
2808     return this;
2809   }
2810 
2811   /**
2812    * Sets the element's top position directly using CSS style (instead of
2813    * {@link #setY}).
2814    * 
2815    * @param top the top value
2816    * @return this
2817    */
2818   public El setTop(int top) {
2819     dom.getStyle().setPropertyPx("top", top);
2820     return this;
2821   }
2822 
2823   /**
2824    * Sets the element's value property.
2825    * 
2826    * @param value the value
2827    */
2828   public El setValue(String value) {
2829     dom.setPropertyString("value", value);
2830     return this;
2831   }
2832 
2833   /**
2834    * Sets the elements css 'visibility' property. Behavior is different than
2835    * using the 'display' property.
2836    * 
2837    * @param visible <code>true</code> to show, <code>false</code> to hide
2838    * @return this
2839    */
2840   public El setVisibility(boolean visible) {
2841     setStyleAttribute("visibility", visible ? "visible" : "hidden");
2842     return this;
2843   }
2844 
2845   /**
2846    * Sets the element's visibility mode. When setVisible() is called it will use
2847    * this to determine whether to set the visibility or the display property.
2848    * 
2849    * @param visMode value {link VisMode#VISIBILITY}} or {@link VisMode#DISPLAY}
2850    * @return this
2851    */
2852   public El setVisibilityMode(VisMode visMode) {
2853     visiblityMode = visMode;
2854     return this;
2855   }
2856 
2857   /**
2858    * Sets the visibility of the element (see details). If the vis mode is set to
2859    * DISPLAY, it will use the display property to hide the element, otherwise it
2860    * uses visibility. The default is to hide and show using the DISPLAY
2861    * property.
2862    * 
2863    * @param visible whether the element is visible
2864    * @return this
2865    */
2866   public El setVisible(boolean visible) {
2867     if (visiblityMode == VisMode.DISPLAY) {
2868       return setDisplayed(visible);
2869     } else {
2870       return setVisibility(visible);
2871     }
2872   }
2873 
2874   /**
2875    * Sets the element's width.
2876    * 
2877    * @param width the new width
2878    * @return this
2879    */
2880   public El setWidth(int width) {
2881     return setWidth(width, false);
2882   }
2883 
2884   /**
2885    * Sets the elements's width.
2886    * 
2887    * @param width the new width
2888    * @param adjust <code>true</code> to adjust for box model issues
2889    * @return this
2890    */
2891   public El setWidth(int width, boolean adjust) {
2892     if (adjust && !isBorderBox()) {
2893       width -= getFrameWidth("lr");
2894     }
2895     if (width >= 0) {
2896       dom.getStyle().setPropertyPx("width", width);
2897     }
2898     return this;
2899   }
2900 
2901   /**
2902    * Sets the element's width.
2903    * 
2904    * @param width the new width
2905    * @return this
2906    */
2907   public El setWidth(String width) {
2908     DOM.setStyleAttribute(dom, "width", addUnits(width, "px"));
2909     return this;
2910   }
2911 
2912   /**
2913    * Sets the X position of the element based on page coordinates. Element must
2914    * be part of the DOM tree to have page coordinates.
2915    * 
2916    * @param x the x coordinate
2917    * @return this
2918    */
2919   public El setX(int x) {
2920     return setXY(x, Style.DEFAULT);
2921   }
2922 
2923   /**
2924    * Sets the elements position in page coordinates.
2925    * 
2926    * @param x the x coordinate
2927    * @param y the y coordinate
2928    * @return this
2929    */
2930   public El setXY(int x, int y) {
2931     return setXY(new Point(x, y));
2932   }
2933 
2934   /**
2935    * Sets the elements position in page coordinates.
2936    * 
2937    * @param x the x coordinate
2938    * @param y the y coordinate
2939    * @return this
2940    */
2941   public El setXY(int x, int y, FxConfig config) {
2942     if (config == null) {
2943       setXY(x, y);
2944     } else {
2945       Fx fx = new Fx(config);
2946       fx.run(new Move(this, x, y));
2947     }
2948     return this;
2949   }
2950 
2951   /**
2952    * Sets the element's position in page coordinates.
2953    * 
2954    * @param p the position
2955    * @return this
2956    */
2957   public El setXY(Point p) {
2958     makePositionable();
2959     Point pts = translatePoints(p);
2960     if (p.x != Style.DEFAULT) {
2961       setLeft(pts.x);
2962     }
2963     if (p.y != Style.DEFAULT) {
2964       setTop(pts.y);
2965     }
2966     return this;
2967   }
2968 
2969   /**
2970    * Sets the Y position of the element based on page coordinates. Element must
2971    * be part of the DOM tree to have page coordinates.
2972    * 
2973    * @param y the y coordinate
2974    * @return this
2975    */
2976   public El setY(int y) {
2977     return setXY(Style.DEFAULT, y);
2978   }
2979 
2980   /**
2981    * Sets the element's z-index.
2982    * 
2983    * @param zIndex the z-index value
2984    * @return this
2985    */
2986   public El setZIndex(int zIndex) {
2987     DOM.setIntStyleAttribute(dom, "zIndex", Math.max(0, zIndex));
2988     return this;
2989   }
2990 
2991   /**
2992    * Shows this element
2993    * 
2994    * @return this
2995    */
2996   public El show() {
2997     return setVisible(true);
2998   }
2999 
3000   /**
3001    * Slides the element in.
3002    * 
3003    * @param direction the direction
3004    * @param config the fx config
3005    * @return this
3006    */
3007   public El slideIn(Direction direction, FxConfig config) {
3008     BaseEffect.slideIn(this, config, direction);
3009     return this;
3010   }
3011 
3012   /**
3013    * Slides the element out.
3014    * 
3015    * @param direction the direction
3016    * @param config the fx config
3017    * @return this
3018    */
3019   public El slideOut(Direction direction, FxConfig config) {
3020     BaseEffect.slideOut(this, config, direction);
3021     return this;
3022   }
3023 
3024   /**
3025    * Returns the element's sub child.
3026    * 
3027    * @param depth the child node depth
3028    * @return the child element
3029    */
3030   public El subChild(int depth) {
3031     Element child = dom;
3032     while (depth-- > 0) {
3033       child = DOM.getChild(child, 0);
3034     }
3035     return new El(child);
3036   }
3037 
3038   /**
3039    * Synchronizes the layer.
3040    * 
3041    * @param show true to show
3042    */
3043   public El sync(boolean show) {
3044     return this;
3045   }
3046 
3047   public String toString() {
3048     return getOuterHtml();
3049   }
3050 
3051   public Point translatePoints(Point p) {
3052     List<String> list = new ArrayList<String>(3);
3053     list.add("position");
3054     list.add("left");
3055     list.add("top");
3056 
3057     Map<String, String> map = getStyleAttribute(list);
3058     boolean relative = "relative".equals(map.get("position"));
3059     int l = Util.parseInt(map.get("left"), -11234);
3060     int t = Util.parseInt(map.get("top"), -11234);
3061 
3062     l = l != -11234 ? l : (relative ? 0 : dom.getOffsetLeft());
3063     t = t != -11234 ? t : (relative ? 0 : dom.getOffsetTop());
3064 
3065     Point o = getXY();
3066     return new Point(p.x - o.x + l, p.y - o.y + t);
3067   }
3068 
3069   /**
3070    * Return clipping (overflow) to original clipping before clip() was called.
3071    * 
3072    * @return this
3073    */
3074   public El unclip() {
3075     if (isClipped) {
3076       isClipped = false;
3077       setStyleAttribute("overflow", originalClipped[0]);
3078       setStyleAttribute("overflowX", originalClipped[1]);
3079       setStyleAttribute("overflowY", originalClipped[2]);
3080     }
3081     return this;
3082   }
3083 
3084   /**
3085    * Removes a previously applied mask.
3086    * 
3087    * return this
3088    */
3089   public El unmask() {
3090     if (_mask != null) {
3091       if (_maskMsg != null) {
3092         _maskMsg.remove();
3093         _maskMsg = null;
3094       }
3095       _mask.setVisible(false);
3096       _mask.remove();
3097       _mask = null;
3098       removeStyleName("x-masked", "x-masked-relative");
3099     }
3100     return this;
3101   }
3102 
3103   /**
3104    * Unwraps the child element.
3105    * 
3106    * @param bounds the original bounds
3107    */
3108   public El unwrap(Element child, Rectangle bounds) {
3109     El.fly(child, "_internal").setLeftTop(bounds.x, bounds.y);
3110     Element p = dom.getParentElement().cast();
3111     int pos = DOM.getChildIndex(p, dom);
3112     p.removeChild(dom);
3113     DOM.insertChild(p, child, pos);
3114     return this;
3115   }
3116 
3117   /**
3118    * Sets the innerHTML to the given markup.
3119    * 
3120    * @param html the html
3121    * @return this
3122    */
3123   public El update(String html) {
3124     DOM.setInnerHTML(dom, html);
3125     return this;
3126   }
3127 
3128   /**
3129    * Sets the element's z-index using {@link XDOM#getTopZIndex()} to ensure it
3130    * has the highest values.
3131    * 
3132    * @param adj the adjustment to be applied to the z-index value
3133    * 
3134    * @return this
3135    */
3136   public El updateZIndex(int adj) {
3137     setZIndex(XDOM.getTopZIndex() + adj);
3138     return this;
3139   }
3140 
3141   /**
3142    * Wraps the element with the specified wrapper. The wrapper will have the
3143    * same size and position of the element. The original bounds can be used to
3144    * 'unwrap' the element.
3145    * 
3146    * @param wrapper the wrapper element
3147    * @return the original bounds
3148    */
3149   public Rectangle wrap(Element wrapper) {
3150     El wrap = new El(wrapper);
3151     wrap.setVisible(false);
3152 
3153     String pos = getStyleAttribute("position");
3154     wrap.setStyleAttribute("position", pos);
3155 
3156     int l = getLeft();
3157     int t = getTop();
3158 
3159     setLeft(5000);
3160     setVisible(true);
3161 
3162     int h = getComputedHeight();
3163     int w = getComputedWidth();
3164 
3165     setLeft(1);
3166     setStyleAttribute("overflow", "hidden");
3167     setVisible(false);
3168 
3169     wrap.insertBefore(dom);
3170     wrap.appendChild(dom);
3171 
3172     wrap.setStyleAttribute("overflow", "hidden");
3173 
3174     wrap.setLeft(l);
3175     wrap.setTop(t);
3176 
3177     setTop(0);
3178     setLeft(0);
3179 
3180     return new Rectangle(l, t, w, h);
3181   }
3182 
3183   protected Point getConstrainToXY(Element elem, Point proposedXY) {
3184     int vw, vh, vx = 0, vy = 0;
3185     if (elem == XDOM.getBody()) {
3186       vw = XDOM.getViewportSize().width;
3187       vh = XDOM.getViewportSize().height;
3188     } else {
3189       vw = fly(elem, "_internal").getWidth();
3190       vh = fly(elem, "_internal").getHeight();
3191     }
3192 
3193     Point xy = proposedXY;
3194     int x = xy.x;
3195     int y = xy.y;
3196 
3197     int vr = vx + vw;
3198     int vb = vy + vh;
3199 
3200     int w = getWidth();
3201     int h = getHeight();
3202 
3203     if ((x + w) > vr) {
3204       x = vr - w;
3205     }
3206     if ((y + h) > vb) {
3207       y = vb - h;
3208 
3209     }
3210 
3211     // then make sure top/left isn't negative
3212     if (x < vx) {
3213       x = vx;
3214     }
3215     if (y < vy) {
3216       y = vy;
3217     }
3218 
3219     return new Point(x, y);
3220   }
3221 
3222   private native boolean isLeftorRight(String s) /*-{
3223     if(@com.extjs.gxt.ui.client.core.El::leftRightTest == null){
3224     @com.extjs.gxt.ui.client.core.El::leftRightTest = new RegExp("Left|Right");
3225     }
3226     return @com.extjs.gxt.ui.client.core.El::leftRightTest.test(s);
3227   }-*/;
3228   /* begin laaglu */
3229   public static native String getClassName(Element dom) /*-{
3230      var cn = dom.className;
3231 	 //@com.google.gwt.core.client.GWT::log(Ljava/lang/String;)(typeof(cn));
3232      if ("object" == typeof(cn)) {
3233        return cn.baseVal;
3234      }
3235 	 return cn;
3236   }-*/;
3237   
3238 
3239   private static native void setClassName(Element dom, String value) /*-{
3240      var cn = dom.className;
3241      if ("object" == typeof(cn)) {
3242        dom.className.baseVal = value;
3243        return;
3244      }
3245      dom.className = value;
3246   }-*/;
3247 
3248 
3249   /* end laaglu */
3250 }