Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for keyboard navigation #2122

Merged
merged 12 commits into from
Aug 28, 2019
83 changes: 61 additions & 22 deletions css/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,6 @@
flex-grow: 1;
}

#oca-spreedme-add-room {
border-bottom: 1px solid var(--color-border);
}

.oca-spreedme-add-person {
border: 1px solid var(--color-border);
border-radius: var(--border-radius);
}

.contactsmenu-popover li > a > img {
/* The app uses border-box sizing, so the size of the icon is the
* width/height plus the padding set by default in the server
Expand Down Expand Up @@ -155,11 +146,36 @@ input[type="password"] {
#select2-drop {
margin-top: -44px !important;
}
#oca-spreedme-add-room .select2-container {
border-bottom: 1px solid var(--color-border);

&.select2-container-active {
border-bottom-color: var(--color-border-dark);
border-right: 1px solid var(--color-border-dark);

.select2-choice,
.select2-default {
color: var(--color-text-light) !important;
}
}
}
.oca-spreedme-add-person .select2-container {
border: 1px solid var(--color-border);
border-radius: var(--border-radius);

&.select2-container-active {
border-color: var(--color-border-dark);

.select2-choice,
.select2-default {
color: var(--color-text-light) !important;
}
}
}
#oca-spreedme-add-room .select2-container,
.oca-spreedme-add-person .select2-container {
width: 100%;
margin: 0 !important;
border: none;
padding: 9px;
}
#oca-spreedme-add-room .select2-container .select2-choice,
Expand All @@ -183,14 +199,12 @@ input[type="password"] {
padding: 0;
}

.participantWithList .avatar,
#app-navigation .app-navigation-entry-link > .avatar {
position: absolute;
left: 6px;
top: 6px;
}

.participantWithList > li > a:first-child > img,
#app-navigation li > a:first-child img {
width: 32px !important;
height: 32px !important;
Expand Down Expand Up @@ -694,7 +708,7 @@ input[type="password"] {
}

.participantWithList .participant-offline {
& > a {
& > span {
color: var(--color-text-maxcontrast);
}
.avatar {
Expand All @@ -708,7 +722,7 @@ input[type="password"] {
box-sizing: border-box;
}

.participantWithList > li > a {
.participantWithList > li > span {
display: block;
width: 100%;
line-height: 44px;
Expand All @@ -722,6 +736,33 @@ input[type="password"] {
background: no-repeat 14px center;
}

.participantWithList > li > span > .avatar-wrapper {
position: absolute;
top: 6px;
left: 6px;

&:focus,
&:active {
border: 1px solid var(--color-border-dark);
border-radius: 50%;

/* Separate the border slightly from the avatar to make it more
* noticeable. */
padding: 3px;

/* Compensate position for the border and the increased size. */
top: 2px;
left: 2px;
}
}

body:not(#body-public) .participantWithList > li > span:not(.currentUser):not(.guestUser) {
.avatar,
.avatar img {
cursor: pointer;
}
}



/**
Expand Down Expand Up @@ -771,21 +812,19 @@ input[type="password"] {
.label-wrapper {
display: flex;
align-items: center;
.edit-button {
.edit-button .icon {
background-color: transparent;
border: none;
padding: 13px 22px;
margin: 0;

opacity: .3;

&:hover,
&:focus,
&:active {
opacity: 1;
}

.icon {
background-color: transparent;
border: none;
padding: 13px 22px;
margin: 0;
}
}
}
.input-wrapper {
Expand Down
3 changes: 2 additions & 1 deletion js/views/callinfoview.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@
'change @ui.linkCheckbox': 'toggleLinkCheckbox',

'keyup @ui.passwordInput': 'keyUpPassword',
'click @ui.passwordButton': 'showPasswordInput',
'click @ui.passwordConfirm': 'confirmPassword',
'submit @ui.passwordForm': 'confirmPassword',
},
Expand Down Expand Up @@ -296,6 +295,7 @@
this.ui.passwordInput.val('');
restoreState();
OC.hideMenus();
this.ui.passwordButton.focus();
}.bind(this),
error: function() {
restoreState();
Expand All @@ -310,6 +310,7 @@
if (e.keyCode === 27) {
// ESC
OC.hideMenus();
this.ui.passwordButton.focus();
}
},

Expand Down
33 changes: 32 additions & 1 deletion js/views/editabletextlabel.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,15 @@
ui: {
labelWrapper: '.label-wrapper',
label: '.label',
editButton: '.edit-button',
editButton: '.edit-button button',
inputWrapper: '.input-wrapper',
input: 'input.username',
confirmButton: '.confirm-button',
loadingIcon: '.icon-loading-small',
},

events: {
'keydown @ui.editButton': 'preventConfirmEditOnNextInputKeyUp',
'click @ui.editButton': 'showInput',
'keyup @ui.input': 'handleInputKeyUp',
'click @ui.confirmButton': 'confirmEdit',
Expand Down Expand Up @@ -181,6 +182,34 @@
this.getUI('label').text(this._getText());
},

/**
* Prevents the edition to be confirmed on the next key up event on the
* input.
*
* When Enter is pressed in the edit button the default behaviour is to
* trigger a click event which, in turn, shows and focus the input.
* However, as the enter key is still pressed as soon as it is released
* a key up event is triggered, now on the focused input, which would
* confirm the edit and hide again the input.
*
* Note that confirming the edition is only prevented for the first key
* up event. If the Enter key is kept pressed on an input the browser
* periodically generates new key down and key up events; surprisingly
* the "repeat" property of the event is "false", so it can not be
* distinguished if the key is being kept pressed. Due to this it is not
* possible to prevent confirming the edition until the Enter key is
* actually released for the first time after showing the input.
*/
preventConfirmEditOnNextInputKeyUp: function(event) {
if (event.keyCode !== 13) {
return;
}

this.getUI('input').one('keyup', function(event) {
event.stopPropagation();
}.bind(this));
},

showInput: function() {
this.getUI('input').val(this.model.get(this.modelAttribute));

Expand All @@ -193,6 +222,8 @@
hideInput: function() {
this.getUI('labelWrapper').removeClass('hidden-important');
this.getUI('inputWrapper').addClass('hidden-important');

this.getUI('editButton').focus();
},

handleInputKeyUp: function(event) {
Expand Down
16 changes: 14 additions & 2 deletions js/views/participantlistview.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,18 @@
name = t('spreed', 'Guest');
}

var isGuestOrGuestModerator = this.model.get('participantType') === OCA.SpreedMe.app.GUEST || this.model.get('participantType') === OCA.SpreedMe.app.GUEST_MODERATOR;
var hasContactsMenu = OC.getCurrentUser().uid && !isSelf && !isGuestOrGuestModerator;

return {
canModerate: canModerate,
canBePromoted: this.model.get('participantType') === OCA.SpreedMe.app.USER || this.model.get('participantType') === OCA.SpreedMe.app.GUEST,
canBeDemoted: this.model.get('participantType') === OCA.SpreedMe.app.MODERATOR || this.model.get('participantType') === OCA.SpreedMe.app.GUEST_MODERATOR,
name: name,
participantHasContactsMenu: hasContactsMenu,
participantIsSelf: isSelf,
participantIsUser: this.model.get('participantType') === OCA.SpreedMe.app.USER,
participantIsGuestOrGuestModerator: isGuestOrGuestModerator,
participantIsGuestModerator: this.model.get('participantType') === OCA.SpreedMe.app.GUEST_MODERATOR,
participantIsModerator: this.model.get('participantType') === OCA.SpreedMe.app.MODERATOR,
participantIsOwner: this.model.get('participantType') === OCA.SpreedMe.app.OWNER,
Expand Down Expand Up @@ -134,8 +140,14 @@

if (OC.getCurrentUser().uid && model.get('userId') &&
model.get('userId') !== OC.getCurrentUser().uid) {
this.$el.find('.participant-entry-link .avatar').contactsMenu(
model.get('userId'), 0, this.$el.find('.participant-entry-link'));
this.$el.find('.participant-entry .avatar').contactsMenu(
model.get('userId'), 0, this.$el.find('.participant-entry'));

this.$el.find('.participant-entry .avatar-wrapper').on('keyup', function(event) {
if (event.key === ' ' || event.key === 'Enter') {
$(this).find('.avatar').click();
}
});
}

this.$el.attr('data-session-id', this.model.get('sessionId'));
Expand Down
16 changes: 15 additions & 1 deletion js/views/tabview.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@

tagName: 'li',
className: 'tabHeader',
attributes: {
tabindex: 0,
},

template: function(context) {
// OCA.Talk.Views.Templates may not have been initialized when this
Expand All @@ -52,14 +55,21 @@
events: {
'click': function() {
this.triggerMethod('click:tabHeader', this.getOption('tabId'));
}
},
'keyup': function(event) {
if (event.key === ' ' || event.key === 'Enter') {
this.triggerMethod('click:tabHeader', this.getOption('tabId'));
}
},
},

setSelected: function(selected) {
if (selected) {
this.$el.addClass('selected');
this.$el.attr('tabindex', '-1');
} else {
this.$el.removeClass('selected');
this.$el.attr('tabindex', '0');
}
}

Expand Down Expand Up @@ -182,6 +192,10 @@
},

selectTabHeader: function(tabId) {
if (this._currentTabId === tabId) {
return;
}

this.triggerMethod('unselect:tabHeader', this._currentTabId);

if (this._currentTabId !== undefined) {
Expand Down
Loading