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
Closes #1418.
  • Loading branch information
Robert Messerle authored and ThomasBurleson committed Feb 10, 2015
1 parent ca60beb commit 0bd8cf1
Show file tree
Hide file tree
Showing 17 changed files with 657 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');
}));
});

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

<md-content class="md-padding" layout="column">
<p>
Use the `md-auto-complete` to search for matches from local or remote data sources.
</p>

<md-autocomplete
md-selected-item="ctrl.selectedItem"
md-search-text="ctrl.searchText"
md-items="item in ctrl.querySearch(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>
66 changes: 66 additions & 0 deletions src/components/autocomplete/demoBasicUsage/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
angular
.module('autocompleteDemo', ['ngMaterial'])
.controller('DemoCtrl', DemoCtrl);

function DemoCtrl ($timeout, $q) {
var self = this;

// list of `state` value/display objects
self.states = loadAll();
self.selectedItem = null;
self.searchText = null;
self.querySearch = querySearch;

// ******************************
// Internal methods
// ******************************

/**
* Search for states... use $timeout to simulate
* remote dataservice call.
*/
function querySearch (query) {
var deferred = $q.defer();

$timeout(function () {

var results = query ? self.states.filter( createFilterFor(query) ) : [ ];
deferred.resolve( results );

}, Math.random() * 1000, false);

return deferred.promise;
}

/**
* Build `states` list of key/value pairs
*/
function loadAll() {
var allStates = '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';

return allStates.split(/, +/g).map( function (state) {
return {
value: state.toLowerCase(),
display: state
};
});
}

/**
* Create filter function for a query string
*/
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);

return function filterFn(state) {
return (state.value.indexOf(lowercaseQuery) === 0);
};

}
}
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 0bd8cf1

Please sign in to comment.