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

Commit

Permalink
amend(select): keep select in DOM but move to body on open
Browse files Browse the repository at this point in the history
references #6071, references #6030
  • Loading branch information
rschmukler committed Dec 8, 2015
1 parent 992d9b5 commit 90ec97c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 29 deletions.
18 changes: 13 additions & 5 deletions src/components/select/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $mdAria, $compile, $par
inputCheckValue();
};


attr.$observe('placeholder', ngModelCtrl.$render);


Expand Down Expand Up @@ -386,6 +387,10 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $mdAria, $compile, $par
if (!element[0].hasAttribute('id')) {
ariaAttrs.id = 'select_' + $mdUtil.nextUid();
}

var containerId = 'select_container_' + $mdUtil.nextUid();
selectContainer.attr('id', containerId);
ariaAttrs['aria-owns'] = containerId;
element.attr(ariaAttrs);

scope.$on('$destroy', function() {
Expand Down Expand Up @@ -419,6 +424,9 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $mdAria, $compile, $par
}
selectMenuCtrl = selectContainer.find('md-select-menu').controller('mdSelectMenu');
selectMenuCtrl.init(ngModelCtrl, attr.ngModel);
element.on('$destroy', function() {
selectContainer.remove();
});
}

function handleKeypress(e) {
Expand All @@ -442,7 +450,7 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $mdAria, $compile, $par
}
}

function openSelect(e) {
function openSelect() {
selectScope.isOpen = true;
element.attr('aria-expanded', 'true');

Expand All @@ -452,8 +460,8 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $mdAria, $compile, $par
skipCompile: true,
element: selectContainer,
target: element[0],
selectCtrl: mdSelectCtrl,
preserveElement: true,
parent: element,
hasBackdrop: true,
loadingAsync: attr.mdOnOpen ? scope.$eval(attr.mdOnOpen) || true : false
}).finally(function() {
Expand Down Expand Up @@ -1247,7 +1255,7 @@ function SelectProvider($$interimElementProvider) {
* trigger the [optional] user-defined expression
*/
function announceClosed(opts) {
var mdSelect = opts.selectEl.controller('mdSelect');
var mdSelect = opts.selectCtrl;
if (mdSelect) {
var menuController = opts.selectEl.controller('mdSelectMenu');
mdSelect.setLabelText(menuController.selectedLabels());
Expand All @@ -1262,7 +1270,7 @@ function SelectProvider($$interimElementProvider) {
function calculateMenuPositions(scope, element, opts) {
var
containerNode = element[0],
targetNode = opts.target[0].children[1], // target the label
targetNode = opts.target[0].children[0], // target the label
parentNode = $document[0].body,
selectNode = opts.selectEl[0],
contentNode = opts.contentEl[0],
Expand Down Expand Up @@ -1370,7 +1378,7 @@ function SelectProvider($$interimElementProvider) {
} else {
left = (targetRect.left + centeredRect.left - centeredRect.paddingLeft) + 2;
top = Math.floor(targetRect.top + targetRect.height / 2 - centeredRect.height / 2 -
centeredRect.top + contentNode.scrollTop) + 5;
centeredRect.top + contentNode.scrollTop) + 4;

transformOrigin = (centeredRect.left + targetRect.width / 2) + 'px ' +
(centeredRect.top + centeredRect.height / 2 - contentNode.scrollTop) + 'px 0px';
Expand Down
74 changes: 50 additions & 24 deletions src/components/select/select.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,19 @@ describe('<md-select>', function() {
var select = setupSelect('ng-model="val", md-container-class="test"').find('md-select');
openSelect(select);

var container = select[0].querySelector('.md-select-menu-container');
var container = $document[0].querySelector('.md-select-menu-container');
expect(container).toBeTruthy();
expect(container.classList.contains('test')).toBe(true);
}));

it('sets aria-owns between the select and the container', function() {
var select = setupSelect('ng-model="val"').find('md-select');
var ownsId = select.attr('aria-owns');
expect(ownsId).toBeTruthy();
var containerId = select[0].querySelector('.md-select-menu-container').getAttribute('id');
expect(ownsId).toBe(containerId);
});

it('calls md-on-close when the select menu closes', inject(function($document, $rootScope) {
var called = false;
$rootScope.onClose = function() {
Expand Down Expand Up @@ -89,6 +97,15 @@ describe('<md-select>', function() {
expect(backdrop.length).toBe(0);
}));

it('removes the menu container when the select is removed', inject(function($document) {
var select = setupSelect('ng-model="val"', [1]).find('md-select');
openSelect(select);

select.remove();

expect($document.find('md-select-menu').length).toBe(0);
}));

it('should not trigger ng-change without a change when using trackBy', inject(function($rootScope) {
var changed = false;
$rootScope.onChange = function() { changed = true; };
Expand Down Expand Up @@ -402,7 +419,6 @@ describe('<md-select>', function() {
clickOption(el, 1);

expect(selectedOptions(el).length).toBe(1);
expect(el.find('md-option').eq(1).attr('selected')).toBe('selected');
expect($rootScope.model).toBe(2);
}));

Expand Down Expand Up @@ -758,33 +774,33 @@ describe('<md-select>', function() {
}));

describe('md-select', function() {
it('can be opened with a space key', inject(function($document) {
it('can be opened with a space key', function() {
var el = setupSelect('ng-model="someModel"', [1, 2, 3]).find('md-select');
pressKey(el, 32);
waitForSelectOpen();
expectSelectOpen(el);
}));
});

it('can be opened with an enter key', inject(function($document) {
it('can be opened with an enter key', function() {
var el = setupSelect('ng-model="someModel"', [1, 2, 3]).find('md-select');
pressKey(el, 13);
waitForSelectOpen();
expectSelectOpen(el);
}));
});

it('can be opened with the up key', inject(function($document) {
it('can be opened with the up key', function() {
var el = setupSelect('ng-model="someModel"', [1, 2, 3]).find('md-select');
pressKey(el, 38);
waitForSelectOpen();
expectSelectOpen(el);
}));
});

it('can be opened with the down key', inject(function($document) {
it('can be opened with the down key', function() {
var el = setupSelect('ng-model="someModel"', [1, 2, 3]).find('md-select');
pressKey(el, 40);
waitForSelectOpen();
expectSelectOpen(el);
}));
});

it('supports typing an option name', inject(function($document, $rootScope) {
var el = setupSelect('ng-model="someModel"', [1, 2, 3]).find('md-select');
Expand All @@ -798,7 +814,7 @@ describe('<md-select>', function() {
var el = setupSelect('ng-model="someVal"', [1, 2, 3]).find('md-select');
openSelect(el);
expectSelectOpen(el);
var selectMenu = el.find('md-select-menu');
var selectMenu = $document.find('md-select-menu');
expect(selectMenu.length).toBe(1);
pressKey(selectMenu, 27);
waitForSelectClose();
Expand Down Expand Up @@ -845,7 +861,15 @@ describe('<md-select>', function() {
}

function selectedOptions(el) {
return angular.element(el[0].querySelectorAll('md-option[selected]'));
var res;
var querySelector = 'md-option[selected]';
inject(function($document) {
res = angular.element($document[0].querySelectorAll(querySelector));
if (!res.length) {
res = angular.element(el[0].querySelectorAll(querySelector));
}
});
return res;
}

function openSelect(el) {
Expand Down Expand Up @@ -891,7 +915,7 @@ describe('<md-select>', function() {
function clickOption(select, index) {
inject(function($rootScope, $document) {
expectSelectOpen(select);
var openMenu = select.find('md-select-menu');
var openMenu = $document.find('md-select-menu');
var opt = angular.element(openMenu.find('md-option')[index]).find('div')[0];

if (!opt) throw Error('Could not find option at index: ' + index);
Expand All @@ -905,21 +929,23 @@ describe('<md-select>', function() {
}

function expectSelectClosed(element) {
element = angular.element(element);
var menu = angular.element(element[0].querySelector('.md-select-menu-container'));
if (menu.length) {
if (menu.hasClass('md-active') || menu.attr('aria-hidden') == 'false') {
throw Error('Expected select to be closed');
inject(function($document) {
var menu = angular.element($document[0].querySelector('.md-select-menu-container'));
if (menu.length) {
if (menu.hasClass('md-active') || menu.attr('aria-hidden') == 'false') {
throw Error('Expected select to be closed');
}
}
}
});
}

function expectSelectOpen(element) {
element = angular.element(element);
var menu = angular.element(element[0].querySelector('.md-select-menu-container'));
if (!(menu.hasClass('md-active') && menu.attr('aria-hidden') == 'false')) {
throw Error('Expected select to be open');
}
inject(function($document) {
var menu = angular.element($document[0].querySelector('.md-select-menu-container'));
if (!(menu.hasClass('md-active') && menu.attr('aria-hidden') == 'false')) {
throw Error('Expected select to be open');
}
});
}

});

0 comments on commit 90ec97c

Please sign in to comment.