diff --git a/build/ng-tags-input.css b/build/ng-tags-input.css index 6ae3d4ff..09700f8c 100644 --- a/build/ng-tags-input.css +++ b/build/ng-tags-input.css @@ -26,6 +26,13 @@ font-size: 14px; } +.ngTagsInput .tags.focused { + outline: none; + -webkit-box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); + -moz-box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); + box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); +} + .ngTagsInput .tags ul { margin: 0px; padding: 0px; diff --git a/build/ng-tags-input.js b/build/ng-tags-input.js index c4ccab26..d97f933b 100644 --- a/build/ng-tags-input.js +++ b/build/ng-tags-input.js @@ -69,7 +69,7 @@ angular.module('tags-input').directive('tagsInput', ["$timeout","$document","con replace: false, transclude: true, template: '
' + - '
' + + '
' + '
    ' + '
  • ' + ' {{ tag }}' + @@ -237,17 +237,24 @@ angular.module('tags-input').directive('tagsInput', ["$timeout","$document","con } } }) - .on('blur', function() { - if (!scope.options.addOnBlur) { + .on('focus', function() { + if (scope.hasFocus) { return; } - + scope.hasFocus = true; + scope.$apply(); + }) + .on('blur', function() { $timeout(function() { var parentElement = angular.element($document[0].activeElement).parent(); - if (parentElement[0] !== element[0] && scope.tryAdd()) { + if (parentElement[0] !== element[0]) { + scope.hasFocus = false; + if (scope.options.addOnBlur) { + scope.tryAdd(); + } scope.$apply(); } - }, 0); + }, 0, false); }); element.find('div').on('click', function() { diff --git a/build/ng-tags-input.min.zip b/build/ng-tags-input.min.zip index 7af94720..ea009b44 100644 Binary files a/build/ng-tags-input.min.zip and b/build/ng-tags-input.min.zip differ diff --git a/build/ng-tags-input.zip b/build/ng-tags-input.zip index 4cc27618..ae14e629 100644 Binary files a/build/ng-tags-input.zip and b/build/ng-tags-input.zip differ diff --git a/css/tags-input.css b/css/tags-input.css index 40fd4bcc..30d1b0bd 100644 --- a/css/tags-input.css +++ b/css/tags-input.css @@ -26,6 +26,13 @@ font-size: 14px; } +.ngTagsInput .tags.focused { + outline: none; + -webkit-box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); + -moz-box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); + box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); +} + .ngTagsInput .tags ul { margin: 0px; padding: 0px; diff --git a/src/tags-input.js b/src/tags-input.js index b61d9c6d..cc32cf3b 100644 --- a/src/tags-input.js +++ b/src/tags-input.js @@ -58,7 +58,7 @@ angular.module('tags-input').directive('tagsInput', function($timeout, $document replace: false, transclude: true, template: '
    ' + - '
    ' + + '
    ' + '
      ' + '
    • ' + ' {{ tag }}' + @@ -226,17 +226,24 @@ angular.module('tags-input').directive('tagsInput', function($timeout, $document } } }) - .on('blur', function() { - if (!scope.options.addOnBlur) { + .on('focus', function() { + if (scope.hasFocus) { return; } - + scope.hasFocus = true; + scope.$apply(); + }) + .on('blur', function() { $timeout(function() { var parentElement = angular.element($document[0].activeElement).parent(); - if (parentElement[0] !== element[0] && scope.tryAdd()) { + if (parentElement[0] !== element[0]) { + scope.hasFocus = false; + if (scope.options.addOnBlur) { + scope.tryAdd(); + } scope.$apply(); } - }, 0); + }, 0, false); }); element.find('div').on('click', function() { diff --git a/test/tags-input.spec.js b/test/tags-input.spec.js index 8a96ac44..f99bb648 100644 --- a/test/tags-input.spec.js +++ b/test/tags-input.spec.js @@ -151,6 +151,77 @@ describe('tags-input-directive', function() { expect(element.find('div').hasClass('myClass')).toBe(true); }); }); + + describe('focus outline', function() { + beforeEach(function() { + compile(); + }); + + it('outlines the tags div when the focused property is true', function() { + // Arrange + isolateScope.hasFocus = true; + + // Act + $scope.$digest(); + + // Assert + expect(element.find('div.tags').hasClass('focused')).toBe(true); + }); + + it('does not outline the tags div when the focused property is false', function() { + // Arrange + isolateScope.hasFocus = false; + + // Act + $scope.$digest(); + + // Assert + expect(element.find('div.tags').hasClass('focused')).toBe(false); + }); + + it('sets the focused property to true when the input field gains focus', function() { + // Arrange + isolateScope.hasFocus = false; + spyOn($scope, '$digest'); + + // Act + getInput().triggerHandler('focus'); + + // Assert + expect(isolateScope.hasFocus).toBe(true); + expect($scope.$digest).toHaveBeenCalled(); + }); + + it('sets the focused property to false when the input field loses focus', function() { + // Arrange + var body = $document.find('body'); + body.append(element); + body.focus(); + + isolateScope.hasFocus = true; + spyOn($scope, '$digest'); + + // Act + getInput().triggerHandler('blur'); + $timeout.flush(); + + // Assert + expect(isolateScope.hasFocus).toBe(false); + expect($scope.$digest).toHaveBeenCalled(); + }); + + it('does not trigger a digest cycle when the input field is focused already', function() { + // Arrange + isolateScope.hasFocus = true; + spyOn($scope, '$digest'); + + // Act + getInput().triggerHandler('focus'); + + // Assert + expect($scope.$digest).not.toHaveBeenCalled(); + }); + }); describe('tabindex option', function() { it('sets the input field tab index', function() { @@ -371,24 +442,22 @@ describe('tags-input-directive', function() { }); describe('option is true', function() { - var anotherElement; + var body; beforeEach(function() { compile('add-on-blur="true"'); - anotherElement = angular.element('
      '); - $document.find('body') - .append(element) - .append(anotherElement); + body = $document.find('body'); + body.append(element); }); it('adds a tag when the input field loses focus to any element on the page but the directive itself', function() { // Arrange isolateScope.newTag = 'foo'; - anotherElement[0].focus(); + body.focus(); // Act - getInput().trigger('blur'); + getInput().triggerHandler('blur'); $timeout.flush(); // Assert @@ -398,10 +467,10 @@ describe('tags-input-directive', function() { it('does not add a tag when the input field loses focus to the directive itself', function() { // Arrange isolateScope.newTag = 'foo'; - element.find('div')[0].focus(); + element.find('div').focus(); // Act - getInput().trigger('blur'); + getInput().triggerHandler('blur'); $timeout.flush(); // Assert @@ -416,7 +485,7 @@ describe('tags-input-directive', function() { isolateScope.newTag = 'foo'; // Act - getInput().trigger('blur'); + getInput().triggerHandler('blur'); // Assert expect($scope.tags).toEqual([]); diff --git a/test/test-page.html b/test/test-page.html index d07a3dc0..35a955c1 100644 --- a/test/test-page.html +++ b/test/test-page.html @@ -10,7 +10,7 @@ + add-on-blur="true">