[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/libraries/ckeditor/_source/plugins/wysiwygarea/ -> plugin.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 The "wysiwygarea" plugin. It registers the "wysiwyg" editing

   8   *        mode, which handles the main editing area space.

   9   */
  10  
  11  (function()
  12  {
  13      // List of elements in which has no way to move editing focus outside.

  14      var nonExitableElementNames = { table:1,pre:1 };
  15  
  16      // Matching an empty paragraph at the end of document.

  17      var emptyParagraphRegexp = /\s*<(p|div|address|h\d|center|li)[^>]*>\s*(?:<br[^>]*>|&nbsp;|\u00A0|&#160;)?\s*(:?<\/\1>)?\s*(?=$|<\/body>)/gi;
  18  
  19      var notWhitespaceEval = CKEDITOR.dom.walker.whitespaces( true );
  20  
  21  	function checkReadOnly( selection )
  22      {
  23          if ( selection.getType() == CKEDITOR.SELECTION_ELEMENT )
  24              return selection.getSelectedElement().isReadOnly();
  25          else
  26              return selection.getCommonAncestor().isReadOnly();
  27      }
  28  
  29  	function onInsertHtml( evt )
  30      {
  31          if ( this.mode == 'wysiwyg' )
  32          {
  33              this.focus();
  34  
  35              var selection = this.getSelection();
  36              if ( checkReadOnly( selection ) )
  37                  return;
  38  
  39              var data = evt.data;
  40              this.fire( 'saveSnapshot' );
  41  
  42              if ( this.dataProcessor )
  43                  data = this.dataProcessor.toHtml( data );
  44  
  45              if ( CKEDITOR.env.ie )
  46              {
  47                  var selIsLocked = selection.isLocked;
  48  
  49                  if ( selIsLocked )
  50                      selection.unlock();
  51  
  52                  var $sel = selection.getNative();
  53  
  54                  // Delete control selections to avoid IE bugs on pasteHTML.

  55                  if ( $sel.type == 'Control' )
  56                      $sel.clear();
  57                  else if  ( selection.getType() == CKEDITOR.SELECTION_TEXT )
  58                  {
  59                      // Due to IE bugs on handling contenteditable=false blocks

  60                      // (#6005), we need to make some checks and eventually

  61                      // delete the selection first.

  62  
  63                      var range = selection.getRanges()[0],
  64                          endContainer = range && range.endContainer;
  65  
  66                      if ( endContainer &&
  67                            endContainer.type == CKEDITOR.NODE_ELEMENT &&
  68                            endContainer.getAttribute( 'contenteditable' ) == 'false' &&
  69                           range.checkBoundaryOfElement( endContainer, CKEDITOR.END ) )
  70                      {
  71                          range.setEndAfter( range.endContainer );
  72                          range.deleteContents();
  73                      }
  74                  }
  75  
  76                  $sel.createRange().pasteHTML( data );
  77  
  78                  if ( selIsLocked )
  79                      this.getSelection().lock();
  80              }
  81              else
  82                  this.document.$.execCommand( 'inserthtml', false, data );
  83  
  84              // Webkit does not scroll to the cursor position after pasting (#5558)

  85              if ( CKEDITOR.env.webkit )
  86              {
  87                  this.document.$.execCommand( 'inserthtml', false, '<span id="cke_paste_marker" cke_temp="1"></span>' );
  88                  var marker = this.document.getById( 'cke_paste_marker' );
  89                  marker.scrollIntoView();
  90                  marker.remove();
  91              }
  92  
  93              CKEDITOR.tools.setTimeout( function()
  94                  {
  95                      this.fire( 'saveSnapshot' );
  96                  }, 0, this );
  97          }
  98      }
  99  
 100  	function onInsertElement( evt )
 101      {
 102          if ( this.mode == 'wysiwyg' )
 103          {
 104              this.focus();
 105  
 106              var selection = this.getSelection();
 107              if ( checkReadOnly( selection ) )
 108                  return;
 109  
 110              this.fire( 'saveSnapshot' );
 111  
 112              var ranges = selection.getRanges(),
 113                  element = evt.data,
 114                  elementName = element.getName(),
 115                  isBlock = CKEDITOR.dtd.$block[ elementName ];
 116  
 117              var selIsLocked = selection.isLocked;
 118  
 119              if ( selIsLocked )
 120                  selection.unlock();
 121  
 122              var range, clone, lastElement, bookmark;
 123  
 124              for ( var i = ranges.length - 1 ; i >= 0 ; i-- )
 125              {
 126                  range = ranges[ i ];
 127  
 128                  // Remove the original contents.

 129                  range.deleteContents();
 130  
 131                  clone = !i && element || element.clone( true );
 132  
 133                  // If we're inserting a block at dtd-violated position, split

 134                  // the parent blocks until we reach blockLimit.

 135                  var current, dtd;
 136                  if ( isBlock )
 137                  {
 138                      while ( ( current = range.getCommonAncestor( false, true ) )
 139                              && ( dtd = CKEDITOR.dtd[ current.getName() ] )
 140                              && !( dtd && dtd [ elementName ] ) )
 141                      {
 142                          // Split up inline elements.

 143                          if ( current.getName() in CKEDITOR.dtd.span )
 144                              range.splitElement( current );
 145                          // If we're in an empty block which indicate a new paragraph,

 146                          // simply replace it with the inserting block.(#3664)

 147                          else if ( range.checkStartOfBlock()
 148                               && range.checkEndOfBlock() )
 149                          {
 150                              range.setStartBefore( current );
 151                              range.collapse( true );
 152                              current.remove();
 153                          }
 154                          else
 155                              range.splitBlock();
 156                      }
 157                  }
 158  
 159                  // Insert the new node.

 160                  range.insertNode( clone );
 161  
 162                  // Save the last element reference so we can make the

 163                  // selection later.

 164                  if ( !lastElement )
 165                      lastElement = clone;
 166              }
 167  
 168              range.moveToPosition( lastElement, CKEDITOR.POSITION_AFTER_END );
 169  
 170              // If we're inserting a block element immediatelly followed by

 171              // another block element, the selection must move there. (#3100,#5436)

 172              if ( isBlock )
 173              {
 174                  var next = lastElement.getNext( notWhitespaceEval ),
 175                      nextName = next && next.type == CKEDITOR.NODE_ELEMENT && next.getName();
 176  
 177                  // Check if it's a block element that accepts text.

 178                  if ( nextName && CKEDITOR.dtd.$block[ nextName ] && CKEDITOR.dtd[ nextName ]['#'] )
 179                      range.moveToElementEditStart( next );
 180              }
 181  
 182              selection.selectRanges( [ range ] );
 183  
 184              if ( selIsLocked )
 185                  this.getSelection().lock();
 186  
 187              // Save snaps after the whole execution completed.

 188              // This's a workaround for make DOM modification's happened after

 189              // 'insertElement' to be included either, e.g. Form-based dialogs' 'commitContents'

 190              // call.

 191              CKEDITOR.tools.setTimeout( function(){
 192                  this.fire( 'saveSnapshot' );
 193              }, 0, this );
 194          }
 195      }
 196  
 197      // DOM modification here should not bother dirty flag.(#4385)

 198  	function restoreDirty( editor )
 199      {
 200          if ( !editor.checkDirty() )
 201              setTimeout( function(){ editor.resetDirty(); } );
 202      }
 203  
 204      var isNotWhitespace = CKEDITOR.dom.walker.whitespaces( true ),
 205          isNotBookmark = CKEDITOR.dom.walker.bookmark( false, true );
 206  
 207  	function isNotEmpty( node )
 208      {
 209          return isNotWhitespace( node ) && isNotBookmark( node );
 210      }
 211  
 212  	function isNbsp( node )
 213      {
 214          return node.type == CKEDITOR.NODE_TEXT
 215                 && CKEDITOR.tools.trim( node.getText() ).match( /^(?:&nbsp;|\xa0)$/ );
 216      }
 217  
 218  	function restoreSelection( selection )
 219      {
 220          if ( selection.isLocked )
 221          {
 222              selection.unlock();
 223              setTimeout( function() { selection.lock(); }, 0 );
 224          }
 225      }
 226  
 227  	function isBlankParagraph( block )
 228      {
 229          return block.getOuterHtml().match( emptyParagraphRegexp );
 230      }
 231  
 232      isNotWhitespace = CKEDITOR.dom.walker.whitespaces( true );
 233  
 234      // Gecko need a key event to 'wake up' the editing

 235      // ability when document is empty.(#3864, #5781)

 236  	function activateEditing( editor )
 237      {
 238          var win = editor.window,
 239              doc = editor.document,
 240              body = editor.document.getBody(),
 241              bodyChildsNum = body.getChildren().count();
 242  
 243          if ( !bodyChildsNum || ( bodyChildsNum == 1&& body.getFirst().hasAttribute( '_moz_editor_bogus_node' ) ) )
 244          {
 245              restoreDirty( editor );
 246  
 247              // Simulating keyboard character input by dispatching a keydown of white-space text.

 248              var keyEventSimulate = doc.$.createEvent( "KeyEvents" );
 249              keyEventSimulate.initKeyEvent( 'keypress', true, true, win.$, false,
 250                  false, false, false, 0, 32 );
 251              doc.$.dispatchEvent( keyEventSimulate );
 252  
 253              // Restore the original document status by placing the cursor before a bogus br created (#5021).

 254              bodyChildsNum && body.getFirst().remove();
 255              doc.getBody().appendBogus();
 256              var nativeRange = new CKEDITOR.dom.range( doc );
 257              nativeRange.setStartAt( body , CKEDITOR.POSITION_AFTER_START );
 258              nativeRange.select();
 259          }
 260      }
 261  
 262      /**

 263       *  Auto-fixing block-less content by wrapping paragraph (#3190), prevent

 264       *  non-exitable-block by padding extra br.(#3189)

 265       */
 266  	function onSelectionChangeFixBody( evt )
 267      {
 268          var editor = evt.editor,
 269              path = evt.data.path,
 270              blockLimit = path.blockLimit,
 271              selection = evt.data.selection,
 272              range = selection.getRanges()[0],
 273              body = editor.document.getBody(),
 274              enterMode = editor.config.enterMode;
 275  
 276          CKEDITOR.env.gecko && activateEditing( editor );
 277  
 278          // When enterMode set to block, we'll establing new paragraph only if we're

 279          // selecting inline contents right under body. (#3657)

 280          if ( enterMode != CKEDITOR.ENTER_BR
 281               && range.collapsed
 282               && blockLimit.getName() == 'body'
 283               && !path.block )
 284          {
 285              editor.fire( 'updateSnapshot' );
 286              restoreDirty( editor );
 287              CKEDITOR.env.ie && restoreSelection( selection );
 288  
 289              var fixedBlock = range.fixBlock( true,
 290                      editor.config.enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p'  );
 291  
 292              // For IE, we should remove any filler node which was introduced before.

 293              if ( CKEDITOR.env.ie )
 294              {
 295                  var first = fixedBlock.getFirst( isNotEmpty );
 296                  first && isNbsp( first ) && first.remove();
 297              }
 298  
 299              // If the fixed block is actually blank and is already followed by an exitable blank

 300              // block, we should revert the fix and move into the existed one. (#3684)

 301              if ( isBlankParagraph( fixedBlock ) )
 302              {
 303                  var element = fixedBlock.getNext( isNotWhitespace );
 304                  if ( element &&
 305                       element.type == CKEDITOR.NODE_ELEMENT &&
 306                       !nonExitableElementNames[ element.getName() ] )
 307                  {
 308                      range.moveToElementEditStart( element );
 309                      fixedBlock.remove();
 310                  }
 311                  else
 312                  {
 313                      element = fixedBlock.getPrevious( isNotWhitespace );
 314                      if ( element &&
 315                           element.type == CKEDITOR.NODE_ELEMENT &&
 316                           !nonExitableElementNames[ element.getName() ] )
 317                      {
 318                          range.moveToElementEditEnd( element );
 319                          fixedBlock.remove();
 320                      }
 321                  }
 322              }
 323  
 324              range.select();
 325              // Notify non-IE that selection has changed.

 326              if ( !CKEDITOR.env.ie )
 327                  editor.selectionChange();
 328          }
 329  
 330          // All browsers are incapable to moving cursor out of certain non-exitable

 331          // blocks (e.g. table, list, pre) at the end of document, make this happen by

 332          // place a bogus node there, which would be later removed by dataprocessor.

 333          var walkerRange = new CKEDITOR.dom.range( editor.document ),
 334              walker = new CKEDITOR.dom.walker( walkerRange );
 335          walkerRange.selectNodeContents( body );
 336          walker.evaluator = function( node )
 337          {
 338              return node.type == CKEDITOR.NODE_ELEMENT && ( node.getName() in nonExitableElementNames );
 339          };
 340          walker.guard = function( node, isMoveout )
 341          {
 342              return !( ( node.type == CKEDITOR.NODE_TEXT && isNotWhitespace( node ) ) || isMoveout );
 343          };
 344  
 345          if ( walker.previous() )
 346          {
 347              editor.fire( 'updateSnapshot' );
 348              restoreDirty( editor );
 349              CKEDITOR.env.ie && restoreSelection( selection );
 350  
 351              var paddingBlock;
 352              if ( enterMode != CKEDITOR.ENTER_BR )
 353                  paddingBlock = body.append( new CKEDITOR.dom.element( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) );
 354              else
 355                  paddingBlock = body;
 356  
 357              if ( !CKEDITOR.env.ie )
 358                  paddingBlock.appendBogus();
 359          }
 360      }
 361  
 362      CKEDITOR.plugins.add( 'wysiwygarea',
 363      {
 364          requires : [ 'editingblock' ],
 365  
 366          init : function( editor )
 367          {
 368              var fixForBody = ( editor.config.enterMode != CKEDITOR.ENTER_BR )
 369                  ? editor.config.enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p' : false;
 370  
 371              var frameLabel = editor.lang.editorTitle.replace( '%1', editor.name );
 372  
 373              var contentDomReadyHandler;
 374              editor.on( 'editingBlockReady', function()
 375                  {
 376                      var mainElement,
 377                          iframe,
 378                          isLoadingData,
 379                          isPendingFocus,
 380                          frameLoaded,
 381                          fireMode;
 382  
 383  
 384                      // Support for custom document.domain in IE.

 385                      var isCustomDomain = CKEDITOR.env.isCustomDomain();
 386  
 387                      // Creates the iframe that holds the editable document.

 388                      var createIFrame = function( data )
 389                      {
 390                          if ( iframe )
 391                              iframe.remove();
 392  
 393  
 394                          var srcScript =
 395                              'document.open();' +
 396  
 397                              // The document domain must be set any time we

 398                              // call document.open().

 399                              ( isCustomDomain ? ( 'document.domain="' + document.domain + '";' ) : '' ) +
 400  
 401                              'document.close();';
 402  
 403                          iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' +
 404                                ' style="width:100%;height:100%"' +
 405                                ' frameBorder="0"' +
 406                                ' title="' + frameLabel + '"' +
 407                              // With IE, the custom domain has to be taken care at first,

 408                              // for other browers, the 'src' attribute should be left empty to

 409                              // trigger iframe's 'load' event.

 410                                ' src="' + ( CKEDITOR.env.ie ? 'javascript:void(function(){' + encodeURIComponent( srcScript ) + '}())' : '' ) + '"' +
 411                              ' tabIndex="' + ( CKEDITOR.env.webkit? -1 : editor.tabIndex ) + '"' +
 412                                ' allowTransparency="true"' +
 413                                '></iframe>' );
 414  
 415                          // #5689 Running inside of Firefox chrome the load event doesn't bubble like in a normal page

 416                          if (document.location.protocol == 'chrome:')
 417                              CKEDITOR.event.useCapture = true;
 418  
 419                          // With FF, it's better to load the data on iframe.load. (#3894,#4058)

 420                          iframe.on( 'load', function( ev )
 421                              {
 422                                  frameLoaded = 1;
 423                                  ev.removeListener();
 424  
 425                                  var doc = iframe.getFrameDocument().$;
 426  
 427                                  // Don't leave any history log in IE. (#5657)

 428                                  doc.open( "text/html","replace" );
 429                                  doc.write( data );
 430                                  doc.close();
 431                              });
 432  
 433                          // #5689 Reset adjustment back to default

 434                          if (document.location.protocol == 'chrome:')
 435                              CKEDITOR.event.useCapture = false;
 436  
 437                          mainElement.append( iframe );
 438                      };
 439  
 440                      // The script that launches the bootstrap logic on 'domReady', so the document

 441                      // is fully editable even before the editing iframe is fully loaded (#4455).

 442                      contentDomReadyHandler = CKEDITOR.tools.addFunction( contentDomReady );
 443                      var activationScript =
 444                          '<script id="cke_actscrpt" type="text/javascript" cke_temp="1">' +
 445                              ( isCustomDomain ? ( 'document.domain="' + document.domain + '";' ) : '' ) +
 446                              'window.parent.CKEDITOR.tools.callFunction( ' + contentDomReadyHandler + ', window );' +
 447                          '</script>';
 448  
 449                      // Editing area bootstrap code.

 450  					function contentDomReady( domWindow )
 451                      {
 452                          if ( !frameLoaded )
 453                              return;
 454                          frameLoaded = 0;
 455  
 456                          editor.fire( 'ariaWidget', iframe );
 457  
 458                          var domDocument = domWindow.document,
 459                              body = domDocument.body;
 460  
 461                          // Remove this script from the DOM.

 462                          var script = domDocument.getElementById( "cke_actscrpt" );
 463                          script.parentNode.removeChild( script );
 464  
 465                          body.spellcheck = !editor.config.disableNativeSpellChecker;
 466  
 467                          if ( CKEDITOR.env.ie )
 468                          {
 469                              // Don't display the focus border.

 470                              body.hideFocus = true;
 471  
 472                              // Disable and re-enable the body to avoid IE from

 473                              // taking the editing focus at startup. (#141 / #523)

 474                              body.disabled = true;
 475                              body.contentEditable = true;
 476                              body.removeAttribute( 'disabled' );
 477                          }
 478                          else
 479                          {
 480                              // Avoid opening design mode in a frame window thread,

 481                              // which will cause host page scrolling.(#4397)

 482                              setTimeout( function()
 483                              {
 484                                  // Prefer 'contentEditable' instead of 'designMode'. (#3593)

 485                                  if ( CKEDITOR.env.gecko && CKEDITOR.env.version >= 10900
 486                                          || CKEDITOR.env.opera )
 487                                      domDocument.$.body.contentEditable = true;
 488                                  else if ( CKEDITOR.env.webkit )
 489                                      domDocument.$.body.parentNode.contentEditable = true;
 490                                  else
 491                                      domDocument.$.designMode = 'on';
 492                              }, 0 );
 493                          }
 494  
 495                          CKEDITOR.env.gecko && CKEDITOR.tools.setTimeout( activateEditing, 0, null, editor );
 496  
 497                          domWindow    = editor.window        = new CKEDITOR.dom.window( domWindow );
 498                          domDocument    = editor.document    = new CKEDITOR.dom.document( domDocument );
 499  
 500                          domDocument.on( 'dblclick', function( evt )
 501                          {
 502                              var element = evt.data.getTarget(),
 503                                  data = { element : element, dialog : '' };
 504                              editor.fire( 'doubleclick', data );
 505                              data.dialog && editor.openDialog( data.dialog );
 506                          });
 507  
 508                          // Gecko/Webkit need some help when selecting control type elements. (#3448)

 509                          if ( !( CKEDITOR.env.ie || CKEDITOR.env.opera) )
 510                          {
 511                              domDocument.on( 'mousedown', function( ev )
 512                              {
 513                                  var control = ev.data.getTarget();
 514                                  if ( control.is( 'img', 'hr', 'input', 'textarea', 'select' ) )
 515                                      editor.getSelection().selectElement( control );
 516                              } );
 517                          }
 518  
 519                          if ( CKEDITOR.env.gecko )
 520                          {
 521                              domDocument.on( 'mouseup', function( ev )
 522                              {
 523                                  if ( ev.data.$.button == 2 )
 524                                  {
 525                                      var target = ev.data.getTarget();
 526  
 527                                      // Prevent right click from selecting an empty block even

 528                                      // when selection is anchored inside it. (#5845)

 529                                      if ( !target.getOuterHtml().replace( emptyParagraphRegexp, '' ) )
 530                                      {
 531                                          var range = new CKEDITOR.dom.range( domDocument );
 532                                          range.moveToElementEditStart( target );
 533                                          range.select( true );
 534                                      }
 535                                  }
 536                              } );
 537                          }
 538  
 539                          // Prevent the browser opening links in read-only blocks. (#6032)

 540                          domDocument.on( 'click', function( ev )
 541                              {
 542                                  ev = ev.data;
 543                                  if ( ev.getTarget().is( 'a' ) && ev.$.button != 2 )
 544                                      ev.preventDefault();
 545                              });
 546  
 547                          // Webkit: avoid from editing form control elements content.

 548                          if ( CKEDITOR.env.webkit )
 549                          {
 550                              // Prevent from tick checkbox/radiobox/select

 551                              domDocument.on( 'click', function( ev )
 552                              {
 553                                  if ( ev.data.getTarget().is( 'input', 'select' ) )
 554                                      ev.data.preventDefault();
 555                              } );
 556  
 557                              // Prevent from editig textfield/textarea value.

 558                              domDocument.on( 'mouseup', function( ev )
 559                              {
 560                                  if ( ev.data.getTarget().is( 'input', 'textarea' ) )
 561                                      ev.data.preventDefault();
 562                              } );
 563                          }
 564  
 565                          // IE standard compliant in editing frame doesn't focus the editor when

 566                          // clicking outside actual content, manually apply the focus. (#1659)

 567                          if ( CKEDITOR.env.ie
 568                              && domDocument.$.compatMode == 'CSS1Compat'
 569                                  || CKEDITOR.env.gecko
 570                                  || CKEDITOR.env.opera )
 571                          {
 572                              var htmlElement = domDocument.getDocumentElement();
 573                              htmlElement.on( 'mousedown', function( evt )
 574                              {
 575                                  // Setting focus directly on editor doesn't work, we

 576                                  // have to use here a temporary element to 'redirect'

 577                                  // the focus.

 578                                  if ( evt.data.getTarget().equals( htmlElement ) )
 579                                  {
 580                                      if ( CKEDITOR.env.gecko && CKEDITOR.env.version >= 10900 )
 581                                          blinkCursor();
 582                                      focusGrabber.focus();
 583                                  }
 584                              } );
 585                          }
 586  
 587                          domWindow.on( 'blur', function()
 588                              {
 589                                  editor.focusManager.blur();
 590                              });
 591  
 592                          domWindow.on( 'focus', function()
 593                              {
 594                                  var doc = editor.document;
 595  
 596                                  if ( CKEDITOR.env.gecko && CKEDITOR.env.version >= 10900 )
 597                                      blinkCursor();
 598                                  else if ( CKEDITOR.env.opera )
 599                                      doc.getBody().focus();
 600  
 601                                  editor.focusManager.focus();
 602                              });
 603  
 604                          var keystrokeHandler = editor.keystrokeHandler;
 605                          if ( keystrokeHandler )
 606                              keystrokeHandler.attach( domDocument );
 607  
 608                          if ( CKEDITOR.env.ie )
 609                          {
 610                              domDocument.getDocumentElement().addClass( domDocument.$.compatMode );
 611                              // Override keystrokes which should have deletion behavior

 612                              //  on control types in IE . (#4047)

 613                              domDocument.on( 'keydown', function( evt )
 614                              {
 615                                  var keyCode = evt.data.getKeystroke();
 616  
 617                                  // Backspace OR Delete.

 618                                  if ( keyCode in { 8 : 1, 46 : 1 } )
 619                                  {
 620                                      var sel = editor.getSelection(),
 621                                          control = sel.getSelectedElement();
 622  
 623                                      if ( control )
 624                                      {
 625                                          // Make undo snapshot.

 626                                          editor.fire( 'saveSnapshot' );
 627  
 628                                          // Delete any element that 'hasLayout' (e.g. hr,table) in IE8 will

 629                                          // break up the selection, safely manage it here. (#4795)

 630                                          var bookmark = sel.getRanges()[ 0 ].createBookmark();
 631                                          // Remove the control manually.

 632                                          control.remove();
 633                                          sel.selectBookmarks( [ bookmark ] );
 634  
 635                                          editor.fire( 'saveSnapshot' );
 636  
 637                                          evt.data.preventDefault();
 638                                      }
 639                                  }
 640                              } );
 641  
 642                              // PageUp/PageDown scrolling is broken in document

 643                              // with standard doctype, manually fix it. (#4736)

 644                              if ( domDocument.$.compatMode == 'CSS1Compat' )
 645                              {
 646                                  var pageUpDownKeys = { 33 : 1, 34 : 1 };
 647                                  domDocument.on( 'keydown', function( evt )
 648                                  {
 649                                      if ( evt.data.getKeystroke() in pageUpDownKeys )
 650                                      {
 651                                          setTimeout( function ()
 652                                          {
 653                                              editor.getSelection().scrollIntoView();
 654                                          }, 0 );
 655                                      }
 656                                  } );
 657                              }
 658                          }
 659  
 660                          // Adds the document body as a context menu target.

 661                          if ( editor.contextMenu )
 662                              editor.contextMenu.addTarget( domDocument, editor.config.browserContextMenuOnCtrl !== false );
 663  
 664                          setTimeout( function()
 665                              {
 666                                  editor.fire( 'contentDom' );
 667  
 668                                  if ( fireMode )
 669                                  {
 670                                      editor.mode = 'wysiwyg';
 671                                      editor.fire( 'mode' );
 672                                      fireMode = false;
 673                                  }
 674  
 675                                  isLoadingData = false;
 676  
 677                                  if ( isPendingFocus )
 678                                  {
 679                                      editor.focus();
 680                                      isPendingFocus = false;
 681                                  }
 682                                  setTimeout( function()
 683                                  {
 684                                      editor.fire( 'dataReady' );
 685                                  }, 0 );
 686  
 687                                  // IE, Opera and Safari may not support it and throw errors.

 688                                  try { editor.document.$.execCommand( 'enableObjectResizing', false, !editor.config.disableObjectResizing ) ; } catch(e) {}
 689                                  try { editor.document.$.execCommand( 'enableInlineTableEditing', false, !editor.config.disableNativeTableHandles ) ; } catch(e) {}
 690  
 691                                  /*

 692                                   * IE BUG: IE might have rendered the iframe with invisible contents.

 693                                   * (#3623). Push some inconsequential CSS style changes to force IE to

 694                                   * refresh it.

 695                                   *

 696                                   * Also, for some unknown reasons, short timeouts (e.g. 100ms) do not

 697                                   * fix the problem. :(

 698                                   */
 699                                  if ( CKEDITOR.env.ie )
 700                                  {
 701                                      setTimeout( function()
 702                                          {
 703                                              if ( editor.document )
 704                                              {
 705                                                  var $body = editor.document.$.body;
 706                                                  $body.runtimeStyle.marginBottom = '0px';
 707                                                  $body.runtimeStyle.marginBottom = '';
 708                                              }
 709                                          }, 1000 );
 710                                  }
 711                              },
 712                              0 );
 713                      }
 714  
 715                      editor.addMode( 'wysiwyg',
 716                          {
 717                              load : function( holderElement, data, isSnapshot )
 718                              {
 719                                  mainElement = holderElement;
 720  
 721                                  if ( CKEDITOR.env.ie && CKEDITOR.env.quirks )
 722                                      holderElement.setStyle( 'position', 'relative' );
 723  
 724                                  // The editor data "may be dirty" after this

 725                                  // point.

 726                                  editor.mayBeDirty = true;
 727  
 728                                  fireMode = true;
 729  
 730                                  if ( isSnapshot )
 731                                      this.loadSnapshotData( data );
 732                                  else
 733                                      this.loadData( data );
 734                              },
 735  
 736                              loadData : function( data )
 737                              {
 738                                  isLoadingData = true;
 739  
 740                                  var config = editor.config,
 741                                      fullPage = config.fullPage,
 742                                      docType = config.docType;
 743  
 744                                  // Build the additional stuff to be included into <head>.

 745                                  var headExtra =
 746                                      '<style type="text/css" cke_temp="1">' +
 747                                          editor._.styles.join( '\n' ) +
 748                                      '</style>';
 749  
 750                                  !fullPage && ( headExtra =
 751                                      CKEDITOR.tools.buildStyleHtml( editor.config.contentsCss ) +
 752                                      headExtra );
 753  
 754                                  var baseTag = config.baseHref ? '<base href="' + config.baseHref + '" cke_temp="1" />' : '';
 755  
 756                                  if ( fullPage )
 757                                  {
 758                                      // Search and sweep out the doctype declaration.

 759                                      data = data.replace( /<!DOCTYPE[^>]*>/i, function( match )
 760                                          {
 761                                              editor.docType = docType = match;
 762                                              return '';
 763                                          });
 764                                  }
 765  
 766                                  // Get the HTML version of the data.

 767                                  if ( editor.dataProcessor )
 768                                      data = editor.dataProcessor.toHtml( data, fixForBody );
 769  
 770                                  if ( fullPage )
 771                                  {
 772                                      // Check if the <body> tag is available.

 773                                      if ( !(/<body[\s|>]/).test( data ) )
 774                                          data = '<body>' + data;
 775  
 776                                      // Check if the <html> tag is available.

 777                                      if ( !(/<html[\s|>]/).test( data ) )
 778                                          data = '<html>' + data + '</html>';
 779  
 780                                      // Check if the <head> tag is available.

 781                                      if ( !(/<head[\s|>]/).test( data ) )
 782                                          data = data.replace( /<html[^>]*>/, '$&<head><title></title></head>' ) ;
 783                                      else if ( !(/<title[\s|>]/).test( data ) )
 784                                          data = data.replace( /<head[^>]*>/, '$&<title></title>' ) ;
 785  
 786                                      // The base must be the first tag in the HEAD, e.g. to get relative

 787                                      // links on styles.

 788                                      baseTag && ( data = data.replace( /<head>/, '$&' + baseTag ) );
 789  
 790                                      // Inject the extra stuff into <head>.

 791                                      // Attention: do not change it before testing it well. (V2)

 792                                      // This is tricky... if the head ends with <meta ... content type>,

 793                                      // Firefox will break. But, it works if we place our extra stuff as

 794                                      // the last elements in the HEAD.

 795                                      data = data.replace( /<\/head\s*>/, headExtra + '$&' );
 796  
 797                                      // Add the DOCTYPE back to it.

 798                                      data = docType + data;
 799                                  }
 800                                  else
 801                                  {
 802                                      data =
 803                                          config.docType +
 804                                          '<html dir="' + config.contentsLangDirection + '"' +
 805                                              ' lang="' + ( config.contentsLanguage || editor.langCode ) + '">' +
 806                                          '<head>' +
 807                                              '<title>' + frameLabel + '</title>' +
 808                                              baseTag +
 809                                              headExtra +
 810                                          '</head>' +
 811                                          '<body' + ( config.bodyId ? ' id="' + config.bodyId + '"' : '' ) +
 812                                                    ( config.bodyClass ? ' class="' + config.bodyClass + '"' : '' ) +
 813                                                    '>' +
 814                                              data +
 815                                          '</html>';
 816                                  }
 817  
 818                                  data += activationScript;
 819  
 820  
 821                                  // The iframe is recreated on each call of setData, so we need to clear DOM objects

 822                                  this.onDispose();
 823                                  createIFrame( data );
 824                              },
 825  
 826                              getData : function()
 827                              {
 828                                  var config = editor.config,
 829                                      fullPage = config.fullPage,
 830                                      docType = fullPage && editor.docType,
 831                                      doc = iframe.getFrameDocument();
 832  
 833                                  var data = fullPage
 834                                      ? doc.getDocumentElement().getOuterHtml()
 835                                      : doc.getBody().getHtml();
 836  
 837                                  if ( editor.dataProcessor )
 838                                      data = editor.dataProcessor.toDataFormat( data, fixForBody );
 839  
 840                                  // Strip the last blank paragraph within document.

 841                                  if ( config.ignoreEmptyParagraph )
 842                                      data = data.replace( emptyParagraphRegexp, '' );
 843  
 844                                  if ( docType )
 845                                      data = docType + '\n' + data;
 846  
 847                                  return data;
 848                              },
 849  
 850                              getSnapshotData : function()
 851                              {
 852                                  return iframe.getFrameDocument().getBody().getHtml();
 853                              },
 854  
 855                              loadSnapshotData : function( data )
 856                              {
 857                                  iframe.getFrameDocument().getBody().setHtml( data );
 858                              },
 859  
 860                              onDispose : function()
 861                              {
 862                                  if ( !editor.document )
 863                                      return;
 864  
 865                                  editor.document.getDocumentElement().clearCustomData();
 866                                  editor.document.getBody().clearCustomData();
 867  
 868                                  editor.window.clearCustomData();
 869                                  editor.document.clearCustomData();
 870  
 871                                  iframe.clearCustomData();
 872  
 873                                  /*

 874                                  * IE BUG: When destroying editor DOM with the selection remains inside

 875                                  * editing area would break IE7/8's selection system, we have to put the editing

 876                                  * iframe offline first. (#3812 and #5441)

 877                                  */
 878                                  iframe.remove();
 879                              },
 880  
 881                              unload : function( holderElement )
 882                              {
 883                                  this.onDispose();
 884  
 885                                  editor.window = editor.document = iframe = mainElement = isPendingFocus = null;
 886  
 887                                  editor.fire( 'contentDomUnload' );
 888                              },
 889  
 890                              focus : function()
 891                              {
 892                                  if ( isLoadingData )
 893                                      isPendingFocus = true;
 894                                  // Temporary solution caused by #6025, supposed be unified by #6154.

 895                                  else if ( CKEDITOR.env.opera && editor.document )
 896                                  {
 897                                      editor.document.getBody().focus();
 898  
 899                                      editor.selectionChange();
 900                                  }
 901                                  else if ( !CKEDITOR.env.opera && editor.window )
 902                                  {
 903                                      editor.window.focus();
 904  
 905                                      editor.selectionChange();
 906                                  }
 907                              }
 908                          });
 909  
 910                      editor.on( 'insertHtml', onInsertHtml, null, null, 20 );
 911                      editor.on( 'insertElement', onInsertElement, null, null, 20 );
 912                      // Auto fixing on some document structure weakness to enhance usabilities. (#3190 and #3189)

 913                      editor.on( 'selectionChange', onSelectionChangeFixBody, null, null, 1 );
 914                  });
 915  
 916              var titleBackup;
 917              // Setting voice label as window title, backup the original one

 918              // and restore it before running into use.

 919              editor.on( 'contentDom', function ()
 920                  {
 921                      var title = editor.document.getElementsByTag( 'title' ).getItem( 0 );
 922                      title.setAttribute( '_cke_title', editor.document.$.title );
 923                      editor.document.$.title = frameLabel;
 924                  });
 925  
 926              // IE8 stricts mode doesn't have 'contentEditable' in effect

 927              // on element unless it has layout. (#5562)

 928              if ( CKEDITOR.env.ie8Compat )
 929              {
 930                  editor.addCss( 'html.CSS1Compat [contenteditable=false]{ min-height:0 !important;}' );
 931  
 932                  var selectors = [];
 933                  for ( var tag in CKEDITOR.dtd.$removeEmpty )
 934                      selectors.push( 'html.CSS1Compat ' + tag + '[contenteditable=false]' );
 935                  editor.addCss( selectors.join( ',' ) + '{ display:inline-block;}' );
 936              }
 937  
 938              // Switch on design mode for a short while and close it after then.

 939  			function blinkCursor( retry )
 940              {
 941                  CKEDITOR.tools.tryThese(
 942                      function()
 943                      {
 944                          editor.document.$.designMode = 'on';
 945                          setTimeout( function ()
 946                          {
 947                              editor.document.$.designMode = 'off';
 948                              editor.document.getBody().focus();
 949                          }, 50 );
 950                      },
 951                      function()
 952                      {
 953                          // The above call is known to fail when parent DOM

 954                          // tree layout changes may break design mode. (#5782)

 955                          // Refresh the 'contentEditable' is a cue to this.

 956                          editor.document.$.designMode = 'off';
 957                          var body = editor.document.getBody();
 958                          body.setAttribute( 'contentEditable', false );
 959                          body.setAttribute( 'contentEditable', true );
 960                          // Try it again once..

 961                          !retry && blinkCursor( 1 );
 962                      });
 963              }
 964  
 965              // Create an invisible element to grab focus.

 966              if ( CKEDITOR.env.gecko || CKEDITOR.env.ie || CKEDITOR.env.opera )
 967              {
 968                  var focusGrabber;
 969                  editor.on( 'uiReady', function()
 970                  {
 971                      focusGrabber = editor.container.append( CKEDITOR.dom.element.createFromHtml(
 972                          // Use 'span' instead of anything else to fly under the screen-reader radar. (#5049)

 973                          '<span tabindex="-1" style="position:absolute; left:-10000" role="presentation"></span>' ) );
 974  
 975                      focusGrabber.on( 'focus', function()
 976                          {
 977                              editor.focus();
 978                          } );
 979                  } );
 980                  editor.on( 'destroy', function()
 981                  {
 982                      CKEDITOR.tools.removeFunction( contentDomReadyHandler );
 983                      focusGrabber.clearCustomData();
 984                  } );
 985              }
 986  
 987              // Disable form elements editing mode provided by some browers. (#5746)

 988              editor.on( 'insertElement', function ( evt )
 989              {
 990                  var element = evt.data;
 991                  if ( element.type == CKEDITOR.NODE_ELEMENT
 992                          && ( element.is( 'input' ) || element.is( 'textarea' ) ) )
 993                  {
 994                      if ( !element.isReadOnly() )
 995                      {
 996                          element.setAttribute( 'contentEditable', false );
 997                          // We should flag that the element was locked by our code so

 998                          // it'll be editable by the editor functions (#6046).

 999                          element.setCustomData( '_cke_notReadOnly', 1 );
1000                      }
1001                  }
1002              });
1003  
1004          }
1005      });
1006  
1007      // Fixing Firefox 'Back-Forward Cache' break design mode. (#4514)

1008      if ( CKEDITOR.env.gecko )
1009      {
1010          ( function ()
1011          {
1012              var body = document.body;
1013  
1014              if ( !body )
1015                  window.addEventListener( 'load', arguments.callee, false );
1016              else
1017              {
1018                  var currentHandler = body.getAttribute( 'onpageshow' );
1019                  body.setAttribute( 'onpageshow', ( currentHandler ? currentHandler + ';' : '') +
1020                              'event.persisted && (function(){' +
1021                                  'var allInstances = CKEDITOR.instances, editor, doc;' +
1022                                  'for ( var i in allInstances )' +
1023                                  '{' +
1024                                  '    editor = allInstances[ i ];' +
1025                                  '    doc = editor.document;' +
1026                                  '    if ( doc )' +
1027                                  '    {' +
1028                                  '        doc.$.designMode = "off";' +
1029                                  '        doc.$.designMode = "on";' +
1030                                  '    }' +
1031                                  '}' +
1032                          '})();' );
1033              }
1034          } )();
1035  
1036      }
1037  })();
1038  
1039  /**

1040   * Disables the ability of resize objects (image and tables) in the editing

1041   * area.

1042   * @type Boolean

1043   * @default false

1044   * @example

1045   * config.disableObjectResizing = true;

1046   */
1047  CKEDITOR.config.disableObjectResizing = false;
1048  
1049  /**

1050   * Disables the "table tools" offered natively by the browser (currently

1051   * Firefox only) to make quick table editing operations, like adding or

1052   * deleting rows and columns.

1053   * @type Boolean

1054   * @default true

1055   * @example

1056   * config.disableNativeTableHandles = false;

1057   */
1058  CKEDITOR.config.disableNativeTableHandles = true;
1059  
1060  /**

1061   * Disables the built-in spell checker while typing natively available in the

1062   * browser (currently Firefox and Safari only).<br /><br />

1063   *

1064   * Even if word suggestions will not appear in the CKEditor context menu, this

1065   * feature is useful to help quickly identifying misspelled words.<br /><br />

1066   *

1067   * This setting is currently compatible with Firefox only due to limitations in

1068   * other browsers.

1069   * @type Boolean

1070   * @default true

1071   * @example

1072   * config.disableNativeSpellChecker = false;

1073   */
1074  CKEDITOR.config.disableNativeSpellChecker = true;
1075  
1076  /**

1077   * Whether the editor must output an empty value ("") if it's contents is made

1078   * by an empty paragraph only.

1079   * @type Boolean

1080   * @default true

1081   * @example

1082   * config.ignoreEmptyParagraph = false;

1083   */
1084  CKEDITOR.config.ignoreEmptyParagraph = true;
1085  
1086  /**

1087   * Fired when data is loaded and ready for retrieval in an editor instance.

1088   * @name CKEDITOR.editor#dataReady

1089   * @event

1090   */


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