[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/libraries/ckeditor/_source/plugins/tableresize/ -> 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  (function()
   7  {
   8      var pxUnit = CKEDITOR.tools.cssLength,
   9          needsIEHacks = CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.quirks || CKEDITOR.env.version < 7 );
  10  
  11  	function getWidth( el )
  12      {
  13          return CKEDITOR.env.ie ? el.$.clientWidth : parseInt( el.getComputedStyle( 'width' ), 10 );
  14      }
  15  
  16  	function getBorderWidth( element, side )
  17      {
  18          var computed = element.getComputedStyle( 'border-' + side + '-width' ),
  19              borderMap =
  20              {
  21                  thin: '0px',
  22                  medium: '1px',
  23                  thick: '2px'
  24              };
  25  
  26          if ( computed.indexOf( 'px' ) < 0 )
  27          {
  28              // look up keywords

  29              if ( computed in borderMap && element.getComputedStyle( 'border-style' ) != 'none' )
  30                  computed = borderMap[ computed ];
  31              else
  32                  computed = 0;
  33          }
  34  
  35          return parseInt( computed, 10 );
  36      }
  37  
  38      // Gets the table row that contains the most columns.

  39  	function getMasterPillarRow( table )
  40      {
  41          var $rows = table.$.rows,
  42              maxCells = 0, cellsCount,
  43              $elected, $tr;
  44  
  45          for ( var i = 0, len = $rows.length ; i < len; i++ )
  46          {
  47              $tr = $rows[ i ];
  48              cellsCount = $tr.cells.length;
  49  
  50              if ( cellsCount > maxCells )
  51              {
  52                  maxCells = cellsCount;
  53                  $elected = $tr;
  54              }
  55          }
  56  
  57          return $elected;
  58      }
  59  
  60  	function buildTableColumnPillars( table )
  61      {
  62          var pillars = [],
  63              pillarIndex = -1,
  64              rtl = ( table.getComputedStyle( 'direction' ) == 'rtl' );
  65  
  66          // Get the raw row element that cointains the most columns.

  67          var $tr = getMasterPillarRow( table );
  68  
  69          // Get the tbody element and position, which will be used to set the

  70          // top and bottom boundaries.

  71          var tbody = new CKEDITOR.dom.element( table.$.tBodies[ 0 ] ),
  72              tbodyPosition = tbody.getDocumentPosition();
  73  
  74          // Loop thorugh all cells, building pillars after each one of them.

  75          for ( var i = 0, len = $tr.cells.length ; i < len ; i++ )
  76          {
  77              // Both the current cell and the successive one will be used in the

  78              // pillar size calculation.

  79              var td = new CKEDITOR.dom.element( $tr.cells[ i ] ),
  80                  nextTd = $tr.cells[ i + 1 ] && new CKEDITOR.dom.element( $tr.cells[ i + 1 ] );
  81  
  82              pillarIndex += td.$.colSpan || 1;
  83  
  84              // Calculate the pillar boundary positions.

  85              var pillarLeft, pillarRight, pillarWidth, pillarPadding;
  86  
  87              var x = td.getDocumentPosition().x;
  88  
  89              // Calculate positions based on the current cell.

  90              rtl ?
  91                  pillarRight = x + getBorderWidth( td, 'left' ) :
  92                  pillarLeft  = x + td.$.offsetWidth - getBorderWidth( td, 'right' );
  93  
  94              // Calculate positions based on the next cell, if available.

  95              if ( nextTd )
  96              {
  97                  x =  nextTd.getDocumentPosition().x;
  98  
  99                  rtl ?
 100                      pillarLeft    = x + nextTd.$.offsetWidth - getBorderWidth( nextTd, 'right' ) :
 101                      pillarRight    = x + getBorderWidth( nextTd, 'left' );
 102              }
 103              // Otherwise calculate positions based on the table (for last cell).

 104              else
 105              {
 106                  x =  table.getDocumentPosition().x;
 107  
 108                  rtl ?
 109                      pillarLeft    = x :
 110                      pillarRight    = x + table.$.offsetWidth;
 111              }
 112  
 113              pillarWidth = Math.max( pillarRight - pillarLeft, 3 );
 114  
 115              // Make the pillar touch area at least 14 pixels wide, for easy to use.

 116              pillarPadding = Math.max( Math.round( 7 - ( pillarWidth / 2 ) ), 0 );
 117  
 118              // The pillar should reflects exactly the shape of the hovered

 119              // column border line.

 120              pillars.push( {
 121                  table : table,
 122                  index : pillarIndex,
 123                  x : pillarLeft,
 124                  y : tbodyPosition.y,
 125                  width : pillarWidth,
 126                  height: tbody.$.offsetHeight,
 127                  padding : pillarPadding,
 128                  rtl : rtl } );
 129          }
 130  
 131          return pillars;
 132      }
 133  
 134  	function getPillarAtPosition( pillars, positionX )
 135      {
 136          for ( var i = 0, len = pillars.length ; i < len ; i++ )
 137          {
 138              var pillar = pillars[ i ],
 139                  pad = pillar.padding;
 140  
 141              if ( positionX >= pillar.x - pad && positionX <= ( pillar.x + pillar.width + pad ) )
 142                  return pillar;
 143          }
 144  
 145          return null;
 146      }
 147  
 148  	function cancel( evt )
 149      {
 150          ( evt.data || evt ).preventDefault();
 151      }
 152  
 153  	function columnResizer( editor )
 154      {
 155          var pillar,
 156              document,
 157              resizer,
 158              isResizing,
 159              startOffset,
 160              currentShift;
 161  
 162          var leftSideCells, rightSideCells, leftShiftBoundary, rightShiftBoundary;
 163  
 164  		function detach()
 165          {
 166              pillar = null;
 167              currentShift = 0;
 168              isResizing = 0;
 169  
 170              document.removeListener( 'mouseup', onMouseUp );
 171              resizer.removeListener( 'mousedown', onMouseDown );
 172              resizer.removeListener( 'mousemove', onMouseMove );
 173  
 174              document.getBody().setStyle( 'cursor', 'auto' );
 175  
 176              // Hide the resizer (remove it on IE7 - #5890).

 177              needsIEHacks ? resizer.remove() : resizer.hide();
 178          }
 179  
 180  		function resizeStart()
 181          {
 182              // Before starting to resize, figure out which cells to change

 183              // and the boundaries of this resizing shift.

 184  
 185              var columnIndex = pillar.index,
 186                  map = CKEDITOR.tools.buildTableMap( pillar.table ),
 187                  leftColumnCells = [],
 188                  rightColumnCells = [],
 189                  leftMinSize = Number.MAX_VALUE,
 190                  rightMinSize = leftMinSize,
 191                  rtl = pillar.rtl;
 192  
 193              for ( var i = 0, len = map.length ; i < len ; i++ )
 194              {
 195                  var row            = map[ i ],
 196                      leftCell    = row[ columnIndex + ( rtl ? 1 : 0 ) ],
 197                      rightCell    = row[ columnIndex + ( rtl ? 0 : 1 ) ];
 198  
 199                  leftCell    = leftCell && new CKEDITOR.dom.element( leftCell );
 200                  rightCell    = rightCell && new CKEDITOR.dom.element( rightCell );
 201  
 202                  if ( !leftCell || !rightCell || !leftCell.equals( rightCell ) )
 203                  {
 204                      leftCell && ( leftMinSize = Math.min( leftMinSize, getWidth( leftCell ) ) );
 205                      rightCell && ( rightMinSize = Math.min( rightMinSize, getWidth( rightCell ) ) );
 206  
 207                      leftColumnCells.push( leftCell );
 208                      rightColumnCells.push( rightCell );
 209                  }
 210              }
 211  
 212              // Cache the list of cells to be resized.

 213              leftSideCells = leftColumnCells;
 214              rightSideCells = rightColumnCells;
 215  
 216              // Cache the resize limit boundaries.

 217              leftShiftBoundary =  pillar.x - leftMinSize;
 218              rightShiftBoundary = pillar.x + rightMinSize;
 219  
 220              resizer.setOpacity( 0.5 );
 221              startOffset = parseInt( resizer.getStyle( 'left' ), 10 );
 222              currentShift = 0;
 223              isResizing = 1;
 224  
 225              resizer.on( 'mousemove', onMouseMove );
 226  
 227              // Prevent the native drag behavior otherwise 'mousemove' won't fire.

 228              document.on( 'dragstart', cancel );
 229          }
 230  
 231  		function resizeEnd()
 232          {
 233              isResizing = 0;
 234  
 235              resizer.setOpacity( 0 );
 236  
 237              currentShift && resizeColumn();
 238  
 239              var table = pillar.table;
 240              setTimeout( function () { table.removeCustomData( '_cke_table_pillars' ); }, 0 );
 241  
 242              document.removeListener( 'dragstart', cancel );
 243          }
 244  
 245  		function resizeColumn()
 246          {
 247              var rtl = pillar.rtl,
 248                  cellsCount = rtl ? rightSideCells.length : leftSideCells.length;
 249  
 250              // Perform the actual resize to table cells, only for those by side of the pillar.

 251              for ( var i = 0 ; i < cellsCount ; i++ )
 252              {
 253                  var leftCell = leftSideCells[ i ],
 254                      rightCell = rightSideCells[ i ],
 255                      table = pillar.table;
 256  
 257                  // Defer the resizing to avoid any interference among cells.

 258                  CKEDITOR.tools.setTimeout(
 259                      function( leftCell, leftOldWidth, rightCell, rightOldWidth, tableWidth, sizeShift )
 260                      {
 261                          leftCell && leftCell.setStyle( 'width', pxUnit( Math.max( leftOldWidth + sizeShift, 0 ) ) );
 262                          rightCell && rightCell.setStyle( 'width', pxUnit( Math.max( rightOldWidth - sizeShift, 0 ) ) );
 263  
 264                          // If we're in the last cell, we need to resize the table as well

 265                          if ( tableWidth )
 266                              table.setStyle( 'width', pxUnit( tableWidth + sizeShift * ( rtl ? -1 : 1 ) ) );
 267                      }
 268                      , 0,
 269                      this, [
 270                          leftCell, leftCell && getWidth( leftCell ),
 271                          rightCell, rightCell && getWidth( rightCell ),
 272                          ( !leftCell || !rightCell ) && ( getWidth( table ) + getBorderWidth( table, 'left' ) + getBorderWidth( table, 'right' ) ),
 273                          currentShift ] );
 274              }
 275          }
 276  
 277  		function onMouseDown( evt )
 278          {
 279              cancel( evt );
 280  
 281              resizeStart();
 282  
 283              document.on( 'mouseup', onMouseUp, this );
 284          }
 285  
 286  		function onMouseUp( evt )
 287          {
 288              evt.removeListener();
 289  
 290              resizeEnd();
 291          }
 292  
 293  		function onMouseMove( evt )
 294          {
 295              move( evt.data.$.clientX );
 296          }
 297  
 298          document = editor.document;
 299  
 300          resizer = CKEDITOR.dom.element.createFromHtml(
 301              '<div cke_temp=1 contenteditable=false unselectable=on '+
 302              'style="position:absolute;cursor:col-resize;filter:alpha(opacity=0);opacity:0;' +
 303                  'padding:0;background-color:#004;background-image:none;border:0px none;z-index:10"></div>', document );
 304  
 305          // Except on IE6/7 (#5890), place the resizer after body to prevent it

 306          // from being editable.

 307          if ( !needsIEHacks )
 308              document.getDocumentElement().append( resizer );
 309  
 310          this.attachTo = function( targetPillar )
 311          {
 312              // Accept only one pillar at a time.

 313              if ( isResizing )
 314                  return;
 315  
 316              // On IE6/7, we append the resizer everytime we need it. (#5890)

 317              if ( needsIEHacks )
 318              {
 319                  document.getBody().append( resizer );
 320                  currentShift = 0;
 321              }
 322  
 323              pillar = targetPillar;
 324  
 325              resizer.setStyles(
 326                  {
 327                      width: pxUnit( targetPillar.width ),
 328                      height : pxUnit( targetPillar.height ),
 329                      left : pxUnit( targetPillar.x ),
 330                      top : pxUnit( targetPillar.y )
 331                  });
 332  
 333              // In IE6/7, it's not possible to have custom cursors for floating

 334              // elements in an editable document. Show the resizer in that case,

 335              // to give the user a visual clue.

 336              needsIEHacks && resizer.setOpacity( 0.25 );
 337  
 338              resizer.on( 'mousedown', onMouseDown, this );
 339  
 340              document.getBody().setStyle( 'cursor', 'col-resize' );
 341  
 342              // Display the resizer to receive events but don't show it,

 343              // only change the cursor to resizable shape.

 344              resizer.show();
 345          };
 346  
 347          var move = this.move = function( posX )
 348          {
 349              if ( !pillar )
 350                  return 0;
 351  
 352              var pad = pillar.padding;
 353  
 354              if ( !isResizing && ( posX < pillar.x - pad || posX > ( pillar.x + pillar.width + pad ) ) )
 355              {
 356                  detach();
 357                  return 0;
 358              }
 359  
 360              var resizerNewPosition = posX - Math.round( resizer.$.offsetWidth / 2 );
 361  
 362              if ( isResizing )
 363              {
 364                  if ( resizerNewPosition == leftShiftBoundary || resizerNewPosition == rightShiftBoundary )
 365                      return 1;
 366  
 367                  resizerNewPosition = Math.max( resizerNewPosition, leftShiftBoundary );
 368                  resizerNewPosition = Math.min( resizerNewPosition, rightShiftBoundary );
 369  
 370                  currentShift = resizerNewPosition - startOffset;
 371              }
 372  
 373              resizer.setStyle( 'left', pxUnit( resizerNewPosition ) );
 374  
 375              return 1;
 376          };
 377      }
 378  
 379  	function clearPillarsCache( evt )
 380      {
 381          var target = evt.data.getTarget();
 382  
 383          if ( evt.name == 'mouseout' )
 384          {
 385              // Bypass interal mouse move.

 386              if ( !target.is ( 'table' ) )
 387                  return;
 388  
 389              var dest = new CKEDITOR.dom.element( evt.data.$.relatedTarget || evt.data.$.toElement );
 390              while( dest && dest.$ && !dest.equals( target ) && !dest.is( 'body' ) )
 391                  dest = dest.getParent();
 392              if ( !dest || dest.equals( target ) )
 393                  return;
 394          }
 395  
 396          target.getAscendant( 'table', true ).removeCustomData( '_cke_table_pillars' );
 397          evt.removeListener();
 398      }
 399  
 400      CKEDITOR.plugins.add( 'tableresize',
 401      {
 402          requires : [ 'tabletools' ],
 403          init : function( editor )
 404          {
 405              editor.on( 'contentDom', function()
 406              {
 407                  var resizer;
 408  
 409                  editor.document.getBody().on( 'mousemove', function( evt )
 410                      {
 411                          evt = evt.data;
 412  
 413                          // If we're already attached to a pillar, simply move the

 414                          // resizer.

 415                          if ( resizer && resizer.move( evt.$.clientX ) )
 416                          {
 417                              cancel( evt );
 418                              return;
 419                          }
 420  
 421                          // Considering table, tr, td, tbody but nothing else.

 422                          var target = evt.getTarget(),
 423                              table,
 424                              pillars;
 425  
 426                          if ( !target.is( 'table' ) && !target.getAscendant( 'tbody', true ) )
 427                              return;
 428  
 429                          table = target.getAscendant( 'table', true );
 430  
 431                          if ( !( pillars = table.getCustomData( '_cke_table_pillars' ) ) )
 432                          {
 433                              // Cache table pillars calculation result.

 434                              table.setCustomData( '_cke_table_pillars', ( pillars = buildTableColumnPillars( table ) ) );
 435                              table.on( 'mouseout', clearPillarsCache );
 436                              table.on( 'mousedown', clearPillarsCache );
 437                          }
 438  
 439                          var pillar = getPillarAtPosition( pillars, evt.$.clientX );
 440                          if ( pillar )
 441                          {
 442                              !resizer && ( resizer = new columnResizer( editor ) );
 443                              resizer.attachTo( pillar );
 444                          }
 445                      });
 446              });
 447          }
 448      });
 449  
 450  })();


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