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 	// Load image preview.
  9 	var IMAGE = 1,
 10 		LINK = 2,
 11 		PREVIEW = 4,
 12 		CLEANUP = 8,
 13 		regexGetSize = /^\s*(\d+)((px)|\%)?\s*$/i,
 14 		regexGetSizeOrEmpty = /(^\s*(\d+)((px)|\%)?\s*$)|^$/i;
 15
 16 	var onSizeChange = function()
 17 	{
 18 		var value = this.getValue(),	// This = input element.
 19 			dialog = this.getDialog(),
 20 			aMatch  =  value.match( regexGetSize );	// Check value
 21 		if ( aMatch )
 22 		{
 23 			if ( aMatch[2] == '%' )			// % is allowed - > unlock ratio.
 24 				switchLockRatio( dialog, false );	// Unlock.
 25 			value = aMatch[1];
 26 		}
 27
 28 		// Only if ratio is locked
 29 		if ( dialog.lockRatio )
 30 		{
 31 			var oImageOriginal = dialog.originalElement;
 32 			if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
 33 			{
 34 				if ( this.id == 'txtHeight' )
 35 				{
 36 					if ( value != '' && value != 0 )
 37 						value = Math.round( oImageOriginal.$.width * ( value  / oImageOriginal.$.height ) );
 38 					if ( !isNaN( value ) )
 39 						dialog.setValueOf( 'info', 'txtWidth', value );
 40 				}
 41 				else		//this.id = txtWidth.
 42 				{
 43 					if ( value != '' && value != 0 )
 44 						value = Math.round( oImageOriginal.$.height * ( value  / oImageOriginal.$.width ) );
 45 					if ( !isNaN( value ) )
 46 						dialog.setValueOf( 'info', 'txtHeight', value );
 47 				}
 48 			}
 49 		}
 50 		updatePreview( dialog );
 51 	};
 52
 53 	var updatePreview = function( dialog )
 54 	{
 55 		//Don't load before onShow.
 56 		if ( !dialog.originalElement || !dialog.preview )
 57 			return 1;
 58
 59 		// Read attributes and update imagePreview;
 60 		dialog.commitContent( PREVIEW, dialog.preview );
 61 		return 0;
 62 	};
 63
 64 	var switchLockRatio = function( dialog, value )
 65 	{
 66 		var oImageOriginal = dialog.originalElement,
 67 			ratioButton = CKEDITOR.document.getById( 'btnLockSizes' );
 68
 69 		if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
 70 		{
 71 			if ( value == 'check' )			// Check image ratio and original image ratio.
 72 			{
 73 				var width = dialog.getValueOf( 'info', 'txtWidth' ),
 74 					height = dialog.getValueOf( 'info', 'txtHeight' ),
 75 					originalRatio = oImageOriginal.$.width * 1000 / oImageOriginal.$.height,
 76 					thisRatio = width * 1000 / height;
 77 				dialog.lockRatio  = false;		// Default: unlock ratio
 78
 79 				if ( width == 0 && height == 0 )
 80 					dialog.lockRatio = true;
 81 				else if ( !isNaN( originalRatio ) && !isNaN( thisRatio ))
 82 					if ( Math.round( originalRatio ) == Math.round( thisRatio ) )
 83 						dialog.lockRatio = true;
 84 			}
 85 			else if ( value != undefined )
 86 				dialog.lockRatio = value
 87 			else
 88 				dialog.lockRatio = !dialog.lockRatio;
 89 		}
 90 		else if ( value != 'check' )		// I can't lock ratio if ratio is unknown.
 91 			dialog.lockRatio = false;
 92
 93 		if ( dialog.lockRatio )
 94 			ratioButton.removeClass( 'BtnUnlocked' );
 95 		else
 96 			ratioButton.addClass( 'BtnUnlocked' );
 97
 98 		return dialog.lockRatio;
 99 	};
100
101 	var resetSize = function( dialog )
102 	{
103 		var oImageOriginal = dialog.originalElement;
104 		if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
105 		{
106 			dialog.setValueOf( 'info', 'txtWidth', oImageOriginal.$.width );
107 			dialog.setValueOf( 'info', 'txtHeight', oImageOriginal.$.height );
108 		}
109 		updatePreview( dialog );
110 	};
111
112 	var setupDimension = function( type, element )
113 	{
114 		if ( type != IMAGE )
115 			return 0;
116
117 		var checkDimension = function( size, defaultValue )
118 		{
119 			var aMatch  =  size.match( regexGetSize );
120 			if ( aMatch )
121 			{
122 				if ( aMatch[2] == '%' )				// % is allowed.
123 				{
124 					aMatch[1] += '%';
125 					switchLockRatio( dialog, false );	// Unlock ratio
126 				}
127 				return aMatch[1];
128 			}
129 			return defaultValue;
130 		},
131 			dialog = this.getDialog(),
132 			value = '',
133 			dimension = (( this.id == 'txtWidth' )? 'width' : 'height' ),
134 			size = element.getAttribute( dimension );
135
136 		if ( size )
137 			value = checkDimension( size, value );
138 		value = checkDimension( element.$.style[ dimension ], value );
139
140 		this.setValue( value );
141 	};
142
143 	var imageDialog = function( editor, dialogType )
144 	{
145 		var onImgLoadEvent = function()
146 		{
147 			// Image is ready.
148 			var original = this.originalElement;
149 			original.setCustomData( 'isReady', 'true' );
150 			original.removeListener( 'load', onImgLoadEvent );
151 			original.removeListener( 'error', onImgLoadErrorEvent );
152 			original.removeListener( 'abort', onImgLoadErrorEvent );
153
154 			// Hide loader
155 			CKEDITOR.document.getById( 'ImagePreviewLoader' ).setStyle( 'display', 'none' );
156
157 			// New image -> new domensions
158 			if ( this.dontResetSize == false )
159 				resetSize( this );
160
161 			if ( this.firstLoad )
162 				switchLockRatio( this, 'check' );
163 			this.firstLoad = false;
164 			this.dontResetSize = false;
165 		};
166
167 		var onImgLoadErrorEvent = function()
168 		{
169 			// Error. Image is not loaded.
170 			var original = this.originalElement;
171 			original.removeListener( 'load', onImgLoadEvent );
172 			original.removeListener( 'error', onImgLoadErrorEvent );
173 			original.removeListener( 'abort', onImgLoadErrorEvent );
174
175 			// Set Error image.
176 			var noimage = CKEDITOR.getUrl(
178 				'skins/' + editor.config.skin + '/images/dialog.noimage.gif' );
179
180 			if ( this.preview )
181 				this.preview.setAttribute( 'src', noimage );
182
183 			// Hide loader
184 			CKEDITOR.document.getById( 'ImagePreviewLoader' ).setStyle( 'display', 'none' );
185 			switchLockRatio( this, false );	// Unlock.
186 		};
187 		return {
188 			title : ( dialogType == 'image' ) ? editor.lang.image.title : editor.lang.image.titleButton,
189 			minWidth : 450,
190 			minHeight : 400,
191 			onShow : function()
192 			{
193 				this.imageElement = false;
194 				this.linkElement = false;
195
196 				// Default: create a new element.
197 				this.imageEditMode = false;
198 				this.linkEditMode = false;
199
200 				this.lockRatio = true;
201 				this.dontResetSize = false;
202 				this.firstLoad = true;
203 				this.addLink = false;
204
205 				//Hide loader.
206 				CKEDITOR.document.getById( 'ImagePreviewLoader' ).setStyle( 'display', 'none' );
207 				// Preview
208 				this.preview = CKEDITOR.document.getById( 'previewImage' );
209
210 				// IE BUG: Selection must be in the editor for getSelectedElement()
211 				// to work.
212 				this.restoreSelection();
213
214 				var editor = this.getParentEditor(),
215 					element = this.getParentEditor().getSelection().getSelectedElement();
216
217 				// Copy of the image
218 				this.originalElement = editor.document.createElement( 'img' );
219 				this.originalElement.setCustomData( 'isReady', 'false' );
220
221 				if ( element && element.getName() == 'a' )
222 				{
223 					this.linkElement = element;
224 					this.linkEditMode = true;
225
226 					// Look for Image element.
227 					var linkChildren = element.getChildren();
228 					if ( linkChildren.count() == 1 )			// 1 child.
229 					{
230 						var childTagName = linkChildren.getItem( 0 ).getName();
231 						if ( childTagName == 'img' || childTagName == 'input' )
232 						{
233 							this.imageElement = linkChildren.getItem( 0 );
234 							if ( this.imageElement.getName() == 'img' )
235 								this.imageEditMode = 'img';
236 							else if ( this.imageElement.getName() == 'input' )
237 								this.imageEditMode = 'input';
238 						}
239 					}
240 					// Fill out all fields.
241 					if ( dialogType == 'image' )
242 						this.setupContent( LINK, element );
243 				}
244 				else if ( element && element.getName() == 'img' && !element.getAttribute( '_cke_protected_html' ) )
245 					this.imageEditMode = 'img';
246 				else if ( element && element.getName() == 'input' && element.getAttribute( 'type' ) && element.getAttribute( 'type' ) == 'image' )
247 					this.imageEditMode = 'input';
248
249 				if ( this.imageEditMode || this.imageElement )
250 				{
251 					if ( !this.imageElement )
252 						this.imageElement = element;
253
254 					// Fill out all fields.
255 					this.setupContent( IMAGE, this.imageElement );
256
257 					// Refresh LockRatio button
258 					switchLockRatio ( this, true );
259 				}
260 			},
261 			onOk : function()
262 			{
263 				// Edit existing Image.
264 				if ( this.imageEditMode )
265 				{
266 					var imgTagName = this.imageEditMode,
267 						removeObj = this.imageElement;
268
269 					// Image dialog and Input element.
270 					if ( dialogType == 'image' && imgTagName == 'input' && confirm( editor.lang.image.button2Img ) )
271 					{
272 						// Replace INPUT-> IMG
273 						imgTagName = 'img';
274 						this.imageElement = editor.document.createElement( 'img' );
275 						removeObj.insertBeforeMe( this.imageElement );
276 						removeObj.remove( false );
277
278 					}
279 					// ImageButton dialog and Image element.
280 					else if ( dialogType != 'image' && imgTagName == 'img' && confirm( editor.lang.image.img2Button ))
281 					{
282 						// Replace IMG -> INPUT
283 						imgTagName = 'input';
284 						this.imageElement = editor.document.createElement( 'input' );
285 						this.imageElement.setAttribute ( 'type' ,'image' );
286 						removeObj.insertBeforeMe( this.imageElement );
287 						removeObj.remove( false );
288 					}
289 				}
290 				else	// Create a new image.
291 				{
292 					// Image dialog -> create IMG element.
293 					if ( dialogType == 'image' )
294 						this.imageElement = editor.document.createElement( 'img' );
295 					else
296 					{
297 						this.imageElement = editor.document.createElement( 'input' );
298 						this.imageElement.setAttribute ( 'type' ,'image' );
299 					}
300 				}
301
302 				// Create a new link.
303 				if ( this.linkEditMode == false )
304 					this.linkElement = editor.document.createElement( 'a' );
305
306 				// Set attributes.
307 				this.commitContent( IMAGE, this.imageElement );
308 				this.commitContent( LINK, this.linkElement );
309
310 				this.restoreSelection();
311 				this.clearSavedSelection();
312
313 				// Insert a new Image.
314 				if ( this.imageEditMode == false )
315 				{
316 					// It doesn't work with IE.
317 					this.restoreSelection();
318 					this.clearSavedSelection();
319
320 					if ( this.addLink )
321 						//Insert a new Link.
322 						if ( this.linkEditMode == false )
323 						{
324 							this.linkElement.append( this.imageElement, false );
325 							editor.insertElement( this.linkElement );
326 						}
327 						else 	//Link already exists, image not.
328 							this.linkElement.append( this.imageElement, false );
329 					else
330 						editor.insertElement( this.imageElement );
331 				}
332 				else		// Image already exists.
333 				{
334 					//Add a new link element.
335 					if ( this.linkEditMode == false && this.addLink )
336 					{
337 						this.imageElement.insertBeforeMe( this.linkElement );
338 						this.imageElement.appendTo( this.linkElement );
339 					}
340 					//Remove Link, Image exists.
341 					else if ( this.linkEditMode == true && this.addLink == false )
342 						this.linkElement.remove( true );
343 				}
344 			},
345 			onLoad : function()
346 			{
347 				if ( dialogType != 'image' )
348 					this.hidePage( 'Link' );		//Hide Link tab.
349 			},
350 			onHide : function()
351 			{
352 				if ( this.preview )
353 					this.commitContent( CLEANUP, this.preview );
354
355 				if ( this.originalElement )
356 				{
357 					this.originalElement.removeListener( 'load', onImgLoadEvent );
358 					this.originalElement.removeListener( 'error', onImgLoadErrorEvent );
359 					this.originalElement.removeListener( 'abort', onImgLoadErrorEvent );
360 					this.originalElement.remove();
361 					this.originalElement = false;		// Dialog is closed.
362 				}
363 			},
364 			contents : [
365 				{
366 					id : 'info',
367 					label : editor.lang.image.infoTab,
368 					accessKey : 'I',
369 					elements :
370 					[
371 						{
372 							type : 'vbox',
373 							padding : 0,
374 							children :
375 							[
376 								{
377 									type : 'html',
378 									html : '<span>' + CKEDITOR.tools.htmlEncode( editor.lang.image.url ) + '</span>'
379 								},
380 								{
381 									type : 'hbox',
382 									widths : [ '280px', '110px' ],
383 									align : 'right',
384 									children :
385 									[
386 										{
387 											id : 'txtUrl',
388 											type : 'text',
389 											label : '',
390 											onChange : function()
391 											{
392 												var dialog = this.getDialog(),
393 													newUrl = this.getValue();
394
395 												//Update original image
396 												if ( newUrl.length > 0 )	//Prevent from load before onShow
397 												{
398 													var dialog = this.getDialog(),
399 														original = dialog.originalElement;
400
401 													original.setCustomData( 'isReady', 'false' );
402 													// Show loader
403 													var loader = CKEDITOR.document.getById( 'ImagePreviewLoader' );
404 													if ( loader )
405 														loader.setStyle( 'display', '' );
406
407 													original.on( 'load', onImgLoadEvent, dialog );
408 													original.on( 'error', onImgLoadErrorEvent, dialog );
409 													original.on( 'abort', onImgLoadErrorEvent, dialog );
410 													original.setAttribute( 'src', newUrl );
411 													dialog.preview.setAttribute( 'src', newUrl );
412
413 													updatePreview( dialog );
414 												}
415 											},
416 											setup : function( type, element )
417 											{
418 												if ( type == IMAGE )
419 												{
420 													var dialog = this.getDialog();
421 													var url = element.getAttribute( '_cke_saved_src' );
422 													if ( !url )
423 														url = element.getAttribute( 'src' );
424 													dialog.dontResetSize = true;
425 													this.setValue( url );		// And call this.onChange()
426 													this.focus();
427 												}
428 											},
429 											commit : function( type, element )
430 											{
431 												if ( type == IMAGE && ( this.getValue() != '' || this.isChanged() ) )
432 												{
433 													element.setAttribute( '_cke_saved_src', decodeURI( this.getValue() ) );
434 													element.setAttribute( 'src', decodeURI( this.getValue() ) );
435 												}
436 												else if ( type == CLEANUP )
437 												{
438 													element.setAttribute( 'src', '' );	// If removeAttribute doesn't work.
439 													element.removeAttribute( 'src' );
440 												}
441 											}
442 										},
443 										{
444 											type : 'button',
445 											id : 'browse',
446 											align : 'center',
447 											label : editor.lang.common.browseServer,
448 											onLoad : function()
449 											{
450 												var dialog = this.getDialog();
451 												if ( dialog.getParentEditor().config.image_browseServer == false )
452 													dialog.getContentElement( 'info', 'browse' ).getElement().hide();
453 											},
454 											onClick : function()
455 											{
456
457 											}
458 										}
459 									]
460 								}
461 							]
462 						},
463 						{
464 							id : 'txtAlt',
465 							type : 'text',
466 							label : editor.lang.image.alt,
467 							accessKey : 'A',
468 							'default' : '',
469 							onChange : function()
470 							{
471 								updatePreview( this.getDialog() );
472 							},
473 							setup : function( type, element )
474 							{
475 								if ( type == IMAGE )
476 									this.setValue( element.getAttribute( 'alt' ) );
477 							},
478 							commit : function( type, element )
479 							{
480 								if ( type == IMAGE )
481 								{
482 									if ( this.getValue() != '' || this.isChanged() )
483 										element.setAttribute( 'alt', this.getValue() );
484 								}
485 								else if ( type == PREVIEW )
486 								{
487 									element.setAttribute( 'alt', this.getValue() );
488 								}
489 								else if ( type == CLEANUP )
490 								{
491 									element.removeAttribute( 'alt' );
492 								}
493 							}
494 						},
495 						{
496 							type : 'hbox',
497 							widths : [ '140px', '240px' ],
498 							children :
499 							[
500 								{
501 									type : 'vbox',
502 									padding : 10,
503 									children :
504 									[
505 										{
506 											type : 'hbox',
507 											widths : [ '70%', '30%' ],
508 											children :
509 											[
510 												{
511 													type : 'vbox',
512 													padding : 1,
513 													children :
514 													[
515 														{
516 															type : 'text',
517 															id : 'txtWidth',
518 															labelLayout : 'horizontal',
519 															label : editor.lang.image.width,
520 															onKeyUp : onSizeChange,
521 															validate: function()
522 															{
523 																var aMatch  =  this.getValue().match( regexGetSizeOrEmpty );
524 																if ( !aMatch )
525 																	alert( editor.lang.common.validateNumberFailed );
526 																return !!aMatch;
527 															},
528 															setup : setupDimension,
529 															commit : function( type, element )
530 															{
531 																if ( type == IMAGE )
532 																{
533 																	var value = this.getValue();
534 																	if ( value != '' )
535 																		element.setAttribute( 'width', value );
536 																	else if ( value == '' && this.isChanged() )
537 																		element.removeAttribute( 'width' );
538 																}
539 																else if ( type == PREVIEW )
540 																{
541 																	var value = this.getValue(),
542 																		aMatch = value.match( regexGetSize );
543 																	if ( !aMatch )
544 																	{
545 																		var oImageOriginal = this.getDialog().originalElement;
546 																		if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
547 																			element.setStyle( 'width',  oImageOriginal.$.width + 'px');
548 																	}
549 																	else
550 																		element.setStyle( 'width', value + 'px');
551 																}
552 																else if ( type == CLEANUP )
553 																{
554 																	element.setStyle( 'width', '0px' );	// If removeAttribute doesn't work.
555 																	element.removeAttribute( 'width' );
556 																	element.removeStyle( 'width' );
557 																}
558 															}
559 														},
560 														{
561 															type : 'text',
562 															id : 'txtHeight',
563 															labelLayout : 'horizontal',
564 															label : editor.lang.image.height,
565 															onKeyUp : onSizeChange,
566 															validate: function()
567 															{
568 																var aMatch = this.getValue().match( regexGetSizeOrEmpty );
569 																if ( !aMatch )
570 																	alert( editor.lang.common.validateNumberFailed );
571 																return !!aMatch;
572 															},
573 															setup : setupDimension,
574 															commit : function( type, element )
575 															{
576 																if ( type == IMAGE )
577 																{
578 																	var value = this.getValue();
579 																	if ( value != '' )
580 																		element.setAttribute( 'height', value );
581 																	else if ( value == '' && this.isChanged() )
582 																		element.removeAttribute( 'height' );
583 																}
584 																else if ( type == PREVIEW )
585 																{
586 																	var value = this.getValue(),
587 																		aMatch = value.match( regexGetSize );
588 																	if ( !aMatch )
589 																	{
590 																		var oImageOriginal = this.getDialog().originalElement;
591 																		if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
592 																			element.setStyle( 'height',  oImageOriginal.$.height + 'px');
593 																	}
594 																	else
595 																		element.setStyle( 'height', value + 'px');
596 																}
597 																else if ( type == CLEANUP )
598 																{
599 																	element.setStyle( 'height', '0px' );	// If removeAttribute doesn't work.
600 																	element.removeAttribute( 'height' );
601 																	element.removeStyle( 'height' );
602 																}
603 															}
604 														}
605 													]
606 												},
607 												{
608 													type : 'html',
609 													style : 'position:relative;top:10px;height:50px;',
610 													onLoad : function()
611 													{
612 														// Activate Reset button
613 														var	resetButton = CKEDITOR.document.getById( 'btnResetSize' );
614 															ratioButton = CKEDITOR.document.getById( 'btnLockSizes' );
615 														if ( resetButton )
616 														{
617 															resetButton.on( 'click', function()
618 																{
619 																	resetSize( this );
620 																}, this.getDialog() );
621 															resetButton.on( 'mouseover', function()
622 																{
623 																	this.addClass( 'BtnOver' );
624 																}, resetButton );
625 															resetButton.on( 'mouseout', function()
626 																{
627 																	this.removeClass( 'BtnOver' );
628 																}, resetButton );
629 														}
630 														// Activate (Un)LockRatio button
631 														if ( ratioButton )
632 														{
633 															ratioButton.on( 'click', function()
634 																{
635 																	var locked = switchLockRatio( this ),
636 																		oImageOriginal = this.originalElement,
637 																		width = this.getValueOf( 'info', 'txtWidth' );
638
639 																	if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' && width )
640 																	{
641 																		var height = oImageOriginal.$.height / oImageOriginal.$.width * width;
642 																		if ( !isNaN( height ) )
643 																		{
644 																			this.setValueOf( 'info', 'txtHeight', Math.round( height ) );
645 																			updatePreview( this );
646 																		}
647 																	}
648 																}, this.getDialog() );
649 															ratioButton.on( 'mouseover', function()
650 																{
651 																	this.addClass( 'BtnOver' );
652 																}, ratioButton );
653 															ratioButton.on( 'mouseout', function()
654 																{
655 																	this.removeClass( 'BtnOver' );
656 																}, ratioButton );
657 														}
658 													},
659 													html : '<div>'+
660 														'<div title="' + editor.lang.image.lockRatio +
661 														'" class="BtnLocked" id="btnLockSizes"></div>' +
662 														'<div title="' + editor.lang.image.resetSize +
663 														'" class="BtnReset" id="btnResetSize"></div>'+
664 														'</div>'
665 												}
666 											]
667 										},
668 										{
669 											type : 'vbox',
670 											padding : 1,
671 											children :
672 											[
673 												{
674 													type : 'text',
675 													id : 'txtBorder',
676 													labelLayout : 'horizontal',
677 													label : editor.lang.image.border,
678 													'default' : '',
679 													onKeyUp : function()
680 													{
681 														updatePreview( this.getDialog() );
682 													},
683 													validate: function()
684 													{
685 														var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
686 														return func.apply( this );
687 													},
688 													setup : function( type, element )
689 													{
690 														if ( type == IMAGE )
691 															this.setValue( element.getAttribute( 'border' ) );
692 													},
693 													commit : function( type, element )
694 													{
695 														if ( type == IMAGE )
696 														{
697 															if ( this.getValue() != '' || this.isChanged() )
698 																element.setAttribute( 'border', this.getValue() );
699 														}
700 														else if ( type == PREVIEW )
701 														{
702 															var value = parseInt( this.getValue(), 10 );
703 															value = isNaN( value ) ? 0 : value;
704 															element.setAttribute( 'border', value );
705 															element.setStyle( 'border', value + 'px solid black' );
706 														}
707 														else if ( type == CLEANUP )
708 														{
709 															element.removeAttribute( 'border' );
710 															element.removeStyle( 'border' );
711 														}
712 													}
713 												},
714 												{
715 													type : 'text',
716 													id : 'txtHSpace',
717 													labelLayout : 'horizontal',
718 													label : editor.lang.image.hSpace,
719 													'default' : '',
720 													onKeyUp : function()
721 													{
722 														updatePreview( this.getDialog() );
723 													},
724 													validate: function()
725 													{
726 														var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
727 														return func.apply( this );
728 													},
729 													setup : function( type, element )
730 													{
731 														if ( type == IMAGE )
732 														{
733 															var value = element.getAttribute( 'hspace' );
734 															if ( value != -1 )				// In IE empty = -1.
735 																this.setValue( value );
736 														}
737 													},
738 													commit : function( type, element )
739 													{
740 														if ( type == IMAGE )
741 														{
742 															if ( this.getValue() != '' || this.isChanged() )
743 																element.setAttribute( 'hspace', this.getValue() );
744 														}
745 														else if ( type == PREVIEW )
746 														{
747 															var value = parseInt( this.getValue(), 10 );
748 															value = isNaN( value ) ? 0 : value;
749 															element.setAttribute( 'hspace', value );
750 															element.setStyle( 'margin-left', value + 'px' );
751 															element.setStyle( 'margin-right', value + 'px' );
752 														}
753 														else if ( type == CLEANUP )
754 														{
755 															element.removeAttribute( 'hspace' );
756 															element.removeStyle( 'margin-left' );
757 															element.removeStyle( 'margin-right' );
758 														}
759 													}
760 												},
761 												{
762 													type : 'text',
763 													id : 'txtVSpace',
764 													labelLayout : 'horizontal',
765 													label : editor.lang.image.vSpace,
766 													'default' : '',
767 													onKeyUp : function()
768 													{
769 														updatePreview( this.getDialog() );
770 													},
771 													validate: function()
772 													{
773 														var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );
774 														return func.apply( this );
775 													},
776 													setup : function( type, element )
777 													{
778 														if ( type == IMAGE )
779 															this.setValue( element.getAttribute( 'vspace' ) );
780 													},
781 													commit : function( type, element )
782 													{
783 														if ( type == IMAGE )
784 														{
785 															if ( this.getValue() != '' || this.isChanged() )
786 																element.setAttribute( 'vspace', this.getValue() );
787 														}
788 														else if ( type == PREVIEW )
789 														{
790 															var value = parseInt( this.getValue(), 10 );
791 															value = isNaN( value ) ? 0 : value;
792 															element.setAttribute( 'vspace', this.getValue() );
793 															element.setStyle( 'margin-top', value + 'px' );
794 															element.setStyle( 'margin-bottom', value + 'px' );
795 														}
796 														else if ( type == CLEANUP )
797 														{
798 															element.removeAttribute( 'vspace' );
799 															element.removeStyle( 'margin-top' );
800 															element.removeStyle( 'margin-bottom' );
801 														}
802 													}
803 												},
804 												{
805 													id : 'cmbAlign',
806 													type : 'select',
807 													labelLayout : 'horizontal',
808 													widths : [ '35%','65%' ],
809 													style : 'width:100%',
810 													label : editor.lang.image.align,
811 													'default' : '',
812 													items :
813 													[
814 														[ editor.lang.common.notSet , ''],
815 														[ editor.lang.image.alignLeft , 'left'],
816 														[ editor.lang.image.alignAbsBottom , 'absBottom'],
817 														[ editor.lang.image.alignAbsMiddle , 'absMiddle'],
818 														[ editor.lang.image.alignBaseline , 'baseline'],
819 														[ editor.lang.image.alignBottom , 'bottom'],
820 														[ editor.lang.image.alignMiddle , 'middle'],
821 														[ editor.lang.image.alignRight , 'right'],
822 														[ editor.lang.image.alignTextTop , 'textTop'],
823 														[ editor.lang.image.alignTop , 'top']
824 													],
825 													onKeyUp : function()
826 													{
827 														updatePreview( this.getDialog() );
828 													},
829 													setup : function( type, element )
830 													{
831 														if ( type == IMAGE )
832 															this.setValue( element.getAttribute( 'align' ) );
833 													},
834 													commit : function( type, element )
835 													{
836 														if ( type == IMAGE )
837 														{
838 															if ( this.getValue() != '' || this.isChanged() )
839 																element.setAttribute( 'align', this.getValue() );
840 														}
841 														else if ( type == PREVIEW )
842 														{
843 															element.setAttribute( 'align', this.getValue() );
844 														}
845 														else if ( type == CLEANUP )
846 														{
847 															element.removeAttribute( 'align' );
848 														}
849 													}
850 												}
851 											]
852 										}
853 									]
854 								},
855 								{
856 									type : 'vbox',
857 									height : '250px',
858 									children :
859 									[
860 										{
861 											type : 'html',
862 											style : 'width:95%;',
863 											html : '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.image.preview ) +'<br>'+
864 											'<div id="ImagePreviewLoader" style="display:none"><div class="loading"> </div></div>'+
865 											'<div id="ImagePreviewBox">'+
866 											'<a href="javascript:void(0)" target="_blank" onclick="return false;" id="previewLink">'+
867 											'<img id="previewImage" src="" /></a>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. '+
868 											'Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, '+
869 											'nulla. Aenean dictum lacinia tortor. Nunc iaculis, nibh non iaculis aliquam, orci felis euismod neque, sed ornare massa mauris sed velit. Nulla pretium mi et risus. Fusce mi pede, tempor id, cursus ac, ullamcorper nec, enim. Sed tortor. Curabitur molestie. Duis velit augue, condimentum at, ultrices a, luctus ut, orci. Donec pellentesque egestas eros. Integer cursus, augue in cursus faucibus, eros pede bibendum sem, in tempus tellus justo quis ligula. Etiam eget tortor. Vestibulum rutrum, est ut placerat elementum, lectus nisl aliquam velit, tempor aliquam eros nunc nonummy metus. In eros metus, gravida a, gravida sed, lobortis id, turpis. Ut ultrices, ipsum at venenatis fringilla, sem nulla lacinia tellus, eget aliquet turpis mauris non enim. Nam turpis. Suspendisse lacinia. Curabitur ac tortor ut ipsum egestas elementum. Nunc imperdiet gravida mauris.' +
870 											'</div>'+'</div>'
871 										}
872 									]
873 								}
874 							]
875 						}
876 					]
877 				},
878 				{
879 					id : 'Link',
880 					label : editor.lang.link.title,
881 					padding : 0,
882 					elements :
883 					[
884 						{
885 							id : 'txtUrl',
886 							type : 'text',
887 							label : editor.lang.image.url,
888 							style : 'width: 100%',
889 							'default' : '',
890 							setup : function( type, element )
891 							{
892 								if ( type == LINK )
893 								{
894 									var href = element.getAttribute( '_cke_saved_href' );
895 									if ( !href )
896 										href = element.getAttribute( 'href' );
897 									this.setValue( href );
898 								}
899 							},
900 							commit : function( type, element )
901 							{
902 								if ( type == LINK )
903 									if ( this.getValue() != '' || this.isChanged() )
904 									{
905 										element.setAttribute( '_cke_saved_href', decodeURI( this.getValue() ) );
906 										element.setAttribute( 'href', 'javascript:void(0)/*' +
907 											CKEDITOR.tools.getNextNumber() + '*/' );
908
909 										if ( this.getValue() != '' || editor.config.image_removeLinkByEmptyURL == false )
910 											this.getDialog().addLink = true;
911 									}
912 							}
913 						},
914 						{
915 							type : 'button',
916 							id : 'browse',
917 							style : 'float:right',
918 							label : editor.lang.common.browseServer,
919 							onClick : function()
920 							{
921 							}
922 						},
923 						{
924 							id : 'cmbTarget',
925 							type : 'select',
926 							label : editor.lang.link.target,
927 							'default' : '',
928 							items :
929 							[
930 								[ editor.lang.link.targetNotSet , ''],
931 								[ editor.lang.link.targetNew , '_blank'],
932 								[ editor.lang.link.targetTop , '_top'],
933 								[ editor.lang.link.targetSelf , '_self'],
934 								[ editor.lang.link.targetParent , '_parent']
935 							],
936 							setup : function( type, element )
937 							{
938 								if ( type == LINK )
939 									this.setValue( element.getAttribute( 'target' ) );
940 							},
941 							commit : function( type, element )
942 							{
943 								if ( type == LINK )
944 									if ( this.getValue() != '' || this.isChanged() )
945 										element.setAttribute( 'target', this.getValue() );
946 							}
947 						}
948 					]
949 				},
950 				{
951 					id : 'Upload',
952 					label : editor.lang.image.upload,
953 					elements :
954 					[
955 						{
956 							type : 'file',
957 							id : 'upload',
958 							label : editor.lang.image.btnUpload,
959 							action : editor.config.image_uploadAction,
960 							size : 38
961 						},
962 						{
963 							type : 'fileButton',
964 							id : 'uploadButton',
965 							label : editor.lang.image.btnUpload,
966 							'for' : [ 'Upload', 'upload' ]
967 						}
968 					]
969 				},
970 				{
971 					id : 'advanced',
972 					label : editor.lang.common.advancedTab,
973 					elements :
974 					[
975 						{
976 							type : 'hbox',
977 							widths : [ '50%', '25%', '25%' ],
978 							children :
979 							[
980 								{
981 									type : 'text',
982 									id : 'linkId',
983 									label : editor.lang.common.id,
984 									setup : function( type, element )
985 									{
986 										if ( type == IMAGE )
987 											this.setValue( element.getAttribute( 'id' ) );
988 									},
989 									commit : function( type, element )
990 									{
991 										if ( type == IMAGE )
992 											if ( this.getValue() != '' || this.isChanged() )
993 												element.setAttribute( 'id', this.getValue() );
994 									}
995 								},
996 								{
997 									id : 'cmbLangDir',
998 									type : 'select',
999 									style : 'width : 100%;',
1000 									label : editor.lang.common.langDir,
1001 									'default' : '',
1002 									items :
1003 									[
1004 										[ editor.lang.common.notSet, '' ],
1005 										[ editor.lang.common.langDirLtr, 'ltr' ],
1006 										[ editor.lang.common.langDirRtl, 'rtl' ]
1007 									],
1008 									setup : function( type, element )
1009 									{
1010 										if ( type == IMAGE )
1011 											this.setValue( element.getAttribute( 'dir' ) );
1012 									},
1013 									commit : function( type, element )
1014 									{
1015 										if ( type == IMAGE )
1016 											if ( this.getValue() != '' || this.isChanged() )
1017 												element.setAttribute( 'dir', this.getValue() );
1018 									}
1019 								},
1020 								{
1021 									type : 'text',
1022 									id : 'txtLangCode',
1023 									label : editor.lang.common.langCode,
1024 									'default' : '',
1025 									setup : function( type, element )
1026 									{
1027 										if ( type == IMAGE )
1028 											this.setValue( element.getAttribute( 'lang' ) );
1029 									},
1030 									commit : function( type, element )
1031 									{
1032 										if ( type == IMAGE )
1033 											if ( this.getValue() != '' || this.isChanged() )
1034 												element.setAttribute( 'lang', this.getValue() );
1035 									}
1036 								}
1037 							]
1038 						},
1039 						{
1040 							type : 'text',
1041 							id : 'txtGenLongDescr',
1042 							label : editor.lang.common.longDescr,
1043 							setup : function( type, element )
1044 							{
1045 								if ( type == IMAGE )
1046 									this.setValue( element.getAttribute( 'longDesc' ) );
1047 							},
1048 							commit : function( type, element )
1049 							{
1050 								if ( type == IMAGE )
1051 									if ( this.getValue() != '' || this.isChanged() )
1052 										element.setAttribute( 'longDesc', this.getValue() );
1053 							}
1054 						},
1055 						{
1056 							type : 'hbox',
1057 							widths : [ '50%', '50%' ],
1058 							children :
1059 							[
1060 								{
1061 									type : 'text',
1062 									id : 'txtGenClass',
1063 									label : editor.lang.common.cssClass,
1064 									'default' : '',
1065 									setup : function( type, element )
1066 									{
1067 										if ( type == IMAGE )
1068 											this.setValue( element.getAttribute( 'class' ) );
1069 									},
1070 									commit : function( type, element )
1071 									{
1072 										if ( type == IMAGE )
1073 											if ( this.getValue() != '' || this.isChanged() )
1074 												element.setAttribute( 'class', this.getValue() );
1075 									}
1076 								},
1077 								{
1078 									type : 'text',
1079 									id : 'txtGenTitle',
1080 									label : editor.lang.common.advisoryTitle,
1081 									'default' : '',
1082 									onChange : function()
1083 									{
1084 										updatePreview( this.getDialog() );
1085 									},
1086 									setup : function( type, element )
1087 									{
1088 										if ( type == IMAGE )
1089 											this.setValue( element.getAttribute( 'title' ) );
1090 									},
1091 									commit : function( type, element )
1092 									{
1093 										if ( type == IMAGE )
1094 										{
1095 											if ( this.getValue() != '' || this.isChanged() )
1096 												element.setAttribute( 'title', this.getValue() );
1097 										}
1098 										else if ( type == PREVIEW )
1099 										{
1100 											element.setAttribute( 'title', this.getValue() );
1101 										}
1102 										else if ( type == CLEANUP )
1103 										{
1104 											element.removeAttribute( 'title' );
1105 										}
1106 									}
1107 								}
1108 							]
1109 						},
1110 						{
1111 							type : 'text',
1112 							id : 'txtdlgGenStyle',
1113 							label : editor.lang.common.cssStyle,
1114 							'default' : '',
1115 							setup : function( type, element )
1116 							{
1117 								if ( type == IMAGE )
1118 								{
1119 									var genStyle = element.getAttribute( 'style' );
1120 									if ( !genStyle && element.$.style.cssText )
1121 										genStyle = element.$.style.cssText;
1122 									this.setValue( genStyle );
1123
1124 									var height = element.$.style.height,
1125 										width = element.$.style.width,
1126 										aMatchH  = ( height ? height : '' ).match( regexGetSize ),
1127 										aMatchW  = ( width ? width : '').match( regexGetSize );
1128
1129 									this.attributesInStyle =
1130 									{
1131 										height : !!aMatchH,
1132 										width : !!aMatchW
1133 									}
1134 								}
1135 							},
1136 							commit : function( type, element )
1137 							{
1138 								if ( type == IMAGE && ( this.getValue() != '' || this.isChanged() ) )
1139 								{
1140 									element.setAttribute( 'style', this.getValue() );
1141
1142 									// Set STYLE dimensions.
1143 									var height = element.getAttribute( 'height' );
1144 										width = element.getAttribute( 'width' );
1145
1146 									if ( this.attributesInStyle && this.attributesInStyle.height )
1147 									{
1148 										if ( height && height != '' )
1149 										{
1150 											if ( height.match( regexGetSize )[2] == '%' )			// % is allowed
1151 												element.setStyle( 'height', height + '%' );
1152 											else
1153 												element.setStyle( 'height', height + 'px' );
1154 										}
1155 										else
1156 											element.removeStyle( 'height' );
1157 									}
1158 									if ( this.attributesInStyle && this.attributesInStyle.width )
1159 									{
1160 										if ( width && width != '' )
1161 											if ( width.match( regexGetSize )[2] == '%' )			// % is allowed
1162 												element.setStyle( 'width', width + '%' );
1163 											else
1164 												element.setStyle( 'width', width + 'px' );
1165 										else
1166 											element.removeStyle( 'width' );
1167 									}
1168 								}
1169 							}
1170 						}
1171 					]
1172 				}
1173 			]
1174 		};
1175 	};
1176
1177 	CKEDITOR.dialog.add( 'image', function( editor )
1178 		{
1179 			return imageDialog( editor, 'image' )
1180 		}
1181 	);
1182
1183 	CKEDITOR.dialog.add( 'imagebutton', function( editor )
1184 		{
1185 			return imageDialog( editor, 'imagebutton' )
1186 		}
1187 	);
1188 })();
1189