summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Calviño Sánchez <danxuliu@gmail.com>2018-03-20 12:02:49 +0100
committerDaniel Calviño Sánchez <danxuliu@gmail.com>2018-03-20 19:09:05 +0100
commit10a4f8e45ee1e3b6a8f2b6c9348271724eb3371b (patch)
tree90b3f698ab399918a920e505a4a525e74d41b65f
parent9371b61c4df9eb9dc6285e988431ac9cae228952 (diff)
downloadnextcloud-server-10a4f8e45ee1e3b6a8f2b6c9348271724eb3371b.tar.gz
nextcloud-server-10a4f8e45ee1e3b6a8f2b6c9348271724eb3371b.zip
Confirm a share also by pressing enter on the input field
Besides confirming a share by clicking on the confirm button now it is possible to do it by pressing enter on the input field. Clicking on the confirm button implicitly hides the autocomplete dropdown. On the other hand, pressing enter on the input field does not, so the autocompletion must be disabled and closed when the confirmation begins and then enabled again once it finishes. Otherwise the autocomplete dropdown would be visible and it would be possible to interact with it while the share is being confirmed. The order in which the input field and the autompletion are disabled is important. Internally, the autocompletion sets a timeout when the input field is modified that requests the suggestions to the server and then shows them in the dropdown. That timeout is not cancelled when the autocompletion is disabled, but when the input field loses its focus and the autocompletion is not disabled. Therefore, the input field has to be disabled (which causes it to lose the focus) before the autocompletion is disabled. Otherwise it could happen that while a share is being confirmed the timeout ends, so an autocompletion request is sent and then, once the share is successfully confirmed and thus the autocompletion is enabled again, the request is received and the autocomplete dropdown is shown with the old suggestions. Strange, but possible nevertheless ;-) Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
-rw-r--r--core/js/sharedialogview.js36
-rw-r--r--core/js/tests/specs/sharedialogviewSpec.js11
2 files changed, 47 insertions, 0 deletions
diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js
index 89bd2e2dbfc..0f1d8f39550 100644
--- a/core/js/sharedialogview.js
+++ b/core/js/sharedialogview.js
@@ -415,6 +415,10 @@
_onSelectRecipient: function(e, s) {
e.preventDefault();
+ // Ensure that the keydown handler for the input field is not
+ // called; otherwise it would try to add the recipient again, which
+ // would fail.
+ e.stopImmediatePropagation();
$(e.target).attr('disabled', true)
.val(s.item.label);
var $loading = this.$el.find('.shareWithLoading');
@@ -451,6 +455,15 @@
$shareWithField.prop('disabled', true);
+ // Disabling the autocompletion does not clear its search timeout;
+ // removing the focus from the input field does, but only if the
+ // autocompletion is not disabled when the field loses the focus.
+ // Thus, the field has to be disabled before disabling the
+ // autocompletion to prevent an old pending search result from
+ // appearing once the field is enabled again.
+ $shareWithField.autocomplete('close');
+ $shareWithField.autocomplete('disable');
+
var perPage = 200;
var onlyExactMatches = true;
this._getSuggestions(
@@ -467,6 +480,8 @@
$shareWithField.prop('disabled', false);
$shareWithField.focus();
+ $shareWithField.autocomplete('enable');
+
// There is no need to show an error message here; it will
// be automatically shown when the autocomplete is activated
// again (due to the focus on the field) and it finds no
@@ -483,6 +498,8 @@
$shareWithField.prop('disabled', false);
$shareWithField.focus();
+ $shareWithField.autocomplete('enable');
+
return;
}
@@ -494,6 +511,8 @@
$shareWithField.val('');
$shareWithField.prop('disabled', false);
$shareWithField.focus();
+
+ $shareWithField.autocomplete('enable');
};
var actionError = function(obj, msg) {
@@ -504,6 +523,8 @@
$shareWithField.prop('disabled', false);
$shareWithField.focus();
+ $shareWithField.autocomplete('enable');
+
OC.Notification.showTemporary(msg);
};
@@ -519,6 +540,8 @@
$shareWithField.prop('disabled', false);
$shareWithField.focus();
+ $shareWithField.autocomplete('enable');
+
// There is no need to show an error message here; it will be
// automatically shown when the autocomplete is activated again
// (due to the focus on the field) and getting the suggestions
@@ -554,6 +577,7 @@
},
render: function() {
+ var self = this;
var baseTemplate = this._getTemplate('base', TEMPLATE_BASE);
this.$el.html(baseTemplate({
@@ -565,6 +589,16 @@
var $shareField = this.$el.find('.shareWithField');
if ($shareField.length) {
+ var shareFieldKeydownHandler = function(event) {
+ if (event.keyCode !== 13) {
+ return true;
+ }
+
+ self._confirmShare();
+
+ return false;
+ };
+
$shareField.autocomplete({
minLength: 1,
delay: 750,
@@ -574,6 +608,8 @@
source: this.autocompleteHandler,
select: this._onSelectRecipient
}).data('ui-autocomplete')._renderItem = this.autocompleteRenderItem;
+
+ $shareField.on('keydown', null, shareFieldKeydownHandler);
}
this.resharerInfoView.$el = this.$el.find('.resharerInfoView');
diff --git a/core/js/tests/specs/sharedialogviewSpec.js b/core/js/tests/specs/sharedialogviewSpec.js
index 76a214f6705..7ef38c022dd 100644
--- a/core/js/tests/specs/sharedialogviewSpec.js
+++ b/core/js/tests/specs/sharedialogviewSpec.js
@@ -1872,6 +1872,8 @@ describe('OC.Share.ShareDialogView', function() {
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(false);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(true);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('disable');
+ expect(autocompleteStub.calledWith('close')).toEqual(true);
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(true);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
});
@@ -1918,6 +1920,7 @@ describe('OC.Share.ShareDialogView', function() {
// Ensure that the UI is not restored before adding the share
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(false);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(true);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('disable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(true);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
@@ -1933,6 +1936,7 @@ describe('OC.Share.ShareDialogView', function() {
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('enable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
expect(dialog.$el.find('.shareWithField').val()).toEqual('');
});
@@ -1981,6 +1985,7 @@ describe('OC.Share.ShareDialogView', function() {
// Ensure that the UI is not restored before adding the share
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(false);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(true);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('disable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(true);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
@@ -1996,6 +2001,7 @@ describe('OC.Share.ShareDialogView', function() {
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('enable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
@@ -2037,6 +2043,7 @@ describe('OC.Share.ShareDialogView', function() {
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('enable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
@@ -2088,6 +2095,7 @@ describe('OC.Share.ShareDialogView', function() {
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('enable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bo');
});
@@ -2143,6 +2151,7 @@ describe('OC.Share.ShareDialogView', function() {
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('enable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
});
@@ -2171,6 +2180,7 @@ describe('OC.Share.ShareDialogView', function() {
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('enable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');
@@ -2188,6 +2198,7 @@ describe('OC.Share.ShareDialogView', function() {
expect(dialog.$el.find('.shareWithLoading').hasClass('hidden')).toEqual(true);
expect(dialog.$el.find('.shareWithConfirm').hasClass('hidden')).toEqual(false);
+ expect(autocompleteStub.lastCall.args[0]).toEqual('enable');
expect(dialog.$el.find('.shareWithField').prop('disabled')).toEqual(false);
expect(dialog.$el.find('.shareWithField').val()).toEqual('bob');