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

Commit b9d8322

Browse files
committed
fix(select): menuController not defined edge case in focusOptionNode
- Handle edge cases where the `selectMenuController` has been destroyed - or is an `{}` rather than a controller - remove unused selectController argument to `focusOptionNode()` Fixes #11885
1 parent 5c75b12 commit b9d8322

File tree

2 files changed

+40
-31
lines changed

2 files changed

+40
-31
lines changed
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
(function () {
22
'use strict';
33
angular
4-
.module('selectDemoBasic', ['ngMaterial'])
5-
.controller('AppCtrl', function() {
6-
this.userState = '';
7-
this.states = ('AL AK AZ AR CA CO CT DE FL GA HI ID IL IN IA KS KY LA ME MD MA MI MN MS ' +
8-
'MO MT NE NV NH NJ NM NY NC ND OH OK OR PA RI SC SD TN TX UT VT VA WA WV WI ' +
9-
'WY').split(' ').map(function (state) { return { abbrev: state }; });
10-
});
4+
.module('selectDemoBasic', ['ngMaterial'])
5+
.controller('AppCtrl', function() {
6+
var ctrl = this;
7+
ctrl.userState = '';
8+
ctrl.states = ('AL AK AZ AR CA CO CT DE FL GA HI ID IL IN IA KS KY LA ME MD MA MI MN MS ' +
9+
'MO MT NE NV NH NJ NM NY NC ND OH OK OR PA RI SC SD TN TX UT VT VA WA WV WI ' +
10+
'WY').split(' ').map(function (state) { return { abbrev: state }; });
11+
});
1112
})();

src/components/select/select.js

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
690690
element.on('keypress', keyListener);
691691

692692
function keyListener(e) {
693-
if (e.keyCode == 13 || e.keyCode == 32) {
693+
if (e.keyCode === 13 || e.keyCode === 32) {
694694
clickListener(e);
695695
}
696696
}
@@ -796,10 +796,10 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
796796
};
797797

798798
/**
799-
* @param {KeyboardEvent} e keyboard event to handle
800-
* @return {DOMElement|HTMLElement|undefined}
799+
* @param {KeyboardEvent} keyboardEvent keyboard event to handle
800+
* @return {Element|HTMLElement|undefined}
801801
*/
802-
self.optNodeForKeyboardSearch = function(e) {
802+
self.optNodeForKeyboardSearch = function(keyboardEvent) {
803803
var search, i;
804804
clearSearchTimeout && clearTimeout(clearSearchTimeout);
805805
clearSearchTimeout = setTimeout(function() {
@@ -809,7 +809,7 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
809809
optNodes = undefined;
810810
}, CLEAR_SEARCH_AFTER);
811811

812-
searchStr += e.key;
812+
searchStr += keyboardEvent.key;
813813
search = new RegExp('^' + $mdUtil.sanitize(searchStr), 'i');
814814
if (!optNodes) {
815815
optNodes = $element.find('md-option');
@@ -818,12 +818,12 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
818818
optText[i] = el.textContent.trim();
819819
});
820820
}
821+
821822
for (i = 0; i < optText.length; ++i) {
822823
if (search.test(optText[i])) {
823824
return optNodes[i];
824825
}
825826
}
826-
827827
};
828828

829829
self.init = function(ngModel, binding) {
@@ -1523,6 +1523,7 @@ function SelectProvider($$interimElementProvider) {
15231523

15241524
/**
15251525
* Initialize container and dropDown menu positions/scale, then animate to show.
1526+
* @return {*} a Promise that resolves after the menu is animated in and an item is focused
15261527
*/
15271528
function positionAndFocusMenu() {
15281529
return $q(function(resolve) {
@@ -1576,12 +1577,11 @@ function SelectProvider($$interimElementProvider) {
15761577
}
15771578

15781579
/**
1579-
* @param {DOMElement|HTMLElement|null=} previousNode
1580-
* @param {DOMElement|HTMLElement} node
1581-
* @param {SelectMenuController|Function} menuController SelectMenuController instance
1582-
* @param {Function|*} selectController SelectController instance
1580+
* @param {Element|HTMLElement|null=} previousNode
1581+
* @param {Element|HTMLElement} node
1582+
* @param {SelectMenuController|Function|Object=} menuController SelectMenuController instance
15831583
*/
1584-
function focusOptionNode(previousNode, node, menuController, selectController) {
1584+
function focusOptionNode(previousNode, node, menuController) {
15851585
var listboxContentNode = opts.contentEl[0];
15861586

15871587
if (node) {
@@ -1590,7 +1590,9 @@ function SelectProvider($$interimElementProvider) {
15901590
}
15911591

15921592
node.classList.add('md-focused');
1593-
menuController.setActiveDescendant(node.id);
1593+
if (menuController && menuController.setActiveDescendant) {
1594+
menuController.setActiveDescendant(node.id);
1595+
}
15941596

15951597
// Scroll the node into view if needed.
15961598
if (listboxContentNode.scrollHeight > listboxContentNode.clientHeight) {
@@ -1603,18 +1605,20 @@ function SelectProvider($$interimElementProvider) {
16031605
}
16041606
}
16051607
opts.focusedNode = node;
1606-
menuController.refreshViewValue();
1608+
if (menuController && menuController.refreshViewValue) {
1609+
menuController.refreshViewValue();
1610+
}
16071611
}
16081612
}
16091613

16101614
/**
1611-
* @param {DOMElement|HTMLElement} nodeToFocus
1615+
* @param {Element|HTMLElement} nodeToFocus
16121616
*/
16131617
function autoFocus(nodeToFocus) {
16141618
var selectMenuController;
16151619
if (nodeToFocus && !nodeToFocus.hasAttribute('disabled')) {
16161620
selectMenuController = opts.selectEl.controller('mdSelectMenu');
1617-
focusOptionNode(null, nodeToFocus, selectMenuController, opts.selectCtrl);
1621+
focusOptionNode(null, nodeToFocus, selectMenuController);
16181622
}
16191623
}
16201624

@@ -1757,7 +1761,7 @@ function SelectProvider($$interimElementProvider) {
17571761
if (shouldHandleKey(ev, $mdConstant)) {
17581762
var optNode = selectMenuController.optNodeForKeyboardSearch(ev);
17591763
if (optNode && !optNode.hasAttribute('disabled')) {
1760-
focusOptionNode(opts.focusedNode, optNode, selectMenuController, opts.selectCtrl);
1764+
focusOptionNode(opts.focusedNode, optNode, selectMenuController);
17611765
}
17621766
}
17631767
}
@@ -1790,7 +1794,7 @@ function SelectProvider($$interimElementProvider) {
17901794
}
17911795
} while (!newOption && index < optionsArray.length - 1 && index > 0);
17921796

1793-
focusOptionNode(prevOption, newOption, selectMenuController, opts.selectCtrl);
1797+
focusOptionNode(prevOption, newOption, selectMenuController);
17941798
}
17951799

17961800
function focusNextOption() {
@@ -1801,8 +1805,11 @@ function SelectProvider($$interimElementProvider) {
18011805
focusOption('prev');
18021806
}
18031807

1804-
function checkCloseMenu(ev) {
1805-
if (ev && (ev.type === 'click') && (ev.currentTarget != dropDown[0])) {
1808+
/**
1809+
* @param {KeyboardEvent|MouseEvent} event
1810+
*/
1811+
function checkCloseMenu(event) {
1812+
if (event && (event.type === 'click') && (event.currentTarget !== dropDown[0])) {
18061813
return;
18071814
}
18081815
if (mouseOnScrollbar()) {
@@ -1811,8 +1818,8 @@ function SelectProvider($$interimElementProvider) {
18111818

18121819
if (opts.focusedNode && opts.focusedNode.hasAttribute &&
18131820
!opts.focusedNode.hasAttribute('disabled')) {
1814-
ev.preventDefault();
1815-
ev.stopPropagation();
1821+
event.preventDefault();
1822+
event.stopPropagation();
18161823
if (!selectMenuController.isMultiple) {
18171824
opts.restoreFocus = true;
18181825

@@ -1821,16 +1828,17 @@ function SelectProvider($$interimElementProvider) {
18211828
}, true);
18221829
}
18231830
}
1831+
18241832
/**
18251833
* check if the mouseup event was on a scrollbar
18261834
*/
18271835
function mouseOnScrollbar() {
18281836
var clickOnScrollbar = false;
1829-
if (ev && (ev.currentTarget.children.length > 0)) {
1830-
var child = ev.currentTarget.children[0];
1837+
if (event && (event.currentTarget.children.length > 0)) {
1838+
var child = event.currentTarget.children[0];
18311839
var hasScrollbar = child.scrollHeight > child.clientHeight;
18321840
if (hasScrollbar && child.children.length > 0) {
1833-
var relPosX = ev.pageX - ev.currentTarget.getBoundingClientRect().left;
1841+
var relPosX = event.pageX - event.currentTarget.getBoundingClientRect().left;
18341842
if (relPosX > child.querySelector('md-option').offsetWidth)
18351843
clickOnScrollbar = true;
18361844
}

0 commit comments

Comments
 (0)