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 удалений

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

@@ -1284,37 +1284,6 @@ limitations under the License.
---
This product contains a modified portion of 'react-autosize-textarea', a light replacement for built-in textarea component which automaticaly adjusts its height to match the content.
* HOMEPAGE:
* https://github.com/buildo/react-autosize-textarea
* LICENSE:
The MIT License (MIT)
Copyright (c) 2016 buildo s.r.l.s.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
This product contains a modified portion of 'compass-mixins', which pulls SASS style sheets on Bower, and enjoys the compass mixins by using libsass for faster compilation, by Christopher M. Eppstein.
* HOMEPAGE:

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;