| 1 | /**@constructor*/ |
| 2 | function ChainNode(object, link) { |
| 3 | this.value = object; |
| 4 | this.link = link; // describes this node's relationship to the previous node |
| 5 | } |
| 6 | |
| 7 | /**@constructor*/ |
| 8 | function Chain(valueLinks) { |
| 9 | this.nodes = []; |
| 10 | this.cursor = -1; |
| 11 | |
| 12 | if (valueLinks && valueLinks.length > 0) { |
| 13 | this.push(valueLinks[0], "//"); |
| 14 | for (var i = 1, l = valueLinks.length; i < l; i+=2) { |
| 15 | this.push(valueLinks[i+1], valueLinks[i]); |
| 16 | } |
| 17 | } |
| 18 | } |
| 19 | |
| 20 | Chain.prototype.push = function(o, link) { |
| 21 | if (this.nodes.length > 0 && link) this.nodes.push(new ChainNode(o, link)); |
| 22 | else this.nodes.push(new ChainNode(o)); |
| 23 | } |
| 24 | |
| 25 | Chain.prototype.unshift = function(o, link) { |
| 26 | if (this.nodes.length > 0 && link) this.nodes[0].link = link; |
| 27 | this.nodes.unshift(new ChainNode(o)); |
| 28 | this.cursor++; |
| 29 | } |
| 30 | |
| 31 | Chain.prototype.get = function() { |
| 32 | if (this.cursor < 0 || this.cursor > this.nodes.length-1) return null; |
| 33 | return this.nodes[this.cursor]; |
| 34 | } |
| 35 | |
| 36 | Chain.prototype.first = function() { |
| 37 | this.cursor = 0; |
| 38 | return this.get(); |
| 39 | } |
| 40 | |
| 41 | Chain.prototype.last = function() { |
| 42 | this.cursor = this.nodes.length-1; |
| 43 | return this.get(); |
| 44 | } |
| 45 | |
| 46 | Chain.prototype.next = function() { |
| 47 | this.cursor++; |
| 48 | return this.get(); |
| 49 | } |
| 50 | |
| 51 | Chain.prototype.prev = function() { |
| 52 | this.cursor--; |
| 53 | return this.get(); |
| 54 | } |
| 55 | |
| 56 | Chain.prototype.toString = function() { |
| 57 | var string = ""; |
| 58 | for (var i = 0, l = this.nodes.length; i < l; i++) { |
| 59 | if (this.nodes[i].link) string += " -("+this.nodes[i].link+")-> "; |
| 60 | string += this.nodes[i].value.toString(); |
| 61 | } |
| 62 | return string; |
| 63 | } |
| 64 | |
| 65 | Chain.prototype.joinLeft = function() { |
| 66 | var result = ""; |
| 67 | for (var i = 0, l = this.cursor; i < l; i++) { |
| 68 | if (result && this.nodes[i].link) result += this.nodes[i].link; |
| 69 | result += this.nodes[i].value.toString(); |
| 70 | } |
| 71 | return result; |
| 72 | } |
| 73 | |
| 74 | |
| 75 | /* USAGE: |
| 76 | |
| 77 | var path = "one/two/three.four/five-six"; |
| 78 | var pathChain = new Chain(path.split(/([\/.-])/)); |
| 79 | print(pathChain); |
| 80 | |
| 81 | var lineage = new Chain(); |
| 82 | lineage.push("Port"); |
| 83 | lineage.push("Les", "son"); |
| 84 | lineage.push("Dawn", "daughter"); |
| 85 | lineage.unshift("Purdie", "son"); |
| 86 | |
| 87 | print(lineage); |
| 88 | |
| 89 | // walk left |
| 90 | for (var node = lineage.last(); node !== null; node = lineage.prev()) { |
| 91 | print("< "+node.value); |
| 92 | } |
| 93 | |
| 94 | // walk right |
| 95 | var node = lineage.first() |
| 96 | while (node !== null) { |
| 97 | print(node.value); |
| 98 | node = lineage.next(); |
| 99 | if (node && node.link) print("had a "+node.link+" named"); |
| 100 | } |
| 101 | |
| 102 | */ |