test_text.html (10125B)
1 <html> 2 3 <head> 4 <title>Accessible mutation events testing</title> 5 6 <link rel="stylesheet" type="text/css" 7 href="chrome://mochikit/content/tests/SimpleTest/test.css" /> 8 9 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 10 <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> 11 12 <script type="application/javascript" 13 src="../common.js"></script> 14 <script type="application/javascript" 15 src="../events.js"></script> 16 17 <script type="application/javascript"> 18 // ////////////////////////////////////////////////////////////////////////// 19 // Invokers 20 21 /** 22 * Base text remove invoker and checker. 23 */ 24 function textRemoveInvoker(aID, aStart, aEnd, aText) { 25 this.DOMNode = getNode(aID); 26 27 this.eventSeq = [ 28 new textChangeChecker(aID, aStart, aEnd, aText, false), 29 ]; 30 } 31 32 function textInsertInvoker(aID, aStart, aEnd, aText) { 33 this.DOMNode = getNode(aID); 34 35 this.eventSeq = [ 36 new textChangeChecker(aID, aStart, aEnd, aText, true), 37 ]; 38 } 39 40 /** 41 * Remove inaccessible child node containing accessibles. 42 */ 43 function removeChildSpan(aID) { 44 this.__proto__ = new textRemoveInvoker(aID, 0, 5, "33322"); 45 46 this.invoke = function removeChildSpan_invoke() { 47 // remove HTML span, a first child of the node 48 this.DOMNode.firstChild.remove(); 49 }; 50 51 this.getID = function removeChildSpan_getID() { 52 return "Remove inaccessible span containing accessible nodes" + prettyName(aID); 53 }; 54 } 55 56 /** 57 * Insert inaccessible child node containing accessibles. 58 */ 59 function insertChildSpan(aID, aInsertAllTogether) { 60 this.__proto__ = new textInsertInvoker(aID, 0, 5, "33322"); 61 62 this.invoke = function insertChildSpan_invoke() { 63 // <span><span>333</span><span>22</span></span> 64 if (aInsertAllTogether) { 65 let topSpan = document.createElement("span"); 66 let fSpan = document.createElement("span"); 67 fSpan.textContent = "333"; 68 topSpan.appendChild(fSpan); 69 let sSpan = document.createElement("span"); 70 sSpan.textContent = "22"; 71 topSpan.appendChild(sSpan); 72 73 this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]); 74 } else { 75 let topSpan = document.createElement("span"); 76 this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]); 77 78 let fSpan = document.createElement("span"); 79 fSpan.textContent = "333"; 80 topSpan.appendChild(fSpan); 81 82 let sSpan = document.createElement("span"); 83 sSpan.textContent = "22"; 84 topSpan.appendChild(sSpan); 85 } 86 }; 87 88 this.getID = function insertChildSpan_getID() { 89 return "Insert inaccessible span containing accessibles" + 90 prettyName(aID); 91 }; 92 } 93 94 /** 95 * Remove child embedded accessible. 96 */ 97 function removeChildDiv(aID) { 98 this.__proto__ = new textRemoveInvoker(aID, 5, 6, kEmbedChar); 99 100 this.invoke = function removeChildDiv_invoke() { 101 var childDiv = this.DOMNode.childNodes[1]; 102 103 // Ensure accessible is created to get text remove event when it's 104 // removed. 105 getAccessible(childDiv); 106 107 this.DOMNode.removeChild(childDiv); 108 }; 109 110 this.getID = function removeChildDiv_getID() { 111 return "Remove accessible div from the middle of text accessible " + 112 prettyName(aID); 113 }; 114 } 115 116 /** 117 * Insert child embedded accessible. 118 */ 119 function insertChildDiv(aID) { 120 this.__proto__ = new textInsertInvoker(aID, 5, 6, kEmbedChar); 121 122 this.invoke = function insertChildDiv_invoke() { 123 var childDiv = document.createElement("div"); 124 // Note after bug 646216, a sole div without text won't be accessible 125 // and would not result in an embedded character. 126 // Therefore, add some text. 127 childDiv.textContent = "hello"; 128 this.DOMNode.insertBefore(childDiv, this.DOMNode.childNodes[1]); 129 }; 130 131 this.getID = function insertChildDiv_getID() { 132 return "Insert accessible div into the middle of text accessible " + 133 prettyName(aID); 134 }; 135 } 136 137 /** 138 * Remove children from text container from first to last child or vice 139 * versa. 140 */ 141 function removeChildren(aID, aLastToFirst, aStart, aEnd, aText) { 142 this.__proto__ = new textRemoveInvoker(aID, aStart, aEnd, aText); 143 144 this.invoke = function removeChildren_invoke() { 145 if (aLastToFirst) { 146 while (this.DOMNode.firstChild) 147 this.DOMNode.removeChild(this.DOMNode.lastChild); 148 } else { 149 while (this.DOMNode.firstChild) 150 this.DOMNode.firstChild.remove(); 151 } 152 }; 153 154 this.getID = function removeChildren_getID() { 155 return "remove children of " + prettyName(aID) + 156 (aLastToFirst ? " from last to first" : " from first to last"); 157 }; 158 } 159 160 /** 161 * Remove text from HTML input. 162 */ 163 function removeTextFromInput(aID, aStart, aEnd, aText) { 164 this.__proto__ = new textRemoveInvoker(aID, aStart, aEnd, aText); 165 166 this.eventSeq.push(new invokerChecker(EVENT_TEXT_VALUE_CHANGE, 167 this.DOMNode)); 168 169 this.invoke = function removeTextFromInput_invoke() { 170 this.DOMNode.focus(); 171 this.DOMNode.setSelectionRange(aStart, aEnd); 172 173 synthesizeKey("KEY_Delete"); 174 }; 175 176 this.getID = function removeTextFromInput_getID() { 177 return "Remove text from " + aStart + " to " + aEnd + " for " + 178 prettyName(aID); 179 }; 180 } 181 182 /** 183 * Add text into HTML input. 184 */ 185 function insertTextIntoInput(aID, aStart, aEnd, aText) { 186 this.__proto__ = new textInsertInvoker(aID, aStart, aEnd, aText); 187 188 this.eventSeq.push(new invokerChecker(EVENT_TEXT_VALUE_CHANGE, 189 this.DOMNode)); 190 191 this.invoke = function insertTextIntoInput_invoke() { 192 this.DOMNode.focus(); 193 sendString("a"); 194 }; 195 196 this.getID = function insertTextIntoInput_getID() { 197 return "Insert text to " + aStart + " for " + prettyName(aID); 198 }; 199 } 200 201 /** 202 * Remove text data from text node of editable area. 203 */ 204 function removeTextFromEditable(aID, aStart, aEnd, aText, aTextNode) { 205 this.__proto__ = new textRemoveInvoker(aID, aStart, aEnd, aText); 206 207 this.invoke = function removeTextFromEditable_invoke() { 208 this.DOMNode.focus(); 209 210 var selection = window.getSelection(); 211 var range = document.createRange(); 212 range.setStart(this.textNode, aStart); 213 range.setEnd(this.textNode, aEnd); 214 selection.addRange(range); 215 216 synthesizeKey("KEY_Delete"); 217 }; 218 219 this.getID = function removeTextFromEditable_getID() { 220 return "Remove text from " + aStart + " to " + aEnd + " for " + 221 prettyName(aID); 222 }; 223 224 this.textNode = getNode(aTextNode); 225 } 226 227 // ////////////////////////////////////////////////////////////////////////// 228 // Do tests 229 gA11yEventDumpToConsole = true; // debugging 230 231 var gQueue = null; 232 function doTests() { 233 gQueue = new eventQueue(); 234 235 // Text remove event on inaccessible child HTML span removal containing 236 // accessible text nodes. 237 gQueue.push(new removeChildSpan("p")); 238 gQueue.push(new insertChildSpan("p"), true); 239 gQueue.push(new insertChildSpan("p"), false); 240 241 // Remove embedded character. 242 gQueue.push(new removeChildDiv("div")); 243 gQueue.push(new insertChildDiv("div")); 244 245 // Remove all children. 246 var text = kEmbedChar + "txt" + kEmbedChar; 247 gQueue.push(new removeChildren("div2", true, 0, 5, text)); 248 gQueue.push(new removeChildren("div3", false, 0, 5, text)); 249 250 // Text remove from text node within hypertext accessible. 251 gQueue.push(new removeTextFromInput("input", 1, 3, "al")); 252 gQueue.push(new insertTextIntoInput("input", 1, 2, "a")); 253 254 // bug 570691 255 todo(false, "Fix text change events from editable area, see bug 570691"); 256 // var textNode = getNode("editable").firstChild; 257 // gQueue.push(new removeTextFromEditable("editable", 1, 3, "al", textNode)); 258 // textNode = getNode("editable2").firstChild.firstChild; 259 // gQueue.push(new removeTextFromEditable("editable2", 1, 3, "al", textNode)); 260 261 gQueue.invoke(); // Will call SimpleTest.finish(); 262 } 263 264 SimpleTest.waitForExplicitFinish(); 265 addA11yLoadEvent(doTests); 266 </script> 267 </head> 268 269 <body> 270 271 <a target="_blank" 272 href="https://bugzilla.mozilla.org/show_bug.cgi?id=566293" 273 title=" wrong length of text remove event when inaccessible node containing accessible nodes is removed"> 274 Mozilla Bug 566293 275 </a><br> 276 <a target="_blank" 277 href="https://bugzilla.mozilla.org/show_bug.cgi?id=570710" 278 title="Avoid extra array traversal during text event creation"> 279 Mozilla Bug 570710 280 </a><br> 281 <a target="_blank" 282 href="https://bugzilla.mozilla.org/show_bug.cgi?id=574003" 283 title="Coalesce text events on nodes removal"> 284 Mozilla Bug 574003 285 </a> 286 <a target="_blank" 287 href="https://bugzilla.mozilla.org/show_bug.cgi?id=575052" 288 title="Cache text offsets within hypertext accessible"> 289 Mozilla Bug 575052 290 </a> 291 <a target="_blank" 292 href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275" 293 title="Rework accessible tree update code"> 294 Mozilla Bug 570275 295 </a> 296 297 <p id="display"></p> 298 <div id="content" style="display: none"></div> 299 <pre id="test"> 300 </pre> 301 302 <p id="p"><span><span>333</span><span>22</span></span>1111</p> 303 <div id="div">hello<div>hello</div>hello</div> 304 <div id="div2"><div>txt</div>txt<div>txt</div></div> 305 <div id="div3"><div>txt</div>txt<div>txt</div></div> 306 <input id="input" value="value"> 307 <div contentEditable="true" id="editable">value</div> 308 <div contentEditable="true" id="editable2"><span>value</span></div> 309 </body> 310 </html>