[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/libraries/ckeditor/_source/plugins/div/dialogs/ -> div.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  (function()
   7  {
   8  
   9      /**

  10       * Add to collection with DUP examination.

  11       * @param {Object} collection

  12       * @param {Object} element

  13       * @param {Object} database

  14       */
  15  	function addSafely( collection, element, database )
  16      {
  17          // 1. IE doesn't support customData on text nodes;

  18          // 2. Text nodes never get chance to appear twice;

  19          if ( !element.is || !element.getCustomData( 'block_processed' ) )
  20          {
  21              element.is && CKEDITOR.dom.element.setMarker( database, element, 'block_processed', true );
  22              collection.push( element );
  23          }
  24      }
  25  
  26  	function getNonEmptyChildren( element )
  27      {
  28          var retval = [];
  29          var children = element.getChildren();
  30          for ( var i = 0 ; i < children.count() ; i++ )
  31          {
  32              var child = children.getItem( i );
  33              if ( ! ( child.type === CKEDITOR.NODE_TEXT
  34                  && ( /^[ \t\n\r]+$/ ).test( child.getText() ) ) )
  35                  retval.push( child );
  36          }
  37          return retval;
  38      }
  39  
  40  
  41      /**

  42       * Dialog reused by both 'creatediv' and 'editdiv' commands.

  43       * @param {Object} editor

  44       * @param {String} command    The command name which indicate what the current command is.

  45       */
  46  	function divDialog( editor, command )
  47      {
  48          // Definition of elements at which div operation should stopped.

  49          var divLimitDefinition = ( function(){
  50  
  51              // Customzie from specialize blockLimit elements

  52              var definition = CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$blockLimit );
  53  
  54              // Exclude 'div' itself.

  55              delete definition.div;
  56  
  57              // Exclude 'td' and 'th' when 'wrapping table'

  58              if ( editor.config.div_wrapTable )
  59              {
  60                  delete definition.td;
  61                  delete definition.th;
  62              }
  63              return definition;
  64          })();
  65  
  66          // DTD of 'div' element

  67          var dtd = CKEDITOR.dtd.div;
  68  
  69          /**

  70           * Get the first div limit element on the element's path.

  71           * @param {Object} element

  72           */
  73  		function getDivLimitElement( element )
  74          {
  75              var pathElements = new CKEDITOR.dom.elementPath( element ).elements;
  76              var divLimit;
  77              for ( var i = 0; i < pathElements.length ; i++ )
  78              {
  79                  if ( pathElements[ i ].getName() in divLimitDefinition )
  80                  {
  81                      divLimit = pathElements[ i ];
  82                      break;
  83                  }
  84              }
  85              return divLimit;
  86          }
  87  
  88          /**

  89           * Init all fields' setup/commit function.

  90           * @memberof divDialog

  91           */
  92  		function setupFields()
  93          {
  94              this.foreach( function( field )
  95              {
  96                  // Exclude layout container elements

  97                  if ( /^(?!vbox|hbox)/.test( field.type ) )
  98                  {
  99                      if ( !field.setup )
 100                      {
 101                          // Read the dialog fields values from the specified

 102                          // element attributes.

 103                          field.setup = function( element )
 104                          {
 105                              field.setValue( element.getAttribute( field.id ) || '' );
 106                          };
 107                      }
 108                      if ( !field.commit )
 109                      {
 110                          // Set element attributes assigned by the dialog

 111                          // fields.

 112                          field.commit = function( element )
 113                          {
 114                              var fieldValue = this.getValue();
 115                              // ignore default element attribute values

 116                              if ( 'dir' == field.id && element.getComputedStyle( 'direction' ) == fieldValue )
 117                                  return;
 118  
 119                              if ( fieldValue )
 120                                  element.setAttribute( field.id, fieldValue );
 121                              else
 122                                  element.removeAttribute( field.id );
 123                          };
 124                      }
 125                  }
 126              } );
 127          }
 128  
 129          /**

 130           * Wrapping 'div' element around appropriate blocks among the selected ranges.

 131           * @param {Object} editor

 132           */
 133  		function createDiv( editor )
 134          {
 135              // new adding containers OR detected pre-existed containers.

 136              var containers = [];
 137              // node markers store.

 138              var database = {};
 139              // All block level elements which contained by the ranges.

 140              var containedBlocks = [], block;
 141  
 142              // Get all ranges from the selection.

 143              var selection = editor.document.getSelection();
 144              var ranges = selection.getRanges();
 145              var bookmarks = selection.createBookmarks();
 146              var i, iterator;
 147  
 148              // Calcualte a default block tag if we need to create blocks.

 149              var blockTag = editor.config.enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p';
 150  
 151              // collect all included elements from dom-iterator

 152              for ( i = 0 ; i < ranges.length ; i++ )
 153              {
 154                  iterator = ranges[ i ].createIterator();
 155                  while ( ( block = iterator.getNextParagraph() ) )
 156                  {
 157                      // include contents of blockLimit elements.

 158                      if ( block.getName() in divLimitDefinition )
 159                      {
 160                          var j, childNodes = block.getChildren();
 161                          for ( j = 0 ; j < childNodes.count() ; j++ )
 162                              addSafely( containedBlocks, childNodes.getItem( j ) , database );
 163                      }
 164                      else
 165                      {
 166                          // Bypass dtd disallowed elements.

 167                          while ( !dtd[ block.getName() ] && block.getName() != 'body' )
 168                              block = block.getParent();
 169                          addSafely( containedBlocks, block, database );
 170                      }
 171                  }
 172              }
 173  
 174              CKEDITOR.dom.element.clearAllMarkers( database );
 175  
 176              var blockGroups = groupByDivLimit( containedBlocks );
 177              var ancestor, blockEl, divElement;
 178  
 179              for ( i = 0 ; i < blockGroups.length ; i++ )
 180              {
 181                  var currentNode = blockGroups[ i ][ 0 ];
 182  
 183                  // Calculate the common parent node of all contained elements.

 184                  ancestor = currentNode.getParent();
 185                  for ( j = 1 ; j < blockGroups[ i ].length; j++ )
 186                      ancestor = ancestor.getCommonAncestor( blockGroups[ i ][ j ] );
 187  
 188                  divElement = new CKEDITOR.dom.element( 'div', editor.document );
 189  
 190                  // Normalize the blocks in each group to a common parent.

 191                  for ( j = 0; j < blockGroups[ i ].length ; j++ )
 192                  {
 193                      currentNode = blockGroups[ i ][ j ];
 194  
 195                      while ( !currentNode.getParent().equals( ancestor ) )
 196                          currentNode = currentNode.getParent();
 197  
 198                      // This could introduce some duplicated elements in array.

 199                      blockGroups[ i ][ j ] = currentNode;
 200                  }
 201  
 202                  // Wrapped blocks counting

 203                  var fixedBlock = null;
 204                  for ( j = 0 ; j < blockGroups[ i ].length ; j++ )
 205                  {
 206                      currentNode = blockGroups[ i ][ j ];
 207  
 208                      // Avoid DUP elements introduced by grouping.

 209                      if ( !( currentNode.getCustomData && currentNode.getCustomData( 'block_processed' ) ) )
 210                      {
 211                          currentNode.is && CKEDITOR.dom.element.setMarker( database, currentNode, 'block_processed', true );
 212  
 213                          // Establish new container, wrapping all elements in this group.

 214                          if ( !j )
 215                              divElement.insertBefore( currentNode );
 216  
 217                          divElement.append( currentNode );
 218                      }
 219                  }
 220  
 221                  CKEDITOR.dom.element.clearAllMarkers( database );
 222                  containers.push( divElement );
 223              }
 224  
 225              selection.selectBookmarks( bookmarks );
 226              return containers;
 227          }
 228  
 229  		function getDiv( editor )
 230          {
 231              var path = new CKEDITOR.dom.elementPath( editor.getSelection().getStartElement() ),
 232                  blockLimit = path.blockLimit,
 233                  div = blockLimit && blockLimit.getAscendant( 'div', true );
 234              return div;
 235          }
 236          /**

 237           * Divide a set of nodes to different groups by their path's blocklimit element.

 238           * Note: the specified nodes should be in source order naturally, which mean they are supposed to producea by following class:

 239           *  * CKEDITOR.dom.range.Iterator

 240           *  * CKEDITOR.dom.domWalker

 241           *  @return {Array []} the grouped nodes

 242           */
 243  		function groupByDivLimit( nodes )
 244          {
 245              var groups = [],
 246                  lastDivLimit = null,
 247                  path, block;
 248              for ( var i = 0 ; i < nodes.length ; i++ )
 249              {
 250                  block = nodes[i];
 251                  var limit = getDivLimitElement( block );
 252                  if ( !limit.equals( lastDivLimit ) )
 253                  {
 254                      lastDivLimit = limit ;
 255                      groups.push( [] ) ;
 256                  }
 257                  groups[ groups.length - 1 ].push( block ) ;
 258              }
 259              return groups;
 260          }
 261  
 262          // Synchronous field values to other impacted fields is required, e.g. div styles

 263          // change should also alter inline-style text.

 264  		function commitInternally( targetFields )
 265          {
 266              var dialog = this.getDialog(),
 267                   element = dialog._element && dialog._element.clone()
 268                           || new CKEDITOR.dom.element( 'div', editor.document );
 269  
 270              // Commit this field and broadcast to target fields.

 271              this.commit( element, true );
 272  
 273              targetFields = [].concat( targetFields );
 274              var length = targetFields.length, field;
 275              for ( var i = 0; i < length; i++ )
 276              {
 277                  field = dialog.getContentElement.apply( dialog, targetFields[ i ].split( ':' ) );
 278                  field && field.setup && field.setup( element, true );
 279              }
 280          }
 281  
 282  
 283          // Registered 'CKEDITOR.style' instances.

 284          var styles = {} ;
 285          /**

 286           * Hold a collection of created block container elements.

 287           */
 288          var containers = [];
 289          /**

 290           * @type divDialog

 291           */
 292          return {
 293              title : editor.lang.div.title,
 294              minWidth : 400,
 295              minHeight : 165,
 296              contents :
 297              [
 298              {
 299                  id :'info',
 300                  label :editor.lang.common.generalTab,
 301                  title :editor.lang.common.generalTab,
 302                  elements :
 303                  [
 304                      {
 305                          type :'hbox',
 306                          widths : [ '50%', '50%' ],
 307                          children :
 308                          [
 309                              {
 310                                  id :'elementStyle',
 311                                  type :'select',
 312                                  style :'width: 100%;',
 313                                  label :editor.lang.div.styleSelectLabel,
 314                                  'default' : '',
 315                                  // Options are loaded dynamically.

 316                                  items :
 317                                  [
 318                                      [ editor.lang.common.notSet , '' ]
 319                                  ],
 320                                  onChange : function()
 321                                  {
 322                                      commitInternally.call( this, [ 'info:class', 'advanced:dir', 'advanced:style' ] );
 323                                  },
 324                                  setup : function( element )
 325                                  {
 326                                      for ( var name in styles )
 327                                          styles[ name ].checkElementRemovable( element, true ) && this.setValue( name );
 328                                  },
 329                                  commit: function( element )
 330                                  {
 331                                      var styleName;
 332                                      if ( ( styleName = this.getValue() ) )
 333                                          styles[ styleName ].applyToObject( element );
 334                                  }
 335                              },
 336                              {
 337                                  id :'class',
 338                                  type :'text',
 339                                  label :editor.lang.common.cssClass,
 340                                  'default' : ''
 341                              }
 342                          ]
 343                      }
 344                  ]
 345              },
 346              {
 347                      id :'advanced',
 348                      label :editor.lang.common.advancedTab,
 349                      title :editor.lang.common.advancedTab,
 350                      elements :
 351                      [
 352                      {
 353                          type :'vbox',
 354                          padding :1,
 355                          children :
 356                          [
 357                              {
 358                                  type :'hbox',
 359                                  widths : [ '50%', '50%' ],
 360                                  children :
 361                                  [
 362                                      {
 363                                          type :'text',
 364                                          id :'id',
 365                                          label :editor.lang.common.id,
 366                                          'default' : ''
 367                                      },
 368                                      {
 369                                          type :'text',
 370                                          id :'lang',
 371                                          label :editor.lang.link.langCode,
 372                                          'default' : ''
 373                                      }
 374                                  ]
 375                              },
 376                              {
 377                                  type :'hbox',
 378                                  children :
 379                                  [
 380                                          {
 381                                              type :'text',
 382                                              id :'style',
 383                                              style :'width: 100%;',
 384                                              label :editor.lang.common.cssStyle,
 385                                              'default' : '',
 386                                              commit : function( element )
 387                                              {
 388                                                  // Merge with 'elementStyle', which is of higher priority.

 389                                                  var value = this.getValue(),
 390                                                          merged = [ value, element.getAttribute( 'style' ) ].join( ';' );
 391                                                  value && element.setAttribute( 'style', merged );
 392                                              }
 393                                          }
 394                                  ]
 395                              },
 396                              {
 397                                  type :'hbox',
 398                                  children :
 399                                  [
 400                                          {
 401                                              type :'text',
 402                                              id :'title',
 403                                              style :'width: 100%;',
 404                                              label :editor.lang.common.advisoryTitle,
 405                                              'default' : ''
 406                                          }
 407                                  ]
 408                              },
 409                              {
 410                                  type :'select',
 411                                  id :'dir',
 412                                  style :'width: 100%;',
 413                                  label :editor.lang.common.langDir,
 414                                  'default' : '',
 415                                  items :
 416                                  [
 417                                      [ editor.lang.common.notSet , '' ],
 418                                      [
 419                                          editor.lang.common.langDirLtr,
 420                                          'ltr'
 421                                      ],
 422                                      [
 423                                          editor.lang.common.langDirRtl,
 424                                          'rtl'
 425                                      ]
 426                                  ]
 427                              }
 428                          ]
 429                      }
 430                      ]
 431                  }
 432              ],
 433              onLoad : function()
 434              {
 435                  setupFields.call(this);
 436  
 437                  // Preparing for the 'elementStyle' field.

 438                  var dialog = this,
 439                       stylesField = this.getContentElement( 'info', 'elementStyle' );
 440  
 441                   // Reuse the 'stylescombo' plugin's styles definition.

 442                  editor.getStylesSet( function( stylesDefinitions )
 443                  {
 444                      var styleName;
 445  
 446                      if ( stylesDefinitions )
 447                      {
 448                          // Digg only those styles that apply to 'div'.

 449                          for ( var i = 0 ; i < stylesDefinitions.length ; i++ )
 450                          {
 451                              var styleDefinition = stylesDefinitions[ i ];
 452                              if ( styleDefinition.element && styleDefinition.element == 'div' )
 453                              {
 454                                  styleName = styleDefinition.name;
 455                                  styles[ styleName ] = new CKEDITOR.style( styleDefinition );
 456  
 457                                  // Populate the styles field options with style name.

 458                                  stylesField.items.push( [ styleName, styleName ] );
 459                                  stylesField.add( styleName, styleName );
 460                              }
 461                          }
 462                      }
 463  
 464                      // We should disable the content element

 465                      // it if no options are available at all.

 466                      stylesField[ stylesField.items.length > 1 ? 'enable' : 'disable' ]();
 467  
 468                      // Now setup the field value manually.

 469                      setTimeout( function() { stylesField.setup( dialog._element ); }, 0 );
 470                  } );
 471              },
 472              onShow : function()
 473              {
 474                  // Whether always create new container regardless of existed

 475                  // ones.

 476                  if ( command == 'editdiv' )
 477                  {
 478                      // Try to discover the containers that already existed in

 479                      // ranges

 480                      var div = getDiv( editor );
 481                      // update dialog field values

 482                      div && this.setupContent( this._element = div );
 483                  }
 484              },
 485              onOk : function()
 486              {
 487                  if ( command == 'editdiv' )
 488                      containers = [ this._element ];
 489                  else
 490                      containers = createDiv( editor, true );
 491  
 492                  // Update elements attributes

 493                  var size = containers.length;
 494                  for ( var i = 0; i < size; i++ )
 495                  {
 496                      this.commitContent( containers[ i ] );
 497  
 498                      // Remove empty 'style' attribute.

 499                      !containers[ i ].getAttribute( 'style' ) && containers[ i ].removeAttribute( 'style' );
 500                  }
 501  
 502                  this.hide();
 503              },
 504              onHide : function()
 505              {
 506                  delete this._element;
 507              }
 508          };
 509      }
 510  
 511      CKEDITOR.dialog.add( 'creatediv', function( editor )
 512          {
 513              return divDialog( editor, 'creatediv' );
 514          } );
 515      CKEDITOR.dialog.add( 'editdiv', function( editor )
 516          {
 517              return divDialog( editor, 'editdiv' );
 518          } );
 519  } )();
 520  
 521  /*

 522   * @name CKEDITOR.config.div_wrapTable

 523   * Whether to wrap the whole table instead of indivisual cells when created 'div' in table cell.

 524   * @type Boolean

 525   * @default false

 526   * @example config.div_wrapTable = true;

 527   */


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