annotate js/ext/html-emitter.js @ 0:633c9cb05555

Origination.
author Atul Varma <varmaa@toolness.com>
date Sun, 07 Jun 2009 19:29:10 -0700
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
1 // Copyright (C) 2008 Google Inc.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
2 //
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
3 // Licensed under the Apache License, Version 2.0 (the "License");
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
4 // you may not use this file except in compliance with the License.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
5 // You may obtain a copy of the License at
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
6 //
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
7 // http://www.apache.org/licenses/LICENSE-2.0
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
8 //
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
9 // Unless required by applicable law or agreed to in writing, software
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
10 // distributed under the License is distributed on an "AS IS" BASIS,
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
12 // See the License for the specific language governing permissions and
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
13 // limitations under the License.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
14
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
15 /**
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
16 * @fileoverview
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
17 * JavaScript support for TemplateCompiler.java.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
18 * <p>
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
19 * This handles the problem of making sure that only the bits of a Gadget's
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
20 * static HTML which should be visible to a script are visible, and provides
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
21 * mechanisms to reliably find elements using dynamically generated unique IDs
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
22 * in the face of DOM modifications by untrusted scripts.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
23 *
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
24 * @author mikesamuel@gmail.com
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
25 */
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
26 function HtmlEmitter(base, opt_tameDocument) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
27 if (!base) { throw new Error(); }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
28
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
29 /**
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
30 * Contiguous pairs of ex-descendants of base, and their ex-parent.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
31 * The detached elements (even indices) are ordered depth-first.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
32 */
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
33 var detached = null;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
34 /** Makes sure IDs are accessible within removed detached nodes. */
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
35 var idMap = null;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
36
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
37 var arraySplice = Array.prototype.splice;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
38
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
39 function buildIdMap() {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
40 idMap = {};
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
41 var descs = base.getElementsByTagName('*');
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
42 for (var i = 0, desc; (desc = descs[i]); ++i) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
43 if (desc.id) { idMap[desc.id] = desc; }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
44 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
45 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
46 /**
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
47 * Returns the element with the given ID under the base node.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
48 * @param id an auto-generated ID since we cannot rely on user supplied IDs
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
49 * to be unique.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
50 * @return {Element|null} null if no such element exists.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
51 */
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
52 function byId(id) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
53 if (!idMap) { buildIdMap(); }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
54 var node = idMap[id];
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
55 if (node) { return node; }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
56 for (; (node = base.ownerDocument.getElementById(id));) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
57 if (base.contains
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
58 ? base.contains(node)
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
59 : (base.compareDocumentPosition(node) & 0x10)) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
60 idMap[id] = node;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
61 return node;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
62 } else {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
63 node.id = '';
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
64 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
65 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
66 return null;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
67 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
68
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
69 // Below we define the attach, unwrap, and finish operations.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
70 // These obey the conventions that:
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
71 // (1) All detached nodes, along with their ex-parents are in detached,
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
72 // and they are ordered depth-first.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
73 // (2) When a node is specified by an ID, after the operation is performed,
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
74 // it is in the tree.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
75 // (3) Each node is attached to the same parent regardless of what the
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
76 // script does. Even if a node is removed from the DOM by a script,
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
77 // any of its children that appear after the script, will be added.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
78 // As an example, consider this HTML which has the end-tags removed since
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
79 // they don't correspond to actual nodes.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
80 // <table>
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
81 // <script>
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
82 // <tr>
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
83 // <td>Foo<script>Bar
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
84 // <th>Baz
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
85 // <script>
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
86 // <p>The-End
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
87 // There are two script elements, and we need to make sure that each only
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
88 // sees the bits of the DOM that it is supposed to be aware of.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
89 //
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
90 // To make sure that things work when javascript is off, we emit the whole
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
91 // HTML tree, and then detach everything that shouldn't be present.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
92 // We represent the removed bits as pairs of (removedNode, parentItWasPartOf).
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
93 // Including both makes us robust against changes scripts make to the DOM.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
94 // In this case, the detach operation results in the tree
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
95 // <table>
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
96 // and the detached list
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
97 // [<tr><td>FooBar<th>Baz in <table>, <p>The-End in (base)]
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
98
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
99 // After the first script executes, we reattach the bits needed by the second
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
100 // script, which gives us the DOM
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
101 // <table><tr><td>Foo
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
102 // and the detached list
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
103 // ['Bar' in <td>, <th>Baz in <tr>, <p>The-End in (base)]
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
104 // Note that we did not simply remove items from the old detached list. Since
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
105 // the second script was deeper than the first, we had to add only a portion
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
106 // of the <tr>'s content which required doing a separate mini-detach operation
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
107 // and push its operation on to the front of the detached list.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
108
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
109 // After the second script executes, we reattach the bits needed by the third
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
110 // script, which gives us the DOM
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
111 // <table><tr><td>FooBar<th>Baz
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
112 // and the detached list
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
113 // [<p>The-End in (base)]
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
114
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
115 // After the third script executes, we reattached the rest of the detached
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
116 // nodes, and we're done.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
117
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
118 // To perform a detach or reattach operation, we impose a depth-first ordering
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
119 // on HTML start tags, and text nodes:
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
120 // [0: <table>, 1: <tr>, 2: <td>, 3: 'Foo', 4: 'Bar', 5: <th>, 6: 'Baz',
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
121 // 7: <p>, 8: 'The-End']
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
122 // Then the detach operation simply removes the minimal number of nodes from
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
123 // the DOM to make sure that only a prefix of those nodes are present.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
124 // In the case above, we are detaching everything after item 0.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
125 // Then the reattach operation advances the number. In the example above, we
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
126 // advance the index from 0 to 3, and then from 3 to 6.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
127 // The finish operation simply reattaches the rest, advancing the counter from
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
128 // 6 to the end.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
129
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
130 // The minimal detached list from the node with DFS index I is the ordered
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
131 // list such that a (node, parent) pair (N, P) is on the list if
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
132 // dfs-index(N) > I and there is no pair (P, GP) on the list.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
133
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
134 // To calculate the minimal detached list given a node representing a point in
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
135 // that ordering, we rely on the following observations:
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
136 // The minimal detached list after a node, is the concatenation of
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
137 // (1) that node's children in order
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
138 // (2) the next sibling of that node and its later siblings,
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
139 // the next sibling of that node's parent and its later siblings,
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
140 // the next sibling of that node's grandparent and its later siblings,
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
141 // etc., until base is reached.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
142
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
143 function detachOnto(limit, out) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
144 // Set detached to be the minimal set of nodes that have to be removed
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
145 // to make sure that limit is the last attached node in DFS order as
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
146 // specified above.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
147
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
148 // First, store all the children.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
149 for (var child = limit.firstChild, next; child; child = next) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
150 next = child.nextSibling; // removeChild kills nextSibling.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
151 out.push(child, limit);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
152 limit.removeChild(child);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
153 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
154
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
155 // Second, store your ancestor's next siblings and recurse.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
156 for (var anc = limit, greatAnc; anc && anc !== base; anc = greatAnc) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
157 greatAnc = anc.parentNode;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
158 for (var sibling = anc.nextSibling, next; sibling; sibling = next) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
159 next = sibling.nextSibling;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
160 out.push(sibling, greatAnc);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
161 greatAnc.removeChild(sibling);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
162 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
163 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
164 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
165 /**
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
166 * Make sure that everything up to and including the node with the given ID
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
167 * is attached, and that nothing that follows the node is attached.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
168 */
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
169 function attach(id) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
170 var limit = byId(id);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
171 if (detached) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
172 // Build an array of arguments to splice so we can replace the reattached
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
173 // nodes with the nodes detached from limit.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
174 var newDetached = [0, 0];
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
175 // Since limit has no parent, detachOnto will bottom out at its sibling.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
176 detachOnto(limit, newDetached);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
177 // Find the node containing limit that appears on detached.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
178 for (var limitAnc = limit, parent; (parent = limitAnc.parentNode);) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
179 limitAnc = parent;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
180 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
181 // Reattach up to and including limit ancestor.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
182 var nConsumed = 0;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
183 while (true) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
184 var toReattach = detached[nConsumed];
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
185 (detached[nConsumed + 1] /* the parent */).appendChild(toReattach);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
186 nConsumed += 2;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
187 if (toReattach === limitAnc) { break; }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
188 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
189 // Replace the reattached bits with the ones detached from limit.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
190 newDetached[1] = nConsumed; // splice's second arg is the number removed
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
191 arraySplice.apply(detached, newDetached);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
192 } else {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
193 // The first time attach is called, the limit is actually part of the DOM.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
194 // There's no point removing anything when all scripts are deferred.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
195 detached = [];
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
196 detachOnto(limit, detached);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
197 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
198 return limit;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
199 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
200 /**
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
201 * Removes a wrapper from a textNode
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
202 * When a text node immediately precedes a script block, the limit will be
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
203 * a text node. Text nodes can't be addressed by ID, so the TemplateCompiler
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
204 * wraps them in a <span> which must be removed to be semantics preserving.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
205 */
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
206 function unwrap(wrapper) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
207 // Text nodes must have exactly one child, so it must be first on the
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
208 // detached list, since children are earlier than siblings by DFS order.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
209 var text = detached[0];
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
210 // If this is not true, the TemplateCompiler must be generating unwrap calls
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
211 // out of order.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
212 // An untrusted script block should not be able to nuke the wrapper before
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
213 // it's removed so there should be a parentNode.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
214 wrapper.parentNode.replaceChild(text, wrapper);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
215 detached.splice(0, 2);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
216 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
217 /**
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
218 * Reattach any remaining detached bits, free resources, and fire a document
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
219 * loaded event.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
220 */
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
221 function finish() {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
222 if (detached) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
223 for (var i = 0, n = detached.length; i < n; i += 2) {
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
224 detached[i + 1].appendChild(detached[i]);
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
225 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
226 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
227 // Release references so nodes can be garbage collected.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
228 idMap = detached = base = null;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
229
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
230 // Signals the close of the document and fires any window.onload event
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
231 // handlers.
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
232 var doc = opt_tameDocument;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
233 if (doc) { doc.signalLoaded___(); }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
234 return this;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
235 }
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
236
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
237 this.byId = byId;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
238 this.attach = attach;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
239 this.unwrap = unwrap;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
240 this.finish = finish;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
241 this.setAttr = bridal.setAttribute;
633c9cb05555 Origination.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
242 }