Adding mapbox-gl branch
This commit is contained in:
@@ -0,0 +1,454 @@
|
||||
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview CSS Object Model helper functions.
|
||||
* References:
|
||||
* - W3C: http://dev.w3.org/csswg/cssom/
|
||||
* - MSDN: http://msdn.microsoft.com/en-us/library/ms531209(VS.85).aspx.
|
||||
* @supported in FF3, IE6, IE7, Safari 3.1.2, Chrome
|
||||
* TODO(user): Fix in Opera.
|
||||
* TODO(user): Consider hacking page, media, etc.. to work.
|
||||
* This would be pretty challenging. IE returns the text for any rule
|
||||
* regardless of whether or not the media is correct or not. Firefox at
|
||||
* least supports CSSRule.type to figure out if it's a media type and then
|
||||
* we could do something interesting, but IE offers no way for us to tell.
|
||||
*/
|
||||
|
||||
goog.provide('goog.cssom');
|
||||
goog.provide('goog.cssom.CssRuleType');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration of {@code CSSRule} types.
|
||||
* @enum {number}
|
||||
*/
|
||||
goog.cssom.CssRuleType = {
|
||||
STYLE: 1,
|
||||
IMPORT: 3,
|
||||
MEDIA: 4,
|
||||
FONT_FACE: 5,
|
||||
PAGE: 6,
|
||||
NAMESPACE: 7
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Recursively gets all CSS as text, optionally starting from a given
|
||||
* CSSStyleSheet.
|
||||
* @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet The CSSStyleSheet.
|
||||
* @return {string} css text.
|
||||
*/
|
||||
goog.cssom.getAllCssText = function(opt_styleSheet) {
|
||||
var styleSheet = opt_styleSheet || document.styleSheets;
|
||||
return /** @type {string} */ (goog.cssom.getAllCss_(styleSheet, true));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Recursively gets all CSSStyleRules, optionally starting from a given
|
||||
* CSSStyleSheet.
|
||||
* Note that this excludes any CSSImportRules, CSSMediaRules, etc..
|
||||
* @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet The CSSStyleSheet.
|
||||
* @return {Array<CSSStyleRule>} A list of CSSStyleRules.
|
||||
*/
|
||||
goog.cssom.getAllCssStyleRules = function(opt_styleSheet) {
|
||||
var styleSheet = opt_styleSheet || document.styleSheets;
|
||||
return /** @type {!Array<CSSStyleRule>} */ (
|
||||
goog.cssom.getAllCss_(styleSheet, false));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the CSSRules from a styleSheet.
|
||||
* Worth noting here is that IE and FF differ in terms of what they will return.
|
||||
* Firefox will return styleSheet.cssRules, which includes ImportRules and
|
||||
* anything which implements the CSSRules interface. IE returns simply a list of
|
||||
* CSSRules.
|
||||
* @param {CSSStyleSheet} styleSheet The CSSStyleSheet.
|
||||
* @throws {Error} If we cannot access the rules on a stylesheet object - this
|
||||
* can happen if a stylesheet object's rules are accessed before the rules
|
||||
* have been downloaded and parsed and are "ready".
|
||||
* @return {CSSRuleList} An array of CSSRules or null.
|
||||
*/
|
||||
goog.cssom.getCssRulesFromStyleSheet = function(styleSheet) {
|
||||
var cssRuleList = null;
|
||||
try {
|
||||
// Select cssRules unless it isn't present. For pre-IE9 IE, use the rules
|
||||
// collection instead.
|
||||
// It's important to be consistent in using only the W3C or IE apis on
|
||||
// IE9+ where both are present to ensure that there is no indexing
|
||||
// mismatches - the collections are subtly different in what the include or
|
||||
// exclude which can lead to one collection being longer than the other
|
||||
// depending on the page's construction.
|
||||
cssRuleList = styleSheet.cssRules /* W3C */ || styleSheet.rules /* IE */;
|
||||
} catch (e) {
|
||||
// This can happen if we try to access the CSSOM before it's "ready".
|
||||
if (e.code == 15) {
|
||||
// Firefox throws an NS_ERROR_DOM_INVALID_ACCESS_ERR error if a stylesheet
|
||||
// is read before it has been fully parsed. Let the caller know which
|
||||
// stylesheet failed.
|
||||
e.styleSheet = styleSheet;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return cssRuleList;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets all CSSStyleSheet objects starting from some CSSStyleSheet. Note that we
|
||||
* want to return the sheets in the order of the cascade, therefore if we
|
||||
* encounter an import, we will splice that CSSStyleSheet object in front of
|
||||
* the CSSStyleSheet that contains it in the returned array of CSSStyleSheets.
|
||||
* @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet A CSSStyleSheet.
|
||||
* @param {boolean=} opt_includeDisabled If true, includes disabled stylesheets,
|
||||
* defaults to false.
|
||||
* @return {!Array<CSSStyleSheet>} A list of CSSStyleSheet objects.
|
||||
*/
|
||||
goog.cssom.getAllCssStyleSheets = function(opt_styleSheet,
|
||||
opt_includeDisabled) {
|
||||
var styleSheetsOutput = [];
|
||||
var styleSheet = opt_styleSheet || document.styleSheets;
|
||||
var includeDisabled = goog.isDef(opt_includeDisabled) ? opt_includeDisabled :
|
||||
false;
|
||||
|
||||
// Imports need to go first.
|
||||
if (styleSheet.imports && styleSheet.imports.length) {
|
||||
for (var i = 0, n = styleSheet.imports.length; i < n; i++) {
|
||||
goog.array.extend(styleSheetsOutput,
|
||||
goog.cssom.getAllCssStyleSheets(styleSheet.imports[i]));
|
||||
}
|
||||
|
||||
} else if (styleSheet.length) {
|
||||
// In case we get a StyleSheetList object.
|
||||
// http://dev.w3.org/csswg/cssom/#the-stylesheetlist
|
||||
for (var i = 0, n = styleSheet.length; i < n; i++) {
|
||||
goog.array.extend(styleSheetsOutput,
|
||||
goog.cssom.getAllCssStyleSheets(styleSheet[i]));
|
||||
}
|
||||
} else {
|
||||
// We need to walk through rules in browsers which implement .cssRules
|
||||
// to see if there are styleSheets buried in there.
|
||||
// If we have a CSSStyleSheet within CssRules.
|
||||
var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(
|
||||
/** @type {!CSSStyleSheet} */ (styleSheet));
|
||||
if (cssRuleList && cssRuleList.length) {
|
||||
// Chrome does not evaluate cssRuleList[i] to undefined when i >=n;
|
||||
// so we use a (i < n) check instead of cssRuleList[i] in the loop below
|
||||
// and in other places where we iterate over a rules list.
|
||||
// See issue # 5917 in Chromium.
|
||||
for (var i = 0, n = cssRuleList.length, cssRule; i < n; i++) {
|
||||
cssRule = cssRuleList[i];
|
||||
// There are more stylesheets to get on this object..
|
||||
if (cssRule.styleSheet) {
|
||||
goog.array.extend(styleSheetsOutput,
|
||||
goog.cssom.getAllCssStyleSheets(cssRule.styleSheet));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a CSSStyleSheet. (IE uses .rules, W3c and Opera cssRules.)
|
||||
if ((styleSheet.type || styleSheet.rules || styleSheet.cssRules) &&
|
||||
(!styleSheet.disabled || includeDisabled)) {
|
||||
styleSheetsOutput.push(styleSheet);
|
||||
}
|
||||
|
||||
return styleSheetsOutput;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the cssText from a CSSRule object cross-browserly.
|
||||
* @param {CSSRule} cssRule A CSSRule.
|
||||
* @return {string} cssText The text for the rule, including the selector.
|
||||
*/
|
||||
goog.cssom.getCssTextFromCssRule = function(cssRule) {
|
||||
var cssText = '';
|
||||
|
||||
if (cssRule.cssText) {
|
||||
// W3C.
|
||||
cssText = cssRule.cssText;
|
||||
} else if (cssRule.style && cssRule.style.cssText && cssRule.selectorText) {
|
||||
// IE: The spacing here is intended to make the result consistent with
|
||||
// FF and Webkit.
|
||||
// We also remove the special properties that we may have added in
|
||||
// getAllCssStyleRules since IE includes those in the cssText.
|
||||
var styleCssText = cssRule.style.cssText.
|
||||
replace(/\s*-closure-parent-stylesheet:\s*\[object\];?\s*/gi, '').
|
||||
replace(/\s*-closure-rule-index:\s*[\d]+;?\s*/gi, '');
|
||||
var thisCssText = cssRule.selectorText + ' { ' + styleCssText + ' }';
|
||||
cssText = thisCssText;
|
||||
}
|
||||
|
||||
return cssText;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the index of the CSSRule in it's CSSStyleSheet.
|
||||
* @param {CSSRule} cssRule A CSSRule.
|
||||
* @param {CSSStyleSheet=} opt_parentStyleSheet A reference to the stylesheet
|
||||
* object this cssRule belongs to.
|
||||
* @throws {Error} When we cannot get the parentStyleSheet.
|
||||
* @return {number} The index of the CSSRule, or -1.
|
||||
*/
|
||||
goog.cssom.getCssRuleIndexInParentStyleSheet = function(cssRule,
|
||||
opt_parentStyleSheet) {
|
||||
// Look for our special style.ruleIndex property from getAllCss.
|
||||
if (cssRule.style && cssRule.style['-closure-rule-index']) {
|
||||
return cssRule.style['-closure-rule-index'];
|
||||
}
|
||||
|
||||
var parentStyleSheet = opt_parentStyleSheet ||
|
||||
goog.cssom.getParentStyleSheet(cssRule);
|
||||
|
||||
if (!parentStyleSheet) {
|
||||
// We could call getAllCssStyleRules() here to get our special indexes on
|
||||
// the style object, but that seems like it could be wasteful.
|
||||
throw Error('Cannot find a parentStyleSheet.');
|
||||
}
|
||||
|
||||
var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(parentStyleSheet);
|
||||
if (cssRuleList && cssRuleList.length) {
|
||||
for (var i = 0, n = cssRuleList.length, thisCssRule; i < n; i++) {
|
||||
thisCssRule = cssRuleList[i];
|
||||
if (thisCssRule == cssRule) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* We do some trickery in getAllCssStyleRules that hacks this in for IE.
|
||||
* If the cssRule object isn't coming from a result of that function call, this
|
||||
* method will return undefined in IE.
|
||||
* @param {CSSRule} cssRule The CSSRule.
|
||||
* @return {CSSStyleSheet} A styleSheet object.
|
||||
*/
|
||||
goog.cssom.getParentStyleSheet = function(cssRule) {
|
||||
return cssRule.parentStyleSheet ||
|
||||
cssRule.style &&
|
||||
cssRule.style['-closure-parent-stylesheet'];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Replace a cssRule with some cssText for a new rule.
|
||||
* If the cssRule object is not one of objects returned by
|
||||
* getAllCssStyleRules, then you'll need to provide both the styleSheet and
|
||||
* possibly the index, since we can't infer them from the standard cssRule
|
||||
* object in IE. We do some trickery in getAllCssStyleRules to hack this in.
|
||||
* @param {CSSRule} cssRule A CSSRule.
|
||||
* @param {string} cssText The text for the new CSSRule.
|
||||
* @param {CSSStyleSheet=} opt_parentStyleSheet A reference to the stylesheet
|
||||
* object this cssRule belongs to.
|
||||
* @param {number=} opt_index The index of the cssRule in its parentStylesheet.
|
||||
* @throws {Error} If we cannot find a parentStyleSheet.
|
||||
* @throws {Error} If we cannot find a css rule index.
|
||||
*/
|
||||
goog.cssom.replaceCssRule = function(cssRule, cssText, opt_parentStyleSheet,
|
||||
opt_index) {
|
||||
var parentStyleSheet = opt_parentStyleSheet ||
|
||||
goog.cssom.getParentStyleSheet(cssRule);
|
||||
if (parentStyleSheet) {
|
||||
var index = opt_index >= 0 ? opt_index :
|
||||
goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule, parentStyleSheet);
|
||||
if (index >= 0) {
|
||||
goog.cssom.removeCssRule(parentStyleSheet, index);
|
||||
goog.cssom.addCssRule(parentStyleSheet, cssText, index);
|
||||
} else {
|
||||
throw Error('Cannot proceed without the index of the cssRule.');
|
||||
}
|
||||
} else {
|
||||
throw Error('Cannot proceed without the parentStyleSheet.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cross browser function to add a CSSRule into a CSSStyleSheet, optionally
|
||||
* at a given index.
|
||||
* @param {CSSStyleSheet} cssStyleSheet The CSSRule's parentStyleSheet.
|
||||
* @param {string} cssText The text for the new CSSRule.
|
||||
* @param {number=} opt_index The index of the cssRule in its parentStylesheet.
|
||||
* @throws {Error} If the css rule text appears to be ill-formatted.
|
||||
* TODO(bowdidge): Inserting at index 0 fails on Firefox 2 and 3 with an
|
||||
* exception warning "Node cannot be inserted at the specified point in
|
||||
* the hierarchy."
|
||||
*/
|
||||
goog.cssom.addCssRule = function(cssStyleSheet, cssText, opt_index) {
|
||||
var index = opt_index;
|
||||
if (index < 0 || index == undefined) {
|
||||
// If no index specified, insert at the end of the current list
|
||||
// of rules.
|
||||
var rules = goog.cssom.getCssRulesFromStyleSheet(cssStyleSheet);
|
||||
index = rules.length;
|
||||
}
|
||||
if (cssStyleSheet.insertRule) {
|
||||
// W3C (including IE9+).
|
||||
cssStyleSheet.insertRule(cssText, index);
|
||||
|
||||
} else {
|
||||
// IE, pre 9: We have to parse the cssRule text to get the selector
|
||||
// separated from the style text.
|
||||
// aka Everything that isn't a colon, followed by a colon, then
|
||||
// the rest is the style part.
|
||||
var matches = /^([^\{]+)\{([^\{]+)\}/.exec(cssText);
|
||||
if (matches.length == 3) {
|
||||
var selector = matches[1];
|
||||
var style = matches[2];
|
||||
cssStyleSheet.addRule(selector, style, index);
|
||||
} else {
|
||||
throw Error('Your CSSRule appears to be ill-formatted.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cross browser function to remove a CSSRule in a CSSStyleSheet at an index.
|
||||
* @param {CSSStyleSheet} cssStyleSheet The CSSRule's parentStyleSheet.
|
||||
* @param {number} index The CSSRule's index in the parentStyleSheet.
|
||||
*/
|
||||
goog.cssom.removeCssRule = function(cssStyleSheet, index) {
|
||||
if (cssStyleSheet.deleteRule) {
|
||||
// W3C.
|
||||
cssStyleSheet.deleteRule(index);
|
||||
|
||||
} else {
|
||||
// IE.
|
||||
cssStyleSheet.removeRule(index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Appends a DOM node to HEAD containing the css text that's passed in.
|
||||
* @param {string} cssText CSS to add to the end of the document.
|
||||
* @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper user for
|
||||
* document interactions.
|
||||
* @return {!Element} The newly created STYLE element.
|
||||
*/
|
||||
goog.cssom.addCssText = function(cssText, opt_domHelper) {
|
||||
var document = opt_domHelper ? opt_domHelper.getDocument() :
|
||||
goog.dom.getDocument();
|
||||
var cssNode = document.createElement('style');
|
||||
cssNode.type = 'text/css';
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
head.appendChild(cssNode);
|
||||
if (cssNode.styleSheet) {
|
||||
// IE.
|
||||
cssNode.styleSheet.cssText = cssText;
|
||||
} else {
|
||||
// W3C.
|
||||
var cssTextNode = document.createTextNode(cssText);
|
||||
cssNode.appendChild(cssTextNode);
|
||||
}
|
||||
return cssNode;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cross browser method to get the filename from the StyleSheet's href.
|
||||
* Explorer only returns the filename in the href, while other agents return
|
||||
* the full path.
|
||||
* @param {!StyleSheet} styleSheet Any valid StyleSheet object with an href.
|
||||
* @throws {Error} When there's no href property found.
|
||||
* @return {?string} filename The filename, or null if not an external
|
||||
* styleSheet.
|
||||
*/
|
||||
goog.cssom.getFileNameFromStyleSheet = function(styleSheet) {
|
||||
var href = styleSheet.href;
|
||||
|
||||
// Another IE/FF difference. IE returns an empty string, while FF and others
|
||||
// return null for CSSStyleSheets not from an external file.
|
||||
if (!href) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need the regexp to ensure we get the filename minus any query params.
|
||||
var matches = /([^\/\?]+)[^\/]*$/.exec(href);
|
||||
var filename = matches[1];
|
||||
return filename;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Recursively gets all CSS text or rules.
|
||||
* @param {CSSStyleSheet|StyleSheetList} styleSheet The CSSStyleSheet.
|
||||
* @param {boolean} isTextOutput If true, output is cssText, otherwise cssRules.
|
||||
* @return {string|!Array<CSSRule>} cssText or cssRules.
|
||||
* @private
|
||||
*/
|
||||
goog.cssom.getAllCss_ = function(styleSheet, isTextOutput) {
|
||||
var cssOut = [];
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets(styleSheet);
|
||||
|
||||
for (var i = 0; styleSheet = styleSheets[i]; i++) {
|
||||
var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
|
||||
if (cssRuleList && cssRuleList.length) {
|
||||
|
||||
// We're going to track cssRule index if we want rule output.
|
||||
if (!isTextOutput) {
|
||||
var ruleIndex = 0;
|
||||
}
|
||||
|
||||
for (var j = 0, n = cssRuleList.length, cssRule; j < n; j++) {
|
||||
cssRule = cssRuleList[j];
|
||||
// Gets cssText output, ignoring CSSImportRules.
|
||||
if (isTextOutput && !cssRule.href) {
|
||||
var res = goog.cssom.getCssTextFromCssRule(cssRule);
|
||||
cssOut.push(res);
|
||||
|
||||
} else if (!cssRule.href) {
|
||||
// Gets cssRules output, ignoring CSSImportRules.
|
||||
if (cssRule.style) {
|
||||
// This is a fun little hack to get parentStyleSheet into the rule
|
||||
// object for IE since it failed to implement rule.parentStyleSheet.
|
||||
// We can later read this property when doing things like hunting
|
||||
// for indexes in order to delete a given CSSRule.
|
||||
// Unfortunately we have to use the style object to store these
|
||||
// pieces of info since the rule object is read-only.
|
||||
if (!cssRule.parentStyleSheet) {
|
||||
cssRule.style['-closure-parent-stylesheet'] = styleSheet;
|
||||
}
|
||||
|
||||
// This is a hack to help with possible removal of the rule later,
|
||||
// where we just append the rule's index in its parentStyleSheet
|
||||
// onto the style object as a property.
|
||||
// Unfortunately we have to use the style object to store these
|
||||
// pieces of info since the rule object is read-only.
|
||||
cssRule.style['-closure-rule-index'] = ruleIndex;
|
||||
}
|
||||
cssOut.push(cssRule);
|
||||
}
|
||||
|
||||
if (!isTextOutput) {
|
||||
ruleIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isTextOutput ? cssOut.join(' ') : cssOut;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>
|
||||
Closure Unit Tests - CSS Object Model helper
|
||||
</title>
|
||||
<script src="../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.cssomTest');
|
||||
</script>
|
||||
</head>
|
||||
<link rel="stylesheet" type="text/css" href="cssom_test_link_1.css">
|
||||
<style>
|
||||
/* This will import css_test_import_1 and css_test_import_2 */
|
||||
@import "cssom_test_import_1.css?cachebust=1";
|
||||
|
||||
.css-style-1 {
|
||||
display: block;
|
||||
}
|
||||
.css-style-2 {
|
||||
display: block;
|
||||
}
|
||||
.css-style-3 {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,323 @@
|
||||
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('goog.cssomTest');
|
||||
goog.setTestOnly('goog.cssomTest');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.cssom');
|
||||
goog.require('goog.cssom.CssRuleType');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
// Since sheet cssom_test1.css's first line is to import
|
||||
// cssom_test2.css, we should get 2 before one in the string.
|
||||
var cssText = '.css-link-1 { display: block; } ' +
|
||||
'.css-import-2 { display: block; } ' +
|
||||
'.css-import-1 { display: block; } ' +
|
||||
'.css-style-1 { display: block; } ' +
|
||||
'.css-style-2 { display: block; } ' +
|
||||
'.css-style-3 { display: block; }';
|
||||
|
||||
var replacementCssText = '.css-repl-1 { display: block; }';
|
||||
|
||||
var isIe7 = goog.userAgent.IE &&
|
||||
(goog.userAgent.compare(goog.userAgent.VERSION, '7.0') == 0);
|
||||
|
||||
// We're going to toLowerCase cssText before testing, because IE returns
|
||||
// CSS property names in UPPERCASE, and the function shouldn't
|
||||
// "fix" the text as it would be expensive and rarely of use.
|
||||
// Same goes for the trailing whitespace in IE.
|
||||
// Same goes for fixing the optimized removal of trailing ; in rules.
|
||||
// Also needed for Opera.
|
||||
function fixCssTextForIe(cssText) {
|
||||
cssText = cssText.toLowerCase().replace(/\s*$/, '');
|
||||
if (cssText.match(/[^;] \}/)) {
|
||||
cssText = cssText.replace(/([^;]) \}/g, '$1; }');
|
||||
}
|
||||
return cssText;
|
||||
}
|
||||
|
||||
function testGetFileNameFromStyleSheet() {
|
||||
var styleSheet = {'href': 'http://foo.com/something/filename.css'};
|
||||
assertEquals('filename.css',
|
||||
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
||||
|
||||
styleSheet = {'href': 'https://foo.com:123/something/filename.css'};
|
||||
assertEquals('filename.css',
|
||||
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
||||
|
||||
styleSheet = {'href': 'http://foo.com/something/filename.css?bar=bas'};
|
||||
assertEquals('filename.css',
|
||||
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
||||
|
||||
styleSheet = {'href': 'filename.css?bar=bas'};
|
||||
assertEquals('filename.css',
|
||||
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
||||
|
||||
styleSheet = {'href': 'filename.css'};
|
||||
assertEquals('filename.css',
|
||||
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
||||
}
|
||||
|
||||
function testGetAllCssStyleSheets() {
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
||||
assertEquals(4, styleSheets.length);
|
||||
// Makes sure they're in the right cascade order.
|
||||
assertEquals('cssom_test_link_1.css',
|
||||
goog.cssom.getFileNameFromStyleSheet(styleSheets[0]));
|
||||
assertEquals('cssom_test_import_2.css',
|
||||
goog.cssom.getFileNameFromStyleSheet(styleSheets[1]));
|
||||
assertEquals('cssom_test_import_1.css',
|
||||
goog.cssom.getFileNameFromStyleSheet(styleSheets[2]));
|
||||
// Not an external styleSheet
|
||||
assertNull(goog.cssom.getFileNameFromStyleSheet(styleSheets[3]));
|
||||
}
|
||||
|
||||
function testGetAllCssText() {
|
||||
var allCssText = goog.cssom.getAllCssText();
|
||||
// In IE7, a CSSRule object gets included twice and replaces another
|
||||
// existing CSSRule object. We aren't using
|
||||
// goog.testing.ExpectedFailures since it brings in additional CSS
|
||||
// which breaks a lot of our expectations about the number of rules
|
||||
// present in a style sheet.
|
||||
if (!isIe7) {
|
||||
assertEquals(cssText, fixCssTextForIe(allCssText));
|
||||
}
|
||||
}
|
||||
|
||||
function testGetAllCssStyleRules() {
|
||||
var allCssRules = goog.cssom.getAllCssStyleRules();
|
||||
assertEquals(6, allCssRules.length);
|
||||
}
|
||||
|
||||
|
||||
function testAddCssText() {
|
||||
var newCssText = '.css-add-1 { display: block; }';
|
||||
var newCssNode = goog.cssom.addCssText(newCssText);
|
||||
|
||||
assertEquals(document.styleSheets.length, 3);
|
||||
|
||||
var allCssText = goog.cssom.getAllCssText();
|
||||
|
||||
// In IE7, a CSSRule object gets included twice and replaces another
|
||||
// existing CSSRule object. We aren't using
|
||||
// goog.testing.ExpectedFailures since it brings in additional CSS
|
||||
// which breaks a lot of our expectations about the number of rules
|
||||
// present in a style sheet.
|
||||
if (!isIe7) {
|
||||
// Opera inserts the CSSRule to the first position. And fixCssText
|
||||
// is also needed to clean up whitespace.
|
||||
if (goog.userAgent.OPERA) {
|
||||
assertEquals(newCssText + ' ' + cssText,
|
||||
fixCssTextForIe(allCssText));
|
||||
} else {
|
||||
assertEquals(cssText + ' ' + newCssText,
|
||||
fixCssTextForIe(allCssText));
|
||||
}
|
||||
}
|
||||
|
||||
var cssRules = goog.cssom.getAllCssStyleRules();
|
||||
assertEquals(7, cssRules.length);
|
||||
|
||||
// Remove the new stylesheet now so it doesn't interfere with other
|
||||
// tests.
|
||||
newCssNode.parentNode.removeChild(newCssNode);
|
||||
// Sanity check.
|
||||
cssRules = goog.cssom.getAllCssStyleRules();
|
||||
assertEquals(6, cssRules.length);
|
||||
}
|
||||
|
||||
function testAddCssRule() {
|
||||
// test that addCssRule correctly adds the rule to the style
|
||||
// sheet.
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
||||
var styleSheet = styleSheets[3];
|
||||
var newCssRule = '.css-addCssRule { display: block; }';
|
||||
var rules = styleSheet.rules || styleSheet.cssRules;
|
||||
var origNumberOfRules = rules.length;
|
||||
|
||||
goog.cssom.addCssRule(styleSheet, newCssRule, 1);
|
||||
|
||||
rules = styleSheet.rules || styleSheet.cssRules;
|
||||
var newNumberOfRules = rules.length;
|
||||
assertEquals(newNumberOfRules, origNumberOfRules + 1);
|
||||
|
||||
// Remove the added rule so we don't mess up other tests.
|
||||
goog.cssom.removeCssRule(styleSheet, 1);
|
||||
}
|
||||
|
||||
function testAddCssRuleAtPos() {
|
||||
// test that addCssRule correctly adds the rule to the style
|
||||
// sheet at the specified position.
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
||||
var styleSheet = styleSheets[3];
|
||||
var newCssRule = '.css-addCssRulePos { display: block; }';
|
||||
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
var origNumberOfRules = rules.length;
|
||||
|
||||
// Firefox croaks if we try to insert a CSSRule at an index that
|
||||
// contains a CSSImport Rule. Since we deal only with CSSStyleRule
|
||||
// objects, we find the first CSSStyleRule and return its index.
|
||||
//
|
||||
// NOTE(user): We could have unified the code block below for all
|
||||
// browsers but IE6 horribly mangled up the stylesheet by creating
|
||||
// duplicate instances of a rule when removeCssRule was invoked
|
||||
// just after addCssRule with the looping construct in. This is
|
||||
// perfectly fine since IE's styleSheet.rules does not contain
|
||||
// references to anything but CSSStyleRules.
|
||||
var pos = 0;
|
||||
if (styleSheet.cssRules) {
|
||||
pos = goog.array.findIndex(rules, function(rule) {
|
||||
return rule.type == goog.cssom.CssRuleType.STYLE;
|
||||
});
|
||||
}
|
||||
goog.cssom.addCssRule(styleSheet, newCssRule, pos);
|
||||
|
||||
rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
var newNumberOfRules = rules.length;
|
||||
assertEquals(newNumberOfRules, origNumberOfRules + 1);
|
||||
|
||||
// Remove the added rule so we don't mess up other tests.
|
||||
goog.cssom.removeCssRule(styleSheet, pos);
|
||||
|
||||
rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
assertEquals(origNumberOfRules, rules.length);
|
||||
}
|
||||
|
||||
function testAddCssRuleNoIndex() {
|
||||
// How well do we handle cases where the optional index is
|
||||
// not passed in?
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
||||
var styleSheet = styleSheets[3];
|
||||
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
var origNumberOfRules = rules.length;
|
||||
var newCssRule = '.css-addCssRuleNoIndex { display: block; }';
|
||||
|
||||
// Try inserting the rule without specifying an index.
|
||||
// Make sure we don't throw an exception, and that we added
|
||||
// the entry.
|
||||
goog.cssom.addCssRule(styleSheet, newCssRule);
|
||||
|
||||
rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
var newNumberOfRules = rules.length;
|
||||
assertEquals(newNumberOfRules, origNumberOfRules + 1);
|
||||
|
||||
// Remove the added rule so we don't mess up the other tests.
|
||||
goog.cssom.removeCssRule(styleSheet, newNumberOfRules - 1);
|
||||
|
||||
rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
assertEquals(origNumberOfRules, rules.length);
|
||||
}
|
||||
|
||||
|
||||
function testGetParentStyleSheetAfterGetAllCssStyleRules() {
|
||||
var cssRules = goog.cssom.getAllCssStyleRules();
|
||||
var cssRule = cssRules[4];
|
||||
var parentStyleSheet = goog.cssom.getParentStyleSheet(cssRule);
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
||||
var styleSheet = styleSheets[3];
|
||||
assertEquals(styleSheet, parentStyleSheet);
|
||||
}
|
||||
|
||||
function testGetCssRuleIndexInParentStyleSheetAfterGetAllCssStyleRules() {
|
||||
var cssRules = goog.cssom.getAllCssStyleRules();
|
||||
var cssRule = cssRules[4];
|
||||
// Note here that this is correct - IE's styleSheet.rules does not
|
||||
// contain references to anything but CSSStyleRules while FF and others
|
||||
// include anything that inherits from the CSSRule interface.
|
||||
// See http://dev.w3.org/csswg/cssom/#cssrule.
|
||||
var parentStyleSheet = goog.cssom.getParentStyleSheet(cssRule);
|
||||
var ruleIndex = goog.isDefAndNotNull(parentStyleSheet.cssRules) ? 2 : 1;
|
||||
assertEquals(ruleIndex,
|
||||
goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule));
|
||||
}
|
||||
|
||||
function testGetCssRuleIndexInParentStyleSheetNonStyleRule() {
|
||||
// IE's styleSheet.rules only contain CSSStyleRules.
|
||||
if (!goog.userAgent.IE) {
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
||||
var styleSheet = styleSheets[3];
|
||||
var newCssRule = '@media print { .css-nonStyle { display: block; } }';
|
||||
goog.cssom.addCssRule(styleSheet, newCssRule);
|
||||
var rules = styleSheet.rules || styleSheet.cssRules;
|
||||
var cssRule = rules[rules.length - 1];
|
||||
assertEquals(goog.cssom.CssRuleType.MEDIA, cssRule.type);
|
||||
// Make sure we don't throw an exception.
|
||||
goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule, styleSheet);
|
||||
// Remove the added rule.
|
||||
goog.cssom.removeCssRule(styleSheet, rules.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests the scenario where we have a known stylesheet and index.
|
||||
function testReplaceCssRuleWithStyleSheetAndIndex() {
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
||||
var styleSheet = styleSheets[3];
|
||||
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
var index = 2;
|
||||
var origCssRule = rules[index];
|
||||
var origCssText =
|
||||
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(origCssRule));
|
||||
|
||||
goog.cssom.replaceCssRule(origCssRule, replacementCssText, styleSheet,
|
||||
index);
|
||||
|
||||
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
var newCssRule = rules[index];
|
||||
var newCssText = goog.cssom.getCssTextFromCssRule(newCssRule);
|
||||
assertEquals(replacementCssText, fixCssTextForIe(newCssText));
|
||||
|
||||
// Now we need to re-replace our rule, to preserve parity for the other
|
||||
// tests.
|
||||
goog.cssom.replaceCssRule(newCssRule, origCssText, styleSheet, index);
|
||||
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
var nowCssRule = rules[index];
|
||||
var nowCssText = goog.cssom.getCssTextFromCssRule(nowCssRule);
|
||||
assertEquals(origCssText, fixCssTextForIe(nowCssText));
|
||||
}
|
||||
|
||||
function testReplaceCssRuleUsingGetAllCssStyleRules() {
|
||||
var cssRules = goog.cssom.getAllCssStyleRules();
|
||||
var origCssRule = cssRules[4];
|
||||
var origCssText =
|
||||
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(origCssRule));
|
||||
// notice we don't pass in the stylesheet or index.
|
||||
goog.cssom.replaceCssRule(origCssRule, replacementCssText);
|
||||
|
||||
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
||||
var styleSheet = styleSheets[3];
|
||||
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
||||
var index = goog.isDefAndNotNull(styleSheet.cssRules) ? 2 : 1;
|
||||
var newCssRule = rules[index];
|
||||
var newCssText =
|
||||
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(newCssRule));
|
||||
assertEquals(replacementCssText, newCssText);
|
||||
|
||||
// try getting it the other way around too.
|
||||
var cssRules = goog.cssom.getAllCssStyleRules();
|
||||
var newCssRule = cssRules[4];
|
||||
var newCssText =
|
||||
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(newCssRule));
|
||||
assertEquals(replacementCssText, newCssText);
|
||||
|
||||
// Now we need to re-replace our rule, to preserve parity for the other
|
||||
// tests.
|
||||
goog.cssom.replaceCssRule(newCssRule, origCssText);
|
||||
var cssRules = goog.cssom.getAllCssStyleRules();
|
||||
var nowCssRule = cssRules[4];
|
||||
var nowCssText =
|
||||
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(nowCssRule));
|
||||
assertEquals(origCssText, nowCssText);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010 The Closure Library Authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Apache License, Version 2.0.
|
||||
* See the COPYING file for details.
|
||||
*/
|
||||
|
||||
@import "cssom_test_import_2.css";
|
||||
.css-import-1 {
|
||||
display: block;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010 The Closure Library Authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Apache License, Version 2.0.
|
||||
* See the COPYING file for details.
|
||||
*/
|
||||
|
||||
.css-import-2 {
|
||||
display: block;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010 The Closure Library Authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Apache License, Version 2.0.
|
||||
* See the COPYING file for details.
|
||||
*/
|
||||
|
||||
.css-link-1 {
|
||||
display: block;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,129 @@
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2010 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<script src="../../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.cssom.iframe.styleTest');
|
||||
</script>
|
||||
<style type="text/css">
|
||||
@import url("style_test_import.css");
|
||||
|
||||
body { font-family: Verdana; }
|
||||
div { background-color: #ffc; margin: 10px 0; }
|
||||
p { margin: 10px 0; }
|
||||
.boxy { padding: 5px; background-color: #fa0; }
|
||||
.special .boxy { padding: 10px; background-color: #abef00; }
|
||||
div div strong { color: red; }
|
||||
div { line-height: 1.3; }
|
||||
.wrapper .inner-wrapper { border: 2px solid pink;}
|
||||
a { color: red; }
|
||||
#source4 { background-color: #900; }
|
||||
|
||||
#backgroundTest-ancestor-1 {
|
||||
background-color: rgb(128,0,128);
|
||||
}
|
||||
#backgroundTest-ancestor-0 {
|
||||
background-image: url("../../images/blank.gif");
|
||||
background-position: 40px 70px;
|
||||
background-repeat: repeat;
|
||||
background-color: transparent;
|
||||
padding: 5px 8px;
|
||||
}
|
||||
div#backgroundTest-parent {
|
||||
border: 1px solid black;
|
||||
background-color: transparent;
|
||||
}
|
||||
div#backgroundTest {
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
height: 100px;
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.goog-presently-theme-monochrome {
|
||||
background-color: black;
|
||||
color: #CCC;
|
||||
}
|
||||
.goog-presently-theme-monochrome a {
|
||||
color: #FFF;
|
||||
}
|
||||
.goog-presently-theme-monochrome p#source4 {
|
||||
font-variant: small-caps;
|
||||
}
|
||||
|
||||
.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: Cavalier;
|
||||
}
|
||||
#cavalier {
|
||||
font-family: Cavalier;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="inner-wrapper">
|
||||
<div id="source1" class="italic">
|
||||
hello world
|
||||
</div>
|
||||
<div id="source2">
|
||||
<div>
|
||||
Some
|
||||
<strong>
|
||||
strong
|
||||
</strong>
|
||||
text
|
||||
</div>
|
||||
<div class="boxy exciting">
|
||||
A box
|
||||
</div>
|
||||
<div class="inner-wrapper">
|
||||
A wrapper
|
||||
</div>
|
||||
</div>
|
||||
<div id="source3" class="special">
|
||||
Some
|
||||
<strong>
|
||||
strong
|
||||
</strong>
|
||||
text
|
||||
<div class="boxy">
|
||||
A box
|
||||
</div>
|
||||
</div>
|
||||
<div id="ancestor" class="goog-presently-theme-monochrome">
|
||||
<p id="source4" style="background-color: #900">
|
||||
Here's a link:
|
||||
<a href="#">
|
||||
my link
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div id="backgroundTest-ancestor-1">
|
||||
<div id="backgroundTest-ancestor-0">
|
||||
<div id="backgroundTest-parent">
|
||||
<div id="backgroundTest">
|
||||
hello
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cavalier">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,292 @@
|
||||
// Copyright 2010 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('goog.cssom.iframe.styleTest');
|
||||
goog.setTestOnly('goog.cssom.iframe.styleTest');
|
||||
|
||||
goog.require('goog.cssom');
|
||||
goog.require('goog.cssom.iframe.style');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.DomHelper');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
// unit tests
|
||||
var propertiesToTest = [
|
||||
'color',
|
||||
'font-family',
|
||||
'font-style',
|
||||
'font-size',
|
||||
'font-variant',
|
||||
'border-top-style',
|
||||
'border-top-width',
|
||||
'border-top-color',
|
||||
'background-color',
|
||||
'margin-bottom'
|
||||
];
|
||||
|
||||
function crawlDom(startNode, func) {
|
||||
if (startNode.nodeType != 1) { return; }
|
||||
func(startNode);
|
||||
for (var i = 0; i < startNode.childNodes.length; i++) {
|
||||
crawlDom(startNode.childNodes[i], func);
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentCssProperties(node, propList) {
|
||||
var props = {};
|
||||
if (node.nodeType != 1) { return; }
|
||||
for (var i = 0; i < propList.length; i++) {
|
||||
var prop = propList[i];
|
||||
if (node.currentStyle) { // IE
|
||||
var propCamelCase = '';
|
||||
var propParts = prop.split('-');
|
||||
for (var j = 0; j < propParts.length; j++) {
|
||||
propCamelCase += propParts[j].charAt(0).toUpperCase() +
|
||||
propParts[j].substring(1, propParts[j].length);
|
||||
}
|
||||
props[prop] = node.currentStyle[propCamelCase];
|
||||
} else { // standards-compliant browsers
|
||||
props[prop] = node.ownerDocument.defaultView.getComputedStyle(
|
||||
node, '').getPropertyValue(prop);
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
function CssPropertyCollector() {
|
||||
var propsList = [];
|
||||
this.propsList = propsList;
|
||||
|
||||
this.collectProps = function(node) {
|
||||
var nodeProps = getCurrentCssProperties(node, propertiesToTest);
|
||||
if (nodeProps) { propsList.push([nodeProps, node]); }
|
||||
};
|
||||
}
|
||||
|
||||
function recursivelyListCssProperties(el) {
|
||||
var collector = new CssPropertyCollector();
|
||||
crawlDom(el, collector.collectProps);
|
||||
return collector.propsList;
|
||||
}
|
||||
|
||||
function testMatchCssSelector() {
|
||||
var container = document.createElement('div');
|
||||
container.className = 'container';
|
||||
var el = document.createElement('div');
|
||||
x = el;
|
||||
el.id = 'mydiv';
|
||||
el.className = 'colorful foo';
|
||||
// set some arbirtrary content
|
||||
el.innerHTML = '<div><ul><li>One</li><li>Two</li></ul></div>';
|
||||
container.appendChild(el);
|
||||
document.body.appendChild(container);
|
||||
|
||||
var elementAncestry = new goog.cssom.iframe.style.NodeAncestry_(el);
|
||||
assertEquals(5, elementAncestry.nodes.length);
|
||||
|
||||
// list of input/output results. Output is the index of the selector
|
||||
// that we expect to match - for example, in 'body div div.colorful',
|
||||
// 'div.colorful' has an index of 2.
|
||||
var expectedResults = [
|
||||
['body div', [4, 1]],
|
||||
['h1', null],
|
||||
['body div h1', [4, 1]],
|
||||
['body div.colorful h1', [4, 1]],
|
||||
['body div div', [4, 2]],
|
||||
['body div div div', [4, 2]],
|
||||
['body div div.somethingelse div', [4, 1]],
|
||||
['body div.somethingelse div', [2, 0]],
|
||||
['div.container', [3, 0]],
|
||||
['div.container div', [4, 1]],
|
||||
['#mydiv', [4, 0]],
|
||||
['div#mydiv', [4, 0]],
|
||||
['div.colorful', [4, 0]],
|
||||
['div#mydiv .colorful', [4, 0]],
|
||||
['.colorful', [4, 0]],
|
||||
['body * div', [4, 2]],
|
||||
['body * *', [4, 2]]
|
||||
];
|
||||
for (var i = 0; i < expectedResults.length; i++) {
|
||||
var input = expectedResults[i][0];
|
||||
var expectedResult = expectedResults[i][1];
|
||||
var selector = new goog.cssom.iframe.style.CssSelector_(input);
|
||||
var result = selector.matchElementAncestry(elementAncestry);
|
||||
if (expectedResult == null) {
|
||||
assertEquals('Expected null result', expectedResult, result);
|
||||
} else {
|
||||
assertEquals('Expected element index for ' + input,
|
||||
expectedResult[0],
|
||||
result.elementIndex);
|
||||
assertEquals('Expected selector part index for ' + input,
|
||||
expectedResult[1],
|
||||
result.selectorPartIndex);
|
||||
}
|
||||
}
|
||||
document.body.removeChild(container);
|
||||
}
|
||||
|
||||
function makeIframeDocument(iframe) {
|
||||
var doc = goog.dom.getFrameContentDocument(iframe);
|
||||
doc.open();
|
||||
doc.write('<html><head>');
|
||||
doc.write('<style>html,body { background-color: transparent; }</style>');
|
||||
doc.write('</head><body></body></html>');
|
||||
doc.close();
|
||||
return doc;
|
||||
}
|
||||
|
||||
function testCopyCss() {
|
||||
for (var i = 1; i <= 4; i++) {
|
||||
var sourceElement = document.getElementById('source' + i);
|
||||
var newFrame = document.createElement('iframe');
|
||||
newFrame.allowTransparency = true;
|
||||
sourceElement.parentNode.insertBefore(newFrame,
|
||||
sourceElement.nextSibling);
|
||||
var doc = makeIframeDocument(newFrame);
|
||||
goog.cssom.addCssText(
|
||||
goog.cssom.iframe.style.getElementContext(sourceElement),
|
||||
new goog.dom.DomHelper(doc));
|
||||
doc.body.innerHTML = sourceElement.innerHTML;
|
||||
|
||||
var oldProps = recursivelyListCssProperties(sourceElement);
|
||||
var newProps = recursivelyListCssProperties(doc.body);
|
||||
|
||||
assertEquals(oldProps.length, newProps.length);
|
||||
for (var j = 0; j < oldProps.length; j++) {
|
||||
for (var k = 0; k < propertiesToTest.length; k++) {
|
||||
assertEquals('testing property ' + propertiesToTest[k],
|
||||
oldProps[j][0][propertiesToTest[k]],
|
||||
newProps[j][0][propertiesToTest[k]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeCssText(cssText) {
|
||||
// Normalize cssText for testing purposes.
|
||||
return cssText.replace(/\s/g, '').toLowerCase();
|
||||
}
|
||||
|
||||
function testAImportantInFF2() {
|
||||
var testDiv = document.getElementById('source1');
|
||||
var cssText = normalizeCssText(
|
||||
goog.cssom.iframe.style.getElementContext(testDiv));
|
||||
var color = standardizeCSSValue('color', 'red');
|
||||
var NORMAL_RULE = 'a{color:' + color;
|
||||
var FF_2_RULE = 'a{color:' + color + '!important';
|
||||
if (goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('1.9a')) {
|
||||
assertContains(FF_2_RULE, cssText);
|
||||
} else {
|
||||
assertContains(NORMAL_RULE, cssText);
|
||||
assertNotContains(FF_2_RULE, cssText);
|
||||
}
|
||||
}
|
||||
|
||||
function testCopyBackgroundContext() {
|
||||
var testDiv = document.getElementById('backgroundTest');
|
||||
var cssText = goog.cssom.iframe.style.getElementContext(testDiv,
|
||||
null,
|
||||
true);
|
||||
var iframe = document.createElement('iframe');
|
||||
var ancestor = document.getElementById('backgroundTest-ancestor-1');
|
||||
ancestor.parentNode.insertBefore(iframe, ancestor.nextSibling);
|
||||
iframe.style.width = '100%';
|
||||
iframe.style.height = '100px';
|
||||
iframe.style.borderWidth = '0px';
|
||||
var doc = makeIframeDocument(iframe);
|
||||
goog.cssom.addCssText(cssText, new goog.dom.DomHelper(doc));
|
||||
doc.body.innerHTML = testDiv.innerHTML;
|
||||
var normalizedCssText = normalizeCssText(cssText);
|
||||
assertTrue(
|
||||
'Background color should be copied from parent element',
|
||||
/body{[^{]*background-color:(?:rgb\(128,0,128\)|#800080)/.test(
|
||||
normalizedCssText));
|
||||
assertTrue(
|
||||
'Background image should be copied from ancestor element',
|
||||
/body{[^{]*background-image:url\(/.test(normalizedCssText));
|
||||
// Background-position can't be calculated in FF2, due to this bug:
|
||||
// http://bugzilla.mozilla.org/show_bug.cgi?id=316981
|
||||
if (!(goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('1.9'))) {
|
||||
// Expected x position is:
|
||||
// originalBackgroundPositionX - elementOffsetLeft
|
||||
// 40px - (1px + 8px) == 31px
|
||||
// Expected y position is:
|
||||
// originalBackgroundPositionY - elementOffsetLeft
|
||||
// 70px - (1px + 10px + 5px) == 54px;
|
||||
assertTrue('Background image position should be adjusted correctly',
|
||||
/body{[^{]*background-position:31px54px/.test(normalizedCssText));
|
||||
}
|
||||
}
|
||||
|
||||
function testCopyBackgroundContextFromIframe() {
|
||||
var testDiv = document.getElementById('backgroundTest');
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.allowTransparency = true;
|
||||
iframe.style.position = 'absolute';
|
||||
iframe.style.top = '5px';
|
||||
iframe.style.left = '5px';
|
||||
iframe.style.borderWidth = '2px';
|
||||
iframe.style.borderStyle = 'solid';
|
||||
testDiv.appendChild(iframe);
|
||||
var doc = makeIframeDocument(iframe);
|
||||
doc.body.backgroundColor = 'transparent';
|
||||
doc.body.style.margin = '0';
|
||||
doc.body.style.padding = '0';
|
||||
doc.body.innerHTML = '<p style="margin: 0">I am transparent!</p>';
|
||||
var normalizedCssText = normalizeCssText(
|
||||
goog.cssom.iframe.style.getElementContext(
|
||||
doc.body.firstChild, null, true));
|
||||
// Background properties should get copied through from the parent
|
||||
// document since the iframe is transparent
|
||||
assertTrue(
|
||||
'Background color should be copied from parent element',
|
||||
/body{[^{]*background-color:(?:rgb\(128,0,128\)|#800080)/.test(
|
||||
normalizedCssText));
|
||||
assertTrue(
|
||||
'Background image should be copied from ancestor element',
|
||||
/body{[^{]*background-image:url\(/.test(normalizedCssText));
|
||||
// Background-position can't be calculated in FF2, due to this bug:
|
||||
// http://bugzilla.mozilla.org/show_bug.cgi?id=316981
|
||||
if (!(goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('1.9'))) {
|
||||
// Image offset should have been calculated to be the same as the
|
||||
// above example, but adding iframe offset and borderWidth.
|
||||
// Expected x position is:
|
||||
// originalBackgroundPositionX - elementOffsetLeft
|
||||
// 40px - (1px + 8px + 5px + 2px) == 24px
|
||||
// Expected y position is:
|
||||
// originalBackgroundPositionY - elementOffsetLeft
|
||||
// 70px - (1px + 10px + 5px + 5px + 2px) == 47px;
|
||||
assertTrue('Background image position should be adjusted correctly',
|
||||
!!/body{[^{]*background-position:24px47px/.exec(
|
||||
normalizedCssText));
|
||||
}
|
||||
iframe.parentNode.removeChild(iframe);
|
||||
}
|
||||
|
||||
function testCopyFontFaceRules() {
|
||||
var isFontFaceCssomSupported =
|
||||
goog.userAgent.WEBKIT ||
|
||||
goog.userAgent.OPERA ||
|
||||
(goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.1'));
|
||||
// We cannot use goog.testing.ExpectedFailures since it dynamically
|
||||
// brings in CSS which causes the background context tests to fail
|
||||
// in IE6.
|
||||
if (isFontFaceCssomSupported) {
|
||||
var cssText = goog.cssom.iframe.style.getElementContext(
|
||||
document.getElementById('cavalier'));
|
||||
assertTrue('The font face rule should have been copied correctly',
|
||||
/@font-face/.test(cssText));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010 The Closure Library Authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Apache License, Version 2.0.
|
||||
* See the COPYING file for details.
|
||||
*/
|
||||
|
||||
div div strong {
|
||||
font-style: italic;
|
||||
}
|
||||
Reference in New Issue
Block a user