ldx-widgets
Version:
widgets
216 lines (175 loc) • 5.26 kB
text/coffeescript
React = require 'react'
PropTypes = require 'prop-types'
createClass = require 'create-react-class'
ReactDOM = require 'react-dom'
Spinner = React.createFactory(require('./spinner'))
FormValidation = require '../mixins/form_validation'
_ = require 'lodash'
{div, ul, button, input} = React.DOM
###
Input Props
@props.loading - OPTIONAL - Boolean
indicator to determine that the input is loading a value from the server
@props.showClear - OPTIONAL - Boolean
indicator to determine whether or not to show the clear "X" button
@props.delayedActionOnChange - OPTIONAL - Object
Takes action and interval parameters, will fire the action after the set interval everytime the componentWillReceiveProps method fires
@props.wrapperClass - OPTIONAL - String
class to be added to the wrpper div
@props.regexAllow - OPTIONAL - Array
runs the value through a regex test to see if it passes
###
TextInput = createClass
displayName: 'TextInput'
# Note - See form_validation for required props when using with this mixin
mixins: [FormValidation]
propTypes:
type: PropTypes.string
className: PropTypes.string
regexAllow: PropTypes.object
delayedActionOnChange: PropTypes.object
tabIndex: PropTypes.number
maxLength: PropTypes.number
disabled: PropTypes.bool
onChange: PropTypes.func
onInput: PropTypes.func
onKeyDown: PropTypes.func
onKeyUp: PropTypes.func
onKeyPress: PropTypes.func
style: PropTypes.object
autoComplete: PropTypes.oneOfType [
PropTypes.string
PropTypes.bool
]
placeholder: PropTypes.oneOfType [
PropTypes.string
PropTypes.number
]
value: PropTypes.oneOfType [
PropTypes.string
PropTypes.number
]
id: PropTypes.oneOfType [
PropTypes.string
PropTypes.number
]
getInitialState: ->
{
value: @props.value or ''
}
getDefaultProps: ->
{
type: 'text'
loading: false
className: 'text-input'
wrapperClass: null
showClear: false
autoComplete: false
}
componentWillReceiveProps: (nextProps) ->
{value} = nextProps
if value? and value isnt @props.value
@fireDelayedAction()
@setState({ value: value })
delayedActionTimer: null
fireDelayedAction: ->
{delayedActionOnChange} = @props
if delayedActionOnChange?
{action, interval} = delayedActionOnChange
clearInterval(@delayedActionTimer)
@delayedActionTimer = setTimeout =>
action(@state.value)
, interval
render: ->
{placeholder, tabIndex, className, maxLength, loading, type, showClear, onKeyDown, onKeyPress, wrapperClass, wrapperLabel, id, disabled, autoComplete, onBlur, style, onInput} = @props
{value} = @state
# Separate the false evaluations from the validation hash
@getErrors()
inputClass = className if className?
inputClass += ' loading-spinner' if loading
outerClass = 'field-wrap'
outerClass += " #{wrapperClass}" if wrapperClass
# Autocomplete
autoComplete = switch typeof autoComplete
when 'string' then autoComplete
when 'boolean'
if autoComplete then 'on' else 'off'
div {
className: "#{outerClass} #{@invalidClass}"
style: style
}, [
input {
id: id
className: inputClass
ref: 'textInput'
type: type
placeholder: placeholder
key: 'textInput'
tabIndex: tabIndex
value: value
onChange: @handleChange unless onInput?
onInput: @handleChange if onInput?
onKeyDown: @onKeyDown
onKeyUp: @handleKeyUp
onKeyPress: onKeyPress
onBlur: onBlur
maxLength: maxLength
spellCheck: false
disabled: disabled
autoComplete: autoComplete
}
div({
key: 'input-spinner'
className: 'input-spinner'
},
Spinner {
length: 3
}
) if loading
button {
className: 'search-clear'
title: 'Clear Search'
key: 'searchClearBtn'
onClick: @clear
tabIndex: -1
}, [] if value.length > 0 and showClear
div({
className: 'field-errors-show'
key: 'textInputErrorsShow'
}, [
div {
className: 'field-errors'
key: 'textInputErrors'
},
ul {
className: 'field-errors-list'
}, @validationErrors
]) if @validationErrors.length and not loading
]
handleChange: (e) ->
{value} = e.target
{regexAllow, onChange} = @props
# Check for disallowed chars
if regexAllow? and value and not regexAllow.test(value) then return
@setState {
value: value
}
onChange?(e)
onKeyDown: (e) ->
e.preventDefault() if e.key is 'Enter'
@props.onKeyDown?(e)
handleKeyUp: (e) ->
if e.key is 'Enter'
e.preventDefault()
@props.onEnterKey?(e)
@props.onKeyUp?(e)
getValue: ->
@refs.textInput.value
clear: ->
@props.onChange(true)
@setState({ value: '' })
focus: ->
ReactDOM.findDOMNode(@refs.textInput).focus()
blur: ->
ReactDOM.findDOMNode(@refs.textInput).blur()
module.exports = TextInput