1<html xmlns="http://www.w3.org/1999/xhtml">
2<!-- NodeIterator basics and filters tests.
3     Originally written by Ian Hickson, Mochi-ified by Zack Weinberg.
4     This file based on 001.xml, 002.xml, and 010.xml from
5       http://hixie.ch/tests/adhoc/dom/traversal/node-iterator/
6     with some additional cases.
7  -->
8<head>
9  <title>DOM Traversal: NodeIterator: Basics and Filters</title>
10  <script src="/tests/SimpleTest/SimpleTest.js"></script>
11  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
12</head>
13<body>
14<p id="display"></p>
15<div id="content" style="display: none">
16<!-- comment -->
17<?body processing instruction?>
18</div>
19<pre id="test">
20<script class="testbody" type="text/javascript"><![CDATA[
21  function compare_arrays(e, f, label) {
22    var length = (e.length > f.length) ? e.length : f.length;
23    for (var i = 0; i < length; i += 1) {
24      if (e[i] > 0)
25        is(f[i], e[i], label + " - index " + i + ": ");
26      else
27        todo_is(f[i], -e[i], label + " - index " + i + ": ");
28    }
29  }
30
31  /** DOM Traversal: NodeIterator: Basics **/
32  // NOTE: If you change the document structure, you have to make sure
33  // the magic numbers in this array (and 'expected_f', below) match.
34  var expected = new Array(9, // document
35                           1, // html
36                           3, 8, // leading comment
37                           3, 1, // head
38                           3, 1, 3, // title
39                           3, 1, // first script tag
40                           3, 1, // stylesheet tag
41                           3,    // close head
42                           3, 1, // body
43                           3, 1, // p#display
44                           3, 1, // div#content
45                           3, 8, // comment
46                           3, 7, // processing instruction
47                           3,    // close div
48                           3, 1, // pre#test
49                           3, 1, 4, // script and CDATA block
50                           -3, -3, -3); // close close close
51                                        // these aren't there
52                                        // not sure why
53  var found = new Array();
54
55  var iterator = document.createNodeIterator(document,
56                                             NodeFilter.SHOW_ALL,
57                                             null);
58  var node;
59
60  // forwards
61  while (node = iterator.nextNode())
62    found.push(node.nodeType);
63  compare_arrays(expected, found, 'basics forward');
64
65  // backwards
66  found.length = 0;
67  while (node = iterator.previousNode())
68    found.unshift(node.nodeType);
69  compare_arrays(expected, found, 'basics backward');
70
71  /** DOM Traversal: NodeIterator: Filters **/
72  function filter(n) {
73    if (n.nodeType == 3) {
74      return NodeFilter.FILTER_SKIP;
75    } else if (n.nodeName == 'body') {
76      return NodeFilter.FILTER_REJECT; // same as _SKIP
77    }
78    return 1; // FILTER_ACCEPT
79  }
80
81  // Same warning applies to this array as to 'expected'.
82  var expect_f = new Array(9, // document
83                           1, // html
84                           8, // leading comment
85                           1, // head
86                           1, // title
87                           1, // first script tag
88                           1, // stylesheet tag
89                           // body skipped
90                           1, // p#display
91                           1, // div#content
92                           8, // comment
93                           // processing instruction skipped
94                           1, // pre#test
95                           1, 4); // script and CDATA block
96
97  found.length = 0;
98  iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL,
99                                         filter);
100
101  // forwards
102  while (node = iterator.nextNode())
103    found.push(node.nodeType);
104  compare_arrays(expect_f, found, 'filtered forward');
105
106  // backwards
107  found.length = 0;
108  while (node = iterator.previousNode())
109    found.unshift(node.nodeType);
110  compare_arrays(expect_f, found, 'filtered backward');
111
112  function checkBadFilter(method, n) {
113    var iter =
114      document.createNodeIterator(document, NodeFilter.SHOW_ALL,
115                                  function() {
116                                    if (n < 0)
117                                      iter.detach();
118                                    return NodeFilter.FILTER_ACCEPT;
119                                  });
120    while (--n >= 0)
121      iter.nextNode();
122    try {
123      iter[method]();
124      ok(true, "Able to call " + method + " on a NodeIterator after calling no-op detach()");
125    } catch (x) { ok(false, x) }
126  }
127  checkBadFilter("nextNode", 2);
128  checkBadFilter("previousNode", 3);
129
130  (function() {
131    // Implementing the scenario outlined in
132    // http://bugzilla.mozilla.org/show_bug.cgi?id=552110#c4
133
134    var iter = (function(filt) {
135      var grandparent = document.createElement("div"),
136          parent = document.createElement("span");
137
138      grandparent.appendChild(parent);
139      parent.appendChild(document.createElement("img"));
140      parent.appendChild(document.createElement("p"));
141
142      return document.createNodeIterator(grandparent,
143                                         NodeFilter.SHOW_ALL,
144                                         filt);
145    })(function(n) {
146      if (n.nodeName != "img")
147        return NodeFilter.FILTER_ACCEPT;
148
149      iter.detach();
150
151      n.parentNode.remove();
152      // Drop any node references passed into this function.
153      for (var i = 0; i < arguments.length; ++i)
154        arguments[i] = null;
155      ok(!n, "arguments[0] = null should have nulled out n");
156
157      // Try to trigger GC.
158      var xhr = new XMLHttpRequest();
159      xhr.open("GET", location.href, false);
160      xhr.send();
161
162      return NodeFilter.FILTER_SKIP;
163    });
164
165    is(iter.nextNode().nodeName, "div",
166       "iter.nextNode() returned the wrong node");
167    is(iter.nextNode().nodeName, "span",
168       "iter.nextNode() returned the wrong node");
169    try {
170      var p = iter.nextNode();
171      ok(false, "iter.nextNode() should have thrown, but instead it returned <" + p.nodeName + ">");
172    } catch (x) { ok(true, x) }
173  })();
174
175]]></script>
176</pre>
177</body>
178</html>
179