[ Index ]
 

Code source de FCKeditor 2.4

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/editor/_source/internals/ -> fckxhtml.js (source)

   1  /*
   2   * FCKeditor - The text editor for Internet - http://www.fckeditor.net
   3   * Copyright (C) 2003-2007 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   * File Name: fckxhtml.js
  22   *     Defines the FCKXHtml object, responsible for the XHTML operations.
  23   * 
  24   * File Authors:
  25   *         Frederico Caldeira Knabben (www.fckeditor.net)
  26   *         Alfonso Martinez de Lizarrondo - Uritec (alfonso at uritec dot net)
  27   */
  28  
  29  var FCKXHtml = new Object() ;
  30  
  31  FCKXHtml.CurrentJobNum = 0 ;
  32  
  33  FCKXHtml.GetXHTML = function( node, includeNode, format )
  34  {
  35      FCKXHtmlEntities.Initialize() ;
  36      
  37      // Save the current IsDirty state. The XHTML processor may change the
  38      // original HTML, dirtying it.
  39      var bIsDirty = FCK.IsDirty() ;
  40      
  41      this._CreateNode = FCKConfig.ForceStrongEm ? FCKXHtml_CreateNode_StrongEm : FCKXHtml_CreateNode_Normal ;
  42  
  43      // Special blocks are blocks of content that remain untouched during the
  44      // process. It is used for SCRIPTs and STYLEs.
  45      FCKXHtml.SpecialBlocks = new Array() ;
  46  
  47      // Create the XML DOMDocument object.
  48      this.XML = FCKTools.CreateXmlObject( 'DOMDocument' ) ;
  49  
  50      // Add a root element that holds all child nodes.
  51      this.MainNode = this.XML.appendChild( this.XML.createElement( 'xhtml' ) ) ;
  52  
  53      FCKXHtml.CurrentJobNum++ ;
  54  
  55      if ( includeNode )
  56          this._AppendNode( this.MainNode, node ) ;
  57      else
  58          this._AppendChildNodes( this.MainNode, node, false ) ;
  59  
  60      // Get the resulting XHTML as a string.
  61      var sXHTML = this._GetMainXmlString() ;
  62  
  63      this.XML = null ;
  64      
  65      // Strip the "XHTML" root node.
  66      sXHTML = sXHTML.substr( 7, sXHTML.length - 15 ).Trim() ;
  67      
  68      // Remove the trailing <br> added by Gecko.
  69      // REMOVE: Maybe the following is not anymore necessary because a similar
  70      // check is made on _AppendNode
  71      if ( FCKBrowserInfo.IsGecko )
  72          sXHTML = sXHTML.replace( /<br\/>$/, '' ) ;
  73  
  74      // Add a space in the tags with no closing tags, like <br/> -> <br />
  75      sXHTML = sXHTML.replace( FCKRegexLib.SpaceNoClose, ' />');
  76  
  77      if ( FCKConfig.ForceSimpleAmpersand )
  78          sXHTML = sXHTML.replace( FCKRegexLib.ForceSimpleAmpersand, '&' ) ;
  79  
  80      if ( format )
  81          sXHTML = FCKCodeFormatter.Format( sXHTML ) ;
  82  
  83      // Now we put back the SpecialBlocks contents.
  84      for ( var i = 0 ; i < FCKXHtml.SpecialBlocks.length ; i++ )
  85      {
  86          var oRegex = new RegExp( '___FCKsi___' + i ) ;
  87          sXHTML = sXHTML.replace( oRegex, FCKXHtml.SpecialBlocks[i] ) ;
  88      }
  89      
  90      // Replace entities marker with the ampersand.
  91      sXHTML = sXHTML.replace( FCKRegexLib.GeckoEntitiesMarker, '&' ) ;
  92  
  93      // Restore the IsDirty state if it was not dirty.
  94      if ( !bIsDirty )
  95          FCK.ResetIsDirty() ;
  96  
  97      return sXHTML ;
  98  }
  99  
 100  FCKXHtml._AppendAttribute = function( xmlNode, attributeName, attributeValue )
 101  {
 102      try
 103      {
 104          if ( attributeValue == undefined || attributeValue == null )
 105              attributeValue = '' ;
 106          else if ( attributeValue.replace )
 107          {
 108              if ( FCKConfig.ForceSimpleAmpersand )
 109                  attributeValue = attributeValue.replace( /&/g, '___FCKAmp___' ) ;
 110              
 111              // Entities must be replaced in the attribute values.
 112              attributeValue = attributeValue.replace( FCKXHtmlEntities.EntitiesRegex, FCKXHtml_GetEntity ) ;
 113          }
 114          
 115          // Create the attribute.
 116          var oXmlAtt = this.XML.createAttribute( attributeName ) ;
 117          oXmlAtt.value = attributeValue ;
 118  
 119          // Set the attribute in the node.
 120          xmlNode.attributes.setNamedItem( oXmlAtt ) ;
 121      }
 122      catch (e)
 123      {}
 124  }
 125  
 126  FCKXHtml._AppendChildNodes = function( xmlNode, htmlNode, isBlockElement )
 127  {
 128      // Trim block elements. This is also needed to avoid Firefox leaving extra
 129      // BRs at the end of them (check made inside _AppendNode).
 130      if ( isBlockElement )
 131          FCKDomTools.TrimNode( htmlNode ) ;
 132  
 133      var iCount = 0 ;
 134      
 135      var oNode = htmlNode.firstChild ;
 136  
 137      while ( oNode )
 138      {
 139          if ( this._AppendNode( xmlNode, oNode ) )
 140              iCount++ ;
 141  
 142          oNode = oNode.nextSibling ;
 143      }
 144      
 145      if ( iCount == 0 )
 146      {
 147          if ( isBlockElement && FCKConfig.FillEmptyBlocks )
 148          {
 149              this._AppendEntity( xmlNode, 'nbsp' ) ;
 150              return xmlNode ;
 151          }
 152          
 153          var sNodeName = xmlNode.nodeName ;
 154          
 155          // Some inline elements are required to have something inside (span, strong, etc...).
 156          if ( FCKListsLib.InlineChildReqElements[ sNodeName ] )
 157              return null ;
 158  
 159          // We can't use short representation of empty elements that are not marked
 160          // as empty in th XHTML DTD.
 161          if ( !FCKListsLib.EmptyElements[ sNodeName ] )
 162              xmlNode.appendChild( this.XML.createTextNode('') ) ;
 163      }
 164      
 165      return xmlNode ;
 166  }
 167  
 168  FCKXHtml._AppendNode = function( xmlNode, htmlNode )
 169  {
 170      if ( !htmlNode )
 171          return false ;
 172  
 173      switch ( htmlNode.nodeType )
 174      {
 175          // Element Node.
 176          case 1 :
 177  
 178              // Here we found an element that is not the real element, but a 
 179              // fake one (like the Flash placeholder image), so we must get the real one.
 180              if ( htmlNode.getAttribute('_fckfakelement') )
 181                  return FCKXHtml._AppendNode( xmlNode, FCK.GetRealElement( htmlNode ) ) ;
 182          
 183              // Mozilla insert custom nodes in the DOM.
 184              if ( FCKBrowserInfo.IsGecko && htmlNode.hasAttribute('_moz_editor_bogus_node') )
 185                  return false ;
 186              
 187              // This is for elements that are instrumental to FCKeditor and 
 188              // must be removed from the final HTML.
 189              if ( htmlNode.getAttribute('_fcktemp') )
 190                  return false ;
 191  
 192              // Get the element name.
 193              var sNodeName = htmlNode.tagName.toLowerCase()  ;
 194              
 195              if ( FCKBrowserInfo.IsIE )
 196              {
 197                  // IE doens't include the scope name in the nodeName. So, add the namespace.
 198                  if ( htmlNode.scopeName && htmlNode.scopeName != 'HTML' && htmlNode.scopeName != 'FCK' )
 199                      sNodeName = htmlNode.scopeName.toLowerCase() + ':' + sNodeName ;
 200              }
 201              else
 202              {
 203                  if ( sNodeName.StartsWith( 'fck:' ) )
 204                      sNodeName = sNodeName.Remove( 0,4 ) ;
 205              }
 206  
 207              // Check if the node name is valid, otherwise ignore this tag.
 208              // If the nodeName starts with a slash, it is a orphan closing tag.
 209              // On some strange cases, the nodeName is empty, even if the node exists.
 210              if ( !FCKRegexLib.ElementName.test( sNodeName ) )
 211                  return false ;
 212  
 213              // Remove the <br> if it is a bogus node or is the last child.
 214              if ( sNodeName == 'br' && ( htmlNode.getAttribute( 'type', 2 ) == '_moz' || !htmlNode.nextSibling ) )
 215                  return false ;
 216  
 217              // The already processed nodes must be marked to avoid then to be duplicated (bad formatted HTML).
 218              // So here, the "mark" is checked... if the element is Ok, then mark it.
 219              if ( htmlNode._fckxhtmljob && htmlNode._fckxhtmljob == FCKXHtml.CurrentJobNum )
 220                  return false ;
 221  
 222              var oNode = this._CreateNode( sNodeName ) ;
 223              
 224              // Add all attributes.
 225              FCKXHtml._AppendAttributes( xmlNode, htmlNode, oNode, sNodeName ) ;
 226              
 227              htmlNode._fckxhtmljob = FCKXHtml.CurrentJobNum ;
 228  
 229              // Tag specific processing.
 230              var oTagProcessor = FCKXHtml.TagProcessors[ sNodeName ] ;
 231  
 232              if ( oTagProcessor )
 233                  oNode = oTagProcessor( oNode, htmlNode, xmlNode ) ;
 234              else
 235                  oNode = this._AppendChildNodes( oNode, htmlNode, Boolean( FCKListsLib.NonEmptyBlockElements[ sNodeName ] ) ) ;
 236  
 237              if ( !oNode ) 
 238                  break ;
 239  
 240              xmlNode.appendChild( oNode ) ;
 241  
 242              break ;
 243  
 244          // Text Node.
 245          case 3 :
 246              return this._AppendTextNode( xmlNode, htmlNode.nodeValue.ReplaceNewLineChars(' ') ) ;
 247  
 248          // Comment
 249          case 8 :
 250              // IE catches the <!DOTYPE ... > as a comment, but it has no
 251              // innerHTML, so we can catch it, and ignore it.
 252              if ( FCKBrowserInfo.IsIE && !htmlNode.innerHTML )
 253                  break ;
 254  
 255              try { xmlNode.appendChild( this.XML.createComment( htmlNode.nodeValue ) ) ; }
 256              catch (e) { /* Do nothing... probably this is a wrong format comment. */ }
 257              break ;
 258  
 259          // Unknown Node type.
 260          default :
 261              xmlNode.appendChild( this.XML.createComment( "Element not supported - Type: " + htmlNode.nodeType + " Name: " + htmlNode.nodeName ) ) ;
 262              break ;
 263      }
 264      return true ;
 265  }
 266  
 267  function FCKXHtml_CreateNode_StrongEm( nodeName )
 268  {
 269      switch ( nodeName )
 270      {
 271          case 'b' :
 272              nodeName = 'strong' ;
 273              break ;
 274          case 'i' :
 275              nodeName = 'em' ;
 276              break ;
 277      }
 278      return this.XML.createElement( nodeName ) ;
 279  }
 280  
 281  function FCKXHtml_CreateNode_Normal( nodeName )
 282  {
 283      return this.XML.createElement( nodeName ) ;
 284  }
 285  
 286  // Append an item to the SpecialBlocks array and returns the tag to be used.
 287  FCKXHtml._AppendSpecialItem = function( item )
 288  {
 289      return '___FCKsi___' + FCKXHtml.SpecialBlocks.AddItem( item ) ;
 290  }
 291  
 292  FCKXHtml._AppendEntity = function( xmlNode, entity )
 293  {
 294      xmlNode.appendChild( this.XML.createTextNode( '#?-:' + entity + ';' ) ) ;
 295  }
 296  
 297  FCKXHtml._AppendTextNode = function( targetNode, textValue )
 298  {
 299      var bHadText = textValue.length > 0 ;
 300      if ( bHadText )
 301          targetNode.appendChild( this.XML.createTextNode( textValue.replace( FCKXHtmlEntities.EntitiesRegex, FCKXHtml_GetEntity ) ) ) ;
 302      return bHadText ;
 303  }
 304  
 305  // Retrieves a entity (internal format) for a given character.
 306  function FCKXHtml_GetEntity( character )
 307  {
 308      // We cannot simply place the entities in the text, because the XML parser
 309      // will translate & to &amp;. So we use a temporary marker which is replaced
 310      // in the end of the processing.
 311      var sEntity = FCKXHtmlEntities.Entities[ character ] || ( '#' + character.charCodeAt(0) ) ;
 312      return '#?-:' + sEntity + ';' ;
 313  }
 314  
 315  // Remove part of an attribute from a node according to a regExp
 316  FCKXHtml._RemoveAttribute = function( xmlNode, regX, sAttribute )
 317  {
 318      var oAtt = xmlNode.attributes.getNamedItem( sAttribute ) ;
 319  
 320      if ( oAtt && regX.test( oAtt.nodeValue ) )
 321      {
 322          var sValue = oAtt.nodeValue.replace( regX, '' ) ;
 323  
 324          if ( sValue.length == 0 )
 325              xmlNode.attributes.removeNamedItem( sAttribute ) ;
 326          else
 327              oAtt.nodeValue = sValue ;
 328      }
 329  }
 330  
 331  // An object that hold tag specific operations.
 332  FCKXHtml.TagProcessors =
 333  {
 334      img : function( node, htmlNode )
 335      {
 336          // The "ALT" attribute is required in XHTML.
 337          if ( ! node.attributes.getNamedItem( 'alt' ) )
 338              FCKXHtml._AppendAttribute( node, 'alt', '' ) ;
 339  
 340          var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ;
 341          if ( sSavedUrl != null )
 342              FCKXHtml._AppendAttribute( node, 'src', sSavedUrl ) ;
 343  
 344          return node ;
 345      },
 346  
 347      a : function( node, htmlNode )
 348      {
 349          // Firefox may create empty tags when deleting the selection in some special cases (SF-BUG 1556878).
 350          if ( htmlNode.innerHTML.Trim().length == 0 && !htmlNode.name )
 351              return false ;
 352  
 353          var sSavedUrl = htmlNode.getAttribute( '_fcksavedurl' ) ;
 354          if ( sSavedUrl != null )
 355              FCKXHtml._AppendAttribute( node, 'href', sSavedUrl ) ;
 356  
 357  
 358          // Anchors with content has been marked with an additional class, now we must remove it.
 359          if ( FCKBrowserInfo.IsIE )
 360          {
 361              FCKXHtml._RemoveAttribute( node, FCKRegexLib.FCK_Class, 'class' ) ;
 362  
 363              // Buggy IE, doesn't copy the name of changed anchors.
 364              if ( htmlNode.name )
 365                  FCKXHtml._AppendAttribute( node, 'name', htmlNode.name ) ;
 366          }
 367  
 368          FCKXHtml._AppendChildNodes( node, htmlNode, false ) ;
 369  
 370          return node ;
 371      },
 372  
 373      script : function( node, htmlNode )
 374      {
 375          // The "TYPE" attribute is required in XHTML.
 376          if ( ! node.attributes.getNamedItem( 'type' ) )
 377              FCKXHtml._AppendAttribute( node, 'type', 'text/javascript' ) ;
 378  
 379          node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( htmlNode.text ) ) ) ;
 380  
 381          return node ;
 382      },
 383  
 384      style : function( node, htmlNode )
 385      {
 386          // The "TYPE" attribute is required in XHTML.
 387          if ( ! node.attributes.getNamedItem( 'type' ) )
 388              FCKXHtml._AppendAttribute( node, 'type', 'text/css' ) ;
 389  
 390          node.appendChild( FCKXHtml.XML.createTextNode( FCKXHtml._AppendSpecialItem( htmlNode.innerHTML ) ) ) ;
 391  
 392          return node ;
 393      },
 394  
 395      title : function( node, htmlNode )
 396      {
 397          node.appendChild( FCKXHtml.XML.createTextNode( FCK.EditorDocument.title ) ) ;
 398  
 399          return node ;
 400      },
 401  
 402      table : function( node, htmlNode )
 403      {
 404          // There is a trick to show table borders when border=0. We add to the
 405          // table class the FCK__ShowTableBorders rule. So now we must remove it.
 406  
 407          if ( FCKBrowserInfo.IsIE )
 408              FCKXHtml._RemoveAttribute( node, FCKRegexLib.FCK_Class, 'class' ) ;
 409  
 410          FCKXHtml._AppendChildNodes( node, htmlNode, false ) ;
 411  
 412          return node ;
 413      },
 414  
 415      // Fix nested <ul> and <ol>.
 416      ol : function( node, htmlNode, targetNode )
 417      {
 418          if ( htmlNode.innerHTML.Trim().length == 0 )
 419              return false ;
 420  
 421          var ePSibling = targetNode.lastChild ;
 422          
 423          if ( ePSibling && ePSibling.nodeType == 3 )
 424              ePSibling = ePSibling.previousSibling ;
 425          
 426          if ( ePSibling && ePSibling.nodeName.toUpperCase() == 'LI' )
 427          {
 428              htmlNode._fckxhtmljob = null ;
 429              FCKXHtml._AppendNode( ePSibling, htmlNode ) ;
 430              return false ;
 431          }
 432  
 433          FCKXHtml._AppendChildNodes( node, htmlNode ) ;
 434  
 435          return node ;
 436      },
 437  
 438      span : function( node, htmlNode )
 439      {
 440          // Firefox may create empty tags when deleting the selection in some special cases (SF-BUG 1084404).
 441          if ( htmlNode.innerHTML.length == 0 )
 442              return false ;
 443              
 444          FCKXHtml._AppendChildNodes( node, htmlNode, false ) ;
 445  
 446          return node ;
 447      }
 448  } ;
 449  
 450  FCKXHtml.TagProcessors.ul = FCKXHtml.TagProcessors.ol ;


Généré le : Sun Feb 25 15:28:05 2007 par Balluche grâce à PHPXref 0.7