module("tinymce.dom.Selection", { setupModule: function() { QUnit.stop(); tinymce.init({ selector: "textarea", add_unload_trigger: false, skin: false, forced_root_block: '', entities: 'raw', valid_styles: { '*': 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display' }, custom_elements: 'custom1,~custom2', extended_valid_elements: 'custom1,custom2', init_instance_callback: function(ed) { window.editor = ed; QUnit.start(); } }); } }); test('getContent', function() { var rng, eventObj; // Get selected contents editor.setContent('

text

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 1); editor.selection.setRng(rng); 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); equal(editor.selection.getContent(), '', 'Get selected contents (collapsed)'); // Get selected contents, onGetContent event eventObj = {}; function handler(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(); equal(eventObj.content, '

text

', 'Get selected contents, onGetContent event'); editor.off('GetContent', handler); }); test('setContent', function() { var 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('
test
'); equal(editor.getContent(), '
test
', 'Set contents at selection'); // Set contents at selection (collapsed) editor.setContent('

text

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 0); editor.selection.setRng(rng); editor.selection.setContent('
test
'); equal(editor.getContent(), '
test
\n

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('
'); equal(editor.getContent(), '

before
after

', 'Set contents at selection (inside paragraph)'); // Check the caret is left in the correct position. rng = editor.selection.getRng(true); if (document.createRange) { equal(rng.startContainer, editor.getBody().firstChild, 'Selection start container'); equal(rng.startOffset, 2, 'Selection start offset'); equal(rng.endContainer, editor.getBody().firstChild, 'Selection end container'); equal(rng.endOffset, 2, 'Selection end offset'); } else { // TridentSelection resolves indexed text nodes equal(rng.startContainer, editor.getBody().firstChild.lastChild, 'Selection start container'); equal(rng.startOffset, 0, 'Selection start offset'); equal(rng.endContainer, editor.getBody().firstChild.lastChild, 'Selection end container'); equal(rng.endOffset, 0, 'Selection end offset'); } editor.setContent('

text

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 0); editor.selection.setRng(rng); editor.selection.setContent(''); 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 equal(rng.startContainer, editor.getBody().firstChild.firstChild, 'Selection start container'); equal(rng.startOffset, 0, 'Selection start offset'); equal(rng.endContainer, editor.getBody().firstChild.firstChild, 'Selection end container'); equal(rng.endOffset, 0, 'Selection end offset'); } else { equal(rng.startContainer, editor.getBody(), 'Selection start container'); equal(rng.startOffset, 0, 'Selection start offset'); equal(rng.endContainer, editor.getBody(), 'Selection end container'); equal(rng.endOffset, 0, 'Selection end offset'); } // Set selected contents, onSetContent event eventObj = {}; function handler(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
'); equal(eventObj.content, '
text
', 'Set selected contents, onSetContent event'); editor.off('SetContent', handler); }); test('getStart/getEnd', function() { var rng; // Selected contents editor.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); equal(editor.selection.getStart().id, 'a', 'Selected contents (getStart)'); equal(editor.selection.getEnd().id, 'b', 'Selected contents (getEnd)'); // Selected contents (collapsed) editor.setContent('

text

\n

text

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild.firstChild, 0); rng.setEnd(editor.getBody().firstChild.firstChild, 0); editor.selection.setRng(rng); equal(editor.selection.getStart().id, 'a', 'Selected contents (getStart, collapsed)'); equal(editor.selection.getEnd().id, 'a', 'Selected contents (getEnd, collapsed)'); }); test('getBookmark/setBookmark (persistent)', function() { var 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(); equal(editor.getContent(), 'text', 'Editor contents (text)'); editor.selection.moveToBookmark(bookmark); equal(editor.selection.getContent(), 'ex', 'Selected contents (text)'); // Get persistent bookmark multiple elements text selection editor.setContent('

text

\n

text

'); 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(); equal(editor.getContent(), '

text

\n

text

', 'Editor contents (elements)'); editor.selection.moveToBookmark(bookmark); equal(editor.selection.getContent(), '

ext

\n

tex

', 'Selected contents (elements)'); }); test('getBookmark/setBookmark (simple)', function() { var 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); equal(editor.getContent(), 'text', 'Editor contents (text)'); editor.selection.moveToBookmark(bookmark); equal(editor.selection.getContent(), 'ex', 'Selected contents (text)'); // Get persistent bookmark multiple elements text selection editor.setContent('

text

\n

text

'); 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); equal(editor.getContent(), '

text

\n

text

', 'Editor contents (elements)'); editor.selection.moveToBookmark(bookmark); equal(editor.selection.getContent(), '

ext

\n

tex

', 'Selected contents (elements)'); }); test('getBookmark/setBookmark (nonintrusive) - simple text selection', function() { var rng, bookmark; expect(2); 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); equal(editor.getContent(), 'text', 'Editor contents (text)'); editor.selection.moveToBookmark(bookmark); equal(editor.selection.getContent(), 'ex', 'Selected contents (text)'); }); test('getBookmark/setBookmark (nonintrusive) - Get non intrusive bookmark simple element selection', function() { var rng, bookmark; expect(1); // 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); equal(editor.selection.getContent(), 'b', 'Selected contents (element)'); }); test('getBookmark/setBookmark (nonintrusive) - Get non intrusive bookmark multiple elements text selection', function() { var rng, bookmark; expect(2); // Get non intrusive bookmark multiple elements text selection editor.setContent('

text

\n

text

'); 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); equal(editor.getContent(), '

text

\n

text

', 'Editor contents (elements)'); editor.selection.moveToBookmark(bookmark); equal(editor.selection.getContent(), '

ext

\n

tex

', 'Selected contents (elements)'); }); test('getBookmark/setBookmark (nonintrusive)', function() { var rng, bookmark; expect(2); // 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); equal(editor.getContent(), '

textaaatext

\n

text

', 'Editor contents (fragmented, elements)'); editor.selection.moveToBookmark(bookmark); equal(editor.selection.getContent(), '

ext

\n

tex

', 'Selected contents (fragmented, elements)'); }); test('getBookmark/setBookmark (nonintrusive) - fragmentext text (normalized)', function() { var rng, bookmark; expect(2); // 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()); equal(editor.getContent(), '

textaaatext

\n

text

', 'Editor contents (fragmented, elements)'); editor.selection.moveToBookmark(bookmark); equal(editor.selection.getContent(), '

ext

\n

tex

', 'Selected contents (fragmented, elements)'); }); test('getBookmark/setBookmark (nonintrusive) - Get bookmark before image', function() { var rng, bookmark; expect(4); editor.setContent('

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 0); rng.setEnd(editor.getBody().firstChild, 0); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.getBody().innerHTML = editor.getBody().innerHTML; editor.selection.moveToBookmark(bookmark); rng = editor.selection.getRng(true); equal(rng.startContainer, editor.getBody().firstChild); equal(rng.startOffset, 0); equal(rng.endContainer, editor.getBody().firstChild); equal(rng.endOffset, 0); }); test('getBookmark/setBookmark (nonintrusive) - Get bookmark before/after image', function() { var rng, bookmark; expect(4); editor.setContent('

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 0); rng.setEnd(editor.getBody().firstChild, 1); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.getBody().innerHTML = editor.getBody().innerHTML; editor.selection.moveToBookmark(bookmark); rng = editor.selection.getRng(true); equal(rng.startContainer, editor.getBody().firstChild); equal(rng.startOffset, 0); equal(rng.endContainer, editor.getBody().firstChild); equal(rng.endOffset, 1); }); test('getBookmark/setBookmark (nonintrusive) - Get bookmark after image', function() { var rng, bookmark; expect(4); editor.setContent('

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 1); rng.setEnd(editor.getBody().firstChild, 1); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.getBody().innerHTML = editor.getBody().innerHTML; editor.selection.moveToBookmark(bookmark); rng = editor.selection.getRng(true); equal(rng.startContainer, editor.getBody().firstChild); equal(rng.startOffset, 1); equal(rng.endContainer, editor.getBody().firstChild); equal(rng.endOffset, 1); }); test('getBookmark/setBookmark (nonintrusive) - Get bookmark before element', function() { var rng, bookmark; expect(4); editor.setContent('abc123'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 0); rng.setEnd(editor.getBody().firstChild, 2); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.getBody().innerHTML = editor.getBody().innerHTML; editor.selection.moveToBookmark(bookmark); rng = editor.selection.getRng(true); equal(rng.startContainer, editor.getBody().firstChild); equal(rng.startOffset, 0); equal(rng.endContainer, editor.getBody().firstChild); equal(rng.endOffset, 2); }); test('getBookmark/setBookmark (nonintrusive) - Get bookmark after element', function() { var rng, bookmark; expect(4); // Get bookmark after element editor.setContent('123abc'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().lastChild, 1); rng.setEnd(editor.getBody().lastChild, 2); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.getBody().innerHTML = editor.getBody().innerHTML; editor.selection.moveToBookmark(bookmark); rng = editor.selection.getRng(true); equal(rng.startContainer, editor.getBody().lastChild); equal(rng.startOffset, 1); equal(rng.endContainer, editor.getBody().lastChild); equal(rng.endOffset, 2); }); test('getBookmark/setBookmark (nonintrusive) - Get bookmark inside element', function() { var rng, bookmark; expect(4); editor.setContent('abc123abc'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().childNodes[1].firstChild, 1); rng.setEnd(editor.getBody().childNodes[1].firstChild, 2); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.getBody().innerHTML = editor.getBody().innerHTML; editor.selection.moveToBookmark(bookmark); rng = editor.selection.getRng(true); equal(rng.startContainer, editor.getBody().childNodes[1].firstChild); equal(rng.startOffset, 1); equal(rng.endContainer, editor.getBody().childNodes[1].firstChild); equal(rng.endOffset, 2); }); test('getBookmark/setBookmark (nonintrusive) - Get bookmark inside root text', function() { var rng, bookmark; expect(4); editor.setContent('abc'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 1); rng.setEnd(editor.getBody().firstChild, 2); editor.selection.setRng(rng); bookmark = editor.selection.getBookmark(2, true); editor.getBody().innerHTML = editor.getBody().innerHTML; editor.selection.moveToBookmark(bookmark); rng = editor.selection.getRng(true); equal(rng.startContainer, editor.getBody().firstChild); equal(rng.startOffset, 1); equal(rng.endContainer, editor.getBody().firstChild); equal(rng.endOffset, 2); }); test('getBookmark/setBookmark (nonintrusive) - Get bookmark inside complex html', function() { var rng, bookmark; expect(4); editor.setContent('

abc

123

123

123123
abc

'); editor.execCommand('SelectAll'); Utils.setSelection('td', 1, 'td', 2); bookmark = editor.selection.getBookmark(2, true); editor.getBody().innerHTML = editor.getBody().innerHTML; editor.selection.moveToBookmark(bookmark); rng = editor.selection.getRng(true); equal(rng.startContainer, editor.dom.select('td')[0].firstChild); equal(rng.startOffset, 1); equal(rng.endContainer, editor.dom.select('td')[0].firstChild); equal(rng.endOffset, 2); }); test('select first p', 2, function() { editor.setContent('

text1

text2

'); editor.selection.select(editor.dom.select('p')[0]); equal(editor.selection.getContent(), '

text1

', 'Select simple element, content'); equal(editor.selection.getStart().nodeName, 'P', 'Select simple element, nodeName'); }); test('select table', 2, function() { editor.setContent('
text1
'); editor.selection.select(editor.dom.select('table')[0]); equal(editor.selection.getContent(), '\n\n\n\n\n\n
text1
', 'Select complex element, content'); equal(editor.selection.getNode().nodeName, 'TABLE', 'Select complex element, nodeName'); }); test('select table text 1', 2, function() { editor.setContent('
text1text2
'); editor.selection.select(editor.dom.select('table')[0], true); equal(editor.selection.getStart().id, 'a', 'Expand to text content 1 (start)'); equal(editor.selection.getEnd().id, 'b', 'Expand to text content 1 (end)'); }); test('select table text 2', 2, function() { editor.setContent('


'); editor.selection.select(editor.dom.select('table')[0], true); equal(editor.dom.getParent(editor.selection.getStart(), 'td').id, 'a', 'Expand to text content 2 (start)'); equal(editor.dom.getParent(editor.selection.getEnd(), 'td').id, 'b', 'Expand to text content 2 (end)'); }); test('getNode', function() { var rng; editor.setContent('

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); deepEqual(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); deepEqual(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); deepEqual(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); deepEqual(editor.selection.getNode(), editor.dom.get('p1'), 'Detect selection wrapping multiple nodes does not collapse.'); }); test('normalize to text node from document', function() { var 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); equal(rng.startContainer.nodeType, 3, 'startContainer node type'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeType, 3, 'endContainer node type'); equal(rng.endOffset, 0, 'endOffset offset'); }); test('normalize to br from document', function() { var 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('


'); 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); equal(rng.startContainer.nodeName, 'P', 'startContainer node name'); equal(rng.startContainer.nodeType, 1, 'startContainer node type'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeType, 1, 'endContainer node type'); equal(rng.endOffset, 0, 'endOffset offset'); }); // Only run on non IE browsers since it's not an issue on IE if (!tinymce.isIE) { test('normalize with contentEditable:false element', function() { var rng; 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); equal(rng.collapsed, true); equal(rng.startContainer.nodeType, 3); equal(rng.startContainer.data, 'c'); }); test('normalize with contentEditable:false parent and contentEditable:true child element', function() { editor.setContent('

ab

'); Utils.setSelection('em', 0); editor.selection.normalize(); var rng = editor.selection.getRng(true); equal(rng.collapsed, true); equal(rng.startContainer.nodeType, 3); equal(rng.startContainer.data, 'b'); }); test('normalize with contentEditable:true parent and contentEditable:false child element', function() { editor.setContent('

ab

'); Utils.setSelection('em', 0); editor.selection.normalize(); var rng = editor.selection.getRng(true); equal(rng.collapsed, true); equal(rng.startContainer.nodeType, 3); equal(rng.startContainer.data, 'a'); equal(rng.startOffset, 1); }); test('normalize to text node from body', function() { var 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); equal(rng.startContainer.nodeType, 3, 'startContainer node type'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeType, 3, 'endContainer node type'); equal(rng.endOffset, 0, 'endOffset offset'); }); test('normalize to br from body', function() { var rng; editor.setContent('


'); 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); equal(rng.startContainer.nodeName, 'P', 'startContainer node name'); equal(rng.startContainer.nodeType, 1, 'startContainer node type'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeType, 1, 'endContainer node type'); equal(rng.endOffset, 0, 'endOffset offset'); }); test('normalize ignore img', function() { var rng; editor.getBody().innerHTML = ''; 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); equal(rng.startContainer.nodeName, 'BODY', 'startContainer node name'); equal(rng.startContainer.nodeType, 1, 'startContainer node type'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeName, 'BODY', 'endContainer node name'); equal(rng.endContainer.nodeType, 1, 'endContainer node type'); equal(rng.endOffset, 1, 'endOffset offset'); }); test('normalize to before/after img', function() { var rng; editor.getBody().innerHTML = '

'; 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); equal(rng.startContainer.nodeName, 'P', 'startContainer node name'); equal(rng.startContainer.nodeType, 1, 'startContainer node type'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeName, 'P', 'endContainer node name'); equal(rng.endContainer.nodeType, 1, 'endContainer node type'); equal(rng.endOffset, 1, 'endOffset offset'); }); test('normalize to text node inside P', function() { var 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); equal(rng.startContainer.nodeName, '#text', 'startContainer node name'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeName, '#text', 'endContainer node name'); equal(rng.endOffset, 3, 'endOffset offset'); }); test('normalize lean left if at the start of text node', function() { var rng; editor.getBody().innerHTML = '

ab

'; Utils.setSelection('i', 0); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeName, '#text', 'startContainer node name'); equal(rng.startContainer.parentNode.nodeName, 'B'); equal(rng.startOffset, 1, 'startContainer offset'); equal(rng.endContainer.nodeName, '#text'); equal(rng.endContainer.parentNode.nodeName, 'B'); equal(rng.endOffset, 1, 'endOffset offset'); }); test('normalize lean start to the right if at end of text node', function() { var rng; editor.getBody().innerHTML = '

ab

'; Utils.setSelection('b', 1, 'i', 1); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeName, '#text', 'startContainer node name'); equal(rng.startContainer.parentNode.nodeName, 'I'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeName, '#text'); equal(rng.endContainer.parentNode.nodeName, 'I'); equal(rng.endOffset, 1, 'endOffset offset'); }); test('normalize lean left but break before br', function() { var rng; editor.getBody().innerHTML = '

a
b

'; Utils.setSelection('b', 0); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeValue, 'b'); equal(rng.startOffset, 0); }); test('normalize lean left but break before img', function() { var rng; editor.getBody().innerHTML = '

ab

'; Utils.setSelection('b', 0); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeValue, 'b'); equal(rng.startOffset, 0); }); test('normalize lean left but don\'t walk out the parent block', function() { var rng; editor.getBody().innerHTML = '

a

b

'; Utils.setSelection('b', 0); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeValue, 'b'); equal(rng.startOffset, 0); }); test('normalize lean left into empty inline elements when caret is before br', function() { var 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); equal(rng.startContainer.nodeName, 'B'); equal(rng.startOffset, 0); }); test('normalize don\'t lean left into empty inline elements if there is a br element after caret', function() { var 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); equal(rng.startContainer.nodeName, 'P'); equal(rng.startOffset, 2); }); test('normalize don\'t lean left into empty inline elements if there is a br element before caret', function() { var 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); equal(rng.startContainer.nodeName, 'P'); equal(rng.startOffset, 1); }); test('normalize don\'t move start/end if it\'s before/after table', function() { var rng; editor.getBody().innerHTML = '
X
'; rng = editor.dom.createRng(); rng.setStartBefore(editor.getBody().firstChild); rng.setEndAfter(editor.getBody().lastChild); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeName, 'BODY'); equal(rng.startOffset, 0); equal(rng.endContainer.nodeName, 'BODY'); equal(rng.endOffset, 1); }); test('normalize after paragraph', function() { var rng; editor.getBody().innerHTML = '

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); equal(rng.startContainer.nodeName, '#text'); equal(rng.startOffset, 1); equal(rng.endContainer.nodeName, '#text'); equal(rng.endOffset, 1); }); test('normalize caret after trailing BR', function() { var rng; editor.setContent('

a

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 2); rng.setEnd(editor.getBody().firstChild, 2); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeName, '#text', 'startContainer node name'); equal(rng.startOffset, 1, 'startContainer offset'); equal(rng.endContainer.nodeName, '#text', 'endContainer node name'); equal(rng.endOffset, 1, 'endOffset offset'); }); test('normalize caret after bogus block BR', function() { var rng; editor.setContent('


'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 1); rng.setEnd(editor.getBody().firstChild, 1); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeName, 'P', 'startContainer node name'); equal(rng.startOffset, 0, 'startContainer offset'); equal(rng.endContainer.nodeName, 'P', 'endContainer node name'); equal(rng.endOffset, 0, 'endOffset offset'); }); /* test('normalize caret after last BR in block', function() { var rng; editor.setContent('



'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 2); rng.setEnd(editor.getBody().firstChild, 2); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeName, 'P', 'startContainer node name'); equal(rng.startOffset, 1, 'startContainer offset'); equal(rng.endContainer.nodeName, 'P', 'endContainer node name'); equal(rng.endOffset, 1, 'endOffset offset'); }); */ test('normalize caret after double BR', function() { var rng; editor.setContent('

a

'); rng = editor.dom.createRng(); rng.setStart(editor.getBody().firstChild, 3); rng.setEnd(editor.getBody().firstChild, 3); editor.selection.setRng(rng); editor.selection.normalize(); rng = editor.selection.getRng(true); equal(rng.startContainer.nodeName, 'P', 'startContainer node name'); equal(rng.startOffset, 3, 'startContainer offset'); equal(rng.endContainer.nodeName, 'P', 'endContainer node name'); equal(rng.endOffset, 3, 'endOffset offset'); }); } test('custom elements', function() { var rng; editor.setContent('testtest'); rng = editor.dom.createRng(); rng.setStart(editor.getBody(), 0); rng.setEnd(editor.getBody(), 2); editor.selection.setRng(rng); equal(editor.selection.getContent(), 'testtest'); }); test('selectorChanged', function() { var newState, newArgs; editor.selection.selectorChanged('a[href]', function(state, args) { newState = state; newArgs = args; }); editor.getBody().innerHTML = '

text

'; Utils.setSelection('a', 0, 'a', 4); editor.nodeChanged(); ok(newState); equal(newArgs.selector, 'a[href]'); equal(newArgs.node, editor.getBody().firstChild.firstChild); equal(newArgs.parents.length, 2); editor.getBody().innerHTML = '

text

'; Utils.setSelection('p', 0, 'p', 4); editor.nodeChanged(); equal(newArgs.selector, 'a[href]'); equal(newArgs.node, editor.getBody().firstChild); equal(newArgs.parents.length, 1); });