protodiv demo
[oweals/finalsclub.git] / public / javascripts / protodiv.js
1
2 /*
3 Copyright 2011 Sleepless Software Inc. All rights reserved.
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to
7 deal in the Software without restriction, including without limitation the
8 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 sell copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 IN THE SOFTWARE. 
22 */
23
24
25 ProtoDiv = {}
26
27 ProtoDiv.elem = function(v) {
28         return (typeof v === "string") ? document.getElementById(v) : v
29 }
30
31 ProtoDiv.reduce = function(list, cb) {
32         var i, l = list.length
33         for(i = 0; i < l; i++) 
34                 cb(list[i])
35 }
36
37 ProtoDiv.map = function(node, list, cb) {
38         if(node.hasChildNodes()) {
39                 var kids = node.childNodes
40                 for(var i = 0; i < kids.length; i++) {
41                         var kid = kids[i]
42                         if(cb(kid))
43                                 list.push(kid)
44                         ProtoDiv.map(kid, list, cb)
45                 }
46         }
47 }
48
49 ProtoDiv.substitute = function(s, obj) {
50         for(var key in obj) {
51                 re = new RegExp("__"+key+"__", "g")
52                 s = s.replace(re, obj[key])
53         }
54         return s
55 }
56
57 ProtoDiv.inject = function(id, obj) {
58         var proto = ProtoDiv.elem(id)
59
60         proto.innerHTML = ProtoDiv.substitute(proto.innerHTML, obj)
61
62         for(var i = 0; i < proto.attributes.length; i++) {
63                 var a = proto.attributes[i]
64                 a.textContent = ProtoDiv.substitute(a.textContent, obj)
65         }
66
67         for(var key in obj) {
68                 var c = key.substring(1)
69                 var list = []
70                 switch(key.substring(0,1)) {
71                 case "#":
72                         ProtoDiv.map(proto, list, function(e) {
73                                 return e.id == c
74                         })
75                         ProtoDiv.reduce(list, function(e) {
76                                 e.innerHTML = obj[key]
77                         })
78                         break
79                 case ".":
80                         ProtoDiv.map(proto, list, function(e) {
81                                 return e.className == c
82                         })
83                         ProtoDiv.reduce(list, function(e) {
84                                 e.innerHTML = obj[key]
85                         })
86                         break
87                 }
88         }
89
90         return proto
91 }
92
93 ProtoDiv.replicate = function(id, arr, keep) {
94         var proto = ProtoDiv.elem(id)
95         var sib = proto.nextSibling     // might be null
96         var mom = proto.parentNode
97         if(!(arr instanceof Array))
98                 arr = [arr]
99         var l = arr.length
100         var obj
101         
102         if(proto.origSib === undefined) {
103                 proto.origSib = sib
104                 proto.origDisplay = proto.style.display
105         }
106
107         for(var i = 0; i < l; i++) {
108                 obj = arr[i]
109                 var e = proto.cloneNode(true)
110                 delete e.id
111                 mom.insertBefore(e, sib)
112                 ProtoDiv.inject(e, obj)
113         }
114
115         if(!keep)
116                 proto.style.display = "none"
117
118         return proto
119 }
120
121 ProtoDiv.reset = function(id) {
122         var proto = ProtoDiv.elem(id)
123         if(proto.origSib !== undefined) {
124                 proto.style.display = proto.origDisplay
125                 while(proto.nextSibling !== proto.origSib) {
126                         proto.parentNode.removeChild(proto.nextSibling)
127                 }
128                 delete proto.origSib
129                 delete proto.origDisplay
130         }
131         return proto
132 }
133
134