|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <head> |
|
4 <meta charset="utf-8"> |
|
5 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
6 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> |
|
7 </head> |
|
8 <body onload="startTest()"> |
|
9 <p id="display"></p> |
|
10 <script> |
|
11 // Global variables we want eval() to be able to reference from anywhere |
|
12 var f1d; |
|
13 var text; |
|
14 var suppressedText; |
|
15 var suppressedText2; |
|
16 var comment; |
|
17 var fragment; |
|
18 var openedWindow; |
|
19 var zeroPoint = new DOMPoint(0,0); |
|
20 var zeroRect = new DOMRect(0,0,0,0); |
|
21 var zeroQuad = new DOMQuad(zeroRect); |
|
22 var notInDocument = document.createElement('div'); |
|
23 |
|
24 function isEval(expr, b) { |
|
25 is(eval(expr), b, expr); |
|
26 } |
|
27 |
|
28 function isApprox(a, b, msg, options) { |
|
29 if (a != b && 'tolerance' in options && |
|
30 Math.abs(a - b) < options.tolerance) { |
|
31 ok(true, msg + "(" + a + " within " + options.tolerance + " of " + b + ")"); |
|
32 return; |
|
33 } |
|
34 is(a, b, msg); |
|
35 } |
|
36 |
|
37 function makeQuadsExpr(fromStr, options) { |
|
38 var getBoxQuadsOptionParts = []; |
|
39 if ('box' in options) { |
|
40 getBoxQuadsOptionParts.push("box:'" + options.box + "'"); |
|
41 } |
|
42 if ('toStr' in options) { |
|
43 getBoxQuadsOptionParts.push("relativeTo:" + options.toStr); |
|
44 } |
|
45 return fromStr + ".getBoxQuads({" + getBoxQuadsOptionParts.join(',') + "})"; |
|
46 } |
|
47 |
|
48 function makePointExpr(fromStr, options, x, y) { |
|
49 var convertPointOptionParts = []; |
|
50 if ('box' in options) { |
|
51 convertPointOptionParts.push("fromBox:'" + options.box + "'"); |
|
52 } |
|
53 if ('toBox' in options) { |
|
54 convertPointOptionParts.push("toBox:'" + options.toBox + "'"); |
|
55 } |
|
56 return ('toStr' in options ? options.toStr : "document") + |
|
57 ".convertPointFromNode(new DOMPoint(" + x + "," + y + ")," + fromStr + ",{" + |
|
58 convertPointOptionParts.join(",") + "})"; |
|
59 } |
|
60 |
|
61 function checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) { |
|
62 var selfQuads = eval(fromStr).getBoxQuads( |
|
63 {box:options.box == "" ? "border" : options.box, |
|
64 relativeTo:eval(fromStr)}); |
|
65 var boxWidth = selfQuads[0].bounds.width; |
|
66 var boxHeight = selfQuads[0].bounds.height; |
|
67 |
|
68 var convertTopLeftPointExpr = makePointExpr(fromStr, options, 0, 0); |
|
69 var topLeft = eval(convertTopLeftPointExpr); |
|
70 isApprox(topLeft.x, x1, convertTopLeftPointExpr + ".x", options); |
|
71 isApprox(topLeft.y, y1, convertTopLeftPointExpr + ".y", options); |
|
72 |
|
73 var convertTopRightPointExpr = makePointExpr(fromStr, options, boxWidth, 0); |
|
74 var topRight = eval(convertTopRightPointExpr); |
|
75 isApprox(topRight.x, x2, convertTopRightPointExpr + ".x", options); |
|
76 isApprox(topRight.y, y2, convertTopRightPointExpr + ".y", options); |
|
77 |
|
78 var convertBottomRightPointExpr = makePointExpr(fromStr, options, boxWidth, boxHeight); |
|
79 var bottomRight = eval(convertBottomRightPointExpr); |
|
80 isApprox(bottomRight.x, x3, convertBottomRightPointExpr + ".x", options); |
|
81 isApprox(bottomRight.y, y3, convertBottomRightPointExpr + ".y", options); |
|
82 |
|
83 var convertBottomLeftPointExpr = makePointExpr(fromStr, options, 0, boxHeight); |
|
84 var bottomLeft = eval(convertBottomLeftPointExpr); |
|
85 isApprox(bottomLeft.x, x4, convertBottomLeftPointExpr + ".x", options); |
|
86 isApprox(bottomLeft.y, y4, convertBottomLeftPointExpr + ".y", options); |
|
87 } |
|
88 |
|
89 function checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) { |
|
90 var selfQuads = eval(fromStr).getBoxQuads( |
|
91 {box:options.box == "" ? "border" : options.box, |
|
92 relativeTo:eval(fromStr)}); |
|
93 var boxWidth = selfQuads[0].bounds.width; |
|
94 var boxHeight = selfQuads[0].bounds.height; |
|
95 |
|
96 var convertPointOptionParts = []; |
|
97 if ('box' in options) { |
|
98 convertPointOptionParts.push("fromBox:'" + options.box + "'"); |
|
99 } |
|
100 if ('toBox' in options) { |
|
101 convertPointOptionParts.push("toBox:'" + options.toBox + "'"); |
|
102 } |
|
103 |
|
104 var convertRectExpr = ('toStr' in options ? options.toStr : "document") + |
|
105 ".convertRectFromNode(new DOMRect(0,0," + boxWidth + "," + boxHeight + ")," + |
|
106 fromStr + ",{" + convertPointOptionParts.join(",") + "})"; |
|
107 var quad = eval(convertRectExpr); |
|
108 isApprox(quad.p1.x, x1, convertRectExpr + ".p1.x", options); |
|
109 isApprox(quad.p1.y, y1, convertRectExpr + ".p1.y", options); |
|
110 isApprox(quad.p2.x, x2, convertRectExpr + ".p2.x", options); |
|
111 isApprox(quad.p2.y, y2, convertRectExpr + ".p2.y", options); |
|
112 isApprox(quad.p3.x, x3, convertRectExpr + ".p3.x", options); |
|
113 isApprox(quad.p3.y, y3, convertRectExpr + ".p3.y", options); |
|
114 isApprox(quad.p4.x, x4, convertRectExpr + ".p4.x", options); |
|
115 isApprox(quad.p4.y, y4, convertRectExpr + ".p4.y", options); |
|
116 } |
|
117 |
|
118 function checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) { |
|
119 var selfQuads = eval(fromStr).getBoxQuads( |
|
120 {box:options.box == "" ? "border" : options.box, |
|
121 relativeTo:eval(fromStr)}); |
|
122 var boxWidth = selfQuads[0].bounds.width; |
|
123 var boxHeight = selfQuads[0].bounds.height; |
|
124 |
|
125 var convertPointOptionParts = []; |
|
126 if ('box' in options) { |
|
127 convertPointOptionParts.push("fromBox:'" + options.box + "'"); |
|
128 } |
|
129 if ('toBox' in options) { |
|
130 convertPointOptionParts.push("toBox:'" + options.toBox + "'"); |
|
131 } |
|
132 |
|
133 var convertQuadExpr = ('toStr' in options ? options.toStr : "document") + |
|
134 ".convertQuadFromNode(new DOMQuad(new DOMRect(0,0," + boxWidth + "," + boxHeight + "))," + |
|
135 fromStr + ",{" + convertPointOptionParts.join(",") + "})"; |
|
136 var quad = eval(convertQuadExpr); |
|
137 isApprox(quad.p1.x, x1, convertQuadExpr + ".p1.x", options); |
|
138 isApprox(quad.p1.y, y1, convertQuadExpr + ".p1.y", options); |
|
139 isApprox(quad.p2.x, x2, convertQuadExpr + ".p2.x", options); |
|
140 isApprox(quad.p2.y, y2, convertQuadExpr + ".p2.y", options); |
|
141 isApprox(quad.p3.x, x3, convertQuadExpr + ".p3.x", options); |
|
142 isApprox(quad.p3.y, y3, convertQuadExpr + ".p3.y", options); |
|
143 isApprox(quad.p4.x, x4, convertQuadExpr + ".p4.x", options); |
|
144 isApprox(quad.p4.y, y4, convertQuadExpr + ".p4.y", options); |
|
145 } |
|
146 |
|
147 function checkQuadIsRect(fromStr, options, x, y, w, h) { |
|
148 var quadsExpr = makeQuadsExpr(fromStr, options); |
|
149 var quads = eval(quadsExpr); |
|
150 is(quads.length, 1, quadsExpr + " checking quad count"); |
|
151 var q = quads[0]; |
|
152 isApprox(q.p1.x, x, quadsExpr + " checking quad.p1.x", options); |
|
153 isApprox(q.p1.y, y, quadsExpr + " checking quad.p1.y", options); |
|
154 isApprox(q.p2.x, x + w, quadsExpr + " checking quad.p2.x", options); |
|
155 isApprox(q.p2.y, y, quadsExpr + " checking quad.p2.y", options); |
|
156 isApprox(q.p3.x, x + w, quadsExpr + " checking quad.p3.x", options); |
|
157 isApprox(q.p3.y, y + h, quadsExpr + " checking quad.p3.y", options); |
|
158 isApprox(q.p4.x, x, quadsExpr + " checking quad.p4.x", options); |
|
159 isApprox(q.p4.y, y + h, quadsExpr + " checking quad.p4.y", options); |
|
160 |
|
161 isApprox(q.bounds.left, x, quadsExpr + " checking quad.bounds.left", options); |
|
162 isApprox(q.bounds.top, y, quadsExpr + " checking quad.bounds.top", options); |
|
163 isApprox(q.bounds.width, w, quadsExpr + " checking quad.bounds.width", options); |
|
164 isApprox(q.bounds.height, h, quadsExpr + " checking quad.bounds.height", options); |
|
165 |
|
166 checkConvertPoints(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h); |
|
167 checkConvertRect(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h); |
|
168 checkConvertQuad(fromStr, options, x, y, x + w, y, x + w, y + h, x, y + h); |
|
169 } |
|
170 |
|
171 function checkQuadIsQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4) { |
|
172 var quadsExpr = makeQuadsExpr(fromStr, options); |
|
173 var quads = eval(quadsExpr); |
|
174 is(quads.length, 1, quadsExpr + " checking quad count"); |
|
175 var q = quads[0]; |
|
176 isApprox(q.p1.x, x1, quadsExpr + " checking quad.p1.x", options); |
|
177 isApprox(q.p1.y, y1, quadsExpr + " checking quad.p1.y", options); |
|
178 isApprox(q.p2.x, x2, quadsExpr + " checking quad.p2.x", options); |
|
179 isApprox(q.p2.y, y2, quadsExpr + " checking quad.p2.y", options); |
|
180 isApprox(q.p3.x, x3, quadsExpr + " checking quad.p3.x", options); |
|
181 isApprox(q.p3.y, y3, quadsExpr + " checking quad.p3.y", options); |
|
182 isApprox(q.p4.x, x4, quadsExpr + " checking quad.p4.x", options); |
|
183 isApprox(q.p4.y, y4, quadsExpr + " checking quad.p4.y", options); |
|
184 |
|
185 isApprox(q.bounds.left, Math.min(x1,x2,x3,x4), quadsExpr + " checking quad.bounds.left", options); |
|
186 isApprox(q.bounds.top, Math.min(y1,y2,y3,y4), quadsExpr + " checking quad.bounds.top", options); |
|
187 isApprox(q.bounds.right, Math.max(x1,x2,x3,x4), quadsExpr + " checking quad.bounds.right", options); |
|
188 isApprox(q.bounds.bottom, Math.max(y1,y2,y3,y4), quadsExpr + " checking quad.bounds.bottom", options); |
|
189 |
|
190 checkConvertPoints(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4); |
|
191 checkConvertRect(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4); |
|
192 checkConvertQuad(fromStr, options, x1, y1, x2, y2, x3, y3, x4, y4); |
|
193 } |
|
194 |
|
195 function checkException(expr, name) { |
|
196 try { |
|
197 eval(expr); |
|
198 ok(false, "Exception should have been thrown for " + expr); |
|
199 } catch (ex) { |
|
200 is(ex.name, name, "Checking exception type for " + expr); |
|
201 } |
|
202 } |
|
203 |
|
204 function checkNotFound(fromStr, toStr, x1, y1, x2, y2) { |
|
205 var convertPointExpr = toStr + ".convertPointFromNode(new DOMPoint(" + x1 + |
|
206 "," + y1 + ")," + fromStr + ")"; |
|
207 checkException(convertPointExpr, "NotFoundError"); |
|
208 |
|
209 var convertRectExpr = toStr + ".convertRectFromNode(new DOMRect(" + x1 + |
|
210 "," + y1 + "," + x2 + "," + y2 + ")," + fromStr + ")"; |
|
211 checkException(convertRectExpr, "NotFoundError"); |
|
212 |
|
213 var convertQuadExpr = toStr + ".convertQuadFromNode(new DOMQuad(new DOMRect(" + x1 + |
|
214 "," + y1 + "," + x2 + "," + y2 + "))," + fromStr + ")"; |
|
215 checkException(convertQuadExpr, "NotFoundError"); |
|
216 } |
|
217 </script> |
|
218 <style> |
|
219 em { |
|
220 display:inline-block; height:10px; background:gray; |
|
221 } |
|
222 </style> |
|
223 <div id="dContainer" |
|
224 style="padding:13px 14px 15px 16px; |
|
225 border-width:17px 18px 19px 20px; border-style:solid; border-color:yellow; |
|
226 margin:21px 22px 23px 24px;"> |
|
227 <div id="d" |
|
228 style="width:120px; height:90px; padding:1px 2px 3px 4px; |
|
229 border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow; |
|
230 margin:9px 10px 11px 12px; background:blue;"> |
|
231 </div> |
|
232 </div> |
|
233 |
|
234 <div id="dUnrelated" style="width:50px; height:50px;"></div> |
|
235 |
|
236 <iframe id="f1" style="width:50px; height:50px; border:0; background:lime;" |
|
237 src="data:text/html,<!DOCTYPE HTML><html style='padding:25px'><div id='f1d' style='position:absolute; left:14px; top:15px; width:16px; height:17px; background:pink'></div>"> |
|
238 </iframe> |
|
239 <!-- |
|
240 It matters that the first part of this span is on the same line as the above <iframe>! |
|
241 That ensures the first quad's X position is not equal to the anonymous block's X position. |
|
242 --> |
|
243 <span id="ibSplit" |
|
244 ><em id="ibSplitPart1" style="width:100px;"></em |
|
245 ><div style="width:110px; height:20px; background:black"></div |
|
246 ><em style="width:130px;"></em></span> |
|
247 |
|
248 <table cellspacing="0" id="table" style="border:0; margin:0; padding:0; background:orange"> |
|
249 <tbody style="padding:0; margin:0; border:0; background:blue"> |
|
250 <tr style="height:50px; padding:0; margin:0; border:0"> |
|
251 <td style="border:0; margin:0; padding:0">Cell</td> |
|
252 </tr> |
|
253 </tbody> |
|
254 <caption style="height:40px; background:yellow">Caption</caption> |
|
255 </table> |
|
256 |
|
257 <div style="height:80px; -moz-column-count:2; -moz-column-fill:auto; border:2px solid black;"> |
|
258 <div style="height:20px;"></div> |
|
259 <div id="colSplit" style="height:80px; background:blue; border:10px solid red; border-bottom-width:15px"></div> |
|
260 </div> |
|
261 |
|
262 <div style="width:200px; border:2px solid black;" |
|
263 ><em style="width:150px;"></em |
|
264 ><span id="inlineSplit" style="background:pink; border:10px solid red; border-right-width:15px" |
|
265 ><em style="width:20px; background:green"></em><em style="width:60px"></em |
|
266 ></span |
|
267 ></div> |
|
268 |
|
269 <div style="width:200px; border:2px solid black;" |
|
270 ><em style="width:150px;"></em |
|
271 ><span id="textContainer">T |
|
272 TextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextTextText</span |
|
273 ></div> |
|
274 |
|
275 <div id="suppressedTextContainer"> </div> |
|
276 <div id="suppressedTextContainer2"> </div> |
|
277 |
|
278 <div id="commentContainer"><!-- COMMENT --></div> |
|
279 |
|
280 <div id="displayNone" style="display:none"></div> |
|
281 |
|
282 <div id="overflowHidden" |
|
283 style="overflow:hidden; width:120px; height:90px; padding:1px 2px 3px 4px; |
|
284 border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow; |
|
285 margin:9px 10px 11px 12px; background:blue;"> |
|
286 <div style="height:400px; background:lime;"></div> |
|
287 </div> |
|
288 |
|
289 <div id="overflowScroll" |
|
290 style="overflow:scroll; width:120px; height:90px; padding:1px 2px 3px 4px; |
|
291 border-width:5px 6px 7px 8px; border-style:solid; border-color:yellow; |
|
292 margin:9px 10px 11px 12px; background:blue; background-clip:content-box;"> |
|
293 <div id="overflowScrollChild" style="height:400px;"></div> |
|
294 </div> |
|
295 |
|
296 <div id="scaleTransformContainer" style="width:200px; height:200px;"> |
|
297 <div id="scaleTransform" |
|
298 style="transform:scale(2); transform-origin:top left; width:70px; height:80px; background:yellow"></div> |
|
299 </div> |
|
300 |
|
301 <div id="translateTransformContainer" style="width:200px; height:200px;"> |
|
302 <div id="translateTransform" |
|
303 style="transform:translate(30px,40px); width:70px; height:80px; background:yellow"></div> |
|
304 </div> |
|
305 |
|
306 <div id="rotateTransformContainer" style="width:200px; height:200px;"> |
|
307 <div id="rotateTransform" |
|
308 style="transform:rotate(90deg); width:70px; height:80px; background:yellow"></div> |
|
309 </div> |
|
310 |
|
311 <div id="flipTransformContainer" style="width:200px; height:200px;"> |
|
312 <div id="flipTransform" |
|
313 style="transform:scaleY(-1); width:70px; height:80px; background:yellow"></div> |
|
314 </div> |
|
315 |
|
316 <div id="rot45TransformContainer" style="width:200px; height:200px;"> |
|
317 <div id="rot45Transform" |
|
318 style="transform:rotate(45deg); width:100px; height:100px; background:yellow"></div> |
|
319 </div> |
|
320 |
|
321 <div id="singularTransform" style="transform:scale(0); width:200px; height:200px;"> |
|
322 <div id="singularTransformChild1" style="height:50px;"></div> |
|
323 <div id="singularTransformChild2" style="height:50px;"></div> |
|
324 </div> |
|
325 |
|
326 <div id="threeDTransformContainer" style="perspective:600px; width:200px; height:200px"> |
|
327 <div id="threeDTransform" style="transform:rotateY(70deg); background:yellow; height:100px; perspective:600px"> |
|
328 <div id="threeDTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div> |
|
329 </div> |
|
330 </div> |
|
331 |
|
332 <div id="preserve3DTransformContainer" style="perspective:600px; width:200px; height:200px"> |
|
333 <div id="preserve3DTransform" style="transform:rotateY(70deg); transform-style:preserve-3d; background:yellow; height:100px;"> |
|
334 <div id="preserve3DTransformChild" style="transform:rotateY(-70deg); background:blue; height:50px;"></div> |
|
335 </div> |
|
336 </div> |
|
337 |
|
338 <div id="svgContainer"> |
|
339 <svg id="svg" style="width:200px; height:200px; background:lightgray;"> |
|
340 <circle id="circle" cx="50" cy="50" r="20" fill="red" style="margin:20px; padding:10px; border:15px solid black"></circle> |
|
341 <g transform="scale(2)"> |
|
342 <foreignObject x="50" y="20"> |
|
343 <div id="foreign" style="width:100px; height:60px; background:purple"></div> |
|
344 </foreignObject> |
|
345 </g> |
|
346 </svg> |
|
347 </div> |
|
348 |
|
349 <script> |
|
350 SimpleTest.waitForExplicitFinish(); |
|
351 |
|
352 window.scrollTo(0,0); |
|
353 |
|
354 function startTest() { |
|
355 SpecialPowers.pushPrefEnv({"set": [["layout.css.DOMPoint.enabled", true], |
|
356 ["layout.css.DOMQuad.enabled", true], |
|
357 ["layout.css.getBoxQuads.enabled", true], |
|
358 ["layout.css.convertFromNode.enabled", true]]}, runTest); |
|
359 } |
|
360 |
|
361 function runTest() { |
|
362 // Setup globals |
|
363 f1d = f1.contentWindow.f1d; |
|
364 text = textContainer.firstChild; |
|
365 suppressedText = suppressedTextContainer.firstChild; |
|
366 suppressedText2 = suppressedTextContainer2.firstChild; |
|
367 comment = commentContainer.firstChild; |
|
368 fragment = document.createDocumentFragment(); |
|
369 |
|
370 // Test basic BoxQuadOptions.box. |
|
371 var dX = d.getBoundingClientRect().left; |
|
372 var dY = d.getBoundingClientRect().top; |
|
373 var dW = d.getBoundingClientRect().width; |
|
374 var dH = d.getBoundingClientRect().height; |
|
375 |
|
376 checkQuadIsRect("d", {box:"content"}, |
|
377 dX + 4 + 8, dY + 1 + 5, 120, 90); |
|
378 checkQuadIsRect("d", {box:"padding"}, |
|
379 dX + 8, dY + 5, 120 + 2 + 4, 90 + 1 + 3); |
|
380 checkQuadIsRect("d", {box:"border"}, |
|
381 dX, dY, dW, dH); |
|
382 checkQuadIsRect("d", {}, |
|
383 dX, dY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); |
|
384 checkQuadIsRect("d", {box:"margin"}, |
|
385 dX - 12, dY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11); |
|
386 |
|
387 // Test basic BoxQuadOptions.relativeTo |
|
388 checkQuadIsRect("d", {toStr:"dContainer"}, |
|
389 12 + 16 + 20, 9 + 13 + 17, dW, dH); |
|
390 |
|
391 // Test BoxQuadOptions.relativeTo relative to this document |
|
392 checkQuadIsRect("d", {toStr:"document"}, |
|
393 dX, dY, dW, dH); |
|
394 // Test BoxQuadOptions.relativeTo relative to a non-ancestor. |
|
395 var dUnrelatedX = dUnrelated.getBoundingClientRect().left; |
|
396 var dUnrelatedY = dUnrelated.getBoundingClientRect().top; |
|
397 checkQuadIsRect("d", {toStr:"dUnrelated"}, |
|
398 dX - dUnrelatedX, dY - dUnrelatedY, dW, dH); |
|
399 // Test BoxQuadOptions.relativeTo relative to an element in a different document (and the document) |
|
400 var f1X = f1.getBoundingClientRect().left; |
|
401 var f1Y = f1.getBoundingClientRect().top; |
|
402 checkQuadIsRect("d", {toStr:"f1.contentWindow.f1d"}, |
|
403 dX - (f1X + 14), dY - (f1Y + 15), dW, dH); |
|
404 checkQuadIsRect("d", {toStr:"f1.contentDocument"}, |
|
405 dX - f1X, dY - f1Y, dW, dH); |
|
406 // Test one document relative to another |
|
407 checkQuadIsRect("f1.contentDocument", {toStr:"document"}, |
|
408 f1X, f1Y, 50, 50); |
|
409 // The box type is irrelevant for a document |
|
410 checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"content"}, |
|
411 f1X, f1Y, 50, 50); |
|
412 checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"margin"}, |
|
413 f1X, f1Y, 50, 50); |
|
414 checkQuadIsRect("f1.contentDocument", {toStr:"document",box:"padding"}, |
|
415 f1X, f1Y, 50, 50); |
|
416 |
|
417 // Test that anonymous boxes are correctly ignored when building quads. |
|
418 var ibSplitPart1X = ibSplitPart1.getBoundingClientRect().left; |
|
419 var ibSplitY = ibSplit.getBoundingClientRect().top; |
|
420 isEval("ibSplit.getBoxQuads().length", 3); |
|
421 isEval("ibSplit.getBoxQuads()[0].bounds.left", ibSplitPart1X); |
|
422 isEval("ibSplit.getBoxQuads()[0].bounds.width", 100); |
|
423 isEval("ibSplit.getBoxQuads()[1].bounds.width", 110); |
|
424 isEval("ibSplit.getBoxQuads()[2].bounds.width", 130); |
|
425 isEval("table.getBoxQuads().length", 2); |
|
426 isEval("table.getBoxQuads()[0].bounds.height", 50); |
|
427 isEval("table.getBoxQuads()[1].bounds.height", 40); |
|
428 |
|
429 // Test that we skip anonymous boxes when finding the right box to be relative to. |
|
430 checkQuadIsRect("d", {toStr:"ibSplit"}, |
|
431 dX - ibSplitPart1X, dY - ibSplitY, dW, dH); |
|
432 var tableX = table.getClientRects()[0].left; |
|
433 var tableY = table.getClientRects()[0].top; |
|
434 checkQuadIsRect("d", {toStr:"table"}, |
|
435 dX - tableX, dY - tableY, dW, dH); |
|
436 isEval("ibSplit.convertPointFromNode(zeroPoint,d).x", dX - ibSplitPart1X); |
|
437 isEval("table.convertPointFromNode(zeroPoint,d).x", dX - table.getClientRects()[0].left); |
|
438 |
|
439 // Test boxes generated by block splitting. Check for borders being placed correctly. |
|
440 var colSplitY = colSplit.getClientRects()[0].top; |
|
441 isEval("colSplit.getBoxQuads().length", 2); |
|
442 isEval("colSplit.getBoxQuads()[0].bounds.top", colSplitY); |
|
443 isEval("colSplit.getBoxQuads()[0].bounds.height", 60); |
|
444 isEval("colSplit.getBoxQuads()[1].bounds.top", colSplitY - 20); |
|
445 isEval("colSplit.getBoxQuads()[1].bounds.height", 45); |
|
446 isEval("colSplit.getBoxQuads({box:'content'}).length", 2); |
|
447 // The first box for the block has the top border; the second box has the bottom border. |
|
448 isEval("colSplit.getBoxQuads({box:'content'})[0].bounds.top", colSplitY + 10); |
|
449 isEval("colSplit.getBoxQuads({box:'content'})[0].bounds.height", 50); |
|
450 isEval("colSplit.getBoxQuads({box:'content'})[1].bounds.top", colSplitY - 20); |
|
451 isEval("colSplit.getBoxQuads({box:'content'})[1].bounds.height", 30); |
|
452 |
|
453 var inlineSplitX = inlineSplit.getClientRects()[0].left; |
|
454 isEval("inlineSplit.getBoxQuads().length", 2); |
|
455 isEval("inlineSplit.getBoxQuads()[0].bounds.left", inlineSplitX); |
|
456 isEval("inlineSplit.getBoxQuads()[0].bounds.width", 30); |
|
457 isEval("inlineSplit.getBoxQuads()[1].bounds.left", inlineSplitX - 150); |
|
458 isEval("inlineSplit.getBoxQuads()[1].bounds.width", 75); |
|
459 isEval("inlineSplit.getBoxQuads({box:'content'}).length", 2); |
|
460 // The first box for the inline has the left border; the second box has the right border. |
|
461 isEval("inlineSplit.getBoxQuads({box:'content'})[0].bounds.left", inlineSplitX + 10); |
|
462 isEval("inlineSplit.getBoxQuads({box:'content'})[0].bounds.width", 20); |
|
463 isEval("inlineSplit.getBoxQuads({box:'content'})[1].bounds.left", inlineSplitX - 150); |
|
464 isEval("inlineSplit.getBoxQuads({box:'content'})[1].bounds.width", 60); |
|
465 |
|
466 var textX = textContainer.getClientRects()[0].left; |
|
467 isEval("text.getBoxQuads().length", 2); |
|
468 isEval("text.getBoxQuads()[0].bounds.left", textX); |
|
469 isEval("text.getBoxQuads()[1].bounds.left", textX - 150); |
|
470 // Box types are irrelevant for text |
|
471 isEval("text.getBoxQuads({box:'content'}).length", 2); |
|
472 isEval("text.getBoxQuads({box:'content'})[0].bounds.left", textX); |
|
473 isEval("text.getBoxQuads({box:'content'})[1].bounds.left", textX - 150); |
|
474 isEval("text.getBoxQuads({box:'padding'}).length", 2); |
|
475 isEval("text.getBoxQuads({box:'padding'})[0].bounds.left", textX); |
|
476 isEval("text.getBoxQuads({box:'padding'})[1].bounds.left", textX - 150); |
|
477 isEval("text.getBoxQuads({box:'margin'}).length", 2); |
|
478 isEval("text.getBoxQuads({box:'margin'})[0].bounds.left", textX); |
|
479 isEval("text.getBoxQuads({box:'margin'})[1].bounds.left", textX - 150); |
|
480 |
|
481 // Check that a text node whose layout might have been optimized away gives |
|
482 // correct results. |
|
483 var suppressedTextContainerX = suppressedTextContainer.getBoundingClientRect().left; |
|
484 isEval("suppressedText.getBoxQuads().length", 1); |
|
485 isEval("suppressedText.getBoxQuads()[0].bounds.left", suppressedTextContainerX); |
|
486 isEval("suppressedText.getBoxQuads()[0].bounds.width", 0); |
|
487 |
|
488 var suppressedTextContainer2X = suppressedTextContainer2.getBoundingClientRect().left; |
|
489 isEval("document.convertPointFromNode(zeroPoint,suppressedText2).x", |
|
490 suppressedTextContainer2X); |
|
491 |
|
492 checkException("comment.getBoxQuads()", "TypeError"); |
|
493 checkException("d.getBoxQuads({relativeTo:comment})", "TypeError"); |
|
494 checkException("comment.convertPointFromNode(zeroPoint,document)", "TypeError"); |
|
495 checkException("document.convertPointFromNode(zeroPoint,comment)", "TypeError"); |
|
496 checkException("comment.convertRectFromNode(zeroRect,document)", "TypeError"); |
|
497 checkException("document.convertRectFromNode(zeroRect,comment)", "TypeError"); |
|
498 checkException("comment.convertQuadFromNode(zeroQuad,document)", "TypeError"); |
|
499 checkException("document.convertQuadFromNode(zeroQuad,comment)", "TypeError"); |
|
500 |
|
501 checkException("fragment.getBoxQuads()", "TypeError"); |
|
502 checkException("d.getBoxQuads({relativeTo:fragment})", "TypeError"); |
|
503 checkException("fragment.convertPointFromNode(zeroPoint,document)", "TypeError"); |
|
504 checkException("document.convertPointFromNode(zeroPoint,fragment)", "TypeError"); |
|
505 checkException("fragment.convertRectFromNode(zeroRect,document)", "TypeError"); |
|
506 checkException("document.convertRectFromNode(zeroRect,fragment)", "TypeError"); |
|
507 checkException("fragment.convertQuadFromNode(zeroQuad,document)", "TypeError"); |
|
508 checkException("document.convertQuadFromNode(zeroQuad,fragment)", "TypeError"); |
|
509 |
|
510 isEval("displayNone.getBoxQuads().length", 0); |
|
511 isEval("notInDocument.getBoxQuads().length", 0); |
|
512 checkNotFound("displayNone", "document", 1, 2, 3, 4); |
|
513 checkNotFound("notInDocument", "document", 1, 2, 3, 4); |
|
514 checkNotFound("document", "displayNone", 1, 2, 3, 4); |
|
515 checkNotFound("document", "notInDocument", 1, 2, 3, 4); |
|
516 |
|
517 // Test an overflow:hidden version of d. overflow:hidden should not affect |
|
518 // the quads, basically. |
|
519 var oHX = overflowHidden.getBoundingClientRect().left; |
|
520 var oHY = overflowHidden.getBoundingClientRect().top; |
|
521 checkQuadIsRect("overflowHidden", {box:"content"}, |
|
522 oHX + 4 + 8, oHY + 1 + 5, 120, 90); |
|
523 checkQuadIsRect("overflowHidden", {box:"padding"}, |
|
524 oHX + 8, oHY + 5, 120 + 2 + 4, 90 + 1 + 3); |
|
525 checkQuadIsRect("overflowHidden", {box:"border"}, |
|
526 oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); |
|
527 checkQuadIsRect("overflowHidden", {}, |
|
528 oHX, oHY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); |
|
529 checkQuadIsRect("overflowHidden", {box:"margin"}, |
|
530 oHX - 12, oHY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11); |
|
531 |
|
532 // Test an overflow:scroll version of d. I assume that boxes aren't affected |
|
533 // by the scrollbar although it's not clear that this is correct. |
|
534 var oSX = overflowScroll.getBoundingClientRect().left; |
|
535 var oSY = overflowScroll.getBoundingClientRect().top; |
|
536 checkQuadIsRect("overflowScroll", {box:"content"}, |
|
537 oSX + 4 + 8, oSY + 1 + 5, 120, 90); |
|
538 checkQuadIsRect("overflowScroll", {box:"padding"}, |
|
539 oSX + 8, oSY + 5, 120 + 2 + 4, 90 + 1 + 3); |
|
540 checkQuadIsRect("overflowScroll", {box:"border"}, |
|
541 oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); |
|
542 checkQuadIsRect("overflowScroll", {}, |
|
543 oSX, oSY, 120 + 2 + 4 + 6 + 8, 90 + 1 + 3 + 5 + 7); |
|
544 checkQuadIsRect("overflowScroll", {box:"margin"}, |
|
545 oSX - 12, oSY - 9, 120 + 2 + 4 + 6 + 8 + 10 + 12, 90 + 1 + 3 + 5 + 7 + 9 + 11); |
|
546 |
|
547 // Test simple 2D transforms. |
|
548 var stcX = scaleTransformContainer.getBoundingClientRect().left; |
|
549 var stcY = scaleTransformContainer.getBoundingClientRect().top; |
|
550 checkQuadIsRect("scaleTransform", {}, |
|
551 stcX, stcY, 140, 160); |
|
552 var ttcX = translateTransformContainer.getBoundingClientRect().left; |
|
553 var ttcY = translateTransformContainer.getBoundingClientRect().top; |
|
554 checkQuadIsRect("translateTransform", {}, |
|
555 ttcX + 30, ttcY + 40, 70, 80); |
|
556 // Test mapping into a transformed element. |
|
557 checkQuadIsRect("scaleTransform", {toStr:"translateTransform"}, |
|
558 stcX - (ttcX + 30), stcY - (ttcY + 40), 140, 160); |
|
559 // Test 90 degree rotation. |
|
560 var rotatetcX = rotateTransformContainer.getBoundingClientRect().left; |
|
561 var rotatetcY = rotateTransformContainer.getBoundingClientRect().top; |
|
562 checkQuadIsQuad("rotateTransform", {}, |
|
563 rotatetcX + 75, rotatetcY + 5, |
|
564 rotatetcX + 75, rotatetcY + 75, |
|
565 rotatetcX - 5, rotatetcY + 75, |
|
566 rotatetcX - 5, rotatetcY + 5); |
|
567 // Test vertical flip. |
|
568 var fliptcX = flipTransformContainer.getBoundingClientRect().left; |
|
569 var fliptcY = flipTransformContainer.getBoundingClientRect().top; |
|
570 checkQuadIsQuad("flipTransform", {}, |
|
571 fliptcX, fliptcY + 80, |
|
572 fliptcX + 70, fliptcY + 80, |
|
573 fliptcX + 70, fliptcY, |
|
574 fliptcX, fliptcY); |
|
575 // Test non-90deg rotation. |
|
576 var rot45tcX = rot45TransformContainer.getBoundingClientRect().left; |
|
577 var rot45tcY = rot45TransformContainer.getBoundingClientRect().top; |
|
578 var halfDiagonal = 100/Math.sqrt(2); |
|
579 checkQuadIsQuad("rot45Transform", {tolerance:0.01}, |
|
580 rot45tcX + 50, rot45tcY + 50 - halfDiagonal, |
|
581 rot45tcX + 50 + halfDiagonal, rot45tcY + 50, |
|
582 rot45tcX + 50, rot45tcY + 50 + halfDiagonal, |
|
583 rot45tcX + 50 - halfDiagonal, rot45tcY + 50); |
|
584 |
|
585 // Test singular transforms. |
|
586 var singularTransformX = singularTransform.getBoundingClientRect().left; |
|
587 var singularTransformY = singularTransform.getBoundingClientRect().top; |
|
588 // They map everything to a point. |
|
589 checkQuadIsRect("singularTransform", {}, |
|
590 singularTransformX, singularTransformY, 0, 0); |
|
591 checkQuadIsRect("singularTransformChild2", {}, |
|
592 singularTransformX, singularTransformY, 0, 0); |
|
593 // Mapping into an element with a singular transform from outside sets |
|
594 // everything to zero. |
|
595 checkQuadIsRect("d", {toStr:"singularTransform"}, |
|
596 0, 0, 0, 0); |
|
597 // But mappings within a subtree of an element with a singular transform work. |
|
598 checkQuadIsRect("singularTransformChild2", {toStr:"singularTransformChild1"}, |
|
599 0, 50, 200, 50); |
|
600 |
|
601 // Test 3D transforms. |
|
602 var t3tcX = threeDTransformContainer.getBoundingClientRect().left; |
|
603 var t3tcY = threeDTransformContainer.getBoundingClientRect().top; |
|
604 checkQuadIsQuad("threeDTransform", {tolerance:0.01}, |
|
605 t3tcX + 59.446714, t3tcY - 18.569847, |
|
606 t3tcX + 129.570778, t3tcY + 13.540874, |
|
607 t3tcX + 129.570778, t3tcY + 100, |
|
608 t3tcX + 59.446714, t3tcY + 100); |
|
609 // Test nested 3D transforms (without preserve-3d). |
|
610 checkQuadIsQuad("threeDTransformChild", {tolerance:0.01}, |
|
611 t3tcX + 89.395061, t3tcY + 2.243033, |
|
612 t3tcX + 113.041727, t3tcY - 2.758530, |
|
613 t3tcX + 113.041727, t3tcY + 52.985921, |
|
614 t3tcX + 89.395061, t3tcY + 47.571899); |
|
615 // Test preserve-3D. |
|
616 var p3dtcX = preserve3DTransformContainer.getBoundingClientRect().left; |
|
617 var p3dtcY = preserve3DTransformContainer.getBoundingClientRect().top; |
|
618 checkQuadIsRect("preserve3DTransformChild", {tolerance:0.01}, |
|
619 p3dtcX, p3dtcY, 200, 50, |
|
620 {tolerance:0.0001}); |
|
621 // Test mapping back into preserve-3D. |
|
622 checkQuadIsRect("d", {toStr:"preserve3DTransformChild",tolerance:0.01}, |
|
623 dX - p3dtcX, dY - p3dtcY, dW, dH); |
|
624 |
|
625 // Test SVG. |
|
626 var svgContainerX = svgContainer.getBoundingClientRect().left; |
|
627 var svgContainerY = svgContainer.getBoundingClientRect().top; |
|
628 checkQuadIsRect("circle", {}, |
|
629 svgContainerX + 30, svgContainerY + 30, 40, 40); |
|
630 // Box types are ignored for SVG elements. |
|
631 checkQuadIsRect("circle", {box:"content"}, |
|
632 svgContainerX + 30, svgContainerY + 30, 40, 40); |
|
633 checkQuadIsRect("circle", {box:"padding"}, |
|
634 svgContainerX + 30, svgContainerY + 30, 40, 40); |
|
635 checkQuadIsRect("circle", {box:"margin"}, |
|
636 svgContainerX + 30, svgContainerY + 30, 40, 40); |
|
637 checkQuadIsRect("d", {toStr:"circle"}, |
|
638 dX - (svgContainerX + 30), dY - (svgContainerY + 30), dW, dH); |
|
639 // Test foreignObject inside an SVG transform. |
|
640 checkQuadIsRect("foreign", {}, |
|
641 svgContainerX + 100, svgContainerY + 40, 200, 120); |
|
642 |
|
643 // XXX Test SVG text (probably broken; unclear what the best way is to handle it) |
|
644 |
|
645 // Test that converting between nodes in different toplevel browsing contexts |
|
646 // throws an exception. |
|
647 try { |
|
648 openedWindow = window.open("data:text/html,<div id='d'>",""); |
|
649 } catch (ex) { |
|
650 // in some cases we can't open the window. |
|
651 openedWindow = null; |
|
652 } |
|
653 if (openedWindow) { |
|
654 openedWindow.addEventListener("load", function() { |
|
655 checkException("openedWindow.d.getBoxQuads({relativeTo:document})", "NotFoundError"); |
|
656 checkException("document.getBoxQuads({relativeTo:openedWindow.d})", "NotFoundError"); |
|
657 checkException("openedWindow.d.convertPointFromNode(zeroPoint,document)", "NotFoundError"); |
|
658 checkException("document.convertPointFromNode(zeroPoint,openedWindow.d)", "NotFoundError"); |
|
659 checkException("openedWindow.d.convertRectFromNode(zeroRect,document)", "NotFoundError"); |
|
660 checkException("document.convertRectFromNode(zeroRect,openedWindow.d)", "NotFoundError"); |
|
661 checkException("openedWindow.d.convertQuadFromNode(zeroQuad,document)", "NotFoundError"); |
|
662 checkException("document.convertQuadFromNode(zeroQuad,openedWindow.d)", "NotFoundError"); |
|
663 openedWindow.close(); |
|
664 SimpleTest.finish(); |
|
665 }); |
|
666 } else { |
|
667 SimpleTest.finish(); |
|
668 } |
|
669 } |
|
670 </script> |
|
671 </body> |
|
672 </html> |