diff options
Diffstat (limited to 'node_modules/react-dom/lib/DOMPropertyOperations.js')
-rw-r--r-- | node_modules/react-dom/lib/DOMPropertyOperations.js | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/node_modules/react-dom/lib/DOMPropertyOperations.js b/node_modules/react-dom/lib/DOMPropertyOperations.js new file mode 100644 index 000000000..94b110930 --- /dev/null +++ b/node_modules/react-dom/lib/DOMPropertyOperations.js @@ -0,0 +1,236 @@ +/** + * 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 DOMProperty = require('./DOMProperty'); +var ReactDOMComponentTree = require('./ReactDOMComponentTree'); +var ReactInstrumentation = require('./ReactInstrumentation'); + +var quoteAttributeValueForBrowser = require('./quoteAttributeValueForBrowser'); +var warning = require('fbjs/lib/warning'); + +var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$'); +var illegalAttributeNameCache = {}; +var validatedAttributeNameCache = {}; + +function isAttributeNameSafe(attributeName) { + if (validatedAttributeNameCache.hasOwnProperty(attributeName)) { + return true; + } + if (illegalAttributeNameCache.hasOwnProperty(attributeName)) { + return false; + } + if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { + validatedAttributeNameCache[attributeName] = true; + return true; + } + illegalAttributeNameCache[attributeName] = true; + process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0; + return false; +} + +function shouldIgnoreValue(propertyInfo, value) { + return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false; +} + +/** + * Operations for dealing with DOM properties. + */ +var DOMPropertyOperations = { + + /** + * Creates markup for the ID property. + * + * @param {string} id Unescaped ID. + * @return {string} Markup string. + */ + createMarkupForID: function (id) { + return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id); + }, + + setAttributeForID: function (node, id) { + node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id); + }, + + createMarkupForRoot: function () { + return DOMProperty.ROOT_ATTRIBUTE_NAME + '=""'; + }, + + setAttributeForRoot: function (node) { + node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, ''); + }, + + /** + * Creates markup for a property. + * + * @param {string} name + * @param {*} value + * @return {?string} Markup string, or null if the property was invalid. + */ + createMarkupForProperty: function (name, value) { + var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; + if (propertyInfo) { + if (shouldIgnoreValue(propertyInfo, value)) { + return ''; + } + var attributeName = propertyInfo.attributeName; + if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) { + return attributeName + '=""'; + } + return attributeName + '=' + quoteAttributeValueForBrowser(value); + } else if (DOMProperty.isCustomAttribute(name)) { + if (value == null) { + return ''; + } + return name + '=' + quoteAttributeValueForBrowser(value); + } + return null; + }, + + /** + * Creates markup for a custom property. + * + * @param {string} name + * @param {*} value + * @return {string} Markup string, or empty string if the property was invalid. + */ + createMarkupForCustomAttribute: function (name, value) { + if (!isAttributeNameSafe(name) || value == null) { + return ''; + } + return name + '=' + quoteAttributeValueForBrowser(value); + }, + + /** + * Sets the value for a property on a node. + * + * @param {DOMElement} node + * @param {string} name + * @param {*} value + */ + setValueForProperty: function (node, name, value) { + var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; + if (propertyInfo) { + var mutationMethod = propertyInfo.mutationMethod; + if (mutationMethod) { + mutationMethod(node, value); + } else if (shouldIgnoreValue(propertyInfo, value)) { + this.deleteValueForProperty(node, name); + return; + } else if (propertyInfo.mustUseProperty) { + // Contrary to `setAttribute`, object properties are properly + // `toString`ed by IE8/9. + node[propertyInfo.propertyName] = value; + } else { + var attributeName = propertyInfo.attributeName; + var namespace = propertyInfo.attributeNamespace; + // `setAttribute` with objects becomes only `[object]` in IE8/9, + // ('' + value) makes it output the correct toString()-value. + if (namespace) { + node.setAttributeNS(namespace, attributeName, '' + value); + } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) { + node.setAttribute(attributeName, ''); + } else { + node.setAttribute(attributeName, '' + value); + } + } + } else if (DOMProperty.isCustomAttribute(name)) { + DOMPropertyOperations.setValueForAttribute(node, name, value); + return; + } + + if (process.env.NODE_ENV !== 'production') { + var payload = {}; + payload[name] = value; + ReactInstrumentation.debugTool.onHostOperation({ + instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID, + type: 'update attribute', + payload: payload + }); + } + }, + + setValueForAttribute: function (node, name, value) { + if (!isAttributeNameSafe(name)) { + return; + } + if (value == null) { + node.removeAttribute(name); + } else { + node.setAttribute(name, '' + value); + } + + if (process.env.NODE_ENV !== 'production') { + var payload = {}; + payload[name] = value; + ReactInstrumentation.debugTool.onHostOperation({ + instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID, + type: 'update attribute', + payload: payload + }); + } + }, + + /** + * Deletes an attributes from a node. + * + * @param {DOMElement} node + * @param {string} name + */ + deleteValueForAttribute: function (node, name) { + node.removeAttribute(name); + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation({ + instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID, + type: 'remove attribute', + payload: name + }); + } + }, + + /** + * Deletes the value for a property on a node. + * + * @param {DOMElement} node + * @param {string} name + */ + deleteValueForProperty: function (node, name) { + var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; + if (propertyInfo) { + var mutationMethod = propertyInfo.mutationMethod; + if (mutationMethod) { + mutationMethod(node, undefined); + } else if (propertyInfo.mustUseProperty) { + var propName = propertyInfo.propertyName; + if (propertyInfo.hasBooleanValue) { + node[propName] = false; + } else { + node[propName] = ''; + } + } else { + node.removeAttribute(propertyInfo.attributeName); + } + } else if (DOMProperty.isCustomAttribute(name)) { + node.removeAttribute(name); + } + + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation({ + instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID, + type: 'remove attribute', + payload: name + }); + } + } + +}; + +module.exports = DOMPropertyOperations;
\ No newline at end of file |