mirror of https://github.com/vector-im/riot-web
Auto-complete clicked suggestions
parent
0dbb8d5294
commit
e541ddb060
|
@ -29,6 +29,7 @@ class TabComplete {
|
||||||
opts.wordSuffix = opts.wordSuffix || "";
|
opts.wordSuffix = opts.wordSuffix || "";
|
||||||
opts.allowLooping = opts.allowLooping || false;
|
opts.allowLooping = opts.allowLooping || false;
|
||||||
opts.autoEnterTabComplete = opts.autoEnterTabComplete || false;
|
opts.autoEnterTabComplete = opts.autoEnterTabComplete || false;
|
||||||
|
opts.onClickCompletes = opts.onClickCompletes || false;
|
||||||
this.opts = opts;
|
this.opts = opts;
|
||||||
this.completing = false;
|
this.completing = false;
|
||||||
this.list = []; // full set of tab-completable things
|
this.list = []; // full set of tab-completable things
|
||||||
|
@ -45,6 +46,14 @@ class TabComplete {
|
||||||
*/
|
*/
|
||||||
setCompletionList(completeList) {
|
setCompletionList(completeList) {
|
||||||
this.list = completeList;
|
this.list = completeList;
|
||||||
|
if (this.opts.onClickCompletes) {
|
||||||
|
// assign onClick listeners for each entry to complete the text
|
||||||
|
this.list.forEach((l) => {
|
||||||
|
l.onClick = () => {
|
||||||
|
this.completeTo(l.getText());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,6 +82,17 @@ class TabComplete {
|
||||||
this._calculateCompletions();
|
this._calculateCompletions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do an auto-complete with the given word. This terminates the tab-complete.
|
||||||
|
* @param {string} someVal
|
||||||
|
*/
|
||||||
|
completeTo(someVal) {
|
||||||
|
this.textArea.value = this._replaceWith(someVal, true);
|
||||||
|
this.stopTabCompleting();
|
||||||
|
// keep focus on the text area
|
||||||
|
this.textArea.focus();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Number} numAheadToPeek Return *up to* this many elements.
|
* @param {Number} numAheadToPeek Return *up to* this many elements.
|
||||||
* @return {Entry[]}
|
* @return {Entry[]}
|
||||||
|
@ -184,15 +204,10 @@ class TabComplete {
|
||||||
}
|
}
|
||||||
var looped = this.currentIndex === 0; // catch forward and backward looping
|
var looped = this.currentIndex === 0; // catch forward and backward looping
|
||||||
|
|
||||||
var suffix = "";
|
|
||||||
|
|
||||||
if (this.currentIndex !== 0) { // don't suffix the original text!
|
|
||||||
suffix = this.isFirstWord ? this.opts.startingWordSuffix : this.opts.wordSuffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set textarea to this new value
|
// set textarea to this new value
|
||||||
this.textArea.value = this._replaceWith(
|
this.textArea.value = this._replaceWith(
|
||||||
this.matchedList[this.currentIndex].text + suffix
|
this.matchedList[this.currentIndex].text,
|
||||||
|
this.currentIndex !== 0 // don't suffix the original text!
|
||||||
);
|
);
|
||||||
|
|
||||||
// visual display to the user that we looped - TODO: This should be configurable
|
// visual display to the user that we looped - TODO: This should be configurable
|
||||||
|
@ -211,8 +226,15 @@ class TabComplete {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_replaceWith(newVal) {
|
_replaceWith(newVal, includeSuffix) {
|
||||||
return this.originalText.replace(MATCH_REGEX, newVal);
|
var replacementText = (
|
||||||
|
newVal + (
|
||||||
|
includeSuffix ?
|
||||||
|
(this.isFirstWord ? this.opts.startingWordSuffix : this.opts.wordSuffix) :
|
||||||
|
""
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return this.originalText.replace(MATCH_REGEX, replacementText);
|
||||||
}
|
}
|
||||||
|
|
||||||
_calculateCompletions() {
|
_calculateCompletions() {
|
||||||
|
|
|
@ -41,6 +41,13 @@ class Entry {
|
||||||
getKey() {
|
getKey() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this entry is clicked.
|
||||||
|
*/
|
||||||
|
onClick() {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemberEntry extends Entry {
|
class MemberEntry extends Entry {
|
||||||
|
|
|
@ -93,6 +93,7 @@ module.exports = React.createClass({
|
||||||
wordSuffix: " ",
|
wordSuffix: " ",
|
||||||
allowLooping: false,
|
allowLooping: false,
|
||||||
autoEnterTabComplete: true,
|
autoEnterTabComplete: true,
|
||||||
|
onClickCompletes: true,
|
||||||
onStateChange: (isCompleting) => {
|
onStateChange: (isCompleting) => {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,8 +201,8 @@ module.exports = React.createClass({
|
||||||
this.onEnter(ev);
|
this.onEnter(ev);
|
||||||
}
|
}
|
||||||
else if (ev.keyCode === KeyCode.TAB) {
|
else if (ev.keyCode === KeyCode.TAB) {
|
||||||
|
if (this.props.tabComplete && this.props.room) {
|
||||||
var memberList = [];
|
var memberList = [];
|
||||||
if (this.props.room) {
|
|
||||||
// TODO: We should cache this list and only update it when the
|
// TODO: We should cache this list and only update it when the
|
||||||
// member list changes. It's also horrendous that this is done here.
|
// member list changes. It's also horrendous that this is done here.
|
||||||
memberList = this.props.room.getJoinedMembers().sort(function(a, b) {
|
memberList = this.props.room.getJoinedMembers().sort(function(a, b) {
|
||||||
|
@ -231,8 +231,6 @@ module.exports = React.createClass({
|
||||||
}).map(function(m) {
|
}).map(function(m) {
|
||||||
return new MemberEntry(m);
|
return new MemberEntry(m);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
if (this.props.tabComplete) {
|
|
||||||
this.props.tabComplete.setCompletionList(memberList);
|
this.props.tabComplete.setCompletionList(memberList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,11 @@ module.exports = React.createClass({
|
||||||
<div className="mx_TabCompleteBar">
|
<div className="mx_TabCompleteBar">
|
||||||
{this.props.entries.map(function(entry, i) {
|
{this.props.entries.map(function(entry, i) {
|
||||||
return (
|
return (
|
||||||
<div key={entry.getKey() || i + ""} className="mx_TabCompleteBar_item">
|
<div key={entry.getKey() || i + ""} className="mx_TabCompleteBar_item"
|
||||||
|
onClick={entry.onClick.bind(entry)} >
|
||||||
{entry.getImageJsx()}
|
{entry.getImageJsx()}
|
||||||
<span className="mx_TabCompleteBar_text">
|
<span className="mx_TabCompleteBar_text">
|
||||||
{entry.text}
|
{entry.getText()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue