You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.6 KiB
136 lines
4.6 KiB
/** |
|
* Copyright 2013-2015, 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 ReactDOMTextarea |
|
*/ |
|
|
|
'use strict'; |
|
|
|
var AutoFocusMixin = require("./AutoFocusMixin"); |
|
var DOMPropertyOperations = require("./DOMPropertyOperations"); |
|
var LinkedValueUtils = require("./LinkedValueUtils"); |
|
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin"); |
|
var ReactClass = require("./ReactClass"); |
|
var ReactElement = require("./ReactElement"); |
|
var ReactUpdates = require("./ReactUpdates"); |
|
|
|
var assign = require("./Object.assign"); |
|
var invariant = require("./invariant"); |
|
|
|
var warning = require("./warning"); |
|
|
|
var textarea = ReactElement.createFactory('textarea'); |
|
|
|
function forceUpdateIfMounted() { |
|
/*jshint validthis:true */ |
|
if (this.isMounted()) { |
|
this.forceUpdate(); |
|
} |
|
} |
|
|
|
/** |
|
* Implements a <textarea> native component that allows setting `value`, and |
|
* `defaultValue`. This differs from the traditional DOM API because value is |
|
* usually set as PCDATA children. |
|
* |
|
* If `value` is not supplied (or null/undefined), user actions that affect the |
|
* value will trigger updates to the element. |
|
* |
|
* If `value` is supplied (and not null/undefined), the rendered element will |
|
* not trigger updates to the element. Instead, the `value` prop must change in |
|
* order for the rendered element to be updated. |
|
* |
|
* The rendered element will be initialized with an empty value, the prop |
|
* `defaultValue` if specified, or the children content (deprecated). |
|
*/ |
|
var ReactDOMTextarea = ReactClass.createClass({ |
|
displayName: 'ReactDOMTextarea', |
|
tagName: 'TEXTAREA', |
|
|
|
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], |
|
|
|
getInitialState: function() { |
|
var defaultValue = this.props.defaultValue; |
|
// TODO (yungsters): Remove support for children content in <textarea>. |
|
var children = this.props.children; |
|
if (children != null) { |
|
if ("production" !== process.env.NODE_ENV) { |
|
("production" !== process.env.NODE_ENV ? warning( |
|
false, |
|
'Use the `defaultValue` or `value` props instead of setting ' + |
|
'children on <textarea>.' |
|
) : null); |
|
} |
|
("production" !== process.env.NODE_ENV ? invariant( |
|
defaultValue == null, |
|
'If you supply `defaultValue` on a <textarea>, do not pass children.' |
|
) : invariant(defaultValue == null)); |
|
if (Array.isArray(children)) { |
|
("production" !== process.env.NODE_ENV ? invariant( |
|
children.length <= 1, |
|
'<textarea> can only have at most one child.' |
|
) : invariant(children.length <= 1)); |
|
children = children[0]; |
|
} |
|
|
|
defaultValue = '' + children; |
|
} |
|
if (defaultValue == null) { |
|
defaultValue = ''; |
|
} |
|
var value = LinkedValueUtils.getValue(this); |
|
return { |
|
// We save the initial value so that `ReactDOMComponent` doesn't update |
|
// `textContent` (unnecessary since we update value). |
|
// The initial value can be a boolean or object so that's why it's |
|
// forced to be a string. |
|
initialValue: '' + (value != null ? value : defaultValue) |
|
}; |
|
}, |
|
|
|
render: function() { |
|
// Clone `this.props` so we don't mutate the input. |
|
var props = assign({}, this.props); |
|
|
|
("production" !== process.env.NODE_ENV ? invariant( |
|
props.dangerouslySetInnerHTML == null, |
|
'`dangerouslySetInnerHTML` does not make sense on <textarea>.' |
|
) : invariant(props.dangerouslySetInnerHTML == null)); |
|
|
|
props.defaultValue = null; |
|
props.value = null; |
|
props.onChange = this._handleChange; |
|
|
|
// Always set children to the same thing. In IE9, the selection range will |
|
// get reset if `textContent` is mutated. |
|
return textarea(props, this.state.initialValue); |
|
}, |
|
|
|
componentDidUpdate: function(prevProps, prevState, prevContext) { |
|
var value = LinkedValueUtils.getValue(this); |
|
if (value != null) { |
|
var rootNode = this.getDOMNode(); |
|
// Cast `value` to a string to ensure the value is set correctly. While |
|
// browsers typically do this as necessary, jsdom doesn't. |
|
DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value); |
|
} |
|
}, |
|
|
|
_handleChange: function(event) { |
|
var returnValue; |
|
var onChange = LinkedValueUtils.getOnChange(this); |
|
if (onChange) { |
|
returnValue = onChange.call(this, event); |
|
} |
|
ReactUpdates.asap(forceUpdateIfMounted, this); |
|
return returnValue; |
|
} |
|
|
|
}); |
|
|
|
module.exports = ReactDOMTextarea;
|
|
|