PLT-4404/PLT-4578/PLT-4541/PLT-4542 Replaced third party autosizing textarea with a custom one (#4442)

* PLT-4578 Replaced third party autosizing textarea with a custom one

* Fix Textbox.handleHeightChange not being called

* Removed unused CSS

* PLT-4541 Force EditPostModal to resize upon opening

* Removed usage of jquery from AutosizeTextarea

* Reverted changes made for PLT-4580 as they're no longer needed
Этот коммит содержится в:
Harrison Healey
2016-11-04 12:35:38 -04:00
коммит произвёл Christopher Speller
родитель 7403bbce69
Коммит e63e80dee0
8 изменённых файлов: 138 добавлений и 87 удалений

90
webapp/components/autosize_textarea.jsx Обычный файл
Просмотреть файл

@@ -0,0 +1,90 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
export default class AutosizeTextarea extends React.Component {
static propTypes = {
value: React.PropTypes.string,
placeholder: React.PropTypes.string,
onHeightChange: React.PropTypes.func
}
constructor(props) {
super(props);
this.height = 0;
}
get value() {
return this.refs.textarea.value;
}
set value(value) {
this.refs.textarea.value = value;
}
componentDidUpdate() {
this.recalculateSize();
}
recalculateSize() {
const height = this.refs.reference.scrollHeight;
if (height > 0 && height !== this.height) {
const textarea = this.refs.textarea;
const style = getComputedStyle(textarea);
const borderWidth = parseInt(style.borderTopWidth, 10) + parseInt(style.borderBottomWidth, 10);
// Directly change the height to avoid circular rerenders
textarea.style.height = String(height + borderWidth) + 'px';
this.height = height;
if (this.props.onHeightChange) {
this.props.onHeightChange(height, parseInt(style.maxHeight, 10));
}
}
}
getDOMNode() {
return this.refs.textarea;
}
render() {
window.forceUpdate = this.forceUpdate.bind(this);
const {
value,
placeholder,
...otherProps
} = this.props;
const heightProps = {};
if (this.height <= 0) {
// Set an initial number of rows so that the textarea doesn't appear too large when its first rendered
heightProps.rows = 1;
} else {
heightProps.height = this.height;
}
return (
<div>
<textarea
ref='textarea'
{...heightProps}
{...this.props}
/>
<div style={{height: 0, overflow: 'hidden'}}>
<textarea
ref='reference'
style={{height: 'auto', width: '100%'}}
value={value || placeholder}
rows='1'
{...otherProps}
/>
</div>
</div>
);
}
}

Просмотреть файл

@@ -156,6 +156,8 @@ export default class EditPostModal extends React.Component {
onModalShown() {
this.refs.editbox.focus();
this.refs.editbox.recalculateSize();
}
onModalHide() {

Просмотреть файл

@@ -9,7 +9,7 @@ import * as GlobalActions from 'actions/global_actions.jsx';
import SuggestionStore from 'stores/suggestion_store.jsx';
import * as Utils from 'utils/utils.jsx';
import TextareaAutosize from 'react-autosize-textarea';
import AutosizeTextarea from 'components/autosize_textarea.jsx';
const KeyCodes = Constants.KeyCodes;
@@ -46,14 +46,17 @@ export default class SuggestionBox extends React.Component {
}
getTextbox() {
// this is to support old code that looks at the input/textarea DOM nodes
let textbox = this.refs.textbox;
if (!(textbox instanceof HTMLElement)) {
textbox = ReactDOM.findDOMNode(textbox);
if (this.props.type === 'textarea') {
return this.refs.textbox.getDOMNode();
}
return textbox;
return this.refs.textbox;
}
recalculateSize() {
if (this.props.type === 'textarea') {
this.refs.textbox.recalculateSize();
}
}
handleDocumentClick(e) {
@@ -71,7 +74,7 @@ export default class SuggestionBox extends React.Component {
}
handleChange(e) {
const textbox = ReactDOM.findDOMNode(this.refs.textbox);
const textbox = this.getTextbox();
const caret = Utils.getCaretPosition(textbox);
const pretext = textbox.value.substring(0, caret);
@@ -83,7 +86,7 @@ export default class SuggestionBox extends React.Component {
}
handleCompleteWord(term, matchedPretext) {
const textbox = ReactDOM.findDOMNode(this.refs.textbox);
const textbox = this.getTextbox();
const caret = Utils.getCaretPosition(textbox);
const text = this.props.value;
const pretext = text.substring(0, caret);
@@ -150,48 +153,57 @@ export default class SuggestionBox extends React.Component {
}
render() {
const {
type,
listComponent,
listStyle,
renderDividers,
...props
} = this.props;
let textbox = null;
if (this.props.type === 'input') {
if (type === 'input') {
textbox = (
<input
ref='textbox'
type='text'
{...this.props}
onChange={this.handleChange}
{...props}
onInput={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
);
} else if (this.props.type === 'search') {
} else if (type === 'search') {
textbox = (
<input
ref='textbox'
type='search'
{...this.props}
onChange={this.handleChange}
{...props}
onInput={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
);
} else if (this.props.type === 'textarea') {
} else if (type === 'textarea') {
textbox = (
<TextareaAutosize
<AutosizeTextarea
id={this.suggestionId}
ref='textbox'
{...this.props}
onChange={this.handleChange}
{...props}
onInput={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
);
}
const SuggestionListComponent = this.props.listComponent;
// This needs to be upper case so React doesn't think it's an html tag
const SuggestionListComponent = listComponent;
return (
<div>
{textbox}
<SuggestionListComponent
suggestionId={this.suggestionId}
location={this.props.listStyle}
renderDividers={this.props.renderDividers}
location={listStyle}
renderDividers={renderDividers}
/>
</div>
);

Просмотреть файл

@@ -25,6 +25,7 @@ export default class Textbox extends React.Component {
super(props);
this.focus = this.focus.bind(this);
this.recalculateSize = this.recalculateSize.bind(this);
this.getStateFromStores = this.getStateFromStores.bind(this);
this.onRecievedError = this.onRecievedError.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
@@ -91,13 +92,10 @@ export default class Textbox extends React.Component {
}
}
handleHeightChange(height) {
const textbox = $(this.refs.message.getTextbox());
handleHeightChange(height, maxHeight) {
const wrapper = $(this.refs.wrapper);
const maxHeight = parseInt(textbox.css('max-height'), 10);
// move over attachment icon to compensate for the scrollbar
// Move over attachment icon to compensate for the scrollbar
if (height > maxHeight) {
wrapper.closest('.post-body__cell').addClass('scroll');
} else {
@@ -106,7 +104,14 @@ export default class Textbox extends React.Component {
}
focus() {
this.refs.message.getTextbox().focus();
const textbox = this.refs.message.getTextbox();
textbox.focus();
Utils.placeCaretAtEnd(textbox);
}
recalculateSize() {
this.refs.message.recalculateSize();
}
showPreview(e) {

Просмотреть файл

@@ -24,7 +24,6 @@
"perfect-scrollbar": "0.6.12",
"react": "15.3.2",
"react-addons-pure-render-mixin": "15.3.2",
"react-autosize-textarea": "0.3.3",
"react-bootstrap": "0.30.3",
"react-custom-scrollbars": "4.0.0",
"react-dom": "15.3.2",

Просмотреть файл

@@ -21,7 +21,7 @@
.custom-textarea {
max-height: 60vh;
min-height: 20em;
min-height: 8em;
}
.suggestion-list {

Просмотреть файл

@@ -22,31 +22,6 @@
color: #d04444 !important;
}
.textarea-div {
border: 0;
color: rgba(0,0,0,0);
height: auto;
left: 1px;
line-height: 20px;
min-height: 36px;
position: absolute;
top: 0px;
white-space: pre-wrap;
word-break: break-word;
word-wrap: normal;
}
body.ios {
.textarea-div {
-webkit-overflow-scrolling: auto;
padding: 7px 17px 7px 15px;
}
}
.textarea-div::-webkit-scrollbar {
display: none;
}
.textarea-wrapper {
min-height: 36px;
position: relative;
@@ -390,7 +365,6 @@ body.ios {
.custom-textarea {
bottom: 0;
line-height: 1.5;
max-height: 162px !important;
padding-right: 28px;
padding-top: 8px;