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 CKEDITOR.dialog.add( 'select', function( editor )
  6 {
  7 	// Add a new option to a SELECT object (combo or list).
  8 	function addOption( combo, optionText, optionValue, documentObject, index )
  9 	{
 10 		combo = getSelect( combo );
 11 		var oOption;
 12 		if ( documentObject )
 13 			oOption = documentObject.createElement( "OPTION" );
 14 		else
 15 			oOption = document.createElement( "OPTION" );
 16
 17 		if ( combo && oOption && oOption.getName() == 'option' )
 18 		{
 19 			if ( CKEDITOR.env.ie ) {
 20 				if ( !isNaN( parseInt( index, 10) ) )
 21 					combo.$.options.add( oOption.$, index );
 22 				else
 23 					combo.$.options.add( oOption.$ );
 24
 25 				oOption.$.innerHTML = optionText.length > 0 ? optionText : '';
 26 				oOption.$.value     = optionValue;
 27 			}
 28 			else
 29 			{
 30 				if ( index != null && index < combo.getChildCount() )
 31 					combo.getChild( index < 0 ? 0 : index ).insertBeforeMe( oOption );
 32 				else
 33 					combo.append( oOption );
 34
 35 				oOption.setText( optionText.length > 0 ? optionText : '' );
 36 				oOption.setValue( optionValue );
 37 			}
 38 		}
 39 		else
 40 			return false;
 41
 42 		return oOption;
 43 	}
 44 	// Remove all selected options from a SELECT object.
 45 	function removeSelectedOptions( combo )
 46 	{
 47 		combo = getSelect( combo );
 48
 49 		// Save the selected index
 50 		var iSelectedIndex = getSelectedIndex( combo );
 51
 52 		// Remove all selected options.
 53 		for ( var i = combo.getChildren().count() - 1 ; i >= 0 ; i-- )
 54 		{
 55 			if ( combo.getChild( i ).$.selected )
 56 				combo.getChild( i ).remove();
 57 		}
 58
 59 		// Reset the selection based on the original selected index.
 60 		setSelectedIndex( combo, iSelectedIndex );
 61 	}
 62 	//Modify option  from a SELECT object.
 63 	function modifyOption( combo, index, title, value )
 64 	{
 65 		combo = getSelect( combo );
 66 		if ( index < 0 )
 67 			return false;
 68 		var child = combo.getChild( index );
 69 		child.setText( title );
 70 		child.setValue( value );
 71 		return child;
 72 	}
 73 	function removeAllOptions( combo )
 74 	{
 75 		combo = getSelect( combo );
 76 		while( combo.getChild( 0 ) && combo.getChild( 0 ).remove() );
 77 	}
 78 	// Moves the selected option by a number of steps (also negative).
 79 	function changeOptionPosition( combo, steps, documentObject )
 80 	{
 81 		combo = getSelect( combo );
 82 		var iActualIndex = getSelectedIndex( combo );
 83 		if ( iActualIndex < 0 )
 84 			return false;
 85
 86 		var iFinalIndex = iActualIndex + steps;
 87 		iFinalIndex = ( iFinalIndex < 0 ) ? 0 : iFinalIndex;
 88 		iFinalIndex = ( iFinalIndex >= combo.getChildCount() ) ? combo.getChildCount() - 1 : iFinalIndex;
 89
 90 		if ( iActualIndex == iFinalIndex )
 91 			return false;
 92
 93 		var oOption = combo.getChild( iActualIndex ),
 94 			sText	= oOption.getText(),
 95 			sValue	= oOption.getValue();
 96
 97 		oOption.remove();
 98
 99 		oOption = addOption( combo, sText, sValue, ( !documentObject ) ? null : documentObject, iFinalIndex );
100 		setSelectedIndex( combo, iFinalIndex );
101 		return oOption;
102 	}
103 	function getSelectedIndex( combo )
104 	{
105 		combo = getSelect( combo );
106 		return combo ? combo.$.selectedIndex : -1;
107 	}
108 	function setSelectedIndex( combo, index )
109 	{
110 		combo = getSelect( combo );
111 		if ( index < 0 )
112 			return ;
113 		var count = combo.getChildren().count();
114 		combo.$.selectedIndex = ( index >= count ) ? ( count - 1 ) : index;
115 		return combo;
116 	}
117 	function getOptions( combo )
118 	{
119 		combo = getSelect( combo );
120 		return combo ? combo.getChildren() : false;
121 	}
122 	function getSelect( obj )
123 	{
124 		if ( obj && obj.domId && obj.getInputElement().$ )				// Dialog element.
125 			return  obj.getInputElement();
126 		else if ( obj && obj.$ )
127 			return obj;
128 		return false;
129 	}
130
131 	return {
132 		title : editor.lang.select.title,
133 		minWidth : 400,
134 		minHeight : 370,
135 		onShow : function()
136 		{
137 			// IE BUG: Selection must be in the editor for getSelectedElement()
138 			// to work.
139 			this.restoreSelection();
140
141 			this.setupContent( 'clear' );
142 			var element = this.getParentEditor().getSelection().getSelectedElement();
143 			if ( element && element.getName() == "select" )
144 			{
145 				this._element = element;
146 				this.setupContent( element.getName(), element );
147
148 				//Load Options into dialog.
149 				var objOptions = getOptions( element );
150 				for ( var i = 0 ; i < objOptions.count() ; i++ )
151 					this.setupContent( 'option', objOptions.getItem( i ) );
152 			}
153 		},
154 		onOk : function()
155 		{
156 			var editor = this.getParentEditor(),
157 				element = this._element,
158 				isInsertMode = !element;
159
160 			if ( isInsertMode )
161 				element = editor.document.createElement( 'select' );
162 			this.commitContent( element );
163
164 			if ( isInsertMode )
165 			{
166 				this.restoreSelection();
167 				this.clearSavedSelection();
168 				editor.insertElement( element );
169 			}
170 		},
171 		contents : [
172 			{
173 				id : 'info',
174 				label : editor.lang.select.selectInfo,
175 				title : editor.lang.select.selectInfo,
176 				accessKey : '',
177 				elements : [
178 					{
179 						id : 'txtName',
180 						type : 'text',
181 						widths : [ '25%','75%' ],
182 						labelLayout : 'horizontal',
183 						label : editor.lang.common.name,
184 						'default' : '',
185 						accessKey : 'N',
186 						align : 'center',
187 						style : 'width:350px',
188 						setup : function( name, element )
189 						{
190 							if ( name == 'select' )
191 							{
192 								this.setValue( element.getAttribute( 'name' ) );
193 								this.focus();
194 							}
195 						},
196 						commit : function( element )
197 						{
198 							if ( this.getValue() != '' || this.isChanged() )
199 								element.setAttribute( 'name', this.getValue() );
200 						}
201 					},
202 					{
203 						id : 'txtValue',
204 						type : 'text',
205 						widths : [ '25%','75%' ],
206 						labelLayout : 'horizontal',
207 						label : editor.lang.select.value,
208 						style : 'width:350px',
209 						'default' : '',
210 						readonly : true,		// TODO: make it readonly somehow.
211 						disabled : true
212 					},
213 					{
214 						type : 'hbox',
215 						widths : [ '175px', '170px' ],
216 						align : 'center',
217 						children :
218 						[
219 							{
220 								id : 'txtSize',
221 								type : 'text',
222 								align : 'center',
223 								labelLayout : 'horizontal',
224 								label : editor.lang.select.size,
225 								'default' : '',
226 								accessKey : 'S',
227 								style : 'width:175px',
228 								validate: function()
229 								{
230 									var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
231 									return ( ( this.getValue() == '' ) || func.apply( this ) );
232 								},
233 								setup : function( name, element )
234 								{
235 									if ( name == 'select' )
236 										this.setValue( element.getAttribute( 'size' ) );
237 								},
238 								commit : function( element )
239 								{
240 									if ( this.getValue() != '' || this.isChanged() )
241 										element.setAttribute( 'size', this.getValue() );
242 								}
243 							},
244 							{
245 								type : 'html',
246 								html : '<span>' + CKEDITOR.tools.htmlEncode( editor.lang.select.lines ) + '</span>'
247 							}
248 						]
249 					},
250 					{
251 						type : 'html',
252 						html : '<span>' + CKEDITOR.tools.htmlEncode( editor.lang.select.opAvail ) + '</span>'
253 					},
254 					{
255 						type : 'hbox',
256 						widths : [ '115px', '115px' ,'100px' ],
257 						align : 'top',
258 						children :
259 						[
260 							{
261 								type : 'vbox',
262 								children :
263 								[
264 									{
265 										id : 'txtOptName',
266 										type : 'text',
267 										label : editor.lang.select.opText,
268 										style : 'width:115px',
269 										setup : function( name, element )
270 										{
271 											if ( name == 'clear' )
272 												this.setValue( "" );
273 										}
274 									},
275 									{
276 										type : 'select',
277 										id : 'cmbName',
278 										label : '',
279 										title : '',
280 										size : 5,
281 										style : 'width:115px;height:75px',
282 										items : [],
283 										onChange : function()
284 										{
285 											var dialog = this.getDialog(),
286 												values = dialog.getContentElement( 'info', 'cmbValue' ),
287 												optName = dialog.getContentElement( 'info', 'txtOptName' ),
288 												optValue = dialog.getContentElement( 'info', 'txtOptValue' ),
289 												iIndex = getSelectedIndex( this );
290
291 											setSelectedIndex( values, iIndex );
292 											optName.setValue( this.getValue() );
293 											optValue.setValue( values.getValue() );
294 										},
295 										setup : function( name, element )
296 										{
297 											if ( name == 'clear' )
298 												removeAllOptions( this );
299 											else if ( name == 'option' )
300 												addOption( this, element.getText(), element.getText(),
301 													this.getDialog().getParentEditor().document );
302 										},
303 										commit : function( element )
304 										{
305 											var dialog = this.getDialog(),
306 												optionsNames = getOptions( this ),
307 												optionsValues = getOptions( dialog.getContentElement( 'info', 'cmbValue' ) ),
308 												selectValue = dialog.getContentElement( 'info', 'txtValue' ).getValue();
309
310 											removeAllOptions( element );
311
312 											for ( var i = 0 ; i < optionsNames.count() ; i++ )
313 											{
314 												var oOption = addOption( element, optionsNames.getItem( i ).getValue(),
315 													optionsValues.getItem( i ).getValue(), dialog.getParentEditor().document );
316 												if ( optionsValues.getItem( i ).getValue() == selectValue )
317 												{
318 													oOption.setAttribute( 'selected', 'selected' );
319 													oOption.selected = true;
320 												}
321 											}
322 										}
323 									}
324 								]
325 							},
326 							{
327 								type : 'vbox',
328 								children :
329 								[
330 									{
331 										id : 'txtOptValue',
332 										type : 'text',
333 										label : editor.lang.select.opValue,
334 										style : 'width:115px',
335 										setup : function( name, element )
336 										{
337 											if ( name == 'clear' )
338 												this.setValue( "" );
339 										}
340 									},
341 									{
342 										type : 'select',
343 										id : 'cmbValue',
344 										label : '',
345 										size : 5,
346 										style : 'width:115px;height:75px',
347 										items : [],
348 										onChange : function()
349 										{
350 											var dialog = this.getDialog(),
351 												names = dialog.getContentElement( 'info', 'cmbName' ),
352 												optName = dialog.getContentElement( 'info', 'txtOptName' ),
353 												optValue = dialog.getContentElement( 'info', 'txtOptValue' ),
354 												iIndex = getSelectedIndex( this );
355
356 											setSelectedIndex( names, iIndex );
357 											optName.setValue( names.getValue() );
358 											optValue.setValue( this.getValue() );
359 										},
360 										setup : function( name, element )
361 										{
362 											if ( name == 'clear' )
363 												removeAllOptions( this );
364 											else if ( name == 'option' )
365 											{
366 												var oValue	= element.getValue();
367 												addOption( this, oValue, oValue,
368 													this.getDialog().getParentEditor().document );
369 												if ( element.getAttribute( 'selected' ) == 'selected' )
370 													this.getDialog().getContentElement( 'info', 'txtValue' ).setValue( oValue );
371 											}
372 										}
373 									},
374 								]
375 							},
376 							{
377 								type : 'vbox',
378 								padding : 5,
379 								children :
380 								[
381 									{
382 										type : 'button',
383 										style : '',
384 										label : editor.lang.select.btnAdd,
385 										title : editor.lang.select.btnAdd,
386 										style : 'width:100%;',
387 										onClick : function()
388 										{
389 											//Add new option.
390 											var dialog = this.getDialog();
391 												parentEditor = dialog.getParentEditor(),
392 												optName = dialog.getContentElement( 'info', 'txtOptName' ),
393 												optValue = dialog.getContentElement( 'info', 'txtOptValue' ),
394 												names = dialog.getContentElement( 'info', 'cmbName' ),
395 												values = dialog.getContentElement( 'info', 'cmbValue' );
396
397 											addOption(names, optName.getValue(), optName.getValue(), dialog.getParentEditor().document );
398 											addOption(values, optValue.getValue(), optValue.getValue(), dialog.getParentEditor().document );
399
400 											optName.setValue( "" );
401 											optValue.setValue( "" );
402 										}
403 									},
404 									{
405 										type : 'button',
406 										label : editor.lang.select.btnModify,
407 										title : editor.lang.select.btnModify,
408 										style : 'width:100%;',
409 										onClick : function()
410 										{
411 											//Modify selected option.
412 											var dialog = this.getDialog();
413 												optName = dialog.getContentElement( 'info', 'txtOptName' ),
414 												optValue = dialog.getContentElement( 'info', 'txtOptValue' ),
415 												names = dialog.getContentElement( 'info', 'cmbName' ),
416 												values = dialog.getContentElement( 'info', 'cmbValue' ),
417 												iIndex = getSelectedIndex( names );
418
419 											if ( iIndex >= 0 )
420 											{
421 												modifyOption( names, iIndex, optName.getValue(), optName.getValue() );
422 												modifyOption( values, iIndex, optValue.getValue(), optValue.getValue() );
423 											}
424 										}
425 									},
426 									{
427 										type : 'button',
428 										style : 'width:100%;',
429 										label : editor.lang.select.btnUp,
430 										title : editor.lang.select.btnUp,
431 										onClick : function()
432 										{
433 											//Move up.
434 											var dialog = this.getDialog(),
435 												names = dialog.getContentElement( 'info', 'cmbName' ),
436 												values = dialog.getContentElement( 'info', 'cmbValue' );
437
438 											changeOptionPosition( names, -1, dialog.getParentEditor().document );
439 											changeOptionPosition( values, -1, dialog.getParentEditor().document );
440 										}
441 									},
442 									{
443 										type : 'button',
444 										style : 'width:100%;',
445 										label : editor.lang.select.btnDown,
446 										title : editor.lang.select.btnDown,
447 										onClick : function()
448 										{
449 											//Move down.
450 											var dialog = this.getDialog(),
451 												names = dialog.getContentElement( 'info', 'cmbName' ),
452 												values = dialog.getContentElement( 'info', 'cmbValue' );
453
454 											changeOptionPosition( names, 1, dialog.getParentEditor().document );
455 											changeOptionPosition( values, 1, dialog.getParentEditor().document );
456 										}
457 									}
458 								]
459 							}
460 						]
461 					},
462 					{
463 						type : 'hbox',
464 						widths : [ '40%', '20%', '40%' ],
465 						children :
466 						[
467 							{
468 								type : 'button',
469 								label : editor.lang.select.btnSetValue,
470 								title : editor.lang.select.btnSetValue,
471 								onClick : function()
472 								{
473 									//Set as default value.
474 									var dialog = this.getDialog(),
475 										values = dialog.getContentElement( 'info', 'cmbValue' ),
476 										txtValue = dialog.getContentElement( 'info', 'txtValue' );
477 									txtValue.setValue( values.getValue() );
478 								}
479 							},
480 							{
481 								type : 'button',
482 								label : editor.lang.select.btnDelete,
483 								title : editor.lang.select.btnDelete,
484 								onClick : function()
485 								{
486 									// Delete option.
487 									var dialog = this.getDialog(),
488 										names = dialog.getContentElement( 'info', 'cmbName' ),
489 										values = dialog.getContentElement( 'info', 'cmbValue' ),
490 										optName = dialog.getContentElement( 'info', 'txtOptName' ),
491 										optValue = dialog.getContentElement( 'info', 'txtOptValue' );
492
493 									removeSelectedOptions( names );
494 									removeSelectedOptions( values );
495
496 									optName.setValue( "" );
497 									optValue.setValue( "" );
498 								}
499 							},
500 							{
501 								id : 'chkMulti',
502 								type : 'checkbox',
503 								label : editor.lang.select.chkMulti,
504 								'default' : '',
505 								accessKey : 'M',
506 								value : "checked",
507 								setup : function( name, element )
508 								{
509 									if ( name == 'select' )
510 										this.setValue( element.getAttribute( 'multiple' ) );
511 								},
512 								commit : function( element )
513 								{
514 									if ( this.getValue() == true || this.isChanged() )
515 										element.setAttribute( 'multiple', this.getValue() );
516 								}
517 							}
518 						]
519 					}
520 				]
521 			}
522 		]
523 	};
524 });
525