Skip to content

Instantly share code, notes, and snippets.

@zaaack
Created August 16, 2016 01:45
Show Gist options
  • Save zaaack/ba51beb4999b77e8b50767132e5d36e6 to your computer and use it in GitHub Desktop.
Save zaaack/ba51beb4999b77e8b50767132e5d36e6 to your computer and use it in GitHub Desktop.
var _CommentInput = React.createClass({
propTypes: {
atUser: PropTypes.string,
placeholder: PropTypes.string,
focus: false,
onEnter: PropTypes.func,
onChange: PropTypes.func
},
getDefaultProps: function () {
return {
placeholder: '添加回应',
}
},
componentDidUpdate: function(prevProps, prevState) {
if (this.props.focus) {
var input = this.refs.input.getDOMNode()
input.focus()
}
},
strip_tags: function (html) {
if(!html) return ''
return html.replace(/<[^>]*?>/g, '')
},
onChange: function (e) {
e.target.value = this.strip_tags(e.target.innerHTML)
if(this.props.onChange){
console.log('change', e);
this.props.onChange.call(this, [].slice.call(arguments))
}
},
onKeyUp: function (e) {
e.target.value = this.strip_tags(e.target.innerHTML)
if (e.keyCode === 13 && this.props.onEnter) { // enter
this.props.onEnter.call(this, [].slice.call(arguments))
}
},
setSelection: function (startContainer, startOffset, endContainer, endOffset) {
endContainer = endContainer || startContainer
endOffset = endOffset || startOffset
var range = document.createRange()
range.setStart(startContainer, startOffset)
range.setEnd(endContainer, endOffset)
},
checkIllegalRange: function (container, offset, maxTextOffset) {
maxTextOffset = maxTextOffset || 0
function hasCls(rangeContainer, clsName) {
return rangeContainer.parentElement.classList.contains(clsName)
}
if (hasCls(container, 'at')) {
return true
}
if (hasCls(container, 'text')) {
if (container.previousSibling) {
return false
} else {
return offset <= maxTextOffset
}
}
},
onKeyDown: function (e) {
var inputSpan = this.refs.inputSpan.getDOMNode()
var sel = window.getSelection()
var range = sel.getRangeAt(0)
var rangeHasChanged = false
// 开始位置在at节点或者输入节点与at节点的临界点
if (this.checkIllegalRange(range.startContainer, range.startOffset)) {
range.setStart(inputSpan.childNodes[0], 1)
rangeHasChanged = true
e.preventDefault()
}
// 结束位置在at节点或者输入节点与at节点的临界点
if (this.checkIllegalRange(range.endContainer, range.endOffset)) {
range.setEnd(inputSpan.childNodes[0], 1)
rangeHasChanged = true
e.preventDefault()
}
// 在at节点或者输入节点的空格后面时禁止删除
if (e.keyCode === 8) { // delete
if (this.checkIllegalRange(range.endContainer, range.endOffset, 1)) {
range.setStart(inputSpan.childNodes[0], 1)
range.setEnd(inputSpan.childNodes[0], 1)
rangeHasChanged = true
e.preventDefault()
}
}
// 更新光标
if (rangeHasChanged){
sel.removeAllRanges()
sel.addRange(range)
}
},
render: function() {
var placeholder = this.props.placeholder
var value = this.props.value
return (
<form className="comment-input" name="comment-form">
<div
type="search"
className="ci-input" ref="input" contentEditable
placeholder={ placeholder } onKeyUp={ this.onKeyUp }
onKeyDown={ this.onKeyDown } onChange={ this.onChange }>
<span className="at" onTouchEnd={ stopEvent }>
{this.props.atUser? '@'+this.props.atUser: ''}
</span>
<span className="text" ref="inputSpan" dangerouslySetInnerHTML={{__html: '&nbsp;'}} />
</div>
</form>
)
}
})
_CommentInput = makeSingleContainer(_CommentInput)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment