├── .gitignore
├── README.md
├── bower.json
├── media
└── octopi.png
├── octopi.js
├── plugins
├── delete.js
└── has.js
└── test
├── test.html
├── test.js
├── test_delete.js
└── test_has.js
/.gitignore:
--------------------------------------------------------------------------------
1 | bower_components/
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # octopi.js
2 |
3 |
4 |
5 | Micro (0.5kB) trie based suggestion generating
6 | library, made with autocompletion, control, and
7 | performance on mobile browsers in mind. Check out
8 | the [demo](https://eugene-eeo.github.io/octopi/demo.html).
9 |
10 | ```js
11 | var oct = new Octopi(['bird', 'boy']);
12 | oct.add('bid', {'word': 'BID'});
13 | oct.get('bi'); // => ['bird', {'word':'BID'}]
14 | ```
15 |
16 | ### Do you even normalise?
17 |
18 | Octopi allows for arbitrary data to be associated
19 | with words added to the tree. This means that you
20 | have full control over normalisation of the words.
21 | For example:
22 |
23 | ```js
24 | word = 'CoolUseRName';
25 | oct.add(word.toLowerCase(), word);
26 | oct.get(word.toLowerCase());
27 | ```
28 |
29 | ### Deleting entries
30 |
31 | You can use the [delete](plugins/delete.js) plugin:
32 |
33 | ```js
34 | oct.delete('bid');
35 | ```
36 |
37 | ### Installation
38 |
39 | ```sh
40 | $ bower install eugenee-eeo/octopi
41 | ```
42 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "octopi",
3 | "main": "octopi.js",
4 | "authors": [
5 | "Eeo Jun <141bytes@gmail.com>"
6 | ],
7 | "description": "micro client-side suggestions library",
8 | "moduleType": [],
9 | "keywords": [
10 | "trie"
11 | ],
12 | "license": "MIT",
13 | "homepage": "github.com/eugene-eeo/octopi",
14 | "ignore": [
15 | "**/.*",
16 | "node_modules",
17 | "bower_components",
18 | "test",
19 | "tests",
20 | "media"
21 | ],
22 | "devDependencies": {
23 | "mocha": "~2.3.4",
24 | "chai": "~3.4.2"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/media/octopi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eugene-eeo/octopi/ade8c4d742a0494327455c0845cf944baf691f72/media/octopi.png
--------------------------------------------------------------------------------
/octopi.js:
--------------------------------------------------------------------------------
1 | Octopi = function(words) {
2 | this.uid = 0;
3 | this.tree = {$$: []};
4 | this.table = {};
5 | words = (words || []);
6 | for (var i = 0; i < words.length; i++)
7 | this.add(words[i]);
8 | };
9 |
10 | /**
11 | * Take serialized Octopi data as string and initialize the Octopi object
12 | * @param json String The serialized Octopi trie
13 | */
14 | Octopi.load = function(json){
15 | var oct = new Octopi();
16 | var o = JSON.parse(json);
17 | oct.uid = o.uid;
18 | oct.tree = o.tree;
19 | oct.table = o.table;
20 | return oct;
21 | }
22 |
23 | Octopi.prototype = {
24 | constructor: Octopi,
25 | /**
26 | * Add a new element to the trie
27 | * @param key String prefix to look up
28 | * @param data Object returned by trie
29 | */
30 | add: function(key, data) {
31 | var id = ++this.uid;
32 | var sub = this.tree;
33 |
34 | this.table[id] = data || key;
35 | sub.$$.push(id);
36 |
37 | for (var i = 0; i < key.length; i++) {
38 | var c = key[i];
39 | sub = sub[c] || (sub[c] = {$$:[]});
40 | sub.$$.push(id);
41 | }
42 | },
43 |
44 | /**
45 | * Return the list of elements in the trie for a given query
46 | * @param key String The prefix to lookup
47 | */
48 | get: function(key) {
49 | var sub = this.tree;
50 | var tbl = this.table;
51 | for (var i = 0; i < key.length; i++)
52 | if (!(sub = sub[key[i]]))
53 | return [];
54 |
55 | return sub.$$.map(function(id) {
56 | return tbl[id];
57 | });
58 | },
59 | /**
60 | * Serialize the Octopi trie as string
61 | *
62 | * @return String
63 | */
64 | serialize: function(){
65 | var o = { uid: this.uid,
66 | tree: this.tree,
67 | table: this.table
68 | }
69 | return JSON.stringify(o);
70 |
71 | }
72 | };
73 |
--------------------------------------------------------------------------------
/plugins/delete.js:
--------------------------------------------------------------------------------
1 | Octopi.prototype.delete = function(key) {
2 | var sub = this.tree;
3 | var trees = [sub];
4 | var length = key.length;
5 |
6 | for (var i = 0; i < length; i++) {
7 | if (!(sub = sub[key[i]]))
8 | return;
9 | trees.push(sub);
10 | }
11 |
12 | var toDelete = sub.$$;
13 |
14 | for (var i = toDelete.length; i--;) {
15 | var id = toDelete[i];
16 |
17 | for (var j = trees.length; j--;) {
18 | var ids = trees[j].$$;
19 | ids.splice(ids.indexOf(id), 1);
20 | if (j && !ids.length)
21 | delete trees[j-1][key[j-1]];
22 | }
23 |
24 | delete this.table[id];
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/plugins/has.js:
--------------------------------------------------------------------------------
1 | Octopi.prototype.has = function(key) {
2 | return !!this.get(key).length;
3 | };
4 |
--------------------------------------------------------------------------------
/test/test.html:
--------------------------------------------------------------------------------
1 |