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

Commit 920018e

Browse files
committed
fix(list): primary action is fired twice on space/enter keydown
- disable keydown handler added by ng-aria - fix doc and comment typos - fix md-menu example not rendering - rename `copyAttributes` to `moveAttributes` as the attribute are removed from the source - improve JSDoc Fixes #11756
1 parent ef9a589 commit 920018e

File tree

1 file changed

+38
-24
lines changed

1 file changed

+38
-24
lines changed

src/components/list/list.js

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ function mdListDirective($mdTheming) {
154154
* The recognized `md-switch` will toggle its state, when the user clicks on the `md-list-item`.
155155
*
156156
* It is also possible to have a `md-menu` inside of a `md-list-item`.
157+
*
157158
* <hljs lang="html">
158159
* <md-list-item>
159160
* <p>Click anywhere to fire the secondary action</p>
@@ -185,12 +186,13 @@ function mdListDirective($mdTheming) {
185186
*
186187
* The menu will automatically open, when the users clicks on the `md-list-item`.<br/>
187188
*
188-
* If the developer didn't specify any position mode on the menu, the `md-list-item` will automatically detect the
189-
* position mode and applies it to the `md-menu`.
189+
* If the developer didn't specify any position mode on the menu, the `md-list-item` will
190+
* automatically detect the position mode and apply it to the `md-menu`.
190191
*
191192
* ### Avatars
192-
* Sometimes you may want to have some avatars inside of the `md-list-item `.<br/>
193-
* You are able to create a optimized icon for the list item, by applying the `.md-avatar` class on the `<img>` element.
193+
* Sometimes you may want to have avatars inside of the `md-list-item `.<br/>
194+
* You are able to create an optimized icon for the list item, by applying the `.md-avatar` class on
195+
* the `<img>` element.
194196
*
195197
* <hljs lang="html">
196198
* <md-list-item>
@@ -199,15 +201,16 @@ function mdListDirective($mdTheming) {
199201
* </hljs>
200202
*
201203
* When using `<md-icon>` for an avatar, you have to use the `.md-avatar-icon` class.
204+
*
202205
* <hljs lang="html">
203206
* <md-list-item>
204207
* <md-icon class="md-avatar-icon" md-svg-icon="social:person"></md-icon>
205208
* <span>Timothy Kopra</span>
206209
* </md-list-item>
207210
* </hljs>
208211
*
209-
* In cases, you have a `md-list-item`, which doesn't have any avatar,
210-
* but you want to align it with the other avatar items, you have to use the `.md-offset` class.
212+
* In cases where you have a `md-list-item`, which doesn't have an avatar,
213+
* but you want to align it with the other avatar items, you need to use the `.md-offset` class.
211214
*
212215
* <hljs lang="html">
213216
* <md-list-item class="md-offset">
@@ -220,7 +223,7 @@ function mdListDirective($mdTheming) {
220223
*
221224
* ---
222225
* If the `md-list-item` is clickable, we wrap all content inside of a `<div>` and create
223-
* an overlaying button, which will will execute the given actions (like `ng-href`, `ng-click`)
226+
* an overlaying button, which will will execute the given actions (like `ng-href`, `ng-click`).
224227
*
225228
* We create an overlaying button, instead of wrapping all content inside of the button,
226229
* because otherwise some elements may not be clickable inside of the button.
@@ -344,7 +347,7 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
344347
'<md-button class="md-no-style"></md-button>'
345348
);
346349

347-
copyAttributes(tElement[0], buttonWrap[0]);
350+
moveAttributes(tElement[0], buttonWrap[0]);
348351

349352
// If there is no aria-label set on the button (previously copied over if present)
350353
// we determine the label from the content and copy it to the button.
@@ -353,13 +356,14 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
353356
}
354357

355358
// We allow developers to specify the `md-no-focus` class, to disable the focus style
356-
// on the button executor. Once more classes should be forwarded, we should probably make the
357-
// class forward more generic.
359+
// on the button executor. Once more classes should be forwarded, we should probably make
360+
// the class forward more generic.
358361
if (tElement.hasClass('md-no-focus')) {
359362
buttonWrap.addClass('md-no-focus');
360363
}
361364

362-
// Append the button wrap before our list-item content, because it will overlay in relative.
365+
// Append the button wrap before our list-item content, because it will overlay in
366+
// relative.
363367
itemContainer.prepend(buttonWrap);
364368
itemContainer.children().eq(1).append(tElement.contents());
365369

@@ -392,10 +396,10 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
392396
$mdAria.expect(secondaryItem, 'aria-label');
393397
var buttonWrapper = angular.element('<md-button class="md-secondary md-icon-button">');
394398

395-
// Copy the attributes from the secondary item to the generated button.
399+
// Move the attributes from the secondary item to the generated button.
396400
// We also support some additional attributes from the secondary item,
397401
// because some developers may use a ngIf, ngHide, ngShow on their item.
398-
copyAttributes(secondaryItem, buttonWrapper[0], ['ng-if', 'ng-hide', 'ng-show']);
402+
moveAttributes(secondaryItem, buttonWrapper[0], ['ng-if', 'ng-hide', 'ng-show']);
399403

400404
secondaryItem.setAttribute('tabindex', '-1');
401405
buttonWrapper.append(secondaryItem);
@@ -416,14 +420,14 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
416420
}
417421

418422
/**
419-
* Copies attributes from a source element to the destination element
420-
* By default the function will copy the most necessary attributes, supported
423+
* Moves attributes from a source element to the destination element.
424+
* By default, the function will copy the most necessary attributes, supported
421425
* by the button executor for clickable list items.
422426
* @param source Element with the specified attributes
423-
* @param destination Element which will retrieve the attributes
424-
* @param extraAttrs Additional attributes, which will be copied over.
427+
* @param destination Element which will receive the attributes
428+
* @param extraAttrs Additional attributes, which will be moved over
425429
*/
426-
function copyAttributes(source, destination, extraAttrs) {
430+
function moveAttributes(source, destination, extraAttrs) {
427431
var copiedAttrs = $mdUtil.prefixer([
428432
'ng-if', 'ng-click', 'ng-dblclick', 'aria-label', 'ng-disabled', 'ui-sref',
429433
'href', 'ng-href', 'rel', 'target', 'ng-attr-ui-sref', 'ui-sref-opts', 'download'
@@ -466,7 +470,9 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
466470
function hasClickEvent(element) {
467471
var attr = element.attributes;
468472
for (var i = 0; i < attr.length; i++) {
469-
if (tAttrs.$normalize(attr[i].name) === 'ngClick') return true;
473+
if (tAttrs.$normalize(attr[i].name) === 'ngClick') {
474+
return true;
475+
}
470476
}
471477
return false;
472478
}
@@ -555,14 +561,19 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
555561
return false;
556562
}
557563

558-
var clickChildKeypressListener = function(e) {
559-
if (e.target.nodeName !== 'INPUT' && e.target.nodeName !== 'TEXTAREA' && !e.target.isContentEditable) {
560-
var keyCode = e.which || e.keyCode;
564+
/**
565+
* @param {KeyboardEvent} keypressEvent
566+
*/
567+
var clickChildKeypressListener = function(keypressEvent) {
568+
if (keypressEvent.target.nodeName !== 'INPUT' &&
569+
keypressEvent.target.nodeName !== 'TEXTAREA' &&
570+
!keypressEvent.target.isContentEditable) {
571+
var keyCode = keypressEvent.which || keypressEvent.keyCode;
561572
if (keyCode === $mdConstant.KEY_CODE.SPACE) {
562573
if (clickChild) {
563574
clickChild.click();
564-
e.preventDefault();
565-
e.stopPropagation();
575+
keypressEvent.preventDefault();
576+
keypressEvent.stopPropagation();
566577
}
567578
}
568579
}
@@ -574,6 +585,9 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
574585

575586
$element.off('click');
576587
$element.off('keypress');
588+
// Disable ng-aria's "helpful" keydown event that causes our ng-click handlers to be called
589+
// twice.
590+
$element.off('keydown');
577591

578592
if (proxies.length === 1 && clickChild) {
579593
$element.children().eq(0).on('click', function(clickEvent) {

0 commit comments

Comments
 (0)