Files
react/src/renderers/dom/shared/CSSPropertyOperations.js
T
Ben Alpert ba9b985406 Rename host-y things to be "host" not "native" (#6754)
For clarity.

I left "native event" as-is because there's a lot of it, it's not particularly ambiguous, and SimulateNative/nativeTouchData are public API in ReactTestUtils.
2016-05-11 23:22:59 -07:00

241 lines
6.6 KiB
JavaScript

/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CSSPropertyOperations
*/
'use strict';
var CSSProperty = require('CSSProperty');
var ExecutionEnvironment = require('ExecutionEnvironment');
var ReactInstrumentation = require('ReactInstrumentation');
var camelizeStyleName = require('camelizeStyleName');
var dangerousStyleValue = require('dangerousStyleValue');
var hyphenateStyleName = require('hyphenateStyleName');
var memoizeStringOnly = require('memoizeStringOnly');
var warning = require('warning');
var processStyleName = memoizeStringOnly(function(styleName) {
return hyphenateStyleName(styleName);
});
var hasShorthandPropertyBug = false;
var styleFloatAccessor = 'cssFloat';
if (ExecutionEnvironment.canUseDOM) {
var tempStyle = document.createElement('div').style;
try {
// IE8 throws "Invalid argument." if resetting shorthand style properties.
tempStyle.font = '';
} catch (e) {
hasShorthandPropertyBug = true;
}
// IE8 only supports accessing cssFloat (standard) as styleFloat
if (document.documentElement.style.cssFloat === undefined) {
styleFloatAccessor = 'styleFloat';
}
}
if (__DEV__) {
// 'msTransform' is correct, but the other prefixes should be capitalized
var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
// style values shouldn't contain a semicolon
var badStyleValueWithSemicolonPattern = /;\s*$/;
var warnedStyleNames = {};
var warnedStyleValues = {};
var warnedForNaNValue = false;
var warnHyphenatedStyleName = function(name, owner) {
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
return;
}
warnedStyleNames[name] = true;
warning(
false,
'Unsupported style property %s. Did you mean %s?%s',
name,
camelizeStyleName(name),
checkRenderMessage(owner)
);
};
var warnBadVendoredStyleName = function(name, owner) {
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
return;
}
warnedStyleNames[name] = true;
warning(
false,
'Unsupported vendor-prefixed style property %s. Did you mean %s?%s',
name,
name.charAt(0).toUpperCase() + name.slice(1),
checkRenderMessage(owner)
);
};
var warnStyleValueWithSemicolon = function(name, value, owner) {
if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
return;
}
warnedStyleValues[value] = true;
warning(
false,
'Style property values shouldn\'t contain a semicolon.%s ' +
'Try "%s: %s" instead.',
checkRenderMessage(owner),
name,
value.replace(badStyleValueWithSemicolonPattern, '')
);
};
var warnStyleValueIsNaN = function(name, value, owner) {
if (warnedForNaNValue) {
return;
}
warnedForNaNValue = true;
warning(
false,
'`NaN` is an invalid value for the `%s` css style property.%s',
name,
checkRenderMessage(owner)
);
};
var checkRenderMessage = function(owner) {
if (owner) {
var name = owner.getName();
if (name) {
return ' Check the render method of `' + name + '`.';
}
}
return '';
};
/**
* @param {string} name
* @param {*} value
* @param {ReactDOMComponent} component
*/
var warnValidStyle = function(name, value, component) {
var owner;
if (component) {
owner = component._currentElement._owner;
}
if (name.indexOf('-') > -1) {
warnHyphenatedStyleName(name, owner);
} else if (badVendoredStyleNamePattern.test(name)) {
warnBadVendoredStyleName(name, owner);
} else if (badStyleValueWithSemicolonPattern.test(value)) {
warnStyleValueWithSemicolon(name, value, owner);
}
if (typeof value === 'number' && isNaN(value)) {
warnStyleValueIsNaN(name, value, owner);
}
};
}
/**
* Operations for dealing with CSS properties.
*/
var CSSPropertyOperations = {
/**
* Serializes a mapping of style properties for use as inline styles:
*
* > createMarkupForStyles({width: '200px', height: 0})
* "width:200px;height:0;"
*
* Undefined values are ignored so that declarative programming is easier.
* The result should be HTML-escaped before insertion into the DOM.
*
* @param {object} styles
* @param {ReactDOMComponent} component
* @return {?string}
*/
createMarkupForStyles: function(styles, component) {
var serialized = '';
for (var styleName in styles) {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
var styleValue = styles[styleName];
if (__DEV__) {
warnValidStyle(styleName, styleValue, component);
}
if (styleValue != null) {
serialized += processStyleName(styleName) + ':';
serialized +=
dangerousStyleValue(styleName, styleValue, component) + ';';
}
}
return serialized || null;
},
/**
* Sets the value for multiple styles on a node. If a value is specified as
* '' (empty string), the corresponding style property will be unset.
*
* @param {DOMElement} node
* @param {object} styles
* @param {ReactDOMComponent} component
*/
setValueForStyles: function(node, styles, component) {
if (__DEV__) {
ReactInstrumentation.debugTool.onHostOperation(
component._debugID,
'update styles',
styles
);
}
var style = node.style;
for (var styleName in styles) {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
if (__DEV__) {
warnValidStyle(styleName, styles[styleName], component);
}
var styleValue = dangerousStyleValue(
styleName,
styles[styleName],
component
);
if (styleName === 'float' || styleName === 'cssFloat') {
styleName = styleFloatAccessor;
}
if (styleValue) {
style[styleName] = styleValue;
} else {
var expansion =
hasShorthandPropertyBug &&
CSSProperty.shorthandPropertyExpansions[styleName];
if (expansion) {
// Shorthand property that IE8 won't like unsetting, so unset each
// component to placate it
for (var individualStyleName in expansion) {
style[individualStyleName] = '';
}
} else {
style[styleName] = '';
}
}
}
},
};
module.exports = CSSPropertyOperations;