Make typedInput keyboard navigable

This commit is contained in:
Nick O'Leary 2016-11-08 13:18:28 +00:00
parent 9c675a7847
commit 91f16215e5
3 changed files with 99 additions and 33 deletions

View File

@ -133,7 +133,7 @@
this.options.types = this.options.types||Object.keys(allOptions);
this.selectTrigger = $('<a href="#"></a>').prependTo(this.uiSelect);
this.selectTrigger = $('<button tabindex="0"></button>').prependTo(this.uiSelect);
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
this.selectLabel = $('<span></span>').appendTo(this.selectTrigger);
@ -160,32 +160,72 @@
})
this.selectTrigger.click(function(event) {
event.preventDefault();
if (that.typeList.length > 1) {
that._showMenu(that.menu,that.selectTrigger);
} else {
that.element.focus();
}
that._showTypeMenu();
});
this.selectTrigger.on('keydown',function(evt) {
if (evt.keyCode === 40) {
// Down
that._showTypeMenu();
}
}).on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus');
})
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
this.optionSelectTrigger = $('<a href="#" class="red-ui-typedInput-option-trigger" style="display:inline-block"><i class="fa fa-sort-desc"></i></a>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span></span>').prependTo(this.optionSelectTrigger);
this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="fa fa-sort-desc"></i></span></button>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
this.optionSelectTrigger.click(function(event) {
event.preventDefault();
if (that.optionMenu) {
that.optionMenu.css({
minWidth:that.optionSelectLabel.width()
});
that._showMenu(that.optionMenu,that.optionSelectLabel)
that._showOptionSelectMenu();
}).on('keydown', function(evt) {
if (evt.keyCode === 40) {
// Down
that._showOptionSelectMenu();
}
}).on('blur', function() {
that.uiSelect.removeClass('red-ui-typedInput-focus');
}).on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus');
});
this.type(this.options.default||this.typeList[0].value);
},
_showTypeMenu: function() {
if (this.typeList.length > 1) {
this._showMenu(this.menu,this.selectTrigger);
this.menu.find("[value='"+this.propertyType+"']").focus();
} else {
this.element.focus();
}
},
_showOptionSelectMenu: function() {
if (this.optionMenu) {
this.optionMenu.css({
minWidth:this.optionSelectLabel.width()
});
this._showMenu(this.optionMenu,this.optionSelectLabel);
var selectedOption = this.optionMenu.find("[value='"+this.value()+"']");
if (selectedOption.length === 0) {
selectedOption = this.optionMenu.children(":first");
}
selectedOption.focus();
}
},
_hideMenu: function(menu) {
$(document).off("mousedown.close-property-select");
menu.hide();
this.element.focus();
if (this.elementDiv.is(":visible")) {
this.element.focus();
} else if (this.optionSelectTrigger.is(":visible")){
this.optionSelectTrigger.focus();
} else {
this.selectTrigger.focus();
}
},
_createMenu: function(opts,callback) {
var that = this;
@ -194,7 +234,7 @@
if (typeof opt === 'string') {
opt = {value:opt,label:opt};
}
var op = $('<a href="#">').attr("value",opt.value).appendTo(menu);
var op = $('<a href="#"></a>').attr("value",opt.value).appendTo(menu);
if (opt.label) {
op.text(opt.label);
}
@ -214,6 +254,21 @@
display: "none",
});
menu.appendTo(document.body);
menu.on('keydown', function(evt) {
if (evt.keyCode === 40) {
// DOWN
$(this).children(":focus").next().focus();
} else if (evt.keyCode === 38) {
// UP
$(this).children(":focus").prev().focus();
} else if (evt.keyCode === 27) {
that._hideMenu(menu);
}
})
return menu;
},
@ -273,7 +328,7 @@
var labelWidth = this._getLabelWidth(this.selectTrigger);
this.elementDiv.css('left',labelWidth+"px");
if (this.optionSelectTrigger) {
this.optionSelectTrigger.css('left',(labelWidth+5)+"px");
this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'});
}
}
},

View File

@ -58,7 +58,7 @@ $workspace-button-color-focus-outline: rgba(85,150,230,0.2);
$typedInput-button-background: #efefef;
$typedInput-button-background-hover: #ddd;
$typedInput-button-background-active: #e3e3e3;
$typedInput-button-background-active: #ddd;
$editor-button-color-primary: #eee;
$editor-button-background-primary: #AD1625;

View File

@ -49,7 +49,10 @@
border-color: $form-input-focus-color !important;
}
a {
button {
text-align: left;
border: none;
position: absolute;
box-sizing: border-box;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
@ -82,13 +85,11 @@
&:not(.disabled):hover {
text-decoration: none;
background: $typedInput-button-background-hover;
span {
background: $typedInput-button-background-hover;
}
}
&:focus {
text-decoration: none;
outline: none;
box-shadow: inset 0 0 0 1px $form-input-focus-color;
}
&:not(.disabled):active {
background: $typedInput-button-background-active;
@ -96,30 +97,40 @@
}
}
a.red-ui-typedInput-option-trigger {
button.red-ui-typedInput-option-trigger {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
padding: 0 5px 0 0;
padding: 0 0 0 0;
position:absolute;
left:0;
top:0;
bottom:0;
right:0;
width: calc( 100% );
i {
position:absolute;
right: 4px;
top: 7px;
}
span {
.red-ui-typedInput-option-label {
background:#fff;
position:absolute;
left:0;
right:23px;
top: 0;
padding: 0 5px 0 5px;
}
.red-ui-typedInput-option-caret {
top: 0;
position: absolute;
right: 0;
width: 17px;
}
&:focus {
box-shadow: none;
}
&:focus .red-ui-typedInput-option-caret {
box-shadow: inset 0 0 0 1px $form-input-focus-color;
}
}
}
.red-ui-typedInput-options {
@ -139,12 +150,12 @@
}
&:focus {
text-decoration: none;
background: $typedInput-button-background-active;
outline: none;
}
&:active {
background: $typedInput-button-background-active;
text-decoration: none;
background: $typedInput-button-background-active;
}
}
}