2 * @class Ext.core.Element
7 isCSS1 = doc.compatMode == "CSS1Compat",
8 ELEMENT = Ext.core.Element,
11 _fly = new Ext.core.Element.Flyweight();
17 // If the browser does not support document.activeElement we need some assistance.
18 // This covers old Safari 3.2 (4.0 added activeElement along with just about all
19 // other browsers). We need this support to handle issues with old Safari.
20 if (!('activeElement' in doc) && doc.addEventListener) {
21 doc.addEventListener('focus',
23 if (ev && ev.target) {
24 activeElement = (ev.target == doc) ? null : ev.target;
30 * Helper function to create the function that will restore the selection.
32 function makeSelectionRestoreFn (activeEl, start, end) {
34 activeEl.selectionStart = start;
35 activeEl.selectionEnd = end;
40 isAncestor : function(p, c) {
48 } else if (p.compareDocumentPosition) {
49 return !!(p.compareDocumentPosition(c) & 16);
51 while ((c = c.parentNode)) {
60 * Returns the active element in the DOM. If the browser supports activeElement
61 * on the document, this is returned. If not, the focus is tracked and the active
62 * element is maintained internally.
63 * @return {HTMLElement} The active (focused) element in the document.
65 getActiveElement: function () {
66 return doc.activeElement || activeElement;
70 * Creates a function to call to clean up problems with the work-around for the
71 * WebKit RightMargin bug. The work-around is to add "display: 'inline-block'" to
72 * the element before calling getComputedStyle and then to restore its original
73 * display value. The problem with this is that it corrupts the selection of an
74 * INPUT or TEXTAREA element (as in the "I-beam" goes away but ths focus remains).
75 * To cleanup after this, we need to capture the selection of any such element and
76 * then restore it after we have restored the display style.
78 * @param target {Element} The top-most element being adjusted.
81 getRightMarginFixCleaner: function (target) {
82 var supports = Ext.supports,
83 hasInputBug = supports.DisplayChangeInputSelectionBug,
84 hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug;
86 if (hasInputBug || hasTextAreaBug) {
87 var activeEl = doc.activeElement || activeElement, // save a call
88 tag = activeEl && activeEl.tagName,
92 if ((hasTextAreaBug && tag == 'TEXTAREA') ||
93 (hasInputBug && tag == 'INPUT' && activeEl.type == 'text')) {
94 if (ELEMENT.isAncestor(target, activeEl)) {
95 start = activeEl.selectionStart;
96 end = activeEl.selectionEnd;
98 if (Ext.isNumber(start) && Ext.isNumber(end)) { // to be safe...
99 // We don't create the raw closure here inline because that
100 // will be costly even if we don't want to return it (nested
101 // function decls and exprs are often instantiated on entry
102 // regardless of whether execution ever reaches them):
103 return makeSelectionRestoreFn(activeEl, start, end);
109 return Ext.emptyFn; // avoid special cases, just return a nop
112 getViewWidth : function(full) {
113 return full ? ELEMENT.getDocumentWidth() : ELEMENT.getViewportWidth();
116 getViewHeight : function(full) {
117 return full ? ELEMENT.getDocumentHeight() : ELEMENT.getViewportHeight();
120 getDocumentHeight: function() {
121 return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, ELEMENT.getViewportHeight());
124 getDocumentWidth: function() {
125 return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, ELEMENT.getViewportWidth());
128 getViewportHeight: function(){
130 (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :
134 getViewportWidth : function() {
135 return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth :
136 Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;
139 getY : function(el) {
140 return ELEMENT.getXY(el)[1];
143 getX : function(el) {
144 return ELEMENT.getXY(el)[0];
147 getXY : function(el) {
158 bd = (doc.body || doc.documentElement),
164 hasAbsolute = fly(el).isStyle("position", "absolute");
166 if (el.getBoundingClientRect) {
167 b = el.getBoundingClientRect();
168 scroll = fly(document).getScroll();
169 ret = [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
178 hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");
181 y += bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
182 x += bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
184 if (p != el && !pe.isStyle('overflow','visible')) {
192 if (Ext.isSafari && hasAbsolute) {
197 if (Ext.isGecko && !hasAbsolute) {
199 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
200 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
204 while (p && p != bd) {
205 if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {
217 setXY : function(el, xy) {
218 (el = Ext.fly(el, '_setXY')).position();
220 var pts = el.translatePoints(xy),
221 style = el.dom.style,
225 if (!isNaN(pts[pos])) {
226 style[pos] = pts[pos] + "px";
231 setX : function(el, x) {
232 ELEMENT.setXY(el, [x, false]);
235 setY : function(el, y) {
236 ELEMENT.setXY(el, [false, y]);
240 * Serializes a DOM form into a url encoded string
241 * @param {Object} form The form
242 * @return {String} The url encoded form
244 serializeForm: function(form) {
245 var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,
247 encoder = encodeURIComponent,
253 Ext.each(fElements, function(element){
257 if (!element.disabled && name) {
258 if (/select-(one|multiple)/i.test(type)) {
259 Ext.each(element.options, function(opt){
261 hasValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttributeNode('value').specified;
262 data += Ext.String.format("{0}={1}&", encoder(name), encoder(hasValue ? opt.value : opt.text));
265 } else if (!(/file|undefined|reset|button/i.test(type))) {
266 if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)) {
267 data += encoder(name) + '=' + encoder(element.value) + '&';
268 hasSubmit = /submit/i.test(type);
273 return data.substr(0, data.length - 1);