Created
June 24, 2013 17:11
-
-
Save eyston/5851760 to your computer and use it in GitHub Desktop.
angular typeahead
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('ymusica').controller('AlbumSearch', ['$scope', 'Albums', 'Artists', '$q', function($scope, albums, artists, $q) { | |
$scope.albums = []; | |
$scope.artists = []; | |
var terms = new Rx.Subject(); | |
$scope.searchMusic = terms.onNext.bind(terms); | |
terms.sample(250) | |
.select(function(term) { | |
var promise = $q.all([albums.query(term), artists.query(term)]); | |
return Rx.promiseToObservable(promise) | |
}) | |
.switchLatest() | |
.select(function(promise) { return [promise[0].data.albums, promise[1].data.artists]; }) | |
.subscribe(function(result) { | |
$scope.albums = result[0].slice(0, 5); | |
$scope.artists = result[1].slice(0, 5); | |
$scope.music = $scope.albums.concat($scope.artists); | |
}); | |
$scope.selectMusic = function(item) { | |
console.log('music selected!', item); | |
$scope.term = item.name; | |
}; | |
$scope.imageSource = function(item) { | |
return item.images['medium']; | |
}; | |
$scope.hasAlbums = function() { | |
return $scope.albums.length > 0; | |
}; | |
$scope.hasArtists = function() { | |
return $scope.artists.length > 0; | |
}; | |
}]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> | |
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> | |
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> | |
<!--[if gt IE 8]><!--> <html class="no-js" ng-app="ymusica"> <!--<![endif]--> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
<title>ymusica</title> | |
<meta name="description" content=""> | |
<meta name="viewport" content="width=device-width"> | |
<!-- Place favicon.ico and apple-touch-icon.png in the root directory --> | |
<link rel="stylesheet" href="/css/vendor/bootstrap.css"> | |
<link rel="stylesheet" href="/css/main.css"> | |
<script src="/js/vendor/modernizr.js"></script> | |
</head> | |
<body> | |
<!--[if lt IE 7]> | |
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p> | |
<![endif]--> | |
<div class="container"> | |
<div ng-controller="AlbumSearch" class="album-search text-center" ng-cloak> | |
<typeahead class="typeahead" items="music" term="term" search="searchMusic(term)" select="selectMusic(item)"> | |
<div class="menu" ng-cloak> | |
<h3 ng-show="hasAlbums()">Albums</h3> | |
<ul> | |
<li typeahead-item="album" ng-repeat="album in albums" class="results"> | |
<img ng-src="{{imageSource(album)}}"><p class="name">{{album.name}}</p><p class="artist">{{album.artist}}</p> | |
</li> | |
</ul> | |
<h3 ng-show="hasArtists()">Artists</h3> | |
<ul> | |
<li typeahead-item="artist" ng-repeat="artist in artists" class="results"> | |
<img ng-src="{{imageSource(artist)}}"><p class="name">{{artist.name}}</p> | |
</li> | |
</ul> | |
</div> | |
</typeahead> | |
</div> | |
</div> | |
<script src="/js/vendor/jquery.js"></script> | |
<script src="/js/vendor/rx.js"></script> | |
<script src="/js/vendor/rx.time.js"></script> | |
<script src="/js/vendor/rx.coincidence.js"></script> | |
<script src="/js/vendor/angular.js"></script> | |
<script src="/js/vendor/angular-resource.js"></script> | |
<script src="/js/vendor/bootstrap.js"></script> | |
<script src="/js/ymusica.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('ymusica').directive('typeahead', ["$timeout", function($timeout) { | |
return { | |
restrict: 'E', | |
transclude: true, | |
replace: true, | |
template: '<div><form><input ng-model="term" ng-change="query()" type="text" autocomplete="off" /></form><div ng-transclude></div></div>', | |
scope: { | |
search: "&", | |
select: "&", | |
items: "=", | |
term: "=" | |
}, | |
controller: ["$scope", function($scope) { | |
$scope.items = []; | |
$scope.hide = false; | |
this.activate = function(item) { | |
$scope.active = item; | |
}; | |
this.activateNextItem = function() { | |
var index = $scope.items.indexOf($scope.active); | |
this.activate($scope.items[(index + 1) % $scope.items.length]); | |
}; | |
this.activatePreviousItem = function() { | |
var index = $scope.items.indexOf($scope.active); | |
this.activate($scope.items[index === 0 ? $scope.items.length - 1 : index - 1]); | |
}; | |
this.isActive = function(item) { | |
return $scope.active === item; | |
}; | |
this.selectActive = function() { | |
this.select($scope.active); | |
}; | |
this.select = function(item) { | |
$scope.hide = true; | |
$scope.focused = true; | |
$scope.select({item:item}); | |
}; | |
$scope.isVisible = function() { | |
return !$scope.hide && ($scope.focused || $scope.mousedOver); | |
}; | |
$scope.query = function() { | |
$scope.hide = false; | |
$scope.search({term:$scope.term}); | |
} | |
}], | |
link: function(scope, element, attrs, controller) { | |
var $input = element.find('form > input'); | |
var $list = element.find('> div'); | |
$input.bind('focus', function() { | |
scope.$apply(function() { scope.focused = true; }); | |
}); | |
$input.bind('blur', function() { | |
scope.$apply(function() { scope.focused = false; }); | |
}); | |
$list.bind('mouseover', function() { | |
scope.$apply(function() { scope.mousedOver = true; }); | |
}); | |
$list.bind('mouseleave', function() { | |
scope.$apply(function() { scope.mousedOver = false; }); | |
}); | |
$input.bind('keyup', function(e) { | |
if (e.keyCode === 9 || e.keyCode === 13) { | |
scope.$apply(function() { controller.selectActive(); }); | |
} | |
if (e.keyCode === 27) { | |
scope.$apply(function() { scope.hide = true; }); | |
} | |
}); | |
$input.bind('keydown', function(e) { | |
if (e.keyCode === 9 || e.keyCode === 13 || e.keyCode === 27) { | |
e.preventDefault(); | |
}; | |
if (e.keyCode === 40) { | |
e.preventDefault(); | |
scope.$apply(function() { controller.activateNextItem(); }); | |
} | |
if (e.keyCode === 38) { | |
e.preventDefault(); | |
scope.$apply(function() { controller.activatePreviousItem(); }); | |
} | |
}); | |
scope.$watch('items', function(items) { | |
controller.activate(items.length ? items[0] : null); | |
}); | |
scope.$watch('focused', function(focused) { | |
if (focused) { | |
$timeout(function() { $input.focus(); }, 0, false); | |
} | |
}); | |
scope.$watch('isVisible()', function(visible) { | |
if (visible) { | |
var pos = $input.position(); | |
var height = $input[0].offsetHeight; | |
$list.css({ | |
top: pos.top + height, | |
left: pos.left, | |
position: 'absolute', | |
display: 'block' | |
}); | |
} else { | |
$list.css('display', 'none'); | |
} | |
}); | |
} | |
}; | |
}]); | |
angular.module('ymusica').directive('typeaheadItem', function() { | |
return { | |
require: '^typeahead', | |
link: function(scope, element, attrs, controller) { | |
var item = scope.$eval(attrs.typeaheadItem); | |
scope.$watch(function() { return controller.isActive(item); }, function(active) { | |
if (active) { | |
element.addClass('active'); | |
} else { | |
element.removeClass('active'); | |
} | |
}); | |
element.bind('mouseenter', function(e) { | |
scope.$apply(function() { controller.activate(item); }); | |
}); | |
element.bind('click', function(e) { | |
scope.$apply(function() { controller.select(item); }); | |
}); | |
} | |
}; | |
}); |
yeah - i cannot see how it gets the URL for the music, and also ymusica.js - where is this file? How does the HTML file include the typeahead.js etc? I thought this would make things clearer but they are more muddy :-/
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Will you be able to send me the complete working code for the application. I am new to angular and trying to work on some project. Thanks