| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 /* 2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net 3 * Copyright (C) 2003-2009 Frederico Caldeira Knabben 4 * 5 * == BEGIN LICENSE == 6 * 7 * Licensed under the terms of any of the following licenses at your 8 * choice: 9 * 10 * - GNU General Public License Version 2 or later (the "GPL") 11 * http://www.gnu.org/licenses/gpl.html 12 * 13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") 14 * http://www.gnu.org/licenses/lgpl.html 15 * 16 * - Mozilla Public License Version 1.1 or later (the "MPL") 17 * http://www.mozilla.org/MPL/MPL-1.1.html 18 * 19 * == END LICENSE == 20 * 21 * Controls the [Enter] keystroke behavior in a document. 22 */ 23 24 /* 25 * Constructor. 26 * @targetDocument : the target document. 27 * @enterMode : the behavior for the <Enter> keystroke. 28 * May be "p", "div", "br". Default is "p". 29 * @shiftEnterMode : the behavior for the <Shift>+<Enter> keystroke. 30 * May be "p", "div", "br". Defaults to "br". 31 */ 32 var FCKEnterKey = function( targetWindow, enterMode, shiftEnterMode, tabSpaces ) 33 { 34 this.Window = targetWindow ; 35 this.EnterMode = enterMode || 'p' ; 36 this.ShiftEnterMode = shiftEnterMode || 'br' ; 37 38 // Setup the Keystroke Handler. 39 var oKeystrokeHandler = new FCKKeystrokeHandler( false ) ; 40 oKeystrokeHandler._EnterKey = this ; 41 oKeystrokeHandler.OnKeystroke = FCKEnterKey_OnKeystroke ; 42 43 oKeystrokeHandler.SetKeystrokes( [ 44 [ 13 , 'Enter' ], 45 [ SHIFT + 13, 'ShiftEnter' ], 46 [ 8 , 'Backspace' ], 47 [ CTRL + 8 , 'CtrlBackspace' ], 48 [ 46 , 'Delete' ] 49 ] ) ; 50 51 this.TabText = '' ; 52 53 // Safari by default inserts 4 spaces on TAB, while others make the editor 54 // loose focus. So, we need to handle it here to not include those spaces. 55 if ( tabSpaces > 0 || FCKBrowserInfo.IsSafari ) 56 { 57 while ( tabSpaces-- ) 58 this.TabText += '\xa0' ; 59 60 oKeystrokeHandler.SetKeystrokes( [ 9, 'Tab' ] ); 61 } 62 63 oKeystrokeHandler.AttachToElement( targetWindow.document ) ; 64 } 65 66 67 function FCKEnterKey_OnKeystroke( keyCombination, keystrokeValue ) 68 { 69 var oEnterKey = this._EnterKey ; 70 71 try 72 { 73 switch ( keystrokeValue ) 74 { 75 case 'Enter' : 76 return oEnterKey.DoEnter() ; 77 break ; 78 case 'ShiftEnter' : 79 return oEnterKey.DoShiftEnter() ; 80 break ; 81 case 'Backspace' : 82 return oEnterKey.DoBackspace() ; 83 break ; 84 case 'Delete' : 85 return oEnterKey.DoDelete() ; 86 break ; 87 case 'Tab' : 88 return oEnterKey.DoTab() ; 89 break ; 90 case 'CtrlBackspace' : 91 return oEnterKey.DoCtrlBackspace() ; 92 break ; 93 } 94 } 95 catch (e) 96 { 97 // If for any reason we are not able to handle it, go 98 // ahead with the browser default behavior. 99 } 100 101 return false ; 102 } 103 104 /* 105 * Executes the <Enter> key behavior. 106 */ 107 FCKEnterKey.prototype.DoEnter = function( mode, hasShift ) 108 { 109 // Save an undo snapshot before doing anything 110 FCKUndo.SaveUndoStep() ; 111 112 this._HasShift = ( hasShift === true ) ; 113 114 var parentElement = FCKSelection.GetParentElement() ; 115 var parentPath = new FCKElementPath( parentElement ) ; 116 var sMode = mode || this.EnterMode ; 117 118 if ( sMode == 'br' || parentPath.Block && parentPath.Block.tagName.toLowerCase() == 'pre' ) 119 return this._ExecuteEnterBr() ; 120 else 121 return this._ExecuteEnterBlock( sMode ) ; 122 } 123 124 /* 125 * Executes the <Shift>+<Enter> key behavior. 126 */ 127 FCKEnterKey.prototype.DoShiftEnter = function() 128 { 129 return this.DoEnter( this.ShiftEnterMode, true ) ; 130 } 131 132 /* 133 * Executes the <Backspace> key behavior. 134 */ 135 FCKEnterKey.prototype.DoBackspace = function() 136 { 137 var bCustom = false ; 138 139 // Get the current selection. 140 var oRange = new FCKDomRange( this.Window ) ; 141 oRange.MoveToSelection() ; 142 143 // Kludge for #247 144 if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) ) 145 { 146 this._FixIESelectAllBug( oRange ) ; 147 return true ; 148 } 149 150 var isCollapsed = oRange.CheckIsCollapsed() ; 151 152 if ( !isCollapsed ) 153 { 154 // Bug #327, Backspace with an img selection would activate the default action in IE. 155 // Let's override that with our logic here. 156 if ( FCKBrowserInfo.IsIE && this.Window.document.selection.type.toLowerCase() == "control" ) 157 { 158 var controls = this.Window.document.selection.createRange() ; 159 for ( var i = controls.length - 1 ; i >= 0 ; i-- ) 160 { 161 var el = controls.item( i ) ; 162 el.parentNode.removeChild( el ) ; 163 } 164 return true ; 165 } 166 167 return false ; 168 } 169 170 // On IE, it is better for us handle the deletion if the caret is preceeded 171 // by a <br> (#1383). 172 if ( FCKBrowserInfo.IsIE ) 173 { 174 var previousElement = FCKDomTools.GetPreviousSourceElement( oRange.StartNode, true ) ; 175 176 if ( previousElement && previousElement.nodeName.toLowerCase() == 'br' ) 177 { 178 // Create a range that starts after the <br> and ends at the 179 // current range position. 180 var testRange = oRange.Clone() ; 181 testRange.SetStart( previousElement, 4 ) ; 182 183 // If that range is empty, we can proceed cleaning that <br> manually. 184 if ( testRange.CheckIsEmpty() ) 185 { 186 previousElement.parentNode.removeChild( previousElement ) ; 187 return true ; 188 } 189 } 190 } 191 192 var oStartBlock = oRange.StartBlock ; 193 var oEndBlock = oRange.EndBlock ; 194 195 // The selection boundaries must be in the same "block limit" element 196 if ( oRange.StartBlockLimit == oRange.EndBlockLimit && oStartBlock && oEndBlock ) 197 { 198 if ( !isCollapsed ) 199 { 200 var bEndOfBlock = oRange.CheckEndOfBlock() ; 201 202 oRange.DeleteContents() ; 203 204 if ( oStartBlock != oEndBlock ) 205 { 206 oRange.SetStart(oEndBlock,1) ; 207 oRange.SetEnd(oEndBlock,1) ; 208 209 // if ( bEndOfBlock ) 210 // oEndBlock.parentNode.removeChild( oEndBlock ) ; 211 } 212 213 oRange.Select() ; 214 215 bCustom = ( oStartBlock == oEndBlock ) ; 216 } 217 218 if ( oRange.CheckStartOfBlock() ) 219 { 220 var oCurrentBlock = oRange.StartBlock ; 221 222 var ePrevious = FCKDomTools.GetPreviousSourceElement( oCurrentBlock, true, [ 'BODY', oRange.StartBlockLimit.nodeName ], ['UL','OL'] ) ; 223 224 bCustom = this._ExecuteBackspace( oRange, ePrevious, oCurrentBlock ) ; 225 } 226 else if ( FCKBrowserInfo.IsGeckoLike ) 227 { 228 // Firefox and Opera (#1095) loose the selection when executing 229 // CheckStartOfBlock, so we must reselect. 230 oRange.Select() ; 231 } 232 } 233 234 oRange.Release() ; 235 return bCustom ; 236 } 237 238 FCKEnterKey.prototype.DoCtrlBackspace = function() 239 { 240 FCKUndo.SaveUndoStep() ; 241 var oRange = new FCKDomRange( this.Window ) ; 242 oRange.MoveToSelection() ; 243 if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) ) 244 { 245 this._FixIESelectAllBug( oRange ) ; 246 return true ; 247 } 248 return false ; 249 } 250 251 FCKEnterKey.prototype._ExecuteBackspace = function( range, previous, currentBlock ) 252 { 253 var bCustom = false ; 254 255 // We could be in a nested LI. 256 if ( !previous && currentBlock && currentBlock.nodeName.IEquals( 'LI' ) && currentBlock.parentNode.parentNode.nodeName.IEquals( 'LI' ) ) 257 { 258 this._OutdentWithSelection( currentBlock, range ) ; 259 return true ; 260 } 261 262 if ( previous && previous.nodeName.IEquals( 'LI' ) ) 263 { 264 var oNestedList = FCKDomTools.GetLastChild( previous, ['UL','OL'] ) ; 265 266 while ( oNestedList ) 267 { 268 previous = FCKDomTools.GetLastChild( oNestedList, 'LI' ) ; 269 oNestedList = FCKDomTools.GetLastChild( previous, ['UL','OL'] ) ; 270 } 271 } 272 273 if ( previous && currentBlock ) 274 { 275 // If we are in a LI, and the previous block is not an LI, we must outdent it. 276 if ( currentBlock.nodeName.IEquals( 'LI' ) && !previous.nodeName.IEquals( 'LI' ) ) 277 { 278 this._OutdentWithSelection( currentBlock, range ) ; 279 return true ; 280 } 281 282 // Take a reference to the parent for post processing cleanup. 283 var oCurrentParent = currentBlock.parentNode ; 284 285 var sPreviousName = previous.nodeName.toLowerCase() ; 286 if ( FCKListsLib.EmptyElements[ sPreviousName ] != null || sPreviousName == 'table' ) 287 { 288 FCKDomTools.RemoveNode( previous ) ; 289 bCustom = true ; 290 } 291 else 292 { 293 // Remove the current block. 294 FCKDomTools.RemoveNode( currentBlock ) ; 295 296 // Remove any empty tag left by the block removal. 297 while ( oCurrentParent.innerHTML.Trim().length == 0 ) 298 { 299 var oParent = oCurrentParent.parentNode ; 300 oParent.removeChild( oCurrentParent ) ; 301 oCurrentParent = oParent ; 302 } 303 304 // Cleanup the previous and the current elements. 305 FCKDomTools.LTrimNode( currentBlock ) ; 306 FCKDomTools.RTrimNode( previous ) ; 307 308 // Append a space to the previous. 309 // Maybe it is not always desirable... 310 // previous.appendChild( this.Window.document.createTextNode( ' ' ) ) ; 311 312 // Set the range to the end of the previous element and bookmark it. 313 range.SetStart( previous, 2, true ) ; 314 range.Collapse( true ) ; 315 var oBookmark = range.CreateBookmark( true ) ; 316 317 // Move the contents of the block to the previous element and delete it. 318 // But for some block types (e.g. table), moving the children to the previous block makes no sense. 319 // So a check is needed. (See #1081) 320 if ( ! currentBlock.tagName.IEquals( [ 'TABLE' ] ) ) 321 FCKDomTools.MoveChildren( currentBlock, previous ) ; 322 323 // Place the selection at the bookmark. 324 range.SelectBookmark( oBookmark ) ; 325 326 bCustom = true ; 327 } 328 } 329 330 return bCustom ; 331 } 332 333 /* 334 * Executes the <Delete> key behavior. 335 */ 336 FCKEnterKey.prototype.DoDelete = function() 337 { 338 // Save an undo snapshot before doing anything 339 // This is to conform with the behavior seen in MS Word 340 FCKUndo.SaveUndoStep() ; 341 342 // The <Delete> has the same effect as the <Backspace>, so we have the same 343 // results if we just move to the next block and apply the same <Backspace> logic. 344 345 var bCustom = false ; 346 347 // Get the current selection. 348 var oRange = new FCKDomRange( this.Window ) ; 349 oRange.MoveToSelection() ; 350 351 // Kludge for #247 352 if ( FCKBrowserInfo.IsIE && this._CheckIsAllContentsIncluded( oRange, this.Window.document.body ) ) 353 { 354 this._FixIESelectAllBug( oRange ) ; 355 return true ; 356 } 357 358 // There is just one special case for collapsed selections at the end of a block. 359 if ( oRange.CheckIsCollapsed() && oRange.CheckEndOfBlock( FCKBrowserInfo.IsGeckoLike ) ) 360 { 361 var oCurrentBlock = oRange.StartBlock ; 362 var eCurrentCell = FCKTools.GetElementAscensor( oCurrentBlock, 'td' ); 363 364 var eNext = FCKDomTools.GetNextSourceElement( oCurrentBlock, true, [ oRange.StartBlockLimit.nodeName ], 365 ['UL','OL','TR'], true ) ; 366 367 // Bug #1323 : if we're in a table cell, and the next node belongs to a different cell, then don't 368 // delete anything. 369 if ( eCurrentCell ) 370 { 371 var eNextCell = FCKTools.GetElementAscensor( eNext, 'td' ); 372 if ( eNextCell != eCurrentCell ) 373 return true ; 374 } 375 376 bCustom = this._ExecuteBackspace( oRange, oCurrentBlock, eNext ) ; 377 } 378 379 oRange.Release() ; 380 return bCustom ; 381 } 382 383 /* 384 * Executes the <Tab> key behavior. 385 */ 386 FCKEnterKey.prototype.DoTab = function() 387 { 388 var oRange = new FCKDomRange( this.Window ); 389 oRange.MoveToSelection() ; 390 391 // If the user pressed <tab> inside a table, we should give him the default behavior ( moving between cells ) 392 // instead of giving him more non-breaking spaces. (Bug #973) 393 var node = oRange._Range.startContainer ; 394 while ( node ) 395 { 396 if ( node.nodeType == 1 ) 397 { 398 var tagName = node.tagName.toLowerCase() ; 399 if ( tagName == "tr" || tagName == "td" || tagName == "th" || tagName == "tbody" || tagName == "table" ) 400 return false ; 401 else 402 break ; 403 } 404 node = node.parentNode ; 405 } 406 407 if ( this.TabText ) 408 { 409 oRange.DeleteContents() ; 410 oRange.InsertNode( this.Window.document.createTextNode( this.TabText ) ) ; 411 oRange.Collapse( false ) ; 412 oRange.Select() ; 413 } 414 return true ; 415 } 416 417 FCKEnterKey.prototype._ExecuteEnterBlock = function( blockTag, range ) 418 { 419 // Get the current selection. 420 var oRange = range || new FCKDomRange( this.Window ) ; 421 422 var oSplitInfo = oRange.SplitBlock( blockTag ) ; 423 424 if ( oSplitInfo ) 425 { 426 // Get the current blocks. 427 var ePreviousBlock = oSplitInfo.PreviousBlock ; 428 var eNextBlock = oSplitInfo.NextBlock ; 429 430 var bIsStartOfBlock = oSplitInfo.WasStartOfBlock ; 431 var bIsEndOfBlock = oSplitInfo.WasEndOfBlock ; 432 433 // If there is one block under a list item, modify the split so that the list item gets split as well. (Bug #1647) 434 if ( eNextBlock ) 435 { 436 if ( eNextBlock.parentNode.nodeName.IEquals( 'li' ) ) 437 { 438 FCKDomTools.BreakParent( eNextBlock, eNextBlock.parentNode ) ; 439 FCKDomTools.MoveNode( eNextBlock, eNextBlock.nextSibling, true ) ; 440 } 441 } 442 else if ( ePreviousBlock && ePreviousBlock.parentNode.nodeName.IEquals( 'li' ) ) 443 { 444 FCKDomTools.BreakParent( ePreviousBlock, ePreviousBlock.parentNode ) ; 445 oRange.MoveToElementEditStart( ePreviousBlock.nextSibling ); 446 FCKDomTools.MoveNode( ePreviousBlock, ePreviousBlock.previousSibling ) ; 447 } 448 449 // If we have both the previous and next blocks, it means that the 450 // boundaries were on separated blocks, or none of them where on the 451 // block limits (start/end). 452 if ( !bIsStartOfBlock && !bIsEndOfBlock ) 453 { 454 // If the next block is an <li> with another list tree as the first child 455 // We'll need to append a placeholder or the list item wouldn't be editable. (Bug #1420) 456 if ( eNextBlock.nodeName.IEquals( 'li' ) && eNextBlock.firstChild 457 && eNextBlock.firstChild.nodeName.IEquals( ['ul', 'ol'] ) ) 458 eNextBlock.insertBefore( FCKTools.GetElementDocument( eNextBlock ).createTextNode( '\xa0' ), eNextBlock.firstChild ) ; 459 // Move the selection to the end block. 460 if ( eNextBlock ) 461 oRange.MoveToElementEditStart( eNextBlock ) ; 462 } 463 else 464 { 465 if ( bIsStartOfBlock && bIsEndOfBlock && ePreviousBlock.tagName.toUpperCase() == 'LI' ) 466 { 467 oRange.MoveToElementStart( ePreviousBlock ) ; 468 this._OutdentWithSelection( ePreviousBlock, oRange ) ; 469 oRange.Release() ; 470 return true ; 471 } 472 473 var eNewBlock ; 474 475 if ( ePreviousBlock ) 476 { 477 var sPreviousBlockTag = ePreviousBlock.tagName.toUpperCase() ; 478 479 // If is a header tag, or we are in a Shift+Enter (#77), 480 // create a new block element (later in the code). 481 if ( !this._HasShift && !(/^H[1-6]$/).test( sPreviousBlockTag ) ) 482 { 483 // Otherwise, duplicate the previous block. 484 eNewBlock = FCKDomTools.CloneElement( ePreviousBlock ) ; 485 } 486 } 487 else if ( eNextBlock ) 488 eNewBlock = FCKDomTools.CloneElement( eNextBlock ) ; 489 490 if ( !eNewBlock ) 491 eNewBlock = this.Window.document.createElement( blockTag ) ; 492 493 // Recreate the inline elements tree, which was available 494 // before the hitting enter, so the same styles will be 495 // available in the new block. 496 var elementPath = oSplitInfo.ElementPath ; 497 if ( elementPath ) 498 { 499 for ( var i = 0, len = elementPath.Elements.length ; i < len ; i++ ) 500 { 501 var element = elementPath.Elements[i] ; 502 503 if ( element == elementPath.Block || element == elementPath.BlockLimit ) 504 break ; 505 506 if ( FCKListsLib.InlineChildReqElements[ element.nodeName.toLowerCase() ] ) 507 { 508 element = FCKDomTools.CloneElement( element ) ; 509 FCKDomTools.MoveChildren( eNewBlock, element ) ; 510 eNewBlock.appendChild( element ) ; 511 } 512 } 513 } 514 515 if ( FCKBrowserInfo.IsGeckoLike ) 516 FCKTools.AppendBogusBr( eNewBlock ) ; 517 518 oRange.InsertNode( eNewBlock ) ; 519 520 // This is tricky, but to make the new block visible correctly 521 // we must select it. 522 if ( FCKBrowserInfo.IsIE ) 523 { 524 // Move the selection to the new block. 525 oRange.MoveToElementEditStart( eNewBlock ) ; 526 oRange.Select() ; 527 } 528 529 // Move the selection to the new block. 530 oRange.MoveToElementEditStart( bIsStartOfBlock && !bIsEndOfBlock ? eNextBlock : eNewBlock ) ; 531 } 532 533 if ( FCKBrowserInfo.IsGeckoLike ) 534 { 535 if ( eNextBlock ) 536 { 537 // If we have split the block, adds a temporary span at the 538 // range position and scroll relatively to it. 539 var tmpNode = this.Window.document.createElement( 'span' ) ; 540 541 // We need some content for Safari. 542 tmpNode.innerHTML = ' '; 543 544 oRange.InsertNode( tmpNode ) ; 545 FCKDomTools.ScrollIntoView( tmpNode, false ) ; 546 oRange.DeleteContents() ; 547 } 548 else 549 { 550 // We may use the above scroll logic for the new block case 551 // too, but it gives some weird result with Opera. 552 FCKDomTools.ScrollIntoView( eNextBlock || eNewBlock, false ) ; 553 } 554 } 555 556 oRange.Select() ; 557 } 558 559 // Release the resources used by the range. 560 oRange.Release() ; 561 562 return true ; 563 } 564 565 FCKEnterKey.prototype._ExecuteEnterBr = function( blockTag ) 566 { 567 // Get the current selection. 568 var oRange = new FCKDomRange( this.Window ) ; 569 oRange.MoveToSelection() ; 570 571 // The selection boundaries must be in the same "block limit" element. 572 if ( oRange.StartBlockLimit == oRange.EndBlockLimit ) 573 { 574 oRange.DeleteContents() ; 575 576 // Get the new selection (it is collapsed at this point). 577 oRange.MoveToSelection() ; 578 579 var bIsStartOfBlock = oRange.CheckStartOfBlock() ; 580 var bIsEndOfBlock = oRange.CheckEndOfBlock() ; 581 582 var sStartBlockTag = oRange.StartBlock ? oRange.StartBlock.tagName.toUpperCase() : '' ; 583 584 var bHasShift = this._HasShift ; 585 var bIsPre = false ; 586 587 if ( !bHasShift && sStartBlockTag == 'LI' ) 588 return this._ExecuteEnterBlock( null, oRange ) ; 589 590 // If we are at the end of a header block. 591 if ( !bHasShift && bIsEndOfBlock && (/^H[1-6]$/).test( sStartBlockTag ) ) 592 { 593 // Insert a BR after the current paragraph. 594 FCKDomTools.InsertAfterNode( oRange.StartBlock, this.Window.document.createElement( 'br' ) ) ; 595 596 // The space is required by Gecko only to make the cursor blink. 597 if ( FCKBrowserInfo.IsGecko ) 598 FCKDomTools.InsertAfterNode( oRange.StartBlock, this.Window.document.createTextNode( '' ) ) ; 599 600 // IE and Gecko have different behaviors regarding the position. 601 oRange.SetStart( oRange.StartBlock.nextSibling, FCKBrowserInfo.IsIE ? 3 : 1 ) ; 602 } 603 else 604 { 605 var eLineBreak ; 606 bIsPre = sStartBlockTag.IEquals( 'pre' ) ; 607 if ( bIsPre ) 608 eLineBreak = this.Window.document.createTextNode( FCKBrowserInfo.IsIE ? '\r' : '\n' ) ; 609 else 610 eLineBreak = this.Window.document.createElement( 'br' ) ; 611 612 oRange.InsertNode( eLineBreak ) ; 613 614 // The space is required by Gecko only to make the cursor blink. 615 if ( FCKBrowserInfo.IsGecko ) 616 FCKDomTools.InsertAfterNode( eLineBreak, this.Window.document.createTextNode( '' ) ) ; 617 618 // If we are at the end of a block, we must be sure the bogus node is available in that block. 619 if ( bIsEndOfBlock && FCKBrowserInfo.IsGeckoLike ) 620 FCKTools.AppendBogusBr( eLineBreak.parentNode ) ; 621 622 if ( FCKBrowserInfo.IsIE ) 623 oRange.SetStart( eLineBreak, 4 ) ; 624 else 625 oRange.SetStart( eLineBreak.nextSibling, 1 ) ; 626 627 if ( ! FCKBrowserInfo.IsIE ) 628 { 629 var dummy = null ; 630 if ( FCKBrowserInfo.IsOpera ) 631 dummy = this.Window.document.createElement( 'span' ) ; 632 else 633 dummy = this.Window.document.createElement( 'br' ) ; 634 635 eLineBreak.parentNode.insertBefore( dummy, eLineBreak.nextSibling ) ; 636 637 FCKDomTools.ScrollIntoView( dummy, false ) ; 638 639 dummy.parentNode.removeChild( dummy ) ; 640 } 641 } 642 643 // This collapse guarantees the cursor will be blinking. 644 oRange.Collapse( true ) ; 645 646 oRange.Select( bIsPre ) ; 647 } 648 649 // Release the resources used by the range. 650 oRange.Release() ; 651 652 return true ; 653 } 654 655 // Outdents a LI, maintaining the selection defined on a range. 656 FCKEnterKey.prototype._OutdentWithSelection = function( li, range ) 657 { 658 var oBookmark = range.CreateBookmark() ; 659 660 FCKListHandler.OutdentListItem( li ) ; 661 662 range.MoveToBookmark( oBookmark ) ; 663 range.Select() ; 664 } 665 666 // Is all the contents under a node included by a range? 667 FCKEnterKey.prototype._CheckIsAllContentsIncluded = function( range, node ) 668 { 669 var startOk = false ; 670 var endOk = false ; 671 672 /* 673 FCKDebug.Output( 'sc='+range.StartContainer.nodeName+ 674 ',so='+range._Range.startOffset+ 675 ',ec='+range.EndContainer.nodeName+ 676 ',eo='+range._Range.endOffset ) ; 677 */ 678 if ( range.StartContainer == node || range.StartContainer == node.firstChild ) 679 startOk = ( range._Range.startOffset == 0 ) ; 680 681 if ( range.EndContainer == node || range.EndContainer == node.lastChild ) 682 { 683 var nodeLength = range.EndContainer.nodeType == 3 ? range.EndContainer.length : range.EndContainer.childNodes.length ; 684 endOk = ( range._Range.endOffset == nodeLength ) ; 685 } 686 687 return startOk && endOk ; 688 } 689 690 // Kludge for #247 691 FCKEnterKey.prototype._FixIESelectAllBug = function( range ) 692 { 693 var doc = this.Window.document ; 694 doc.body.innerHTML = '' ; 695 var editBlock ; 696 if ( FCKConfig.EnterMode.IEquals( ['div', 'p'] ) ) 697 { 698 editBlock = doc.createElement( FCKConfig.EnterMode ) ; 699 doc.body.appendChild( editBlock ) ; 700 } 701 else 702 editBlock = doc.body ; 703 704 range.MoveToNodeContents( editBlock ) ; 705 range.Collapse( true ) ; 706 range.Select() ; 707 range.Release() ; 708 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |