2
* FCKeditor - The text editor for internet
3
* Copyright (C) 2003-2005 Frederico Caldeira Knabben
5
* Licensed under the terms of the GNU Lesser General Public License:
6
* http://www.opensource.org/licenses/lgpl-license.php
8
* For further information visit:
9
* http://www.fckeditor.net/
11
* "Support Open Source software. What about a donation today?"
13
* File Name: fckxhtml.js
14
* Defines the FCKXHtml object, responsible for the XHTML operations.
17
* Frederico Caldeira Knabben (fredck@fckeditor.net)
20
var FCKXHtml = new Object() ;
22
FCKXHtml.CurrentJobNum = 0 ;
24
FCKXHtml.GetXHTML = function( node, includeNode, format )
26
// Special blocks are blocks of content that remain untouched during the
27
// process. It is used for SCRIPTs and STYLEs.
28
FCKXHtml.SpecialBlocks = new Array() ;
30
// Create the XML DOMDocument object.
31
this.XML = FCKTools.CreateXmlObject( 'DOMDocument' ) ;
33
// Add a root element that holds all child nodes.
34
this.MainNode = this.XML.appendChild( this.XML.createElement( 'xhtml' ) ) ;
36
FCKXHtml.CurrentJobNum++ ;
39
this._AppendNode( this.MainNode, node ) ;
41
this._AppendChildNodes( this.MainNode, node, false ) ;
43
// Get the resulting XHTML as a string.
44
var sXHTML = this._GetMainXmlString() ;
46
// Strip the "XHTML" root node.
47
sXHTML = sXHTML.substr( 7, sXHTML.length - 15 ).trim() ;
49
// Remove the trailing <br> added by Gecko.
50
if ( FCKBrowserInfo.IsGecko )
51
sXHTML = sXHTML.replace( /<br\/>$/, '' ) ;
53
// Add a space in the tags with no closing tags, like <br/> -> <br />
54
sXHTML = sXHTML.replace( FCKRegexLib.SpaceNoClose, ' />');
56
if ( FCKConfig.ForceSimpleAmpersand )
57
sXHTML = sXHTML.replace( FCKRegexLib.ForceSimpleAmpersand, '&' ) ;
60
sXHTML = FCKCodeFormatter.Format( sXHTML ) ;
62
// Now we put back the SpecialBlocks contents.
63
for ( var i = 0 ; i < FCKXHtml.SpecialBlocks.length ; i++ )
65
var oRegex = new RegExp( '___FCKsi___' + i ) ;
66
sXHTML = sXHTML.replace( oRegex, FCKXHtml.SpecialBlocks[i] ) ;
74
FCKXHtml._AppendAttribute = function( xmlNode, attributeName, attributeValue )
78
// Create the attribute.
79
var oXmlAtt = this.XML.createAttribute( attributeName ) ;
81
oXmlAtt.value = attributeValue ? attributeValue : '' ;
83
// Set the attribute in the node.
84
xmlNode.attributes.setNamedItem( oXmlAtt ) ;
90
FCKXHtml._AppendChildNodes = function( xmlNode, htmlNode, isBlockElement )
94
var oNode = htmlNode.firstChild ;
98
if ( this._AppendNode( xmlNode, oNode ) )
101
oNode = oNode.nextSibling ;
106
if ( isBlockElement && FCKConfig.FillEmptyBlocks )
108
this._AppendEntity( xmlNode, 'nbsp' ) ;
112
// We can't use short representation of empty elements that are not marked
113
// as empty in th XHTML DTD.
114
if ( !FCKRegexLib.EmptyElements.test( htmlNode.nodeName ) )
115
xmlNode.appendChild( this.XML.createTextNode('') ) ;
119
FCKXHtml._AppendNode = function( xmlNode, htmlNode )
124
switch ( htmlNode.nodeType )
128
if ( htmlNode.getAttribute('_fckfakelement') )
129
return FCKXHtml._AppendNode( xmlNode, FCK.GetRealElement( htmlNode ) ) ;
131
// Mozilla insert custom nodes in the DOM.
132
if ( FCKBrowserInfo.IsGecko && htmlNode.hasAttribute('_moz_editor_bogus_node') )
135
if ( htmlNode.getAttribute('_fckdelete') )
138
// Get the element name.
139
var sNodeName = htmlNode.nodeName ;
142
if ( FCKBrowserInfo.IsIE && htmlNode.scopeName && htmlNode.scopeName != 'HTML' )
143
sNodeName = htmlNode.scopeName + ':' + sNodeName ;
145
// Check if the node name is valid, otherwise ignore this tag.
146
// If the nodeName starts with a slash, it is a orphan closing tag.
147
// On some strange cases, the nodeName is empty, even if the node exists.
148
if ( !FCKRegexLib.ElementName.test( sNodeName ) )
151
sNodeName = sNodeName.toLowerCase() ;
153
if ( FCKBrowserInfo.IsGecko && sNodeName == 'br' && htmlNode.hasAttribute('type') && htmlNode.getAttribute( 'type', 2 ) == '_moz' )
156
// The already processed nodes must be marked to avoid then to be duplicated (bad formatted HTML).
157
// So here, the "mark" is checked... if the element is Ok, then mark it.
158
if ( htmlNode._fckxhtmljob && htmlNode._fckxhtmljob == FCKXHtml.CurrentJobNum )
161
var oNode = this._CreateNode( sNodeName ) ;
163
// Add all attributes.
164
FCKXHtml._AppendAttributes( xmlNode, htmlNode, oNode, sNodeName ) ;
166
htmlNode._fckxhtmljob = FCKXHtml.CurrentJobNum ;
168
// Tag specific processing.
169
var oTagProcessor = FCKXHtml.TagProcessors[ sNodeName ] ;
173
oNode = oTagProcessor( oNode, htmlNode ) ;
174
if ( !oNode ) break ;
177
this._AppendChildNodes( oNode, htmlNode, FCKRegexLib.BlockElements.test( sNodeName ) ) ;
179
xmlNode.appendChild( oNode ) ;
185
this._AppendTextNode( xmlNode, htmlNode.nodeValue.replaceNewLineChars(' ') ) ;
190
try { xmlNode.appendChild( this.XML.createComment( htmlNode.nodeValue ) ) ; }
191
catch (e) { /* Do nothing... probably this is a wrong format comment. */ }
194
// Unknown Node type.
196
xmlNode.appendChild( this.XML.createComment( "Element not supported - Type: " + htmlNode.nodeType + " Name: " + htmlNode.nodeName ) ) ;
202
if ( FCKConfig.ForceStrongEm )
204
FCKXHtml._CreateNode = function( nodeName )
209
nodeName = 'strong' ;
215
return this.XML.createElement( nodeName ) ;
220
FCKXHtml._CreateNode = function( nodeName )
222
return this.XML.createElement( nodeName ) ;
226
// Append an item to the SpecialBlocks array and returns the tag to be used.
227
FCKXHtml._AppendSpecialItem = function( item )
229
return '___FCKsi___' + FCKXHtml.SpecialBlocks.addItem( item ) ;
232
//if ( FCKConfig.ProcessHTMLEntities )
234
FCKXHtml._AppendTextNode = function( targetNode, textValue )
236
// We can't just replace the special chars with entities and create a
237
// text node with it. We must split the text isolating the special chars
238
// and add each piece a time.
239
var asPieces = textValue.match( FCKXHtmlEntities.EntitiesRegex ) ;
243
for ( var i = 0 ; i < asPieces.length ; i++ )
245
if ( asPieces[i].length == 1 )
247
var sEntity = FCKXHtmlEntities.Entities[ asPieces[i] ] ;
248
if ( sEntity != null )
250
this._AppendEntity( targetNode, sEntity ) ;
254
targetNode.appendChild( this.XML.createTextNode( asPieces[i] ) ) ;
261
// FCKXHtml._AppendTextNode = function( targetNode, textValue )
263
// targetNode.appendChild( this.XML.createTextNode( textValue ) ) ;
267
// An object that hold tag specific operations.
268
FCKXHtml.TagProcessors = new Object() ;
270
FCKXHtml.TagProcessors['img'] = function( node, htmlNode )
272
// The "ALT" attribute is required in XHTML.
273
if ( ! node.attributes.getNamedItem( 'alt' ) )
274
FCKXHtml._AppendAttribute( node, 'alt', '' ) ;
276
var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ;
277
if ( sSavedUrl && sSavedUrl.length > 0 )
278
FCKXHtml._AppendAttribute( node, 'src', sSavedUrl ) ;
283
FCKXHtml.TagProcessors['a'] = function( node, htmlNode )
285
var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ;
286
if ( sSavedUrl && sSavedUrl.length > 0 )
287
FCKXHtml._AppendAttribute( node, 'href', sSavedUrl ) ;
289
FCKXHtml._AppendChildNodes( node, htmlNode, false ) ;
294
FCKXHtml.TagProcessors['script'] = function( node, htmlNode )
296
// The "TYPE" attribute is required in XHTML.
297
if ( ! node.attributes.getNamedItem( 'type' ) )
298
FCKXHtml._AppendAttribute( node, 'type', 'text/javascript' ) ;
300
node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( htmlNode.text ) ) ) ;
305
FCKXHtml.TagProcessors['style'] = function( node, htmlNode )
307
// The "_fcktemp" attribute is used to mark the <STYLE> used by the editor
308
// to set some behaviors.
309
if ( htmlNode.getAttribute( '_fcktemp' ) )
312
// The "TYPE" attribute is required in XHTML.
313
if ( ! node.attributes.getNamedItem( 'type' ) )
314
FCKXHtml._AppendAttribute( node, 'type', 'text/css' ) ;
316
node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( htmlNode.innerHTML ) ) ) ;
321
FCKXHtml.TagProcessors['title'] = function( node, htmlNode )
323
node.appendChild( FCKXHtml.XML.createTextNode( FCK.EditorDocument.title ) ) ;
328
FCKXHtml.TagProcessors['base'] = function( node, htmlNode )
330
// The "_fcktemp" attribute is used to mark the <BASE> tag when the editor
331
// automatically sets it using the FCKConfig.BaseHref configuration.
332
if ( htmlNode.getAttribute( '_fcktemp' ) )
335
// IE duplicates the BODY inside the <BASE /> tag (don't ask me why!).
336
// This tag processor does nothing... in this way, no child nodes are added
337
// (also because the BASE tag must be empty).
341
FCKXHtml.TagProcessors['link'] = function( node, htmlNode )
343
// The "_fcktemp" attribute is used to mark the fck_internal.css <LINK>
345
if ( htmlNode.getAttribute( '_fcktemp' ) )
351
FCKXHtml.TagProcessors['table'] = function( node, htmlNode )
353
// There is a trick to show table borders when border=0. We add to the
354
// table class the FCK__ShowTableBorders rule. So now we must remove it.
356
var oClassAtt = node.attributes.getNamedItem( 'class' ) ;
358
if ( oClassAtt && FCKRegexLib.TableBorderClass.test( oClassAtt.nodeValue ) )
360
var sClass = oClassAtt.nodeValue.replace( FCKRegexLib.TableBorderClass, '' ) ;
362
if ( sClass.length == 0 )
363
node.attributes.removeNamedItem( 'class' ) ;
365
FCKXHtml._AppendAttribute( node, 'class', sClass ) ;
368
FCKXHtml._AppendChildNodes( node, htmlNode, false ) ;
b'\\ No newline at end of file'