зеркало из https://github.com/nextcloud/spreed.git
Add basic UI for autocompletion
CSS styles were directly copied from "apps/comments/css/autocomplete.scss". JavaScript code in the chat view was slightly simplified from "apps/comments/js/commentstabview.js". Currently mentions are not formatted when a message is being composed; "@" followed by the user name is added to the message so it can be directly sent without further processing. Formatted mentions will be introduced in another commit. Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Родитель
790bddd06d
Коммит
85cd8181e5
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
* based upon apps/comments/js/vendor/At.js/dist/css/jquery.atwho.css,
|
||||||
|
* only changed colors and font-weight
|
||||||
|
*/
|
||||||
|
|
||||||
|
.atwho-view {
|
||||||
|
position:absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: none;
|
||||||
|
margin-top: 18px;
|
||||||
|
background: $color-main-background;
|
||||||
|
color: $color-main-text;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
box-shadow: 0 0 5px $color-box-shadow;
|
||||||
|
min-width: 120px;
|
||||||
|
z-index: 11110 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atwho-view .atwho-header {
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: solid 1px $color-border;
|
||||||
|
color: $color-main-text;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atwho-view .atwho-header .small {
|
||||||
|
color: $color-main-text;
|
||||||
|
float: right;
|
||||||
|
padding-top: 2px;
|
||||||
|
margin-right: -5px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atwho-view .atwho-header:hover {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atwho-view .cur {
|
||||||
|
background: $color-primary;
|
||||||
|
color: $color-primary-text;
|
||||||
|
}
|
||||||
|
.atwho-view .cur small {
|
||||||
|
color: $color-primary-text;
|
||||||
|
}
|
||||||
|
.atwho-view strong {
|
||||||
|
color: $color-main-text;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.atwho-view .cur strong {
|
||||||
|
color: $color-primary-text;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.atwho-view ul {
|
||||||
|
/* width: 100px; */
|
||||||
|
list-style:none;
|
||||||
|
padding:0;
|
||||||
|
margin:auto;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.atwho-view ul li {
|
||||||
|
display: block;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-bottom: 1px solid $color-border;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.atwho-view small {
|
||||||
|
font-size: smaller;
|
||||||
|
color: $color-main-text;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
|
@ -95,6 +95,7 @@
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#commentsTabView .comment .message .avatar,
|
#commentsTabView .comment .message .avatar,
|
||||||
|
@ -151,6 +152,9 @@
|
||||||
.atwho-view-ul * .avatar-name-wrapper,
|
.atwho-view-ul * .avatar-name-wrapper,
|
||||||
#commentsTabView .comment .authorRow {
|
#commentsTabView .comment .authorRow {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#commentsTabView .comment .authorRow .avatar:not(.currentUser),
|
#commentsTabView .comment .authorRow .avatar:not(.currentUser),
|
||||||
|
@ -159,6 +163,12 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.atwho-view-ul .avatar-name-wrapper,
|
||||||
|
.atwho-view-ul .avatar-name-wrapper .avatar,
|
||||||
|
.atwho-view-ul .avatar-name-wrapper .avatar img {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.atwho-view-ul * .avatar-name-wrapper {
|
.atwho-view-ul * .avatar-name-wrapper {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,67 @@
|
||||||
inputPlaceholder: t('spreed', 'Name'),
|
inputPlaceholder: t('spreed', 'Name'),
|
||||||
buttonTitle: t('spreed', 'Rename')
|
buttonTitle: t('spreed', 'Rename')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_.bindAll(this, '_onAutoComplete');
|
||||||
|
},
|
||||||
|
|
||||||
|
_initAutoComplete: function($target) {
|
||||||
|
var s = this;
|
||||||
|
var limit = 20;
|
||||||
|
$target.atwho({
|
||||||
|
at: '@',
|
||||||
|
limit: limit,
|
||||||
|
callbacks: {
|
||||||
|
remoteFilter: s._onAutoComplete,
|
||||||
|
highlighter: function (li) {
|
||||||
|
// misuse the highlighter callback to instead of
|
||||||
|
// highlighting loads the avatars.
|
||||||
|
var $li = $(li);
|
||||||
|
$li.find('.avatar').avatar(undefined, 32);
|
||||||
|
return $li;
|
||||||
|
},
|
||||||
|
sorter: function (q, items) { return items; }
|
||||||
|
},
|
||||||
|
displayTpl: '<li>'
|
||||||
|
+ '<span class="avatar-name-wrapper">'
|
||||||
|
+ '<div class="avatar" '
|
||||||
|
+ 'data-username="${id}"' // for avatars
|
||||||
|
+ ' data-user="${id}"' // for contactsmenu
|
||||||
|
+ ' data-user-display-name="${label}"></div>'
|
||||||
|
+ ' <strong>${label}</strong>'
|
||||||
|
+ '</span></li>',
|
||||||
|
insertTpl: ''
|
||||||
|
+ '@${id}',
|
||||||
|
searchKey: "label"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_onAutoComplete: function(query, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if(_.isEmpty(query)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!_.isUndefined(this._autoCompleteRequestTimer)) {
|
||||||
|
clearTimeout(this._autoCompleteRequestTimer);
|
||||||
|
}
|
||||||
|
this._autoCompleteRequestTimer = _.delay(function() {
|
||||||
|
if(!_.isUndefined(this._autoCompleteRequestCall)) {
|
||||||
|
this._autoCompleteRequestCall.abort();
|
||||||
|
}
|
||||||
|
this._autoCompleteRequestCall = $.ajax({
|
||||||
|
url: OC.linkToOCS('apps/spreed/api/v1/chat', 2) + self.collection.token + '/autocomplete',
|
||||||
|
data: {
|
||||||
|
search: query
|
||||||
|
},
|
||||||
|
beforeSend: function (request) {
|
||||||
|
request.setRequestHeader('Accept', 'application/json');
|
||||||
|
},
|
||||||
|
success: function (result) {
|
||||||
|
callback(result.ocs.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}.bind(this), 400);
|
||||||
},
|
},
|
||||||
|
|
||||||
template: Handlebars.compile(TEMPLATE),
|
template: Handlebars.compile(TEMPLATE),
|
||||||
|
@ -166,6 +227,8 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._initAutoComplete($message);
|
||||||
|
|
||||||
autosize(this.$el.find('.newCommentRow .message'));
|
autosize(this.$el.find('.newCommentRow .message'));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -398,8 +461,11 @@
|
||||||
$field.data('submitButtonEl', $submitButton);
|
$field.data('submitButtonEl', $submitButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submits form with Enter, but Shift+Enter is a new line
|
// Submits form with Enter, but Shift+Enter is a new line. If the
|
||||||
if (ev.keyCode === 13 && !ev.shiftKey) {
|
// autocomplete popover is being shown Enter does not submit the
|
||||||
|
// form either; it will be handled by At.js which will add the
|
||||||
|
// currently selected item to the message.
|
||||||
|
if (ev.keyCode === 13 && !ev.shiftKey && !$field.atwho('isSelecting')) {
|
||||||
$submitButton.click();
|
$submitButton.click();
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ vendor_style('select2/select2');
|
||||||
|
|
||||||
style('spreed', 'style');
|
style('spreed', 'style');
|
||||||
style('spreed', 'comments');
|
style('spreed', 'comments');
|
||||||
|
style('spreed', 'autocomplete');
|
||||||
script(
|
script(
|
||||||
'spreed',
|
'spreed',
|
||||||
[
|
[
|
||||||
|
@ -14,6 +15,8 @@ script(
|
||||||
'vendor/backbone.radio/build/backbone.radio.min',
|
'vendor/backbone.radio/build/backbone.radio.min',
|
||||||
'vendor/backbone.marionette/lib/backbone.marionette.min',
|
'vendor/backbone.marionette/lib/backbone.marionette.min',
|
||||||
'vendor/jshashes/hashes.min',
|
'vendor/jshashes/hashes.min',
|
||||||
|
'vendor/Caret.js/dist/jquery.caret.min',
|
||||||
|
'vendor/At.js/dist/js/jquery.atwho.min',
|
||||||
'models/chatmessage',
|
'models/chatmessage',
|
||||||
'models/chatmessagecollection',
|
'models/chatmessagecollection',
|
||||||
'models/localstoragemodel',
|
'models/localstoragemodel',
|
||||||
|
|
|
@ -7,6 +7,7 @@ vendor_style('select2/select2');
|
||||||
|
|
||||||
style('spreed', 'style');
|
style('spreed', 'style');
|
||||||
style('spreed', 'comments');
|
style('spreed', 'comments');
|
||||||
|
style('spreed', 'autocomplete');
|
||||||
script(
|
script(
|
||||||
'spreed',
|
'spreed',
|
||||||
[
|
[
|
||||||
|
@ -14,6 +15,8 @@ script(
|
||||||
'vendor/backbone.radio/build/backbone.radio.min',
|
'vendor/backbone.radio/build/backbone.radio.min',
|
||||||
'vendor/backbone.marionette/lib/backbone.marionette.min',
|
'vendor/backbone.marionette/lib/backbone.marionette.min',
|
||||||
'vendor/jshashes/hashes.min',
|
'vendor/jshashes/hashes.min',
|
||||||
|
'vendor/Caret.js/dist/jquery.caret.min',
|
||||||
|
'vendor/At.js/dist/js/jquery.atwho.min',
|
||||||
'models/chatmessage',
|
'models/chatmessage',
|
||||||
'models/chatmessagecollection',
|
'models/chatmessagecollection',
|
||||||
'models/room',
|
'models/room',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче