OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE html> |
| 2 <html> |
| 3 <head> |
| 4 <title>InputEvent: beforeinput for Drag and Drop</title> |
| 5 <script src="../../../resources/testharness.js"></script> |
| 6 <script src="../../../resources/testharnessreport.js"></script> |
| 7 <style> |
| 8 div, img { |
| 9 width: 100px; |
| 10 height: 100px; |
| 11 } |
| 12 </style> |
| 13 </head> |
| 14 <body> |
| 15 <div id="editable1" contenteditable><img id="img" src="../resources/greenbox.png
"></div> |
| 16 <div id="editable2" contenteditable></div> |
| 17 <script> |
| 18 function simulateDragDrop(dragElement, dropElement) { |
| 19 eventSender.mouseMoveTo(dragElement.offsetLeft + dragElement.offsetWidth / 2
, |
| 20 dragElement.offsetTop + dragElement.offsetHeight / 2
); |
| 21 eventSender.mouseDown(); |
| 22 eventSender.leapForward(100); |
| 23 eventSender.mouseMoveTo(dropElement.offsetLeft + dropElement.offsetWidth / 2
, |
| 24 dropElement.offsetTop + dropElement.offsetHeight / 2
); |
| 25 eventSender.mouseUp(); |
| 26 } |
| 27 |
| 28 test(function() { |
| 29 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe
nder.'); |
| 30 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn
er.'); |
| 31 |
| 32 const editable1 = document.getElementById('editable1'); |
| 33 const editable2 = document.getElementById('editable2'); |
| 34 var eventOrderRecorder = []; |
| 35 document.addEventListener('beforeinput', event => |
| 36 eventOrderRecorder.push(`beforeinput:${event.target.id}:${event.inputTyp
e}`)); |
| 37 document.addEventListener('input', event => |
| 38 eventOrderRecorder.push(`input:${event.target.id}:${event.inputType}`)); |
| 39 ['drop', 'dragend'].forEach(eventType => document.addEventListener( |
| 40 eventType, () => eventOrderRecorder.push(`${event.target.id}:${event
Type}`))); |
| 41 |
| 42 function testDragDropEventOrder(dragElement, dropElement, expectedOrder) { |
| 43 assert_equals(dragElement.children.length, 1); |
| 44 eventOrderRecorder = []; |
| 45 simulateDragDrop(dragElement, dropElement); |
| 46 assert_array_equals(eventOrderRecorder, expectedOrder, |
| 47 `Testing drag ${dragElement.id} onto ${dropElement.id} actual order:
${eventOrderRecorder}`); |
| 48 } |
| 49 |
| 50 // Test Drag and Drop. |
| 51 testDragDropEventOrder(editable1, editable2, |
| 52 ['editable2:drop', 'beforeinput:img:deleteByDrag', 'input:editable1:dele
teByDrag', |
| 53 'beforeinput:editable2:insertFromDrop', 'input:editable2:insertFromDrop'
, 'editable1:dragend']); |
| 54 testRunner.execCommand('undo'); |
| 55 }, 'Testing Drag and Drop event order'); |
| 56 |
| 57 test(function() { |
| 58 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe
nder.'); |
| 59 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn
er.'); |
| 60 |
| 61 const editable1 = document.getElementById('editable1'); |
| 62 const editable2 = document.getElementById('editable2'); |
| 63 var lastPlainTextData = {}; |
| 64 var lastHTMLData = {}; |
| 65 document.addEventListener('beforeinput', event => { |
| 66 lastPlainTextData[event.inputType] = event.dataTransfer ? event.dataTran
sfer.getData('text/plain') : null; |
| 67 lastHTMLData[event.inputType] = event.dataTransfer ? event.dataTransfer.
getData('text/html') : null; |
| 68 }); |
| 69 |
| 70 function testDragDropDataTransfer(inputType, dragElement, dropElement, expec
tedPlainText, expectedHTML) { |
| 71 assert_equals(dragElement.children.length, 1); |
| 72 lastPlainTextData = {}; |
| 73 lastHTMLData = {}; |
| 74 simulateDragDrop(dragElement, dropElement); |
| 75 assert_equals(lastPlainTextData[inputType], expectedPlainText, |
| 76 `Testing '${inputType}' getData('text/plain')`); |
| 77 if (expectedHTML && expectedHTML.test) { |
| 78 assert_regexp_match(lastHTMLData[inputType], expectedHTML, |
| 79 `Testing '${inputType}' getData('text/html')`); |
| 80 } else { |
| 81 assert_equals(lastHTMLData[inputType], expectedHTML, |
| 82 `Testing '${inputType}' getData('text/html')`); |
| 83 } |
| 84 } |
| 85 |
| 86 // Test Drag and Drop. |
| 87 testDragDropDataTransfer('deleteByDrag', editable1, editable2, null, null); |
| 88 testRunner.execCommand('undo'); |
| 89 testDragDropDataTransfer('insertFromDrop', editable1, editable2, '', /^<img.
*greenbox\.png".*>$/); |
| 90 testRunner.execCommand('undo'); |
| 91 }, 'Testing Drag and Drop dataTransfer'); |
| 92 |
| 93 test(function() { |
| 94 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe
nder.'); |
| 95 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn
er.'); |
| 96 |
| 97 const editable1 = document.getElementById('editable1'); |
| 98 const editable2 = document.getElementById('editable2'); |
| 99 var inputTypesToPrevent = []; |
| 100 document.addEventListener('beforeinput', event => { |
| 101 if (inputTypesToPrevent.indexOf(event.inputType) != -1) |
| 102 event.preventDefault(); |
| 103 }); |
| 104 |
| 105 function testDragDropPreventDefault(preventDefaultTypes, dragElement, dropEl
ement, expectedDragElementChildren, expectedDropElementChildren) { |
| 106 assert_equals(dragElement.children.length, 1); |
| 107 inputTypesToPrevent = preventDefaultTypes; |
| 108 simulateDragDrop(dragElement, dropElement); |
| 109 assert_equals(dragElement.children.length, expectedDragElementChildren, |
| 110 'Testing preventDefault() on ${preventDefaultTypes} ${dragElement.id
} children count'); |
| 111 assert_equals(dropElement.children.length, expectedDropElementChildren, |
| 112 'Testing preventDefault() on ${preventDefaultTypes} ${dropElement.id
} children count'); |
| 113 inputTypesToPrevent = []; |
| 114 } |
| 115 |
| 116 // Preventing single 'beforeinput' will only cancel DOM update for one event
, |
| 117 // the remaining DOM update will still update undo stack. |
| 118 testDragDropPreventDefault(['deleteByDrag'], editable1, editable2, 1, 1); |
| 119 testRunner.execCommand('undo'); |
| 120 testDragDropPreventDefault(['insertFromDrop'], editable1, editable2, 0, 0); |
| 121 testRunner.execCommand('undo'); |
| 122 |
| 123 // Adding 'insertHTML' command to undo stack. |
| 124 editable2.focus(); |
| 125 document.execCommand('insertHTML', false, '<b>B</b><i>i</i>'); |
| 126 assert_equals(editable2.children.length, 2, |
| 127 '"editable2" should have 2 children after "insertHTML" command'); |
| 128 // Canceling both |deleteByDrag| and |insertFromDrop| won't modify undo stac
k. |
| 129 testDragDropPreventDefault(['deleteByDrag', 'insertFromDrop'], editable1, ed
itable2, 1, 2); |
| 130 // |undo| will undo last 'insertHTML' command. |
| 131 testRunner.execCommand('undo'); |
| 132 assert_equals(editable2.children.length, 0, |
| 133 '"editable2" should have 0 children after undo "insertHTML"'); |
| 134 }, 'Testing Drag and Drop preventDefault()'); |
| 135 |
| 136 test(function() { |
| 137 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe
nder.'); |
| 138 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn
er.'); |
| 139 |
| 140 const editable1 = document.getElementById('editable1'); |
| 141 const editable2 = document.getElementById('editable2'); |
| 142 var eventOrderRecorder = []; |
| 143 [editable1, editable2].forEach(editable => { |
| 144 editable.addEventListener('beforeinput', event => |
| 145 eventOrderRecorder.push(`beforeinput:${editable.id}:${event.inputTyp
e}`)); |
| 146 editable.addEventListener('input', event => |
| 147 eventOrderRecorder.push(`input:${editable.id}:${event.inputType}`)); |
| 148 editable.addEventListener('drop', event => |
| 149 eventOrderRecorder.push(`${editable.id}:drop`)); |
| 150 editable.addEventListener('dragend', event => |
| 151 eventOrderRecorder.push(`${editable.id}:dragend`)); |
| 152 }); |
| 153 |
| 154 function testDragDropEventOrder(dragElement, dropElement, expectedOrder) { |
| 155 assert_equals(dragElement.children.length, 1); |
| 156 eventOrderRecorder = []; |
| 157 simulateDragDrop(dragElement, dropElement); |
| 158 assert_array_equals(eventOrderRecorder, expectedOrder, |
| 159 `Testing drag ${dragElement.id} onto ${dropElement.id} actual order:
${eventOrderRecorder}`); |
| 160 } |
| 161 |
| 162 function removeEditable1Listener() { |
| 163 editable1.remove(); |
| 164 } |
| 165 |
| 166 function removeEditable2Listener() { |
| 167 editable2.remove(); |
| 168 } |
| 169 |
| 170 // Testing remove drop target, |editable2| won't get 'beforeinput' as it's d
isconnected. |
| 171 editable1.addEventListener('beforeinput', removeEditable2Listener); |
| 172 testDragDropEventOrder(editable1, editable2, |
| 173 ['editable2:drop', 'beforeinput:editable1:deleteByDrag', 'input:editable
1:deleteByDrag', 'editable1:dragend']); |
| 174 editable1.removeEventListener('beforeinput', removeEditable2Listener); |
| 175 testRunner.execCommand('undo'); |
| 176 document.body.appendChild(editable2); |
| 177 |
| 178 // Testing remove drag target, |editable1| won't receive DOM updates after d
isconnected. |
| 179 editable1.addEventListener('beforeinput', removeEditable1Listener); |
| 180 testDragDropEventOrder(editable1, editable2, |
| 181 ['editable2:drop', 'beforeinput:editable1:deleteByDrag', 'beforeinput:ed
itable2:insertFromDrop', |
| 182 'input:editable2:insertFromDrop', 'editable1:dragend']); |
| 183 editable1.removeEventListener('beforeinput', removeEditable1Listener); |
| 184 testRunner.execCommand('undo'); |
| 185 document.body.appendChild(editable1); |
| 186 }, 'Testing element removed by event handler'); |
| 187 </script> |
| 188 </body> |
| 189 </html> |
OLD | NEW |