6dcd4d47a33ef3f5a03920773090718428a3e512
[ckeditor.git] / _source / core / dom / elementpath.js
1 /*
2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
4 */
5
6 (function()
7 {
8 // Elements that may be considered the "Block boundary" in an element path.
9 var pathBlockElements = { address:1,blockquote:1,dl:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,li:1,dt:1,dd:1, legend:1,caption:1 };
10
11 // Elements that may be considered the "Block limit" in an element path.
12 var pathBlockLimitElements = { body:1,div:1,table:1,tbody:1,tr:1,td:1,th:1,form:1,fieldset:1 };
13
14 // Check if an element contains any block element.
15 var checkHasBlock = function( element )
16 {
17 var childNodes = element.getChildren();
18
19 for ( var i = 0, count = childNodes.count() ; i < count ; i++ )
20 {
21 var child = childNodes.getItem( i );
22
23 if ( child.type == CKEDITOR.NODE_ELEMENT && CKEDITOR.dtd.$block[ child.getName() ] )
24 return true;
25 }
26
27 return false;
28 };
29
30 /**
31 * @class
32 */
33 CKEDITOR.dom.elementPath = function( lastNode )
34 {
35 var block = null;
36 var blockLimit = null;
37 var elements = [];
38
39 var e = lastNode;
40
41 while ( e )
42 {
43 if ( e.type == CKEDITOR.NODE_ELEMENT )
44 {
45 if ( !this.lastElement )
46 this.lastElement = e;
47
48 var elementName = e.getName();
49 if ( CKEDITOR.env.ie && e.$.scopeName != 'HTML' )
50 elementName = e.$.scopeName.toLowerCase() + ':' + elementName;
51
52 if ( !blockLimit )
53 {
54 if ( !block && pathBlockElements[ elementName ] )
55 block = e;
56
57 if ( pathBlockLimitElements[ elementName ] )
58 {
59 // DIV is considered the Block, if no block is available (#525)
60 // and if it doesn't contain other blocks.
61 if ( !block && elementName == 'div' && !checkHasBlock( e ) )
62 block = e;
63 else
64 blockLimit = e;
65 }
66 }
67
68 elements.push( e );
69
70 if ( elementName == 'body' )
71 break;
72 }
73 e = e.getParent();
74 }
75
76 this.block = block;
77 this.blockLimit = blockLimit;
78 this.elements = elements;
79 };
80 })();
81
82 CKEDITOR.dom.elementPath.prototype =
83 {
84 /**
85 * Compares this element path with another one.
86 * @param {CKEDITOR.dom.elementPath} otherPath The elementPath object to be
87 * compared with this one.
88 * @returns {Boolean} "true" if the paths are equal, containing the same
89 * number of elements and the same elements in the same order.
90 */
91 compare : function( otherPath )
92 {
93 var thisElements = this.elements;
94 var otherElements = otherPath && otherPath.elements;
95
96 if ( !otherElements || thisElements.length != otherElements.length )
97 return false;
98
99 for ( var i = 0 ; i < thisElements.length ; i++ )
100 {
101 if ( !thisElements[ i ].equals( otherElements[ i ] ) )
102 return false;
103 }
104
105 return true;
106 },
107
108 contains : function( tagNames )
109 {
110 var elements = this.elements;
111 for ( var i = 0 ; i < elements.length ; i++ )
112 {
113 if ( elements[ i ].getName() in tagNames )
114 return elements[ i ];
115 }
116
117 return null;
118 }
119 };