Ticket #3299: 3299.patch
File 3299.patch, 11.4 KB (added by , 15 years ago) |
---|
-
_source/core/dom/range.js
259 259 260 260 var inlineChildReqElements = { abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1 }; 261 261 262 // Check every node between the block boundary and the startNode or endNode. 263 var getCheckStartEndBlockFunction = function( isStart ) 262 // Creates the appropriate node evaluator for the dom walker used inside 263 // check(Start|End)OfBlock. 264 function getCheckStartEndBlockEvalFunction( isStart ) 264 265 { 265 return function( evt)266 return function( node ) 266 267 { 267 // Don't check the block boundary itself. 268 if ( this.stopped() || !evt.data.node ) 269 return; 268 var hadBr = false; 270 269 271 var node = evt.data.node, 272 hadBr = false; 273 if ( node.type == CKEDITOR.NODE_ELEMENT ) 270 if ( node.type == CKEDITOR.NODE_TEXT ) 274 271 { 272 // If there's any visible text, then we're not at the start. 273 if ( CKEDITOR.tools.trim( node.getText() ).length ) 274 return false; 275 } 276 else 277 { 275 278 // If there are non-empty inline elements (e.g. <img />), then we're not 276 279 // at the start. 277 280 if ( !inlineChildReqElements[ node.getName() ] ) … … 280 283 if ( !isStart && node.getName() == 'br' && !hadBr ) 281 284 hadBr = true; 282 285 else 283 { 284 this.checkFailed = true; 285 this.stop(); 286 } 286 return false; 287 287 } 288 288 } 289 else if ( node.type == CKEDITOR.NODE_TEXT )290 {291 // If there's any visible text, then we're not at the start.292 var visibleText = CKEDITOR.tools.trim( node.getText() );293 if ( visibleText.length > 0 )294 {295 this.checkFailed = true;296 this.stop();297 }298 }299 289 }; 300 } ;290 } 301 291 302 303 292 CKEDITOR.dom.range.prototype = 304 293 { 305 294 clone : function() … … 1415 1404 checkStartOfBlock : function() 1416 1405 { 1417 1406 var startContainer = this.startContainer, 1418 startOffset = this.startOffset; 1407 startOffset = this.startOffset, 1408 startNode, 1409 startInclusive; 1419 1410 1420 // If the starting node is a text node, and non-empty before the offset, 1421 // then we're surely not at the start of block. 1422 if ( startContainer.type == CKEDITOR.NODE_TEXT ) 1411 if ( startOffset ) 1423 1412 { 1424 var textBefore = CKEDITOR.tools.ltrim( startContainer.getText().substr( 0, startOffset ) ); 1425 if ( textBefore.length > 0 ) 1426 return false; 1413 // If the starting node is a text node, and non-empty before the offset, 1414 // then we're surely not at the start of block. 1415 if ( startContainer.type == CKEDITOR.NODE_TEXT ) 1416 { 1417 var textBefore = CKEDITOR.tools.ltrim( startContainer.substring( 0, startOffset ) ); 1418 if ( textBefore.length ) 1419 return false; 1420 } 1421 else 1422 { 1423 startNode = startContainer.getChild( startOffset - 1 ); 1424 startInclusive = true; 1425 } 1427 1426 } 1427 1428 if ( !startNode ) 1429 startNode = startContainer; 1428 1430 1429 var startNode = this.getBoundaryNodes().startNode,1430 walker = new CKEDITOR.dom.domWalker( startNode);1431 var path = new CKEDITOR.dom.elementPath( startNode ), 1432 walker = new CKEDITOR.dom.walker( startNode, ( path.block || path.blockLimit ) ); 1431 1433 1432 // DFS backwards until the block boundary, with the checker function. 1433 walker.on( 'step', getCheckStartEndBlockFunction( true ), null, null, 20 ); 1434 walker.reverse( CKEDITOR.dom.domWalker.blockBoundary() ); 1434 if ( ( path.block && startNode.equals( path.block ) ) 1435 || ( !path.block && startNode.equals( path.blockLimit ) ) ) 1436 { 1437 return true; 1438 } 1435 1439 1436 return !walker.checkFailed; 1440 walker.startInclusive = startInclusive; 1441 walker.evaluator = getCheckStartEndBlockEvalFunction( true ); 1442 1443 return walker.checkBackward(); 1437 1444 }, 1438 1445 1439 1446 checkEndOfBlock : function() 1440 1447 { 1441 1448 var endContainer = this.endContainer, 1442 endOffset = this.endOffset; 1449 endOffset = this.endOffset, 1450 startNode, 1451 startInclusive; 1443 1452 1444 1453 // If the ending node is a text node, and non-empty after the offset, 1445 1454 // then we're surely not at the end of block. 1446 1455 if ( endContainer.type == CKEDITOR.NODE_TEXT ) 1447 1456 { 1448 var textAfter = CKEDITOR.tools.rtrim( endContainer. getText().substr( endOffset ) );1449 if ( textAfter.length > 0)1457 var textAfter = CKEDITOR.tools.rtrim( endContainer.substring( endOffset ) ); 1458 if ( textAfter.length ) 1450 1459 return false; 1451 1460 } 1461 else 1462 { 1463 startNode = endContainer.getChild( endOffset ); 1464 startInclusive = !!startNode; 1465 } 1452 1466 1453 var endNode = this.getBoundaryNodes().endNode,1454 walker = new CKEDITOR.dom.domWalker( endNode );1467 if ( !startNode ) 1468 startNode = endContainer; 1455 1469 1456 // DFS forward until the block boundary, with the checker function. 1457 walker.on( 'step', getCheckStartEndBlockFunction( false ), null, null, 20 ); 1458 walker.forward( CKEDITOR.dom.domWalker.blockBoundary() ); 1470 var path = new CKEDITOR.dom.elementPath( startNode ), 1471 walker = new CKEDITOR.dom.walker( startNode, ( path.block || path.blockLimit ) ); 1459 1472 1460 return !walker.checkFailed; 1473 if ( ( path.block && startNode.equals( path.block ) ) 1474 || ( !path.block && startNode.equals( path.blockLimit ) ) ) 1475 { 1476 return true; 1477 } 1478 1479 walker.startInclusive = startInclusive; 1480 walker.evaluator = getCheckStartEndBlockEvalFunction( false ); 1481 1482 return walker.checkForward(); 1461 1483 }, 1462 1484 1463 1485 /** -
_source/tests/core/dom/range.html
1604 1604 assert.areSame( 5, range.endOffset, 'range.endOffset' ); 1605 1605 assert.isFalse( range.collapsed, 'range.collapsed' ); 1606 1606 }, 1607 1608 test_checkStartOfBlock1 : function() 1609 { 1610 var p = doc.getById( 'playground' ); 1611 p.setHtml( '<p>Test</p>' ); 1612 p = p.getFirst(); 1607 1613 1614 var range = new CKEDITOR.dom.range( doc ); 1615 1616 range.setStartAt( p, CKEDITOR.POSITION_AFTER_START ); 1617 range.collapse( true ); 1618 1619 assert.isTrue( range.checkStartOfBlock() ); 1620 }, 1621 1622 test_checkStartOfBlock2 : function() 1623 { 1624 var p = doc.getById( 'playground' ); 1625 p.setHtml( '<p>Test</p>' ); 1626 p = p.getFirst(); 1627 1628 var range = new CKEDITOR.dom.range( doc ); 1629 1630 range.setStartAt( p, CKEDITOR.POSITION_BEFORE_END ); 1631 range.collapse( true ); 1632 1633 assert.isFalse( range.checkStartOfBlock() ); 1634 }, 1635 1636 test_checkStartOfBlock3 : function() 1637 { 1638 var p = doc.getById( 'playground' ); 1639 p.setHtml( '<p>Test</p>' ); 1640 p = p.getFirst(); 1641 1642 var range = new CKEDITOR.dom.range( doc ); 1643 1644 range.setStartAt( p.getFirst(), CKEDITOR.POSITION_AFTER_START ); 1645 range.collapse( true ); 1646 1647 assert.isTrue( range.checkStartOfBlock() ); 1648 }, 1649 1650 test_checkStartOfBlock4 : function() 1651 { 1652 var p = doc.getById( 'playground' ); 1653 p.setHtml( '<p>Test</p>' ); 1654 p = p.getFirst(); 1655 1656 var range = new CKEDITOR.dom.range( doc ); 1657 1658 range.setStartAt( p.getFirst(), CKEDITOR.POSITION_BEFORE_END ); 1659 range.collapse( true ); 1660 1661 assert.isFalse( range.checkStartOfBlock() ); 1662 }, 1663 1664 test_checkStartOfBlock5 : function() 1665 { 1666 var el = doc.getById( 'playground' ); 1667 el.setHtml( '<p> Test </p>' ); 1668 el = el.getFirst().getFirst(); 1669 1670 var range = new CKEDITOR.dom.range( doc ); 1671 1672 // IE trims the space in the beginning of text nodes in our case. 1673 // So, let's just check it and make it pass. 1674 range.setStart( el, ( el.substring( 0, 1 ) == 'T' ) ? 0 : 1 ); 1675 range.collapse( true ); 1676 1677 assert.isTrue( range.checkStartOfBlock() ); 1678 }, 1679 1680 test_checkStartOfBlock6 : function() 1681 { 1682 var p = doc.getById( 'playground' ); 1683 p.setHtml( '<p> Test </p>' ); 1684 p = p.getFirst(); 1685 1686 var range = new CKEDITOR.dom.range( doc ); 1687 1688 range.setStart( p.getFirst(), 5 ); 1689 range.collapse( true ); 1690 1691 assert.isFalse( range.checkStartOfBlock() ); 1692 }, 1693 1694 test_checkStartOfBlock7 : function() 1695 { 1696 var el = doc.getById( 'playground' ); 1697 el.setHtml( '<p><b>Test</b></p>' ); 1698 el = el.getFirst().getFirst(); 1699 1700 var range = new CKEDITOR.dom.range( doc ); 1701 range.selectNodeContents( el ); 1702 1703 assert.isTrue( range.checkStartOfBlock() ); 1704 }, 1705 1706 test_checkStartOfBlock8 : function() 1707 { 1708 var el = doc.getById( 'playground' ); 1709 el.setHtml( '<p>A<b>Test</b>B</p>' ); 1710 el = el.getFirst().getFirst().getNext(); 1711 1712 var range = new CKEDITOR.dom.range( doc ); 1713 range.selectNodeContents( el ); 1714 1715 assert.isFalse( range.checkStartOfBlock() ); 1716 }, 1717 1718 test_checkEndOfBlock1 : function() 1719 { 1720 var p = doc.getById( 'playground' ); 1721 p.setHtml( '<p>Test</p>' ); 1722 p = p.getFirst(); 1723 1724 var range = new CKEDITOR.dom.range( doc ); 1725 1726 range.setStartAt( p, CKEDITOR.POSITION_AFTER_START ); 1727 range.collapse( true ); 1728 1729 assert.isFalse( range.checkEndOfBlock() ); 1730 }, 1731 1732 test_checkEndOfBlock2 : function() 1733 { 1734 var p = doc.getById( 'playground' ); 1735 p.setHtml( '<p>Test</p>' ); 1736 p = p.getFirst(); 1737 1738 var range = new CKEDITOR.dom.range( doc ); 1739 1740 range.setStartAt( p, CKEDITOR.POSITION_BEFORE_END ); 1741 range.collapse( true ); 1742 1743 assert.isTrue( range.checkEndOfBlock() ); 1744 }, 1745 1746 test_checkEndOfBlock3 : function() 1747 { 1748 var p = doc.getById( 'playground' ); 1749 p.setHtml( '<p>Test</p>' ); 1750 p = p.getFirst(); 1751 1752 var range = new CKEDITOR.dom.range( doc ); 1753 1754 range.setStartAt( p.getFirst(), CKEDITOR.POSITION_AFTER_START ); 1755 range.collapse( true ); 1756 1757 assert.isFalse( range.checkEndOfBlock() ); 1758 }, 1759 1760 test_checkEndOfBlock4 : function() 1761 { 1762 var p = doc.getById( 'playground' ); 1763 p.setHtml( '<p>Test</p>' ); 1764 p = p.getFirst(); 1765 1766 var range = new CKEDITOR.dom.range( doc ); 1767 1768 range.setStartAt( p.getFirst(), CKEDITOR.POSITION_BEFORE_END ); 1769 range.collapse( true ); 1770 1771 assert.isTrue( range.checkEndOfBlock() ); 1772 }, 1773 1774 test_checkEndOfBlock5 : function() 1775 { 1776 var p = doc.getById( 'playground' ); 1777 p.setHtml( '<p> Test </p>' ); 1778 p = p.getFirst(); 1779 1780 var range = new CKEDITOR.dom.range( doc ); 1781 1782 range.setStart( p.getFirst(), 1 ); 1783 range.collapse( true ); 1784 1785 assert.isFalse( range.checkEndOfBlock() ); 1786 }, 1787 1788 test_checkEndOfBlock6 : function() 1789 { 1790 var p = doc.getById( 'playground' ); 1791 p.setHtml( '<p> Test </p>' ); 1792 p = p.getFirst(); 1793 1794 var range = new CKEDITOR.dom.range( doc ); 1795 1796 range.setStart( p.getFirst(), 5 ); 1797 range.collapse( true ); 1798 1799 assert.isTrue( range.checkEndOfBlock() ); 1800 }, 1801 1802 test_checkEndOfBlock7 : function() 1803 { 1804 var el = doc.getById( 'playground' ); 1805 el.setHtml( '<p><b>Test</b></p>' ); 1806 el = el.getFirst().getFirst(); 1807 1808 var range = new CKEDITOR.dom.range( doc ); 1809 range.selectNodeContents( el ); 1810 1811 assert.isTrue( range.checkEndOfBlock() ); 1812 }, 1813 1814 test_checkEndOfBlock8 : function() 1815 { 1816 var el = doc.getById( 'playground' ); 1817 el.setHtml( '<p>A<b>Test</b>B</p>' ); 1818 el = el.getFirst().getFirst().getNext(); 1819 1820 var range = new CKEDITOR.dom.range( doc ); 1821 range.selectNodeContents( el ); 1822 1823 assert.isFalse( range.checkEndOfBlock() ); 1824 }, 1825 1608 1826 ///////////// 1609 1827 1610 1828 setUp : function()