Skip to content

Commit e4325a2

Browse files
committed
Merge branch 't/10869' into major
2 parents a25991a + 3ede40c commit e4325a2

File tree

4 files changed

+113
-69
lines changed

4 files changed

+113
-69
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CKEditor 4 Changelog
55

66
New Features:
77

8+
* [#10869](http://dev.ckeditor.com/ticket/10869): Widgets: added better integration with elementspath plugin.
89
* [#10886](http://dev.ckeditor.com/ticket/10886): Widgets: added tooltip to the drag handler.
910
* [#10895](http://dev.ckeditor.com/ticket/10895): Image2: added support for server file browsers.
1011
* [#10856](http://dev.ckeditor.com/ticket/10856): Menu-buttons will now toggle their panels visibility when clicked multiple times. Language plugin fixes: added active language highlighting, added option to remove language.

core/dom/node.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
434434
*
435435
* var node = editor.document.getBody().getFirst();
436436
* var parent = node.getParent();
437-
* alert( node.getName() ); // 'body'
437+
* alert( parent.getName() ); // 'body'
438438
*
439439
* @param {Boolean} [allowFragmentParent=false] Consider also parent node that is of
440440
* fragment type {@link CKEDITOR#NODE_DOCUMENT_FRAGMENT}.
@@ -446,7 +446,15 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
446446
},
447447

448448
/**
449-
* @todo
449+
* Returns array containing node parents and node itself. By default nodes are in _descending_ order.
450+
*
451+
* // Assuming that body has paragraph as first child.
452+
* var node = editor.document.getBody().getFirst();
453+
* var parents = node.getParents();
454+
* alert( parents[ 0 ].getName() + ',' + parents[ 2 ].getName() ); // 'html,p'
455+
*
456+
* @param {Boolean} [closerFirst=false] Determines order of returned nodes.
457+
* @returns {Array} Returns array of {@link CKEDITOR.dom.node}.
450458
*/
451459
getParents: function( closerFirst ) {
452460
var node = this;

plugins/elementspath/plugin.js

Lines changed: 83 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@
5757
CKEDITOR.plugins.add( 'elementspath', {
5858
lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
5959
init: function( editor ) {
60+
editor._.elementsPath = {
61+
idBase: 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_',
62+
filters: []
63+
};
64+
6065
editor.on( 'uiSpace', function( event ) {
6166
if ( event.data.space == 'bottom' )
6267
initElementsPath( editor, event.data );
@@ -65,17 +70,15 @@
6570
} );
6671

6772
function initElementsPath( editor, bottomSpaceData ) {
68-
var spaceId = editor.ui.spaceId( 'path' );
69-
var spaceElement;
70-
var getSpaceElement = function() {
73+
var spaceId = editor.ui.spaceId( 'path' ),
74+
spaceElement,
75+
getSpaceElement = function() {
7176
if ( !spaceElement )
7277
spaceElement = CKEDITOR.document.getById( spaceId );
7378
return spaceElement;
74-
};
75-
76-
var idBase = 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_';
77-
78-
editor._.elementsPath = { idBase: idBase, filters: [] };
79+
},
80+
elementsPath = editor._.elementsPath,
81+
idBase = elementsPath.idBase;
7982

8083
bottomSpaceData.html += '<span id="' + spaceId + '_label" class="cke_voice_label">' + editor.lang.elementspath.eleLabel + '</span>' +
8184
'<span id="' + spaceId + '" class="cke_path" role="group" aria-labelledby="' + spaceId + '_label">' + emptyHtml + '</span>';
@@ -87,8 +90,8 @@
8790
} );
8891

8992
function onClick( elementIndex ) {
90-
var element = editor._.elementsPath.list[ elementIndex ];
91-
if ( element.equals( editor.editable() ) ) {
93+
var element = elementsPath.list[ elementIndex ];
94+
if ( element.equals( editor.editable() ) || element.getAttribute( 'contenteditable' ) == 'true' ) {
9295
var range = editor.createRange();
9396
range.selectNodeContents( element );
9497
range.select();
@@ -100,58 +103,64 @@
100103
editor.focus();
101104
}
102105

103-
var onClickHanlder = CKEDITOR.tools.addFunction( onClick );
104-
105-
var onKeyDownHandler = CKEDITOR.tools.addFunction( function( elementIndex, ev ) {
106-
var idBase = editor._.elementsPath.idBase,
107-
element;
108-
109-
ev = new CKEDITOR.dom.event( ev );
110-
111-
var rtl = editor.lang.dir == 'rtl';
112-
switch ( ev.getKeystroke() ) {
113-
case rtl ? 39:
114-
37 : // LEFT-ARROW
115-
case 9: // TAB
116-
element = CKEDITOR.document.getById( idBase + ( elementIndex + 1 ) );
117-
if ( !element )
118-
element = CKEDITOR.document.getById( idBase + '0' );
119-
element.focus();
120-
return false;
121-
122-
case rtl ? 37:
123-
39 : // RIGHT-ARROW
124-
case CKEDITOR.SHIFT + 9: // SHIFT + TAB
125-
element = CKEDITOR.document.getById( idBase + ( elementIndex - 1 ) );
126-
if ( !element )
127-
element = CKEDITOR.document.getById( idBase + ( editor._.elementsPath.list.length - 1 ) );
128-
element.focus();
129-
return false;
130-
131-
case 27: // ESC
132-
editor.focus();
133-
return false;
134-
135-
case 13: // ENTER // Opera
136-
case 32: // SPACE
137-
onClick( elementIndex );
138-
return false;
139-
}
140-
return true;
141-
} );
106+
elementsPath.onClick = onClick;
107+
108+
var onClickHanlder = CKEDITOR.tools.addFunction( onClick ),
109+
onKeyDownHandler = CKEDITOR.tools.addFunction( function( elementIndex, ev ) {
110+
var idBase = elementsPath.idBase,
111+
element;
112+
113+
ev = new CKEDITOR.dom.event( ev );
114+
115+
var rtl = editor.lang.dir == 'rtl';
116+
switch ( ev.getKeystroke() ) {
117+
case rtl ? 39:
118+
37 : // LEFT-ARROW
119+
case 9: // TAB
120+
element = CKEDITOR.document.getById( idBase + ( elementIndex + 1 ) );
121+
if ( !element )
122+
element = CKEDITOR.document.getById( idBase + '0' );
123+
element.focus();
124+
return false;
125+
126+
case rtl ? 37:
127+
39 : // RIGHT-ARROW
128+
case CKEDITOR.SHIFT + 9: // SHIFT + TAB
129+
element = CKEDITOR.document.getById( idBase + ( elementIndex - 1 ) );
130+
if ( !element )
131+
element = CKEDITOR.document.getById( idBase + ( elementsPath.list.length - 1 ) );
132+
element.focus();
133+
return false;
134+
135+
case 27: // ESC
136+
editor.focus();
137+
return false;
138+
139+
case 13: // ENTER // Opera
140+
case 32: // SPACE
141+
onClick( elementIndex );
142+
return false;
143+
}
144+
return true;
145+
} );
142146

143147
editor.on( 'selectionChange', function( ev ) {
144148
var env = CKEDITOR.env,
145149
editable = editor.editable(),
146150
selection = ev.data.selection,
147-
element = selection.getStartElement(),
148151
html = [],
149-
elementsList = editor._.elementsPath.list = [],
150-
filters = editor._.elementsPath.filters;
151-
152-
while ( element ) {
153-
var ignore = 0,
154-
name;
152+
elementsList = elementsPath.list = [],
153+
namesList = [],
154+
filters = elementsPath.filters,
155+
isContentEditable = true,
156+
name,
157+
elementsChain = selection.getStartElement().getParents(),
158+
chainLength = elementsChain.length;
159+
160+
// Starts iteration from body element, skipping html.
161+
for ( var j = 1; j < chainLength; j++ ) {
162+
var element = elementsChain[ j ],
163+
ignore = 0;
155164

156165
if ( element.data( 'cke-display-name' ) )
157166
name = element.data( 'cke-display-name' );
@@ -160,6 +169,14 @@
160169
else
161170
name = element.getName();
162171

172+
isContentEditable = element.hasAttribute( 'contenteditable' ) ?
173+
element.getAttribute( 'contenteditable' ) == 'true' : isContentEditable;
174+
175+
// If elem is non-contenteditable, and it's not specifying contenteditable
176+
// attribute - then elem should be ignored.
177+
if ( !isContentEditable && !element.hasAttribute( 'contenteditable' ) )
178+
ignore = 1;
179+
163180
for ( var i = 0; i < filters.length; i++ ) {
164181
var ret = filters[ i ]( element, name );
165182
if ( ret === false ) {
@@ -170,10 +187,15 @@
170187
}
171188

172189
if ( !ignore ) {
173-
var index = elementsList.push( element ) - 1,
174-
label = editor.lang.elementspath.eleTitle.replace( /%1/, name );
190+
elementsList.unshift( element );
191+
namesList.unshift( name );
192+
}
193+
}
175194

176-
var item = pathItemTpl.output({
195+
for ( var iterationLimit = elementsList.length, index = 0; index < iterationLimit; index++ ) {
196+
name = namesList[ index ];
197+
var label = editor.lang.elementspath.eleTitle.replace( /%1/, name ),
198+
item = pathItemTpl.output( {
177199
id: idBase + index,
178200
label: label,
179201
text: name,
@@ -182,14 +204,8 @@
182204
keyDownFn: onKeyDownHandler,
183205
clickFn: onClickHanlder
184206
} );
185-
html.unshift( item );
186-
187-
}
188-
189-
if ( element.equals( editable ) )
190-
break;
191207

192-
element = element.getParent();
208+
html.unshift( item );
193209
}
194210

195211
var space = getSpaceElement();
@@ -199,7 +215,7 @@
199215

200216
function empty() {
201217
spaceElement && spaceElement.setHtml( emptyHtml );
202-
delete editor._.elementsPath.list;
218+
delete elementsPath.list;
203219
}
204220

205221
editor.on( 'readOnly', empty );

plugins/widget/plugin.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,8 @@
540540
wrapper = new CKEDITOR.dom.element( isInline ? 'span' : 'div' );
541541
wrapper.setAttributes( getWrapperAttributes( isInline ) );
542542

543+
wrapper.data( 'cke-display-name', widgetDef.pathName ? widgetDef.pathName : element.getName() );
544+
543545
// Replace element unless it is a detached one.
544546
if ( element.getParent( true ) )
545547
wrapper.replace( element );
@@ -564,6 +566,8 @@
564566

565567
wrapper = new CKEDITOR.htmlParser.element( isInline ? 'span' : 'div', getWrapperAttributes( isInline ) );
566568

569+
wrapper.attributes[ 'data-cke-display-name' ] = widgetDef.pathName ? widgetDef.pathName : element.name;
570+
567571
var parent = element.parent,
568572
index;
569573

@@ -992,6 +996,9 @@
992996
// cleanUpWidgetElement for performance and code size reasons.
993997
editable.removeClass( 'cke_widget_editable_focused' );
994998

999+
if ( definition.pathName )
1000+
editable.data( 'cke-display-name', definition.pathName );
1001+
9951002
this.editor.focusManager.add( editable );
9961003
editable.on( 'focus', onEditableFocus, this );
9971004
CKEDITOR.env.ie && editable.on( 'blur', onEditableBlur, this );
@@ -2766,6 +2773,12 @@
27662773
* @property editables
27672774
*/
27682775

2776+
/**
2777+
* Widget name displayed in elements path.
2778+
*
2779+
* @property {String} pathName
2780+
*/
2781+
27692782
/**
27702783
* If set to `true`, the widget's element will be covered with a transparent mask.
27712784
* This will prevent its content from being clickable, which matters in case
@@ -2840,4 +2853,10 @@
28402853
* use it to limit the editor features available in the nested editable.
28412854
*
28422855
* @property {CKEDITOR.filter.allowedContentRules} allowedContent
2856+
*/
2857+
2858+
/**
2859+
* Nested editable name displayed in elements path.
2860+
*
2861+
* @property {String} pathName
28432862
*/

0 commit comments

Comments
 (0)