-
-
Save slattery/6708206 to your computer and use it in GitHub Desktop.
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); }); | |
}); | |
} | |
}; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment