Skip to content
This repository has been archived by the owner on Oct 2, 2019. It is now read-only.

Commit

Permalink
feat: provide a way to skip the focusser
Browse files Browse the repository at this point in the history
There was no easy way to configure if the focusser should be skipped
after selecting an item. The fact that the focusser is always focused
after selecting an item is especially problematic on mobile devices,
since this leads to the keyboard being shown, which might not be
desirable.

This commit provides the skip-focusser option to configure this
behavior on the ui-select directive.

Fixes #869, #401, #818, #603, #432 (partially)
  • Loading branch information
excentris committed Mar 13, 2016
1 parent abf16f9 commit 302e80f
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ var uis = angular.module('ui.select', [])
placeholder: '', // Empty by default, like HTML tag <select>
refreshDelay: 1000, // In milliseconds
closeOnSelect: true,
skipFocusser: false,
dropdownPosition: 'auto',
generateId: function() {
return latestId++;
Expand Down
4 changes: 2 additions & 2 deletions src/uiSelectChoicesDirective.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ uis.directive('uiSelectChoices',
.attr('ng-if', '$select.open'); //Prevent unnecessary watches when dropdown is closed
if ($window.document.addEventListener) { //crude way to exclude IE8, specifically, which also cannot capture events
choices.attr('ng-mouseenter', '$select.setActiveItem('+$select.parserResult.itemName +')')
.attr('ng-click', '$select.select(' + $select.parserResult.itemName + ',false,$event)');
.attr('ng-click', '$select.select(' + $select.parserResult.itemName + ',$select.skipFocusser,$event)');
}

var rowsInner = element.querySelectorAll('.ui-select-choices-row-inner');
if (rowsInner.length !== 1) throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row-inner but got '{0}'.", rowsInner.length);
rowsInner.attr('uis-transclude-append', ''); //Adding uisTranscludeAppend directive to row element after choices element has ngRepeat
if (!$window.document.addEventListener) { //crude way to target IE8, specifically, which also cannot capture events - so event bindings must be here
rowsInner.attr('ng-mouseenter', '$select.setActiveItem('+$select.parserResult.itemName +')')
.attr('ng-click', '$select.select(' + $select.parserResult.itemName + ',false,$event)');
.attr('ng-click', '$select.select(' + $select.parserResult.itemName + ',$select.skipFocusser,$event)');
}

$compile(element, transcludeFn)(scope); //Passing current transcludeFn to be able to append elements correctly from uisTranscludeAppend
Expand Down
3 changes: 2 additions & 1 deletion src/uiSelectController.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ uis.controller('uiSelectCtrl',

ctrl.removeSelected = false; //If selected item(s) should be removed from dropdown list
ctrl.closeOnSelect = true; //Initialized inside uiSelect directive link function
ctrl.skipFocusser = false; //Set to true to avoid returning focus to ctrl when item is selected
ctrl.search = EMPTY_SEARCH;

ctrl.activeIndex = 0; //Dropdown of choices
Expand Down Expand Up @@ -476,7 +477,7 @@ uis.controller('uiSelectCtrl',
break;
case KEY.ENTER:
if(ctrl.open && (ctrl.tagging.isActivated || ctrl.activeIndex >= 0)){
ctrl.select(ctrl.items[ctrl.activeIndex]); // Make sure at least one dropdown item is highlighted before adding if not in tagging mode
ctrl.select(ctrl.items[ctrl.activeIndex], ctrl.skipFocusser); // Make sure at least one dropdown item is highlighted before adding if not in tagging mode
} else {
ctrl.activate(false, true); //In case its the search input in 'multiple' mode
}
Expand Down
19 changes: 14 additions & 5 deletions src/uiSelectDirective.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ uis.directive('uiSelect',
}
}();

scope.$watch('skipFocusser', function() {
var skipFocusser = scope.$eval(attrs.skipFocusser);
$select.skipFocusser = skipFocusser !== undefined ? skipFocusser : uiSelectConfig.skipFocusser;
});

$select.onSelectCallback = $parse(attrs.onSelect);
$select.onRemoveCallback = $parse(attrs.onRemove);

Expand Down Expand Up @@ -162,11 +167,15 @@ uis.directive('uiSelect',
}

if (!contains && !$select.clickTriggeredSelect) {
//Will lose focus only with certain targets
var focusableControls = ['input','button','textarea','select'];
var targetController = angular.element(e.target).controller('uiSelect'); //To check if target is other ui-select
var skipFocusser = targetController && targetController !== $select; //To check if target is other ui-select
if (!skipFocusser) skipFocusser = ~focusableControls.indexOf(e.target.tagName.toLowerCase()); //Check if target is input, button or textarea
if (!$select.skipFocusser) {
//Will lose focus only with certain targets
var focusableControls = ['input','button','textarea','select'];
var targetController = angular.element(e.target).controller('uiSelect'); //To check if target is other ui-select
var skipFocusser = targetController && targetController !== $select; //To check if target is other ui-select
if (!skipFocusser) skipFocusser = ~focusableControls.indexOf(e.target.tagName.toLowerCase()); //Check if target is input, button or textarea
} else {
skipFocusser = true;
}
$select.close(skipFocusser);
scope.$digest();
}
Expand Down

0 comments on commit 302e80f

Please sign in to comment.