/*
Copyright (c) 2003-2010, 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 )
{
var lastChild = lastNoneSpaceChild( block );
return !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 extendBlockForDisplay( block )
{
trimFillers( block, true );
if ( blockNeedsExtension( block ) )
{
if ( CKEDITOR.env.ie )
block.add( new CKEDITOR.htmlParser.text( '\xa0' ) );
else
block.add( new CKEDITOR.htmlParser.element( 'br', {} ) );
}
}
function extendBlockForOutput( block )
{
trimFillers( block );
if ( blockNeedsExtension( block ) )
block.add( new CKEDITOR.htmlParser.text( '\xa0' ) );
}
var dtd = CKEDITOR.dtd;
// 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 ( ! ( i in Object.prototype ) )
{
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 = { attributeNames : [ // Event attributes (onXYZ) must not be directly set. They can become // active in the editing area (IE|WebKit). [ ( /^on/ ), '_cke_pa_on' ] ] }; var defaultDataBlockFilterRules = { elements : {} }; for ( i in blockLikeTags ) defaultDataBlockFilterRules.elements[ i ] = extendBlockForDisplay; var defaultHtmlFilterRules = { elementNames : [ // Remove the "cke:" namespace prefix. [ ( /^cke:/ ), '' ], // Ignore tags. [ ( /^\?xml:namespace$/ ), '' ] ], attributeNames : [ // Attributes saved for changes and protected attributes. [ ( /^_cke_(saved|pa)_/ ), '' ], // All "_cke" attributes are to be ignored. [ ( /^_cke.*/ ), '' ], [ 'hidefocus', '' ] ], elements : { $ : function( element ) { var attribs = element.attributes; if ( attribs ) { // Elements marked as temporary are to be ignored. if ( attribs.cke_temp ) return false; // Remove duplicated attributes - #3789. var attributeNames = [ 'name', 'href', 'src' ], savedAttributeName; for ( var i = 0 ; i < attributeNames.length ; i++ ) { savedAttributeName = '_cke_saved_' + attributeNames[ i ]; savedAttributeName in attribs && ( delete attribs[ attributeNames[ i ] ] ); } } return element; }, embed : function( element ) { var parent = element.parent; // If the