Reputation: 4510
using React I am trying to build a component for highlighting text.
In order to do this, I have a textarea element and a div on the same level, copying the value of the textarea into the div. My code is below.
The textarea is inside the TextArea component, and the div is inside the HighlightedDiv component.
I just found out that newlines and spaces are not handled by the div in the same way that they are in the textarea. So when I entered multiple spaces inside the textarea, the div only shows one space. And when I press enter inside the textarea, the text in the div stays on the same line.
Somewhere I found that adding this to the div's css styling fixes that:
white-space: pre;
And it does, but now I also want my text to keep wrapping when it hits the border of the div, like it does when I use the following css:
white-space: normal;
word-wrap: break-word;
The problem is, obviously, that I need both white-space: pre, and white-space: normal. Which is, to be overly clear, not possible.
Does anyone know another way to reach what I want?
My code:
(I am using s styling library, styled components, so the StyledTextArea and Div element below are just a plain textarea and div, respectively.)
HighlightTextArea (parent):
import React, { Component } from 'react'
import styled from 'styled-components'
import HighlightDiv from './HighlightDiv'
import TextArea from './TextArea'
const Container = styled.div`
border: 1px green solid;
width: 100vh;
padding: 20px;
`
export default class HighlightTextArea extends Component {
constructor() {
super()
this.state = {
text: ''
}
}
setHighlightTextAreaState = (newStateObject) => {
for (let key in newStateObject) {
this.setState({ [key]: newStateObject[key] })
}
}
render() {
return (
<Container>
<TextArea setHighlightTextAreaState={this.setHighlightTextAreaState}/>
<HighlightDiv text={this.state.text}/>
</Container>
);
}
}
TextArea (Child):
import React, { Component } from 'react'
import styled from 'styled-components'
const StyledTextArea = styled.textarea`
border: 1px solid blue;
font-family: 'Inconsolata', monospace;
font-size: 1rem;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
position: absolute;
top: 0;
left: 0;
z-index: 20;
color: blue;
opacity: 0.5;
`
export default class TextArea extends Component {
constructor(props) {
super(props)
}
handleChange = (event) => {
console.log("TextArea.handleChange - event.target.value:")
console.log("\"" + event.target.value + "\"")
console.log("TextArea.handleChange - event.target.value.length: " + event.target.value.length)
this.props.setHighlightTextAreaState({
text: event.target.value,
})
}
// componentDidMount() {
// let textAreaRect = document.getElementById("text-area").getBoundingClientRect()
//
// }
render() {
return (
<StyledTextArea id="text-area" onChange={this.handleChange}></StyledTextArea>
);
}
}
HighlightDiv (Child):
import React, { Component } from 'react'
import styled from 'styled-components'
const Div = styled.div`
border: 1px solid red;
font-family: 'Inconsolata', monospace;
font-size: 1rem;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
position: absolute;
top: 0;
left: 0;
z-index: 10;
color: red;
text-align: left;
white-space: normal;
word-wrap: break-word;
`
export default class HighlightDiv extends Component {
constructor(props) {
super(props)
}
renderTextHtml = () => {
// Loop over all characters in this.props.text
// Check if character is space or enter
}
render() {
return (
<Div>
{this.props.text}
</Div>
)
}
}
Upvotes: 0
Views: 1205
Reputation: 87292
You should use white-space: pre-wrap;
Stack snippet - side-by-side div
/textarea
div {
white-space: pre-wrap;
}
/* for the purpose of this demo */
div, textarea {
display: inline-block;
vertical-align: top;
width: 220px;
height: 220px;
font-size: 16px;
font-family: arial;
overflow: hidden;
}
<div>But ere she from the church-door stepped She smiled and told us why:
'It was a wicked woman's curse,' Quoth she, 'and what care I?'
She smiled, and smiled, and passed it off Ere from the door she stept
</div>
<textarea>But ere she from the church-door stepped She smiled and told us why:
'It was a wicked woman's curse,' Quoth she, 'and what care I?'
She smiled, and smiled, and passed it off Ere from the door she stept
</textarea>
Upvotes: 2