Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 't/10869' into major
  • Loading branch information
mlewand committed Nov 5, 2013
2 parents a25991a + 3ede40c commit e4325a2
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 69 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -5,6 +5,7 @@ CKEditor 4 Changelog

New Features:

* [#10869](http://dev.ckeditor.com/ticket/10869): Widgets: added better integration with elementspath plugin.
* [#10886](http://dev.ckeditor.com/ticket/10886): Widgets: added tooltip to the drag handler.
* [#10895](http://dev.ckeditor.com/ticket/10895): Image2: added support for server file browsers.
* [#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.
Expand Down
12 changes: 10 additions & 2 deletions core/dom/node.js
Expand Up @@ -434,7 +434,7 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
*
* var node = editor.document.getBody().getFirst();
* var parent = node.getParent();
* alert( node.getName() ); // 'body'
* alert( parent.getName() ); // 'body'
*
* @param {Boolean} [allowFragmentParent=false] Consider also parent node that is of
* fragment type {@link CKEDITOR#NODE_DOCUMENT_FRAGMENT}.
Expand All @@ -446,7 +446,15 @@ CKEDITOR.tools.extend( CKEDITOR.dom.node.prototype, {
},

/**
* @todo
* Returns array containing node parents and node itself. By default nodes are in _descending_ order.
*
* // Assuming that body has paragraph as first child.
* var node = editor.document.getBody().getFirst();
* var parents = node.getParents();
* alert( parents[ 0 ].getName() + ',' + parents[ 2 ].getName() ); // 'html,p'
*
* @param {Boolean} [closerFirst=false] Determines order of returned nodes.
* @returns {Array} Returns array of {@link CKEDITOR.dom.node}.
*/
getParents: function( closerFirst ) {
var node = this;
Expand Down
150 changes: 83 additions & 67 deletions plugins/elementspath/plugin.js
Expand Up @@ -57,6 +57,11 @@
CKEDITOR.plugins.add( 'elementspath', {
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%
init: function( editor ) {
editor._.elementsPath = {
idBase: 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_',
filters: []
};

editor.on( 'uiSpace', function( event ) {
if ( event.data.space == 'bottom' )
initElementsPath( editor, event.data );
Expand All @@ -65,17 +70,15 @@
} );

function initElementsPath( editor, bottomSpaceData ) {
var spaceId = editor.ui.spaceId( 'path' );
var spaceElement;
var getSpaceElement = function() {
var spaceId = editor.ui.spaceId( 'path' ),
spaceElement,
getSpaceElement = function() {
if ( !spaceElement )
spaceElement = CKEDITOR.document.getById( spaceId );
return spaceElement;
};

var idBase = 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_';

editor._.elementsPath = { idBase: idBase, filters: [] };
},
elementsPath = editor._.elementsPath,
idBase = elementsPath.idBase;

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

function onClick( elementIndex ) {
var element = editor._.elementsPath.list[ elementIndex ];
if ( element.equals( editor.editable() ) ) {
var element = elementsPath.list[ elementIndex ];
if ( element.equals( editor.editable() ) || element.getAttribute( 'contenteditable' ) == 'true' ) {
var range = editor.createRange();
range.selectNodeContents( element );
range.select();
Expand All @@ -100,58 +103,64 @@
editor.focus();
}

var onClickHanlder = CKEDITOR.tools.addFunction( onClick );

var onKeyDownHandler = CKEDITOR.tools.addFunction( function( elementIndex, ev ) {
var idBase = editor._.elementsPath.idBase,
element;

ev = new CKEDITOR.dom.event( ev );

var rtl = editor.lang.dir == 'rtl';
switch ( ev.getKeystroke() ) {
case rtl ? 39:
37 : // LEFT-ARROW
case 9: // TAB
element = CKEDITOR.document.getById( idBase + ( elementIndex + 1 ) );
if ( !element )
element = CKEDITOR.document.getById( idBase + '0' );
element.focus();
return false;

case rtl ? 37:
39 : // RIGHT-ARROW
case CKEDITOR.SHIFT + 9: // SHIFT + TAB
element = CKEDITOR.document.getById( idBase + ( elementIndex - 1 ) );
if ( !element )
element = CKEDITOR.document.getById( idBase + ( editor._.elementsPath.list.length - 1 ) );
element.focus();
return false;

case 27: // ESC
editor.focus();
return false;

case 13: // ENTER // Opera
case 32: // SPACE
onClick( elementIndex );
return false;
}
return true;
} );
elementsPath.onClick = onClick;

var onClickHanlder = CKEDITOR.tools.addFunction( onClick ),
onKeyDownHandler = CKEDITOR.tools.addFunction( function( elementIndex, ev ) {
var idBase = elementsPath.idBase,
element;

ev = new CKEDITOR.dom.event( ev );

var rtl = editor.lang.dir == 'rtl';
switch ( ev.getKeystroke() ) {
case rtl ? 39:
37 : // LEFT-ARROW
case 9: // TAB
element = CKEDITOR.document.getById( idBase + ( elementIndex + 1 ) );
if ( !element )
element = CKEDITOR.document.getById( idBase + '0' );
element.focus();
return false;

case rtl ? 37:
39 : // RIGHT-ARROW
case CKEDITOR.SHIFT + 9: // SHIFT + TAB
element = CKEDITOR.document.getById( idBase + ( elementIndex - 1 ) );
if ( !element )
element = CKEDITOR.document.getById( idBase + ( elementsPath.list.length - 1 ) );
element.focus();
return false;

case 27: // ESC
editor.focus();
return false;

case 13: // ENTER // Opera
case 32: // SPACE
onClick( elementIndex );
return false;
}
return true;
} );

editor.on( 'selectionChange', function( ev ) {
var env = CKEDITOR.env,
editable = editor.editable(),
selection = ev.data.selection,
element = selection.getStartElement(),
html = [],
elementsList = editor._.elementsPath.list = [],
filters = editor._.elementsPath.filters;

while ( element ) {
var ignore = 0,
name;
elementsList = elementsPath.list = [],
namesList = [],
filters = elementsPath.filters,
isContentEditable = true,
name,
elementsChain = selection.getStartElement().getParents(),
chainLength = elementsChain.length;

// Starts iteration from body element, skipping html.
for ( var j = 1; j < chainLength; j++ ) {
var element = elementsChain[ j ],
ignore = 0;

if ( element.data( 'cke-display-name' ) )
name = element.data( 'cke-display-name' );
Expand All @@ -160,6 +169,14 @@
else
name = element.getName();

isContentEditable = element.hasAttribute( 'contenteditable' ) ?
element.getAttribute( 'contenteditable' ) == 'true' : isContentEditable;

// If elem is non-contenteditable, and it's not specifying contenteditable
// attribute - then elem should be ignored.
if ( !isContentEditable && !element.hasAttribute( 'contenteditable' ) )
ignore = 1;

for ( var i = 0; i < filters.length; i++ ) {
var ret = filters[ i ]( element, name );
if ( ret === false ) {
Expand All @@ -170,10 +187,15 @@
}

if ( !ignore ) {
var index = elementsList.push( element ) - 1,
label = editor.lang.elementspath.eleTitle.replace( /%1/, name );
elementsList.unshift( element );
namesList.unshift( name );
}
}

var item = pathItemTpl.output({
for ( var iterationLimit = elementsList.length, index = 0; index < iterationLimit; index++ ) {
name = namesList[ index ];
var label = editor.lang.elementspath.eleTitle.replace( /%1/, name ),
item = pathItemTpl.output( {
id: idBase + index,
label: label,
text: name,
Expand All @@ -182,14 +204,8 @@
keyDownFn: onKeyDownHandler,
clickFn: onClickHanlder
} );
html.unshift( item );

}

if ( element.equals( editable ) )
break;

element = element.getParent();
html.unshift( item );
}

var space = getSpaceElement();
Expand All @@ -199,7 +215,7 @@

function empty() {
spaceElement && spaceElement.setHtml( emptyHtml );
delete editor._.elementsPath.list;
delete elementsPath.list;
}

editor.on( 'readOnly', empty );
Expand Down
19 changes: 19 additions & 0 deletions plugins/widget/plugin.js
Expand Up @@ -540,6 +540,8 @@
wrapper = new CKEDITOR.dom.element( isInline ? 'span' : 'div' );
wrapper.setAttributes( getWrapperAttributes( isInline ) );

wrapper.data( 'cke-display-name', widgetDef.pathName ? widgetDef.pathName : element.getName() );

// Replace element unless it is a detached one.
if ( element.getParent( true ) )
wrapper.replace( element );
Expand All @@ -564,6 +566,8 @@

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

wrapper.attributes[ 'data-cke-display-name' ] = widgetDef.pathName ? widgetDef.pathName : element.name;

var parent = element.parent,
index;

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

if ( definition.pathName )
editable.data( 'cke-display-name', definition.pathName );

this.editor.focusManager.add( editable );
editable.on( 'focus', onEditableFocus, this );
CKEDITOR.env.ie && editable.on( 'blur', onEditableBlur, this );
Expand Down Expand Up @@ -2766,6 +2773,12 @@
* @property editables
*/

/**
* Widget name displayed in elements path.
*
* @property {String} pathName
*/

/**
* If set to `true`, the widget's element will be covered with a transparent mask.
* This will prevent its content from being clickable, which matters in case
Expand Down Expand Up @@ -2840,4 +2853,10 @@
* use it to limit the editor features available in the nested editable.
*
* @property {CKEDITOR.filter.allowedContentRules} allowedContent
*/

/**
* Nested editable name displayed in elements path.
*
* @property {String} pathName
*/

0 comments on commit e4325a2

Please sign in to comment.