All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.smartclient.debug.public.sc.client.widgets.Element.js Maven / Gradle / Ivy

The newest version!
/*
 * Isomorphic SmartClient
 * Version SC_SNAPSHOT-2011-08-08 (2011-08-08)
 * Copyright(c) 1998 and beyond Isomorphic Software, Inc. All rights reserved.
 * "SmartClient" is a trademark of Isomorphic Software, Inc.
 *
 * [email protected]
 *
 * http://smartclient.com/license
 */

 




//>	@class	Element
//
// Helper class containing methods for direct DOM interaction. Note that even if 
// +link{isc, isc_useSimpleNames} is true, this class is not available in the global scope
// as window.Element - to access it developers must always use 
// isc.Element
//
//  @treeLocation Client Reference/Foundation
//  @visibility internal
//<
// Currently has no exposed methods - Developers typically will only need to interact with 
// higher level canvas methods
isc.ClassFactory.defineClass("Element", null, null, true);

isc.Element.addClassMethods({


// --------------------------------------------------------------------------------------------
// DOM Access / Manipulation

//>	@classMethod	Element.get()
//		Like the DOM method document.getElementById(), but works in all supported browsers.
//<
get : function (id, doc) {
    doc = doc || this.getDocument();
    if (isc.Browser.isDOM) return doc.getElementById(id);
},


// _getElementFromSelection()
// Determine which DOM element contains the current selection.
// 'doc' param allows caller to pass in a pointer to the document element - (may be document
// element from some frame/iframe - if not specified the main page document is used).

_getElementFromSelection : function (doc) {

    

    if (!doc) doc = document;

    if (isc.Browser.isIE ) {
        var selection = doc.selection,
            type = selection.type.toLowerCase(),
            isText = (type == "text" || type == "none");
            
        if (!selection) return null;
            
        // If it's a text range use the 'parentElement()' method to determine what element
        // contains the text.
        // NOTE: an empty selection will be reported as type "None", but can be used to create
        // a zero char text range, so we treat it like a "Text" selection.
        if (isText) {
            var range;
            
            try {
                range = selection.createRange();
            } catch (e) {
                
            }
            return range ? range.parentElement() : null;

        // If it's a control range, we can get at the elements in the control range
        // by index.    Iterate through the elements and find the common ancester.
        
        } else {  
            // If this is a control range 
            // We're interested in the first common ancestor of the elements
            var range = selection.createRange(),
                commonParent;
            for (var i = 0; i < range.length; i++) {

                if (!commonParent) {
                    commonParent = range(i).parentElement;                

                } else {
                    // To determine whether the element is contained by the common parent, 
                    // we're creating a textRange from both elements and using the inRange
                    // method.
                    while (!commonParent.contains(range(i))) {
                        commonParent = commonParent.parentElement;
                    }
                } 
                
            }
            return commonParent;
        }
    }
},

// Given an element attribute, iterate recursively through child nodes till you find a match.
// May be slow for deep hierarchies
findAttribute : function (element, attribute, value) {
    if (!element) return null;    
    if (element[attribute] == value || 
    (element.getAttribute && element.getAttribute(attribute) == value)) {   
        return element;
    }
    var children = element.childNodes;
    for (var i = 0; i < children.length; i++) {
        var subElement = this.findAttribute(children[i], attribute, value);
        if (subElement) return subElement;
    }
    return null;
    
},


// helpers for createAbsoluteElement
_insertAfterBodyStart : window.isc_insertAfterBodyStart,
_globalInsertionMarker : "isc_global_insertion_marker",
getInsertionMarkerHTML : function () {
    return "";
},
getInsertionMarker : function () {
    return document.getElementById(this._globalInsertionMarker);
},
// create a new, absolutely positioned element, after page load
_$afterBegin : "afterBegin",
_$afterEnd : "afterEnd",
_$beforeBegin: "beforeBegin",
_$beforeEnd : "beforeEnd",
createAbsoluteElement : function (html, targetWindow) {
    var wd = targetWindow || this.getWindow(),
         
        body = this.getDocumentBody(true);

    
    
    //>DEBUG
    // if there's no body tag, we bail
    if (body == null && !isc.Element.noBodyTagMessageShown) {
        isc.Element.noBodyTagMessageShown = true;
        var msg ="Error: Attempt to write content into a page outside the BODY tag.  Isomorphic " +
            "SmartClient requires this tag be present and all widgets be written out inside " +
            "it.\r" +
            "Please ensure your file has a BODY tag and any code to draw SmartClient widgets " +
            "is enclosed in this tag."
            ;
        //alert(msg);
        this.logError(msg);
        return;
    }
    // element with no enclosing 
tag, right at the end of the page. var node = body.lastChild; while (node && node.nodeType == 3) node = node.previousSibling; if (node != null) { isc.Element.insertAdjacentHTML(node, this._$beforeBegin, this.getInsertionMarkerHTML()); } else { // all nodes of the body are text nodes, insert after body begin isc.Element.insertAdjacentHTML(body, this._$afterBegin, this.getInsertionMarkerHTML()); } } this._insertionMarker = this.getInsertionMarker(); } return isc.Element.insertAdjacentHTML(this._insertionMarker, this._$afterEnd, html, true); } else { return isc.Element.insertAdjacentHTML(body, this._$beforeEnd, html, true); } }, // emulate IE's insertAdjacentHTML on any fully DOM-compliant browser insertAdjacentHTML : function (element, where, html, singleElement) { // handle string element IDs if (isc.isA.String(element)) element = isc.Element.get(element); //>DEBUG if (!element) this.logWarn("insertAdjacentHTML: element is null for where: '" + where + "' with html: " + html); //DEBUG isc.Log.logWarn("element parentNode null"); // height ? largestBottom : height; }, // get the largest bottom coordinate for any explicitly positioned DOM children of this element _getPositionedChildrenBottom : function (element) { if (element.childNodes == null) return 0; var largest = 0, // constants for determining whether a DOM node is an element. elementType = document.ELEMENT_NODE || 1, debug = this.logIsDebugEnabled("sizing"); for (var i = 0; i < element.childNodes.length; i++) { var child = element.childNodes.item(i); // ignore anything that isn't an element (only elements report any size information) if (child.nodeType != elementType) continue; var childPosition = isc.Element.getComputedStyleAttribute(child, "position"); // get the top coordinate of the child var childTop = 0; if (childPosition == isc.Canvas.ABSOLUTE || childPosition == isc.Canvas.RELATIVE) { childTop += isc.Element.getOffsetTop(child); } else { // inline content ("position" property unset). We don't inspect this because the // scrollWidth reported by the element includes inline content continue; } var canvas = child.getAttribute("eventProxy"), childVisibleHeight; if (canvas != null && !isc.isAn.emptyString(canvas) && !window[canvas]._retrievingScrollHeight && isc.isA.Function(window[canvas].getVisibleHeight)) { childVisibleHeight = window[canvas].getVisibleHeight(); } else { // For regular DOM elements call isc.Element.getVisibleHeight(element) instead childVisibleHeight = isc.Element.getVisibleHeight(child); } var childBottom = childTop + childVisibleHeight; // Notes: // - the 'visibleHeight' is the height of this child, including any margins. // if this (parent) is scrollable, and the child is absolutely positioned, we // natively can't scroll to the right/bottom margin, so deduct this from the reported // parent scroll-width. // - This child will be drawn over the top of any padding applied to the element, so we // don't need to add that to the childBottom value. Only inline elements will force // the parents' padding to show up below them. if (childPosition == isc.Canvas.ABSOLUTE && (element.style.overflow == isc.Canvas.SCROLL || element.style.overflow == isc.Canvas.AUTO || element.style.overflow == isc.Canvas.HIDDEN)) childBottom -= isc.Element.getBottomMargin(child); if (childBottom > largest) largest = childBottom; } return largest; }, // isc.Element.getScrollWidth(element) - See comments for getScrollHeight getScrollWidth : function (element) { if (element == null) return 0; var width = ((element.scrollWidth != null && element.scrollWidth != "undefined") ? element.scrollWidth : element.offsetWidth); // if we have any position:absolute or position:relative children, find the right-most one var largestRight = this._getPositionedChildrenRight(element); return largestRight > width ? largestRight : width; }, // get the largest right coordinate for any explicitly positioned DOM children of this element _getPositionedChildrenRight : function (element) { if (element.childNodes == null) return 0; var largest = 0, // constants for determining whether a DOM node is an element. elementType = document.ELEMENT_NODE || 1, debug = this.logIsDebugEnabled("sizing"); for (var i = 0; i < element.childNodes.length; i++) { var child = element.childNodes.item(i); if (child.nodeType != elementType) continue; var childStyle = isc.Element.getComputedStyle(child, ["position", "display", "left"]); var childLeft = 0; if (childStyle.position == isc.Canvas.ABSOLUTE || childStyle.position == isc.Canvas.RELATIVE) { childLeft = isc.Element.getOffsetLeft(child); } else { // inline content ("position" property unset). We don't inspect this because the // scrollWidth reported by the element includes inline content continue; } var canvas = child.getAttribute("eventProxy"), childVisibleWidth; if (canvas != null && !isc.isAn.emptyString(canvas) && !window[canvas]._retrievingScrollWidth && isc.isA.Function(window[canvas].getVisibleWidth)) { childVisibleWidth = window[canvas].getVisibleWidth(); } else { // For regular DOM elements call isc.Element.getVisibleWidth(element) instead childVisibleWidth = isc.Element.getVisibleWidth(child); } var childRight = childLeft + childVisibleWidth; if (element.style.overflow == isc.Canvas.SCROLL || element.style.overflow == isc.Canvas.HIDDEN || element.style.overflow == isc.Canvas.AUTO) { childRight -= isc.Element.getRightMargin(child); } if (childRight > largest) largest = childRight; //>DEBUG if (debug) { this.logInfo("getChildNodesRight: child node " + i + " of " + element.childNodes.length + " (" + this.echoLeaf(child) + ")" + " left:" + childLeft + ", width: " + childVisibleWidth + ", right:" + childRight, "sizing"); } // 0) { left -= leftMargin; } var documentBody = this.getDocumentBody(), parentStyle, px = "px", // determine whether the element is absolutely / relatively / etc. positioned elementPosition = element.style.position; // Workarounds for Moz if (isc.Browser.isMoz) { // In moz we get some unexpected results if (element.offsetParent == null) return left; if (element.offsetParent != documentBody) { parentStyle = this.ns.Element.getComputedStyle(element.offsetParent, ["borderLeftWidth", "overflow"]); // The behavior changes with different releses of Moz / Firefox var geckoVersion = isc.Browser.geckoVersion, scrollingAdjustment = (parentStyle.overflow != "visible") && (geckoVersion >= 20051111 || (elementPosition == isc.Canvas.ABSOLUTE && parentStyle.overflow != "hidden")), accountForBorderBox = (geckoVersion > 20020826 && (element.offsetParent.style.MozBoxSizing == "border-box")); if (accountForBorderBox != scrollingAdjustment) { if (accountForBorderBox) { left -= (isc.isA.Number(parseInt(parentStyle.borderLeftWidth)) ? parseInt(parentStyle.borderLeftWidth) : 0); } if (scrollingAdjustment) { left += (isc.isA.Number(parseInt(parentStyle.borderLeftWidth)) ? parseInt(parentStyle.borderLeftWidth) : 0); } } } } // Workarounds for IE if (isc.Browser.isIE && !isc.Browser.isIE8Strict && !isc.Browser.isIE9) { var currentParent = element.offsetParent, parentStyle; if (parentStyle != documentBody) parentStyle = currentParent.currentStyle; var hasSpecifiedSize = (element.currentStyle.height != isc.Canvas.AUTO || element.currentStyle.width != isc.Canvas.AUTO); var continueDeductingBorders = true; // iterate up the offsetParents till we reach the doc. body while (currentParent != documentBody) { if (parentStyle.position == isc.Canvas.ABSOLUTE) continueDeductingBorders = false; if (parentStyle.width == isc.Canvas.AUTO && parentStyle.height == isc.Canvas.AUTO && parentStyle.position == isc.Canvas.RELATIVE) { if (continueDeductingBorders && isc.isA.String(parentStyle.borderLeftWidth) && parentStyle.borderLeftWidth.contains(px) ) { left -= parseInt(parentStyle.borderLeftWidth); } if (hasSpecifiedSize) { if (isc.isA.String(parentStyle.marginLeft) && parentStyle.marginLeft.contains(px)) { var parentMarginLeft = parseInt(parentStyle.marginLeft); if (parentMarginLeft > 0) left -= parentMarginLeft; } if (currentParent.offsetParent != documentBody) { var superPadding = currentParent.offsetParent.currentStyle.padding; if (isc.isA.String(superPadding) && superPadding.contains(px)) { left -= parseInt(superPadding); } } else { left -= (documentBody.leftMargin ? parseInt(documentBody.leftMargin) : 0); } } } // end of if elementPosition = currentParent.style.position; currentParent = currentParent.offsetParent; if (currentParent != document.body) { parentStyle = currentParent.currentStyle; } } // End of while loop } // Workarounds for Safari if (isc.Browser.isSafari && isc.Browser.safariVersion < 525.271) { // In some versions of Safari, if the offsetParent has a border, the offsetLeft / top // reported is relative to the outside of that border, rather than the inside, so deduct // that value // No longer the case in Safari 3.2.1 (525.27.1) if (element.offsetParent != null && element.offsetParent != documentBody) { var parentBorder = this.ns.Element.getComputedStyle(element.offsetParent, ["borderLeftWidth"]).borderLeftWidth; if (parentBorder != null) parentBorder = parseInt(parentBorder); if (isc.isA.Number(parentBorder)) left -= parentBorder; } } // --- cacheing code: // Cache the calculated and reported value, by saving it as attributes on the DOM element element._cachedReportedOffsetLeft = element.offsetLeft; element._cachedCalculatedOffsetLeft = left; return left; }, // Element.getOffsetTop() // Takes 'element' // element should be a pointer to a DOM element or the ID for a DOM element (doesn't // handle getting a widget ID - in that case use widget.getOffsetTop() instead) // Returns the true offsetTop - the absolute top coordinate with respect to (the inside of any // border of) whatever is reported by the DOM as the offsetParent of the element. getOffsetTop : function (element) { // In theory the value element.offsetTop should be what we want here. However it is // unreliable in a number of ways. if (element == null) { this.logWarn("getOffsetTop: passed null element"); return 0; } // IE and Moz both return somewhat unreliable values for element.offsetTop by default. // Paper over these bugs and differences. var top = element.offsetTop; // This is what we'd return if the browsers worked correctly! // --- caching code: // If we've already calculated a value (based on a reported offsetTop value), and // the reported value has not changed, return the previously calculated value. if (element._cachedReportedOffsetTop == top) { return element._cachedCalculatedOffsetTop; } else { // debug message for sanity checking coordinate caching //this.logWarn(element.getAttribute("eventProxy") + ": new DOM value for offsetTop"); } // The reported offsetTop is the offset from the element, INSIDE of margins to the // offsetParent - if we have a top margin we should subtract it to get the position OUTSIDE // the margins. // Exception: If the margin is negative, we don't need to adjust for it. In this case the // reported offset is still to the outside of the element, even though the element is // essentially shifted above where it would normally appear. var topMargin = parseInt(isc.Element.getComputedStyleAttribute(element, "marginTop")); if (isc.isA.Number(topMargin) && topMargin > 0) { top -= topMargin; } var documentBody = this.getDocumentBody(), parentStyle, px = "px", elementPosition = element.style.position; // Workarounds for Moz if (isc.Browser.isMoz) { if (element.offsetParent == null) return top; if (element.offsetParent != documentBody) { // get the offsetParent's style info parentStyle = this.ns.Element.getComputedStyle(element.offsetParent, ["overflow", "borderTopWidth"]); var scrollingAdjustment = (parentStyle.overflow != "visible") && (isc.Browser.geckoVersion >= 20051111 || (elementPosition == isc.Canvas.ABSOLUTE && parentStyle.overflow != "hidden")), accountForBorderBox = (isc.Browser.geckoVersion > 20020826 && element.offsetParent.style.MozBoxSizing == "border-box"); if (accountForBorderBox != scrollingAdjustment) { if (accountForBorderBox) { top -= (isc.isA.Number(parseInt(parentStyle.borderTopWidth)) ? parseInt(parentStyle.borderTopWidth) : 0); } if (scrollingAdjustment) { top += (isc.isA.Number(parseInt(parentStyle.borderTopWidth)) ? parseInt(parentStyle.borderTopWidth) : 0); } } } } // Workarounds for IE if (isc.Browser.isIE && !isc.Browser.isIE9) { if (element.offsetParent && element.offsetParent != documentBody) { parentStyle = element.offsetParent.currentStyle; if ( parentStyle.position == isc.Canvas.RELATIVE && parentStyle.height == isc.Canvas.AUTO && parentStyle.width == isc.Canvas.AUTO && isc.isA.String(parentStyle.borderTopWidth) && parentStyle.borderTopWidth.contains(px) ) { top -= parseInt(parentStyle.borderTopWidth); } } } // Workarounds for Safari if (isc.Browser.isSafari && isc.Browser.safariVersion < 525.271) { // As noted in 'getOffsetLeft()', in Safari the width of the parent's border is included // in the offsetLeft/top value reported. if (element.offsetParent && element.offsetParent != documentBody) { var parentBorder = this.ns.Element.getComputedStyle(element.offsetParent, ["borderTopWidth"]).borderTopWidth; if (parentBorder != null) parentBorder = parseInt(parentBorder); if (isc.isA.Number(parentBorder)) top -= parentBorder; } } // --- cacheing code: // Cache the calculated and reported value, by saving it as attributes on the DOM element element._cachedReportedOffsetTop = element.offsetTop; element._cachedCalculatedOffsetTop = top; return top; }, // getLeftOffset(element, targetElement, rtl) // // DOM Only method to return the absolute (offset) position for some element within some other // DOM parent element. We will return this value from the outside of any border / margin on // the child to the inside of the ancestor element. // getLeftOffset : function (element, targetElement, rtl, canvasArgs) { return this.getOffset(isc.Canvas.LEFT, element, targetElement, rtl, canvasArgs); }, // Return the absolute position of an element within a DOM parent element. // If no target parent element is passed, we return page level position. getTopOffset : function (element, targetElement, canvasArgs) { return this.getOffset(isc.Canvas.TOP, element, targetElement, null, canvasArgs); }, _$borderLeftWidth : isc.Browser.isMoz ? "border-left-width" : "borderLeftWidth", _$borderTopWidth : isc.Browser.isMoz ? "border-top-width" : "borderTopWidth", _$marginLeft : isc.Browser.isMoz ? "margin-left" : "marginLeft", _$marginTop : isc.Browser.isMoz ? "margin-top" : "marginTop", _$none:"none", cacheCount:0, uncachedCount:0, _$leftCoords : "_$leftCoords", _$topCoords : "_$topCoords", // cacheOffestCoordinates: If set we will cache calculated offsets between SmartClient // ancestor/descendent components. // This improves performance on repeated lookups during (EG) drag/drop, etc cacheOffsetCoords:true, getOffset : function (dir, sourceElement, origTargetElement, rtl, canvasArgs) { var sourceIsCanvas = canvasArgs || isc.isA.Canvas(sourceElement), targetIsCanvas = canvasArgs || origTargetElement == null || isc.isA.Canvas(origTargetElement); var cacheCoords = sourceIsCanvas && targetIsCanvas && this.cacheOffsetCoords && (sourceElement.cacheOffsetCoords != false); var coordCacheName = (dir == isc.Canvas.LEFT) ? this._$leftCoords : this._$topCoords; if (cacheCoords && sourceElement[coordCacheName] != null) { var cachedCoord = sourceElement[coordCacheName][origTargetElement ? origTargetElement.ID : this._$none]; if (cachedCoord != null) { this.cacheCount++; return cachedCoord; } } this.uncachedCount++; var element = sourceIsCanvas ? sourceElement.getClipHandle() : sourceElement; var targetElement; // if we're not passed an element, determine the offset from the top level HTML element. if (origTargetElement == null) targetElement = this.getDocumentBody(); else if (targetIsCanvas) targetElement = origTargetElement.getHandle(); else targetElement = origTargetElement; //!DONTCOMBINE //>DEBUG if (targetElement == null || element == null) { return 0; } // 0) offset += marginWidth; } else if (isc.Browser.isMoz) { styleObj = document.defaultView.getComputedStyle(nextParent, null); borderWidth = parseInt(styleObj.getPropertyValue(borderWidthProp)); offset += borderWidth; marginWidth = parseInt(styleObj.getPropertyValue(marginProp)); if (marginWidth > 0) offset += marginWidth; } else { borderWidth = parseInt(this.getComputedStyleAttribute(nextParent, borderWidthProp)); if (isc.isA.Number(borderWidth)) offset += borderWidth; marginWidth = parseInt(this.getComputedStyleAttribute(nextParent, marginProp)); if (isc.isA.Number(marginWidth) && marginWidth > 0) offset += marginWidth; } // Move up the DOM chain currentNode = nextParent; nextParent = currentNode.offsetParent; iterations++; } // At this point the nextParent is either the target or it's offsetParent. // add the offsetLeft between the current node and the nextParent. offset += (isLeft ? this.ns.Element.getOffsetLeft(currentNode) : this.ns.Element.getOffsetTop(currentNode)); // OffsetLeft from the last iteration was relative to the target's offsetParent - // deduct the target's offsetLeft to get the offset relative to the target instead. if (nextParent == targetParent) { // deduct the targetElement's offsetLeft // No need to adjust for border / padding in this case offset -= (isLeft ? this.ns.Element.getOffsetLeft(targetElement) : this.ns.Element.getOffsetTop(targetElement)); } if (cacheCoords) { var coordCache = sourceElement[coordCacheName] = sourceElement[coordCacheName] || {}; coordCache[origTargetElement ? origTargetElement.ID : this._$none] = offset; } //this.logWarn("iterations: " + iterations); return offset; }, // ---------------------------------------------------------------------------------------- // CSS / Styling Lookups // ---------------------------------------------------------------------------------------- // Retrieval of CSS style declaration and computed styles // Styling: what we need and why: // We need to be able to look up border, padding and margin sizes in order to: // - compensate for errors in reported offsetLeft / offsetTop to have correct page-level // coordinates when relatively positioned (needed for arbitrary containing elements not // created by ISC) // - when using the CSS standard box model, be able to write HTML that will render with // predictable sizes even when using author-specified CSS styling. This is critical for grid // cell rendering, where correcting sizes after draw is not even close to feasible. // - get correct scrollHeight when allowing natively positioned children // cache of CSS style objects _styleCache:{}, // get the edge widths (border, margin, padding) for a CSS style getStyleEdges : function (className) { if (isc.Browser.isSafari && !isc.Element._safariStrictChecked) { isc.Browser.isStrict = isc.Element._testForSafariStrictMode(); isc.Element._safariStrictChecked = true; } if (className == null) return null; // check whether cache value is defined, so we can cache failed lookups as nulls var undef; if (this._styleCache[className] !== undef) return this._styleCache[className]; //this.logWarn("style lookup: " + className + this.getStackTrace()); var cantDeriveStyles = (isc.Browser.isMoz && isc.Browser.geckoVersion < 20040616), styleInfo; if (cantDeriveStyles) { styleInfo = this.getStyleDeclaration(className); } else { var mask = isc.Browser.isIE ? this._styleEdgeMaskArray : this._styleEdgeMask; styleInfo = this._deriveStyleProperties(className, mask); } this._styleCache[className] = styleInfo; return styleInfo; }, // In Safari, document.compatMode is not available, so we rely on the fact that // table cells render their padding outside their specified height in strict mode but not in // normal compat mode to determine whether we're currently in strict mode _testForSafariStrictMode : function () { if (document.compatMode != null) { return document.compatMode == "CSS1Compat"; } var tableHTML = "
x
" var tester = isc.Element.createAbsoluteElement(tableHTML); var isStrict = tester.offsetHeight > 30; isc.Element.clear(tester); return isStrict; }, // get certain key properties of a style by applying it to an element and inspecting that // element. Edge-related properties are reliably derivable this way, cssText is known not // available, other properties would need testing. _deriveStyleProperties : function (className, mask) { var requiresDivTester = (isc.Browser.isIE || isc.Browser.isOpera || isc.Browser.isSafari || (isc.Browser.isMoz && isc.Browser.geckoVersion >=20080205)); if (!this._cellStyleTester) { this.createAbsoluteElement( "" : " ID=isc_cellStyleTester> " + "
" + isc.Canvas.blankImgHTML(30,30) + "
 
" ) ); this._cellStyleTester = isc.Element.get("isc_cellStyleTester"); if (isc.Browser.isIE8Strict) { this._cellInnerStyleTester = isc.Element.get("isc_cellInnerStyleTester"); } // we set the table cellPadding to 81px - this will then be reported back // if the padding on the style was unset (allows us to differentiate between // null and explicit zero) this._$81px = "81px"; if (isc.Browser.isSafari || isc.Browser.isChrome) { var noStyleElement = isc.Element.get("isc_cellNoStyleTester"); var paddingLeft = ["paddingLeft"]; var reported81 = this.getComputedStyle(noStyleElement, paddingLeft).paddingLeft; if (reported81 != this._$81px) { this.logDebug("Browser natively misreporting cell-padding (81px reported as:" + reported81 + "). This behavior is known to occur when the view is " + "zoomed in certain browsers but is worked around by SmartClient and " + "should have no visible effect on the application.", "sizing"); this._$81px = reported81; } } this._$16384px = "-16384px"; if (requiresDivTester) { this.createAbsoluteElement( "
 
" ); this._styleTester = isc.Element.get("isc_styleTester"); this._marginMask = ["marginLeft", "marginTop", "marginRight", "marginBottom"]; if (isc.Browser.isIE8Strict) { this._marginMask.addList(["borderLeftWidth", "borderTopWidth", "borderRightWidth", "borderBottomWidth"]); } } } this._cellStyleTester.className = className; var style = this.getComputedStyle(this._cellStyleTester, mask); //this.logWarn(className + " style is: " + this.echo(style)); // test for unset padding var nullIndicator = this._$81px; if (style.paddingLeft == nullIndicator) style.paddingLeft = null; if (style.paddingTop == nullIndicator) style.paddingTop = null; if (style.paddingRight == nullIndicator) style.paddingRight = null; if (style.paddingBottom == nullIndicator) style.paddingBottom = null; if (isc.Browser.isIE8Strict) { var innerTester = this._cellInnerStyleTester, offsetLeft = innerTester.offsetLeft, offsetTop = innerTester.offsetTop; if (offsetLeft == 81) style.paddingLeft = null; if (offsetTop == 81) style.paddingTop = null; if (this._cellStyleTester.offsetWidth - offsetLeft - 30 == 81) { style.paddingRight = null; } if (this._cellStyleTester.offsetHeight - offsetTop - 30 == 81) { style.paddingBottom = null; } } if (isc.Browser.isSafari) { // older Safari versions report unset padding as "auto" instead of reporting the // cellPadding if (isc.Browser.safariVersion < 419.3) { nullIndicator = isc.Canvas.AUTO; if (style.paddingLeft == nullIndicator) style.paddingLeft = null; if (style.paddingTop == nullIndicator) style.paddingTop = null; if (style.paddingRight == nullIndicator) style.paddingRight = null; if (style.paddingBottom == nullIndicator) style.paddingBottom = null; } // serious bug introduced in Safari 419.3 / 2.0.4, aka Tiger update 10.4.7: unset // marginTop/Bottom on cells reported as "-16384px". Chimp factor 9.89 nullIndicator = this._$16384px; if (style.marginTop == nullIndicator) style.marginTop = null; if (style.marginBottom == nullIndicator) style.marginBottom = null; } if (requiresDivTester) { this._styleTester.className = className; var results = this.getComputedStyle(this._styleTester, this._marginMask); style.marginLeft = results.marginLeft; style.marginRight = results.marginRight; style.marginTop = results.marginTop; style.marginBottom = results.marginBottom; if (isc.Browser.isIE8Strict) { style.borderLeftWidth = results.borderLeftWidth; style.borderRightWidth = results.borderRightWidth; style.borderTopWidth = results.borderTopWidth; style.borderBottomWidth = results.borderBottomWidth; } } return style; }, //> @classMethod Element.getComputedStyle() // Returns an object containing the current (computed) style for a DOM element. This object // includes all the attributes set directly on the element's style property, and those inherited // from the element's CSS class. // @param ID (string | object) element, or ID of the element // @param mask (array) list of propertyNames to include in the returned object // @return (object) object containing computed style attributes. //< getComputedStyle : function (ID, mask) { var element, style, styleInfo; if (isc.isA.String(ID)) { element = isc.Element.get(ID); } else { // Otherwise just assume the DOM element was passed in directly element = ID; } if (element == null || !isc.isAn.Object(element)) { //>DEBUG this.logWarn("getComputedStyle: Unable to get to DOM element specified by '" + ID + "'." + this.getStackTrace()); //Safari if (isc.Browser.isSafari) { var propertyValue = null; if (element.style) propertyValue = element.style[property]; if ((propertyValue == null || isc.isAn.emptyString(propertyValue)) && element.className) { var styleDecl = isc.Element.getStyleEdges(element.className); if (styleDecl) propertyValue = styleDecl[property]; } if (isc.isAn.emptyString(propertyValue)) return null; return propertyValue; } //= 312) { className = className.toLowerCase(); } var selector = "." + className, commaSpace = ", "; // Check the array of style rules from any styleSheets // - This will include