Search Part VI: Autocomplete

Highlighting

by rocketegg0

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular-sanitize.min.js"></script>
<div ng-controller="MyCtrl">
    <h2>Part 6: Autocomplete</h2>
    <div>Search: <input type="text" ng-model="textIn"></input></div>
    <div>Limit: <input type="number" ng-model="limit"></input>
        <p>Use 0 for unlimited</p>
    </div>
    <div>Use BFS: <input type="radio" ng-model="bfs" ng-value=
"true"></input>
        Use DFS: <input type="radio" ng-model="bfs" ng-value="false"></input>
    </div>
    <div>
        <table>
            <caption>Search Results ({{ results.length }})</caption>
            <tr>
                <th>Words</th>
            </tr>
            <tr ng-repeat="word in results">
                <td><a ng-href="#{{word}}" ng-click="select(word)">{{::word}}</a></td>
            </tr>
        </table>
        <table>
            <tr>
                <td>
                    <p><strong>{{textIn}}<strong></p>
                    <p><em>{{dictionary[textIn.toUpperCase()]}}</em></p>
                </td>
            </tr>
        </table>
    </div>
</div>

CSS

h2 {
    font-size: 150%;
}

table {
    margin-top: 10px;
    border: 1px solid #ccc;
    width: 100%;
}

table th {
    font-weight: bold;
}

em {
    font-style:italic;
}

strong {
    font-weight: bold;
}
}

JavaScript

var myApp = angular.module('myApp',['ngSanitize']);

myApp.controller('MyCtrl', function($scope, $http) {
    
    // Compute unique hash words
    var toHash = function(dict) {
        return Object.keys(dict.split(' ').reduce(function(memo, word) {
			if (!memo.hasOwnProperty(word)) { memo[word] = true; }
            return memo;
        }, {})).sort();
    };
    
    // Compute prefix trie
    var toTrie = function(words) {
    	var root = new Node();
        words.forEach(function(word) {
            root.insert(word.toLowerCase());
        });
		return root;
    };
    
    $scope.select = function(word) { $scope.textIn = word; };
    
    $scope.autocomplete = function(textIn) {
        if (!textIn || textIn.length < 2) {
            return [];
        }
        var node = $scope.root;
        var path = '';
        var chars = textIn.split('').map(function(c) { return c.toLowerCase(); })
        for (var i = 0; i < chars.length; i++) {
            if (node && node.children.hasOwnProperty(chars[i])) {
                node = node.children[chars[i]];
                path += chars[i];
            } else {
				return [];
            }
        }
        if (!node.hasChildren()) {
			return [path];
        }
        $scope.current_node = node;
        var results = [];
        if ($scope.bfs) {
            node.traverseBFS(results, path.substr(0, path.length-1), $scope.limit);
        } else {
            node.traverseDFS(results, path, $scope.limit);
        }
        return results;
    };
    /* load dictionary */
    $scope.limit = 10;
    $scope.bfs = true;
    $http.get("https://raw.githubusercontent.com/adambom/dictionary/master/dictionary.json").then(function(response) {
        $scope.dictionary = response.data;
    	$scope.root = toTrie(Object.keys($scope.dictionary));
        $scope.$watch('textIn', function(newText) {
             $scope.results = $scope.autocomplete(newText);
	    });
        $scope.$watch('limit', function(newLimit) {
            ...