Permalink
Browse files

Reorganize, write.

  • Loading branch information...
1 parent 89c2c76 commit 1909c49a70c822a014505db0dfd3b2e83720be3c @tmcw committed Oct 7, 2012
File renamed without changes.
@@ -1,15 +1,29 @@
body {
font:normal 15px/20px 'Helvetica';
+ color:#444;
}
a {
text-decoration:none;
color:#26B;
}
input#search {
- font-size:20px;
- padding:5px;
+ font-size:16px;
line-height:30px;
width:300px;
+ background: white;
+ border: 1px solid #CCC;
+ border-color: #CCC #DDD #DDD;
+ padding: 0px 2px;
+ box-shadow: inset #DDD 0px 1px 3px;
+ outline:none;
+}
+input#search:focus {
+ border-color:#000;
+}
+.autocomplete-option {
+ float:left;
+ font:normal 12px/15px 'Helvetica';
+ padding:2px 5px;
}
* {
-moz-box-sizing: border-box;
@@ -36,5 +50,5 @@ div.result {
}
h3 {
- font:normal 20px/35px 'Helvetica';
-}
+ font:normal 15px/20px 'Helvetica';
+}
File renamed without changes.
@@ -0,0 +1,22 @@
+var _s = require('underscore.string'),
+ path = require('path'),
+ fs = require('fs');
+
+var words = {};
+fs.readdir('../indexes', function(err, files) {
+ files.map(function(f) {
+ var obj = JSON.parse(fs.readFileSync('../indexes/' + f, 'utf8'));
+ var keys = Object.keys(obj);
+ var trie = {};
+ for (var i = 0; i < keys.length; i++) {
+ var pos = trie;
+ for (var j = 0; j < keys[i].length; j++) {
+ if (pos[keys[i][j]] === undefined) {
+ pos[keys[i][j]] = {};
+ }
+ pos = pos[keys[i][j]];
+ }
+ }
+ fs.writeFileSync('../indexes/' + f + '.trie.json', JSON.stringify(trie));
+ });
+});
View
@@ -2,58 +2,66 @@
<html>
<head>
<title>DC Municipal Regulations</title>
- <link href='reset.css' type='text/css' rel='stylesheet' />
- <link href='style.css' type='text/css' rel='stylesheet' />
+ <link href='css/reset.css' type='text/css' rel='stylesheet' />
+ <link href='css/style.css' type='text/css' rel='stylesheet' />
</head>
<body>
<div class='left'>
<div class='header'>
<h1>DC Municipal Regulations</h1>
- <p>This is an <em>unofficial</em> of the Washington, DC
+ <p>This is an <em>unofficial</em> version of the Washington, DC
municipal regulations.</p>
</div>
<form action='POST'>
- <input type='text' id='search' placeholder='search' />
+ <input type='text' id='search' placeholder='search' autofocus />
</form>
+ <div id='autocomplete'>
+ </div>
</div>
<div class='right'>
<div id='output'></div>
</div>
- <script src='jquery.js'></script>
+ <script src='js/jquery.js'></script>
+ <script src='js/search.js'></script>
<script>
var indexes = {}, titles;
$.getJSON('titles.json', function(o) {
titles = o;
});
var $output = $('#output');
- $('#search').keyup(function() {
- var v = this.value;
- var norm = v.replace(/[^A-Za-z]/g, '').toLowerCase();
- if (norm.length > 2) {
- var a = norm[0];
- if (!indexes[a]) {
- indexes[a] = {};
- $('#output').text('');
- $.getJSON('indexes/' + a + '.json', function(o) {
- indexes[a] = o;
- });
- } else {
- $output.empty();
- (indexes[a][norm] || []).map(function(i) {
- var d = document.createElement('div');
- d.className = 'result';
- var link = document.createElement('a');
- link.href = 'text/' + i + '.txt';
- var h3 = document.createElement('h3');
- h3.innerHTML = titles[i];
- link.appendChild(h3);
- d.appendChild(link);
- $output.append(d);
- });
+ var $autocomplete = $('#autocomplete');
+ var s = search();
+ $('#search').keyup(function(e) {
+ $autocomplete.empty();
+ s.autocomplete(this.value, function(results) {
+ $autocomplete.empty();
+ for (var i = 0; i < results.length; i++) {
+ var a = document.createElement('a');
+ a.innerHTML = results[i];
+ a.className = 'autocomplete-option';
+ a.onclick = function() {
+ var s = $('#search').val();
+ var terms = s.split(/\s+/);
+ if (!terms) return;
+ terms[terms.length - 1] = this.innerHTML;
+ $('#search').val(terms.join(' ')).keyup().focus();
+ }
+ $autocomplete[0].appendChild(a);
+ }
+ });
+ });
+ $('#search').keyup(function(e) {
+ s.query(this.value, function(results) {
+ $output.empty();
+ for (var i = 0; i < results.length; i++) {
+ var h3 = document.createElement('h3');
+ var a = document.createElement('a');
+ a.href = 'text/' + results[i].id + '.txt'
+ a.innerHTML = results[i].title;
+ h3.appendChild(a);
+ $output[0].appendChild(h3);
}
- } else {
- $output.text('');
- }
+ });
});
</script>
</body>
File renamed without changes.
View
@@ -0,0 +1,139 @@
+function search() {
+ // the search system object
+ var s = {};
+
+ // sharded indexes
+ var indexes = {};
+
+ var titles = {};
+
+ // tries
+ var tries = {};
+
+ function shard(a) {
+ if (!a) return false;
+ return a[0].toLowerCase();
+ }
+
+ // Get a shard.
+ function getindex(a, callback) {
+ if (indexes[shard(a)]) return callback(indexes[shard(a)]);
+
+ $.getJSON('indexes/' + shard(a) + '.json', function(o) {
+ indexes[shard(a)] = o;
+ callback(indexes[shard(a)]);
+ });
+ }
+
+ function gettrie(a, callback) {
+ if (tries[shard(a)]) return callback(tries[shard(a)]);
+
+ $.getJSON('indexes/' + shard(a) + '.json.trie.json', function(o) {
+ tries[shard(a)] = o;
+ callback(tries[shard(a)]);
+ });
+ }
+
+
+ function jointitles(x) {
+ var l = [];
+ for (var i = 0; i < x.length; i++) {
+ l.push({
+ id: x[i],
+ title: titles[x[i]] || ''
+ });
+ }
+ return l;
+ }
+
+ function intersect(a, b) {
+ var c = [];
+ for (var i = 0; i < a.length; i++) {
+ if (b.indexOf(a[i]) !== -1) {
+ c.push(a[i]);
+ }
+ }
+ return c;
+ }
+
+ function cleansplit(q) {
+ var terms = q.split(/\s+/);
+ if (!terms.length) return [];
+ terms = terms.map(function(t) {
+ var clean = t.replace(/[^A-Za-z]/g, '');
+ if (!clean) return false;
+ else return clean.toLowerCase();
+ }).filter(function(t) {
+ return t;
+ });
+ return terms;
+ }
+
+ function isEmpty(obj) {
+ for (var key in obj) return false;
+ return true;
+ }
+
+ function autocomplete(q, callback) {
+ var terms = cleansplit(q);
+ if (!terms) return callback([]);
+ var last = terms.pop();
+ var limit = 20;
+ gettrie(last, function(trie) {
+ var pos = trie;
+ // inch up pos to end
+ var prefix = '';
+ for (var i = 0; i < last.length; i++) {
+ if (pos[last[i]]) {
+ prefix += last[i];
+ pos = pos[last[i]];
+ }
+ }
+ var strs = [];
+ function traverse(pos, prefix) {
+ if (strs.length > limit) return callback(strs);
+ if (isEmpty(pos)) {
+ strs.push(prefix);
+ }
+ for (var i in pos) {
+ traverse(pos[i], prefix + i);
+ }
+ }
+ traverse(pos, prefix);
+ return callback(strs);
+ });
+ }
+
+ function query(q, callback) {
+ var terms = cleansplit(q);
+ if (!terms) return callback([]);
+ function doterm(idx) {
+ var term = terms.pop();
+ getindex(term, function(index) {
+ if (!index[term]) return callback([]);
+ if (idx) {
+ idx = intersect(idx, index[term]);
+ } else {
+ idx = index[term];
+ }
+ if (!idx) return callback([]);
+ if (terms.length) {
+ doterm(idx);
+ } else {
+ return callback(jointitles(idx));
+ }
+
+ });
+ }
+ doterm();
+ }
+
+ s.query = query;
+ s.autocomplete = autocomplete;
+
+ $.getJSON('titles.json', function(t) {
+ titles = t;
+ });
+
+ return s;
+}
File renamed without changes.

0 comments on commit 1909c49

Please sign in to comment.