2017-05-03 15:35:00 +02:00
/ * *
* 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 .
*
* /
'use strict' ;
var CSSProperty = require ( './CSSProperty' ) ;
var ExecutionEnvironment = require ( 'fbjs/lib/ExecutionEnvironment' ) ;
var ReactInstrumentation = require ( './ReactInstrumentation' ) ;
var camelizeStyleName = require ( 'fbjs/lib/camelizeStyleName' ) ;
var dangerousStyleValue = require ( './dangerousStyleValue' ) ;
var hyphenateStyleName = require ( 'fbjs/lib/hyphenateStyleName' ) ;
var memoizeStringOnly = require ( 'fbjs/lib/memoizeStringOnly' ) ;
var warning = require ( 'fbjs/lib/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 ( process . env . NODE _ENV !== 'production' ) {
// '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 ;
process . env . NODE _ENV !== 'production' ? warning ( false , 'Unsupported style property %s. Did you mean %s?%s' , name , camelizeStyleName ( name ) , checkRenderMessage ( owner ) ) : void 0 ;
} ;
var warnBadVendoredStyleName = function ( name , owner ) {
if ( warnedStyleNames . hasOwnProperty ( name ) && warnedStyleNames [ name ] ) {
return ;
}
warnedStyleNames [ name ] = true ;
process . env . NODE _ENV !== 'production' ? warning ( false , 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s' , name , name . charAt ( 0 ) . toUpperCase ( ) + name . slice ( 1 ) , checkRenderMessage ( owner ) ) : void 0 ;
} ;
var warnStyleValueWithSemicolon = function ( name , value , owner ) {
if ( warnedStyleValues . hasOwnProperty ( value ) && warnedStyleValues [ value ] ) {
return ;
}
warnedStyleValues [ value ] = true ;
2017-08-14 05:01:11 +02:00
process . env . NODE _ENV !== 'production' ? warning ( false , "Style property values shouldn't contain a semicolon.%s " + 'Try "%s: %s" instead.' , checkRenderMessage ( owner ) , name , value . replace ( badStyleValueWithSemicolonPattern , '' ) ) : void 0 ;
2017-05-03 15:35:00 +02:00
} ;
var warnStyleValueIsNaN = function ( name , value , owner ) {
if ( warnedForNaNValue ) {
return ;
}
warnedForNaNValue = true ;
process . env . NODE _ENV !== 'production' ? warning ( false , '`NaN` is an invalid value for the `%s` css style property.%s' , name , checkRenderMessage ( owner ) ) : void 0 ;
} ;
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 ;
}
2017-08-14 05:01:11 +02:00
var isCustomProperty = styleName . indexOf ( '--' ) === 0 ;
2017-05-03 15:35:00 +02:00
var styleValue = styles [ styleName ] ;
if ( process . env . NODE _ENV !== 'production' ) {
2017-08-14 05:01:11 +02:00
if ( ! isCustomProperty ) {
warnValidStyle ( styleName , styleValue , component ) ;
}
2017-05-03 15:35:00 +02:00
}
if ( styleValue != null ) {
serialized += processStyleName ( styleName ) + ':' ;
2017-08-14 05:01:11 +02:00
serialized += dangerousStyleValue ( styleName , styleValue , component , isCustomProperty ) + ';' ;
2017-05-03 15:35:00 +02:00
}
}
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 ( process . env . NODE _ENV !== 'production' ) {
ReactInstrumentation . debugTool . onHostOperation ( {
instanceID : component . _debugID ,
type : 'update styles' ,
payload : styles
} ) ;
}
var style = node . style ;
for ( var styleName in styles ) {
if ( ! styles . hasOwnProperty ( styleName ) ) {
continue ;
}
2017-08-14 05:01:11 +02:00
var isCustomProperty = styleName . indexOf ( '--' ) === 0 ;
2017-05-03 15:35:00 +02:00
if ( process . env . NODE _ENV !== 'production' ) {
2017-08-14 05:01:11 +02:00
if ( ! isCustomProperty ) {
warnValidStyle ( styleName , styles [ styleName ] , component ) ;
}
2017-05-03 15:35:00 +02:00
}
2017-08-14 05:01:11 +02:00
var styleValue = dangerousStyleValue ( styleName , styles [ styleName ] , component , isCustomProperty ) ;
2017-05-03 15:35:00 +02:00
if ( styleName === 'float' || styleName === 'cssFloat' ) {
styleName = styleFloatAccessor ;
}
2017-08-14 05:01:11 +02:00
if ( isCustomProperty ) {
style . setProperty ( styleName , styleValue ) ;
} else if ( styleValue ) {
2017-05-03 15:35:00 +02:00
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 ;