Rift.IO OSM R1 Initial Submission
[osm/UI.git] / skyquake / framework / widgets / text-area / rw.text-area.js
1
2 /*
3 *
4 * Copyright 2016 RIFT.IO Inc
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 var React = require('react');
21 var ButtonEventListenerMixin = require('../mixins/ButtonEventListener.js');
22
23
24 /**
25 * A text input component.
26 * It's props values and a brief description below
27 *
28 * value: Holds the initial text content of the input.
29 * label: The text content of the label.
30 * requiredText: The text content of the "if required" message.
31 * errorText: The text content of the error message.
32 * placeholder: The initial placeholder text of the input
33 * ClassName: Css Classes applied to the element.
34 * rows: Number of text lines the input element displays at one time.
35 * cols: Number of characters per line.
36 * resizable: If the input element is resizable.
37 * isRequired: A boolean indicating whether or not the input is required.
38 * isDisabled: A boolean indicating the disabled state of the element.
39 * isReadONly: A boolean indicating whether or not the input is read only.
40 * maxLength: The hard limit on how many characters can be in the input.
41 **/
42 module.exports = React.createClass({
43 displayName: "TextArea",
44 mixins:[ButtonEventListenerMixin],
45 propTypes: {
46 value: React.PropTypes.string,
47 label: React.PropTypes.string,
48 requiredText: React.PropTypes.string,
49 errorText: React.PropTypes.string,
50 placeholder: React.PropTypes.string,
51 className: React.PropTypes.string,
52 rows: React.PropTypes.number,
53 cols: React.PropTypes.number,
54 resizable: React.PropTypes.bool,
55 isRequired: React.PropTypes.bool,
56 isDisabled: React.PropTypes.bool,
57 isReadOnly: React.PropTypes.bool,
58 maxLength: React.PropTypes.number,
59 instructions: React.PropTypes.string
60 },
61
62
63 /**
64 * Sets the default input state.
65 * If there is no description for the variable, assume it's the same as it's props counterpart.
66 *
67 * value: Holds the current text contents of the input element.
68 * isActive: Boolean to indicate if input is active.
69 * isHovered: Boolean to indicate if the input is being hovered over.
70 * isFocused: Boolean to indicate if the input has been focused.
71 * isDisabled: Boolean to indicate if input has been disabled.
72 *
73 * @returns {{sizeOfButton: (*|string), isActive: boolean, isHovered: boolean, isFocused: boolean, isDisabled: (*|boolean),
74 * isReadOnly: (*|.textInput.isReadOnly|.exports.propTypes.isReadOnly|.exports.getInitialState.isReadOnly|boolean),
75 * isRequired: (*|.textInput.isRequired|.exports.propTypes.isRequired|.exports.getInitialState.isRequired|isRequired|null),
76 * isValid: null, isSuccess: null}}
77 */
78 getInitialState: function() {
79 return {
80 value: this.props.value || "",
81 label: this.props.label || "",
82 requiredText: this.props.requiredText || "Required",
83 errorText: this.props.errorText || "",
84 instructionsText: this.props.instructions || "",
85 isActive: false,
86 isHovered: false,
87 isFocused: false,
88 isDisabled: this.props.isDisabled || false,
89 isReadOnly: this.props.isReadOnly || false,
90 isRequired: this.props.isRequired || null,
91 isValid: null, // Three way bool. Valid: true. Invalid: false. Not acted on: null.
92 isSuccess: null // Three way bool. Success: true. Error: false. Not acted on: null.
93
94 }
95 },
96
97 /**
98 * If any of the state variables have changed, the component should update.
99 * "nextProps" and "nextState" hold the state and property variables as they will be after the update.
100 * "this.props" and "this.state" hold the state and property variables as they were before the update.
101 * returns true if the state have changed. Otherwise returns false.
102 * @param nextProps
103 * @param nextState
104 * @returns {boolean}
105 */
106 shouldComponentUpdate: function(nextProps, nextState) {
107 var currentStateString = this.state.isReadOnly + this.state.isDisabled + this.state.isActive + this.state.isFocused +
108 this.state.isHovered + this.state.isValid + this.state.isSuccess + this.state.value;
109 var nextStateString = nextState.isReadOnly + nextState.isDisabled + nextState.isActive + nextState.isFocused +
110 nextState.isHovered + nextState.isValid + nextState.isSuccess + nextState.value;
111 if (currentStateString == nextStateString) {
112 return false;
113 }
114 return true;
115 },
116 /**
117 * Makes sure that when the user types new input, the contents of the input changes accordingly.
118 *
119 * @param event
120 */
121 handleChange: function(event) {
122 this.setState({value:event.target.value});
123 },
124
125 /**
126 * Returns a string reflecting the current state of the input.
127 * If the component state "isDisabled" is true, returns a string "disabled".
128 * If the component state "isReadOnly" is true, returns a string "readonly".
129 * Otherwise returns a string containing a word for each state that has been set to true.
130 * (ie "active focused" if the states active and focused are true, but hovered is false).
131 * @returns {string}
132 */
133 setComponentState: function() {
134 var ret = "";
135 if (this.state.isDisabled) {
136 return "disabled";
137 }
138 if (this.state.isReadOnly) {
139 return "readonly";
140 }
141 if (this.state.isActive) {
142 ret += "active ";
143 }
144 if (this.state.isHovered) {
145 ret += "hovered ";
146 }
147 if (this.state.isFocused) {
148 ret += "focused ";
149 }
150 return ret;
151 },
152
153 /**
154 * Renders the Text Input component.
155 *
156 **/
157 render: function() {
158 var value = this.state.value;
159 var input = null;
160 var textarea_style = {};
161 var textarea_state = this.setComponentState();
162
163 // creates a style for the "resizable" attribute.
164 if (!this.props.resizable) {
165 textarea_style.resize = "none";
166 }
167
168 // The input element.
169 input = React.createElement("textarea", {
170 ref: "inputRef",
171 "data-state": textarea_state,
172 value: value,
173 "style": textarea_style,
174 placeholder: this.props.placeholder,
175 rows: this.props.rows,
176 cols: this.props.cols,
177 maxLength: this.props.maxLength,
178 required: this.state.isRequired,
179 disabled: this.state.isDisabled,
180 readOnly: this.state.isReadOnly,
181 onChange: this.handleChange,
182 onClick: this.onClick,
183 onMouseUp: this.onMouseUp,
184 onMouseDown: this.onMouseDown,
185 onMouseOver: this.onMouseOver,
186 onMouseEnter: this.onMouseEnter,
187 onMouseLeave: this.onMouseLeave,
188 onMouseOut: this.onMouseOut,
189 onTouchCancel: this.onTouchCancel,
190 onTouchEnd: this.onTouchEnd,
191 onTouchMove: this.onTouchMove,
192 onTouchStart: this.onTouchStart,
193 onKeyDown: this.onKeyDown,
194 onKeyPress: this.onKeyPress,
195 onKeyUp: this.onKeyUp,
196 onFocus: this.onFocus,
197 onBlur: this.onBlur,
198 className: (this.props.className || "rw-textarea"),
199 tabIndex: 0
200 },
201 null
202 );
203
204 // The "if required" element. It displays a label if the element is required.
205 if(this.props.isRequired == true){
206 var requiredEle = React.createElement("small", {className: "rw-form-requiredLabel"}, this.state.requiredText);
207 }
208
209 // The label element associated with the input.
210 var label = React.createElement("label", null, this.state.label, requiredEle, input);
211
212 // The "error" element. It pops up as a message if there is an error with the input.
213 if(this.state.errorText != "") {
214 var error = React.createElement("p", {className: "rw-form-errorMsg"}, this.state.errorText);
215 }
216
217 //
218 if(this.state.instructionsText != ""){
219 var instructions = React.createElement("p", {className: "rw-form-instructions"}, this.state.instructionsText)
220 }
221
222 // The parent element for all.
223 var ret = React.createElement("div", {
224 "data-state": textarea_state,
225 required: this.state.isRequired,
226 disabled: this.state.isDisabled,
227 readOnly: this.state.isReadOnly
228 }, label, error, instructions);
229
230 return ret;
231 }
232 });