UNPKG

react-addons

Version:

Simple packaging of react addons to avoid fiddly 'react/addons' npm module.

219 lines (198 loc) 7.29 kB
/** * Copyright 2013-2014 Facebook, Inc. * * 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. * * @providesModule ReactDOMIDOperations * @typechecks static-only */ /*jslint evil: true */ "use strict"; var CSSPropertyOperations = require("./CSSPropertyOperations"); var DOMChildrenOperations = require("./DOMChildrenOperations"); var DOMPropertyOperations = require("./DOMPropertyOperations"); var ReactMount = require("./ReactMount"); var ReactPerf = require("./ReactPerf"); var invariant = require("./invariant"); /** * Errors for properties that should not be updated with `updatePropertyById()`. * * @type {object} * @private */ var INVALID_PROPERTY_ERRORS = { dangerouslySetInnerHTML: '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.', style: '`style` must be set using `updateStylesByID()`.' }; var useWhitespaceWorkaround; /** * Operations used to process updates to DOM nodes. This is made injectable via * `ReactComponent.BackendIDOperations`. */ var ReactDOMIDOperations = { /** * Updates a DOM node with new property values. This should only be used to * update DOM properties in `DOMProperty`. * * @param {string} id ID of the node to update. * @param {string} name A valid property name, see `DOMProperty`. * @param {*} value New value of the property. * @internal */ updatePropertyByID: ReactPerf.measure( 'ReactDOMIDOperations', 'updatePropertyByID', function(id, name, value) { var node = ReactMount.getNode(id); ("production" !== process.env.NODE_ENV ? invariant( !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name] ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); // If we're updating to null or undefined, we should remove the property // from the DOM node instead of inadvertantly setting to a string. This // brings us in line with the same behavior we have on initial render. if (value != null) { DOMPropertyOperations.setValueForProperty(node, name, value); } else { DOMPropertyOperations.deleteValueForProperty(node, name); } } ), /** * Updates a DOM node to remove a property. This should only be used to remove * DOM properties in `DOMProperty`. * * @param {string} id ID of the node to update. * @param {string} name A property name to remove, see `DOMProperty`. * @internal */ deletePropertyByID: ReactPerf.measure( 'ReactDOMIDOperations', 'deletePropertyByID', function(id, name, value) { var node = ReactMount.getNode(id); ("production" !== process.env.NODE_ENV ? invariant( !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name] ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); DOMPropertyOperations.deleteValueForProperty(node, name, value); } ), /** * Updates a DOM node with new style values. If a value is specified as '', * the corresponding style property will be unset. * * @param {string} id ID of the node to update. * @param {object} styles Mapping from styles to values. * @internal */ updateStylesByID: ReactPerf.measure( 'ReactDOMIDOperations', 'updateStylesByID', function(id, styles) { var node = ReactMount.getNode(id); CSSPropertyOperations.setValueForStyles(node, styles); } ), /** * Updates a DOM node's innerHTML. * * @param {string} id ID of the node to update. * @param {string} html An HTML string. * @internal */ updateInnerHTMLByID: ReactPerf.measure( 'ReactDOMIDOperations', 'updateInnerHTMLByID', function(id, html) { var node = ReactMount.getNode(id); // IE8: When updating a just created node with innerHTML only leading // whitespace is removed. When updating an existing node with innerHTML // whitespace in root TextNodes is also collapsed. // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html if (useWhitespaceWorkaround === undefined) { // Feature detection; only IE8 is known to behave improperly like this. var temp = document.createElement('div'); temp.innerHTML = ' '; useWhitespaceWorkaround = temp.innerHTML === ''; } if (useWhitespaceWorkaround) { // Magic theory: IE8 supposedly differentiates between added and updated // nodes when processing innerHTML, innerHTML on updated nodes suffers // from worse whitespace behavior. Re-adding a node like this triggers // the initial and more favorable whitespace behavior. node.parentNode.replaceChild(node, node); } if (useWhitespaceWorkaround && html.match(/^[ \r\n\t\f]/)) { // Recover leading whitespace by temporarily prepending any character. // \uFEFF has the potential advantage of being zero-width/invisible. node.innerHTML = '\uFEFF' + html; node.firstChild.deleteData(0, 1); } else { node.innerHTML = html; } } ), /** * Updates a DOM node's text content set by `props.content`. * * @param {string} id ID of the node to update. * @param {string} content Text content. * @internal */ updateTextContentByID: ReactPerf.measure( 'ReactDOMIDOperations', 'updateTextContentByID', function(id, content) { var node = ReactMount.getNode(id); DOMChildrenOperations.updateTextContent(node, content); } ), /** * Replaces a DOM node that exists in the document with markup. * * @param {string} id ID of child to be replaced. * @param {string} markup Dangerous markup to inject in place of child. * @internal * @see {Danger.dangerouslyReplaceNodeWithMarkup} */ dangerouslyReplaceNodeWithMarkupByID: ReactPerf.measure( 'ReactDOMIDOperations', 'dangerouslyReplaceNodeWithMarkupByID', function(id, markup) { var node = ReactMount.getNode(id); DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup); } ), /** * Updates a component's children by processing a series of updates. * * @param {array<object>} updates List of update configurations. * @param {array<string>} markup List of markup strings. * @internal */ dangerouslyProcessChildrenUpdates: ReactPerf.measure( 'ReactDOMIDOperations', 'dangerouslyProcessChildrenUpdates', function(updates, markup) { for (var i = 0; i < updates.length; i++) { updates[i].parentNode = ReactMount.getNode(updates[i].parentID); } DOMChildrenOperations.processUpdates(updates, markup); } ) }; module.exports = ReactDOMIDOperations;