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