goog.cssom.iframe.style.getBackgroundContext = function()

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;
};