source: branches/2.2/filemanager/tp/ckeditor/_source/core/dom/node.js @ 3019

Revision 3019, 16.1 KB checked in by amuller, 14 years ago (diff)

Ticket #1135 - Corrigindo CSS e adicionando filemanager

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