/* Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ /** * @fileOverview The "elementspath" plugin. It shows all elements in the DOM * parent tree relative to the current selection in the editing area. */ (function() { var commands = { toolbarFocus : { editorFocus : false, readOnly : 1, exec : function( editor ) { var idBase = editor._.elementsPath.idBase; var element = CKEDITOR.document.getById( idBase + '0' ); // Make the first button focus accessible for IE. (#3417) // Adobe AIR instead need while of delay. element && element.focus( CKEDITOR.env.ie || CKEDITOR.env.air ); } } }; var emptyHtml = ' '; CKEDITOR.plugins.add( 'elementspath', { requires : [ 'selection' ], init : function( editor ) { var spaceId = 'cke_path_' + editor.name; var spaceElement; var getSpaceElement = function() { if ( !spaceElement ) spaceElement = CKEDITOR.document.getById( spaceId ); return spaceElement; }; var idBase = 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_'; editor._.elementsPath = { idBase : idBase, filters : [] }; editor.on( 'themeSpace', function( event ) { if ( event.data.space == 'bottom' ) { event.data.html += '' + editor.lang.elementsPath.eleLabel + '' + '
' + emptyHtml + '
'; } }); function onClick( elementIndex ) { editor.focus(); var element = editor._.elementsPath.list[ elementIndex ]; if ( element.is( 'body' ) ) { var range = new CKEDITOR.dom.range( editor.document ); range.selectNodeContents( element ); range.select(); } else editor.getSelection().selectElement( element ); } 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; }); editor.on( 'selectionChange', function( ev ) { var env = CKEDITOR.env, selection = ev.data.selection, element = selection.getStartElement(), html = [], editor = ev.editor, elementsList = editor._.elementsPath.list = [], filters = editor._.elementsPath.filters; while ( element ) { var ignore = 0, name; if ( element.data( 'cke-display-name' ) ) name = element.data( 'cke-display-name' ); else if ( element.data( 'cke-real-element-type' ) ) name = element.data( 'cke-real-element-type' ); else name = element.getName(); for ( var i = 0; i < filters.length; i++ ) { var ret = filters[ i ]( element, name ); if ( ret === false ) { ignore = 1; break; } name = ret || name; } if ( !ignore ) { var index = elementsList.push( element ) - 1; // Use this variable to add conditional stuff to the // HTML (because we are doing it in reverse order... unshift). var extra = ''; // Some browsers don't cancel key events in the keydown but in the // keypress. // TODO: Check if really needed for Gecko+Mac. if ( env.opera || ( env.gecko && env.mac ) ) extra += ' onkeypress="return false;"'; // With Firefox, we need to force the button to redraw, otherwise it // will remain in the focus state. if ( env.gecko ) extra += ' onblur="this.style.cssText = this.style.cssText;"'; var label = editor.lang.elementsPath.eleTitle.replace( /%1/, name ); html.unshift( '', name, '' + label + '', '' ); } if ( name == 'body' ) break; element = element.getParent(); } var space = getSpaceElement(); space.setHtml( html.join('') + emptyHtml ); editor.fire( 'elementsPathUpdate', { space : space } ); }); function empty() { spaceElement && spaceElement.setHtml( emptyHtml ); delete editor._.elementsPath.list; } editor.on( 'readOnly', empty ); editor.on( 'contentDomUnload', empty ); editor.addCommand( 'elementsPathFocus', commands.toolbarFocus ); } }); })(); /** * Fired when the contents of the elementsPath are changed * @name CKEDITOR.editor#elementsPathUpdate * @event * @param {Object} eventData.space The elementsPath container */