[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/libraries/ckeditor/_source/core/dom/ -> element.js (source)

   1  /*

   2  Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.

   3  For licensing, see LICENSE.html or http://ckeditor.com/license

   4  */
   5  
   6  /**

   7   * @fileOverview Defines the {@link CKEDITOR.dom.element} class, which

   8   *        represents a DOM element.

   9   */
  10  
  11  /**

  12   * Represents a DOM element.

  13   * @constructor

  14   * @augments CKEDITOR.dom.node

  15   * @param {Object|String} element A native DOM element or the element name for

  16   *        new elements.

  17   * @param {CKEDITOR.dom.document} [ownerDocument] The document that will contain

  18   *        the element in case of element creation.

  19   * @example

  20   * // Create a new <span> element.

  21   * var element = new CKEDITOR.dom.element( 'span' );

  22   * @example

  23   * // Create an element based on a native DOM element.

  24   * var element = new CKEDITOR.dom.element( document.getElementById( 'myId' ) );

  25   */
  26  CKEDITOR.dom.element = function( element, ownerDocument )
  27  {
  28      if ( typeof element == 'string' )
  29          element = ( ownerDocument ? ownerDocument.$ : document ).createElement( element );
  30  
  31      // Call the base constructor (we must not call CKEDITOR.dom.node).

  32      CKEDITOR.dom.domObject.call( this, element );
  33  };
  34  
  35  // PACKAGER_RENAME( CKEDITOR.dom.element )

  36  
  37  /**

  38   * The the {@link CKEDITOR.dom.element} representing and element. If the

  39   * element is a native DOM element, it will be transformed into a valid

  40   * CKEDITOR.dom.element object.

  41   * @returns {CKEDITOR.dom.element} The transformed element.

  42   * @example

  43   * var element = new CKEDITOR.dom.element( 'span' );

  44   * alert( element == <b>CKEDITOR.dom.element.get( element )</b> );  "true"

  45   * @example

  46   * var element = document.getElementById( 'myElement' );

  47   * alert( <b>CKEDITOR.dom.element.get( element )</b>.getName() );  e.g. "p"

  48   */
  49  CKEDITOR.dom.element.get = function( element )
  50  {
  51      return element && ( element.$ ? element : new CKEDITOR.dom.element( element ) );
  52  };
  53  
  54  CKEDITOR.dom.element.prototype = new CKEDITOR.dom.node();
  55  
  56  /**

  57   * Creates an instance of the {@link CKEDITOR.dom.element} class based on the

  58   * HTML representation of an element.

  59   * @param {String} html The element HTML. It should define only one element in

  60   *        the "root" level. The "root" element can have child nodes, but not

  61   *        siblings.

  62   * @returns {CKEDITOR.dom.element} The element instance.

  63   * @example

  64   * var element = <b>CKEDITOR.dom.element.createFromHtml( '&lt;strong class="anyclass"&gt;My element&lt;/strong&gt;' )</b>;

  65   * alert( element.getName() );  // "strong"

  66   */
  67  CKEDITOR.dom.element.createFromHtml = function( html, ownerDocument )
  68  {
  69      var temp = new CKEDITOR.dom.element( 'div', ownerDocument );
  70      temp.setHtml( html );
  71  
  72      // When returning the node, remove it from its parent to detach it.

  73      return temp.getFirst().remove();
  74  };
  75  
  76  CKEDITOR.dom.element.setMarker = function( database, element, name, value )
  77  {
  78      var id = element.getCustomData( 'list_marker_id' ) ||
  79              ( element.setCustomData( 'list_marker_id', CKEDITOR.tools.getNextNumber() ).getCustomData( 'list_marker_id' ) ),
  80          markerNames = element.getCustomData( 'list_marker_names' ) ||
  81              ( element.setCustomData( 'list_marker_names', {} ).getCustomData( 'list_marker_names' ) );
  82      database[id] = element;
  83      markerNames[name] = 1;
  84  
  85      return element.setCustomData( name, value );
  86  };
  87  
  88  CKEDITOR.dom.element.clearAllMarkers = function( database )
  89  {
  90      for ( var i in database )
  91          CKEDITOR.dom.element.clearMarkers( database, database[i], true );
  92  };
  93  
  94  CKEDITOR.dom.element.clearMarkers = function( database, element, removeFromDatabase )
  95  {
  96      var names = element.getCustomData( 'list_marker_names' ),
  97          id = element.getCustomData( 'list_marker_id' );
  98      for ( var i in names )
  99          element.removeCustomData( i );
 100      element.removeCustomData( 'list_marker_names' );
 101      if ( removeFromDatabase )
 102      {
 103          element.removeCustomData( 'list_marker_id' );
 104          delete database[id];
 105      }
 106  };
 107  
 108  CKEDITOR.tools.extend( CKEDITOR.dom.element.prototype,
 109      /** @lends CKEDITOR.dom.element.prototype */

 110      {
 111          /**

 112           * The node type. This is a constant value set to

 113           * {@link CKEDITOR.NODE_ELEMENT}.

 114           * @type Number

 115           * @example

 116           */
 117          type : CKEDITOR.NODE_ELEMENT,
 118  
 119          /**

 120           * Adds a CSS class to the element. It appends the class to the

 121           * already existing names.

 122           * @param {String} className The name of the class to be added.

 123           * @example

 124           * var element = new CKEDITOR.dom.element( 'div' );

 125           * element.addClass( 'classA' );  // &lt;div class="classA"&gt;

 126           * element.addClass( 'classB' );  // &lt;div class="classA classB"&gt;

 127           * element.addClass( 'classA' );  // &lt;div class="classA classB"&gt;

 128           */
 129          addClass : function( className )
 130          {
 131              var c = this.$.className;
 132              if ( c )
 133              {
 134                  var regex = new RegExp( '(?:^|\\s)' + className + '(?:\\s|$)', '' );
 135                  if ( !regex.test( c ) )
 136                      c += ' ' + className;
 137              }
 138              this.$.className = c || className;
 139          },
 140  
 141          /**

 142           * Removes a CSS class name from the elements classes. Other classes

 143           * remain untouched.

 144           * @param {String} className The name of the class to remove.

 145           * @example

 146           * var element = new CKEDITOR.dom.element( 'div' );

 147           * element.addClass( 'classA' );  // &lt;div class="classA"&gt;

 148           * element.addClass( 'classB' );  // &lt;div class="classA classB"&gt;

 149           * element.removeClass( 'classA' );  // &lt;div class="classB"&gt;

 150           * element.removeClass( 'classB' );  // &lt;div&gt;

 151           */
 152          removeClass : function( className )
 153          {
 154              var c = this.getAttribute( 'class' );
 155              if ( c )
 156              {
 157                  var regex = new RegExp( '(?:^|\\s+)' + className + '(?=\\s|$)', 'i' );
 158                  if ( regex.test( c ) )
 159                  {
 160                      c = c.replace( regex, '' ).replace( /^\s+/, '' );
 161  
 162                      if ( c )
 163                          this.setAttribute( 'class', c );
 164                      else
 165                          this.removeAttribute( 'class' );
 166                  }
 167              }
 168          },
 169  
 170          hasClass : function( className )
 171          {
 172              var regex = new RegExp( '(?:^|\\s+)' + className + '(?=\\s|$)', '' );
 173              return regex.test( this.getAttribute('class') );
 174          },
 175  
 176          /**

 177           * Append a node as a child of this element.

 178           * @param {CKEDITOR.dom.node|String} node The node or element name to be

 179           *        appended.

 180           * @param {Boolean} [toStart] Indicates that the element is to be

 181           *        appended at the start.

 182           * @returns {CKEDITOR.dom.node} The appended node.

 183           * @example

 184           * var p = new CKEDITOR.dom.element( 'p' );

 185           *

 186           * var strong = new CKEDITOR.dom.element( 'strong' );

 187           * <b>p.append( strong );</b>

 188           *

 189           * var em = <b>p.append( 'em' );</b>

 190           *

 191           * // result: "&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;"

 192           */
 193          append : function( node, toStart )
 194          {
 195              if ( typeof node == 'string' )
 196                  node = this.getDocument().createElement( node );
 197  
 198              if ( toStart )
 199                  this.$.insertBefore( node.$, this.$.firstChild );
 200              else
 201                  this.$.appendChild( node.$ );
 202  
 203              return node;
 204          },
 205  
 206          appendHtml : function( html )
 207          {
 208              if ( !this.$.childNodes.length )
 209                  this.setHtml( html );
 210              else
 211              {
 212                  var temp = new CKEDITOR.dom.element( 'div', this.getDocument() );
 213                  temp.setHtml( html );
 214                  temp.moveChildren( this );
 215              }
 216          },
 217  
 218          /**

 219           * Append text to this element.

 220           * @param {String} text The text to be appended.

 221           * @returns {CKEDITOR.dom.node} The appended node.

 222           * @example

 223           * var p = new CKEDITOR.dom.element( 'p' );

 224           * p.appendText( 'This is' );

 225           * p.appendText( ' some text' );

 226           *

 227           * // result: "&lt;p&gt;This is some text&lt;/p&gt;"

 228           */
 229          appendText : function( text )
 230          {
 231              if ( this.$.text != undefined )
 232                  this.$.text += text;
 233              else
 234                  this.append( new CKEDITOR.dom.text( text ) );
 235          },
 236  
 237          appendBogus : function()
 238          {
 239              var lastChild = this.getLast() ;
 240  
 241              // Ignore empty/spaces text.

 242              while ( lastChild && lastChild.type == CKEDITOR.NODE_TEXT && !CKEDITOR.tools.rtrim( lastChild.getText() ) )
 243                  lastChild = lastChild.getPrevious();
 244              if ( !lastChild || !lastChild.is || !lastChild.is( 'br' ) )
 245              {
 246                  var bogus = CKEDITOR.env.opera ?
 247                          this.getDocument().createText('') :
 248                          this.getDocument().createElement( 'br' );
 249  
 250                  CKEDITOR.env.gecko && bogus.setAttribute( 'type', '_moz' );
 251  
 252                  this.append( bogus );
 253              }
 254          },
 255  
 256          /**

 257           * Breaks one of the ancestor element in the element position, moving

 258           * this element between the broken parts.

 259           * @param {CKEDITOR.dom.element} parent The anscestor element to get broken.

 260           * @example

 261           * // Before breaking:

 262           * //     &lt;b&gt;This &lt;i&gt;is some&lt;span /&gt; sample&lt;/i&gt; test text&lt;/b&gt;

 263           * // If "element" is &lt;span /&gt; and "parent" is &lt;i&gt;:

 264           * //     &lt;b&gt;This &lt;i&gt;is some&lt;/i&gt;&lt;span /&gt;&lt;i&gt; sample&lt;/i&gt; test text&lt;/b&gt;

 265           * element.breakParent( parent );

 266           * @example

 267           * // Before breaking:

 268           * //     &lt;b&gt;This &lt;i&gt;is some&lt;span /&gt; sample&lt;/i&gt; test text&lt;/b&gt;

 269           * // If "element" is &lt;span /&gt; and "parent" is &lt;b&gt;:

 270           * //     &lt;b&gt;This &lt;i&gt;is some&lt;/i&gt;&lt;/b&gt;&lt;span /&gt;&lt;b&gt;&lt;i&gt; sample&lt;/i&gt; test text&lt;/b&gt;

 271           * element.breakParent( parent );

 272           */
 273          breakParent : function( parent )
 274          {
 275              var range = new CKEDITOR.dom.range( this.getDocument() );
 276  
 277              // We'll be extracting part of this element, so let's use our

 278              // range to get the correct piece.

 279              range.setStartAfter( this );
 280              range.setEndAfter( parent );
 281  
 282              // Extract it.

 283              var docFrag = range.extractContents();
 284  
 285              // Move the element outside the broken element.

 286              range.insertNode( this.remove() );
 287  
 288              // Re-insert the extracted piece after the element.

 289              docFrag.insertAfterNode( this );
 290          },
 291  
 292          contains :
 293              CKEDITOR.env.ie || CKEDITOR.env.webkit ?
 294                  function( node )
 295                  {
 296                      var $ = this.$;
 297  
 298                      return node.type != CKEDITOR.NODE_ELEMENT ?
 299                          $.contains( node.getParent().$ ) :
 300                          $ != node.$ && $.contains( node.$ );
 301                  }
 302              :
 303                  function( node )
 304                  {
 305                      return !!( this.$.compareDocumentPosition( node.$ ) & 16 );
 306                  },
 307  
 308          /**

 309           * Moves the selection focus to this element.

 310           * @example

 311           * var element = CKEDITOR.document.getById( 'myTextarea' );

 312           * <b>element.focus()</b>;

 313           */
 314          focus : function()
 315          {
 316              // IE throws error if the element is not visible.

 317              try
 318              {
 319                  this.$.focus();
 320              }
 321              catch (e)
 322              {}
 323          },
 324  
 325          /**

 326           * Gets the inner HTML of this element.

 327           * @returns {String} The inner HTML of this element.

 328           * @example

 329           * var element = CKEDITOR.dom.element.createFromHtml( '&lt;div&gt;&lt;b&gt;Example&lt;/b&gt;&lt;/div&gt;' );

 330           * alert( <b>p.getHtml()</b> );  // "&lt;b&gt;Example&lt;/b&gt;"

 331           */
 332          getHtml : function()
 333          {
 334              var retval = this.$.innerHTML;
 335              // Strip <?xml:namespace> tags in IE. (#3341).

 336              return CKEDITOR.env.ie ? retval.replace( /<\?[^>]*>/g, '' ) : retval;
 337          },
 338  
 339          getOuterHtml : function()
 340          {
 341              if ( this.$.outerHTML )
 342              {
 343                  // IE includes the <?xml:namespace> tag in the outerHTML of

 344                  // namespaced element. So, we must strip it here. (#3341)

 345                  return this.$.outerHTML.replace( /<\?[^>]*>/, '' );
 346              }
 347  
 348              var tmpDiv = this.$.ownerDocument.createElement( 'div' );
 349              tmpDiv.appendChild( this.$.cloneNode( true ) );
 350              return tmpDiv.innerHTML;
 351          },
 352  
 353          /**

 354           * Sets the inner HTML of this element.

 355           * @param {String} html The HTML to be set for this element.

 356           * @returns {String} The inserted HTML.

 357           * @example

 358           * var p = new CKEDITOR.dom.element( 'p' );

 359           * <b>p.setHtml( '&lt;b&gt;Inner&lt;/b&gt; HTML' );</b>

 360           *

 361           * // result: "&lt;p&gt;&lt;b&gt;Inner&lt;/b&gt; HTML&lt;/p&gt;"

 362           */
 363          setHtml : function( html )
 364          {
 365              return ( this.$.innerHTML = html );
 366          },
 367  
 368          /**

 369           * Sets the element contents as plain text.

 370           * @param {String} text The text to be set.

 371           * @returns {String} The inserted text.

 372           * @example

 373           * var element = new CKEDITOR.dom.element( 'div' );

 374           * element.setText( 'A > B & C < D' );

 375           * alert( element.innerHTML );  // "A &amp;gt; B &amp;amp; C &amp;lt; D"

 376           */
 377          setText : function( text )
 378          {
 379              CKEDITOR.dom.element.prototype.setText = ( this.$.innerText != undefined ) ?
 380                  function ( text )
 381                  {
 382                      return this.$.innerText = text;
 383                  } :
 384                  function ( text )
 385                  {
 386                      return this.$.textContent = text;
 387                  };
 388  
 389              return this.setText( text );
 390          },
 391  
 392          /**

 393           * Gets the value of an element attribute.

 394           * @function

 395           * @param {String} name The attribute name.

 396           * @returns {String} The attribute value or null if not defined.

 397           * @example

 398           * var element = CKEDITOR.dom.element.createFromHtml( '&lt;input type="text" /&gt;' );

 399           * alert( <b>element.getAttribute( 'type' )</b> );  // "text"

 400           */
 401          getAttribute : (function()
 402          {
 403              var standard = function( name )
 404              {
 405                  return this.$.getAttribute( name, 2 );
 406              };
 407  
 408              if ( CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) )
 409              {
 410                  return function( name )
 411                  {
 412                      switch ( name )
 413                      {
 414                          case 'class':
 415                              name = 'className';
 416                              break;
 417  
 418                          case 'tabindex':
 419                              var tabIndex = standard.call( this, name );
 420  
 421                              // IE returns tabIndex=0 by default for all

 422                              // elements. For those elements,

 423                              // getAtrribute( 'tabindex', 2 ) returns 32768

 424                              // instead. So, we must make this check to give a

 425                              // uniform result among all browsers.

 426                              if ( tabIndex !== 0 && this.$.tabIndex === 0 )
 427                                  tabIndex = null;
 428  
 429                              return tabIndex;
 430                              break;
 431  
 432                          case 'checked':
 433                          {
 434                              var attr = this.$.attributes.getNamedItem( name ),
 435                                  attrValue = attr.specified ? attr.nodeValue     // For value given by parser.
 436                                                               : this.$.checked;  // For value created via DOM interface.

 437  
 438                              return attrValue ? 'checked' : null;
 439                          }
 440  
 441                          case 'hspace':
 442                              return this.$.hspace;
 443  
 444                          case 'style':
 445                              // IE does not return inline styles via getAttribute(). See #2947.

 446                              return this.$.style.cssText;
 447                      }
 448  
 449                      return standard.call( this, name );
 450                  };
 451              }
 452              else
 453                  return standard;
 454          })(),
 455  
 456          getChildren : function()
 457          {
 458              return new CKEDITOR.dom.nodeList( this.$.childNodes );
 459          },
 460  
 461          /**

 462           * Gets the current computed value of one of the element CSS style

 463           * properties.

 464           * @function

 465           * @param {String} propertyName The style property name.

 466           * @returns {String} The property value.

 467           * @example

 468           * var element = new CKEDITOR.dom.element( 'span' );

 469           * alert( <b>element.getComputedStyle( 'display' )</b> );  // "inline"

 470           */
 471          getComputedStyle :
 472              CKEDITOR.env.ie ?
 473                  function( propertyName )
 474                  {
 475                      return this.$.currentStyle[ CKEDITOR.tools.cssStyleToDomStyle( propertyName ) ];
 476                  }
 477              :
 478                  function( propertyName )
 479                  {
 480                      return this.getWindow().$.getComputedStyle( this.$, '' ).getPropertyValue( propertyName );
 481                  },
 482  
 483          /**

 484           * Gets the DTD entries for this element.

 485           * @returns {Object} An object containing the list of elements accepted

 486           *        by this element.

 487           */
 488          getDtd : function()
 489          {
 490              var dtd = CKEDITOR.dtd[ this.getName() ];
 491  
 492              this.getDtd = function()
 493              {
 494                  return dtd;
 495              };
 496  
 497              return dtd;
 498          },
 499  
 500          getElementsByTag : CKEDITOR.dom.document.prototype.getElementsByTag,
 501  
 502          /**

 503           * Gets the computed tabindex for this element.

 504           * @function

 505           * @returns {Number} The tabindex value.

 506           * @example

 507           * var element = CKEDITOR.document.getById( 'myDiv' );

 508           * alert( <b>element.getTabIndex()</b> );  // e.g. "-1"

 509           */
 510          getTabIndex :
 511              CKEDITOR.env.ie ?
 512                  function()
 513                  {
 514                      var tabIndex = this.$.tabIndex;
 515  
 516                      // IE returns tabIndex=0 by default for all elements. In

 517                      // those cases we must check that the element really has

 518                      // the tabindex attribute set to zero, or it is one of

 519                      // those element that should have zero by default.

 520                      if ( tabIndex === 0 && !CKEDITOR.dtd.$tabIndex[ this.getName() ] && parseInt( this.getAttribute( 'tabindex' ), 10 ) !== 0 )
 521                          tabIndex = -1;
 522  
 523                          return tabIndex;
 524                  }
 525              : CKEDITOR.env.webkit ?
 526                  function()
 527                  {
 528                      var tabIndex = this.$.tabIndex;
 529  
 530                      // Safari returns "undefined" for elements that should not

 531                      // have tabindex (like a div). So, we must try to get it

 532                      // from the attribute.

 533                      // https://bugs.webkit.org/show_bug.cgi?id=20596

 534                      if ( tabIndex == undefined )
 535                      {
 536                          tabIndex = parseInt( this.getAttribute( 'tabindex' ), 10 );
 537  
 538                          // If the element don't have the tabindex attribute,

 539                          // then we should return -1.

 540                          if ( isNaN( tabIndex ) )
 541                              tabIndex = -1;
 542                      }
 543  
 544                      return tabIndex;
 545                  }
 546              :
 547                  function()
 548                  {
 549                      return this.$.tabIndex;
 550                  },
 551  
 552          /**

 553           * Gets the text value of this element.

 554           *

 555           * Only in IE (which uses innerText), &lt;br&gt; will cause linebreaks,

 556           * and sucessive whitespaces (including line breaks) will be reduced to

 557           * a single space. This behavior is ok for us, for now. It may change

 558           * in the future.

 559           * @returns {String} The text value.

 560           * @example

 561           * var element = CKEDITOR.dom.element.createFromHtml( '&lt;div&gt;Same &lt;i&gt;text&lt;/i&gt;.&lt;/div&gt;' );

 562           * alert( <b>element.getText()</b> );  // "Sample text."

 563           */
 564          getText : function()
 565          {
 566              return this.$.textContent || this.$.innerText || '';
 567          },
 568  
 569          /**

 570           * Gets the window object that contains this element.

 571           * @returns {CKEDITOR.dom.window} The window object.

 572           * @example

 573           */
 574          getWindow : function()
 575          {
 576              return this.getDocument().getWindow();
 577          },
 578  
 579          /**

 580           * Gets the value of the "id" attribute of this element.

 581           * @returns {String} The element id, or null if not available.

 582           * @example

 583           * var element = CKEDITOR.dom.element.createFromHtml( '&lt;p id="myId"&gt;&lt;/p&gt;' );

 584           * alert( <b>element.getId()</b> );  // "myId"

 585           */
 586          getId : function()
 587          {
 588              return this.$.id || null;
 589          },
 590  
 591          /**

 592           * Gets the value of the "name" attribute of this element.

 593           * @returns {String} The element name, or null if not available.

 594           * @example

 595           * var element = CKEDITOR.dom.element.createFromHtml( '&lt;input name="myName"&gt;&lt;/input&gt;' );

 596           * alert( <b>element.getNameAtt()</b> );  // "myName"

 597           */
 598          getNameAtt : function()
 599          {
 600              return this.$.name || null;
 601          },
 602  
 603          /**

 604           * Gets the element name (tag name). The returned name is guaranteed to

 605           * be always full lowercased.

 606           * @returns {String} The element name.

 607           * @example

 608           * var element = new CKEDITOR.dom.element( 'span' );

 609           * alert( <b>element.getName()</b> );  // "span"

 610           */
 611          getName : function()
 612          {
 613              // Cache the lowercased name inside a closure.

 614              var nodeName = this.$.nodeName.toLowerCase();
 615  
 616              if ( CKEDITOR.env.ie )
 617              {
 618                  var scopeName = this.$.scopeName;
 619                  if ( scopeName != 'HTML' )
 620                      nodeName = scopeName.toLowerCase() + ':' + nodeName;
 621              }
 622  
 623              return (
 624              this.getName = function()
 625                  {
 626                      return nodeName;
 627                  })();
 628          },
 629  
 630          /**

 631           * Gets the value set to this element. This value is usually available

 632           * for form field elements.

 633           * @returns {String} The element value.

 634           */
 635          getValue : function()
 636          {
 637              return this.$.value;
 638          },
 639  
 640          /**

 641           * Gets the first child node of this element.

 642           * @param {Function} evaluator Filtering the result node.

 643           * @returns {CKEDITOR.dom.node} The first child node or null if not

 644           *        available.

 645           * @example

 646           * var element = CKEDITOR.dom.element.createFromHtml( '&lt;div&gt;&lt;b&gt;Example&lt;/b&gt;&lt;/div&gt;' );

 647           * var first = <b>element.getFirst()</b>;

 648           * alert( first.getName() );  // "b"

 649           */
 650          getFirst : function( evaluator )
 651          {
 652              var first = this.$.firstChild,
 653                  retval = first && new CKEDITOR.dom.node( first );
 654              if ( retval && evaluator && !evaluator( retval ) )
 655                  retval = retval.getNext( evaluator );
 656  
 657              return retval;
 658          },
 659  
 660          /**

 661           * @param {Function} evaluator Filtering the result node.

 662           */
 663          getLast : function( evaluator )
 664          {
 665              var last = this.$.lastChild,
 666                  retval = last && new CKEDITOR.dom.node( last );
 667              if ( retval && evaluator && !evaluator( retval ) )
 668                  retval = retval.getPrevious( evaluator );
 669  
 670              return retval;
 671          },
 672  
 673          getStyle : function( name )
 674          {
 675              return this.$.style[ CKEDITOR.tools.cssStyleToDomStyle( name ) ];
 676          },
 677  
 678          /**

 679           * Checks if the element name matches one or more names.

 680           * @param {String} name[,name[,...]] One or more names to be checked.

 681           * @returns {Boolean} true if the element name matches any of the names.

 682           * @example

 683           * var element = new CKEDITOR.element( 'span' );

 684           * alert( <b>element.is( 'span' )</b> );  "true"

 685           * alert( <b>element.is( 'p', 'span' )</b> );  "true"

 686           * alert( <b>element.is( 'p' )</b> );  "false"

 687           * alert( <b>element.is( 'p', 'div' )</b> );  "false"

 688           */
 689          is : function()
 690          {
 691              var name = this.getName();
 692              for ( var i = 0 ; i < arguments.length ; i++ )
 693              {
 694                  if ( arguments[ i ] == name )
 695                      return true;
 696              }
 697              return false;
 698          },
 699  
 700          isEditable : function()
 701          {
 702              // Get the element name.

 703              var name = this.getName();
 704  
 705              // Get the element DTD (defaults to span for unknown elements).

 706              var dtd = !CKEDITOR.dtd.$nonEditable[ name ]
 707                          && ( CKEDITOR.dtd[ name ] || CKEDITOR.dtd.span );
 708  
 709              // In the DTD # == text node.

 710              return ( dtd && dtd['#'] );
 711          },
 712  
 713          isIdentical : function( otherElement )
 714          {
 715              if ( this.getName() != otherElement.getName() )
 716                  return false;
 717  
 718              var thisAttribs = this.$.attributes,
 719                  otherAttribs = otherElement.$.attributes;
 720  
 721              var thisLength = thisAttribs.length,
 722                  otherLength = otherAttribs.length;
 723  
 724              if ( !CKEDITOR.env.ie && thisLength != otherLength )
 725                  return false;
 726  
 727              for ( var i = 0 ; i < thisLength ; i++ )
 728              {
 729                  var attribute = thisAttribs[ i ];
 730  
 731                  if ( ( !CKEDITOR.env.ie || ( attribute.specified && attribute.nodeName != '_cke_expando' ) ) && attribute.nodeValue != otherElement.getAttribute( attribute.nodeName ) )
 732                      return false;
 733              }
 734  
 735              // For IE, we have to for both elements, because it's difficult to

 736              // know how the atttibutes collection is organized in its DOM.

 737              if ( CKEDITOR.env.ie )
 738              {
 739                  for ( i = 0 ; i < otherLength ; i++ )
 740                  {
 741                      attribute = otherAttribs[ i ];
 742                      if ( attribute.specified && attribute.nodeName != '_cke_expando'
 743                              && attribute.nodeValue != this.getAttribute( attribute.nodeName ) )
 744                          return false;
 745                  }
 746              }
 747  
 748              return true;
 749          },
 750  
 751          /**

 752           * Checks if this element is visible. May not work if the element is

 753           * child of an element with visibility set to "hidden", but works well

 754           * on the great majority of cases.

 755           * @return {Boolean} True if the element is visible.

 756           */
 757          isVisible : function()
 758          {
 759              var isVisible = !!this.$.offsetHeight && this.getComputedStyle( 'visibility' ) != 'hidden',
 760                  elementWindow,
 761                  elementWindowFrame;
 762  
 763              // Webkit and Opera report non-zero offsetHeight despite that

 764              // element is inside an invisible iframe. (#4542)

 765              if ( isVisible && ( CKEDITOR.env.webkit || CKEDITOR.env.opera ) )
 766              {
 767                  elementWindow = this.getWindow();
 768  
 769                  if ( !elementWindow.equals( CKEDITOR.document.getWindow() )
 770                          && ( elementWindowFrame = elementWindow.$.frameElement ) )
 771                  {
 772                      isVisible = new CKEDITOR.dom.element( elementWindowFrame ).isVisible();
 773                  }
 774              }
 775  
 776              return isVisible;
 777          },
 778  
 779          /**

 780           * Whether it's an empty inline elements which has no visual impact when removed.

 781           */
 782          isEmptyInlineRemoveable : function()
 783          {
 784              if ( !CKEDITOR.dtd.$removeEmpty[ this.getName() ] )
 785                  return false;
 786  
 787              var children = this.getChildren();
 788              for ( var i = 0, count = children.count(); i < count; i++ )
 789              {
 790                  var child = children.getItem( i );
 791  
 792                  if ( child.type == CKEDITOR.NODE_ELEMENT && child.getAttribute( '_fck_bookmark' ) )
 793                      continue;
 794  
 795                  if ( child.type == CKEDITOR.NODE_ELEMENT && !child.isEmptyInlineRemoveable()
 796                      || child.type == CKEDITOR.NODE_TEXT && CKEDITOR.tools.trim( child.getText() ) )
 797                  {
 798                      return false;
 799                  }
 800              }
 801              return true;
 802          },
 803  
 804          /**

 805           * Indicates that the element has defined attributes.

 806           * @returns {Boolean} True if the element has attributes.

 807           * @example

 808           * var element = CKEDITOR.dom.element.createFromHtml( '<div title="Test">Example</div>' );

 809           * alert( <b>element.hasAttributes()</b> );  "true"

 810           * @example

 811           * var element = CKEDITOR.dom.element.createFromHtml( '<div>Example</div>' );

 812           * alert( <b>element.hasAttributes()</b> );  "false"

 813           */
 814          hasAttributes :
 815              CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) ?
 816                  function()
 817                  {
 818                      var attributes = this.$.attributes;
 819  
 820                      for ( var i = 0 ; i < attributes.length ; i++ )
 821                      {
 822                          var attribute = attributes[i];
 823  
 824                          switch ( attribute.nodeName )
 825                          {
 826                              case 'class' :
 827                                  // IE has a strange bug. If calling removeAttribute('className'),

 828                                  // the attributes collection will still contain the "class"

 829                                  // attribute, which will be marked as "specified", even if the

 830                                  // outerHTML of the element is not displaying the class attribute.

 831                                  // Note : I was not able to reproduce it outside the editor,

 832                                  // but I've faced it while working on the TC of #1391.

 833                                  if ( this.getAttribute( 'class' ) )
 834                                      return true;
 835  
 836                              // Attributes to be ignored.

 837                              case '_cke_expando' :
 838                                  continue;
 839  
 840                              /*jsl:fallthru*/

 841  
 842                              default :
 843                                  if ( attribute.specified )
 844                                      return true;
 845                          }
 846                      }
 847  
 848                      return false;
 849                  }
 850              :
 851                  function()
 852                  {
 853                      var attrs = this.$.attributes,
 854                          attrsNum = attrs.length;
 855  
 856                      // The _moz_dirty attribute might get into the element after pasting (#5455)

 857                      var execludeAttrs = { _cke_expando : 1, _moz_dirty : 1 };
 858  
 859                      return attrsNum > 0 &&
 860                          ( attrsNum > 2 ||
 861                              !execludeAttrs[ attrs[0].nodeName ] ||
 862                              ( attrsNum == 2 && !execludeAttrs[ attrs[1].nodeName ] ) );
 863                  },
 864  
 865          /**

 866           * Indicates whether a specified attribute is defined for this element.

 867           * @returns {Boolean} True if the specified attribute is defined.

 868           * @param (String) name The attribute name.

 869           * @example

 870           */
 871          hasAttribute : function( name )
 872          {
 873              var $attr = this.$.attributes.getNamedItem( name );
 874              return !!( $attr && $attr.specified );
 875          },
 876  
 877          /**

 878           * Hides this element (display:none).

 879           * @example

 880           * var element = CKEDITOR.dom.element.getById( 'myElement' );

 881           * <b>element.hide()</b>;

 882           */
 883          hide : function()
 884          {
 885              this.setStyle( 'display', 'none' );
 886          },
 887  
 888          moveChildren : function( target, toStart )
 889          {
 890              var $ = this.$;
 891              target = target.$;
 892  
 893              if ( $ == target )
 894                  return;
 895  
 896              var child;
 897  
 898              if ( toStart )
 899              {
 900                  while ( ( child = $.lastChild ) )
 901                      target.insertBefore( $.removeChild( child ), target.firstChild );
 902              }
 903              else
 904              {
 905                  while ( ( child = $.firstChild ) )
 906                      target.appendChild( $.removeChild( child ) );
 907              }
 908          },
 909  
 910          mergeSiblings : ( function()
 911          {
 912  			function mergeElements( element, sibling, isNext )
 913              {
 914                  if ( sibling && sibling.type == CKEDITOR.NODE_ELEMENT )
 915                  {
 916                      // Jumping over bookmark nodes and empty inline elements, e.g. <b><i></i></b>,

 917                      // queuing them to be moved later. (#5567)

 918                      var pendingNodes = [];
 919  
 920                      while ( sibling.getAttribute( '_fck_bookmark' )
 921                          || sibling.isEmptyInlineRemoveable() )
 922                      {
 923                          pendingNodes.push( sibling );
 924                          sibling = isNext ? sibling.getNext() : sibling.getPrevious();
 925                          if ( !sibling || sibling.type != CKEDITOR.NODE_ELEMENT )
 926                              return;
 927                      }
 928  
 929                      if ( element.isIdentical( sibling ) )
 930                      {
 931                          // Save the last child to be checked too, to merge things like

 932                          // <b><i></i></b><b><i></i></b> => <b><i></i></b>

 933                          var innerSibling = isNext ? element.getLast() : element.getFirst();
 934  
 935                          // Move pending nodes first into the target element.

 936                          while( pendingNodes.length )
 937                              pendingNodes.shift().move( element, !isNext );
 938  
 939                          sibling.moveChildren( element, !isNext );
 940                          sibling.remove();
 941  
 942                          // Now check the last inner child (see two comments above).

 943                          if ( innerSibling && innerSibling.type == CKEDITOR.NODE_ELEMENT )
 944                              innerSibling.mergeSiblings();
 945                      }
 946                  }
 947              }
 948  
 949              return function()
 950                  {
 951                      // Merge empty links and anchors also. (#5567)

 952                      if ( !( CKEDITOR.dtd.$removeEmpty[ this.getName() ] || this.is( 'a' ) ) )
 953                          return;
 954  
 955                      mergeElements( this, this.getNext(), true );
 956                      mergeElements( this, this.getPrevious() );
 957                  };
 958          } )(),
 959  
 960          /**

 961           * Shows this element (display it).

 962           * @example

 963           * var element = CKEDITOR.dom.element.getById( 'myElement' );

 964           * <b>element.show()</b>;

 965           */
 966          show : function()
 967          {
 968              this.setStyles(
 969                  {
 970                      display : '',
 971                      visibility : ''
 972                  });
 973          },
 974  
 975          /**

 976           * Sets the value of an element attribute.

 977           * @param {String} name The name of the attribute.

 978           * @param {String} value The value to be set to the attribute.

 979           * @function

 980           * @returns {CKEDITOR.dom.element} This element instance.

 981           * @example

 982           * var element = CKEDITOR.dom.element.getById( 'myElement' );

 983           * <b>element.setAttribute( 'class', 'myClass' )</b>;

 984           * <b>element.setAttribute( 'title', 'This is an example' )</b>;

 985           */
 986          setAttribute : (function()
 987          {
 988              var standard = function( name, value )
 989              {
 990                  this.$.setAttribute( name, value );
 991                  return this;
 992              };
 993  
 994              if ( CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) )
 995              {
 996                  return function( name, value )
 997                  {
 998                      if ( name == 'class' )
 999                          this.$.className = value;
1000                      else if ( name == 'style' )
1001                          this.$.style.cssText = value;
1002                      else if ( name == 'tabindex' )    // Case sensitive.
1003                          this.$.tabIndex = value;
1004                      else if ( name == 'checked' )
1005                          this.$.checked = value;
1006                      else
1007                          standard.apply( this, arguments );
1008                      return this;
1009                  };
1010              }
1011              else
1012                  return standard;
1013          })(),
1014  
1015          /**

1016           * Sets the value of several element attributes.

1017           * @param {Object} attributesPairs An object containing the names and

1018           *        values of the attributes.

1019           * @returns {CKEDITOR.dom.element} This element instance.

1020           * @example

1021           * var element = CKEDITOR.dom.element.getById( 'myElement' );

1022           * <b>element.setAttributes({

1023           *     'class' : 'myClass',

1024           *     'title' : 'This is an example' })</b>;

1025           */
1026          setAttributes : function( attributesPairs )
1027          {
1028              for ( var name in attributesPairs )
1029                  this.setAttribute( name, attributesPairs[ name ] );
1030              return this;
1031          },
1032  
1033          /**

1034           * Sets the element value. This function is usually used with form

1035           * field element.

1036           * @param {String} value The element value.

1037           * @returns {CKEDITOR.dom.element} This element instance.

1038           */
1039          setValue : function( value )
1040          {
1041              this.$.value = value;
1042              return this;
1043          },
1044  
1045          /**

1046           * Removes an attribute from the element.

1047           * @param {String} name The attribute name.

1048           * @function

1049           * @example

1050           * var element = CKEDITOR.dom.element.createFromHtml( '<div class="classA"></div>' );

1051           * element.removeAttribute( 'class' );

1052           */
1053          removeAttribute : (function()
1054          {
1055              var standard = function( name )
1056              {
1057                  this.$.removeAttribute( name );
1058              };
1059  
1060              if ( CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.ie6Compat ) )
1061              {
1062                  return function( name )
1063                  {
1064                      if ( name == 'class' )
1065                          name = 'className';
1066                      else if ( name == 'tabindex' )
1067                          name = 'tabIndex';
1068                      standard.call( this, name );
1069                  };
1070              }
1071              else
1072                  return standard;
1073          })(),
1074  
1075          removeAttributes : function ( attributes )
1076          {
1077              if ( CKEDITOR.tools.isArray( attributes ) )
1078              {
1079                  for ( var i = 0 ; i < attributes.length ; i++ )
1080                      this.removeAttribute( attributes[ i ] );
1081              }
1082              else
1083              {
1084                  for ( var attr in attributes )
1085                      attributes.hasOwnProperty( attr ) && this.removeAttribute( attr );
1086              }
1087          },
1088  
1089          /**

1090           * Removes a style from the element.

1091           * @param {String} name The style name.

1092           * @function

1093           * @example

1094           * var element = CKEDITOR.dom.element.createFromHtml( '<div style="display:none"></div>' );

1095           * element.removeStyle( 'display' );

1096           */
1097          removeStyle : function( name )
1098          {
1099              this.setStyle( name, '' );
1100              if ( this.$.style.removeAttribute )
1101                  this.$.style.removeAttribute( CKEDITOR.tools.cssStyleToDomStyle( name ) );
1102  
1103              if ( !this.$.style.cssText )
1104                  this.removeAttribute( 'style' );
1105          },
1106  
1107          /**

1108           * Sets the value of an element style.

1109           * @param {String} name The name of the style. The CSS naming notation

1110           *        must be used (e.g. "background-color").

1111           * @param {String} value The value to be set to the style.

1112           * @returns {CKEDITOR.dom.element} This element instance.

1113           * @example

1114           * var element = CKEDITOR.dom.element.getById( 'myElement' );

1115           * <b>element.setStyle( 'background-color', '#ff0000' )</b>;

1116           * <b>element.setStyle( 'margin-top', '10px' )</b>;

1117           * <b>element.setStyle( 'float', 'right' )</b>;

1118           */
1119          setStyle : function( name, value )
1120          {
1121              this.$.style[ CKEDITOR.tools.cssStyleToDomStyle( name ) ] = value;
1122              return this;
1123          },
1124  
1125          /**

1126           * Sets the value of several element styles.

1127           * @param {Object} stylesPairs An object containing the names and

1128           *        values of the styles.

1129           * @returns {CKEDITOR.dom.element} This element instance.

1130           * @example

1131           * var element = CKEDITOR.dom.element.getById( 'myElement' );

1132           * <b>element.setStyles({

1133           *     'position' : 'absolute',

1134           *     'float' : 'right' })</b>;

1135           */
1136          setStyles : function( stylesPairs )
1137          {
1138              for ( var name in stylesPairs )
1139                  this.setStyle( name, stylesPairs[ name ] );
1140              return this;
1141          },
1142  
1143          /**

1144           * Sets the opacity of an element.

1145           * @param {Number} opacity A number within the range [0.0, 1.0].

1146           * @example

1147           * var element = CKEDITOR.dom.element.getById( 'myElement' );

1148           * <b>element.setOpacity( 0.75 )</b>;

1149           */
1150          setOpacity : function( opacity )
1151          {
1152              if ( CKEDITOR.env.ie )
1153              {
1154                  opacity = Math.round( opacity * 100 );
1155                  this.setStyle( 'filter', opacity >= 100 ? '' : 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + opacity + ')' );
1156              }
1157              else
1158                  this.setStyle( 'opacity', opacity );
1159          },
1160  
1161          /**

1162           * Makes the element and its children unselectable.

1163           * @function

1164           * @example

1165           * var element = CKEDITOR.dom.element.getById( 'myElement' );

1166           * element.unselectable();

1167           */
1168          unselectable :
1169              CKEDITOR.env.gecko ?
1170                  function()
1171                  {
1172                      this.$.style.MozUserSelect = 'none';
1173                      this.on( 'dragstart', function (evt) { evt.data.preventDefault(); } );
1174                  }
1175              : CKEDITOR.env.webkit ?
1176                  function()
1177                  {
1178                      this.$.style.KhtmlUserSelect = 'none';
1179                      this.on( 'dragstart', function (evt) { evt.data.preventDefault(); } );
1180                  }
1181              :
1182                  function()
1183                  {
1184                      if ( CKEDITOR.env.ie || CKEDITOR.env.opera )
1185                      {
1186                          var element = this.$,
1187                              e,
1188                              i = 0;
1189  
1190                          element.unselectable = 'on';
1191  
1192                          while ( ( e = element.all[ i++ ] ) )
1193                          {
1194                              switch ( e.tagName.toLowerCase() )
1195                              {
1196                                  case 'iframe' :
1197                                  case 'textarea' :
1198                                  case 'input' :
1199                                  case 'select' :
1200                                      /* Ignore the above tags */

1201                                      break;
1202                                  default :
1203                                      e.unselectable = 'on';
1204                              }
1205                          }
1206                      }
1207                  },
1208  
1209          getPositionedAncestor : function()
1210          {
1211              var current = this;
1212              while ( current.getName() != 'html' )
1213              {
1214                  if ( current.getComputedStyle( 'position' ) != 'static' )
1215                      return current;
1216  
1217                  current = current.getParent();
1218              }
1219              return null;
1220          },
1221  
1222          getDocumentPosition : function( refDocument )
1223          {
1224              var x = 0, y = 0,
1225                  body = this.getDocument().getBody(),
1226                  quirks = this.getDocument().$.compatMode == 'BackCompat';
1227  
1228              var doc = this.getDocument();
1229  
1230              if ( document.documentElement[ "getBoundingClientRect" ] )
1231              {
1232                  var box  = this.$.getBoundingClientRect(),
1233                      $doc = doc.$,
1234                      $docElem = $doc.documentElement;
1235  
1236                  var clientTop = $docElem.clientTop || body.$.clientTop || 0,
1237                      clientLeft = $docElem.clientLeft || body.$.clientLeft || 0,
1238                      needAdjustScrollAndBorders = true;
1239  
1240                  /*

1241                   * #3804: getBoundingClientRect() works differently on IE and non-IE

1242                   * browsers, regarding scroll positions.

1243                   *

1244                   * On IE, the top position of the <html> element is always 0, no matter

1245                   * how much you scrolled down.

1246                   *

1247                   * On other browsers, the top position of the <html> element is negative

1248                   * scrollTop.

1249                   */
1250                  if ( CKEDITOR.env.ie )
1251                  {
1252                      var inDocElem = doc.getDocumentElement().contains( this ),
1253                          inBody = doc.getBody().contains( this );
1254  
1255                      needAdjustScrollAndBorders = ( quirks && inBody ) || ( !quirks && inDocElem );
1256                  }
1257  
1258                  if ( needAdjustScrollAndBorders )
1259                  {
1260                      x = box.left + ( !quirks && $docElem.scrollLeft || body.$.scrollLeft );
1261                      x -= clientLeft;
1262                      y = box.top  + ( !quirks && $docElem.scrollTop || body.$.scrollTop );
1263                      y -= clientTop;
1264                  }
1265              }
1266              else
1267               {
1268                  var current = this, previous = null, offsetParent;
1269                  while ( current && !( current.getName() == 'body' || current.getName() == 'html' ) )
1270                  {
1271                      x += current.$.offsetLeft - current.$.scrollLeft;
1272                      y += current.$.offsetTop - current.$.scrollTop;
1273  
1274                      // Opera includes clientTop|Left into offsetTop|Left.

1275                      if ( !current.equals( this ) )
1276                      {
1277                          x += ( current.$.clientLeft || 0 );
1278                          y += ( current.$.clientTop || 0 );
1279                      }
1280  
1281                      var scrollElement = previous;
1282                      while ( scrollElement && !scrollElement.equals( current ) )
1283                      {
1284                          x -= scrollElement.$.scrollLeft;
1285                          y -= scrollElement.$.scrollTop;
1286                          scrollElement = scrollElement.getParent();
1287                      }
1288  
1289                      previous = current;
1290                      current = ( offsetParent = current.$.offsetParent ) ?
1291                                new CKEDITOR.dom.element( offsetParent ) : null;
1292                  }
1293              }
1294  
1295              if ( refDocument )
1296              {
1297                  var currentWindow = this.getWindow(),
1298                      refWindow = refDocument.getWindow();
1299  
1300                  if ( !currentWindow.equals( refWindow ) && currentWindow.$.frameElement )
1301                  {
1302                      var iframePosition = ( new CKEDITOR.dom.element( currentWindow.$.frameElement ) ).getDocumentPosition( refDocument );
1303  
1304                      x += iframePosition.x;
1305                      y += iframePosition.y;
1306                  }
1307              }
1308  
1309              if ( !document.documentElement[ "getBoundingClientRect" ] )
1310              {
1311                  // In Firefox, we'll endup one pixel before the element positions,

1312                  // so we must add it here.

1313                  if ( CKEDITOR.env.gecko && !quirks )
1314                  {
1315                      x += this.$.clientLeft ? 1 : 0;
1316                      y += this.$.clientTop ? 1 : 0;
1317                  }
1318              }
1319  
1320              return { x : x, y : y };
1321          },
1322  
1323          scrollIntoView : function( alignTop )
1324          {
1325              // Get the element window.

1326              var win = this.getWindow(),
1327                  winHeight = win.getViewPaneSize().height;
1328  
1329              // Starts from the offset that will be scrolled with the negative value of

1330              // the visible window height.

1331              var offset = winHeight * -1;
1332  
1333              // Append the view pane's height if align to top.

1334              // Append element height if we are aligning to the bottom.

1335              if ( alignTop )
1336                  offset += winHeight;
1337              else
1338              {
1339                  offset += this.$.offsetHeight || 0;
1340  
1341                  // Consider the margin in the scroll, which is ok for our current needs, but

1342                  // needs investigation if we will be using this function in other places.

1343                  offset += parseInt( this.getComputedStyle( 'marginBottom' ) || 0, 10 ) || 0;
1344              }
1345  
1346              // Append the offsets for the entire element hierarchy.

1347              var elementPosition = this.getDocumentPosition();
1348              offset += elementPosition.y;
1349  
1350              // offset value might be out of range(nagative), fix it(#3692).

1351              offset = offset < 0 ? 0 : offset;
1352  
1353              // Scroll the window to the desired position, if not already visible(#3795).

1354              var currentScroll = win.getScrollPosition().y;
1355              if ( offset > currentScroll || offset < currentScroll - winHeight )
1356                  win.$.scrollTo( 0, offset );
1357          },
1358  
1359          setState : function( state )
1360          {
1361              switch ( state )
1362              {
1363                  case CKEDITOR.TRISTATE_ON :
1364                      this.addClass( 'cke_on' );
1365                      this.removeClass( 'cke_off' );
1366                      this.removeClass( 'cke_disabled' );
1367                      break;
1368                  case CKEDITOR.TRISTATE_DISABLED :
1369                      this.addClass( 'cke_disabled' );
1370                      this.removeClass( 'cke_off' );
1371                      this.removeClass( 'cke_on' );
1372                      break;
1373                  default :
1374                      this.addClass( 'cke_off' );
1375                      this.removeClass( 'cke_on' );
1376                      this.removeClass( 'cke_disabled' );
1377                      break;
1378              }
1379          },
1380  
1381          /**

1382           * Returns the inner document of this IFRAME element.

1383           * @returns {CKEDITOR.dom.document} The inner document.

1384           */
1385          getFrameDocument : function()
1386          {
1387              var $ = this.$;
1388  
1389              try
1390              {
1391                  // In IE, with custom document.domain, it may happen that

1392                  // the iframe is not yet available, resulting in "Access

1393                  // Denied" for the following property access.

1394                  $.contentWindow.document;
1395              }
1396              catch ( e )
1397              {
1398                  // Trick to solve this issue, forcing the iframe to get ready

1399                  // by simply setting its "src" property.

1400                  $.src = $.src;
1401  
1402                  // In IE6 though, the above is not enough, so we must pause the

1403                  // execution for a while, giving it time to think.

1404                  if ( CKEDITOR.env.ie && CKEDITOR.env.version < 7 )
1405                  {
1406                      window.showModalDialog(
1407                          'javascript:document.write("' +
1408                              '<script>' +
1409                                  'window.setTimeout(' +
1410                                      'function(){window.close();}' +
1411                                      ',50);' +
1412                              '</script>")' );
1413                  }
1414              }
1415  
1416              return $ && new CKEDITOR.dom.document( $.contentWindow.document );
1417          },
1418  
1419          /**

1420           * Copy all the attributes from one node to the other, kinda like a clone

1421           * skipAttributes is an object with the attributes that must NOT be copied.

1422           * @param {CKEDITOR.dom.element} dest The destination element.

1423           * @param {Object} skipAttributes A dictionary of attributes to skip.

1424           * @example

1425           */
1426          copyAttributes : function( dest, skipAttributes )
1427          {
1428              var attributes = this.$.attributes;
1429              skipAttributes = skipAttributes || {};
1430  
1431              for ( var n = 0 ; n < attributes.length ; n++ )
1432              {
1433                  var attribute = attributes[n];
1434  
1435                  // Lowercase attribute name hard rule is broken for

1436                  // some attribute on IE, e.g. CHECKED.

1437                  var attrName = attribute.nodeName.toLowerCase(),
1438                      attrValue;
1439  
1440                  // We can set the type only once, so do it with the proper value, not copying it.

1441                  if ( attrName in skipAttributes )
1442                      continue;
1443  
1444                  if ( attrName == 'checked' && ( attrValue = this.getAttribute( attrName ) ) )
1445                      dest.setAttribute( attrName, attrValue );
1446                  // IE BUG: value attribute is never specified even if it exists.

1447                  else if ( attribute.specified ||
1448                    ( CKEDITOR.env.ie && attribute.nodeValue && attrName == 'value' ) )
1449                  {
1450                      attrValue = this.getAttribute( attrName );
1451                      if ( attrValue === null )
1452                          attrValue = attribute.nodeValue;
1453  
1454                      dest.setAttribute( attrName, attrValue );
1455                  }
1456              }
1457  
1458              // The style:

1459              if ( this.$.style.cssText !== '' )
1460                  dest.$.style.cssText = this.$.style.cssText;
1461          },
1462  
1463          /**

1464           * Changes the tag name of the current element.

1465           * @param {String} newTag The new tag for the element.

1466           */
1467          renameNode : function( newTag )
1468          {
1469              // If it's already correct exit here.

1470              if ( this.getName() == newTag )
1471                  return;
1472  
1473              var doc = this.getDocument();
1474  
1475              // Create the new node.

1476              var newNode = new CKEDITOR.dom.element( newTag, doc );
1477  
1478              // Copy all attributes.

1479              this.copyAttributes( newNode );
1480  
1481              // Move children to the new node.

1482              this.moveChildren( newNode );
1483  
1484              // Replace the node.

1485              this.getParent() && this.$.parentNode.replaceChild( newNode.$, this.$ );
1486              newNode.$._cke_expando = this.$._cke_expando;
1487              this.$ = newNode.$;
1488          },
1489  
1490          /**

1491           * Gets a DOM tree descendant under the current node.

1492           * @param {Array|Number} indices The child index or array of child indices under the node.

1493           * @returns {CKEDITOR.dom.node} The specified DOM child under the current node. Null if child does not exist.

1494           * @example

1495           * var strong = p.getChild(0);

1496           */
1497          getChild : function( indices )
1498          {
1499              var rawNode = this.$;
1500  
1501              if ( !indices.slice )
1502                  rawNode = rawNode.childNodes[ indices ];
1503              else
1504              {
1505                  while ( indices.length > 0 && rawNode )
1506                      rawNode = rawNode.childNodes[ indices.shift() ];
1507              }
1508  
1509              return rawNode ? new CKEDITOR.dom.node( rawNode ) : null;
1510          },
1511  
1512          getChildCount : function()
1513          {
1514              return this.$.childNodes.length;
1515           },
1516  
1517          disableContextMenu : function()
1518          {
1519              this.on( 'contextmenu', function( event )
1520                  {
1521                      // Cancel the browser context menu.

1522                      if ( !event.data.getTarget().hasClass( 'cke_enable_context_menu' ) )
1523                          event.data.preventDefault();
1524                  } );
1525          }
1526      });


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7