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

Commit

Permalink
feat(autocomplete): added initial files for autocomplete
Browse files Browse the repository at this point in the history
feat(autocomplete): adds accessibility support

TODO: wire aria-activedescendant as a watched property with a value of the active listItem id

refactor(autocomplete): re-organizes aria changes to live in controller

chore(autocomplete): removes temporary comments

refactor(autocomplete): renames ambiguous directive

refactor(styles): renames `visuallyhidden` to `visually-hidden` for consistency.

refactor(autocomplete): removes unused template file

refactor(autocomplete): uses `$mdConstant` rather than hard-coded values

refactor(autocomplete): various cleanup based on feedback

refactor(autocomplete): cleans up scope confusion

refactor(autocomplete): includes theming, updates directive name to prevent potential conflicts
  • Loading branch information
Robert Messerle committed Feb 10, 2015
1 parent 4e930ed commit ef60d49
Show file tree
Hide file tree
Showing 17 changed files with 613 additions and 14 deletions.
2 changes: 1 addition & 1 deletion config/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = function(config) {
// demos in the tests, and Karma doesn't support advanced
// globbing.
'src/components/*/*.js',
'src/components/tabs/js/*.js'
'src/components/*/js/*.js'
];

var COMPILED_SRC = [
Expand Down
11 changes: 0 additions & 11 deletions docs/app/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,6 @@ code:not(.highlight) {
-webkit-font-smoothing: auto;
}

.visuallyhidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
text-transform: none;
width: 1px;
}
.md-sidenav-inner {
background: #fff;
}
Expand Down
2 changes: 1 addition & 1 deletion docs/app/partials/menu-link.tmpl.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<md-button ng-class="{'active' : isSelected()}"
ng-href="#{{section.url}}">
{{section | humanizeDoc}}
<span class="visuallyhidden"
<span class="visually-hidden"
ng-if="isSelected()">
current page
</span>
Expand Down
2 changes: 1 addition & 1 deletion docs/app/partials/menu-toggle.tmpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{{section.name}}
<span aria-hidden="true" class="md-toggle-icon"
ng-class="{'toggled' : isOpen()}"></span>
<span class="visuallyhidden">
<span class="visually-hidden">
Toggle {{isOpen()? 'expanded' : 'collapsed'}}
</span>
</md-button>
Expand Down
20 changes: 20 additions & 0 deletions src/components/autocomplete/autocomplete-theme.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
md-autocomplete {
background: '{{background-50}}';
button {
background: '{{background-200}}';
}
ul {
background: '{{background-50}}';
li {
border-top: 1px solid '{{background-400}}';
color: '{{background-900}}';
.highlight {
color: '{{background-600}}';
}
&:hover,
&.selected {
background: '{{background-200}}';
}
}
}
}
11 changes: 11 additions & 0 deletions src/components/autocomplete/autocomplete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(function () {
'use strict';
/**
* @ngdoc module
* @name material.components.autocomplete
*/
/*
* @see js folder for autocomplete implementation
*/
angular.module('material.components.autocomplete', [ 'material.core' ]);
})();
145 changes: 145 additions & 0 deletions src/components/autocomplete/autocomplete.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
@keyframes md-autocomplete-list-out {
0% {
animation-timing-function: linear;
}
50% {
opacity: 0;
height: 40px;
animation-timing-function: ease-in;
}
100% {
height: 0;
opacity: 0;
}
}
@keyframes md-autocomplete-list-in {
0% {
opacity: 0;
height: 0;
animation-timing-function: ease-out;
}
50% {
opacity: 0;
height: 40px;
}
100% {
opacity: 1;
height: 40px;
}
}
md-content {
overflow: visible;
}
md-autocomplete {
box-shadow: 0 2px 5px rgba(black, 0.25);
border-radius: 2px;
display: block;
height: 40px;
position: relative;
overflow: visible;

md-autocomplete-wrap {
display: block;
position: relative;
overflow: visible;
height: 40px;

md-progress-linear {
position: absolute;
bottom: 0; left: 0; width: 100%;
height: 3px;
transition: none;

.md-container {
transition: none;
top: auto;
height: 3px;
}
&.ng-enter {
transition: opacity 0.15s linear;
&.ng-enter-active {
opacity: 1;
}
}
&.ng-leave {
transition: opacity 0.15s linear;
&.ng-leave-active {
opacity: 0;
}
}
}
}
input {
position: absolute;
left: 0;
top: 0;
width: 100%;
box-sizing: border-box;
border: none;
box-shadow: none;
padding: 0 15px;
font-size: 14px;
line-height: 40px;
height: 40px;
outline: none;
z-index: 2;
background: transparent;
}
button {
position: absolute;
top: 10px;
right: 10px;
line-height: 20px;
z-index: 2;
text-align: center;
width: 20px;
height: 20px;
cursor: pointer;
border: none;
border-radius: 50%;
padding: 0;
font-size: 12px;
&.ng-enter {
transform: scale(0);
transition: transform 0.15s ease-out;
&.ng-enter-active {
transform: scale(1);
}
}
&.ng-leave {
transition: transform 0.15s ease-out;
&.ng-leave-active {
transform: scale(0);
}
}
}
ul {
position: absolute;
top: 100%;
left: 0;
right: 0;
box-shadow: 0 2px 5px rgba(black, 0.25);
margin: 0;
list-style: none;
padding: 0;
overflow: auto;
max-height: 41px * 5.5;
li {
border-top: 1px solid #ddd;
padding: 0 15px;
line-height: 40px;
font-size: 14px;
overflow: hidden;
height: 40px;
transition: background 0.15s linear;
cursor: pointer;
margin: 0;
&.ng-enter {
animation: md-autocomplete-list-in 0.2s;
}
&.ng-leave {
animation: md-autocomplete-list-out 0.2s;
}
}
}
}
64 changes: 64 additions & 0 deletions src/components/autocomplete/autocomplete.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
describe('<md-autocomplete>', function() {

beforeEach(module('material.components.autocomplete'));

function compile (str, scope) {
var container;
inject(function ($compile) {
container = $compile(str)(scope);
scope.$apply();
});
return container;
}

function createScope () {
var scope;
var items = ['foo', 'bar', 'baz'].map(function (item) { return { display: item }; });
inject(function ($rootScope) {
scope = $rootScope.$new();
scope.match = function (term) {
return items.filter(function (item) {
return item.display.indexOf(term) === 0;
});
};
scope.searchText = '';
scope.selectedItem = null;
});
return scope;
}

describe('basic functionality', function () {
it('should fail', inject(function($timeout, $mdConstant) {
var scope = createScope();
var template = '\
<md-autocomplete\
md-selected-item="selectedItem"\
md-search-text="searchText"\
md-items="item in match(searchText)"\
md-item-text="display"\
placeholder="placeholder">\
<span md-highlight-text="searchText">{{item.display}}</span>\
</md-autocomplete>';
var element = compile(template, scope);
var ctrl = element.controller('mdAutocomplete');

expect(scope.searchText).toBe('');
expect(scope.selectedItem).toBe(null);

element.scope().searchText = 'fo';
ctrl.keydown({});
element.scope().$apply();
$timeout.flush();

expect(scope.searchText).toBe('fo');
expect(scope.match(scope.searchText).length).toBe(1);
expect(element.find('li').length).toBe(1);

ctrl.keydown({ keyCode: $mdConstant.KEY_CODE.DOWN_ARROW, preventDefault: angular.noop });
ctrl.keydown({ keyCode: $mdConstant.KEY_CODE.ENTER, preventDefault: angular.noop });
scope.$apply();
expect(scope.searchText).toBe('foo');
}));
});

});
18 changes: 18 additions & 0 deletions src/components/autocomplete/demoBasicUsage/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div ng-app="inputBasicDemo" ng-controller="DemoCtrl as ctrl" layout="column">

<md-content class="md-padding" layout="column">

<md-autocomplete
md-selected-item="ctrl.selectedItem"
md-search-text="ctrl.searchText"
md-items="item in ctrl.getItems(ctrl.searchText)"
md-item-text="display"
placeholder="select a state...">
<span md-highlight-text="ctrl.searchText">{{item.display}}</span>
</md-autocomplete>

<p>Current search term: "{{ctrl.searchText}}"</p>

</md-content>

</div>
26 changes: 26 additions & 0 deletions src/components/autocomplete/demoBasicUsage/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
angular
.module('autocompleteDemo', ['ngMaterial'])
.controller('DemoCtrl', DemoCtrl);

function DemoCtrl ($timeout, $q) {
var self = this;
this.selectedItem = null;
this.searchText = null;
this.states = 'Alabama, Alaska, Arizona, Arkansas, California, Colorado, Connecticut, Deleware,\
Florida, Georgia, Hawaii, Idaho, Illanois, Indiana, Iowa, Kansas, Kentucky, Louisiana,\
Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana,\
Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina,\
North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina,\
South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia,\
Wisconsin, Wyoming'.split(/, +/g).map(function (state) { return { value: state.toLowerCase(), display: state }; });
this.getItems = getItems;

function getItems (query) {
if (!query) return [];
var deferred = $q.defer();
var lowercaseQuery = angular.lowercase(query);
var results = self.states.filter(function (state) { return state.value.indexOf(lowercaseQuery) === 0; });
$timeout(function () { deferred.resolve(results); }, Math.random() * 1000, false);
return deferred.promise;
}
}
3 changes: 3 additions & 0 deletions src/components/autocomplete/demoBasicUsage/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
md-content {
min-height: 500px;
}
Loading

0 comments on commit ef60d49

Please sign in to comment.