Tag Complete directive has proper focus behavior

The wrapper around the tag-complete method has been taught to delegate
its focus method to the encapsulated <input>, and an additional class
was added to apply the bootstrap-highlight-focus style to the control.
Note that to properly respond to tab focus, we have to explicitly issue
a $digest() after both focus(added) and blur(already there).

Change-Id: I488140abeebaa2b0d8d484058f2f96590cb8ca24
This commit is contained in:
Michael Krotscheck 2014-06-27 07:53:35 -07:00
parent d9f729b792
commit 6f72378cca
3 changed files with 35 additions and 10 deletions

View File

@ -19,13 +19,13 @@
* set of source data, and restricts inputs to items in that list.
*/
angular.module('sb.util').directive('tagComplete',
function ($q, $parse, $position, typeaheadParser) {
function ($q, $parse, $rootScope, $position, typeaheadParser) {
'use strict';
var HOT_KEYS = [9, 13, 27, 38, 40];
return {
restrict: 'EAo',
restrict: 'EA',
replace: true,
scope: {
tagCompleteTags: '=',
@ -43,6 +43,14 @@ angular.module('sb.util').directive('tagComplete',
*/
var $input = $element.find('input');
/**
* Override the element's focus method, use it to focus our
* input instead.
*/
$element[0].focus = function () {
$input[0].focus();
};
/**
* The typeahead query parser, used for our selection syntax.
*/
@ -72,7 +80,7 @@ angular.module('sb.util').directive('tagComplete',
* Are we focused?
* @type {Boolean}
*/
var hasFocus = false;
$scope.hasFocus = false;
/**
* Reset the matches on the scope.
@ -89,7 +97,7 @@ angular.module('sb.util').directive('tagComplete',
*/
var getMatchesAsync = function (inputValue) {
if (!hasFocus || !inputValue) {
if (!$scope.hasFocus || !inputValue) {
return;
}
@ -103,7 +111,8 @@ angular.module('sb.util').directive('tagComplete',
// Make sure that the returned query equals what's
// currently being searched for: It could be that
// we have multiple queries in flight...
if (inputValue === $scope.newTagName && hasFocus) {
if (inputValue === $scope.newTagName &&
$scope.hasFocus) {
// Transform Matches
$scope.matches = [];
@ -146,7 +155,10 @@ angular.module('sb.util').directive('tagComplete',
* Focus when the input gets focus.
*/
$input.on('focus', function () {
hasFocus = true;
$scope.hasFocus = true;
if (!$rootScope.$$phase) {
$scope.$digest();
}
});
/**
@ -155,8 +167,10 @@ angular.module('sb.util').directive('tagComplete',
$input.on('blur', function () {
resetMatches();
$scope.newTagName = '';
hasFocus = false;
$scope.$digest();
$scope.hasFocus = false;
if (!$rootScope.$$phase) {
$scope.$digest();
}
});
/**
@ -203,7 +217,6 @@ angular.module('sb.util').directive('tagComplete',
selectedTags.pop();
return true;
}
// return false;
};
/**

View File

@ -1,4 +1,5 @@
<div>
<div class="tag-complete"
ng-class="{'focused': hasFocus}">
<div class="form-control tag-input"
ng-click="focus()">
<span ng-repeat="tag in tagCompleteTags track by $index"

View File

@ -131,4 +131,15 @@
border-radius: (@border-radius-small - 1);
}
}
}
.tag-complete {
&.focused {
.form-control.tag-input {
@color-rgba: rgba(red(@input-border-focus), green(@input-border-focus), blue(@input-border-focus), .6);
border-color: @input-border-focus;
outline: 0;
.box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}");
}
}
}