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

Commit

Permalink
fix(list): Copy md-icon.md-secondary attributes to button.
Browse files Browse the repository at this point in the history
When an secondary md-icon was used in combination with a
checkbox, the md-icon was only copying the `ng-click` attribute
instead of all attributes including things like `ng-disabled`.

Fix by ensuring we copy all relevant attributes to the wrapper.

Fixes #3356. Closes #5716.
  • Loading branch information
topherfangio authored and ThomasBurleson committed Nov 25, 2015
1 parent 58ab379 commit 7d8bc2d
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 42 deletions.
23 changes: 13 additions & 10 deletions src/components/list/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,7 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
tEl.addClass('md-proxy-focus');
} else {
container = angular.element('<md-button class="md-no-style"><div class="md-list-item-inner"></div></md-button>');
var copiedAttrs = ['ng-click', 'aria-label', 'ng-disabled',
'ui-sref', 'href', 'ng-href', 'ng-attr-ui-sref'];
angular.forEach(copiedAttrs, function(attr) {
if (tEl[0].hasAttribute(attr)) {
container[0].setAttribute(attr, tEl[0].getAttribute(attr));
tEl[0].removeAttribute(attr);
}
});
copyAttributes(tEl[0], container[0]);
container.children().eq(0).append(tEl.contents());
}

Expand All @@ -153,8 +146,7 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
if (secondaryItem && !isButton(secondaryItem) && secondaryItem.hasAttribute('ng-click')) {
$mdAria.expect(secondaryItem, 'aria-label');
var buttonWrapper = angular.element('<md-button class="md-secondary-container md-icon-button">');
buttonWrapper.attr('ng-click', secondaryItem.getAttribute('ng-click'));
secondaryItem.removeAttribute('ng-click');
copyAttributes(secondaryItem, buttonWrapper[0]);
secondaryItem.setAttribute('tabindex', '-1');
secondaryItem.classList.remove('md-secondary');
buttonWrapper.append(secondaryItem);
Expand All @@ -172,6 +164,17 @@ function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) {
}
}

function copyAttributes(item, wrapper) {
var copiedAttrs = ['ng-click', 'aria-label', 'ng-disabled',
'ui-sref', 'href', 'ng-href', 'ng-attr-ui-sref'];
angular.forEach(copiedAttrs, function(attr) {
if (item.hasAttribute(attr)) {
wrapper.setAttribute(attr, item.getAttribute(attr));
item.removeAttribute(attr);
}
});
}

function isProxiedElement(el) {
return proxiedTypes.indexOf(el.nodeName.toLowerCase()) != -1;
}
Expand Down
79 changes: 47 additions & 32 deletions src/components/list/list.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('mdListItem directive', function() {
var $compile, $rootScope;

beforeEach(module('material.components.list', 'material.components.checkbox', 'material.components.switch'));
beforeEach(inject(function(_$compile_, _$rootScope_){
beforeEach(inject(function(_$compile_, _$rootScope_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
Expand All @@ -26,16 +26,16 @@ describe('mdListItem directive', function() {
return el;
}

it('supports empty list items',function() {
it('supports empty list items', function() {
var list = setup('\
<md-list>\
<md-list-item></md-list-item>\
</md-list>'
);
);

var cntr = list[0].querySelector('div');

if (cntr && cntr.click ) {
if (cntr && cntr.click) {
cntr.click();
expect($rootScope.modelVal).toBe(false);
}
Expand All @@ -46,7 +46,7 @@ describe('mdListItem directive', function() {
var listItem = setup('<md-list-item><md-checkbox ng-model="modelVal"></md-checkbox></md-list-item>');
var cntr = listItem[0].querySelector('div');

if (cntr && cntr.click ) {
if (cntr && cntr.click) {
cntr.click();
expect($rootScope.modelVal).toBe(true);
}
Expand All @@ -57,48 +57,48 @@ describe('mdListItem directive', function() {
var listItem = setup('<md-list-item><md-switch ng-model="modelVal"></md-switch></md-list-item>');
var cntr = listItem[0].querySelector('div');

if (cntr && cntr.click ) {
if (cntr && cntr.click) {
cntr.click();
expect($rootScope.modelVal).toBe(true);
}

});

it('should convert spacebar keypress events as clicks', inject(function($mdConstant) {
var listItem = setup('<md-list-item><md-checkbox ng-model="modelVal"></md-checkbox></md-list-item>');
var checkbox = angular.element(listItem[0].querySelector('md-checkbox'));

expect($rootScope.modelVal).toBeFalsy();
checkbox.triggerHandler({
type: 'keypress',
keyCode: $mdConstant.KEY_CODE.SPACE
});
expect($rootScope.modelVal).toBe(true);
var listItem = setup('<md-list-item><md-checkbox ng-model="modelVal"></md-checkbox></md-list-item>');
var checkbox = angular.element(listItem[0].querySelector('md-checkbox'));

expect($rootScope.modelVal).toBeFalsy();
checkbox.triggerHandler({
type: 'keypress',
keyCode: $mdConstant.KEY_CODE.SPACE
});
expect($rootScope.modelVal).toBe(true);
}));

it('should not convert spacebar keypress for text areas', inject(function($mdConstant) {
var listItem = setup('<md-list-item><textarea ng-model="modelVal"></md-list-item>');
var inputEl = angular.element(listItem[0].querySelector('textarea')[0]);

expect($rootScope.modelVal).toBeFalsy();
inputEl.triggerHandler({
type: 'keypress',
keyCode: $mdConstant.KEY_CODE.SPACE
});
expect($rootScope.modelVal).toBeFalsy();
var listItem = setup('<md-list-item><textarea ng-model="modelVal"></md-list-item>');
var inputEl = angular.element(listItem[0].querySelector('textarea')[0]);

expect($rootScope.modelVal).toBeFalsy();
inputEl.triggerHandler({
type: 'keypress',
keyCode: $mdConstant.KEY_CODE.SPACE
});
expect($rootScope.modelVal).toBeFalsy();
}));

xit('should not convert spacebar keypress for text inputs', inject(function($mdConstant) {

var listItem = setup('<md-list-item><input ng-keypress="pressed = true" type="text"></md-list-item>');
var inputEl = angular.element(listItem[0].querySelector('input')[0]);
var listItem = setup('<md-list-item><input ng-keypress="pressed = true" type="text"></md-list-item>');
var inputEl = angular.element(listItem[0].querySelector('input')[0]);

expect($rootScope.pressed).toBeFalsy();
inputEl.triggerHandler({
type: 'keypress',
keyCode: $mdConstant.KEY_CODE.SPACE
});
expect($rootScope.pressed).toBe(true);
expect($rootScope.pressed).toBeFalsy();
inputEl.triggerHandler({
type: 'keypress',
keyCode: $mdConstant.KEY_CODE.SPACE
});
expect($rootScope.pressed).toBe(true);
}));


Expand Down Expand Up @@ -157,6 +157,21 @@ describe('mdListItem directive', function() {
expect(listItem.hasClass('md-no-proxy')).toBeTruthy();
});

it('should copy md-icon.md-secondary attributes to the button', function() {
var listItem = setup(
'<md-list-item>' +
' <div>Content Here</div>' +
' <md-checkbox></md-checkbox>' +
' <md-icon class="md-secondary" ng-click="sayHello()" ng-disabled="true">Hello</md-icon>' +
'</md-list-item>'
);

var button = listItem.find('md-button');

expect(button[0].hasAttribute('ng-click')).toBeTruthy();
expect(button[0].hasAttribute('ng-disabled')).toBeTruthy();
});

describe('with a clickable item', function() {

it('should wrap secondary icons in a md-button', function() {
Expand Down

0 comments on commit 7d8bc2d

Please sign in to comment.