| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>InputEvent: cancelable</title> |
| <script src="../../../resources/testharness.js"></script> |
| <script src="../../../resources/testharnessreport.js"></script> |
| <style> |
| div { |
| width: 100px; |
| height: 100px; |
| } |
| </style> |
| </head> |
| <body> |
| <div id="editable" contenteditable></div> |
| <div id="editable1" contenteditable>EditableText</div> |
| <div id="editable2" contenteditable></div> |
| <script> |
| function simulateDragDrop(dragElement, dropElement) { |
| if (dragElement.select) { |
| dragElement.select(); |
| } else { |
| var selection = window.getSelection(); |
| selection.collapse(dragElement, 0); |
| selection.extend(dragElement, 1); |
| } |
| |
| eventSender.mouseMoveTo(dragElement.offsetLeft + dragElement.offsetWidth / 2, |
| dragElement.offsetTop + dragElement.offsetHeight / 2); |
| eventSender.mouseDown(); |
| eventSender.leapForward(600); |
| eventSender.mouseMoveTo(dropElement.offsetLeft + dropElement.offsetWidth / 2, |
| dropElement.offsetTop + dropElement.offsetHeight / 2); |
| eventSender.mouseUp(); |
| } |
| |
| async_test(t => { |
| assert_not_equals(window.eventSender, undefined, 'This test requires eventSender.'); |
| assert_not_equals(window.testRunner, undefined, 'This test requires testRunner.'); |
| assert_not_equals(internals, undefined, 'This test requires internals.'); |
| assert_not_equals(textInputController, undefined, 'This test requires textInputController.'); |
| |
| const editable = document.getElementById('editable'); |
| const editable1 = document.getElementById('editable1'); |
| const editable2 = document.getElementById('editable2'); |
| const kNoncancelableInputTypes = [ |
| 'insertCompositionText', |
| ]; |
| |
| let lastBeforeInputType = ''; |
| let doCancel = false; |
| document.addEventListener('beforeinput', t.step_func(event => { |
| lastBeforeInputType = event.inputType; |
| assert_equals(kNoncancelableInputTypes.indexOf(event.inputType) === -1, event.cancelable); |
| if (doCancel) event.preventDefault(); |
| })); |
| |
| function testKeyDown(key, modifiers, inputType) { |
| lastBeforeInputType = ''; |
| doCancel = false; |
| eventSender.keyDown(key, modifiers); |
| assert_equals(inputType, lastBeforeInputType, `${modifiers.toString()}+${key} should produce input type: ${inputType}`); |
| } |
| |
| function testCommand(command, inputType) { |
| lastBeforeInputType = ''; |
| doCancel = false; |
| testRunner.execCommand(command); |
| assert_equals(inputType, lastBeforeInputType, `${command} should produce input type: ${inputType}`); |
| } |
| |
| function sendCancel(key, inputType) { |
| lastBeforeInputType = ''; |
| doCancel = true; |
| eventSender.keyDown(key, []); |
| } |
| |
| // Typing |
| editable.focus(); |
| testKeyDown('a', [], 'insertText'); |
| testKeyDown('6', [], 'insertText'); |
| testKeyDown('l', ['shiftKey'], 'insertText'); |
| testKeyDown('w', ['shiftKey'], 'insertText'); |
| testKeyDown('Enter', [], 'insertParagraph'); |
| testKeyDown('Enter', ['shiftKey'], 'insertLineBreak'); |
| editable.innerText = ''; |
| testKeyDown('a', [], 'insertText'); |
| assert_equals(editable.innerText, 'a'); |
| sendCancel('b', 'insertText'); |
| assert_equals(editable.innerText, 'a'); |
| |
| // Deletion |
| const isMacOS = navigator.platform.indexOf('Mac') === 0; |
| const deleteWordModifier = isMacOS ? 'altKey' : 'ctrlKey'; |
| editable.innerHTML = 'abc def</br>123 456'; |
| const selection = window.getSelection(); |
| selection.collapse(editable, 1); // End of first line. |
| testKeyDown('Backspace', [], 'deleteContentBackward'); |
| testKeyDown('Delete', [], 'deleteContentForward'); |
| testKeyDown('Backspace', [deleteWordModifier], 'deleteWordBackward'); |
| testKeyDown('Delete', [deleteWordModifier], 'deleteWordForward'); |
| testCommand('deleteToBeginningOfLine', 'deleteSoftLineBackward'); |
| testCommand('deleteToEndOfLine', 'deleteSoftLineForward'); |
| testCommand('deleteToBeginningOfParagraph', 'deleteHardLineBackward'); |
| testCommand('deleteToEndOfParagraph', 'deleteHardLineForward'); |
| editable.innerText = ''; |
| testKeyDown('a', [], 'insertText'); |
| assert_equals(editable.innerText, 'a'); |
| sendCancel('Backspace', 'deleteContentBackward'); |
| assert_equals(editable.innerText, 'a'); |
| |
| // Format |
| editable.innerHTML = 'abc'; |
| selection.collapse(editable, 0); |
| selection.extend(editable, 1); |
| testCommand('bold', 'formatBold'); |
| testCommand('italic', 'formatItalic'); |
| testCommand('underline', 'formatUnderline'); |
| testCommand('strikeThrough', 'formatStrikeThrough'); |
| testCommand('superscript', 'formatSuperscript'); |
| testCommand('subscript', 'formatSubscript'); |
| |
| // Cut and paste |
| editable.innerHTML = 'abc'; |
| selection.collapse(editable, 0); |
| selection.extend(editable, 1); |
| testKeyDown('Cut', [], 'deleteByCut'); |
| testKeyDown('Paste', [], 'insertFromPaste'); |
| |
| // Drag and drop |
| simulateDragDrop(editable1, editable2); |
| assert_equals('insertFromDrop', lastBeforeInputType); |
| |
| // Undo and redo |
| testCommand('undo', 'historyUndo'); |
| testCommand('redo', 'historyRedo'); |
| |
| // Spell-checker |
| editable.innerHTML = 'appla'; |
| selection.collapse(editable, 0); |
| selection.extend(editable, 1); |
| internals.setMarker(document, selection.getRangeAt(0), 'Spelling'); |
| internals.replaceMisspelled(document, 'apple'); |
| assert_equals('insertReplacementText', lastBeforeInputType); |
| |
| // IME |
| editable.innerHTML = 'wo'; |
| selection.collapse(editable, 0); |
| selection.extend(editable, 1); |
| textInputController.setComposition('word'); |
| assert_equals('insertCompositionText', lastBeforeInputType); |
| |
| t.done(); |
| }, 'Text input and IME related input types are non-cancelable.'); |
| |
| </script> |
| </body> |
| </html> |