    /**
     * @class Ext.Element
     */
    Ext.Element.addMethods(
    function(){
        var VISIBILITY = "visibility",
            DISPLAY = "display",
            HIDDEN = "hidden",
            NONE = "none",
    	    XMASKED = "x-masked",
    		XMASKEDRELATIVE = "x-masked-relative",
            data = Ext.Element.data;

    	return {
    		/**
    	     * Checks whether the element is currently visible using both visibility and display properties.
    	     * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
    	     * @return {Boolean} True if the element is currently visible, else false
    	     */
    	    isVisible : function(deep) {
    	        var vis = !this.isStyle(VISIBILITY,HIDDEN) && !this.isStyle(DISPLAY,NONE),
    	        	p = this.dom.parentNode;
    	        if(deep !== true || !vis){
    	            return vis;
    	        }
    	        while(p && !/body/i.test(p.tagName)){
    	            if(!Ext.fly(p, '_isVisible').isVisible()){
    	                return false;
    	            }
    	            p = p.parentNode;
    	        }
    	        return true;
    	    },

    	    /**
    	     * Returns true if display is not "none"
    	     * @return {Boolean}
    	     */
    	    isDisplayed : function() {
    	        return !this.isStyle(DISPLAY, NONE);
    	    },

    		/**
    	     * Convenience method for setVisibilityMode(Element.DISPLAY)
    	     * @param {String} display (optional) What to set display to when visible
    	     * @return {Ext.Element} this
    	     */
    	    enableDisplayMode : function(display){
    	        this.setVisibilityMode(Ext.Element.DISPLAY);
    	        if(!Ext.isEmpty(display)){
                    data(this.dom, 'originalDisplay', display);
                }
    	        return this;
    	    },

    		/**
    	     * Puts a mask over this element to disable user interaction. Requires core.css.
    	     * This method can only be applied to elements which accept child nodes.
    	     * @param {String} msg (optional) A message to display in the mask
    	     * @param {String} msgCls (optional) A css class to apply to the msg element
    	     * @return {Element} The mask element
    	     */
    	    mask : function(msg, msgCls){
    		    var me = this,
    		    	dom = me.dom,
    		    	dh = Ext.DomHelper,
    		    	EXTELMASKMSG = "ext-el-mask-msg",
                    el,
                    mask;

    	        if(me.getStyle("position") == "static"){
    	            me.addClass(XMASKEDRELATIVE);
    	        }
    	        if((el = data(dom, 'maskMsg'))){
    	            el.remove();
    	        }
    	        if((el = data(dom, 'mask'))){
    	            el.remove();
    	        }

                mask = dh.append(dom, {cls : "ext-el-mask"}, true);
    	        data(dom, 'mask', mask);

    	        me.addClass(XMASKED);
    	        mask.setDisplayed(true);
    	        if(typeof msg == 'string'){
                    var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
                    data(dom, 'maskMsg', mm);
    	            mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
    	            mm.dom.firstChild.innerHTML = msg;
    	            mm.setDisplayed(true);
    	            mm.center(me);
    	        }
    	        if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto'){ // ie will not expand full height automatically
    	            mask.setSize(undefined, me.getHeight());
    	        }
    	        return mask;
    	    },

    	    /**
    	     * Removes a previously applied mask.
    	     */
    	    unmask : function(){
    		    var me = this,
                    dom = me.dom,
    		    	mask = data(dom, 'mask'),
    		    	maskMsg = data(dom, 'maskMsg');
    	        if(mask){
    	            if(maskMsg){
    	                maskMsg.remove();
                        data(dom, 'maskMsg', undefined);
    	            }
    	            mask.remove();
                    data(dom, 'mask', undefined);
    	        }
    	        me.removeClass([XMASKED, XMASKEDRELATIVE]);
    	    },

    	    /**
    	     * Returns true if this element is masked
    	     * @return {Boolean}
    	     */
    	    isMasked : function(){
                var m = data(this.dom, 'mask');
    	        return m && m.isVisible();
    	    },

    	    /**
    	     * Creates an iframe shim for this element to keep selects and other windowed objects from
    	     * showing through.
    	     * @return {Ext.Element} The new shim element
    	     */
    	    createShim : function(){
    	        var el = document.createElement('iframe'),
    	        	shim;
    	        el.frameBorder = '0';
    	        el.className = 'ext-shim';
    	        el.src = Ext.SSL_SECURE_URL;
    	        shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
    	        shim.autoBoxAdjust = false;
    	        return shim;
    	    }
        };
    }());