1 /*
  2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
  3 For licensing, see LICENSE.html or http://ckeditor.com/license
  4 */
  5
  6 /**
  7  * @fileOverview The "elementspath" plugin. It shows all elements in the DOM
  8  *		parent tree relative to the current selection in the editing area.
  9  */
 10
 11 (function()
 12 {
 13 	var commands =
 14 	{
 15 		toolbarFocus :
 16 		{
 17 			exec : function( editor )
 18 			{
 19 				var idBase = editor._.elementsPath.idBase;
 20 				var element = CKEDITOR.document.getById( idBase + '0' );
 21
 22 				if ( element )
 23 					element.focus();
 24 			}
 25 		}
 26 	};
 27
 28 	CKEDITOR.plugins.add( 'elementspath',
 29 	{
 30 		requires : [ 'selection' ],
 31
 32 		init : function( editor, pluginPath )
 33 		{
 34 			var spaceId = 'cke_path_' + editor.name;
 35 			var spaceElement;
 36 			var getSpaceElement = function()
 37 			{
 38 				if ( !spaceElement )
 39 					spaceElement = CKEDITOR.document.getById( spaceId );
 40 				return spaceElement;
 41 			};
 42
 43 			var idBase = 'cke_elementspath_' + CKEDITOR.tools.getNextNumber() + '_';
 44
 45 			editor._.elementsPath = { idBase : idBase };
 46
 47 			editor.on( 'themeSpace', function( event )
 48 				{
 49 					if ( event.data.space == 'bottom' )
 50 						event.data.html += '<div id="' + spaceId + '" class="cke_path"><br></div>';
 51 				});
 52
 53 			editor.on( 'selectionChange', function( ev )
 54 				{
 55 					var env = CKEDITOR.env;
 56
 57 					var selection = ev.data.selection;
 58
 59 					var element = selection.getStartElement(),
 60 						html = [],
 61 						elementsList = this._.elementsPath.list = [];
 62
 63 					while ( element )
 64 					{
 65 						var index = elementsList.push( element ) - 1;
 66 						var name;
 67 						if ( element.getAttribute( '_cke_real_element_type' ) )
 68 							name = element.getAttribute( '_cke_real_element_type' );
 69 						else
 70 							name = element.getName();
 71
 72 						// Use this variable to add conditional stuff to the
 73 						// HTML (because we are doing it in reverse order... unshift).
 74 						var extra = '';
 75
 76 						// Some browsers don't cancel key events in the keydown but in the
 77 						// keypress.
 78 						// TODO: Check if really needed for Gecko+Mac.
 79 						if ( env.opera || ( env.gecko && env.mac ) )
 80 							extra += ' onkeypress="return false;"';
 81
 82 						// With Firefox, we need to force the button to redraw, otherwise it
 83 						// will remain in the focus state.
 84 						if ( env.gecko )
 85 							extra += ' onblur="this.style.cssText = this.style.cssText;"';
 86
 87 						html.unshift(
 88 							'<a' +
 89 								' id="', idBase, index, '"' +
 90 								' href="javascript:void(\'', name, '\')"' +
 91 								' tabindex="-1"' +
 92 								' title="', editor.lang.elementsPath.eleTitle.replace( /%1/, name ), '"' +
 93 								' onkeydown="return CKEDITOR._.elementsPath.keydown(\'', this.name, '\',', index, ', event);"' +
 94 								extra ,
 95 								' onclick="return CKEDITOR._.elementsPath.click(\'', this.name, '\',', index, ');">',
 96 									name,
 97 							'</a>' );
 98
 99 						if ( name == 'body' )
100 							break;
101
102 						element = element.getParent();
103 					}
104
105 					getSpaceElement().setHtml( html.join('') );
106 				});
107
108 			editor.on( 'contentDomUnload', function()
109 				{
110 					getSpaceElement().setHtml( '<br>' );
111 				});
112
113 			editor.addCommand( 'elementsPathFocus', commands.toolbarFocus );
114 		}
115 	});
116 })();
117
118 /**
119  * Handles the click on an element in the element path.
120  * @private
121  */
122 CKEDITOR._.elementsPath =
123 {
124 	click : function( instanceName, elementIndex )
125 	{
126 		var editor = CKEDITOR.instances[ instanceName ];
127 		editor.focus();
128
129 		var element = editor._.elementsPath.list[ elementIndex ];
130 		editor.getSelection().selectElement( element );
131
132 		return false;
133 	},
134
135 	keydown : function( instanceName, elementIndex, ev )
136 	{
137 		var instance = CKEDITOR.ui.button._.instances[ elementIndex ];
138 		var editor = CKEDITOR.instances[ instanceName ];
139 		var idBase = editor._.elementsPath.idBase;
140
141 		var element;
142
143 		ev = new CKEDITOR.dom.event( ev );
144
145 		switch ( ev.getKeystroke() )
146 		{
147 			case 37 :					// LEFT-ARROW
148 			case 9 :					// TAB
149 				element = CKEDITOR.document.getById( idBase + ( elementIndex + 1 ) );
150 				if ( !element )
151 					element = CKEDITOR.document.getById( idBase + '0' );
152 				element.focus();
153 				return false;
154
155 			case 39 :					// RIGHT-ARROW
156 			case CKEDITOR.SHIFT + 9 :	// SHIFT + TAB
157 				element = CKEDITOR.document.getById( idBase + ( elementIndex - 1 ) );
158 				if ( !element )
159 					element = CKEDITOR.document.getById( idBase + ( editor._.elementsPath.list.length - 1 ) );
160 				element.focus();
161 				return false;
162
163 			case 27 :					// ESC
164 				editor.focus();
165 				return false;
166
167 			case 13 :					// ENTER	// Opera
168 			case 32 :					// SPACE
169 				this.click( instanceName, elementIndex );
170 				return false;
171
172 			//default :
173 			//	alert( ev.getKeystroke() );
174 		}
175 		return true;
176 	}
177 };
178