in closure/goog/cssom/iframe/style.js [894:988]
goog.cssom.iframe.style.getBackgroundContext = function(element) {
'use strict';
var propertyValues = {'backgroundImage': 'none'};
var ancestor = element;
/** @type {!Window|undefined} */
var currentIframeWindow;
// Walk up the DOM tree to find the ancestor nodes whose backgrounds
// may be visible underneath this element. Background-image and
// background-color don't have to come from the same node, but as soon
// an element with background-color is found there's no need to continue
// because backgrounds farther up the chain won't be visible.
// (This implementation is not sophisticated enough to handle opacity,
// or multple layered partially-transparent background images.)
while ((ancestor = /** @type {!Element} */ (ancestor.parentNode)) &&
ancestor.nodeType == goog.dom.NodeType.ELEMENT) {
var computedStyle =
goog.cssom.iframe.style.getComputedStyleObject_(ancestor);
// Copy background color if a non-transparent value is found.
var backgroundColorValue = computedStyle['backgroundColor'];
if (!goog.cssom.iframe.style.isTransparentValue_(backgroundColorValue)) {
propertyValues['backgroundColor'] = backgroundColorValue;
}
// If a background image value is found, copy background-image,
// background-repeat, and background-position.
if (computedStyle['backgroundImage'] &&
computedStyle['backgroundImage'] != 'none') {
propertyValues['backgroundImage'] = computedStyle['backgroundImage'];
propertyValues['backgroundRepeat'] = computedStyle['backgroundRepeat'];
// Calculate the offset between the original element and the element
// providing the background image, so the background position can be
// adjusted.
var relativePosition;
if (currentIframeWindow) {
relativePosition =
goog.style.getFramedPageOffset(element, currentIframeWindow);
var frameElement = currentIframeWindow.frameElement;
var iframeRelativePosition = goog.style.getRelativePosition(
/** @type {!Element} */ (frameElement), ancestor);
var iframeBorders = goog.style.getBorderBox(frameElement);
relativePosition.x += iframeRelativePosition.x + iframeBorders.left;
relativePosition.y += iframeRelativePosition.y + iframeBorders.top;
} else {
relativePosition = goog.style.getRelativePosition(element, ancestor);
}
var backgroundXYValues =
goog.cssom.iframe.style.getBackgroundXYValues_(computedStyle);
// Parse background-repeat-* values in the form "10px", and adjust them.
for (var i = 0; i < 2; i++) {
var positionValue = backgroundXYValues[i];
var coordinate = i == 0 ? 'X' : 'Y';
var positionProperty = 'backgroundPosition' + coordinate;
// relative position to its ancestor.
var positionValueParts =
goog.cssom.iframe.style.valueWithUnitsRegEx_.exec(positionValue);
if (positionValueParts) {
var value =
parseInt(positionValueParts[1] + positionValueParts[2], 10);
var units = positionValueParts[3];
// This only attempts to handle pixel values for now (plus
// '0anything', which is equivalent to 0px).
// TODO(user) Convert non-pixel values to pixels when possible.
if (value == 0 || units == 'px') {
value -=
(coordinate == 'X' ? relativePosition.x : relativePosition.y);
}
positionValue = value + units;
}
propertyValues[positionProperty] = positionValue;
}
propertyValues['backgroundPosition'] =
propertyValues['backgroundPositionX'] + ' ' +
propertyValues['backgroundPositionY'];
}
if (propertyValues['backgroundColor']) {
break;
}
if (ancestor.tagName == goog.dom.TagName.HTML) {
try {
currentIframeWindow = goog.dom.getWindow(
/** @type {Document} */ (ancestor.parentNode));
// This could theoretically throw a security exception if the parent
// iframe is in a different domain.
ancestor = currentIframeWindow.frameElement;
if (!ancestor) {
// Loop has reached the top level window.
break;
}
} catch (e) {
// We don't have permission to go up to the parent window, stop here.
break;
}
}
}
return propertyValues;
};