Switched Textbox to use a TextareaAutosize and removed custom resizing code
Этот коммит содержится в:
@@ -27,8 +27,8 @@ const holders = defineMessages({
|
||||
import React from 'react';
|
||||
|
||||
class EditPostModal extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleEdit = this.handleEdit.bind(this);
|
||||
this.handleEditInput = this.handleEditInput.bind(this);
|
||||
@@ -56,12 +56,13 @@ class EditPostModal extends React.Component {
|
||||
updatedPost.id = this.state.post_id;
|
||||
updatedPost.channel_id = this.state.channel_id;
|
||||
|
||||
Client.updatePost(updatedPost,
|
||||
function success() {
|
||||
Client.updatePost(
|
||||
updatedPost,
|
||||
() => {
|
||||
AsyncClient.getPosts(updatedPost.channel_id);
|
||||
window.scrollTo(0, 0);
|
||||
},
|
||||
function error(err) {
|
||||
(err) => {
|
||||
AsyncClient.dispatchError(err, 'updatePost');
|
||||
}
|
||||
);
|
||||
@@ -106,11 +107,11 @@ class EditPostModal extends React.Component {
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function onHidden() {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', () => {
|
||||
self.setState({editText: '', title: '', channel_id: '', post_id: '', comments: 0, refocusId: '', error: ''});
|
||||
});
|
||||
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', function onShow(e) {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', (e) => {
|
||||
var button = e.relatedTarget;
|
||||
if (!button) {
|
||||
return;
|
||||
@@ -118,12 +119,11 @@ class EditPostModal extends React.Component {
|
||||
self.setState({editText: $(button).attr('data-message'), title: $(button).attr('data-title'), channel_id: $(button).attr('data-channelid'), post_id: $(button).attr('data-postid'), comments: $(button).attr('data-comments'), refocusId: $(button).attr('data-refocusid')});
|
||||
});
|
||||
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', function onShown() {
|
||||
self.refs.editbox.resize();
|
||||
$('#edit_textbox').get(0).focus();
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', () => {
|
||||
self.refs.editbox.focus();
|
||||
});
|
||||
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hide.bs.modal', function onShown() {
|
||||
$(ReactDOM.findDOMNode(this.refs.modal)).on('hide.bs.modal', () => {
|
||||
if (self.state.refocusId !== '') {
|
||||
setTimeout(() => {
|
||||
$(self.state.refocusId).get(0).focus();
|
||||
@@ -221,4 +221,4 @@ EditPostModal.propTypes = {
|
||||
intl: intlShape.isRequired
|
||||
};
|
||||
|
||||
export default injectIntl(EditPostModal);
|
||||
export default injectIntl(EditPostModal);
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
|
||||
import $ from 'jquery';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Constants from 'utils/constants.jsx';
|
||||
import * as GlobalActions from 'action_creators/global_actions.jsx';
|
||||
import SuggestionStore from 'stores/suggestion_store.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
|
||||
const KeyCodes = Constants.KeyCodes;
|
||||
|
||||
import React from 'react';
|
||||
@@ -44,7 +47,13 @@ export default class SuggestionBox extends React.Component {
|
||||
|
||||
getTextbox() {
|
||||
// this is to support old code that looks at the input/textarea DOM nodes
|
||||
return ReactDOM.findDOMNode(this.refs.textbox);
|
||||
let textbox = this.refs.textbox;
|
||||
|
||||
if (!(textbox instanceof HTMLElement)) {
|
||||
textbox = ReactDOM.findDOMNode(textbox);
|
||||
}
|
||||
|
||||
return textbox;
|
||||
}
|
||||
|
||||
handleDocumentClick(e) {
|
||||
@@ -132,7 +141,8 @@ export default class SuggestionBox extends React.Component {
|
||||
);
|
||||
} else if (this.props.type === 'textarea') {
|
||||
textbox = (
|
||||
<textarea
|
||||
<TextareaAutosize
|
||||
id={this.suggestionId}
|
||||
ref='textbox'
|
||||
{...newProps}
|
||||
/>
|
||||
@@ -163,5 +173,6 @@ SuggestionBox.propTypes = {
|
||||
|
||||
// explicitly name any input event handlers we override and need to manually call
|
||||
onChange: React.PropTypes.func,
|
||||
onKeyDown: React.PropTypes.func
|
||||
onKeyDown: React.PropTypes.func,
|
||||
onHeightChange: React.PropTypes.func
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// See License.txt for license information.
|
||||
|
||||
import $ from 'jquery';
|
||||
import ReactDOM from 'react-dom';
|
||||
import AtMentionProvider from './suggestion/at_mention_provider.jsx';
|
||||
import CommandProvider from './suggestion/command_provider.jsx';
|
||||
import EmoticonProvider from './suggestion/emoticon_provider.jsx';
|
||||
@@ -29,7 +28,7 @@ export default class Textbox extends React.Component {
|
||||
this.onRecievedError = this.onRecievedError.bind(this);
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||
this.resize = this.resize.bind(this);
|
||||
this.handleHeightChange = this.handleHeightChange.bind(this);
|
||||
this.showPreview = this.showPreview.bind(this);
|
||||
|
||||
this.state = {
|
||||
@@ -54,8 +53,6 @@ export default class Textbox extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
ErrorStore.addChangeListener(this.onRecievedError);
|
||||
|
||||
this.resize();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@@ -72,10 +69,6 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.resize();
|
||||
}
|
||||
|
||||
handleKeyPress(e) {
|
||||
this.props.onKeyPress(e);
|
||||
}
|
||||
@@ -86,50 +79,28 @@ export default class Textbox extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.refs.message.getTextbox().focus();
|
||||
handleHeightChange(height) {
|
||||
const textbox = $(this.refs.message.getTextbox());
|
||||
const wrapper = $(this.refs.wrapper);
|
||||
|
||||
const maxHeight = parseInt(textbox.css('max-height'), 10);
|
||||
|
||||
// move over attachment icon to compensate for the scrollbar
|
||||
if (height > maxHeight) {
|
||||
wrapper.closest('.post-body__cell').addClass('scroll');
|
||||
} else {
|
||||
wrapper.closest('.post-body__cell').removeClass('scroll');
|
||||
}
|
||||
}
|
||||
|
||||
resize() {
|
||||
const textbox = this.refs.message.getTextbox();
|
||||
const $textbox = $(textbox);
|
||||
const $wrapper = $(ReactDOM.findDOMNode(this.refs.wrapper));
|
||||
|
||||
const padding = parseInt($textbox.css('padding-bottom'), 10) + parseInt($textbox.css('padding-top'), 10);
|
||||
const borders = parseInt($textbox.css('border-bottom-width'), 10) + parseInt($textbox.css('border-top-width'), 10);
|
||||
const maxHeight = parseInt($textbox.css('max-height'), 10) - borders;
|
||||
|
||||
// set the height to auto and remove the scrollbar so we can get the actual size of the contents
|
||||
$textbox.css('height', 'auto').css('overflow-y', 'hidden');
|
||||
|
||||
let height = textbox.scrollHeight - padding;
|
||||
|
||||
if (height + padding > maxHeight) {
|
||||
height = maxHeight - padding;
|
||||
|
||||
// turn scrollbar on and move over attachment icon to compensate for that
|
||||
$textbox.css('overflow-y', 'scroll');
|
||||
$wrapper.closest('.post-body__cell').addClass('scroll');
|
||||
} else {
|
||||
$wrapper.closest('.post-body__cell').removeClass('scroll');
|
||||
}
|
||||
|
||||
// set the textarea to be the proper height
|
||||
$textbox.height(height);
|
||||
|
||||
// set the wrapper height to match the height of the textbox including padding and borders
|
||||
$wrapper.height(height + padding + borders);
|
||||
|
||||
if (this.state.preview) {
|
||||
$(ReactDOM.findDOMNode(this.refs.preview)).height(height + borders);
|
||||
}
|
||||
focus() {
|
||||
this.refs.message.getTextbox().focus();
|
||||
}
|
||||
|
||||
showPreview(e) {
|
||||
e.preventDefault();
|
||||
e.target.blur();
|
||||
this.setState({preview: !this.state.preview});
|
||||
this.resize();
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -157,7 +128,7 @@ export default class Textbox extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
let helpText = (
|
||||
const helpText = (
|
||||
<div
|
||||
style={{visibility: hasText ? 'visible' : 'hidden', opacity: hasText ? '0.5' : '0'}}
|
||||
className='help_format_text'
|
||||
@@ -174,12 +145,16 @@ export default class Textbox extends React.Component {
|
||||
defaultMessage='_italic_'
|
||||
/>
|
||||
</i>
|
||||
<span>~~<strike>
|
||||
<FormattedMessage
|
||||
id='textbox.strike'
|
||||
defaultMessage='strike'
|
||||
/>
|
||||
</strike>~~ </span>
|
||||
<span>
|
||||
{'~~'}
|
||||
<strike>
|
||||
<FormattedMessage
|
||||
id='textbox.strike'
|
||||
defaultMessage='strike'
|
||||
/>
|
||||
</strike>
|
||||
{'~~ '}
|
||||
</span>
|
||||
<code>
|
||||
<FormattedMessage
|
||||
id='textbox.inlinecode'
|
||||
@@ -214,16 +189,17 @@ export default class Textbox extends React.Component {
|
||||
spellCheck='true'
|
||||
autoComplete='off'
|
||||
autoCorrect='off'
|
||||
rows='1'
|
||||
maxLength={Constants.MAX_POST_LEN}
|
||||
placeholder={this.props.createMessage}
|
||||
value={this.props.messageText}
|
||||
onUserInput={this.props.onUserInput}
|
||||
onKeyPress={this.handleKeyPress}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onHeightChange={this.handleHeightChange}
|
||||
style={{visibility: this.state.preview ? 'hidden' : 'visible'}}
|
||||
listComponent={SuggestionList}
|
||||
providers={this.suggestionProviders}
|
||||
channelId={this.props.channelId}
|
||||
/>
|
||||
<div
|
||||
ref='preview'
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"react-dom": "0.14.7",
|
||||
"react-intl": "2.0.0-rc-1",
|
||||
"react-router": "2.0.1",
|
||||
"react-textarea-autosize": "3.3.0",
|
||||
"twemoji": "1.4.1",
|
||||
"velocity-animate": "1.2.3"
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
.suggestion-list--top {
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
.suggestion-list__content {
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
line-height: 20px;
|
||||
min-height: 36px;
|
||||
overflow-x: hidden;
|
||||
position: absolute;
|
||||
resize: none;
|
||||
top: 0px;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user