2 Copyright (c) 2003-2013, 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
849 element.removeStyle( 'border' );
\r
851 if ( !internalCommit && type == IMAGE )
\r
852 element.removeAttribute( 'border' );
\r
854 else if ( type == CLEANUP )
\r
856 element.removeAttribute( 'border' );
\r
857 element.removeStyle( 'border-width' );
\r
858 element.removeStyle( 'border-style' );
\r
859 element.removeStyle( 'border-color' );
\r
867 label : editor.lang.image.hSpace,
\r
869 onKeyUp : function()
\r
871 updatePreview( this.getDialog() );
\r
873 onChange : function()
\r
875 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
877 validate : CKEDITOR.dialog.validate.integer( editor.lang.image.validateHSpace ),
\r
878 setup : function( type, element )
\r
880 if ( type == IMAGE )
\r
885 marginLeftStyle = element.getStyle( 'margin-left' ),
\r
886 marginRightStyle = element.getStyle( 'margin-right' );
\r
888 marginLeftStyle = marginLeftStyle && marginLeftStyle.match( pxLengthRegex );
\r
889 marginRightStyle = marginRightStyle && marginRightStyle.match( pxLengthRegex );
\r
890 marginLeftPx = parseInt( marginLeftStyle, 10 );
\r
891 marginRightPx = parseInt( marginRightStyle, 10 );
\r
893 value = ( marginLeftPx == marginRightPx ) && marginLeftPx;
\r
894 isNaN( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'hspace' ) );
\r
896 this.setValue( value );
\r
899 commit : function( type, element, internalCommit )
\r
901 var value = parseInt( this.getValue(), 10 );
\r
902 if ( type == IMAGE || type == PREVIEW )
\r
904 if ( !isNaN( value ) )
\r
906 element.setStyle( 'margin-left', CKEDITOR.tools.cssLength( value ) );
\r
907 element.setStyle( 'margin-right', CKEDITOR.tools.cssLength( value ) );
\r
909 else if ( !value && this.isChanged( ) )
\r
911 element.removeStyle( 'margin-left' );
\r
912 element.removeStyle( 'margin-right' );
\r
915 if ( !internalCommit && type == IMAGE )
\r
916 element.removeAttribute( 'hspace' );
\r
918 else if ( type == CLEANUP )
\r
920 element.removeAttribute( 'hspace' );
\r
921 element.removeStyle( 'margin-left' );
\r
922 element.removeStyle( 'margin-right' );
\r
930 label : editor.lang.image.vSpace,
\r
932 onKeyUp : function()
\r
934 updatePreview( this.getDialog() );
\r
936 onChange : function()
\r
938 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
940 validate : CKEDITOR.dialog.validate.integer( editor.lang.image.validateVSpace ),
\r
941 setup : function( type, element )
\r
943 if ( type == IMAGE )
\r
948 marginTopStyle = element.getStyle( 'margin-top' ),
\r
949 marginBottomStyle = element.getStyle( 'margin-bottom' );
\r
951 marginTopStyle = marginTopStyle && marginTopStyle.match( pxLengthRegex );
\r
952 marginBottomStyle = marginBottomStyle && marginBottomStyle.match( pxLengthRegex );
\r
953 marginTopPx = parseInt( marginTopStyle, 10 );
\r
954 marginBottomPx = parseInt( marginBottomStyle, 10 );
\r
956 value = ( marginTopPx == marginBottomPx ) && marginTopPx;
\r
957 isNaN ( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'vspace' ) );
\r
958 this.setValue( value );
\r
961 commit : function( type, element, internalCommit )
\r
963 var value = parseInt( this.getValue(), 10 );
\r
964 if ( type == IMAGE || type == PREVIEW )
\r
966 if ( !isNaN( value ) )
\r
968 element.setStyle( 'margin-top', CKEDITOR.tools.cssLength( value ) );
\r
969 element.setStyle( 'margin-bottom', CKEDITOR.tools.cssLength( value ) );
\r
971 else if ( !value && this.isChanged( ) )
\r
973 element.removeStyle( 'margin-top' );
\r
974 element.removeStyle( 'margin-bottom' );
\r
977 if ( !internalCommit && type == IMAGE )
\r
978 element.removeAttribute( 'vspace' );
\r
980 else if ( type == CLEANUP )
\r
982 element.removeAttribute( 'vspace' );
\r
983 element.removeStyle( 'margin-top' );
\r
984 element.removeStyle( 'margin-bottom' );
\r
991 widths : [ '35%','65%' ],
\r
992 style : 'width:90px',
\r
993 label : editor.lang.common.align,
\r
997 [ editor.lang.common.notSet , ''],
\r
998 [ editor.lang.common.alignLeft , 'left'],
\r
999 [ editor.lang.common.alignRight , 'right']
\r
1000 // Backward compatible with v2 on setup when specified as attribute value,
\r
1001 // while these values are no more available as select options.
\r
1002 // [ editor.lang.image.alignAbsBottom , 'absBottom'],
\r
1003 // [ editor.lang.image.alignAbsMiddle , 'absMiddle'],
\r
1004 // [ editor.lang.image.alignBaseline , 'baseline'],
\r
1005 // [ editor.lang.image.alignTextTop , 'text-top'],
\r
1006 // [ editor.lang.image.alignBottom , 'bottom'],
\r
1007 // [ editor.lang.image.alignMiddle , 'middle'],
\r
1008 // [ editor.lang.image.alignTop , 'top']
\r
1010 onChange : function()
\r
1012 updatePreview( this.getDialog() );
\r
1013 commitInternally.call( this, 'advanced:txtdlgGenStyle' );
\r
1015 setup : function( type, element )
\r
1017 if ( type == IMAGE )
\r
1019 var value = element.getStyle( 'float' );
\r
1022 // Ignore those unrelated values.
\r
1028 !value && ( value = ( element.getAttribute( 'align' ) || '' ).toLowerCase() );
\r
1029 this.setValue( value );
\r
1032 commit : function( type, element, internalCommit )
\r
1034 var value = this.getValue();
\r
1035 if ( type == IMAGE || type == PREVIEW )
\r
1038 element.setStyle( 'float', value );
\r
1040 element.removeStyle( 'float' );
\r
1042 if ( !internalCommit && type == IMAGE )
\r
1044 value = ( element.getAttribute( 'align' ) || '' ).toLowerCase();
\r
1047 // we should remove it only if it matches "left" or "right",
\r
1048 // otherwise leave it intact.
\r
1051 element.removeAttribute( 'align' );
\r
1055 else if ( type == CLEANUP )
\r
1056 element.removeStyle( 'float' );
\r
1071 id : 'htmlPreview',
\r
1072 style : 'width:95%;',
\r
1073 html : '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.common.preview ) +'<br>'+
\r
1074 '<div id="' + imagePreviewLoaderId + '" class="ImagePreviewLoader" style="display:none"><div class="loading"> </div></div>'+
\r
1075 '<div class="ImagePreviewBox"><table><tr><td>'+
\r
1076 '<a href="javascript:void(0)" target="_blank" onclick="return false;" id="' + previewLinkId + '">'+
\r
1077 '<img id="' + previewImageId + '" alt="" /></a>' +
\r
1078 ( editor.config.image_previewText ||
\r
1079 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. '+
\r
1080 'Maecenas feugiat consequat diam. Maecenas metus. Vivamus diam purus, cursus a, commodo non, facilisis vitae, '+
\r
1081 '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
1082 '</td></tr></table></div></div>'
\r
1092 label : editor.lang.link.title,
\r
1099 label : editor.lang.common.url,
\r
1100 style : 'width: 100%',
\r
1102 setup : function( type, element )
\r
1104 if ( type == LINK )
\r
1106 var href = element.data( 'cke-saved-href' );
\r
1108 href = element.getAttribute( 'href' );
\r
1109 this.setValue( href );
\r
1112 commit : function( type, element )
\r
1114 if ( type == LINK )
\r
1116 if ( this.getValue() || this.isChanged() )
\r
1118 var url = decodeURI( this.getValue() );
\r
1119 element.data( 'cke-saved-href', url );
\r
1120 element.setAttribute( 'href', url );
\r
1122 if ( this.getValue() || !editor.config.image_removeLinkByEmptyURL )
\r
1123 this.getDialog().addLink = true;
\r
1133 action : 'Browse',
\r
1134 target: 'Link:txtUrl',
\r
1135 url: editor.config.filebrowserImageBrowseLinkUrl
\r
1137 style : 'float:right',
\r
1139 label : editor.lang.common.browseServer
\r
1144 label : editor.lang.common.target,
\r
1148 [ editor.lang.common.notSet , ''],
\r
1149 [ editor.lang.common.targetNew , '_blank'],
\r
1150 [ editor.lang.common.targetTop , '_top'],
\r
1151 [ editor.lang.common.targetSelf , '_self'],
\r
1152 [ editor.lang.common.targetParent , '_parent']
\r
1154 setup : function( type, element )
\r
1156 if ( type == LINK )
\r
1157 this.setValue( element.getAttribute( 'target' ) || '' );
\r
1159 commit : function( type, element )
\r
1161 if ( type == LINK )
\r
1163 if ( this.getValue() || this.isChanged() )
\r
1164 element.setAttribute( 'target', this.getValue() );
\r
1173 filebrowser : 'uploadButton',
\r
1174 label : editor.lang.image.upload,
\r
1180 label : editor.lang.image.btnUpload,
\r
1181 style: 'height:40px',
\r
1185 type : 'fileButton',
\r
1186 id : 'uploadButton',
\r
1187 filebrowser : 'info:txtUrl',
\r
1188 label : editor.lang.image.btnUpload,
\r
1189 'for' : [ 'Upload', 'upload' ]
\r
1195 label : editor.lang.common.advancedTab,
\r
1200 widths : [ '50%', '25%', '25%' ],
\r
1206 label : editor.lang.common.id,
\r
1207 setup : function( type, element )
\r
1209 if ( type == IMAGE )
\r
1210 this.setValue( element.getAttribute( 'id' ) );
\r
1212 commit : function( type, element )
\r
1214 if ( type == IMAGE )
\r
1216 if ( this.getValue() || this.isChanged() )
\r
1217 element.setAttribute( 'id', this.getValue() );
\r
1222 id : 'cmbLangDir',
\r
1224 style : 'width : 100px;',
\r
1225 label : editor.lang.common.langDir,
\r
1229 [ editor.lang.common.notSet, '' ],
\r
1230 [ editor.lang.common.langDirLtr, 'ltr' ],
\r
1231 [ editor.lang.common.langDirRtl, 'rtl' ]
\r
1233 setup : function( type, element )
\r
1235 if ( type == IMAGE )
\r
1236 this.setValue( element.getAttribute( 'dir' ) );
\r
1238 commit : function( type, element )
\r
1240 if ( type == IMAGE )
\r
1242 if ( this.getValue() || this.isChanged() )
\r
1243 element.setAttribute( 'dir', this.getValue() );
\r
1249 id : 'txtLangCode',
\r
1250 label : editor.lang.common.langCode,
\r
1252 setup : function( type, element )
\r
1254 if ( type == IMAGE )
\r
1255 this.setValue( element.getAttribute( 'lang' ) );
\r
1257 commit : function( type, element )
\r
1259 if ( type == IMAGE )
\r
1261 if ( this.getValue() || this.isChanged() )
\r
1262 element.setAttribute( 'lang', this.getValue() );
\r
1270 id : 'txtGenLongDescr',
\r
1271 label : editor.lang.common.longDescr,
\r
1272 setup : function( type, element )
\r
1274 if ( type == IMAGE )
\r
1275 this.setValue( element.getAttribute( 'longDesc' ) );
\r
1277 commit : function( type, element )
\r
1279 if ( type == IMAGE )
\r
1281 if ( this.getValue() || this.isChanged() )
\r
1282 element.setAttribute( 'longDesc', this.getValue() );
\r
1288 widths : [ '50%', '50%' ],
\r
1293 id : 'txtGenClass',
\r
1294 label : editor.lang.common.cssClass,
\r
1296 setup : function( type, element )
\r
1298 if ( type == IMAGE )
\r
1299 this.setValue( element.getAttribute( 'class' ) );
\r
1301 commit : function( type, element )
\r
1303 if ( type == IMAGE )
\r
1305 if ( this.getValue() || this.isChanged() )
\r
1306 element.setAttribute( 'class', this.getValue() );
\r
1312 id : 'txtGenTitle',
\r
1313 label : editor.lang.common.advisoryTitle,
\r
1315 onChange : function()
\r
1317 updatePreview( this.getDialog() );
\r
1319 setup : function( type, element )
\r
1321 if ( type == IMAGE )
\r
1322 this.setValue( element.getAttribute( 'title' ) );
\r
1324 commit : function( type, element )
\r
1326 if ( type == IMAGE )
\r
1328 if ( this.getValue() || this.isChanged() )
\r
1329 element.setAttribute( 'title', this.getValue() );
\r
1331 else if ( type == PREVIEW )
\r
1333 element.setAttribute( 'title', this.getValue() );
\r
1335 else if ( type == CLEANUP )
\r
1337 element.removeAttribute( 'title' );
\r
1345 id : 'txtdlgGenStyle',
\r
1346 label : editor.lang.common.cssStyle,
\r
1347 validate : CKEDITOR.dialog.validate.inlineStyle( editor.lang.common.invalidInlineStyle ),
\r
1349 setup : function( type, element )
\r
1351 if ( type == IMAGE )
\r
1353 var genStyle = element.getAttribute( 'style' );
\r
1354 if ( !genStyle && element.$.style.cssText )
\r
1355 genStyle = element.$.style.cssText;
\r
1356 this.setValue( genStyle );
\r
1358 var height = element.$.style.height,
\r
1359 width = element.$.style.width,
\r
1360 aMatchH = ( height ? height : '' ).match( regexGetSize ),
\r
1361 aMatchW = ( width ? width : '').match( regexGetSize );
\r
1363 this.attributesInStyle =
\r
1365 height : !!aMatchH,
\r
1370 onChange : function ()
\r
1372 commitInternally.call( this,
\r
1373 [ 'info:cmbFloat', 'info:cmbAlign',
\r
1374 'info:txtVSpace', 'info:txtHSpace',
\r
1376 'info:txtWidth', 'info:txtHeight' ] );
\r
1377 updatePreview( this );
\r
1379 commit : function( type, element )
\r
1381 if ( type == IMAGE && ( this.getValue() || this.isChanged() ) )
\r
1383 element.setAttribute( 'style', this.getValue() );
\r
1393 CKEDITOR.dialog.add( 'image', function( editor )
\r
1395 return imageDialog( editor, 'image' );
\r
1398 CKEDITOR.dialog.add( 'imagebutton', function( editor )
\r
1400 return imageDialog( editor, 'imagebutton' );
\r