ModuleLoader.require([ "tinymce/Env", "tinymce/caret/CaretWalker", "tinymce/caret/CaretPosition" ], function(Env, CaretWalker, CaretPosition) { module("tinymce.caret.CaretWalker"); if (!Env.ceFalse) { return; } function getRoot() { return document.getElementById('view'); } function setupHtml(html) { tinymce.$(getRoot()).empty(); getRoot().innerHTML = html; } function findElm(selector) { return tinymce.$(selector, getRoot())[0]; } function findElmPos(selector, offset) { return CaretPosition(tinymce.$(selector, getRoot())[0], offset); } function findTextPos(selector, offset) { return CaretPosition(tinymce.$(selector, getRoot())[0].firstChild, offset); } var assertCaretPosition = Utils.assertCaretPosition, logicalCaret = new CaretWalker(getRoot()); test('inside empty root', function() { setupHtml(''); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 0)), null); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 0)), null); }); test('on null', function() { setupHtml(''); assertCaretPosition(logicalCaret.next(null), null); assertCaretPosition(logicalCaret.prev(null), null); }); test('within text node in root', function() { setupHtml('abc'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 0)), CaretPosition(getRoot().firstChild, 1)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 1)), CaretPosition(getRoot().firstChild, 2)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 2)), CaretPosition(getRoot().firstChild, 3)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 3)), null); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().firstChild, 3)), CaretPosition(getRoot().firstChild, 2)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().firstChild, 2)), CaretPosition(getRoot().firstChild, 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().firstChild, 1)), CaretPosition(getRoot().firstChild, 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().firstChild, 0)), null); }); test('within text node in element', function() { setupHtml('

abc

'); assertCaretPosition(logicalCaret.next(findTextPos('p', 0)), findTextPos('p', 1)); assertCaretPosition(logicalCaret.next(findTextPos('p', 1)), findTextPos('p', 2)); assertCaretPosition(logicalCaret.next(findTextPos('p', 2)), findTextPos('p', 3)); assertCaretPosition(logicalCaret.next(findTextPos('p', 3)), null); assertCaretPosition(logicalCaret.prev(findTextPos('p', 3)), findTextPos('p', 2)); assertCaretPosition(logicalCaret.prev(findTextPos('p', 2)), findTextPos('p', 1)); assertCaretPosition(logicalCaret.prev(findTextPos('p', 1)), findTextPos('p', 0)); assertCaretPosition(logicalCaret.prev(findTextPos('p', 0)), null); }); test('from index text node over comment', function() { setupHtml('abcdabcd'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 0)), CaretPosition(getRoot().firstChild, 0)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 1)), CaretPosition(getRoot().lastChild, 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), CaretPosition(getRoot().firstChild, 4)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 3)), CaretPosition(getRoot().lastChild, 4)); }); test('from text to text across elements', function() { setupHtml('

abc

abc

'); assertCaretPosition(logicalCaret.next(findTextPos('p:first', 3)), findTextPos('p:last', 0)); assertCaretPosition(logicalCaret.prev(findTextPos('p:last', 0)), findTextPos('p:first', 3)); }); test('from text to text across elements with siblings', function() { setupHtml('

abc

abc

'); assertCaretPosition(logicalCaret.next(findTextPos('p:first', 3)), CaretPosition(findElm('p:last').lastChild, 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(findElm('p:last').lastChild)), findTextPos('p:first', 3)); }); test('from input to text', function() { setupHtml('123456'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 2)), CaretPosition(getRoot().lastChild, 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 1)), CaretPosition(getRoot().firstChild, 3)); }); test('from input to input across elements', function() { setupHtml('

'); assertCaretPosition(logicalCaret.next(CaretPosition(findElm('p:first'), 1)), CaretPosition(findElm('p:last'), 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(findElm('p:last'), 0)), CaretPosition(findElm('p:first'), 1)); }); test('next br to br across elements', function() { setupHtml('



'); assertCaretPosition(logicalCaret.next(CaretPosition(findElm('p:first'), 0)), CaretPosition(findElm('p:last'), 0)); }); test('prev br to br across elements', function() { setupHtml('



'); assertCaretPosition(logicalCaret.prev(CaretPosition(findElm('p:last'), 0)), CaretPosition(findElm('p:first'), 0)); }); test('from before/after br to text', function() { setupHtml('
123
456
789'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 0)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 2)), CaretPosition(getRoot(), 3)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 4)), CaretPosition(getRoot(), 5)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 5)), CaretPosition(getRoot().lastChild, 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 5)), CaretPosition(getRoot(), 4)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 4)), CaretPosition(getRoot().childNodes[3], 3)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 1)), CaretPosition(getRoot(), 0)); }); test('over br', function() { setupHtml('


'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 0)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 1)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 2)), CaretPosition(getRoot(), 3)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 3)), null); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 3)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 1)), CaretPosition(getRoot(), 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 0)), null); }); test('over input', function() { setupHtml(''); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 0)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 1)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 2)), CaretPosition(getRoot(), 3)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 3)), null); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 3)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 1)), CaretPosition(getRoot(), 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 0)), null); }); test('over img', function() { setupHtml(''); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 0)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 1)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 2)), CaretPosition(getRoot(), 3)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 3)), null); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 3)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 1)), CaretPosition(getRoot(), 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 0)), null); }); test('over script/style/textarea', function() { setupHtml('abcd'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 1)), CaretPosition(getRoot().childNodes[2], 0)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().childNodes[2], 1)), CaretPosition(getRoot().childNodes[4], 0)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 5)), CaretPosition(getRoot(), 6)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 6)), CaretPosition(getRoot(), 5)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().childNodes[4], 0)), CaretPosition(getRoot().childNodes[2], 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), CaretPosition(getRoot().childNodes[0], 1)); }); test('around tables', function() { setupHtml('a
A
B
b'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 1)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 1)), findTextPos('td:first', 0)); assertCaretPosition(logicalCaret.next(findTextPos('td:first', 1)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 2)), findTextPos('td:last', 0)); assertCaretPosition(logicalCaret.next(findTextPos('table:last td', 1)), CaretPosition(getRoot(), 3)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 3)), CaretPosition(getRoot().lastChild, 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().lastChild, 0)), CaretPosition(getRoot(), 3)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 3)), findTextPos('td:last', 1)); assertCaretPosition(logicalCaret.prev(findTextPos('td:last', 0)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), findTextPos('td:first', 1)); assertCaretPosition(logicalCaret.prev(findTextPos('td:first', 0)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 1)), CaretPosition(getRoot().firstChild, 1)); }); test('over cE=false', function() { setupHtml('123a456'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 3)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 1)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().lastChild, 0)), CaretPosition(getRoot(), 2)); }); /* test('from outside cE=false to nested cE=true', function() { setupHtml('abcbcdef'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 3)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 1)), findTextPos('span span', 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().lastChild, 0)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), findTextPos('span span', 1)); }); test('from outside cE=false to nested cE=true before/after cE=false', function() { setupHtml('abd'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot(), 1)), CaretPosition(findElm('span span'), 0)); assertCaretPosition(logicalCaret.next(CaretPosition(findElm('span span'), 1)), CaretPosition(getRoot(), 2)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot(), 2)), CaretPosition(findElm('span span'), 1)); }); */ test('from inside cE=true in cE=false to after cE=false', function() { setupHtml( '

' + '' + '' + 'abc' + '' + 'def' + '' + '

' + '

abc

' ); assertCaretPosition(logicalCaret.next(findTextPos('span span', 3)), CaretPosition(findElm('p'), 1)); }); test('around cE=false inside nested cE=true', function() { setupHtml( '' + '' + '1' + '2' + '3' + '' + '' ); assertCaretPosition(logicalCaret.next(CaretPosition(findElm('span span'), 0)), CaretPosition(findElm('span span'), 1)); assertCaretPosition(logicalCaret.next(CaretPosition(findElm('span span'), 1)), CaretPosition(findElm('span span'), 2)); assertCaretPosition(logicalCaret.next(CaretPosition(findElm('span span'), 2)), CaretPosition(findElm('span span'), 3)); assertCaretPosition(logicalCaret.next(CaretPosition(findElm('span span'), 3)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(findElm('span span'), 0)), CaretPosition(getRoot(), 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(findElm('span span'), 1)), CaretPosition(findElm('span span'), 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(findElm('span span'), 2)), CaretPosition(findElm('span span'), 1)); assertCaretPosition(logicalCaret.prev(CaretPosition(findElm('span span'), 3)), CaretPosition(findElm('span span'), 2)); }); test('next from last node', function() { setupHtml( '

' + '' + '

' ); assertCaretPosition(logicalCaret.next(findElmPos('p:first', 1)), CaretPosition(getRoot(), 1)); assertCaretPosition(logicalCaret.next(findElmPos('p:last', 1)), null); }); test('left/right between cE=false inlines in different blocks', function() { setupHtml( '

' + 'abc' + '

' + '

' + 'def' + '

' ); assertCaretPosition(logicalCaret.next(findElmPos('p:first', 1)), findElmPos('p:last', 0)); assertCaretPosition(logicalCaret.prev(findElmPos('p:last', 0)), findElmPos('p:first', 1)); }); test('never into caret containers', function() { setupHtml('abcdefghi'); assertCaretPosition(logicalCaret.next(CaretPosition(getRoot().firstChild, 3)), CaretPosition(getRoot().lastChild, 0)); assertCaretPosition(logicalCaret.prev(CaretPosition(getRoot().lastChild, 0)), CaretPosition(getRoot().firstChild, 3)); }); });