/** * @class Ext.Element */ (function(){ var doc = document, activeElement = null, isCSS1 = doc.compatMode == "CSS1Compat", ELEMENT = Ext.Element, fly = function(el){ if (!_fly) { _fly = new Ext.Element.Flyweight(); } _fly.dom = el; return _fly; }, _fly; // If the browser does not support document.activeElement we need some assistance. // This covers old Safari 3.2 (4.0 added activeElement along with just about all // other browsers). We need this support to handle issues with old Safari. if (!('activeElement' in doc) && doc.addEventListener) { doc.addEventListener('focus', function (ev) { if (ev && ev.target) { activeElement = (ev.target == doc) ? null : ev.target; } }, true); } /* * Helper function to create the function that will restore the selection. */ function makeSelectionRestoreFn (activeEl, start, end) { return function () { activeEl.selectionStart = start; activeEl.selectionEnd = end; }; } Ext.apply(ELEMENT, { isAncestor : function(p, c) { var ret = false; p = Ext.getDom(p); c = Ext.getDom(c); if (p && c) { if (p.contains) { return p.contains(c); } else if (p.compareDocumentPosition) { return !!(p.compareDocumentPosition(c) & 16); } else { while ((c = c.parentNode)) { ret = c == p || ret; } } } return ret; }, /** * Returns the active element in the DOM. If the browser supports activeElement * on the document, this is returned. If not, the focus is tracked and the active * element is maintained internally. * @return {HTMLElement} The active (focused) element in the document. */ getActiveElement: function () { return doc.activeElement || activeElement; }, /** * Creates a function to call to clean up problems with the work-around for the * WebKit RightMargin bug. The work-around is to add "display: 'inline-block'" to * the element before calling getComputedStyle and then to restore its original * display value. The problem with this is that it corrupts the selection of an * INPUT or TEXTAREA element (as in the "I-beam" goes away but ths focus remains). * To cleanup after this, we need to capture the selection of any such element and * then restore it after we have restored the display style. * * @param target {Element} The top-most element being adjusted. * @private */ getRightMarginFixCleaner: function (target) { var supports = Ext.supports, hasInputBug = supports.DisplayChangeInputSelectionBug, hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug; if (hasInputBug || hasTextAreaBug) { var activeEl = doc.activeElement || activeElement, // save a call tag = activeEl && activeEl.tagName, start, end; if ((hasTextAreaBug && tag == 'TEXTAREA') || (hasInputBug && tag == 'INPUT' && activeEl.type == 'text')) { if (ELEMENT.isAncestor(target, activeEl)) { start = activeEl.selectionStart; end = activeEl.selectionEnd; if (Ext.isNumber(start) && Ext.isNumber(end)) { // to be safe... // We don't create the raw closure here inline because that // will be costly even if we don't want to return it (nested // function decls and exprs are often instantiated on entry // regardless of whether execution ever reaches them): return makeSelectionRestoreFn(activeEl, start, end); } } } } return Ext.emptyFn; // avoid special cases, just return a nop }, getViewWidth : function(full) { return full ? ELEMENT.getDocumentWidth() : ELEMENT.getViewportWidth(); }, getViewHeight : function(full) { return full ? ELEMENT.getDocumentHeight() : ELEMENT.getViewportHeight(); }, getDocumentHeight: function() { return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, ELEMENT.getViewportHeight()); }, getDocumentWidth: function() { return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, ELEMENT.getViewportWidth()); }, getViewportHeight: function(){ return Ext.isIE ? (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) : self.innerHeight; }, getViewportWidth : function() { return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth : Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth; }, getY : function(el) { return ELEMENT.getXY(el)[1]; }, getX : function(el) { return ELEMENT.getXY(el)[0]; }, getOffsetParent: function (el) { el = Ext.getDom(el); try { // accessing offsetParent can throw "Unspecified Error" in IE6-8 (not 9) return el.offsetParent; } catch (e) { var body = document.body; // safe bet, unless... return (el == body) ? null : body; } }, getXY : function(el) { var p, pe, b, bt, bl, dbd, x = 0, y = 0, scroll, hasAbsolute, bd = (doc.body || doc.documentElement), ret; el = Ext.getDom(el); if(el != bd){ hasAbsolute = fly(el).isStyle("position", "absolute"); if (el.getBoundingClientRect) { try { b = el.getBoundingClientRect(); scroll = fly(document).getScroll(); ret = [ Math.round(b.left + scroll.left), Math.round(b.top + scroll.top) ]; } catch (e) { // IE6-8 can also throw from getBoundingClientRect... } } if (!ret) { for (p = el; p; p = ELEMENT.getOffsetParent(p)) { pe = fly(p); x += p.offsetLeft; y += p.offsetTop; hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute"); if (Ext.isGecko) { y += bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0; x += bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0; if (p != el && !pe.isStyle('overflow','visible')) { x += bl; y += bt; } } } if (Ext.isSafari && hasAbsolute) { x -= bd.offsetLeft; y -= bd.offsetTop; } if (Ext.isGecko && !hasAbsolute) { dbd = fly(bd); x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0; y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0; } p = el.parentNode; while (p && p != bd) { if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) { x -= p.scrollLeft; y -= p.scrollTop; } p = p.parentNode; } ret = [x,y]; } } return ret || [0,0]; }, setXY : function(el, xy) { (el = Ext.fly(el, '_setXY')).position(); var pts = el.translatePoints(xy), style = el.dom.style, pos; for (pos in pts) { if (!isNaN(pts[pos])) { style[pos] = pts[pos] + "px"; } } }, setX : function(el, x) { ELEMENT.setXY(el, [x, false]); }, setY : function(el, y) { ELEMENT.setXY(el, [false, y]); }, /** * Serializes a DOM form into a url encoded string * @param {Object} form The form * @return {String} The url encoded form */ serializeForm: function(form) { var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements, hasSubmit = false, encoder = encodeURIComponent, name, data = '', type, hasValue; Ext.each(fElements, function(element){ name = element.name; type = element.type; if (!element.disabled && name) { if (/select-(one|multiple)/i.test(type)) { Ext.each(element.options, function(opt){ if (opt.selected) { hasValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttributeNode('value').specified; data += Ext.String.format("{0}={1}&", encoder(name), encoder(hasValue ? opt.value : opt.text)); } }); } else if (!(/file|undefined|reset|button/i.test(type))) { if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)) { data += encoder(name) + '=' + encoder(element.value) + '&'; hasSubmit = /submit/i.test(type); } } } }); return data.substr(0, data.length - 1); } }); })();