import { Pipeline } from '@ephox/agar'; import { LegacyUnit, TinyLoader } from '@ephox/mcagar'; import * as CaretContainer from 'tinymce/core/caret/CaretContainer'; import Env from 'tinymce/core/api/Env'; import Zwsp from 'tinymce/core/text/Zwsp'; import Theme from 'tinymce/themes/modern/Theme'; import { UnitTest } from '@ephox/bedrock'; UnitTest.asynctest('browser.tinymce.core.dom.SelectionTest', function () { const success = arguments[arguments.length - 2]; const failure = arguments[arguments.length - 1]; const suite = LegacyUnit.createSuite(); Theme(); suite.test('getContent', function (editor) { let rng, eventObj; editor.focus(); // Get selected contents editor.setContent('
text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 1); editor.selection.setRng(rng); LegacyUnit.equal(editor.selection.getContent(), 'text
', 'Get selected contents'); // Get selected contents (collapsed) editor.setContent('text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 0); editor.selection.setRng(rng); LegacyUnit.equal(editor.selection.getContent(), '', 'Get selected contents (collapsed)'); // Get selected contents, onGetContent event eventObj = {}; const handler = function (event) { eventObj = event; }; editor.on('GetContent', handler); editor.setContent('text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 1); editor.selection.setRng(rng); editor.selection.getContent(); LegacyUnit.equal(eventObj.content, 'text
', 'Get selected contents, onGetContent event'); editor.off('GetContent', handler); }); suite.test('getContent contextual', function (editor) { editor.setContent('text
'); const rng = editor.dom.createRng(); rng.setStart(editor.dom.select('em')[0].firstChild, 1); rng.setEnd(editor.dom.select('em')[0].firstChild, 3); editor.selection.setRng(rng); LegacyUnit.equal(editor.selection.getContent({ contextual: true }), 'ex', 'Get selected contents'); }); suite.test('getContent of zwsp', function (editor) { editor.setContent('a' + Zwsp.ZWSP + 'b
'); const rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 1); editor.selection.setRng(rng); LegacyUnit.equal(editor.selection.getContent(), 'ab
', 'Get selected contents'); LegacyUnit.equal(editor.selection.getContent({ format: 'text' }), 'ab', 'Get selected contents'); }); suite.test('setContent', function (editor) { let rng, eventObj; // Set contents at selection editor.setContent('text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 1); editor.selection.setRng(rng); editor.selection.setContent('text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 0); editor.selection.setRng(rng); editor.selection.setContent('text
', 'Set contents at selection (collapsed)'); // Insert in middle of paragraph editor.setContent('beforeafter
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.firstChild, 'before'.length); rng.setEnd(editor.getBody().firstChild.firstChild, 'before'.length); editor.selection.setRng(rng); editor.selection.setContent('before
after
text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 0); editor.selection.setRng(rng); editor.selection.setContent(''); LegacyUnit.equal(editor.getContent(), 'text
', 'Set contents to empty at selection (collapsed)'); rng = editor.selection.getRng(true); if (!document.createRange) { // The old IE selection can only be positioned in text nodes LegacyUnit.equalDom(rng.startContainer, editor.getBody().firstChild.firstChild, 'Selection start container'); LegacyUnit.equal(rng.startOffset, 0, 'Selection start offset'); LegacyUnit.equalDom(rng.endContainer, editor.getBody().firstChild.firstChild, 'Selection end container'); LegacyUnit.equal(rng.endOffset, 0, 'Selection end offset'); } else { LegacyUnit.equalDom(rng.startContainer, editor.getBody(), 'Selection start container'); LegacyUnit.equal(rng.startOffset, 0, 'Selection start offset'); LegacyUnit.equalDom(rng.endContainer, editor.getBody(), 'Selection end container'); LegacyUnit.equal(rng.endOffset, 0, 'Selection end offset'); } // Set selected contents, onSetContent event eventObj = {}; const handler = function (event) { eventObj = event; }; editor.on('SetContent', handler); editor.setContent('text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 1); editor.selection.setRng(rng); editor.selection.setContent('text
text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.firstChild, 0); rng.setEnd(editor.getBody().lastChild.firstChild, 0); editor.selection.setRng(rng); LegacyUnit.equal(editor.selection.getStart().id, 'a', 'Selected contents (getStart)'); LegacyUnit.equal(editor.selection.getEnd().id, 'b', 'Selected contents (getEnd)'); // Selected contents (collapsed) editor.setContent('text
\ntext
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.firstChild, 0); rng.setEnd(editor.getBody().firstChild.firstChild, 0); editor.selection.setRng(rng); LegacyUnit.equal(editor.selection.getStart().id, 'a', 'Selected contents (getStart, collapsed)'); LegacyUnit.equal(editor.selection.getEnd().id, 'a', 'Selected contents (getEnd, collapsed)'); }); suite.test('getStart/getEnd on comment should return parent element', function (editor) { editor.setContent(''); const rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 0); rng.setEnd(editor.getBody().firstChild, 0); editor.selection.setRng(rng); LegacyUnit.equal(editor.selection.getStart().nodeName, 'P', 'Node name should be paragraph'); LegacyUnit.equal(editor.selection.getStart(true).nodeName, 'P', 'Node name should be paragraph'); LegacyUnit.equal(editor.selection.getEnd().nodeName, 'P', 'Node name should be paragraph'); LegacyUnit.equal(editor.selection.getEnd(true).nodeName, 'P', 'Node name should be paragraph'); }); suite.test('getBookmark/setBookmark (persistent)', function (editor) { let rng, bookmark; // Get persistent bookmark simple text selection editor.setContent('text'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 1); rng.setEnd(editor.getBody().firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(); LegacyUnit.equal(editor.getContent(), 'text', 'Editor contents (text)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ex', 'Selected contents (text)'); // Get persistent bookmark multiple elements text selection editor.setContent('text
\ntext
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.firstChild, 1); rng.setEnd(editor.getBody().lastChild.firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(); LegacyUnit.equal(editor.getContent(), 'text
\ntext
', 'Editor contents (elements)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ext
\ntex
', 'Selected contents (elements)'); }); suite.test('getBookmark/setBookmark (simple)', function (editor) { let rng, bookmark; // Get persistent bookmark simple text selection editor.setContent('text'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 1); rng.setEnd(editor.getBody().firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(1); LegacyUnit.equal(editor.getContent(), 'text', 'Editor contents (text)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ex', 'Selected contents (text)'); // Get persistent bookmark multiple elements text selection editor.setContent('text
\ntext
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.firstChild, 1); rng.setEnd(editor.getBody().lastChild.firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(1); LegacyUnit.equal(editor.getContent(), 'text
\ntext
', 'Editor contents (elements)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ext
\ntex
', 'Selected contents (elements)'); }); suite.test('getBookmark/setBookmark (nonintrusive) - simple text selection', function (editor) { let rng, bookmark; editor.setContent('text'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 1); rng.setEnd(editor.getBody().firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2); LegacyUnit.equal(editor.getContent(), 'text', 'Editor contents (text)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ex', 'Selected contents (text)'); }); suite.test('getBookmark/setBookmark (nonintrusive) - Get non intrusive bookmark simple element selection', function (editor) { let rng, bookmark; // Get non intrusive bookmark simple element selection editor.setContent('textabc
'); rng = editor.dom.createRng(); rng.setStart(editor.dom.select('em')[0], 1); rng.setEnd(editor.dom.select('em')[0], 2); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'b', 'Selected contents (element)'); }); suite.test('getBookmark/setBookmark (nonintrusive) - Get non intrusive bookmark multiple elements text selection', function (editor) { let rng, bookmark; // Get non intrusive bookmark multiple elements text selection editor.setContent('text
\ntext
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.firstChild, 1); rng.setEnd(editor.getBody().lastChild.firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2); LegacyUnit.equal(editor.getContent(), 'text
\ntext
', 'Editor contents (elements)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ext
\ntex
', 'Selected contents (elements)'); }); suite.test('getBookmark/setBookmark (nonintrusive)', function (editor) { let rng, bookmark; // Get non intrusive bookmark multiple elements text selection fragmented editor.setContent('text
text
'); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a')); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a')); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a')); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('text')); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.lastChild, 1); rng.setEnd(editor.getBody().lastChild.firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2); LegacyUnit.equal(editor.getContent(), 'textaaatext
\ntext
', 'Editor contents (fragmented, elements)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ext
\ntex
', 'Selected contents (fragmented, elements)'); }); suite.test('getBookmark/setBookmark (nonintrusive) - fragmentext text (normalized)', function (editor) { let rng, bookmark; // Get non intrusive bookmark multiple elements text selection fragmented editor.setContent('text
text
'); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a')); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a')); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a')); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('text')); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.lastChild, 1); rng.setEnd(editor.getBody().lastChild.firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.setContent(editor.getContent()); LegacyUnit.equal(editor.getContent(), 'textaaatext
\ntext
', 'Editor contents (fragmented, elements)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ext
\ntex
', 'Selected contents (fragmented, elements)'); }); suite.test('getBookmark/setBookmark (nonintrusive) - fragmentext text with zwsp (normalized)', function (editor) { let rng, bookmark; // Get non intrusive bookmark multiple elements text selection fragmented editor.setContent('text
text
'); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a')); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode(Zwsp.ZWSP)); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode(Zwsp.ZWSP)); editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('text')); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.lastChild, 1); rng.setEnd(editor.getBody().lastChild.firstChild, 3); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.setContent(editor.getContent()); LegacyUnit.equal(editor.getContent(), 'textatext
\ntext
', 'Editor contents (fragmented, elements)'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equal(editor.selection.getContent(), 'ext
\ntex
', 'Selected contents (fragmented, elements)'); }); suite.test('getBookmark/setBookmark (nonintrusive) - Get bookmark before image', function (editor) { let rng, bookmark; editor.setContent('abc
123123
123123
| abc |
1
'); CaretContainer.insertInline(editor.$('span')[0], true); rng = editor.dom.createRng(); rng.setStart(editor.$('span')[0].previousSibling, 0); rng.setEnd(editor.$('span')[0].previousSibling, 0); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2); editor.setContent('1
'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equalDom(editor.selection.getNode(), editor.$('span')[0]); }); suite.test('getBookmark/setBookmark before cE=false block', function (editor) { let rng, bookmark; editor.setContent('1
'); CaretContainer.insertBlock('p', editor.$('p')[0], true); rng = editor.dom.createRng(); rng.setStart(editor.$('p')[0], 0); rng.setEnd(editor.$('p')[0], 0); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2); editor.setContent('1
'); editor.selection.moveToBookmark(bookmark); LegacyUnit.equalDom(editor.selection.getNode(), editor.$('p')[0]); }); suite.test('select empty TD', function (editor) { editor.getBody().innerHTML = 'text1
text2
'); editor.selection.select(editor.dom.select('p')[0]); LegacyUnit.equal(editor.selection.getContent(), 'text1
', 'Select simple element, content'); LegacyUnit.equal(editor.selection.getStart().nodeName, 'P', 'Select simple element, nodeName'); }); suite.test('select table', function (editor) { editor.setContent('| text1 |
| text1 | \n
| text1 | text2 |
span1 word span2 word span3
'); rng = editor.dom.createRng(); rng.setStart(editor.dom.get('s1').firstChild, 0); rng.setEnd(editor.dom.get('s1').nextSibling, 0); editor.selection.setRng(rng); LegacyUnit.equalDom( editor.selection.getNode(), editor.dom.get('s1'), 'Detect selection ends immediately after node at start of paragraph.' ); rng = editor.dom.createRng(); rng.setStart(editor.dom.get('s2').previousSibling, editor.dom.get('s2').previousSibling.length); rng.setEnd(editor.dom.get('s2').nextSibling, 0); editor.selection.setRng(rng); LegacyUnit.equalDom( editor.selection.getNode(), editor.dom.get('s2'), 'Detect selection immediately surrounds node in middle of paragraph.' ); rng = editor.dom.createRng(); rng.setStart(editor.dom.get('s3').previousSibling, editor.dom.get('s3').previousSibling.length); rng.setEnd(editor.dom.get('s3').lastChild, editor.dom.get('s3').lastChild.length); editor.selection.setRng(rng); LegacyUnit.equalDom( editor.selection.getNode(), editor.dom.get('s3'), 'Detect selection starts immediately before node at end of paragraph.' ); rng = editor.dom.createRng(); rng.setStart(editor.dom.get('s2').previousSibling, editor.dom.get('s2').previousSibling.length); rng.setEnd(editor.dom.get('s3').lastChild, editor.dom.get('s3').lastChild.length); editor.selection.setRng(rng); LegacyUnit.equalDom( editor.selection.getNode(), editor.dom.get('p1'), 'Detect selection wrapping multiple nodes does not collapse.' ); }); suite.test('normalize to text node from document', function (editor) { let rng; // if (tinymce.isOpera || tinymce.isIE) { // ok(true, "Skipped on Opera/IE since Opera doesn't let you to set the range to document and IE will steal focus."); // return; // } editor.setContent('text
'); rng = editor.dom.createRng(); rng.setStart(editor.getDoc(), 0); rng.setEnd(editor.getDoc(), 0); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); LegacyUnit.equal(rng.startContainer.nodeType, 3, 'startContainer node type'); LegacyUnit.equal(rng.startOffset, 0, 'startContainer offset'); LegacyUnit.equal(rng.endContainer.nodeType, 3, 'endContainer node type'); LegacyUnit.equal(rng.endOffset, 0, 'endOffset offset'); }); suite.test('normalize to br from document', function (editor) { let rng; // if (tinymce.isOpera || tinymce.isIE) { // ok(true, "Skipped on Opera/IE since Opera doesn't let you to set the range to document and IE will steal focus."); // return; // } editor.setContent('abc
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.lastChild, 0); rng.setEnd(editor.getBody().firstChild.lastChild, 0); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); LegacyUnit.equal(rng.collapsed, true); LegacyUnit.equal(CaretContainer.isCaretContainer(rng.startContainer), true); }); suite.test('normalize with contentEditable:false parent and contentEditable:true child element', function (editor) { editor.setContent('ab
'); LegacyUnit.setSelection(editor, 'em', 0); editor.selection.normalize(); const rng = editor.selection.getRng(true); LegacyUnit.equal(rng.collapsed, true); LegacyUnit.equal(rng.startContainer.nodeType, 3); LegacyUnit.equal(rng.startContainer.data, 'b'); // WebKit is in some state state here, so lets restore it rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 0); editor.selection.setRng(rng); }); suite.test('normalize with contentEditable:true parent and contentEditable:false child element', function (editor) { if (Env.ie && Env.ie < 12) { editor.setContent('ab
'); LegacyUnit.setSelection(editor, 'em', 0); editor.selection.normalize(); const rng = editor.selection.getRng(true); LegacyUnit.equal(rng.startContainer.parentNode.contentEditable !== 'false', true); LegacyUnit.equal(rng.startOffset, 0); } }); suite.test('normalize to text node from body', function (editor) { let rng; editor.setContent('text
'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 0); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); LegacyUnit.equal(rng.startContainer.nodeType, 3, 'startContainer node type'); LegacyUnit.equal(rng.startOffset, 0, 'startContainer offset'); LegacyUnit.equal(rng.endContainer.nodeType, 3, 'endContainer node type'); LegacyUnit.equal(rng.endOffset, 0, 'endOffset offset'); }); suite.test('normalize to br from body', function (editor) { let rng; editor.setContent('a';
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeName, 'BODY', 'startContainer node name');
LegacyUnit.equal(rng.startContainer.nodeType, 1, 'startContainer node type');
LegacyUnit.equal(rng.startOffset, 0, 'startContainer offset');
LegacyUnit.equal(rng.endContainer.nodeName, 'BODY', 'endContainer node name');
LegacyUnit.equal(rng.endContainer.nodeType, 1, 'endContainer node type');
LegacyUnit.equal(rng.endOffset, 1, 'endOffset offset');
});
suite.test('normalize to text node inside P', function (editor) {
let rng;
editor.getBody().innerHTML = 'abc
';
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeName, '#text', 'startContainer node name');
LegacyUnit.equal(rng.startOffset, 0, 'startContainer offset');
LegacyUnit.equal(rng.endContainer.nodeName, '#text', 'endContainer node name');
LegacyUnit.equal(rng.endOffset, 3, 'endOffset offset');
});
suite.test('normalize lean left if at the start of text node', function (editor) {
let rng;
editor.getBody().innerHTML = 'ab
';
LegacyUnit.setSelection(editor, 'i', 0);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeName, '#text', 'startContainer node name');
LegacyUnit.equal(rng.startContainer.parentNode.nodeName, 'B');
LegacyUnit.equal(rng.startOffset, 1, 'startContainer offset');
LegacyUnit.equal(rng.endContainer.nodeName, '#text');
LegacyUnit.equal(rng.endContainer.parentNode.nodeName, 'B');
LegacyUnit.equal(rng.endOffset, 1, 'endOffset offset');
});
suite.test('normalize lean start to the right if at end of text node', function (editor) {
let rng;
editor.getBody().innerHTML = 'ab
';
LegacyUnit.setSelection(editor, 'b', 1, 'i', 1);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeName, '#text', 'startContainer node name');
LegacyUnit.equal(rng.startContainer.parentNode.nodeName, 'I');
LegacyUnit.equal(rng.startOffset, 0, 'startContainer offset');
LegacyUnit.equal(rng.endContainer.nodeName, '#text');
LegacyUnit.equal(rng.endContainer.parentNode.nodeName, 'I');
LegacyUnit.equal(rng.endOffset, 1, 'endOffset offset');
});
suite.test('normalize lean left but break before br', function (editor) {
let rng;
editor.getBody().innerHTML = 'a
b
';
LegacyUnit.setSelection(editor, 'b', 0);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeValue, 'b');
LegacyUnit.equal(rng.startOffset, 0);
});
suite.test('normalize lean left but break before img', function (editor) {
let rng;
editor.getBody().innerHTML = 'a
b
';
LegacyUnit.setSelection(editor, 'b', 0);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeValue, 'b');
LegacyUnit.equal(rng.startOffset, 0);
});
suite.test('normalize lean left but don\'t walk out the parent block', function (editor) {
let rng;
editor.getBody().innerHTML = 'a
b
';
LegacyUnit.setSelection(editor, 'b', 0);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeValue, 'b');
LegacyUnit.equal(rng.startOffset, 0);
});
suite.test('normalize lean left into empty inline elements when caret is before br', function (editor) {
let rng;
editor.getBody().innerHTML = '
';
rng = editor.dom.createRng();
rng.setStartBefore(editor.getBody().firstChild.lastChild);
rng.setEndBefore(editor.getBody().firstChild.lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeName, 'B');
LegacyUnit.equal(rng.startOffset, 0);
});
suite.test('normalize lean left from br into formatter caret container', function (editor) {
let rng;
editor.getBody().innerHTML = '' + Zwsp.ZWSP + '
';
rng = editor.dom.createRng();
rng.setStartBefore(editor.getBody().firstChild.lastChild);
rng.setEndBefore(editor.getBody().firstChild.lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeType, 3);
LegacyUnit.equal(rng.startOffset, 1);
});
suite.test('normalize don\'t lean left into empty inline elements if there is a br element after caret', function (editor) {
let rng;
editor.getBody().innerHTML = '
';
rng = editor.dom.createRng();
rng.setStartBefore(editor.getBody().firstChild.lastChild);
rng.setEndBefore(editor.getBody().firstChild.lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeName, 'P');
LegacyUnit.equal(rng.startOffset, 2);
});
suite.test('normalize don\'t lean left into empty inline elements if there is a br element before caret', function (editor) {
let rng;
editor.getBody().innerHTML = '
';
rng = editor.dom.createRng();
rng.setStartBefore(editor.getBody().firstChild.lastChild);
rng.setEndBefore(editor.getBody().firstChild.lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
LegacyUnit.equal(rng.startContainer.nodeName, 'P');
LegacyUnit.equal(rng.startOffset, 1);
});
suite.test('normalize don\'t move start/end if it\'s before/after table', function (editor) {
let rng;
editor.getBody().innerHTML = '| X |
a
'; rng = editor.dom.createRng(); rng.setStartAfter(editor.getBody().firstChild); rng.setEndAfter(editor.getBody().lastChild); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); LegacyUnit.equal(rng.startContainer.nodeName, '#text'); LegacyUnit.equal(rng.startOffset, 1); LegacyUnit.equal(rng.endContainer.nodeName, '#text'); LegacyUnit.equal(rng.endOffset, 1); }); suite.test('normalize caret after trailing BR', function (editor) { let rng; editor.getBody().innerHTML = 'a
| b |
a
text
'; LegacyUnit.setSelection(editor, 'p', 0, 'p', 4); editor.nodeChanged(); LegacyUnit.equal(newArgs.selector, 'a[href]'); LegacyUnit.equalDom(newArgs.node, editor.getBody().firstChild); LegacyUnit.equal(newArgs.parents.length, 1); }); suite.test('setRng', function (editor) { let rng = editor.dom.createRng(); editor.setContent('x
'); rng.setStart(editor.$('p')[0].firstChild, 0); rng.setEnd(editor.$('p')[0].firstChild, 1); editor.selection.setRng(rng); editor.selection.setRng(null); rng = editor.selection.getRng(true); LegacyUnit.equal(rng.startContainer.nodeName, '#text'); LegacyUnit.equal(rng.startOffset, 0); LegacyUnit.equal(rng.endContainer.nodeName, '#text'); LegacyUnit.equal(rng.endOffset, 1); }); suite.test('setRng invalid range', function (editor) { let rng = editor.dom.createRng(); editor.setContent('x
'); rng.setStart(editor.$('p')[0].firstChild, 0); rng.setEnd(editor.$('p')[0].firstChild, 1); editor.selection.setRng(rng); const tmpNode = document.createTextNode('y'); const invalidRng = rng.cloneRange(); invalidRng.setStart(tmpNode, 0); invalidRng.setEnd(tmpNode, 0); editor.selection.setRng(invalidRng); rng = editor.selection.getRng(true); LegacyUnit.equal(rng.startContainer.nodeName, '#text'); LegacyUnit.equal(rng.startContainer.data, 'x'); LegacyUnit.equal(rng.startOffset, 0); LegacyUnit.equal(rng.endContainer.nodeName, '#text'); LegacyUnit.equal(rng.endOffset, 1); }); suite.test('setRng invalid range removed parent context', function (editor) { editor.setContent('x
'); const textNode = editor.$('em')[0].firstChild; editor.setContent(''); const rng = editor.dom.createRng(); rng.setStart(textNode, 0); rng.setEnd(textNode, 1); editor.selection.setRng(rng); const curRng = editor.selection.getRng(true); LegacyUnit.equal(curRng.startContainer.nodeName, 'BODY'); LegacyUnit.equal(curRng.startOffset, 0); LegacyUnit.equal(curRng.endContainer.nodeName, 'BODY'); LegacyUnit.equal(curRng.endOffset, 0); }); /* // TODO: Re-implement this test as a separate test if needed by destroying an editor etc suite.test('getRng should return null if win.document is not defined or null', function (editor) { const win = editor.selection.win; let rng = editor.dom.createRng(); editor.setContent('x
'); rng.setStart(editor.$('p')[0].firstChild, 0); rng.setEnd(editor.$('p')[0].firstChild, 1); editor.selection.setRng(rng); editor.selection.setRng(null); editor.selection.win = {}; rng = editor.selection.getRng(true); LegacyUnit.equal(rng, null); editor.selection.win = { document: null }; rng = editor.selection.getRng(true); LegacyUnit.equal(rng, null); editor.selection.win = win; }); */ suite.test('image selection webkit bug', function (editor) { const testImageSelection = function (inputHtml, expectedContainerName, expectedOffset) { editor.setContent(inputHtml); editor.selection.select(editor.dom.select('img')[0]); const rng = editor.selection.getRng(true); LegacyUnit.equal(rng.startContainer.nodeName, 'P'); LegacyUnit.equal(rng.startOffset, expectedOffset); LegacyUnit.equal(rng.startContainer.nodeName, 'P'); LegacyUnit.equal(rng.endOffset, expectedOffset + 1); LegacyUnit.equal(editor.selection.getNode().nodeName, 'IMG'); LegacyUnit.equal(editor.selection.getStart().nodeName, 'IMG'); LegacyUnit.equal(editor.selection.getEnd().nodeName, 'IMG'); const nativeRng = editor.selection.getSel().getRangeAt(0); LegacyUnit.equal(nativeRng.startContainer.nodeName, 'P'); LegacyUnit.equal(nativeRng.startOffset, expectedOffset); LegacyUnit.equal(nativeRng.startContainer.nodeName, 'P'); LegacyUnit.equal(nativeRng.endOffset, expectedOffset + 1); }; testImageSelection('abc
abc
abcdef
abc
abc
abcdef
abc
abc
abcdef
abc
abc
abcdef
abc
abc
abcdef