/*
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
(function()
{
// Regex to scan for at the end of blocks, which are actually placeholders.
// Safari transforms the to \xa0. (#4172)
var tailNbspRegex = /^[\t\r\n ]*(?: |\xa0)$/;
var protectedSourceMarker = '{cke_protected}';
// Return the last non-space child node of the block (#4344).
function lastNoneSpaceChild( block )
{
var lastIndex = block.children.length,
last = block.children[ lastIndex - 1 ];
while ( last && last.type == CKEDITOR.NODE_TEXT && !CKEDITOR.tools.trim( last.value ) )
last = block.children[ --lastIndex ];
return last;
}
function trimFillers( block, fromSource )
{
// If the current node is a block, and if we're converting from source or
// we're not in IE then search for and remove any tailing BR node.
//
// Also, any at the end of blocks are fillers, remove them as well.
// (#2886)
var children = block.children, lastChild = lastNoneSpaceChild( block );
if ( lastChild )
{
if ( ( fromSource || !CKEDITOR.env.ie ) && lastChild.type == CKEDITOR.NODE_ELEMENT && lastChild.name == 'br' )
children.pop();
if ( lastChild.type == CKEDITOR.NODE_TEXT && tailNbspRegex.test( lastChild.value ) )
children.pop();
}
}
function blockNeedsExtension( block, fromSource, extendEmptyBlock )
{
if( !fromSource && ( !extendEmptyBlock ||
typeof extendEmptyBlock == 'function' && ( extendEmptyBlock( block ) === false ) ) )
return false;
// 1. For IE version >=8, empty blocks are displayed correctly themself in wysiwiyg;
// 2. For the rest, at least table cell and list item need no filler space.
// (#6248)
if ( fromSource && CKEDITOR.env.ie &&
( document.documentMode > 7
|| block.name in CKEDITOR.dtd.tr
|| block.name in CKEDITOR.dtd.$listItem ) )
return false;
var lastChild = lastNoneSpaceChild( block );
return !lastChild || lastChild &&
( lastChild.type == CKEDITOR.NODE_ELEMENT && lastChild.name == 'br'
// Some of the controls in form needs extension too,
// to move cursor at the end of the form. (#4791)
|| block.name == 'form' && lastChild.name == 'input' );
}
function getBlockExtension( isOutput, emptyBlockFiller )
{
return function( node )
{
trimFillers( node, !isOutput );
if ( blockNeedsExtension( node, !isOutput, emptyBlockFiller ) )
{
if ( isOutput || CKEDITOR.env.ie )
node.add( new CKEDITOR.htmlParser.text( '\xa0' ) );
else
node.add( new CKEDITOR.htmlParser.element( 'br', {} ) );
}
};
}
var dtd = CKEDITOR.dtd;
// Define orders of table elements.
var tableOrder = [ 'caption', 'colgroup', 'col', 'thead', 'tfoot', 'tbody' ];
// Find out the list of block-like tags that can contain
.
var blockLikeTags = CKEDITOR.tools.extend( {}, dtd.$block, dtd.$listItem, dtd.$tableContent );
for ( var i in blockLikeTags )
{
if ( ! ( 'br' in dtd[i] ) )
delete blockLikeTags[i];
}
// We just avoid filler in
right now. // TODO: Support filler for, line break is also occupy line height. delete blockLikeTags.pre; var defaultDataFilterRules = { elements : {}, attributeNames : [ // Event attributes (onXYZ) must not be directly set. They can become // active in the editing area (IE|WebKit). [ ( /^on/ ), 'data-cke-pa-on' ] ] }; var defaultDataBlockFilterRules = { elements : {} }; for ( i in blockLikeTags ) defaultDataBlockFilterRules.elements[ i ] = getBlockExtension(); var defaultHtmlFilterRules = { elementNames : [ // Remove the "cke:" namespace prefix. [ ( /^cke:/ ), '' ], // Ignore tags. [ ( /^\?xml:namespace$/ ), '' ] ], attributeNames : [ // Attributes saved for changes and protected attributes. [ ( /^data-cke-(saved|pa)-/ ), '' ], // All "data-cke-" attributes are to be ignored. [ ( /^data-cke-.*/ ), '' ], [ 'hidefocus', '' ] ], elements : { $ : function( element ) { var attribs = element.attributes; if ( attribs ) { // Elements marked as temporary are to be ignored. if ( attribs[ 'data-cke-temp' ] ) return false; // Remove duplicated attributes - #3789. var attributeNames = [ 'name', 'href', 'src' ], savedAttributeName; for ( var i = 0 ; i < attributeNames.length ; i++ ) { savedAttributeName = 'data-cke-saved-' + attributeNames[ i ]; savedAttributeName in attribs && ( delete attribs[ attributeNames[ i ] ] ); } } return element; }, // The contents of table should be in correct order (#4809). table : function( element ) { var children = element.children; children.sort( function ( node1, node2 ) { return node1.type == CKEDITOR.NODE_ELEMENT && node2.type == node1.type ? CKEDITOR.tools.indexOf( tableOrder, node1.name ) > CKEDITOR.tools.indexOf( tableOrder, node2.name ) ? 1 : -1 : 0; } ); }, embed : function( element ) { var parent = element.parent; // If the