diff options
Diffstat (limited to 'docs/app/src/search.js')
| -rw-r--r-- | docs/app/src/search.js | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/docs/app/src/search.js b/docs/app/src/search.js new file mode 100644 index 00000000..9ae18ff6 --- /dev/null +++ b/docs/app/src/search.js @@ -0,0 +1,149 @@ +angular.module('search', []) + +.controller('DocsSearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) { + function clearResults() { + $scope.results = []; + $scope.colClassName = null; + $scope.hasResults = false; + } + + $scope.search = function(q) { + var MIN_SEARCH_LENGTH = 3; + if(q.length >= MIN_SEARCH_LENGTH) { + var results = docsSearch(q); + var totalAreas = 0; + for(var i in results) { + ++totalAreas; + } + if(totalAreas > 0) { + $scope.colClassName = 'cols-' + totalAreas; + } + $scope.hasResults = totalAreas > 0; + $scope.results = results; + } + else { + clearResults(); + } + if(!$scope.$$phase) $scope.$apply(); + }; + $scope.submit = function() { + var result; + for(var i in $scope.results) { + result = $scope.results[i][0]; + if(result) { + break; + } + } + if(result) { + $location.path(result.url); + $scope.hideResults(); + } + }; + $scope.hideResults = function() { + clearResults(); + $scope.q = ''; + }; +}]) + +.factory('lunrSearch', function() { + return function(properties) { + if (window.RUNNING_IN_NG_TEST_RUNNER) return null; + + var engine = lunr(properties); + return { + store : function(values) { + engine.add(values); + }, + search : function(q) { + return engine.search(q); + } + }; + }; +}) + +.factory('docsSearch', ['$rootScope','lunrSearch', 'NG_PAGES', + function($rootScope, lunrSearch, NG_PAGES) { + if (window.RUNNING_IN_NG_TEST_RUNNER) { + return null; + } + + var index = lunrSearch(function() { + this.ref('id'); + this.field('title', {boost: 50}); + this.field('keywords', { boost : 20 }); + }); + + angular.forEach(NG_PAGES, function(page, key) { + if(page.searchTerms) { + index.store({ + id : key, + title : page.searchTerms.titleWords, + keywords : page.searchTerms.keywords + }); + }; + }); + + return function(q) { + var results = { + api : [], + tutorial : [], + guide : [], + error : [], + misc : [] + }; + angular.forEach(index.search(q), function(result) { + var key = result.ref; + var item = NG_PAGES[key]; + var area = item.area; + item.path = key; + + var limit = area == 'api' ? 40 : 14; + if(results[area].length < limit) { + results[area].push(item); + } + }); + return results; + }; +}]) + +.directive('focused', function($timeout) { + return function(scope, element, attrs) { + element[0].focus(); + element.on('focus', function() { + scope.$apply(attrs.focused + '=true'); + }); + element.on('blur', function() { + // have to use $timeout, so that we close the drop-down after the user clicks, + // otherwise when the user clicks we process the closing before we process the click. + $timeout(function() { + scope.$eval(attrs.focused + '=false'); + }); + }); + scope.$eval(attrs.focused + '=true'); + }; +}) + +.directive('docsSearchInput', ['$document',function($document) { + return function(scope, element, attrs) { + var ESCAPE_KEY_KEYCODE = 27, + FORWARD_SLASH_KEYCODE = 191; + angular.element($document[0].body).bind('keydown', function(event) { + var input = element[0]; + if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement != input) { + event.stopPropagation(); + event.preventDefault(); + input.focus(); + } + }); + + element.bind('keydown', function(event) { + if(event.keyCode == ESCAPE_KEY_KEYCODE) { + event.stopPropagation(); + event.preventDefault(); + scope.$apply(function() { + scope.hideResults(); + }); + } + }); + }; +}]); |
