Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 703f2c8

Browse files
topherfangioThomasBurleson
authored andcommitted
fix(mdChips): Backspace key and custom input focus/blur.
* Fix backspace key in Firefox to not change browser history/url In Firefox, the backspace key would also modify the browser's history/url. * Fix focus/blur on chips with custom input: Chips with a custom input did not properly update it's class list when the inner input was focused/blurred. Fixes #3562. Fixes #3960. Fixes #2607. Closes #4359.
1 parent f2e6b16 commit 703f2c8

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

src/components/chips/chips.spec.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,58 @@ describe('<md-chips>', function() {
217217
expect(scope.appendChip).toHaveBeenCalled();
218218
expect(scope.appendChip.calls.mostRecent().args[0]).toBe('Apple');
219219
});
220+
221+
it('should prevent the default when backspace is pressed', inject(function($mdConstant) {
222+
var element = buildChips(BASIC_CHIP_TEMPLATE);
223+
var ctrl = element.controller('mdChips');
224+
225+
var backspaceEvent = {
226+
type: 'keydown',
227+
keyCode: $mdConstant.KEY_CODE.BACKSPACE,
228+
which: $mdConstant.KEY_CODE.BACKSPACE,
229+
preventDefault: jasmine.createSpy('preventDefault')
230+
};
231+
232+
element.find('input').triggerHandler(backspaceEvent);
233+
234+
expect(backspaceEvent.preventDefault).toHaveBeenCalled();
235+
}));
236+
237+
describe('with input text', function() {
238+
239+
it('should prevent the default when enter is pressed', inject(function($mdConstant) {
240+
var element = buildChips(BASIC_CHIP_TEMPLATE);
241+
var ctrl = element.controller('mdChips');
242+
243+
var enterEvent = {
244+
type: 'keydown',
245+
keyCode: $mdConstant.KEY_CODE.ENTER,
246+
which: $mdConstant.KEY_CODE.ENTER,
247+
preventDefault: jasmine.createSpy('preventDefault')
248+
};
249+
250+
ctrl.chipBuffer = 'Test';
251+
element.find('input').triggerHandler(enterEvent);
252+
253+
expect(enterEvent.preventDefault).toHaveBeenCalled();
254+
}));
255+
});
256+
257+
it('focuses/blurs the component when focusing/blurring the input', inject(function() {
258+
var element = buildChips(BASIC_CHIP_TEMPLATE);
259+
var ctrl = element.controller('mdChips');
260+
261+
// Focus the input and check
262+
element.find('input').triggerHandler('focus');
263+
expect(ctrl.inputHasFocus).toBe(true);
264+
expect(element.find('md-chips-wrap').hasClass('md-focused')).toBe(true);
265+
266+
// Blur the input and check
267+
element.find('input').triggerHandler('blur');
268+
expect(ctrl.inputHasFocus).toBe(false);
269+
expect(element.find('md-chips-wrap').hasClass('md-focused')).toBe(false);
270+
}));
271+
220272
});
221273

222274
describe('custom inputs', function() {
@@ -264,6 +316,24 @@ describe('<md-chips>', function() {
264316
<input type="text">\
265317
</md-chips>';
266318

319+
it('focuses/blurs the component when focusing/blurring the input', inject(function($timeout) {
320+
var element = buildChips(INPUT_TEMPLATE);
321+
var ctrl = element.controller('mdChips');
322+
$timeout.flush();
323+
324+
// Focus the input and check
325+
element.find('input').triggerHandler('focus');
326+
$timeout.flush();
327+
expect(ctrl.inputHasFocus).toBe(true);
328+
expect(element.find('md-chips-wrap').hasClass('md-focused')).toBe(true);
329+
330+
// Blur the input and check
331+
element.find('input').triggerHandler('blur');
332+
$timeout.flush();
333+
expect(ctrl.inputHasFocus).toBe(false);
334+
expect(element.find('md-chips-wrap').hasClass('md-focused')).toBe(false);
335+
}));
336+
267337
describe('using ngModel', function() {
268338
it('should add the ngModelCtrl.$viewValue when <enter> is pressed',
269339
inject(function($timeout) {

src/components/chips/js/chipsController.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ function MdChipsCtrl ($scope, $mdConstant, $log, $element, $timeout) {
9292
*/
9393
MdChipsCtrl.prototype.inputKeydown = function(event) {
9494
var chipBuffer = this.getChipBuffer();
95+
9596
switch (event.keyCode) {
9697
case this.$mdConstant.KEY_CODE.ENTER:
9798
if ((this.hasAutocomplete && this.requireMatch) || !chipBuffer) break;
@@ -101,6 +102,7 @@ MdChipsCtrl.prototype.inputKeydown = function(event) {
101102
break;
102103
case this.$mdConstant.KEY_CODE.BACKSPACE:
103104
if (chipBuffer) break;
105+
event.preventDefault();
104106
event.stopPropagation();
105107
if (this.items.length) this.selectAndFocusChipSafe(this.items.length - 1);
106108
break;
@@ -373,14 +375,20 @@ MdChipsCtrl.prototype.configureUserInput = function(inputElement) {
373375
this.userInputNgModelCtrl = ngModelCtrl;
374376
}
375377

376-
// Bind to keydown and focus events of input
377378
var scope = this.$scope;
378379
var ctrl = this;
380+
381+
// Run all of the events using evalAsync because a focus may fire a blur in the same digest loop
382+
var scopeApplyFn = function(event, fn) {
383+
scope.$evalAsync(angular.bind(ctrl, fn, event));
384+
};
385+
386+
// Bind to keydown and focus events of input
379387
inputElement
380388
.attr({ tabindex: 0 })
381-
.on('keydown', function(event) { scope.$apply( angular.bind(ctrl, function() { ctrl.inputKeydown(event); })) })
382-
.on('focus', angular.bind(ctrl, ctrl.onInputFocus))
383-
.on('blur', angular.bind(ctrl, ctrl.onInputBlur));
389+
.on('keydown', function(event) { scopeApplyFn(event, ctrl.inputKeydown) })
390+
.on('focus', function(event) { scopeApplyFn(event, ctrl.onInputFocus) })
391+
.on('blur', function(event) { scopeApplyFn(event, ctrl.onInputBlur) })
384392
};
385393

386394
MdChipsCtrl.prototype.configureAutocomplete = function(ctrl) {

0 commit comments

Comments
 (0)