2 Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license
\r
8 var imageDialog = function( editor, dialogType )
\r
10 // Load image preview.
\r
15 regexGetSize = /^\s*(\d+)((px)|\%)?\s*$/i,
\r
16 regexGetSizeOrEmpty = /(^\s*(\d+)((px)|\%)?\s*$)|^$/i,
\r
17 pxLengthRegex = /^\d+px$/;
\r
19 var onSizeChange = function()
\r
21 var value = this.getValue(), // This = input element.
\r
22 dialog = this.getDialog(),
\r
23 aMatch = value.match( regexGetSize ); // Check value
\r
26 if ( aMatch[2] == '%' ) // % is allowed - > unlock ratio.
\r
27 switchLockRatio( dialog, false ); // Unlock.
\r
31 // Only if ratio is locked
\r
32 if ( dialog.lockRatio )
\r
34 var oImageOriginal = dialog.originalElement;
\r
35 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
\r
37 if ( this.id == 'txtHeight' )
\r
39 if ( value && value != '0' )
\r
40 value = Math.round( oImageOriginal.$.width * ( value / oImageOriginal.$.height ) );
\r
41 if ( !isNaN( value ) )
\r
42 dialog.setValueOf( 'info', 'txtWidth', value );
\r
44 else //this.id = txtWidth.
\r
46 if ( value && value != '0' )
\r
47 value = Math.round( oImageOriginal.$.height * ( value / oImageOriginal.$.width ) );
\r
48 if ( !isNaN( value ) )
\r
49 dialog.setValueOf( 'info', 'txtHeight', value );
\r
53 updatePreview( dialog );
\r
56 var updatePreview = function( dialog )
\r
58 //Don't load before onShow.
\r
59 if ( !dialog.originalElement || !dialog.preview )
\r
62 // Read attributes and update imagePreview;
\r
63 dialog.commitContent( PREVIEW, dialog.preview );
\r
67 // Custom commit dialog logic, where we're intended to give inline style
\r
68 // field (txtdlgGenStyle) higher priority to avoid overwriting styles contribute
\r
70 function commitContent()
\r
72 var args = arguments;
\r
73 var inlineStyleField = this.getContentElement( 'advanced', 'txtdlgGenStyle' );
\r
74 inlineStyleField && inlineStyleField.commit.apply( inlineStyleField, args );
\r
76 this.foreach( function( widget )
\r
78 if ( widget.commit && widget.id != 'txtdlgGenStyle' )
\r
79 widget.commit.apply( widget, args );
\r
83 // Avoid recursions.
\r
86 // Synchronous field values to other impacted fields is required, e.g. border
\r
87 // size change should alter inline-style text as well.
\r
88 function commitInternally( targetFields )
\r
95 var dialog = this.getDialog(),
\r
96 element = dialog.imageElement;
\r
99 // Commit this field and broadcast to target fields.
\r
100 this.commit( IMAGE, element );
\r
102 targetFields = [].concat( targetFields );
\r
103 var length = targetFields.length,
\r
105 for ( var i = 0; i < length; i++ )
\r
107 field = dialog.getContentElement.apply( dialog, targetFields[ i ].split( ':' ) );
\r
108 // May cause recursion.
\r
109 field && field.setup( IMAGE, element );
\r
116 var switchLockRatio = function( dialog, value )
\r
118 if ( !dialog.getContentElement( 'info', 'ratioLock' ) )
\r
121 var oImageOriginal = dialog.originalElement;
\r
123 // Dialog may already closed. (#5505)
\r
124 if( !oImageOriginal )
\r
127 // Check image ratio and original image ratio, but respecting user's preference.
\r
128 if ( value == 'check' )
\r
130 if ( !dialog.userlockRatio && oImageOriginal.getCustomData( 'isReady' ) == 'true' )
\r
132 var width = dialog.getValueOf( 'info', 'txtWidth' ),
\r
133 height = dialog.getValueOf( 'info', 'txtHeight' ),
\r
134 originalRatio = oImageOriginal.$.width * 1000 / oImageOriginal.$.height,
\r
135 thisRatio = width * 1000 / height;
\r
136 dialog.lockRatio = false; // Default: unlock ratio
\r
138 if ( !width && !height )
\r
139 dialog.lockRatio = true;
\r
140 else if ( !isNaN( originalRatio ) && !isNaN( thisRatio ) )
\r
142 if ( Math.round( originalRatio ) == Math.round( thisRatio ) )
\r
143 dialog.lockRatio = true;
\r
147 else if ( value != undefined )
\r
148 dialog.lockRatio = value;
\r
151 dialog.userlockRatio = 1;
\r
152 dialog.lockRatio = !dialog.lockRatio;
\r
155 var ratioButton = CKEDITOR.document.getById( btnLockSizesId );
\r
156 if ( dialog.lockRatio )
\r
157 ratioButton.removeClass( 'cke_btn_unlocked' );
\r
159 ratioButton.addClass( 'cke_btn_unlocked' );
\r
161 ratioButton.setAttribute( 'aria-checked', dialog.lockRatio );
\r
163 // Ratio button hc presentation - WHITE SQUARE / BLACK SQUARE
\r
164 if ( CKEDITOR.env.hc )
\r
166 var icon = ratioButton.getChild( 0 );
\r
167 icon.setHtml( dialog.lockRatio ? CKEDITOR.env.ie ? '\u25A0': '\u25A3' : CKEDITOR.env.ie ? '\u25A1' : '\u25A2' );
\r
170 return dialog.lockRatio;
\r
173 var resetSize = function( dialog )
\r
175 var oImageOriginal = dialog.originalElement;
\r
176 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
\r
178 var widthField = dialog.getContentElement( 'info', 'txtWidth' ),
\r
179 heightField = dialog.getContentElement( 'info', 'txtHeight' );
\r
180 widthField && widthField.setValue( oImageOriginal.$.width );
\r
181 heightField && heightField.setValue( oImageOriginal.$.height );
\r
183 updatePreview( dialog );
\r
186 var setupDimension = function( type, element )
\r
188 if ( type != IMAGE )
\r
191 function checkDimension( size, defaultValue )
\r
193 var aMatch = size.match( regexGetSize );
\r
196 if ( aMatch[2] == '%' ) // % is allowed.
\r
199 switchLockRatio( dialog, false ); // Unlock ratio
\r
203 return defaultValue;
\r
206 var dialog = this.getDialog(),
\r
208 dimension = this.id == 'txtWidth' ? 'width' : 'height',
\r
209 size = element.getAttribute( dimension );
\r
212 value = checkDimension( size, value );
\r
213 value = checkDimension( element.getStyle( dimension ), value );
\r
215 this.setValue( value );
\r
218 var previewPreloader;
\r
220 var onImgLoadEvent = function()
\r
223 var original = this.originalElement;
\r
224 original.setCustomData( 'isReady', 'true' );
\r
225 original.removeListener( 'load', onImgLoadEvent );
\r
226 original.removeListener( 'error', onImgLoadErrorEvent );
\r
227 original.removeListener( 'abort', onImgLoadErrorEvent );
\r
230 CKEDITOR.document.getById( imagePreviewLoaderId ).setStyle( 'display', 'none' );
\r
232 // New image -> new domensions
\r
233 if ( !this.dontResetSize )
\r
236 if ( this.firstLoad )
\r
237 CKEDITOR.tools.setTimeout( function(){ switchLockRatio( this, 'check' ); }, 0, this );
\r
239 this.firstLoad = false;
\r
240 this.dontResetSize = false;
\r
243 var onImgLoadErrorEvent = function()
\r
245 // Error. Image is not loaded.
\r
246 var original = this.originalElement;
\r
247 original.removeListener( 'load', onImgLoadEvent );
\r
248 original.removeListener( 'error', onImgLoadErrorEvent );
\r
249 original.removeListener( 'abort', onImgLoadErrorEvent );
\r
251 // Set Error image.
\r
252 var noimage = CKEDITOR.getUrl( editor.skinPath + 'images/noimage.png' );
\r
254 if ( this.preview )
\r
255 this.preview.setAttribute( 'src', noimage );
\r
258 CKEDITOR.document.getById( imagePreviewLoaderId ).setStyle( 'display', 'none' );
\r
259 switchLockRatio( this, false ); // Unlock.
\r
262 var numbering = function( id )
\r
264 return CKEDITOR.tools.getNextId() + '_' + id;
\r
266 btnLockSizesId = numbering( 'btnLockSizes' ),
\r
267 btnResetSizeId = numbering( 'btnResetSize' ),
\r
268 imagePreviewLoaderId = numbering( 'ImagePreviewLoader' ),
\r
269 previewLinkId = numbering( 'previewLink' ),
\r
270 previewImageId = numbering( 'previewImage' );
\r
273 title : editor.lang.image[ dialogType == 'image' ? 'title' : 'titleButton' ],
\r
276 onShow : function()
\r
278 this.imageElement = false;
\r
279 this.linkElement = false;
\r
281 // Default: create a new element.
\r
282 this.imageEditMode = false;
\r
283 this.linkEditMode = false;
\r
285 this.lockRatio = true;
\r
286 this.userlockRatio = 0;
\r
287 this.dontResetSize = false;
\r
288 this.firstLoad = true;
\r
289 this.addLink = false;
\r
291 var editor = this.getParentEditor(),
\r
292 sel = editor.getSelection(),
\r
293 element = sel && sel.getSelectedElement(),
\r
294 link = element && element.getAscendant( 'a' );
\r
297 CKEDITOR.document.getById( imagePreviewLoaderId ).setStyle( 'display', 'none' );
\r
298 // Create the preview before setup the dialog contents.
\r
299 previewPreloader = new CKEDITOR.dom.element( 'img', editor.document );
\r
300 this.preview = CKEDITOR.document.getById( previewImageId );
\r
302 // Copy of the image
\r
303 this.originalElement = editor.document.createElement( 'img' );
\r
304 this.originalElement.setAttribute( 'alt', '' );
\r
305 this.originalElement.setCustomData( 'isReady', 'false' );
\r
309 this.linkElement = link;
\r
310 this.linkEditMode = true;
\r
312 // Look for Image element.
\r
313 var linkChildren = link.getChildren();
\r
314 if ( linkChildren.count() == 1 ) // 1 child.
\r
316 var childTagName = linkChildren.getItem( 0 ).getName();
\r
317 if ( childTagName == 'img' || childTagName == 'input' )
\r
319 this.imageElement = linkChildren.getItem( 0 );
\r
320 if ( this.imageElement.getName() == 'img' )
\r
321 this.imageEditMode = 'img';
\r
322 else if ( this.imageElement.getName() == 'input' )
\r
323 this.imageEditMode = 'input';
\r
326 // Fill out all fields.
\r
327 if ( dialogType == 'image' )
\r
328 this.setupContent( LINK, link );
\r
331 if ( element && element.getName() == 'img' && !element.data( 'cke-realelement' )
\r
332 || element && element.getName() == 'input' && element.getAttribute( 'type' ) == 'image' )
\r
334 this.imageEditMode = element.getName();
\r
335 this.imageElement = element;
\r
338 if ( this.imageEditMode )
\r
340 // Use the original element as a buffer from since we don't want
\r
341 // temporary changes to be committed, e.g. if the dialog is canceled.
\r
342 this.cleanImageElement = this.imageElement;
\r
343 this.imageElement = this.cleanImageElement.clone( true, true );
\r
345 // Fill out all fields.
\r
346 this.setupContent( IMAGE, this.imageElement );
\r
349 this.imageElement = editor.document.createElement( 'img' );
\r
351 // Refresh LockRatio button
\r
352 switchLockRatio ( this, true );
\r
354 // Dont show preview if no URL given.
\r
355 if ( !CKEDITOR.tools.trim( this.getValueOf( 'info', 'txtUrl' ) ) )
\r
357 this.preview.removeAttribute( 'src' );
\r
358 this.preview.setStyle( 'display', 'none' );
\r
363 // Edit existing Image.
\r
364 if ( this.imageEditMode )
\r
366 var imgTagName = this.imageEditMode;
\r
368 // Image dialog and Input element.
\r
369 if ( dialogType == 'image' && imgTagName == 'input' && confirm( editor.lang.image.button2Img ) )
\r
371 // Replace INPUT-> IMG
\r
372 imgTagName = 'img';
\r
373 this.imageElement = editor.document.createElement( 'img' );
\r
374 this.imageElement.setAttribute( 'alt', '' );
\r
375 editor.insertElement( this.imageElement );
\r
377 // ImageButton dialog and Image element.
\r
378 else if ( dialogType != 'image' && imgTagName == 'img' && confirm( editor.lang.image.img2Button ))
\r
380 // Replace IMG -> INPUT
\r
381 imgTagName = 'input';
\r
382 this.imageElement = editor.document.createElement( 'input' );
\r
383 this.imageElement.setAttributes(
\r
389 editor.insertElement( this.imageElement );
\r
393 // Restore the original element before all commits.
\r
394 this.imageElement = this.cleanImageElement;
\r
395 delete this.cleanImageElement;
\r
398 else // Create a new image.
\r
400 // Image dialog -> create IMG element.
\r
401 if ( dialogType == 'image' )
\r
402 this.imageElement = editor.document.createElement( 'img' );
\r
405 this.imageElement = editor.document.createElement( 'input' );
\r
406 this.imageElement.setAttribute ( 'type' ,'image' );
\r
408 this.imageElement.setAttribute( 'alt', '' );
\r
411 // Create a new link.
\r
412 if ( !this.linkEditMode )
\r
413 this.linkElement = editor.document.createElement( 'a' );
\r
416 this.commitContent( IMAGE, this.imageElement );
\r
417 this.commitContent( LINK, this.linkElement );
\r
419 // Remove empty style attribute.
\r
420 if ( !this.imageElement.getAttribute( 'style' ) )
\r
421 this.imageElement.removeAttribute( 'style' );
\r
423 // Insert a new Image.
\r
424 if ( !this.imageEditMode )
\r
426 if ( this.addLink )
\r
428 //Insert a new Link.
\r
429 if ( !this.linkEditMode )
\r
431 editor.insertElement( this.linkElement );
\r
432 this.linkElement.append( this.imageElement, false );
\r
434 else //Link already exists, image not.
\r
435 editor.insertElement( this.imageElement );
\r
438 editor.insertElement( this.imageElement );
\r
440 else // Image already exists.
\r
442 //Add a new link element.
\r
443 if ( !this.linkEditMode && this.addLink )
\r
445 editor.insertElement( this.linkElement );
\r
446 this.imageElement.appendTo( this.linkElement );
\r
448 //Remove Link, Image exists.
\r
449 else if ( this.linkEditMode && !this.addLink )
\r
451 editor.getSelection().selectElement( this.linkElement );
\r
452 editor.insertElement( this.imageElement );
\r
456 onLoad : function()
\r
458 if ( dialogType != 'image' )
\r
459 this.hidePage( 'Link' ); //Hide Link tab.
\r
460 var doc = this._.element.getDocument();
\r
462 if ( this.getContentElement( 'info', 'ratioLock' ) )
\r
464 this.addFocusable( doc.getById( btnResetSizeId ), 5 );
\r
465 this.addFocusable( doc.getById( btnLockSizesId ), 5 );
\r
468 this.commitContent = commitContent;
\r
470 onHide : function()
\r
472 if ( this.preview )
\r
473 this.commitContent( CLEANUP, this.preview );
\r
475 if ( this.originalElement )
\r
477 this.originalElement.removeListener( 'load', onImgLoadEvent );
\r
478 this.originalElement.removeListener( 'error', onImgLoadErrorEvent );
\r
479 this.originalElement.removeListener( 'abort', onImgLoadErrorEvent );
\r
480 this.originalElement.remove();
\r
481 this.originalElement = false; // Dialog is closed.
\r
484 delete this.imageElement;
\r
489 label : editor.lang.image.infoTab,
\r
500 widths : [ '280px', '110px' ],
\r
507 label : editor.lang.common.url,
\r
509 onChange : function()
\r
511 var dialog = this.getDialog(),
\r
512 newUrl = this.getValue();
\r
514 //Update original image
\r
515 if ( newUrl.length > 0 ) //Prevent from load before onShow
\r
517 dialog = this.getDialog();
\r
518 var original = dialog.originalElement;
\r
520 dialog.preview.removeStyle( 'display' );
\r
522 original.setCustomData( 'isReady', 'false' );
\r
524 var loader = CKEDITOR.document.getById( imagePreviewLoaderId );
\r
526 loader.setStyle( 'display', '' );
\r
528 original.on( 'load', onImgLoadEvent, dialog );
\r
529 original.on( 'error', onImgLoadErrorEvent, dialog );
\r
530 original.on( 'abort', onImgLoadErrorEvent, dialog );
\r
531 original.setAttribute( 'src', newUrl );
\r
533 // Query the preloader to figure out the url impacted by based href.
\r
534 previewPreloader.setAttribute( 'src', newUrl );
\r
535 dialog.preview.setAttribute( 'src', previewPreloader.$.src );
\r
536 updatePreview( dialog );
\r
538 // Dont show preview if no URL given.
\r
539 else if ( dialog.preview )
\r
541 dialog.preview.removeAttribute( 'src' );
\r
542 dialog.preview.setStyle( 'display', 'none' );
\r
545 setup : function( type, element )
\r
547 if ( type == IMAGE )
\r
549 var url = element.data( 'cke-saved-src' ) || element.getAttribute( 'src' );
\r
552 this.getDialog().dontResetSize = true;
\r
554 field.setValue( url ); // And call this.onChange()
\r
555 // Manually set the initial value.(#4191)
\r
556 field.setInitValue();
\r
559 commit : function( type, element )
\r
561 if ( type == IMAGE && ( this.getValue() || this.isChanged() ) )
\r
563 element.data( 'cke-saved-src', this.getValue() );
\r
564 element.setAttribute( 'src', this.getValue() );
\r
566 else if ( type == CLEANUP )
\r
568 element.setAttribute( 'src', '' ); // If removeAttribute doesn't work.
\r
569 element.removeAttribute( 'src' );
\r
572 validate : CKEDITOR.dialog.validate.notEmpty( editor.lang.image.urlMissing )
\r
577 // v-align with the 'txtUrl' field.
\r
578 // TODO: We need something better than a fixed size here.
\r
579 style : 'display:inline-block;margin-top:10px;',
\r
581 label : editor.lang.common.browseServer,
\r
583 filebrowser : 'info:txtUrl'
\r
592 label : editor.lang.image.alt,
\r
595 onChange : function()
\r
597 updatePreview( this.getDialog() );
\r
599 setup : function( type, element )
\r
601 if ( type == IMAGE )
\r
602 this.setValue( element.getAttribute( 'alt' ) );
\r
604 commit : function( type, element )
\r
606 if ( type == IMAGE )
\r
608 if ( this.getValue() || this.isChanged() )
\r
609 element.setAttribute( 'alt', this.getValue() );
\r
611 else if ( type == PREVIEW )
\r
613 element.setAttribute( 'alt', this.getValue() );
\r
615 else if ( type == CLEANUP )
\r
617 element.removeAttribute( 'alt' );
\r
632 widths : [ '50%', '50%' ],
\r
644 label : editor.lang.common.width,
\r
645 onKeyUp : onSizeChange,
\r
646 onChange : function()
\r
648 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
650 validate : function()
\r
652 var aMatch = this.getValue().match( regexGetSizeOrEmpty ),
\r
653 isValid = !!( aMatch && parseInt( aMatch[1], 10 ) !== 0 );
\r
655 alert( editor.lang.common.invalidWidth );
\r
658 setup : setupDimension,
\r
659 commit : function( type, element, internalCommit )
\r
661 var value = this.getValue();
\r
662 if ( type == IMAGE )
\r
665 element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );
\r
667 element.removeStyle( 'width' );
\r
669 !internalCommit && element.removeAttribute( 'width' );
\r
671 else if ( type == PREVIEW )
\r
673 var aMatch = value.match( regexGetSize );
\r
676 var oImageOriginal = this.getDialog().originalElement;
\r
677 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
\r
678 element.setStyle( 'width', oImageOriginal.$.width + 'px');
\r
681 element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );
\r
683 else if ( type == CLEANUP )
\r
685 element.removeAttribute( 'width' );
\r
686 element.removeStyle( 'width' );
\r
694 label : editor.lang.common.height,
\r
695 onKeyUp : onSizeChange,
\r
696 onChange : function()
\r
698 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
700 validate : function()
\r
702 var aMatch = this.getValue().match( regexGetSizeOrEmpty ),
\r
703 isValid = !!( aMatch && parseInt( aMatch[1], 10 ) !== 0 );
\r
705 alert( editor.lang.common.invalidHeight );
\r
708 setup : setupDimension,
\r
709 commit : function( type, element, internalCommit )
\r
711 var value = this.getValue();
\r
712 if ( type == IMAGE )
\r
715 element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) );
\r
717 element.removeStyle( 'height' );
\r
719 !internalCommit && element.removeAttribute( 'height' );
\r
721 else if ( type == PREVIEW )
\r
723 var aMatch = value.match( regexGetSize );
\r
726 var oImageOriginal = this.getDialog().originalElement;
\r
727 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )
\r
728 element.setStyle( 'height', oImageOriginal.$.height + 'px' );
\r
731 element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) );
\r
733 else if ( type == CLEANUP )
\r
735 element.removeAttribute( 'height' );
\r
736 element.removeStyle( 'height' );
\r
745 style : 'margin-top:30px;width:40px;height:40px;',
\r
746 onLoad : function()
\r
748 // Activate Reset button
\r
749 var resetButton = CKEDITOR.document.getById( btnResetSizeId ),
\r
750 ratioButton = CKEDITOR.document.getById( btnLockSizesId );
\r
753 resetButton.on( 'click', function( evt )
\r
756 evt.data && evt.data.preventDefault();
\r
757 }, this.getDialog() );
\r
758 resetButton.on( 'mouseover', function()
\r
760 this.addClass( 'cke_btn_over' );
\r
762 resetButton.on( 'mouseout', function()
\r
764 this.removeClass( 'cke_btn_over' );
\r
767 // Activate (Un)LockRatio button
\r
770 ratioButton.on( 'click', function(evt)
\r
772 var locked = switchLockRatio( this ),
\r
773 oImageOriginal = this.originalElement,
\r
774 width = this.getValueOf( 'info', 'txtWidth' );
\r
776 if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' && width )
\r
778 var height = oImageOriginal.$.height / oImageOriginal.$.width * width;
\r
779 if ( !isNaN( height ) )
\r
781 this.setValueOf( 'info', 'txtHeight', Math.round( height ) );
\r
782 updatePreview( this );
\r
785 evt.data && evt.data.preventDefault();
\r
786 }, this.getDialog() );
\r
787 ratioButton.on( 'mouseover', function()
\r
789 this.addClass( 'cke_btn_over' );
\r
791 ratioButton.on( 'mouseout', function()
\r
793 this.removeClass( 'cke_btn_over' );
\r
798 '<a href="javascript:void(0)" tabindex="-1" title="' + editor.lang.image.lockRatio +
\r
799 '" class="cke_btn_locked" id="' + btnLockSizesId + '" role="checkbox"><span class="cke_icon"></span><span class="cke_label">' + editor.lang.image.lockRatio + '</span></a>' +
\r
800 '<a href="javascript:void(0)" tabindex="-1" title="' + editor.lang.image.resetSize +
\r
801 '" class="cke_btn_reset" id="' + btnResetSizeId + '" role="button"><span class="cke_label">' + editor.lang.image.resetSize + '</span></a>'+
\r
815 label : editor.lang.image.border,
\r
817 onKeyUp : function()
\r
819 updatePreview( this.getDialog() );
\r
821 onChange : function()
\r
823 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
825 validate : CKEDITOR.dialog.validate.integer( editor.lang.image.validateBorder ),
\r
826 setup : function( type, element )
\r
828 if ( type == IMAGE )
\r
831 borderStyle = element.getStyle( 'border-width' );
\r
832 borderStyle = borderStyle && borderStyle.match( /^(\d+px)(?: \1 \1 \1)?$/ );
\r
833 value = borderStyle && parseInt( borderStyle[ 1 ], 10 );
\r
834 isNaN ( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'border' ) );
\r
835 this.setValue( value );
\r
838 commit : function( type, element, internalCommit )
\r
840 var value = parseInt( this.getValue(), 10 );
\r
841 if ( type == IMAGE || type == PREVIEW )
\r
843 if ( !isNaN( value ) )
\r
845 element.setStyle( 'border-width', CKEDITOR.tools.cssLength( value ) );
\r
846 element.setStyle( 'border-style', 'solid' );
\r
848 else if ( !value && this.isChanged() )
\r
850 element.removeStyle( 'border-width' );
\r
851 element.removeStyle( 'border-style' );
\r
852 element.removeStyle( 'border-color' );
\r
855 if ( !internalCommit && type == IMAGE )
\r
856 element.removeAttribute( 'border' );
\r
858 else if ( type == CLEANUP )
\r
860 element.removeAttribute( 'border' );
\r
861 element.removeStyle( 'border-width' );
\r
862 element.removeStyle( 'border-style' );
\r
863 element.removeStyle( 'border-color' );
\r
871 label : editor.lang.image.hSpace,
\r
873 onKeyUp : function()
\r
875 updatePreview( this.getDialog() );
\r
877 onChange : function()
\r
879 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
881 validate : CKEDITOR.dialog.validate.integer( editor.lang.image.validateHSpace ),
\r
882 setup : function( type, element )
\r
884 if ( type == IMAGE )
\r
889 marginLeftStyle = element.getStyle( 'margin-left' ),
\r
890 marginRightStyle = element.getStyle( 'margin-right' );
\r
892 marginLeftStyle = marginLeftStyle && marginLeftStyle.match( pxLengthRegex );
\r
893 marginRightStyle = marginRightStyle && marginRightStyle.match( pxLengthRegex );
\r
894 marginLeftPx = parseInt( marginLeftStyle, 10 );
\r
895 marginRightPx = parseInt( marginRightStyle, 10 );
\r
897 value = ( marginLeftPx == marginRightPx ) && marginLeftPx;
\r
898 isNaN( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'hspace' ) );
\r
900 this.setValue( value );
\r
903 commit : function( type, element, internalCommit )
\r
905 var value = parseInt( this.getValue(), 10 );
\r
906 if ( type == IMAGE || type == PREVIEW )
\r
908 if ( !isNaN( value ) )
\r
910 element.setStyle( 'margin-left', CKEDITOR.tools.cssLength( value ) );
\r
911 element.setStyle( 'margin-right', CKEDITOR.tools.cssLength( value ) );
\r
913 else if ( !value && this.isChanged( ) )
\r
915 element.removeStyle( 'margin-left' );
\r
916 element.removeStyle( 'margin-right' );
\r
919 if ( !internalCommit && type == IMAGE )
\r
920 element.removeAttribute( 'hspace' );
\r
922 else if ( type == CLEANUP )
\r
924 element.removeAttribute( 'hspace' );
\r
925 element.removeStyle( 'margin-left' );
\r
926 element.removeStyle( 'margin-right' );
\r
934 label : editor.lang.image.vSpace,
\r
936 onKeyUp : function()
\r
938 updatePreview( this.getDialog() );
\r
940 onChange : function()
\r
942 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
944 validate : CKEDITOR.dialog.validate.integer( editor.lang.image.validateVSpace ),
\r
945 setup : function( type, element )
\r
947 if ( type == IMAGE )
\r
952 marginTopStyle = element.getStyle( 'margin-top' ),
\r
953 marginBottomStyle = element.getStyle( 'margin-bottom' );
\r
955 marginTopStyle = marginTopStyle && marginTopStyle.match( pxLengthRegex );
\r
956 marginBottomStyle = marginBottomStyle && marginBottomStyle.match( pxLengthRegex );
\r
957 marginTopPx = parseInt( marginTopStyle, 10 );
\r
958 marginBottomPx = parseInt( marginBottomStyle, 10 );
\r
960 value = ( marginTopPx == marginBottomPx ) && marginTopPx;
\r
961 isNaN ( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'vspace' ) );
\r
962 this.setValue( value );
\r
965 commit : function( type, element, internalCommit )
\r
967 var value = parseInt( this.getValue(), 10 );
\r
968 if ( type == IMAGE || type == PREVIEW )
\r
970 if ( !isNaN( value ) )
\r
972 element.setStyle( 'margin-top', CKEDITOR.tools.cssLength( value ) );
\r
973 element.setStyle( 'margin-bottom', CKEDITOR.tools.cssLength( value ) );
\r
975 else if ( !value && this.isChanged( ) )
\r
977 element.removeStyle( 'margin-top' );
\r
978 element.removeStyle( 'margin-bottom' );
\r
981 if ( !internalCommit && type == IMAGE )
\r
982 element.removeAttribute( 'vspace' );
\r
984 else if ( type == CLEANUP )
\r
986 element.removeAttribute( 'vspace' );
\r
987 element.removeStyle( 'margin-top' );
\r
988 element.removeStyle( 'margin-bottom' );
\r
995 widths : [ '35%','65%' ],
\r
996 style : 'width:90px',
\r
997 label : editor.lang.common.align,
\r
1001 [ editor.lang.common.notSet , ''],
\r
1002 [ editor.lang.common.alignLeft , 'left'],
\r
1003 [ editor.lang.common.alignRight , 'right']
\r
1004 // Backward compatible with v2 on setup when specified as attribute value,
\r
1005 // while these values are no more available as select options.
\r
1006 // [ editor.lang.image.alignAbsBottom , 'absBottom'],
\r
1007 // [ editor.lang.image.alignAbsMiddle , 'absMiddle'],
\r
1008 // [ editor.lang.image.alignBaseline , 'baseline'],
\r
1009 // [ editor.lang.image.alignTextTop , 'text-top'],
\r
1010 // [ editor.lang.image.alignBottom , 'bottom'],
\r
1011 // [ editor.lang.image.alignMiddle , 'middle'],
\r
1012 // [ editor.lang.image.alignTop , 'top']
\r
1014 onChange : function()
\r
1016 updatePreview( this.getDialog() );
\r
1017 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
1019 setup : function( type, element )
\r
1021 if ( type == IMAGE )
\r
1023 var value = element.getStyle( 'float' );
\r
1026 // Ignore those unrelated values.
\r
1032 !value && ( value = ( element.getAttribute( 'align' ) || '' ).toLowerCase() );
\r
1033 this.setValue( value );
\r
1036 commit : function( type, element, internalCommit )
\r
1038 var value = this.getValue();
\r
1039 if ( type == IMAGE || type == PREVIEW )
\r
1042 element.setStyle( 'float', value );
\r
1044 element.removeStyle( 'float' );
\r
1046 if ( !internalCommit && type == IMAGE )
\r
1048 value = ( element.getAttribute( 'align' ) || '' ).toLowerCase();
\r
1051 // we should remove it only if it matches "left" or "right",
\r
1052 // otherwise leave it intact.
\r
1055 element.removeAttribute( 'align' );
\r
1059 else if ( type == CLEANUP )
\r
1060 element.removeStyle( 'float' );
\r
1075 id : 'htmlPreview',
\r
1076 style : 'width:95%;',
\r
1077 html : '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.common.preview ) +'<br>'+
\r
1078 '<div id="' + imagePreviewLoaderId + '" class="ImagePreviewLoader" style="display:none"><div class="loading"> </div></div>'+
\r
1079 '<div class="ImagePreviewBox"><table><tr><td>'+
\r
1080 '<a href="javascript:void(0)" target="_blank" onclick="return false;" id="' + previewLinkId + '">'+
\r
1081 '<img id="' + previewImageId + '" alt="" /></a>' +
\r
1082 ( editor.config.image_previewText ||
\r
1083 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. '+
\r
1084 'Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, '+
\r
1085 '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.' ) +
\r
1086 '</td></tr></table></div></div>'
\r
1096 label : editor.lang.link.title,
\r
1103 label : editor.lang.common.url,
\r
1104 style : 'width: 100%',
\r
1106 setup : function( type, element )
\r
1108 if ( type == LINK )
\r
1110 var href = element.data( 'cke-saved-href' );
\r
1112 href = element.getAttribute( 'href' );
\r
1113 this.setValue( href );
\r
1116 commit : function( type, element )
\r
1118 if ( type == LINK )
\r
1120 if ( this.getValue() || this.isChanged() )
\r
1122 var url = decodeURI( this.getValue() );
\r
1123 element.data( 'cke-saved-href', url );
\r
1124 element.setAttribute( 'href', url );
\r
1126 if ( this.getValue() || !editor.config.image_removeLinkByEmptyURL )
\r
1127 this.getDialog().addLink = true;
\r
1137 action : 'Browse',
\r
1138 target: 'Link:txtUrl',
\r
1139 url: editor.config.filebrowserImageBrowseLinkUrl
\r
1141 style : 'float:right',
\r
1143 label : editor.lang.common.browseServer
\r
1148 label : editor.lang.common.target,
\r
1152 [ editor.lang.common.notSet , ''],
\r
1153 [ editor.lang.common.targetNew , '_blank'],
\r
1154 [ editor.lang.common.targetTop , '_top'],
\r
1155 [ editor.lang.common.targetSelf , '_self'],
\r
1156 [ editor.lang.common.targetParent , '_parent']
\r
1158 setup : function( type, element )
\r
1160 if ( type == LINK )
\r
1161 this.setValue( element.getAttribute( 'target' ) || '' );
\r
1163 commit : function( type, element )
\r
1165 if ( type == LINK )
\r
1167 if ( this.getValue() || this.isChanged() )
\r
1168 element.setAttribute( 'target', this.getValue() );
\r
1177 filebrowser : 'uploadButton',
\r
1178 label : editor.lang.image.upload,
\r
1184 label : editor.lang.image.btnUpload,
\r
1185 style: 'height:40px',
\r
1189 type : 'fileButton',
\r
1190 id : 'uploadButton',
\r
1191 filebrowser : 'info:txtUrl',
\r
1192 label : editor.lang.image.btnUpload,
\r
1193 'for' : [ 'Upload', 'upload' ]
\r
1199 label : editor.lang.common.advancedTab,
\r
1204 widths : [ '50%', '25%', '25%' ],
\r
1210 label : editor.lang.common.id,
\r
1211 setup : function( type, element )
\r
1213 if ( type == IMAGE )
\r
1214 this.setValue( element.getAttribute( 'id' ) );
\r
1216 commit : function( type, element )
\r
1218 if ( type == IMAGE )
\r
1220 if ( this.getValue() || this.isChanged() )
\r
1221 element.setAttribute( 'id', this.getValue() );
\r
1226 id : 'cmbLangDir',
\r
1228 style : 'width : 100px;',
\r
1229 label : editor.lang.common.langDir,
\r
1233 [ editor.lang.common.notSet, '' ],
\r
1234 [ editor.lang.common.langDirLtr, 'ltr' ],
\r
1235 [ editor.lang.common.langDirRtl, 'rtl' ]
\r
1237 setup : function( type, element )
\r
1239 if ( type == IMAGE )
\r
1240 this.setValue( element.getAttribute( 'dir' ) );
\r
1242 commit : function( type, element )
\r
1244 if ( type == IMAGE )
\r
1246 if ( this.getValue() || this.isChanged() )
\r
1247 element.setAttribute( 'dir', this.getValue() );
\r
1253 id : 'txtLangCode',
\r
1254 label : editor.lang.common.langCode,
\r
1256 setup : function( type, element )
\r
1258 if ( type == IMAGE )
\r
1259 this.setValue( element.getAttribute( 'lang' ) );
\r
1261 commit : function( type, element )
\r
1263 if ( type == IMAGE )
\r
1265 if ( this.getValue() || this.isChanged() )
\r
1266 element.setAttribute( 'lang', this.getValue() );
\r
1274 id : 'txtGenLongDescr',
\r
1275 label : editor.lang.common.longDescr,
\r
1276 setup : function( type, element )
\r
1278 if ( type == IMAGE )
\r
1279 this.setValue( element.getAttribute( 'longDesc' ) );
\r
1281 commit : function( type, element )
\r
1283 if ( type == IMAGE )
\r
1285 if ( this.getValue() || this.isChanged() )
\r
1286 element.setAttribute( 'longDesc', this.getValue() );
\r
1292 widths : [ '50%', '50%' ],
\r
1297 id : 'txtGenClass',
\r
1298 label : editor.lang.common.cssClass,
\r
1300 setup : function( type, element )
\r
1302 if ( type == IMAGE )
\r
1303 this.setValue( element.getAttribute( 'class' ) );
\r
1305 commit : function( type, element )
\r
1307 if ( type == IMAGE )
\r
1309 if ( this.getValue() || this.isChanged() )
\r
1310 element.setAttribute( 'class', this.getValue() );
\r
1316 id : 'txtGenTitle',
\r
1317 label : editor.lang.common.advisoryTitle,
\r
1319 onChange : function()
\r
1321 updatePreview( this.getDialog() );
\r
1323 setup : function( type, element )
\r
1325 if ( type == IMAGE )
\r
1326 this.setValue( element.getAttribute( 'title' ) );
\r
1328 commit : function( type, element )
\r
1330 if ( type == IMAGE )
\r
1332 if ( this.getValue() || this.isChanged() )
\r
1333 element.setAttribute( 'title', this.getValue() );
\r
1335 else if ( type == PREVIEW )
\r
1337 element.setAttribute( 'title', this.getValue() );
\r
1339 else if ( type == CLEANUP )
\r
1341 element.removeAttribute( 'title' );
\r
1349 id : 'txtdlgGenStyle',
\r
1350 label : editor.lang.common.cssStyle,
\r
1351 validate : CKEDITOR.dialog.validate.inlineStyle( editor.lang.common.invalidInlineStyle ),
\r
1353 setup : function( type, element )
\r
1355 if ( type == IMAGE )
\r
1357 var genStyle = element.getAttribute( 'style' );
\r
1358 if ( !genStyle && element.$.style.cssText )
\r
1359 genStyle = element.$.style.cssText;
\r
1360 this.setValue( genStyle );
\r
1362 var height = element.$.style.height,
\r
1363 width = element.$.style.width,
\r
1364 aMatchH = ( height ? height : '' ).match( regexGetSize ),
\r
1365 aMatchW = ( width ? width : '').match( regexGetSize );
\r
1367 this.attributesInStyle =
\r
1369 height : !!aMatchH,
\r
1374 onChange : function ()
\r
1376 commitInternally.call( this,
\r
1377 [ 'info:cmbFloat', 'info:cmbAlign',
\r
1378 'info:txtVSpace', 'info:txtHSpace',
\r
1380 'info:txtWidth', 'info:txtHeight' ] );
\r
1381 updatePreview( this );
\r
1383 commit : function( type, element )
\r
1385 if ( type == IMAGE && ( this.getValue() || this.isChanged() ) )
\r
1387 element.setAttribute( 'style', this.getValue() );
\r
1397 CKEDITOR.dialog.add( 'image', function( editor )
\r
1399 return imageDialog( editor, 'image' );
\r
1402 CKEDITOR.dialog.add( 'imagebutton', function( editor )
\r
1404 return imageDialog( editor, 'imagebutton' );
\r