[web] editor config for line endings

This commit is contained in:
Jason 2016-06-17 06:26:46 +08:00
parent f5c597a9e3
commit 4ce7a9ba77
3 changed files with 225 additions and 224 deletions

View File

@ -3,3 +3,4 @@ indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf

View File

@ -1,166 +1,166 @@
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import {Key} from '../../utils.js'
export default class EditorBase extends Component {
static propTypes = {
content: PropTypes.string.isRequired,
onDone: PropTypes.func.isRequired,
contentToHtml: PropTypes.func,
nodeToContent: PropTypes.func,
onStop: PropTypes.func,
submitOnEnter: PropTypes.bool,
className: PropTypes.string,
tag: PropTypes.string,
}
static defaultProps = {
contentToHtml: content => _.escape(content),
nodeToContent: node => node.textContent,
submitOnEnter: true,
className: '',
tag: 'div',
onStop: _.noop,
onMouseDown: _.noop,
onBlur: _.noop,
onInput: _.noop,
}
constructor(props) {
super(props)
this.state = {editable: false}
this.onPaste = this.onPaste.bind(this)
this.onMouseDown = this.onMouseDown.bind(this)
this.onMouseUp = this.onMouseUp.bind(this)
this.onFocus = this.onFocus.bind(this)
this.onClick = this.onClick.bind(this)
this.stop = this.stop.bind(this)
this.onBlur = this.onBlur.bind(this)
this.reset = this.reset.bind(this)
this.onKeyDown = this.onKeyDown.bind(this)
this.onInput = this.onInput.bind(this)
}
stop() {
// a stop would cause a blur as a side-effect.
// but a blur event must trigger a stop as well.
// to fix this, make stop = blur and do the actual stop in the onBlur handler.
ReactDOM.findDOMNode(this).blur()
this.props.onStop()
}
render() {
return (
<this.props.tag
{...this.props}
tabIndex="0"
className={`inline-input ${this.props.className}`}
contentEditable={this.state.editable || undefined}
onFocus={this.onFocus}
onMouseDown={this.onMouseDown}
onClick={this.onClick}
onBlur={this.onBlur}
onKeyDown={this.onKeyDown}
onInput={this.onInput}
onPaste={this.onPaste}
dangerouslySetInnerHTML={{ __html: this.props.contentToHtml(this.props.content) }}
/>
)
}
onPaste(e) {
e.preventDefault()
var content = e.clipboardData.getData('text/plain')
document.execCommand('insertHTML', false, content)
}
onMouseDown(e) {
this._mouseDown = true
window.addEventListener('mouseup', this.onMouseUp)
this.props.onMouseDown(e)
}
onMouseUp() {
if (this._mouseDown) {
this._mouseDown = false
window.removeEventListener('mouseup', this.onMouseUp)
}
}
onClick(e) {
this.onMouseUp()
this.onFocus(e)
}
onFocus(e) {
if (this._mouseDown || this._ignore_events || this.state.editable) {
return
}
// contenteditable in FireFox is more or less broken.
// - we need to blur() and then focus(), otherwise the caret is not shown.
// - blur() + focus() == we need to save the caret position before
// Firefox sometimes just doesn't set a caret position => use caretPositionFromPoint
const sel = window.getSelection()
let range
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0)
} else if (document.caretPositionFromPoint && e.clientX && e.clientY) {
const pos = document.caretPositionFromPoint(e.clientX, e.clientY)
range = document.createRange()
range.setStart(pos.offsetNode, pos.offset)
} else if (document.caretRangeFromPoint && e.clientX && e.clientY) {
range = document.caretRangeFromPoint(e.clientX, e.clientY)
} else {
range = document.createRange()
range.selectNodeContents(ReactDOM.findDOMNode(this))
}
this._ignore_events = true
this.setState({ editable: true }, () => {
const node = ReactDOM.findDOMNode(this)
node.blur()
node.focus()
this._ignore_events = false
})
}
onBlur(e) {
if (this._ignore_events) {
return
}
window.getSelection().removeAllRanges() //make sure that selection is cleared on blur
this.setState({ editable: false })
this.props.onDone(this.props.nodeToContent(ReactDOM.findDOMNode(this)))
this.props.onBlur(e)
}
reset() {
ReactDOM.findDOMNode(this).innerHTML = this.props.contentToHtml(this.props.content)
}
onKeyDown(e) {
e.stopPropagation()
switch (e.keyCode) {
case Key.ESC:
e.preventDefault()
this.reset()
this.stop()
break
case Key.ENTER:
if (this.props.submitOnEnter && !e.shiftKey) {
e.preventDefault()
this.stop()
}
break
default:
break
}
}
onInput() {
this.props.onInput(this.props.nodeToContent(ReactDOM.findDOMNode(this)))
}
}
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import {Key} from '../../utils.js'
export default class EditorBase extends Component {
static propTypes = {
content: PropTypes.string.isRequired,
onDone: PropTypes.func.isRequired,
contentToHtml: PropTypes.func,
nodeToContent: PropTypes.func,
onStop: PropTypes.func,
submitOnEnter: PropTypes.bool,
className: PropTypes.string,
tag: PropTypes.string,
}
static defaultProps = {
contentToHtml: content => _.escape(content),
nodeToContent: node => node.textContent,
submitOnEnter: true,
className: '',
tag: 'div',
onStop: _.noop,
onMouseDown: _.noop,
onBlur: _.noop,
onInput: _.noop,
}
constructor(props) {
super(props)
this.state = {editable: false}
this.onPaste = this.onPaste.bind(this)
this.onMouseDown = this.onMouseDown.bind(this)
this.onMouseUp = this.onMouseUp.bind(this)
this.onFocus = this.onFocus.bind(this)
this.onClick = this.onClick.bind(this)
this.stop = this.stop.bind(this)
this.onBlur = this.onBlur.bind(this)
this.reset = this.reset.bind(this)
this.onKeyDown = this.onKeyDown.bind(this)
this.onInput = this.onInput.bind(this)
}
stop() {
// a stop would cause a blur as a side-effect.
// but a blur event must trigger a stop as well.
// to fix this, make stop = blur and do the actual stop in the onBlur handler.
ReactDOM.findDOMNode(this).blur()
this.props.onStop()
}
render() {
return (
<this.props.tag
{...this.props}
tabIndex="0"
className={`inline-input ${this.props.className}`}
contentEditable={this.state.editable || undefined}
onFocus={this.onFocus}
onMouseDown={this.onMouseDown}
onClick={this.onClick}
onBlur={this.onBlur}
onKeyDown={this.onKeyDown}
onInput={this.onInput}
onPaste={this.onPaste}
dangerouslySetInnerHTML={{ __html: this.props.contentToHtml(this.props.content) }}
/>
)
}
onPaste(e) {
e.preventDefault()
var content = e.clipboardData.getData('text/plain')
document.execCommand('insertHTML', false, content)
}
onMouseDown(e) {
this._mouseDown = true
window.addEventListener('mouseup', this.onMouseUp)
this.props.onMouseDown(e)
}
onMouseUp() {
if (this._mouseDown) {
this._mouseDown = false
window.removeEventListener('mouseup', this.onMouseUp)
}
}
onClick(e) {
this.onMouseUp()
this.onFocus(e)
}
onFocus(e) {
if (this._mouseDown || this._ignore_events || this.state.editable) {
return
}
// contenteditable in FireFox is more or less broken.
// - we need to blur() and then focus(), otherwise the caret is not shown.
// - blur() + focus() == we need to save the caret position before
// Firefox sometimes just doesn't set a caret position => use caretPositionFromPoint
const sel = window.getSelection()
let range
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0)
} else if (document.caretPositionFromPoint && e.clientX && e.clientY) {
const pos = document.caretPositionFromPoint(e.clientX, e.clientY)
range = document.createRange()
range.setStart(pos.offsetNode, pos.offset)
} else if (document.caretRangeFromPoint && e.clientX && e.clientY) {
range = document.caretRangeFromPoint(e.clientX, e.clientY)
} else {
range = document.createRange()
range.selectNodeContents(ReactDOM.findDOMNode(this))
}
this._ignore_events = true
this.setState({ editable: true }, () => {
const node = ReactDOM.findDOMNode(this)
node.blur()
node.focus()
this._ignore_events = false
})
}
onBlur(e) {
if (this._ignore_events) {
return
}
window.getSelection().removeAllRanges() //make sure that selection is cleared on blur
this.setState({ editable: false })
this.props.onDone(this.props.nodeToContent(ReactDOM.findDOMNode(this)))
this.props.onBlur(e)
}
reset() {
ReactDOM.findDOMNode(this).innerHTML = this.props.contentToHtml(this.props.content)
}
onKeyDown(e) {
e.stopPropagation()
switch (e.keyCode) {
case Key.ESC:
e.preventDefault()
this.reset()
this.stop()
break
case Key.ENTER:
if (this.props.submitOnEnter && !e.shiftKey) {
e.preventDefault()
this.stop()
}
break
default:
break
}
}
onInput() {
this.props.onInput(this.props.nodeToContent(ReactDOM.findDOMNode(this)))
}
}

View File

@ -1,58 +1,58 @@
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import EditorBase from './EditorBase'
export default class ValidateEditor extends Component {
static propTypes = {
content: PropTypes.string.isRequired,
onDone: PropTypes.func.isRequired,
onInput: PropTypes.func,
isValid: PropTypes.func,
className: PropTypes.string,
}
constructor(props) {
super(props)
this.state = { currentContent: props.content }
this.onInput = this.onInput.bind(this)
this.onDone = this.onDone.bind(this)
}
componentWillReceiveProps(nextProps) {
this.setState({ currentContent: nextProps.content })
}
onInput(currentContent) {
this.setState({ currentContent })
this.props.onInput && this.props.onInput(currentContent)
}
onDone(content) {
if (this.props.isValid && !this.props.isValid(content)) {
this.refs.editor.reset()
content = this.props.content
}
this.props.onDone(content)
}
render() {
let className = this.props.className || ''
if (this.props.isValid) {
if (this.props.isValid(this.state.currentContent)) {
className += ' has-success'
} else {
className += ' has-warning'
}
}
return (
<EditorBase
{...this.props}
ref="editor"
className={className}
onDone={this.onDone}
onInput={this.onInput}
/>
)
}
}
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import EditorBase from './EditorBase'
export default class ValidateEditor extends Component {
static propTypes = {
content: PropTypes.string.isRequired,
onDone: PropTypes.func.isRequired,
onInput: PropTypes.func,
isValid: PropTypes.func,
className: PropTypes.string,
}
constructor(props) {
super(props)
this.state = { currentContent: props.content }
this.onInput = this.onInput.bind(this)
this.onDone = this.onDone.bind(this)
}
componentWillReceiveProps(nextProps) {
this.setState({ currentContent: nextProps.content })
}
onInput(currentContent) {
this.setState({ currentContent })
this.props.onInput && this.props.onInput(currentContent)
}
onDone(content) {
if (this.props.isValid && !this.props.isValid(content)) {
this.refs.editor.reset()
content = this.props.content
}
this.props.onDone(content)
}
render() {
let className = this.props.className || ''
if (this.props.isValid) {
if (this.props.isValid(this.state.currentContent)) {
className += ' has-success'
} else {
className += ' has-warning'
}
}
return (
<EditorBase
{...this.props}
ref="editor"
className={className}
onDone={this.onDone}
onInput={this.onInput}
/>
)
}
}