| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 /* 2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 /** 7 * @fileOverview Defines the {@link CKEDITOR.dom.node} class, which is the base 8 * class for classes that represent DOM nodes. 9 */ 10 11 /** 12 * Base class for classes representing DOM nodes. This constructor may return 13 * and instance of classes that inherits this class, like 14 * {@link CKEDITOR.dom.element} or {@link CKEDITOR.dom.text}. 15 * @augments CKEDITOR.dom.domObject 16 * @param {Object} domNode A native DOM node. 17 * @constructor 18 * @see CKEDITOR.dom.element 19 * @see CKEDITOR.dom.text 20 * @example 21 */ 22 CKEDITOR.dom.node = function( domNode ) 23 { 24 if ( domNode ) 25 { 26 switch ( domNode.nodeType ) 27 { 28 // Safari don't consider document as element node type. (#3389) 29 case CKEDITOR.NODE_DOCUMENT : 30 return new CKEDITOR.dom.document( domNode ); 31 32 case CKEDITOR.NODE_ELEMENT : 33 return new CKEDITOR.dom.element( domNode ); 34 35 case CKEDITOR.NODE_TEXT : 36 return new CKEDITOR.dom.text( domNode ); 37 } 38 39 // Call the base constructor. 40 CKEDITOR.dom.domObject.call( this, domNode ); 41 } 42 43 return this; 44 }; 45 46 CKEDITOR.dom.node.prototype = new CKEDITOR.dom.domObject(); 47 48 /** 49 * Element node type. 50 * @constant 51 * @example 52 */ 53 CKEDITOR.NODE_ELEMENT = 1; 54 55 /** 56 * Document node type. 57 * @constant 58 * @example 59 */ 60 CKEDITOR.NODE_DOCUMENT = 9; 61 62 /** 63 * Text node type. 64 * @constant 65 * @example 66 */ 67 CKEDITOR.NODE_TEXT = 3; 68 69 /** 70 * Comment node type. 71 * @constant 72 * @example 73 */ 74 CKEDITOR.NODE_COMMENT = 8; 75 76 CKEDITOR.NODE_DOCUMENT_FRAGMENT = 11; 77 78 CKEDITOR.POSITION_IDENTICAL = 0; 79 CKEDITOR.POSITION_DISCONNECTED = 1; 80 CKEDITOR.POSITION_FOLLOWING = 2; 81 CKEDITOR.POSITION_PRECEDING = 4; 82 CKEDITOR.POSITION_IS_CONTAINED = 8; 83 CKEDITOR.POSITION_CONTAINS = 16; 84 85 CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, 86 /** @lends CKEDITOR.dom.node.prototype */ 87 { 88 /** 89 * Makes this node child of another element. 90 * @param {CKEDITOR.dom.element} element The target element to which append 91 * this node. 92 * @returns {CKEDITOR.dom.element} The target element. 93 * @example 94 * var p = new CKEDITOR.dom.element( 'p' ); 95 * var strong = new CKEDITOR.dom.element( 'strong' ); 96 * strong.appendTo( p ); 97 * 98 * // result: "<p><strong></strong></p>" 99 */ 100 appendTo : function( element, toStart ) 101 { 102 element.append( this, toStart ); 103 return element; 104 }, 105 106 clone : function( includeChildren, cloneId ) 107 { 108 var $clone = this.$.cloneNode( includeChildren ); 109 110 if ( !cloneId ) 111 { 112 var removeIds = function( node ) 113 { 114 if ( node.nodeType != CKEDITOR.NODE_ELEMENT ) 115 return; 116 117 node.removeAttribute( 'id', false ) ; 118 node.removeAttribute( '_cke_expando', false ) ; 119 120 var childs = node.childNodes; 121 for ( var i=0 ; i < childs.length ; i++ ) 122 removeIds( childs[ i ] ); 123 }; 124 125 // The "id" attribute should never be cloned to avoid duplication. 126 removeIds( $clone ); 127 } 128 129 return new CKEDITOR.dom.node( $clone ); 130 }, 131 132 hasPrevious : function() 133 { 134 return !!this.$.previousSibling; 135 }, 136 137 hasNext : function() 138 { 139 return !!this.$.nextSibling; 140 }, 141 142 /** 143 * Inserts this element after a node. 144 * @param {CKEDITOR.dom.node} node The that will preceed this element. 145 * @returns {CKEDITOR.dom.node} The node preceeding this one after 146 * insertion. 147 * @example 148 * var em = new CKEDITOR.dom.element( 'em' ); 149 * var strong = new CKEDITOR.dom.element( 'strong' ); 150 * strong.insertAfter( em ); 151 * 152 * // result: "<em></em><strong></strong>" 153 */ 154 insertAfter : function( node ) 155 { 156 node.$.parentNode.insertBefore( this.$, node.$.nextSibling ); 157 return node; 158 }, 159 160 /** 161 * Inserts this element before a node. 162 * @param {CKEDITOR.dom.node} node The that will be after this element. 163 * @returns {CKEDITOR.dom.node} The node being inserted. 164 * @example 165 * var em = new CKEDITOR.dom.element( 'em' ); 166 * var strong = new CKEDITOR.dom.element( 'strong' ); 167 * strong.insertBefore( em ); 168 * 169 * // result: "<strong></strong><em></em>" 170 */ 171 insertBefore : function( node ) 172 { 173 node.$.parentNode.insertBefore( this.$, node.$ ); 174 return node; 175 }, 176 177 insertBeforeMe : function( node ) 178 { 179 this.$.parentNode.insertBefore( node.$, this.$ ); 180 return node; 181 }, 182 183 /** 184 * Retrieves a uniquely identifiable tree address for this node. 185 * The tree address returns is an array of integers, with each integer 186 * indicating a child index of a DOM node, starting from 187 * document.documentElement. 188 * 189 * For example, assuming <body> is the second child from <html> (<head> 190 * being the first), and we'd like to address the third child under the 191 * fourth child of body, the tree address returned would be: 192 * [1, 3, 2] 193 * 194 * The tree address cannot be used for finding back the DOM tree node once 195 * the DOM tree structure has been modified. 196 */ 197 getAddress : function( normalized ) 198 { 199 var address = []; 200 var $documentElement = this.getDocument().$.documentElement; 201 var node = this.$; 202 203 while ( node && node != $documentElement ) 204 { 205 var parentNode = node.parentNode; 206 var currentIndex = -1; 207 208 if ( parentNode ) 209 { 210 for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) 211 { 212 var candidate = parentNode.childNodes[i]; 213 214 if ( normalized && 215 candidate.nodeType == 3 && 216 candidate.previousSibling && 217 candidate.previousSibling.nodeType == 3 ) 218 { 219 continue; 220 } 221 222 currentIndex++; 223 224 if ( candidate == node ) 225 break; 226 } 227 228 address.unshift( currentIndex ); 229 } 230 231 node = parentNode; 232 } 233 234 return address; 235 }, 236 237 /** 238 * Gets the document containing this element. 239 * @returns {CKEDITOR.dom.document} The document. 240 * @example 241 * var element = CKEDITOR.document.getById( 'example' ); 242 * alert( <b>element.getDocument().equals( CKEDITOR.document )</b> ); // "true" 243 */ 244 getDocument : function() 245 { 246 var document = new CKEDITOR.dom.document( this.$.ownerDocument || this.$.parentNode.ownerDocument ); 247 248 return ( 249 this.getDocument = function() 250 { 251 return document; 252 })(); 253 }, 254 255 getIndex : function() 256 { 257 var $ = this.$; 258 259 var currentNode = $.parentNode && $.parentNode.firstChild; 260 var currentIndex = -1; 261 262 while ( currentNode ) 263 { 264 currentIndex++; 265 266 if ( currentNode == $ ) 267 return currentIndex; 268 269 currentNode = currentNode.nextSibling; 270 } 271 272 return -1; 273 }, 274 275 getNextSourceNode : function( startFromSibling, nodeType, guard ) 276 { 277 // If "guard" is a node, transform it in a function. 278 if ( guard && !guard.call ) 279 { 280 var guardNode = guard; 281 guard = function( node ) 282 { 283 return !node.equals( guardNode ); 284 }; 285 } 286 287 var node = ( !startFromSibling && this.getFirst && this.getFirst() ), 288 parent; 289 290 // Guarding when we're skipping the current element( no children or 'startFromSibling' ). 291 // send the 'moving out' signal even we don't actually dive into. 292 if ( !node ) 293 { 294 if ( this.type == CKEDITOR.NODE_ELEMENT && guard && guard( this, true ) === false ) 295 return null; 296 node = this.getNext(); 297 } 298 299 while ( !node && ( parent = ( parent || this ).getParent() ) ) 300 { 301 // The guard check sends the "true" paramenter to indicate that 302 // we are moving "out" of the element. 303 if ( guard && guard( parent, true ) === false ) 304 return null; 305 306 node = parent.getNext(); 307 } 308 309 if ( !node ) 310 return null; 311 312 if ( guard && guard( node ) === false ) 313 return null; 314 315 if ( nodeType && nodeType != node.type ) 316 return node.getNextSourceNode( false, nodeType, guard ); 317 318 return node; 319 }, 320 321 getPreviousSourceNode : function( startFromSibling, nodeType, guard ) 322 { 323 if ( guard && !guard.call ) 324 { 325 var guardNode = guard; 326 guard = function( node ) 327 { 328 return !node.equals( guardNode ); 329 }; 330 } 331 332 var node = ( !startFromSibling && this.getLast && this.getLast() ), 333 parent; 334 335 // Guarding when we're skipping the current element( no children or 'startFromSibling' ). 336 // send the 'moving out' signal even we don't actually dive into. 337 if ( !node ) 338 { 339 if ( this.type == CKEDITOR.NODE_ELEMENT && guard && guard( this, true ) === false ) 340 return null; 341 node = this.getPrevious(); 342 } 343 344 while ( !node && ( parent = ( parent || this ).getParent() ) ) 345 { 346 // The guard check sends the "true" paramenter to indicate that 347 // we are moving "out" of the element. 348 if ( guard && guard( parent, true ) === false ) 349 return null; 350 351 node = parent.getPrevious(); 352 } 353 354 if ( !node ) 355 return null; 356 357 if ( guard && guard( node ) === false ) 358 return null; 359 360 if ( nodeType && node.type != nodeType ) 361 return node.getPreviousSourceNode( false, nodeType, guard ); 362 363 return node; 364 }, 365 366 getPrevious : function( evaluator ) 367 { 368 var previous = this.$, retval; 369 do 370 { 371 previous = previous.previousSibling; 372 retval = previous && new CKEDITOR.dom.node( previous ); 373 } 374 while ( retval && evaluator && !evaluator( retval ) ) 375 return retval; 376 }, 377 378 /** 379 * Gets the node that follows this element in its parent's child list. 380 * @param {Function} evaluator Filtering the result node. 381 * @returns {CKEDITOR.dom.node} The next node or null if not available. 382 * @example 383 * var element = CKEDITOR.dom.element.createFromHtml( '<div><b>Example</b> <i>next</i></div>' ); 384 * var first = <b>element.getFirst().getNext()</b>; 385 * alert( first.getName() ); // "i" 386 */ 387 getNext : function( evaluator ) 388 { 389 var next = this.$, retval; 390 do 391 { 392 next = next.nextSibling; 393 retval = next && new CKEDITOR.dom.node( next ); 394 } 395 while ( retval && evaluator && !evaluator( retval ) ) 396 return retval; 397 }, 398 399 /** 400 * Gets the parent element for this node. 401 * @returns {CKEDITOR.dom.element} The parent element. 402 * @example 403 * var node = editor.document.getBody().getFirst(); 404 * var parent = node.<b>getParent()</b>; 405 * alert( node.getName() ); // "body" 406 */ 407 getParent : function() 408 { 409 var parent = this.$.parentNode; 410 return ( parent && parent.nodeType == 1 ) ? new CKEDITOR.dom.node( parent ) : null; 411 }, 412 413 getParents : function( closerFirst ) 414 { 415 var node = this; 416 var parents = []; 417 418 do 419 { 420 parents[ closerFirst ? 'push' : 'unshift' ]( node ); 421 } 422 while ( ( node = node.getParent() ) ) 423 424 return parents; 425 }, 426 427 getCommonAncestor : function( node ) 428 { 429 if ( node.equals( this ) ) 430 return this; 431 432 if ( node.contains && node.contains( this ) ) 433 return node; 434 435 var start = this.contains ? this : this.getParent(); 436 437 do 438 { 439 if ( start.contains( node ) ) 440 return start; 441 } 442 while ( ( start = start.getParent() ) ); 443 444 return null; 445 }, 446 447 getPosition : function( otherNode ) 448 { 449 var $ = this.$; 450 var $other = otherNode.$; 451 452 if ( $.compareDocumentPosition ) 453 return $.compareDocumentPosition( $other ); 454 455 // IE and Safari have no support for compareDocumentPosition. 456 457 if ( $ == $other ) 458 return CKEDITOR.POSITION_IDENTICAL; 459 460 // Only element nodes support contains and sourceIndex. 461 if ( this.type == CKEDITOR.NODE_ELEMENT && otherNode.type == CKEDITOR.NODE_ELEMENT ) 462 { 463 if ( $.contains ) 464 { 465 if ( $.contains( $other ) ) 466 return CKEDITOR.POSITION_CONTAINS + CKEDITOR.POSITION_PRECEDING; 467 468 if ( $other.contains( $ ) ) 469 return CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING; 470 } 471 472 if ( 'sourceIndex' in $ ) 473 { 474 return ( $.sourceIndex < 0 || $other.sourceIndex < 0 ) ? CKEDITOR.POSITION_DISCONNECTED : 475 ( $.sourceIndex < $other.sourceIndex ) ? CKEDITOR.POSITION_PRECEDING : 476 CKEDITOR.POSITION_FOLLOWING; 477 } 478 } 479 480 // For nodes that don't support compareDocumentPosition, contains 481 // or sourceIndex, their "address" is compared. 482 483 var addressOfThis = this.getAddress(), 484 addressOfOther = otherNode.getAddress(), 485 minLevel = Math.min( addressOfThis.length, addressOfOther.length ); 486 487 // Determinate preceed/follow relationship. 488 for ( var i = 0 ; i <= minLevel - 1 ; i++ ) 489 { 490 if ( addressOfThis[ i ] != addressOfOther[ i ] ) 491 { 492 if ( i < minLevel ) 493 { 494 return addressOfThis[ i ] < addressOfOther[ i ] ? 495 CKEDITOR.POSITION_PRECEDING : CKEDITOR.POSITION_FOLLOWING; 496 } 497 break; 498 } 499 } 500 501 // Determinate contains/contained relationship. 502 return ( addressOfThis.length < addressOfOther.length ) ? 503 CKEDITOR.POSITION_CONTAINS + CKEDITOR.POSITION_PRECEDING : 504 CKEDITOR.POSITION_IS_CONTAINED + CKEDITOR.POSITION_FOLLOWING; 505 }, 506 507 /** 508 * Gets the closes ancestor node of a specified node name. 509 * @param {String} name Node name of ancestor node. 510 * @param {Boolean} includeSelf (Optional) Whether to include the current 511 * node in the calculation or not. 512 * @returns {CKEDITOR.dom.node} Ancestor node. 513 */ 514 getAscendant : function( name, includeSelf ) 515 { 516 var $ = this.$; 517 518 if ( !includeSelf ) 519 $ = $.parentNode; 520 521 while ( $ ) 522 { 523 if ( $.nodeName && $.nodeName.toLowerCase() == name ) 524 return new CKEDITOR.dom.node( $ ); 525 526 $ = $.parentNode; 527 } 528 return null; 529 }, 530 531 hasAscendant : function( name, includeSelf ) 532 { 533 var $ = this.$; 534 535 if ( !includeSelf ) 536 $ = $.parentNode; 537 538 while ( $ ) 539 { 540 if ( $.nodeName && $.nodeName.toLowerCase() == name ) 541 return true; 542 543 $ = $.parentNode; 544 } 545 return false; 546 }, 547 548 move : function( target, toStart ) 549 { 550 target.append( this.remove(), toStart ); 551 }, 552 553 /** 554 * Removes this node from the document DOM. 555 * @param {Boolean} [preserveChildren] Indicates that the children 556 * elements must remain in the document, removing only the outer 557 * tags. 558 * @example 559 * var element = CKEDITOR.dom.element.getById( 'MyElement' ); 560 * <b>element.remove()</b>; 561 */ 562 remove : function( preserveChildren ) 563 { 564 var $ = this.$; 565 var parent = $.parentNode; 566 567 if ( parent ) 568 { 569 if ( preserveChildren ) 570 { 571 // Move all children before the node. 572 for ( var child ; ( child = $.firstChild ) ; ) 573 { 574 parent.insertBefore( $.removeChild( child ), $ ); 575 } 576 } 577 578 parent.removeChild( $ ); 579 } 580 581 return this; 582 }, 583 584 replace : function( nodeToReplace ) 585 { 586 this.insertBefore( nodeToReplace ); 587 nodeToReplace.remove(); 588 }, 589 590 trim : function() 591 { 592 this.ltrim(); 593 this.rtrim(); 594 }, 595 596 ltrim : function() 597 { 598 var child; 599 while ( this.getFirst && ( child = this.getFirst() ) ) 600 { 601 if ( child.type == CKEDITOR.NODE_TEXT ) 602 { 603 var trimmed = CKEDITOR.tools.ltrim( child.getText() ), 604 originalLength = child.getLength(); 605 606 if ( !trimmed ) 607 { 608 child.remove(); 609 continue; 610 } 611 else if ( trimmed.length < originalLength ) 612 { 613 child.split( originalLength - trimmed.length ); 614 615 // IE BUG: child.remove() may raise JavaScript errors here. (#81) 616 this.$.removeChild( this.$.firstChild ); 617 } 618 } 619 break; 620 } 621 }, 622 623 rtrim : function() 624 { 625 var child; 626 while ( this.getLast && ( child = this.getLast() ) ) 627 { 628 if ( child.type == CKEDITOR.NODE_TEXT ) 629 { 630 var trimmed = CKEDITOR.tools.rtrim( child.getText() ), 631 originalLength = child.getLength(); 632 633 if ( !trimmed ) 634 { 635 child.remove(); 636 continue; 637 } 638 else if ( trimmed.length < originalLength ) 639 { 640 child.split( trimmed.length ); 641 642 // IE BUG: child.getNext().remove() may raise JavaScript errors here. 643 // (#81) 644 this.$.lastChild.parentNode.removeChild( this.$.lastChild ); 645 } 646 } 647 break; 648 } 649 650 if ( !CKEDITOR.env.ie && !CKEDITOR.env.opera ) 651 { 652 child = this.$.lastChild; 653 654 if ( child && child.type == 1 && child.nodeName.toLowerCase() == 'br' ) 655 { 656 // Use "eChildNode.parentNode" instead of "node" to avoid IE bug (#324). 657 child.parentNode.removeChild( child ) ; 658 } 659 } 660 }, 661 662 isReadOnly : function() 663 { 664 var current = this; 665 while( current ) 666 { 667 if ( current.type == CKEDITOR.NODE_ELEMENT ) 668 { 669 if ( current.is( 'body' ) || current.getCustomData( '_cke_notReadOnly' ) ) 670 break; 671 672 if ( current.getAttribute( 'contentEditable' ) == 'false' ) 673 return current; 674 else if ( current.getAttribute( 'contentEditable' ) == 'true' ) 675 break; 676 } 677 current = current.getParent(); 678 } 679 680 return false; 681 } 682 } 683 );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |