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

Revision 3019, 11.6 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(function()
7{
8        // This function is to be called under a "walker" instance scope.
9        function iterate( rtl, breakOnFalse )
10        {
11                // Return null if we have reached the end.
12                if ( this._.end )
13                        return null;
14
15                var node,
16                        range = this.range,
17                        guard,
18                        userGuard = this.guard,
19                        type = this.type,
20                        getSourceNodeFn = ( rtl ? 'getPreviousSourceNode' : 'getNextSourceNode' );
21
22                // This is the first call. Initialize it.
23                if ( !this._.start )
24                {
25                        this._.start = 1;
26
27                        // Trim text nodes and optmize the range boundaries. DOM changes
28                        // may happen at this point.
29                        range.trim();
30
31                        // A collapsed range must return null at first call.
32                        if ( range.collapsed )
33                        {
34                                this.end();
35                                return null;
36                        }
37                }
38
39                // Create the LTR guard function, if necessary.
40                if ( !rtl && !this._.guardLTR )
41                {
42                        // Gets the node that stops the walker when going LTR.
43                        var limitLTR = range.endContainer,
44                                blockerLTR = limitLTR.getChild( range.endOffset );
45
46                        this._.guardLTR = function( node, movingOut )
47                        {
48                                return ( ( !movingOut || !limitLTR.equals( node ) )
49                                        && ( !blockerLTR || !node.equals( blockerLTR ) )
50                                        && ( node.type != CKEDITOR.NODE_ELEMENT || node.getName() != 'body' ) );
51                        };
52                }
53
54                // Create the RTL guard function, if necessary.
55                if ( rtl && !this._.guardRTL )
56                {
57                        // Gets the node that stops the walker when going LTR.
58                        var limitRTL = range.startContainer,
59                                blockerRTL = ( range.startOffset > 0 ) && limitRTL.getChild( range.startOffset - 1 );
60
61                        this._.guardRTL = function( node, movingOut )
62                        {
63                                return ( ( !movingOut || !limitRTL.equals( node ) )
64                                        && ( !blockerRTL || !node.equals( blockerRTL ) )
65                                        && ( node.type != CKEDITOR.NODE_ELEMENT || node.getName() != 'body' ) );
66                        };
67                }
68
69                // Define which guard function to use.
70                var stopGuard = rtl ? this._.guardRTL : this._.guardLTR;
71
72                // Make the user defined guard function participate in the process,
73                // otherwise simply use the boundary guard.
74                if ( userGuard )
75                {
76                        guard = function( node, movingOut )
77                        {
78                                if ( stopGuard( node, movingOut ) === false )
79                                        return false;
80
81                                return userGuard( node );
82                        };
83                }
84                else
85                        guard = stopGuard;
86
87                if ( this.current )
88                        node = this.current[ getSourceNodeFn ]( false, type, guard );
89                else
90                {
91                        // Get the first node to be returned.
92
93                        if ( rtl )
94                        {
95                                node = range.endContainer;
96
97                                if ( range.endOffset > 0 )
98                                {
99                                        node = node.getChild( range.endOffset - 1 );
100                                        if ( guard( node ) === false )
101                                                node = null;
102                                }
103                                else
104                                        node = ( guard ( node ) === false ) ?
105                                                null : node.getPreviousSourceNode( true, type, guard );
106                        }
107                        else
108                        {
109                                node = range.startContainer;
110                                node = node.getChild( range.startOffset );
111
112                                if ( node )
113                                {
114                                        if ( guard( node ) === false )
115                                                node = null;
116                                }
117                                else
118                                        node = ( guard ( range.startContainer ) === false ) ?
119                                                null : range.startContainer.getNextSourceNode( true, type, guard ) ;
120                        }
121                }
122
123                while ( node && !this._.end )
124                {
125                        this.current = node;
126
127                        if ( !this.evaluator || this.evaluator( node ) !== false )
128                        {
129                                if ( !breakOnFalse )
130                                        return node;
131                        }
132                        else if ( breakOnFalse && this.evaluator )
133                                return false;
134
135                        node = node[ getSourceNodeFn ]( false, type, guard );
136                }
137
138                this.end();
139                return this.current = null;
140        }
141
142        function iterateToLast( rtl )
143        {
144                var node, last = null;
145
146                while ( ( node = iterate.call( this, rtl ) ) )
147                        last = node;
148
149                return last;
150        }
151
152        CKEDITOR.dom.walker = CKEDITOR.tools.createClass(
153        {
154                /**
155                 * Utility class to "walk" the DOM inside a range boundaries. If
156                 * necessary, partially included nodes (text nodes) are broken to
157                 * reflect the boundaries limits, so DOM and range changes may happen.
158                 * Outside changes to the range may break the walker.
159                 *
160                 * The walker may return nodes that are not totaly included into the
161                 * range boundaires. Let's take the following range representation,
162                 * where the square brackets indicate the boundaries:
163                 *
164                 * [<p>Some <b>sample] text</b>
165                 *
166                 * While walking forward into the above range, the following nodes are
167                 * returned: <p>, "Some ", <b> and "sample". Going
168                 * backwards instead we have: "sample" and "Some ". So note that the
169                 * walker always returns nodes when "entering" them, but not when
170                 * "leaving" them. The guard function is instead called both when
171                 * entering and leaving nodes.
172                 *
173                 * @constructor
174                 * @param {CKEDITOR.dom.range} range The range within which walk.
175                 */
176                $ : function( range )
177                {
178                        this.range = range;
179
180                        /**
181                         * A function executed for every matched node, to check whether
182                         * it's to be considered into the walk or not. If not provided, all
183                         * matched nodes are considered good.
184                         * If the function returns "false" the node is ignored.
185                         * @name CKEDITOR.dom.walker.prototype.evaluator
186                         * @property
187                         * @type Function
188                         */
189                        // this.evaluator = null;
190
191                        /**
192                         * A function executed for every node the walk pass by to check
193                         * whether the walk is to be finished. It's called when both
194                         * entering and exiting nodes, as well as for the matched nodes.
195                         * If this function returns "false", the walking ends and no more
196                         * nodes are evaluated.
197                         * @name CKEDITOR.dom.walker.prototype.guard
198                         * @property
199                         * @type Function
200                         */
201                        // this.guard = null;
202
203                        /** @private */
204                        this._ = {};
205                },
206
207//              statics :
208//              {
209//                      /* Creates a CKEDITOR.dom.walker instance to walk inside DOM boundaries set by nodes.
210//                       * @param {CKEDITOR.dom.node} startNode The node from wich the walk
211//                       *              will start.
212//                       * @param {CKEDITOR.dom.node} [endNode] The last node to be considered
213//                       *              in the walk. No more nodes are retrieved after touching or
214//                       *              passing it. If not provided, the walker stops at the
215//                       *              <body> closing boundary.
216//                       * @returns {CKEDITOR.dom.walker} A DOM walker for the nodes between the
217//                       *              provided nodes.
218//                       */
219//                      createOnNodes : function( startNode, endNode, startInclusive, endInclusive )
220//                      {
221//                              var range = new CKEDITOR.dom.range();
222//                              if ( startNode )
223//                                      range.setStartAt( startNode, startInclusive ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_END ) ;
224//                              else
225//                                      range.setStartAt( startNode.getDocument().getBody(), CKEDITOR.POSITION_AFTER_START ) ;
226//
227//                              if ( endNode )
228//                                      range.setEndAt( endNode, endInclusive ? CKEDITOR.POSITION_AFTER_END : CKEDITOR.POSITION_BEFORE_START ) ;
229//                              else
230//                                      range.setEndAt( startNode.getDocument().getBody(), CKEDITOR.POSITION_BEFORE_END ) ;
231//
232//                              return new CKEDITOR.dom.walker( range );
233//                      }
234//              },
235//
236                proto :
237                {
238                        /**
239                         * Stop walking. No more nodes are retrieved if this function gets
240                         * called.
241                         */
242                        end : function()
243                        {
244                                this._.end = 1;
245                        },
246
247                        /**
248                         * Retrieves the next node (at right).
249                         * @returns {CKEDITOR.dom.node} The next node or null if no more
250                         *              nodes are available.
251                         */
252                        next : function()
253                        {
254                                return iterate.call( this );
255                        },
256
257                        /**
258                         * Retrieves the previous node (at left).
259                         * @returns {CKEDITOR.dom.node} The previous node or null if no more
260                         *              nodes are available.
261                         */
262                        previous : function()
263                        {
264                                return iterate.call( this, true );
265                        },
266
267                        /**
268                         * Check all nodes at right, executing the evaluation fuction.
269                         * @returns {Boolean} "false" if the evaluator function returned
270                         *              "false" for any of the matched nodes. Otherwise "true".
271                         */
272                        checkForward : function()
273                        {
274                                return iterate.call( this, false, true ) !== false;
275                        },
276
277                        /**
278                         * Check all nodes at left, executing the evaluation fuction.
279                         * @returns {Boolean} "false" if the evaluator function returned
280                         *              "false" for any of the matched nodes. Otherwise "true".
281                         */
282                        checkBackward : function()
283                        {
284                                return iterate.call( this, true, true ) !== false;
285                        },
286
287                        /**
288                         * Executes a full walk forward (to the right), until no more nodes
289                         * are available, returning the last valid node.
290                         * @returns {CKEDITOR.dom.node} The last node at the right or null
291                         *              if no valid nodes are available.
292                         */
293                        lastForward : function()
294                        {
295                                return iterateToLast.call( this );
296                        },
297
298                        /**
299                         * Executes a full walk backwards (to the left), until no more nodes
300                         * are available, returning the last valid node.
301                         * @returns {CKEDITOR.dom.node} The last node at the left or null
302                         *              if no valid nodes are available.
303                         */
304                        lastBackward : function()
305                        {
306                                return iterateToLast.call( this, true );
307                        },
308
309                        reset : function()
310                        {
311                                delete this.current;
312                                this._ = {};
313                        }
314
315                }
316        });
317
318        /*
319         * Anything whose display computed style is block, list-item, table,
320         * table-row-group, table-header-group, table-footer-group, table-row,
321         * table-column-group, table-column, table-cell, table-caption, or whose node
322         * name is hr, br (when enterMode is br only) is a block boundary.
323         */
324        var blockBoundaryDisplayMatch =
325        {
326                block : 1,
327                'list-item' : 1,
328                table : 1,
329                'table-row-group' : 1,
330                'table-header-group' : 1,
331                'table-footer-group' : 1,
332                'table-row' : 1,
333                'table-column-group' : 1,
334                'table-column' : 1,
335                'table-cell' : 1,
336                'table-caption' : 1
337        },
338        blockBoundaryNodeNameMatch = { hr : 1 };
339
340        CKEDITOR.dom.element.prototype.isBlockBoundary = function( customNodeNames )
341        {
342                var nodeNameMatches = CKEDITOR.tools.extend( {},
343                                                                                                        blockBoundaryNodeNameMatch, customNodeNames || {} );
344
345                return blockBoundaryDisplayMatch[ this.getComputedStyle( 'display' ) ] ||
346                        nodeNameMatches[ this.getName() ];
347        };
348
349        CKEDITOR.dom.walker.blockBoundary = function( customNodeNames )
350        {
351                return function( node , type )
352                {
353                        return ! ( node.type == CKEDITOR.NODE_ELEMENT
354                                                && node.isBlockBoundary( customNodeNames ) );
355                };
356        };
357
358        CKEDITOR.dom.walker.listItemBoundary = function()
359        {
360                        return this.blockBoundary( { br : 1 } );
361        };
362        /**
363         * Whether the node is a bookmark node's inner text node.
364         */
365        CKEDITOR.dom.walker.bookmarkContents = function( node )
366        {
367        },
368
369        /**
370         * Whether the to-be-evaluated node is a bookmark node OR bookmark node
371         * inner contents.
372         * @param {Boolean} contentOnly Whether only test againt the text content of
373         * bookmark node instead of the element itself(default).
374         * @param {Boolean} isReject Whether should return 'false' for the bookmark
375         * node instead of 'true'(default).
376         */
377        CKEDITOR.dom.walker.bookmark = function( contentOnly, isReject )
378        {
379                function isBookmarkNode( node )
380                {
381                        return ( node && node.getName
382                                        && node.getName() == 'span'
383                                        && node.hasAttribute('_fck_bookmark') );
384                }
385
386                return function( node )
387                {
388                        var isBookmark, parent;
389                        // Is bookmark inner text node?
390                        isBookmark = ( node && !node.getName && ( parent = node.getParent() )
391                                                && isBookmarkNode( parent ) );
392                        // Is bookmark node?
393                        isBookmark = contentOnly ? isBookmark : isBookmark || isBookmarkNode( node );
394                        return isReject ^ isBookmark;
395                };
396        };
397
398        /**
399         * Whether the node contains only white-spaces characters.
400         * @param isReject
401         */
402        CKEDITOR.dom.walker.whitespaces = function( isReject )
403        {
404                return function( node )
405                {
406                        var isWhitespace = node && ( node.type == CKEDITOR.NODE_TEXT )
407                                                        && !CKEDITOR.tools.trim( node.getText() );
408                        return isReject ^ isWhitespace;
409                };
410        };
411})();
Note: See TracBrowser for help on using the repository browser.