1 /*
  2 Copyright (c) 2003-2012, 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 				styles = {},
 17 				stylesList = [],
 18 				combo;
 19 
 20 			function loadStylesSet( callback )
 21 			{
 22 				editor.getStylesSet( function( stylesDefinitions )
 23 				{
 24 					if ( !stylesList.length )
 25 					{
 26 						var style,
 27 							styleName;
 28 
 29 						// Put all styles into an Array.
 30 						for ( var i = 0, count = stylesDefinitions.length ; i < count ; i++ )
 31 						{
 32 							var styleDefinition = stylesDefinitions[ i ];
 33 
 34 							styleName = styleDefinition.name;
 35 
 36 							style = styles[ styleName ] = new CKEDITOR.style( styleDefinition );
 37 							style._name = styleName;
 38 							style._.enterMode = config.enterMode;
 39 
 40 							stylesList.push( style );
 41 						}
 42 
 43 						// Sorts the Array, so the styles get grouped by type.
 44 						stylesList.sort( sortStyles );
 45 					}
 46 
 47 					callback && callback();
 48 				});
 49 			}
 50 
 51 			editor.ui.addRichCombo( 'Styles',
 52 				{
 53 					label : lang.label,
 54 					title : lang.panelTitle,
 55 					className : 'cke_styles',
 56 
 57 					panel :
 58 					{
 59 						css : editor.skin.editor.css.concat( config.contentsCss ),
 60 						multiSelect : true,
 61 						attributes : { 'aria-label' : lang.panelTitle }
 62 					},
 63 
 64 					init : function()
 65 					{
 66 						combo = this;
 67 
 68 						loadStylesSet( function()
 69 							{
 70 								var style,
 71 									styleName,
 72 									lastType,
 73 									type,
 74 									i,
 75 									count;
 76 
 77 								// Loop over the Array, adding all items to the
 78 								// combo.
 79 								for ( i = 0, count = stylesList.length ; i < count ; i++ )
 80 								{
 81 									style = stylesList[ i ];
 82 									styleName = style._name;
 83 									type = style.type;
 84 
 85 									if ( type != lastType )
 86 									{
 87 										combo.startGroup( lang[ 'panelTitle' + String( type ) ] );
 88 										lastType = type;
 89 									}
 90 
 91 									combo.add(
 92 										styleName,
 93 										style.type == CKEDITOR.STYLE_OBJECT ? styleName : style.buildPreview(),
 94 										styleName );
 95 								}
 96 
 97 								combo.commit();
 98 
 99 							});
100 					},
101 
102 					onClick : function( value )
103 					{
104 						editor.focus();
105 						editor.fire( 'saveSnapshot' );
106 
107 						var style = styles[ value ],
108 							selection = editor.getSelection(),
109 							elementPath = new CKEDITOR.dom.elementPath( selection.getStartElement() );
110 
111 						style[ style.checkActive( elementPath ) ? 'remove' : 'apply' ]( editor.document );
112 
113 						editor.fire( 'saveSnapshot' );
114 					},
115 
116 					onRender : function()
117 					{
118 						editor.on( 'selectionChange', function( ev )
119 							{
120 								var currentValue = this.getValue(),
121 									elementPath = ev.data.path,
122 									elements = elementPath.elements;
123 
124 								// For each element into the elements path.
125 								for ( var i = 0, count = elements.length, element ; i < count ; i++ )
126 								{
127 									element = elements[i];
128 
129 									// Check if the element is removable by any of
130 									// the styles.
131 									for ( var value in styles )
132 									{
133 										if ( styles[ value ].checkElementRemovable( element, true ) )
134 										{
135 											if ( value != currentValue )
136 												this.setValue( value );
137 											return;
138 										}
139 									}
140 								}
141 
142 								// If no styles match, just empty it.
143 								this.setValue( '' );
144 							},
145 							this);
146 					},
147 
148 					onOpen : function()
149 					{
150 						if ( CKEDITOR.env.ie || CKEDITOR.env.webkit )
151 							editor.focus();
152 
153 						var selection = editor.getSelection(),
154 							element = selection.getSelectedElement(),
155 							elementPath = new CKEDITOR.dom.elementPath( element || selection.getStartElement() ),
156 							counter = [ 0, 0, 0, 0 ];
157 
158 						this.showAll();
159 						this.unmarkAll();
160 						for ( var name in styles )
161 						{
162 							var style = styles[ name ],
163 								type = style.type;
164 
165 							if ( style.checkActive( elementPath ) )
166 								this.mark( name );
167 							else if ( type == CKEDITOR.STYLE_OBJECT && !style.checkApplicable( elementPath ) )
168 							{
169 								this.hideItem( name );
170 								counter[ type ]--;
171 							}
172 
173 							counter[ type ]++;
174 						}
175 
176 						if ( !counter[ CKEDITOR.STYLE_BLOCK ] )
177 							this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_BLOCK ) ] );
178 
179 						if ( !counter[ CKEDITOR.STYLE_INLINE ] )
180 							this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_INLINE ) ] );
181 
182 						if ( !counter[ CKEDITOR.STYLE_OBJECT ] )
183 							this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_OBJECT ) ] );
184 					},
185 
186 					// Force a reload of the data
187 					reset: function()
188 					{
189 						if ( combo )
190 						{
191 							delete combo._.panel;
192 							delete combo._.list;
193 							combo._.committed = 0;
194 							combo._.items = {};
195 							combo._.state = CKEDITOR.TRISTATE_OFF;
196 						}
197 						styles = {};
198 						stylesList = [];
199 						loadStylesSet();
200 					}
201 				});
202 
203 			editor.on( 'instanceReady', function() { loadStylesSet(); } );
204 		}
205 	});
206 
207 	function sortStyles( styleA, styleB )
208 	{
209 		var typeA = styleA.type,
210 			typeB = styleB.type;
211 
212 		return typeA == typeB ? 0 :
213 			typeA == CKEDITOR.STYLE_OBJECT ? -1 :
214 			typeB == CKEDITOR.STYLE_OBJECT ? 1 :
215 			typeB == CKEDITOR.STYLE_BLOCK ? 1 :
216 			-1;
217 	}
218 })();
219