* Introduce a search field in the top navbar connected to the `/search` service.
* Added a stub implementation of a search service depending on APIList.
Demo: http://nitweb.moz-code.org/
Pull-Request: #2157
Reviewed-by: Jean Privat <jean@pryen.org>
<div class='col-xs-3 navbar-header'>
<a class='navbar-brand' ng-href='/'>Nitdoc</a>
</div>
+ <div class='col-xs-7'>
+ <form ng-controller='SearchCtrl as searchCtrl' >
+ <div class='form-group has-icon'>
+ <input placeholder='Search...' type='text' class='form-control search-input'
+ ng-model-options='{ debounce: 150 }' ng-model='query'
+ ng-keydown='update($event)' ng-change='search()'>
+ <span class='glyphicon glyphicon-search form-control-icon text-muted'></span>
+ </div>
+ <div ng-if='results.length > 0' class='search-results'>
+ <div class='card-list'>
+ <entity-card ng-click='reset()' ng-class='{active: activeItem == $index}' mentity='mentity' ng-repeat='mentity in results' />
+ </div>
+ </div>
+ </form>
+ </div>
</div>
</nav>
<div ng-view></div>
$http.get(apiUrl + '/entity/' + id)
.success(cb)
.error(cbErr);
- }
+ },
+ search: function(q, n, cb, cbErr) {
+ $http.get(apiUrl + '/search?q=' + q + '&n=' + n)
+ .success(cb)
+ .error(cbErr);
+ }
};
}])
})();
angular
.module('ui', [ 'model' ])
+ .controller('SearchCtrl', ['Model', '$routeParams', '$scope', '$window', function(Model, $routeParams, $scope, $window) {
+ $scope.query = '';
+
+ $scope.reset = function() {
+ $scope.activeItem = 0;
+ $scope.results = [];
+ }
+
+ $scope.update = function(e) {
+ if(e.keyCode == 38) {
+ $scope.selectUp();
+ } else if(e.keyCode == 40) {
+ $scope.selectDown();
+ } else if(e.keyCode == 27) {
+ $scope.selectEscape();
+ } else if(e.keyCode == 13) {
+ $scope.selectEnter();
+ }
+ }
+
+ $scope.selectUp = function() {
+ if($scope.activeItem > 0) {
+ $scope.activeItem -= 1;
+ }
+ }
+
+ $scope.selectDown = function() {
+ if($scope.activeItem < $scope.results.length - 1) {
+ $scope.activeItem += 1;
+ }
+ }
+
+ $scope.selectEnter = function() {
+ $window.location.href = $scope.results[$scope.activeItem].web_url;
+ $scope.reset();
+ }
+
+ $scope.selectEscape = function() {
+ $scope.reset();
+ }
+
+ $scope.search = function() {
+ if(!$scope.query) {
+ $scope.reset();
+ return;
+ }
+ Model.search($scope.query, 10,
+ function(data) {
+ $scope.reset();
+ $scope.results = data;
+ }, function(err) {
+ $scope.reset();
+ $scope.error = err;
+ });
+ }
+
+ $scope.reset();
+ }])
+
.directive('uiFilters', function() {
return {
restrict: 'E',
pointer-events: none;
}
+/* search */
+
+.search-input {
+ width: 100%;
+}
+
+.search-results {
+ position: absolute;
+ right: 0;
+}
+
+.search-results .card.active {
+ background: #eee;
+ border-color: #eee;
+}
+
+/* navs */
+
+.nav-tabs li { cursor: pointer; }
+
+.navbar-fixed-top {
+ background-color: #1E9431;
+ box-shadow: 0 0 4px rgba(0,0,0,.14),0 4px 8px rgba(0,0,0,.28);
+}
+
+.navbar-fixed-top .form-control:hover, .navbar-fixed-top .form-control:focus {
+ background: rgba(255, 255, 255, 0.2);
+}
+
+.navbar-fixed-top .form-control {
+ background: rgba(255, 255, 255, 0.1);
+ border: none;
+ color: #fff;
+ box-shadow: none;
+}
+
+.navbar-fixed-top .form-control-icon {
+ color: #fff;
+}
+
+.navbar-fixed-top *::-webkit-input-placeholder {
+ color: #fff;
+}
+.navbar-fixed-top *:-moz-placeholder {
+ /* FF 4-18 */
+ color: #fff;
+}
+.navbar-fixed-top *::-moz-placeholder {
+ /* FF 19+ */
+ color: #fff;
+}
+.navbar-fixed-top *:-ms-input-placeholder {
+ /* IE 10+ */
+ color: #fff;
+}
+
+.navbar-fixed-top .form-group {
+ margin-top: 8px;
+ margin-bottom: 0px;
+}
/*
* Code Highlighting
*/
end
end
-# Search mentities from a query string.
-#
-# Example: `GET /search?q=Arr`
-class APISearch
- super APIHandler
-
- redef fun get(req, res) do
- var q = req.string_arg("q")
- if q == null then
- res.error 400
- return
- end
- var arr = new JsonArray
- for mentity in view.mentities do
- if mentity.name.has_prefix(q) then arr.add mentity
- end
- res.json arr
- end
-end
-
# List all mentities.
#
# MEntities can be filtered on their kind using the `k` parameter.
redef fun get(req, res) do
var mentities = list_mentities(req)
mentities = limit_mentities(req, mentities)
- var arr = new JsonArray
- for mentity in mentities do arr.add mentity
- res.json arr
+ res.json new JsonArray.from(mentities)
+ end
+end
+
+# Search mentities from a query string.
+#
+# Example: `GET /search?q=Arr`
+class APISearch
+ super APIList
+
+ redef fun list_mentities(req) do
+ var q = req.string_arg("q")
+ var mentities = new Array[MEntity]
+ if q == null then return mentities
+ for mentity in view.mentities do
+ if mentity.name.has_prefix(q) then mentities.add mentity
+ end
+ return mentities
end
end
var mentities = list_mentities(req)
mentities = limit_mentities(req, mentities)
mentities = randomize_mentities(req, mentities)
- var arr = new JsonArray
- for mentity in mentities do arr.add mentity
- res.json arr
+ res.json new JsonArray.from(mentities)
end
end