mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 07:13:08 -05:00
Better fix up of mixed inline/block content.
This commit is contained in:
parent
46706db889
commit
aca8fd4fab
4 changed files with 96 additions and 78 deletions
|
@ -508,7 +508,7 @@ function mergeContainers ( node ) {
|
|||
var prev = node.previousSibling,
|
||||
first = node.firstChild,
|
||||
isListItem = ( node.nodeName === 'LI' ),
|
||||
block;
|
||||
needsFix, block;
|
||||
|
||||
// Do not merge LIs, unless it only contains a UL
|
||||
if ( isListItem && ( !first || !/^[OU]L$/.test( first.nodeName ) ) ) {
|
||||
|
@ -526,7 +526,11 @@ function mergeContainers ( node ) {
|
|||
}
|
||||
}
|
||||
detach( node );
|
||||
needsFix = !isContainer( node );
|
||||
prev.appendChild( empty( node ) );
|
||||
if ( needsFix ) {
|
||||
fixContainer( prev );
|
||||
}
|
||||
if ( first ) {
|
||||
mergeContainers( first );
|
||||
}
|
||||
|
@ -537,6 +541,42 @@ function mergeContainers ( node ) {
|
|||
}
|
||||
}
|
||||
|
||||
// Recursively examine container nodes and wrap any inline children.
|
||||
function fixContainer ( container ) {
|
||||
var children = container.childNodes,
|
||||
doc = container.ownerDocument,
|
||||
wrapper = null,
|
||||
i, l, child, isBR;
|
||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||
child = children[i];
|
||||
isBR = child.nodeName === 'BR';
|
||||
if ( !isBR && isInline( child ) ) {
|
||||
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||
wrapper.appendChild( child );
|
||||
i -= 1;
|
||||
l -= 1;
|
||||
} else if ( isBR || wrapper ) {
|
||||
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||
fixCursor( wrapper );
|
||||
if ( isBR ) {
|
||||
container.replaceChild( wrapper, child );
|
||||
} else {
|
||||
container.insertBefore( wrapper, child );
|
||||
i += 1;
|
||||
l += 1;
|
||||
}
|
||||
wrapper = null;
|
||||
}
|
||||
if ( isContainer( child ) ) {
|
||||
fixContainer( child );
|
||||
}
|
||||
}
|
||||
if ( wrapper ) {
|
||||
container.appendChild( fixCursor( wrapper ) );
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
function createElement ( doc, tag, props, children ) {
|
||||
var el = doc.createElement( tag ),
|
||||
attr, value, i, l;
|
||||
|
@ -1114,6 +1154,7 @@ var expandRangeToBlockBoundaries = function ( range ) {
|
|||
mergeInlines,
|
||||
mergeWithBlock,
|
||||
mergeContainers,
|
||||
fixContainer,
|
||||
createElement,
|
||||
|
||||
forEachTextNodeInRange,
|
||||
|
@ -2092,7 +2133,7 @@ var removeList = function ( frag ) {
|
|||
child = children[ll];
|
||||
replaceWith( child, empty( child ) );
|
||||
}
|
||||
wrapTopLevelInline( listFrag, 'DIV' );
|
||||
fixContainer( listFrag );
|
||||
replaceWith( list, listFrag );
|
||||
}
|
||||
return frag;
|
||||
|
@ -2153,7 +2194,7 @@ var decreaseListLevel = function ( frag ) {
|
|||
item = parent;
|
||||
}
|
||||
}, this );
|
||||
wrapTopLevelInline( frag, 'DIV' );
|
||||
fixContainer( frag );
|
||||
return frag;
|
||||
};
|
||||
|
||||
|
@ -2450,38 +2491,6 @@ var cleanTree = function ( node, allowStyles ) {
|
|||
return node;
|
||||
};
|
||||
|
||||
var wrapTopLevelInline = function ( root, tag ) {
|
||||
var children = root.childNodes,
|
||||
doc = root.ownerDocument,
|
||||
wrapper = null,
|
||||
i, l, child, isBR;
|
||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||
child = children[i];
|
||||
isBR = child.nodeName === 'BR';
|
||||
if ( !isBR && isInline( child ) ) {
|
||||
if ( !wrapper ) { wrapper = createElement( doc, tag ); }
|
||||
wrapper.appendChild( child );
|
||||
i -= 1;
|
||||
l -= 1;
|
||||
} else if ( isBR || wrapper ) {
|
||||
if ( !wrapper ) { wrapper = createElement( doc, tag ); }
|
||||
fixCursor( wrapper );
|
||||
if ( isBR ) {
|
||||
root.replaceChild( wrapper, child );
|
||||
} else {
|
||||
root.insertBefore( wrapper, child );
|
||||
i += 1;
|
||||
l += 1;
|
||||
}
|
||||
wrapper = null;
|
||||
}
|
||||
}
|
||||
if ( wrapper ) {
|
||||
root.appendChild( fixCursor( wrapper ) );
|
||||
}
|
||||
return root;
|
||||
};
|
||||
|
||||
var notWSTextNode = function ( node ) {
|
||||
return ( node.nodeType === ELEMENT_NODE ?
|
||||
node.nodeName === 'BR' :
|
||||
|
@ -2532,7 +2541,7 @@ var cleanupBRs = function ( root ) {
|
|||
// If this is not inside a block, replace it by wrapping
|
||||
// inlines in DIV.
|
||||
if ( !isBlock( block ) || !tagAfterSplit[ block.nodeName ] ) {
|
||||
wrapTopLevelInline( block, 'DIV' );
|
||||
fixContainer( block );
|
||||
}
|
||||
// If in a block we can split, split it instead, but only if there
|
||||
// is actual text content in the block. Otherwise, the <br> is a
|
||||
|
@ -2833,7 +2842,7 @@ var keyHandlers = {
|
|||
}
|
||||
}
|
||||
}
|
||||
wrapTopLevelInline( block, 'DIV' );
|
||||
fixContainer( block );
|
||||
splitTag = 'DIV';
|
||||
if ( !splitNode ) {
|
||||
splitNode = block.firstChild;
|
||||
|
@ -3188,7 +3197,7 @@ proto.setHTML = function ( html ) {
|
|||
cleanTree( frag, true );
|
||||
cleanupBRs( frag );
|
||||
|
||||
wrapTopLevelInline( frag, 'DIV' );
|
||||
fixContainer( frag );
|
||||
|
||||
// Fix cursor
|
||||
var node = frag;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -42,6 +42,7 @@
|
|||
mergeInlines,
|
||||
mergeWithBlock,
|
||||
mergeContainers,
|
||||
fixContainer,
|
||||
createElement,
|
||||
|
||||
forEachTextNodeInRange,
|
||||
|
@ -1020,7 +1021,7 @@ var removeList = function ( frag ) {
|
|||
child = children[ll];
|
||||
replaceWith( child, empty( child ) );
|
||||
}
|
||||
wrapTopLevelInline( listFrag, 'DIV' );
|
||||
fixContainer( listFrag );
|
||||
replaceWith( list, listFrag );
|
||||
}
|
||||
return frag;
|
||||
|
@ -1081,7 +1082,7 @@ var decreaseListLevel = function ( frag ) {
|
|||
item = parent;
|
||||
}
|
||||
}, this );
|
||||
wrapTopLevelInline( frag, 'DIV' );
|
||||
fixContainer( frag );
|
||||
return frag;
|
||||
};
|
||||
|
||||
|
@ -1378,38 +1379,6 @@ var cleanTree = function ( node, allowStyles ) {
|
|||
return node;
|
||||
};
|
||||
|
||||
var wrapTopLevelInline = function ( root, tag ) {
|
||||
var children = root.childNodes,
|
||||
doc = root.ownerDocument,
|
||||
wrapper = null,
|
||||
i, l, child, isBR;
|
||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||
child = children[i];
|
||||
isBR = child.nodeName === 'BR';
|
||||
if ( !isBR && isInline( child ) ) {
|
||||
if ( !wrapper ) { wrapper = createElement( doc, tag ); }
|
||||
wrapper.appendChild( child );
|
||||
i -= 1;
|
||||
l -= 1;
|
||||
} else if ( isBR || wrapper ) {
|
||||
if ( !wrapper ) { wrapper = createElement( doc, tag ); }
|
||||
fixCursor( wrapper );
|
||||
if ( isBR ) {
|
||||
root.replaceChild( wrapper, child );
|
||||
} else {
|
||||
root.insertBefore( wrapper, child );
|
||||
i += 1;
|
||||
l += 1;
|
||||
}
|
||||
wrapper = null;
|
||||
}
|
||||
}
|
||||
if ( wrapper ) {
|
||||
root.appendChild( fixCursor( wrapper ) );
|
||||
}
|
||||
return root;
|
||||
};
|
||||
|
||||
var notWSTextNode = function ( node ) {
|
||||
return ( node.nodeType === ELEMENT_NODE ?
|
||||
node.nodeName === 'BR' :
|
||||
|
@ -1460,7 +1429,7 @@ var cleanupBRs = function ( root ) {
|
|||
// If this is not inside a block, replace it by wrapping
|
||||
// inlines in DIV.
|
||||
if ( !isBlock( block ) || !tagAfterSplit[ block.nodeName ] ) {
|
||||
wrapTopLevelInline( block, 'DIV' );
|
||||
fixContainer( block );
|
||||
}
|
||||
// If in a block we can split, split it instead, but only if there
|
||||
// is actual text content in the block. Otherwise, the <br> is a
|
||||
|
@ -1761,7 +1730,7 @@ var keyHandlers = {
|
|||
}
|
||||
}
|
||||
}
|
||||
wrapTopLevelInline( block, 'DIV' );
|
||||
fixContainer( block );
|
||||
splitTag = 'DIV';
|
||||
if ( !splitNode ) {
|
||||
splitNode = block.firstChild;
|
||||
|
@ -2116,7 +2085,7 @@ proto.setHTML = function ( html ) {
|
|||
cleanTree( frag, true );
|
||||
cleanupBRs( frag );
|
||||
|
||||
wrapTopLevelInline( frag, 'DIV' );
|
||||
fixContainer( frag );
|
||||
|
||||
// Fix cursor
|
||||
var node = frag;
|
||||
|
|
|
@ -366,7 +366,7 @@ function mergeContainers ( node ) {
|
|||
var prev = node.previousSibling,
|
||||
first = node.firstChild,
|
||||
isListItem = ( node.nodeName === 'LI' ),
|
||||
block;
|
||||
needsFix, block;
|
||||
|
||||
// Do not merge LIs, unless it only contains a UL
|
||||
if ( isListItem && ( !first || !/^[OU]L$/.test( first.nodeName ) ) ) {
|
||||
|
@ -384,7 +384,11 @@ function mergeContainers ( node ) {
|
|||
}
|
||||
}
|
||||
detach( node );
|
||||
needsFix = !isContainer( node );
|
||||
prev.appendChild( empty( node ) );
|
||||
if ( needsFix ) {
|
||||
fixContainer( prev );
|
||||
}
|
||||
if ( first ) {
|
||||
mergeContainers( first );
|
||||
}
|
||||
|
@ -395,6 +399,42 @@ function mergeContainers ( node ) {
|
|||
}
|
||||
}
|
||||
|
||||
// Recursively examine container nodes and wrap any inline children.
|
||||
function fixContainer ( container ) {
|
||||
var children = container.childNodes,
|
||||
doc = container.ownerDocument,
|
||||
wrapper = null,
|
||||
i, l, child, isBR;
|
||||
for ( i = 0, l = children.length; i < l; i += 1 ) {
|
||||
child = children[i];
|
||||
isBR = child.nodeName === 'BR';
|
||||
if ( !isBR && isInline( child ) ) {
|
||||
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||
wrapper.appendChild( child );
|
||||
i -= 1;
|
||||
l -= 1;
|
||||
} else if ( isBR || wrapper ) {
|
||||
if ( !wrapper ) { wrapper = createElement( doc, 'DIV' ); }
|
||||
fixCursor( wrapper );
|
||||
if ( isBR ) {
|
||||
container.replaceChild( wrapper, child );
|
||||
} else {
|
||||
container.insertBefore( wrapper, child );
|
||||
i += 1;
|
||||
l += 1;
|
||||
}
|
||||
wrapper = null;
|
||||
}
|
||||
if ( isContainer( child ) ) {
|
||||
fixContainer( child );
|
||||
}
|
||||
}
|
||||
if ( wrapper ) {
|
||||
container.appendChild( fixCursor( wrapper ) );
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
function createElement ( doc, tag, props, children ) {
|
||||
var el = doc.createElement( tag ),
|
||||
attr, value, i, l;
|
||||
|
|
Loading…
Reference in a new issue