diff --git a/src/component-index.js b/src/component-index.js
index 5fadb18b6a..e250838cc4 100644
--- a/src/component-index.js
+++ b/src/component-index.js
@@ -51,6 +51,7 @@ module.exports.components['views.dialogs.QuestionDialog'] = require('./component
module.exports.components['views.dialogs.SetDisplayNameDialog'] = require('./components/views/dialogs/SetDisplayNameDialog');
module.exports.components['views.dialogs.TextInputDialog'] = require('./components/views/dialogs/TextInputDialog');
module.exports.components['views.elements.EditableText'] = require('./components/views/elements/EditableText');
+module.exports.components['views.elements.EditableTextContainer'] = require('./components/views/elements/EditableTextContainer');
module.exports.components['views.elements.PowerSelector'] = require('./components/views/elements/PowerSelector');
module.exports.components['views.elements.ProgressBar'] = require('./components/views/elements/ProgressBar');
module.exports.components['views.elements.TintableSvg'] = require('./components/views/elements/TintableSvg');
diff --git a/src/components/views/elements/EditableText.js b/src/components/views/elements/EditableText.js
index 9218fe820e..15118f249e 100644
--- a/src/components/views/elements/EditableText.js
+++ b/src/components/views/elements/EditableText.js
@@ -49,6 +49,8 @@ module.exports = React.createClass({
label: '',
placeholder: '',
editable: true,
+ className: "mx_EditableText",
+ placeholderClassName: "mx_EditableText_placeholder",
};
},
@@ -92,7 +94,7 @@ module.exports = React.createClass({
this.refs.editable_div.textContent = this.value;
this.refs.editable_div.setAttribute("class", this.props.className);
this.placeholder = false;
- }
+ }
},
getValue: function() {
@@ -101,7 +103,7 @@ module.exports = React.createClass({
setValue: function(value) {
this.value = value;
- this.showPlaceholder(!this.value);
+ this.showPlaceholder(!this.value);
},
edit: function() {
@@ -125,7 +127,7 @@ module.exports = React.createClass({
onKeyDown: function(ev) {
// console.log("keyDown: textContent=" + ev.target.textContent + ", value=" + this.value + ", placeholder=" + this.placeholder);
-
+
if (this.placeholder) {
this.showPlaceholder(false);
}
@@ -173,7 +175,7 @@ module.exports = React.createClass({
var range = document.createRange();
range.setStart(node, 0);
range.setEnd(node, node.length);
-
+
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
diff --git a/src/components/views/elements/EditableTextContainer.js b/src/components/views/elements/EditableTextContainer.js
new file mode 100644
index 0000000000..9e863629f2
--- /dev/null
+++ b/src/components/views/elements/EditableTextContainer.js
@@ -0,0 +1,147 @@
+/*
+Copyright 2015, 2016 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from 'react';
+import sdk from '../../../index';
+import q from 'q';
+
+/**
+ * A component which wraps an EditableText, with a spinner while updates take
+ * place.
+ *
+ * Parent components should supply an 'onSubmit' callback which returns a
+ * promise; a spinner is shown until the promise resolves.
+ *
+ * The parent can also supply a 'getIntialValue' callback, which works in a
+ * similarly asynchronous way. If this is not provided, the initial value is
+ * taken from the 'initialValue' property.
+ */
+export default class EditableTextContainer extends React.Component {
+ constructor(props, context) {
+ super(props, context);
+
+ this._unmounted = false;
+ this.state = {
+ busy: false,
+ errorString: null,
+ value: props.initialValue,
+ };
+ this._onValueChanged=this._onValueChanged.bind(this);
+ }
+
+ componentWillMount() {
+ if (this.props.getInitialValue === undefined) {
+ // use whatever was given in the initialValue property.
+ return;
+ }
+
+ this.setState({busy: true});
+
+ this.props.getInitialValue().done(
+ (result) => {
+ if (this._unmounted) { return; }
+ this.setState({
+ busy: false,
+ value: result,
+ });
+ },
+ (error) => {
+ if (this._unmounted) { return; }
+ this.setState({
+ errorString: error.toString(),
+ busy: false,
+ });
+ }
+ );
+ }
+
+ componentWillUnmount() {
+ this._unmounted = true;
+ }
+
+ _onValueChanged(value, shouldSubmit) {
+ if (!shouldSubmit) {
+ return;
+ }
+
+ this.setState({
+ busy: true,
+ errorString: null,
+ });
+
+ this.props.onSubmit(value).done(
+ () => {
+ if (this._unmounted) { return; }
+ this.setState({
+ busy: false,
+ value: value,
+ });
+ },
+ (error) => {
+ if (this._unmounted) { return; }
+ this.setState({
+ errorString: error.toString(),
+ busy: false,
+ });
+ }
+ );
+ }
+
+ render() {
+ if (this.state.busy) {
+ var Loader = sdk.getComponent("elements.Spinner");
+ return (
+