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 (function()
  7 {
  8 	CKEDITOR.plugins.add( 'stylescombo',
  9 	{
 10 		requires : [ 'richcombo', 'styles' ],
 11
 12 		init : function( editor )
 13 		{
 14 			var config = editor.config,
 15 				lang = editor.lang.stylesCombo,
 16 				pluginPath = this.path,
 17 				styles;
 18
 19 			editor.ui.addRichCombo( 'Styles',
 20 				{
 21 					label : lang.label,
 22 					title : lang.panelTitle,
 23 					voiceLabel : lang.voiceLabel,
 24 					className : 'cke_styles',
 25 					multiSelect : true,
 26
 27 					panel :
 28 					{
 29 						css : [ config.contentsCss, CKEDITOR.getUrl( editor.skinPath + 'editor.css' ) ],
 30 						voiceLabel : lang.panelVoiceLabel
 31 					},
 32
 33 					init : function()
 34 					{
 35 						var combo = this,
 36 							stylesSet = config.stylesCombo_stylesSet.split( ':', 2 ),
 37 							stylesSetPath = stylesSet[ 1 ] || CKEDITOR.getUrl( pluginPath + 'styles/' + stylesSet[ 0 ] + '.js' ) ;
 38
 39 						stylesSet = stylesSet[ 0 ];
 40
 41 						CKEDITOR.loadStylesSet( stylesSet, stylesSetPath, function( stylesDefinitions )
 42 							{
 43 								var style,
 44 									styleName,
 45 									stylesList = [];
 46
 47 								styles = {};
 48
 49 								// Put all styles into an Array.
 50 								for ( var i = 0 ; i < stylesDefinitions.length ; i++ )
 51 								{
 52 									var styleDefinition = stylesDefinitions[ i ];
 53
 54 									styleName = styleDefinition.name;
 55
 56 									style = styles[ styleName ] = new CKEDITOR.style( styleDefinition );
 57 									style._name = styleName;
 58
 59 									stylesList.push( style );
 60 								}
 61
 62 								// Sorts the Array, so the styles get grouped
 63 								// by type.
 64 								stylesList.sort( sortStyles );
 65
 66 								// Loop over the Array, adding all items to the
 67 								// combo.
 68 								var lastType;
 69 								for ( i = 0 ; i < stylesList.length ; i++ )
 70 								{
 71 									style = stylesList[ i ];
 72 									styleName = style._name;
 73
 74 									var type = style.type;
 75
 76 									if ( type != lastType )
 77 									{
 78 										combo.startGroup( lang[ 'panelTitle' + String( type ) ] );
 79 										lastType = type;
 80 									}
 81
 82 									combo.add(
 83 										styleName,
 84 										style.type == CKEDITOR.STYLE_OBJECT ? styleName : buildPreview( style._.definition ),
 85 										styleName );
 86 								}
 87
 88 								combo.commit();
 89
 90 								combo.onOpen();
 91 							});
 92 					},
 93
 94 					onClick : function( value )
 95 					{
 96 						editor.focus();
 97 						editor.fire( 'saveSnapshot' );
 98
 99 						var style = styles[ value ],
100 							selection = editor.getSelection();
101
102 						if ( style.type == CKEDITOR.STYLE_OBJECT )
103 						{
104 							var element = selection.getSelectedElement();
105 							if ( element )
106 								style.applyToObject( element );
107
108 							return;
109 						}
110
111 						var elementPath = new CKEDITOR.dom.elementPath( selection.getStartElement() );
112
113 						if ( style.type == CKEDITOR.STYLE_INLINE && style.checkActive( elementPath ) )
114 							style.remove( editor.document );
115 						else
116 							style.apply( editor.document );
117
118 						editor.fire( 'saveSnapshot' );
119 					},
120
121 					onRender : function()
122 					{
123 						editor.on( 'selectionChange', function( ev )
124 							{
125 								var currentValue = this.getValue();
126
127 								var elementPath = ev.data.path,
128 									elements = elementPath.elements;
129
130 								// For each element into the elements path.
131 								for ( var i = 0, element ; i < elements.length ; i++ )
132 								{
133 									element = elements[i];
134
135 									// Check if the element is removable by any of
136 									// the styles.
137 									for ( var value in styles )
138 									{
139 										if ( styles[ value ].checkElementRemovable( element, true ) )
140 										{
141 											if ( value != currentValue )
142 												this.setValue( value );
143 											return;
144 										}
145 									}
146 								}
147
148 								// If no styles match, just empty it.
149 								this.setValue( '' );
150 							},
151 							this);
152 					},
153
154 					onOpen : function()
155 					{
156 						if ( CKEDITOR.env.ie )
157 							editor.focus();
158
159 						var selection = editor.getSelection();
160
161 						var element = selection.getSelectedElement(),
162 							elementName = element && element.getName(),
163 							elementPath = new CKEDITOR.dom.elementPath( element || selection.getStartElement() );
164
165 						var counter = [ 0, 0, 0, 0 ];
166 						this.showAll();
167 						this.unmarkAll();
168 						for ( var name in styles )
169 						{
170 							var style = styles[ name ],
171 								type = style.type;
172
173 							if ( type == CKEDITOR.STYLE_OBJECT )
174 							{
175 								if ( element && style.element == elementName )
176 								{
177 									if ( style.checkElementRemovable( element, true ) )
178 										this.mark( name );
179
180 									counter[ type ]++;
181 								}
182 								else
183 									this.hideItem( name );
184 							}
185 							else
186 							{
187 								if ( style.checkActive( elementPath ) )
188 									this.mark( name );
189
190 								counter[ type ]++;
191 							}
192 						}
193
194 						if ( !counter[ CKEDITOR.STYLE_BLOCK ] )
195 							this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_BLOCK ) ] );
196
197 						if ( !counter[ CKEDITOR.STYLE_INLINE ] )
198 							this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_INLINE ) ] );
199
200 						if ( !counter[ CKEDITOR.STYLE_OBJECT ] )
201 							this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_OBJECT ) ] );
202 					}
203 				});
204 		}
205 	});
206
207 	var stylesSets = {};
208
209 	CKEDITOR.addStylesSet = function( name, styles )
210 	{
211 		stylesSets[ name ] = styles;
212 	};
213
214 	CKEDITOR.loadStylesSet = function( name, url, callback )
215 	{
216 		var stylesSet = stylesSets[ name ];
217
218 		if ( stylesSet )
219 		{
220 			callback( stylesSet );
221 			return ;
222 		}
223
224 		CKEDITOR.scriptLoader.load( url, function()
225 			{
226 				callback( stylesSets[ name ] );
227 			});
228 	};
229
230 	function buildPreview( styleDefinition )
231 	{
232 		var html = [];
233
234 		var elementName = styleDefinition.element;
235
236 		// Avoid <bdo> in the preview.
237 		if ( elementName == 'bdo' )
238 			elementName = 'span';
239
240 		html = [ '<', elementName ];
241
242 		// Assign all defined attributes.
243 		var attribs	= styleDefinition.attributes;
244 		if ( attribs )
245 		{
246 			for ( var att in attribs )
247 			{
248 				html.push( ' ', att, '="', attribs[ att ], '"' );
249 			}
250 		}
251
252 		// Assign the style attribute.
253 		var cssStyle = CKEDITOR.style.getStyleText( styleDefinition );
254 		if ( cssStyle )
255 			html.push( ' style="', cssStyle, '"' );
256
257 		html.push( '>', styleDefinition.name, '</', elementName, '>' );
258
259 		return html.join( '' );
260 	}
261
262 	function sortStyles( styleA, styleB )
263 	{
264 		var typeA = styleA.type,
265 			typeB = styleB.type;
266
267 		return typeA == typeB ? 0 :
268 			typeA == CKEDITOR.STYLE_OBJECT ? -1 :
269 			typeB == CKEDITOR.STYLE_OBJECT ? 1 :
270 			typeB == CKEDITOR.STYLE_BLOCK ? 1 :
271 			-1;
272 	}
273 })();
274
275 CKEDITOR.config.stylesCombo_stylesSet = 'default';
276