| 1 |
/* |
| 2 |
* FCKeditor - The text editor for Internet - http://www.fckeditor.net |
| 3 |
* Copyright (C) 2003-2009 Frederico Caldeira Knabben |
| 4 |
* |
| 5 |
* == BEGIN LICENSE == |
| 6 |
* |
| 7 |
* Licensed under the terms of any of the following licenses at your |
| 8 |
* choice: |
| 9 |
* |
| 10 |
* - GNU General Public License Version 2 or later (the "GPL") |
| 11 |
* http://www.gnu.org/licenses/gpl.html |
| 12 |
* |
| 13 |
* - GNU Lesser General Public License Version 2.1 or later (the "LGPL") |
| 14 |
* http://www.gnu.org/licenses/lgpl.html |
| 15 |
* |
| 16 |
* - Mozilla Public License Version 1.1 or later (the "MPL") |
| 17 |
* http://www.mozilla.org/MPL/MPL-1.1.html |
| 18 |
* |
| 19 |
* == END LICENSE == |
| 20 |
* |
| 21 |
* Defines the FCKXHtml object, responsible for the XHTML operations. |
| 22 |
*/ |
| 23 |
|
| 24 |
var FCKXHtml = new Object() ; |
| 25 |
|
| 26 |
FCKXHtml.CurrentJobNum = 0 ; |
| 27 |
|
| 28 |
FCKXHtml.GetXHTML = function( node, includeNode, format ) |
| 29 |
{ |
| 30 |
FCKDomTools.CheckAndRemovePaddingNode( FCKTools.GetElementDocument( node ), FCKConfig.EnterMode ) ; |
| 31 |
FCKXHtmlEntities.Initialize() ; |
| 32 |
|
| 33 |
// Set the correct entity to use for empty blocks. |
| 34 |
this._NbspEntity = ( FCKConfig.ProcessHTMLEntities? 'nbsp' : '#160' ) ; |
| 35 |
|
| 36 |
// Save the current IsDirty state. The XHTML processor may change the |
| 37 |
// original HTML, dirtying it. |
| 38 |
var bIsDirty = FCK.IsDirty() ; |
| 39 |
|
| 40 |
// Special blocks are blocks of content that remain untouched during the |
| 41 |
// process. It is used for SCRIPTs and STYLEs. |
| 42 |
FCKXHtml.SpecialBlocks = new Array() ; |
| 43 |
|
| 44 |
// Create the XML DOMDocument object. |
| 45 |
this.XML = FCKTools.CreateXmlObject( 'DOMDocument' ) ; |
| 46 |
|
| 47 |
// Add a root element that holds all child nodes. |
| 48 |
this.MainNode = this.XML.appendChild( this.XML.createElement( 'xhtml' ) ) ; |
| 49 |
|
| 50 |
FCKXHtml.CurrentJobNum++ ; |
| 51 |
|
| 52 |
// var dTimer = new Date() ; |
| 53 |
|
| 54 |
if ( includeNode ) |
| 55 |
this._AppendNode( this.MainNode, node ) ; |
| 56 |
else |
| 57 |
this._AppendChildNodes( this.MainNode, node, false ) ; |
| 58 |
|
| 59 |
// Get the resulting XHTML as a string. |
| 60 |
var sXHTML = this._GetMainXmlString() ; |
| 61 |
|
| 62 |
// alert( 'Time: ' + ( ( ( new Date() ) - dTimer ) ) + ' ms' ) ; |
| 63 |
|
| 64 |
this.XML = null ; |
| 65 |
|
| 66 |
// Safari adds xmlns="http://www.w3.org/1999/xhtml" to the root node (#963) |
| 67 |
if ( FCKBrowserInfo.IsSafari ) |
| 68 |
sXHTML = sXHTML.replace( /^<xhtml.*?>/, '<xhtml>' ) ; |
| 69 |
|
| 70 |
// Strip the "XHTML" root node. |
| 71 |
sXHTML = sXHTML.substr( 7, sXHTML.length - 15 ).Trim() ; |
| 72 |
|
| 73 |
// According to the doctype set the proper end for self-closing tags |
| 74 |
// HTML: <br> |
| 75 |
// XHTML: Add a space, like <br/> -> <br /> |
| 76 |
if (FCKConfig.DocType.length > 0 && FCKRegexLib.HtmlDocType.test( FCKConfig.DocType ) ) |
| 77 |
sXHTML = sXHTML.replace( FCKRegexLib.SpaceNoClose, '>'); |
| 78 |
else |
| 79 |
sXHTML = sXHTML.replace( FCKRegexLib.SpaceNoClose, ' />'); |
| 80 |
|
| 81 |
if ( FCKConfig.ForceSimpleAmpersand ) |
| 82 |
sXHTML = sXHTML.replace( FCKRegexLib.ForceSimpleAmpersand, '&' ) ; |
| 83 |
|
| 84 |
if ( format ) |
| 85 |
sXHTML = FCKCodeFormatter.Format( sXHTML ) ; |
| 86 |
|
| 87 |
// Now we put back the SpecialBlocks contents. |
| 88 |
for ( var i = 0 ; i < FCKXHtml.SpecialBlocks.length ; i++ ) |
| 89 |
{ |
| 90 |
var oRegex = new RegExp( '___FCKsi___' + i ) ; |
| 91 |
sXHTML = sXHTML.replace( oRegex, FCKXHtml.SpecialBlocks[i] ) ; |
| 92 |
} |
| 93 |
|
| 94 |
// Replace entities marker with the ampersand. |
| 95 |
sXHTML = sXHTML.replace( FCKRegexLib.GeckoEntitiesMarker, '&' ) ; |
| 96 |
|
| 97 |
// Restore the IsDirty state if it was not dirty. |
| 98 |
if ( !bIsDirty ) |
| 99 |
FCK.ResetIsDirty() ; |
| 100 |
|
| 101 |
FCKDomTools.EnforcePaddingNode( FCKTools.GetElementDocument( node ), FCKConfig.EnterMode ) ; |
| 102 |
return sXHTML ; |
| 103 |
} |
| 104 |
|
| 105 |
FCKXHtml._AppendAttribute = function( xmlNode, attributeName, attributeValue ) |
| 106 |
{ |
| 107 |
try |
| 108 |
{ |
| 109 |
if ( attributeValue == undefined || attributeValue == null ) |
| 110 |
attributeValue = '' ; |
| 111 |
else if ( attributeValue.replace ) |
| 112 |
{ |
| 113 |
if ( FCKConfig.ForceSimpleAmpersand ) |
| 114 |
attributeValue = attributeValue.replace( /&/g, '___FCKAmp___' ) ; |
| 115 |
|
| 116 |
// Entities must be replaced in the attribute values. |
| 117 |
attributeValue = attributeValue.replace( FCKXHtmlEntities.EntitiesRegex, FCKXHtml_GetEntity ) ; |
| 118 |
} |
| 119 |
|
| 120 |
// Create the attribute. |
| 121 |
var oXmlAtt = this.XML.createAttribute( attributeName ) ; |
| 122 |
oXmlAtt.value = attributeValue ; |
| 123 |
|
| 124 |
// Set the attribute in the node. |
| 125 |
xmlNode.attributes.setNamedItem( oXmlAtt ) ; |
| 126 |
} |
| 127 |
catch (e) |
| 128 |
{} |
| 129 |
} |
| 130 |
|
| 131 |
FCKXHtml._AppendChildNodes = function( xmlNode, htmlNode, isBlockElement ) |
| 132 |
{ |
| 133 |
var oNode = htmlNode.firstChild ; |
| 134 |
|
| 135 |
while ( oNode ) |
| 136 |
{ |
| 137 |
this._AppendNode( xmlNode, oNode ) ; |
| 138 |
oNode = oNode.nextSibling ; |
| 139 |
} |
| 140 |
|
| 141 |
// Trim block elements. This is also needed to avoid Firefox leaving extra |
| 142 |
// BRs at the end of them. |
| 143 |
if ( isBlockElement && htmlNode.tagName && htmlNode.tagName.toLowerCase() != 'pre' ) |
| 144 |
{ |
| 145 |
FCKDomTools.TrimNode( xmlNode ) ; |
| 146 |
|
| 147 |
if ( FCKConfig.FillEmptyBlocks ) |
| 148 |
{ |
| 149 |
var lastChild = xmlNode.lastChild ; |
| 150 |
if ( lastChild && lastChild.nodeType == 1 && lastChild.nodeName == 'br' ) |
| 151 |
this._AppendEntity( xmlNode, this._NbspEntity ) ; |
| 152 |
} |
| 153 |
} |
| 154 |
|
| 155 |
// If the resulting node is empty. |
| 156 |
if ( xmlNode.childNodes.length == 0 ) |
| 157 |
{ |
| 158 |
if ( isBlockElement && FCKConfig.FillEmptyBlocks ) |
| 159 |
{ |
| 160 |
this._AppendEntity( xmlNode, this._NbspEntity ) ; |
| 161 |
return xmlNode ; |
| 162 |
} |
| 163 |
|
| 164 |
var sNodeName = xmlNode.nodeName ; |
| 165 |
|
| 166 |
// Some inline elements are required to have something inside (span, strong, etc...). |
| 167 |
if ( FCKListsLib.InlineChildReqElements[ sNodeName ] ) |
| 168 |
return null ; |
| 169 |
|
| 170 |
// We can't use short representation of empty elements that are not marked |
| 171 |
// as empty in th XHTML DTD. |
| 172 |
if ( !FCKListsLib.EmptyElements[ sNodeName ] ) |
| 173 |
xmlNode.appendChild( this.XML.createTextNode('') ) ; |
| 174 |
} |
| 175 |
|
| 176 |
return xmlNode ; |
| 177 |
} |
| 178 |
|
| 179 |
FCKXHtml._AppendNode = function( xmlNode, htmlNode ) |
| 180 |
{ |
| 181 |
if ( !htmlNode ) |
| 182 |
return false ; |
| 183 |
|
| 184 |
switch ( htmlNode.nodeType ) |
| 185 |
{ |
| 186 |
// Element Node. |
| 187 |
case 1 : |
| 188 |
// If we detect a <br> inside a <pre> in Gecko, turn it into a line break instead. |
| 189 |
// This is a workaround for the Gecko bug here: https://bugzilla.mozilla.org/show_bug.cgi?id=92921 |
| 190 |
if ( FCKBrowserInfo.IsGecko |
| 191 |
&& htmlNode.tagName.toLowerCase() == 'br' |
| 192 |
&& htmlNode.parentNode.tagName.toLowerCase() == 'pre' ) |
| 193 |
{ |
| 194 |
var val = '\r' ; |
| 195 |
if ( htmlNode == htmlNode.parentNode.firstChild ) |
| 196 |
val += '\r' ; |
| 197 |
return FCKXHtml._AppendNode( xmlNode, this.XML.createTextNode( val ) ) ; |
| 198 |
} |
| 199 |
|
| 200 |
// Here we found an element that is not the real element, but a |
| 201 |
// fake one (like the Flash placeholder image), so we must get the real one. |
| 202 |
if ( htmlNode.getAttribute('_fckfakelement') ) |
| 203 |
return FCKXHtml._AppendNode( xmlNode, FCK.GetRealElement( htmlNode ) ) ; |
| 204 |
|
| 205 |
// Ignore bogus BR nodes in the DOM. |
| 206 |
if ( FCKBrowserInfo.IsGecko && |
| 207 |
( htmlNode.hasAttribute('_moz_editor_bogus_node') || htmlNode.getAttribute( 'type' ) == '_moz' ) ) |
| 208 |
{ |
| 209 |
if ( htmlNode.nextSibling ) |
| 210 |
return false ; |
| 211 |
else |
| 212 |
{ |
| 213 |
htmlNode.removeAttribute( '_moz_editor_bogus_node' ) ; |
| 214 |
htmlNode.removeAttribute( 'type' ) ; |
| 215 |
} |
| 216 |
} |
| 217 |
|
| 218 |
// This is for elements that are instrumental to FCKeditor and |
| 219 |
// must be removed from the final HTML. |
| 220 |
if ( htmlNode.getAttribute('_fcktemp') ) |
| 221 |
return false ; |
| 222 |
|
| 223 |
// Get the element name. |
| 224 |
var sNodeName = htmlNode.tagName.toLowerCase() ; |
| 225 |
|
| 226 |
if ( FCKBrowserInfo.IsIE ) |
| 227 |
{ |
| 228 |
// IE doens't include the scope name in the nodeName. So, add the namespace. |
| 229 |
if ( htmlNode.scopeName && htmlNode.scopeName != 'HTML' && htmlNode.scopeName != 'FCK' ) |
| 230 |
sNodeName = htmlNode.scopeName.toLowerCase() + ':' + sNodeName ; |
| 231 |
} |
| 232 |
else |
| 233 |
{ |
| 234 |
if ( sNodeName.StartsWith( 'fck:' ) ) |
| 235 |
sNodeName = sNodeName.Remove( 0,4 ) ; |
| 236 |
} |
| 237 |
|
| 238 |
// Check if the node name is valid, otherwise ignore this tag. |
| 239 |
// If the nodeName starts with a slash, it is a orphan closing tag. |
| 240 |
// On some strange cases, the nodeName is empty, even if the node exists. |
| 241 |
if ( !FCKRegexLib.ElementName.test( sNodeName ) ) |
| 242 |
return false ; |
| 243 |
|
| 244 |
// The already processed nodes must be marked to avoid then to be duplicated (bad formatted HTML). |
| 245 |
// So here, the "mark" is checked... if the element is Ok, then mark it. |
| 246 |
if ( htmlNode._fckxhtmljob && htmlNode._fckxhtmljob == FCKXHtml.CurrentJobNum ) |
| 247 |
return false ; |
| 248 |
|
| 249 |
var oNode = this.XML.createElement( sNodeName ) ; |
| 250 |
|
| 251 |
// Add all attributes. |
| 252 |
FCKXHtml._AppendAttributes( xmlNode, htmlNode, oNode, sNodeName ) ; |
| 253 |
|
| 254 |
htmlNode._fckxhtmljob = FCKXHtml.CurrentJobNum ; |
| 255 |
|
| 256 |
// Tag specific processing. |
| 257 |
var oTagProcessor = FCKXHtml.TagProcessors[ sNodeName ] ; |
| 258 |
|
| 259 |
if ( oTagProcessor ) |
| 260 |
oNode = oTagProcessor( oNode, htmlNode, xmlNode ) ; |
| 261 |
else |
| 262 |
oNode = this._AppendChildNodes( oNode, htmlNode, Boolean( FCKListsLib.NonEmptyBlockElements[ sNodeName ] ) ) ; |
| 263 |
|
| 264 |
if ( !oNode ) |
| 265 |
return false ; |
| 266 |
|
| 267 |
xmlNode.appendChild( oNode ) ; |
| 268 |
|
| 269 |
break ; |
| 270 |
|
| 271 |
// Text Node. |
| 272 |
case 3 : |
| 273 |
if ( htmlNode.parentNode && htmlNode.parentNode.nodeName.IEquals( 'pre' ) ) |
| 274 |
return this._AppendTextNode( xmlNode, htmlNode.nodeValue ) ; |
| 275 |
return this._AppendTextNode( xmlNode, htmlNode.nodeValue.ReplaceNewLineChars(' ') ) ; |
| 276 |
|
| 277 |
// Comment |
| 278 |
case 8 : |
| 279 |
// IE catches the <!DOTYPE ... > as a comment, but it has no |
| 280 |
// innerHTML, so we can catch it, and ignore it. |
| 281 |
if ( FCKBrowserInfo.IsIE && !htmlNode.innerHTML ) |
| 282 |
break ; |
| 283 |
|
| 284 |
try { xmlNode.appendChild( this.XML.createComment( htmlNode.nodeValue ) ) ; } |
| 285 |
catch (e) { /* Do nothing... probably this is a wrong format comment. */ } |
| 286 |
break ; |
| 287 |
|
| 288 |
// Unknown Node type. |
| 289 |
default : |
| 290 |
xmlNode.appendChild( this.XML.createComment( "Element not supported - Type: " + htmlNode.nodeType + " Name: " + htmlNode.nodeName ) ) ; |
| 291 |
break ; |
| 292 |
} |
| 293 |
return true ; |
| 294 |
} |
| 295 |
|
| 296 |
// Append an item to the SpecialBlocks array and returns the tag to be used. |
| 297 |
FCKXHtml._AppendSpecialItem = function( item ) |
| 298 |
{ |
| 299 |
return '___FCKsi___' + ( FCKXHtml.SpecialBlocks.push( item ) - 1 ) ; |
| 300 |
} |
| 301 |
|
| 302 |
FCKXHtml._AppendEntity = function( xmlNode, entity ) |
| 303 |
{ |
| 304 |
xmlNode.appendChild( this.XML.createTextNode( '#?-:' + entity + ';' ) ) ; |
| 305 |
} |
| 306 |
|
| 307 |
FCKXHtml._AppendTextNode = function( targetNode, textValue ) |
| 308 |
{ |
| 309 |
var bHadText = textValue.length > 0 ; |
| 310 |
if ( bHadText ) |
| 311 |
targetNode.appendChild( this.XML.createTextNode( textValue.replace( FCKXHtmlEntities.EntitiesRegex, FCKXHtml_GetEntity ) ) ) ; |
| 312 |
return bHadText ; |
| 313 |
} |
| 314 |
|
| 315 |
// Retrieves a entity (internal format) for a given character. |
| 316 |
function FCKXHtml_GetEntity( character ) |
| 317 |
{ |
| 318 |
// We cannot simply place the entities in the text, because the XML parser |
| 319 |
// will translate & to &. So we use a temporary marker which is replaced |
| 320 |
// in the end of the processing. |
| 321 |
var sEntity = FCKXHtmlEntities.Entities[ character ] || ( '#' + character.charCodeAt(0) ) ; |
| 322 |
return '#?-:' + sEntity + ';' ; |
| 323 |
} |
| 324 |
|
| 325 |
// An object that hold tag specific operations. |
| 326 |
FCKXHtml.TagProcessors = |
| 327 |
{ |
| 328 |
a : function( node, htmlNode ) |
| 329 |
{ |
| 330 |
// Firefox may create empty tags when deleting the selection in some special cases (SF-BUG 1556878). |
| 331 |
if ( htmlNode.innerHTML.Trim().length == 0 && !htmlNode.name ) |
| 332 |
return false ; |
| 333 |
|
| 334 |
var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ; |
| 335 |
if ( sSavedUrl != null ) |
| 336 |
FCKXHtml._AppendAttribute( node, 'href', sSavedUrl ) ; |
| 337 |
|
| 338 |
|
| 339 |
// Anchors with content has been marked with an additional class, now we must remove it. |
| 340 |
if ( FCKBrowserInfo.IsIE ) |
| 341 |
{ |
| 342 |
// Buggy IE, doesn't copy the name of changed anchors. |
| 343 |
if ( htmlNode.name ) |
| 344 |
FCKXHtml._AppendAttribute( node, 'name', htmlNode.name ) ; |
| 345 |
} |
| 346 |
|
| 347 |
node = FCKXHtml._AppendChildNodes( node, htmlNode, false ) ; |
| 348 |
|
| 349 |
return node ; |
| 350 |
}, |
| 351 |
|
| 352 |
area : function( node, htmlNode ) |
| 353 |
{ |
| 354 |
var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ; |
| 355 |
if ( sSavedUrl != null ) |
| 356 |
FCKXHtml._AppendAttribute( node, 'href', sSavedUrl ) ; |
| 357 |
|
| 358 |
// IE ignores the "COORDS" and "SHAPE" attribute so we must add it manually. |
| 359 |
if ( FCKBrowserInfo.IsIE ) |
| 360 |
{ |
| 361 |
if ( ! node.attributes.getNamedItem( 'coords' ) ) |
| 362 |
{ |
| 363 |
var sCoords = htmlNode.getAttribute( 'coords', 2 ) ; |
| 364 |
if ( sCoords && sCoords != '0,0,0' ) |
| 365 |
FCKXHtml._AppendAttribute( node, 'coords', sCoords ) ; |
| 366 |
} |
| 367 |
|
| 368 |
if ( ! node.attributes.getNamedItem( 'shape' ) ) |
| 369 |
{ |
| 370 |
var sShape = htmlNode.getAttribute( 'shape', 2 ) ; |
| 371 |
if ( sShape && sShape.length > 0 ) |
| 372 |
FCKXHtml._AppendAttribute( node, 'shape', sShape.toLowerCase() ) ; |
| 373 |
} |
| 374 |
} |
| 375 |
|
| 376 |
return node ; |
| 377 |
}, |
| 378 |
|
| 379 |
body : function( node, htmlNode ) |
| 380 |
{ |
| 381 |
node = FCKXHtml._AppendChildNodes( node, htmlNode, false ) ; |
| 382 |
// Remove spellchecker attributes added for Firefox when converting to HTML code (Bug #1351). |
| 383 |
node.removeAttribute( 'spellcheck' ) ; |
| 384 |
return node ; |
| 385 |
}, |
| 386 |
|
| 387 |
// IE loses contents of iframes, and Gecko does give it back HtmlEncoded |
| 388 |
// Note: Opera does lose the content and doesn't provide it in the innerHTML string |
| 389 |
iframe : function( node, htmlNode ) |
| 390 |
{ |
| 391 |
var sHtml = htmlNode.innerHTML ; |
| 392 |
|
| 393 |
// Gecko does give back the encoded html |
| 394 |
if ( FCKBrowserInfo.IsGecko ) |
| 395 |
sHtml = FCKTools.HTMLDecode( sHtml ); |
| 396 |
|
| 397 |
// Remove the saved urls here as the data won't be processed as nodes |
| 398 |
sHtml = sHtml.replace( /\s_fcksavedurl="[^"]*"/g, '' ) ; |
| 399 |
|
| 400 |
node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( sHtml ) ) ) ; |
| 401 |
|
| 402 |
return node ; |
| 403 |
}, |
| 404 |
|
| 405 |
img : function( node, htmlNode ) |
| 406 |
{ |
| 407 |
// The "ALT" attribute is required in XHTML. |
| 408 |
if ( ! node.attributes.getNamedItem( 'alt' ) ) |
| 409 |
FCKXHtml._AppendAttribute( node, 'alt', '' ) ; |
| 410 |
|
| 411 |
var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ; |
| 412 |
if ( sSavedUrl != null ) |
| 413 |
FCKXHtml._AppendAttribute( node, 'src', sSavedUrl ) ; |
| 414 |
|
| 415 |
// Bug #768 : If the width and height are defined inline CSS, |
| 416 |
// don't define it again in the HTML attributes. |
| 417 |
if ( htmlNode.style.width ) |
| 418 |
node.removeAttribute( 'width' ) ; |
| 419 |
if ( htmlNode.style.height ) |
| 420 |
node.removeAttribute( 'height' ) ; |
| 421 |
|
| 422 |
return node ; |
| 423 |
}, |
| 424 |
|
| 425 |
// Fix orphaned <li> nodes (Bug #503). |
| 426 |
li : function( node, htmlNode, targetNode ) |
| 427 |
{ |
| 428 |
// If the XML parent node is already a <ul> or <ol>, then add the <li> as usual. |
| 429 |
if ( targetNode.nodeName.IEquals( ['ul', 'ol'] ) ) |
| 430 |
return FCKXHtml._AppendChildNodes( node, htmlNode, true ) ; |
| 431 |
|
| 432 |
var newTarget = FCKXHtml.XML.createElement( 'ul' ) ; |
| 433 |
|
| 434 |
// Reset the _fckxhtmljob so the HTML node is processed again. |
| 435 |
htmlNode._fckxhtmljob = null ; |
| 436 |
|
| 437 |
// Loop through all sibling LIs, adding them to the <ul>. |
| 438 |
do |
| 439 |
{ |
| 440 |
FCKXHtml._AppendNode( newTarget, htmlNode ) ; |
| 441 |
|
| 442 |
// Look for the next element following this <li>. |
| 443 |
do |
| 444 |
{ |
| 445 |
htmlNode = FCKDomTools.GetNextSibling( htmlNode ) ; |
| 446 |
|
| 447 |
} while ( htmlNode && htmlNode.nodeType == 3 && htmlNode.nodeValue.Trim().length == 0 ) |
| 448 |
|
| 449 |
} while ( htmlNode && htmlNode.nodeName.toLowerCase() == 'li' ) |
| 450 |
|
| 451 |
return newTarget ; |
| 452 |
}, |
| 453 |
|
| 454 |
// Fix nested <ul> and <ol>. |
| 455 |
ol : function( node, htmlNode, targetNode ) |
| 456 |
{ |
| 457 |
if ( htmlNode.innerHTML.Trim().length == 0 ) |
| 458 |
return false ; |
| 459 |
|
| 460 |
var ePSibling = targetNode.lastChild ; |
| 461 |
|
| 462 |
if ( ePSibling && ePSibling.nodeType == 3 ) |
| 463 |
ePSibling = ePSibling.previousSibling ; |
| 464 |
|
| 465 |
if ( ePSibling && ePSibling.nodeName.toUpperCase() == 'LI' ) |
| 466 |
{ |
| 467 |
htmlNode._fckxhtmljob = null ; |
| 468 |
FCKXHtml._AppendNode( ePSibling, htmlNode ) ; |
| 469 |
return false ; |
| 470 |
} |
| 471 |
|
| 472 |
node = FCKXHtml._AppendChildNodes( node, htmlNode ) ; |
| 473 |
|
| 474 |
return node ; |
| 475 |
}, |
| 476 |
|
| 477 |
pre : function ( node, htmlNode ) |
| 478 |
{ |
| 479 |
var firstChild = htmlNode.firstChild ; |
| 480 |
|
| 481 |
if ( firstChild && firstChild.nodeType == 3 ) |
| 482 |
node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( '\r\n' ) ) ) ; |
| 483 |
|
| 484 |
FCKXHtml._AppendChildNodes( node, htmlNode, true ) ; |
| 485 |
|
| 486 |
return node ; |
| 487 |
}, |
| 488 |
|
| 489 |
script : function( node, htmlNode ) |
| 490 |
{ |
| 491 |
// The "TYPE" attribute is required in XHTML. |
| 492 |
if ( ! node.attributes.getNamedItem( 'type' ) ) |
| 493 |
FCKXHtml._AppendAttribute( node, 'type', 'text/javascript' ) ; |
| 494 |
|
| 495 |
node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( htmlNode.text ) ) ) ; |
| 496 |
|
| 497 |
return node ; |
| 498 |
}, |
| 499 |
|
| 500 |
span : function( node, htmlNode ) |
| 501 |
{ |
| 502 |
// Firefox may create empty tags when deleting the selection in some special cases (SF-BUG 1084404). |
| 503 |
if ( htmlNode.innerHTML.length == 0 ) |
| 504 |
return false ; |
| 505 |
|
| 506 |
node = FCKXHtml._AppendChildNodes( node, htmlNode, false ) ; |
| 507 |
|
| 508 |
return node ; |
| 509 |
}, |
| 510 |
|
| 511 |
style : function( node, htmlNode ) |
| 512 |
{ |
| 513 |
// The "TYPE" attribute is required in XHTML. |
| 514 |
if ( ! node.attributes.getNamedItem( 'type' ) ) |
| 515 |
FCKXHtml._AppendAttribute( node, 'type', 'text/css' ) ; |
| 516 |
|
| 517 |
var cssText = htmlNode.innerHTML ; |
| 518 |
if ( FCKBrowserInfo.IsIE ) // Bug #403 : IE always appends a \r\n to the beginning of StyleNode.innerHTML |
| 519 |
cssText = cssText.replace( /^(\r\n|\n|\r)/, '' ) ; |
| 520 |
|
| 521 |
node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( cssText ) ) ) ; |
| 522 |
|
| 523 |
return node ; |
| 524 |
}, |
| 525 |
|
| 526 |
title : function( node, htmlNode ) |
| 527 |
{ |
| 528 |
node.appendChild( FCKXHtml.XML.createTextNode( FCK.EditorDocument.title ) ) ; |
| 529 |
|
| 530 |
return node ; |
| 531 |
} |
| 532 |
} ; |
| 533 |
|
| 534 |
FCKXHtml.TagProcessors.ul = FCKXHtml.TagProcessors.ol ; |
| 535 |
|