text: /**
   * 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 DOMPropertyOperations
   * @typechecks static-only
   */
  
  "use strict";
  
  var DOMProperty = require("./DOMProperty");
  
  var escapeTextForBrowser = require("./escapeTextForBrowser");
  var memoizeStringOnly = require("./memoizeStringOnly");
  var warning = require("./warning");
  
  function shouldIgnoreValue(name, value) {
    return value == null ||
      (DOMProperty.hasBooleanValue[name] && !value) ||
      (DOMProperty.hasNumericValue[name] && isNaN(value)) ||
      (DOMProperty.hasPositiveNumericValue[name] && (value < 1)) ||
      (DOMProperty.hasOverloadedBooleanValue[name] && value === false);
  }
  
  var processAttributeNameAndPrefix = memoizeStringOnly(function(name) {
    return escapeTextForBrowser(name) + '="';
  });
  
  if ("production" !== process.env.NODE_ENV) {
    var reactProps = {
      children: true,
      dangerouslySetInnerHTML: true,
      key: true,
      ref: true
    };
    var warnedProperties = {};
  
    var warnUnknownProperty = function(name) {
      if (reactProps.hasOwnProperty(name) && reactProps[name] ||
          warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
        return;
      }
  
      warnedProperties[name] = true;
      var lowerCasedName = name.toLowerCase();
  
      // data-* attributes should be lowercase; suggest the lowercase version
      var standardName = (
        DOMProperty.isCustomAttribute(lowerCasedName) ?
          lowerCasedName :
        DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ?
          DOMProperty.getPossibleStandardName[lowerCasedName] :
          null
      );
  
      // For now, only warn when we have a suggested correction. This prevents
      // logging too much when using transferPropsTo.
      ("production" !== process.env.NODE_ENV ? warning(
        standardName == null,
        'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?'
      ) : null);
  
    };
  }
  
  /**
   * 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 processAttributeNameAndPrefix(DOMProperty.ID_ATTRIBUTE_NAME) +
        escapeTextForBrowser(id) + '"';
    },
  
    /**
     * 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) {
      if (DOMProperty.isStandardName.hasOwnProperty(name) &&
          DOMProperty.isStandardName[name]) {
        if (shouldIgnoreValue(name, value)) {
          return '';
        }
        var attributeName = DOMProperty.getAttributeName[name];
        if (DOMProperty.hasBooleanValue[name] ||
            (DOMProperty.hasOverloadedBooleanValue[name] && value === true)) {
          return escapeTextForBrowser(attributeName);
        }
        return processAttributeNameAndPrefix(attributeName) +
          escapeTextForBrowser(value) + '"';
      } else if (DOMProperty.isCustomAttribute(name)) {
        if (value == null) {
          return '';
        }
        return processAttributeNameAndPrefix(name) +
          escapeTextForBrowser(value) + '"';
      } else if ("production" !== process.env.NODE_ENV) {
        warnUnknownProperty(name);
      }
      return null;
    },
  
    /**
     * Sets the value for a property on a node.
     *
     * @param {DOMElement} node
     * @param {string} name
     * @param {*} value
     */
    setValueForProperty: function(node, name, value) {
      if (DOMProperty.isStandardName.hasOwnProperty(name) &&
          DOMProperty.isStandardName[name]) {
        var mutationMethod = DOMProperty.getMutationMethod[name];
        if (mutationMethod) {
          mutationMethod(node, value);
        } else if (shouldIgnoreValue(name, value)) {
          this.deleteValueForProperty(node, name);
        } else if (DOMProperty.mustUseAttribute[name]) {
          node.setAttribute(DOMProperty.getAttributeName[name], '' + value);
        } else {
          var propName = DOMProperty.getPropertyName[name];
          if (!DOMProperty.hasSideEffects[name] || node[propName] !== value) {
            node[propName] = value;
          }
        }
      } else if (DOMProperty.isCustomAttribute(name)) {
        if (value == null) {
          node.removeAttribute(name);
        } else {
          node.setAttribute(name, '' + value);
        }
      } else if ("production" !== process.env.NODE_ENV) {
        warnUnknownProperty(name);
      }
    },
  
    /**
     * Deletes the value for a property on a node.
     *
     * @param {DOMElement} node
     * @param {string} name
     */
    deleteValueForProperty: function(node, name) {
      if (DOMProperty.isStandardName.hasOwnProperty(name) &&
          DOMProperty.isStandardName[name]) {
        var mutationMethod = DOMProperty.getMutationMethod[name];
        if (mutationMethod) {
          mutationMethod(node, undefined);
        } else if (DOMProperty.mustUseAttribute[name]) {
          node.removeAttribute(DOMProperty.getAttributeName[name]);
        } else {
          var propName = DOMProperty.getPropertyName[name];
          var defaultValue = DOMProperty.getDefaultValueForProperty(
            node.nodeName,
            propName
          );
          if (!DOMProperty.hasSideEffects[name] ||
              node[propName] !== defaultValue) {
            node[propName] = defaultValue;
          }
        }
      } else if (DOMProperty.isCustomAttribute(name)) {
        node.removeAttribute(name);
      } else if ("production" !== process.env.NODE_ENV) {
        warnUnknownProperty(name);
      }
    }
  
  };
  
  module.exports = DOMPropertyOperations;
  