]>
git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blob - sources/core/dom/elementpath.js
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
10 var pathBlockLimitElements
= {},
11 pathBlockElements
= {},
14 // Elements that are considered the "Block limit" in an element path.
15 for ( tag
in CKEDITOR
.dtd
.$blockLimit
) {
16 // Exclude from list roots.
17 if ( !( tag
in CKEDITOR
.dtd
.$list
) )
18 pathBlockLimitElements
[ tag
] = 1;
21 // Elements that are considered the "End level Block" in an element path.
22 for ( tag
in CKEDITOR
.dtd
.$block
) {
23 // Exclude block limits, and empty block element, e.g. hr.
24 if ( !( tag
in CKEDITOR
.dtd
.$blockLimit
|| tag
in CKEDITOR
.dtd
.$empty
) )
25 pathBlockElements
[ tag
] = 1;
28 // Check if an element contains any block element.
29 function checkHasBlock( element
) {
30 var childNodes
= element
.getChildren();
32 for ( var i
= 0, count
= childNodes
.count(); i
< count
; i
++ ) {
33 var child
= childNodes
.getItem( i
);
35 if ( child
.type
== CKEDITOR
.NODE_ELEMENT
&& CKEDITOR
.dtd
.$block
[ child
.getName() ] )
43 * Retrieve the list of nodes walked from the start node up to the editable element of the editor.
46 * @constructor Creates an element path class instance.
47 * @param {CKEDITOR.dom.element} startNode From which the path should start.
48 * @param {CKEDITOR.dom.element} root To which element the path should stop, defaults to the `body` element.
50 CKEDITOR
.dom
.elementPath = function( startNode
, root
) {
58 root
= root
|| startNode
.getDocument().getBody();
61 if ( e
.type
== CKEDITOR
.NODE_ELEMENT
) {
64 if ( !this.lastElement
) {
67 // If an object or non-editable element is fully selected at the end of the element path,
68 // it must not become the block limit.
69 if ( e
.is( CKEDITOR
.dtd
.$object
) || e
.getAttribute( 'contenteditable' ) == 'false' )
73 if ( e
.equals( root
) )
77 elementName
= e
.getName();
79 // First editable element becomes a block limit, because it cannot be split.
80 if ( e
.getAttribute( 'contenteditable' ) == 'true' )
82 // "Else" because element cannot be both - block and block levelimit.
83 else if ( !block
&& pathBlockElements
[ elementName
] )
86 if ( pathBlockLimitElements
[ elementName
] ) {
87 // End level DIV is considered as the block, if no block is available. (#525)
88 // But it must NOT be the root element (checked above).
89 if ( !block
&& elementName
== 'div' && !checkHasBlock( e
) )
97 while ( ( e
= e
.getParent() ) );
99 // Block limit defaults to root.
104 * First non-empty block element which:
106 * * is not a {@link CKEDITOR.dtd#$blockLimit},
107 * * or is a `div` which does not contain block elements and is not a `root`.
109 * This means a first, splittable block in elements path.
112 * @property {CKEDITOR.dom.element}
117 * See the {@link CKEDITOR.dtd#$blockLimit} description.
120 * @property {CKEDITOR.dom.element}
122 this.blockLimit
= blockLimit
;
125 * The root of the elements path - `root` argument passed to class constructor or a `body` element.
128 * @property {CKEDITOR.dom.element}
133 * An array of elements (from `startNode` to `root`) in the path.
136 * @property {CKEDITOR.dom.element[]}
138 this.elements
= elements
;
141 * The last element of the elements path - `startNode` or its parent.
144 * @property {CKEDITOR.dom.element} lastElement
150 CKEDITOR
.dom
.elementPath
.prototype = {
152 * Compares this element path with another one.
154 * @param {CKEDITOR.dom.elementPath} otherPath The elementPath object to be
155 * compared with this one.
156 * @returns {Boolean} `true` if the paths are equal, containing the same
157 * number of elements and the same elements in the same order.
159 compare: function( otherPath
) {
160 var thisElements
= this.elements
;
161 var otherElements
= otherPath
&& otherPath
.elements
;
163 if ( !otherElements
|| thisElements
.length
!= otherElements
.length
)
166 for ( var i
= 0; i
< thisElements
.length
; i
++ ) {
167 if ( !thisElements
[ i
].equals( otherElements
[ i
] ) )
175 * Search the path elements that meets the specified criteria.
177 * @param {String/Array/Function/Object/CKEDITOR.dom.element} query The criteria that can be
178 * either a tag name, list (array and object) of tag names, element or an node evaluator function.
179 * @param {Boolean} [excludeRoot] Not taking path root element into consideration.
180 * @param {Boolean} [fromTop] Search start from the topmost element instead of bottom.
181 * @returns {CKEDITOR.dom.element} The first matched dom element or `null`.
183 contains: function( query
, excludeRoot
, fromTop
) {
185 if ( typeof query
== 'string' )
186 evaluator = function( node
) {
187 return node
.getName() == query
;
189 if ( query
instanceof CKEDITOR
.dom
.element
)
190 evaluator = function( node
) {
191 return node
.equals( query
);
193 else if ( CKEDITOR
.tools
.isArray( query
) )
194 evaluator = function( node
) {
195 return CKEDITOR
.tools
.indexOf( query
, node
.getName() ) > -1;
197 else if ( typeof query
== 'function' )
199 else if ( typeof query
== 'object' )
200 evaluator = function( node
) {
201 return node
.getName() in query
;
204 var elements
= this.elements
,
205 length
= elements
.length
;
206 excludeRoot
&& length
--;
209 elements
= Array
.prototype.slice
.call( elements
, 0 );
213 for ( var i
= 0; i
< length
; i
++ ) {
214 if ( evaluator( elements
[ i
] ) )
215 return elements
[ i
];
222 * Check whether the elements path is the proper context for the specified
223 * tag name in the DTD.
225 * @param {String} tag The tag name.
228 isContextFor: function( tag
) {
231 // Check for block context.
232 if ( tag
in CKEDITOR
.dtd
.$block
) {
233 // Indeterminate elements which are not subjected to be splitted or surrounded must be checked first.
234 var inter
= this.contains( CKEDITOR
.dtd
.$intermediate
);
235 holder
= inter
|| ( this.root
.equals( this.block
) && this.block
) || this.blockLimit
;
236 return !!holder
.getDtd()[ tag
];
243 * Retrieve the text direction for this elements path.
245 * @returns {'ltr'/'rtl'}
247 direction: function() {
248 var directionNode
= this.block
|| this.blockLimit
|| this.root
;
249 return directionNode
.getDirection( 1 );