PREVIEW = 4,\r
CLEANUP = 8,\r
regexGetSize = /^\s*(\d+)((px)|\%)?\s*$/i,\r
- regexGetSizeOrEmpty = /(^\s*(\d+)((px)|\%)?\s*$)|^$/i;\r
+ regexGetSizeOrEmpty = /(^\s*(\d+)((px)|\%)?\s*$)|^$/i,\r
+ pxLengthRegex = /^\d+px$/;\r
\r
var onSizeChange = function()\r
{\r
return 0;\r
};\r
\r
+ // Custom commit dialog logic, where we're intended to give inline style\r
+ // field (txtdlgGenStyle) higher priority to avoid overwriting styles contribute\r
+ // by other fields.\r
+ function commitContent()\r
+ {\r
+ var args = arguments;\r
+ var inlineStyleField = this.getContentElement( 'advanced', 'txtdlgGenStyle' );\r
+ inlineStyleField && inlineStyleField.commit.apply( inlineStyleField, args );\r
+\r
+ this.foreach( function( widget )\r
+ {\r
+ if ( widget.commit && widget.id != 'txtdlgGenStyle' )\r
+ widget.commit.apply( widget, args );\r
+ });\r
+ }\r
+\r
+ // Avoid recursions.\r
+ var incommit;\r
+\r
+ // Synchronous field values to other impacted fields is required, e.g. border\r
+ // size change should alter inline-style text as well.\r
+ function commitInternally( targetFields )\r
+ {\r
+ if( incommit )\r
+ return;\r
+\r
+ incommit = 1;\r
+\r
+ var dialog = this.getDialog(),\r
+ element = dialog.imageElement;\r
+ if( element )\r
+ {\r
+ // Commit this field and broadcast to target fields.\r
+ this.commit( IMAGE, element );\r
+\r
+ targetFields = [].concat( targetFields );\r
+ var length = targetFields.length,\r
+ field;\r
+ for ( var i = 0; i < length; i++ )\r
+ {\r
+ field = dialog.getContentElement.apply( dialog, targetFields[ i ].split( ':' ) );\r
+ // May cause recursion.\r
+ field && field.setup( IMAGE, element );\r
+ }\r
+ }\r
+\r
+ incommit = 0;\r
+ }\r
+\r
var switchLockRatio = function( dialog, value )\r
{\r
var oImageOriginal = dialog.originalElement,\r
\r
if ( size )\r
value = checkDimension( size, value );\r
- value = checkDimension( element.$.style[ dimension ], value );\r
+ value = checkDimension( element.getStyle( dimension ), value );\r
\r
this.setValue( value );\r
};\r
this.setupContent( LINK, link );\r
}\r
\r
- if ( element && element.getName() == 'img' && !element.getAttribute( '_cke_protected_html' ) )\r
- this.imageEditMode = 'img';\r
- else if ( element && element.getName() == 'input' && element.getAttribute( 'type' ) && element.getAttribute( 'type' ) == 'image' )\r
- this.imageEditMode = 'input';\r
+ if ( element && element.getName() == 'img' && !element.getAttribute( '_cke_realelement' )\r
+ || element && element.getName() == 'input' && element.getAttribute( 'type' ) == 'image' )\r
+ {\r
+ this.imageEditMode = element.getName();\r
+ this.imageElement = element;\r
+ }\r
\r
- if ( this.imageEditMode || this.imageElement )\r
+ if ( this.imageEditMode )\r
{\r
- if ( !this.imageElement )\r
- this.imageElement = element;\r
+ // Use the original element as a buffer from since we don't want\r
+ // temporary changes to be committed, e.g. if the dialog is canceled.\r
+ this.cleanImageElement = this.imageElement;\r
+ this.imageElement = this.cleanImageElement.clone( true, true );\r
\r
// Fill out all fields.\r
this.setupContent( IMAGE, this.imageElement );\r
// Refresh LockRatio button\r
switchLockRatio ( this, true );\r
}\r
+ else\r
+ this.imageElement = editor.document.createElement( 'img' );\r
\r
// Dont show preview if no URL given.\r
if ( !CKEDITOR.tools.trim( this.getValueOf( 'info', 'txtUrl' ) ) )\r
);\r
editor.insertElement( this.imageElement );\r
}\r
+ else\r
+ {\r
+ // Restore the original element before all commits.\r
+ this.imageElement = this.cleanImageElement;\r
+ delete this.cleanImageElement;\r
+ }\r
}\r
else // Create a new image.\r
{\r
this.commitContent( IMAGE, this.imageElement );\r
this.commitContent( LINK, this.linkElement );\r
\r
+ // Remove empty style attribute.\r
+ if( !this.imageElement.getAttribute( 'style' ) )\r
+ this.imageElement.removeAttribute( 'style' );\r
+\r
// Insert a new Image.\r
if ( !this.imageEditMode )\r
{\r
var doc = this._.element.getDocument();\r
this.addFocusable( doc.getById( 'btnResetSize' ), 5 );\r
this.addFocusable( doc.getById( 'btnLockSizes' ), 5 );\r
+\r
+ this.commitContent = commitContent;\r
},\r
onHide : function()\r
{\r
this.originalElement.remove();\r
this.originalElement = false; // Dialog is closed.\r
}\r
+\r
+ delete this.imageElement;\r
},\r
contents : [\r
{\r
\r
this.getDialog().dontResetSize = true;\r
\r
- // In IE7 the dialog is being rendered improperly when loading\r
- // an image with a long URL. So we need to delay it a bit. (#4122)\r
- setTimeout( function()\r
- {\r
- field.setValue( url ); // And call this.onChange()\r
- // Manually set the initial value.(#4191)\r
- field.setInitValue();\r
- field.focus();\r
- }, 0 );\r
+ field.setValue( url ); // And call this.onChange()\r
+ // Manually set the initial value.(#4191)\r
+ field.setInitValue();\r
+ field.focus();\r
}\r
},\r
commit : function( type, element )\r
labelLayout : 'horizontal',\r
label : editor.lang.image.width,\r
onKeyUp : onSizeChange,\r
+ onChange : function()\r
+ {\r
+ commitInternally.call( this, 'advanced:txtdlgGenStyle' );\r
+ },\r
validate: function()\r
{\r
var aMatch = this.getValue().match( regexGetSizeOrEmpty );\r
return !!aMatch;\r
},\r
setup : setupDimension,\r
- commit : function( type, element )\r
+ commit : function( type, element, internalCommit )\r
{\r
+ var value = this.getValue();\r
if ( type == IMAGE )\r
{\r
- var value = this.getValue();\r
if ( value )\r
- element.setAttribute( 'width', value );\r
- else if ( !value && this.isChanged() )\r
- element.removeAttribute( 'width' );\r
+ element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) );\r
+ else if ( !value && this.isChanged( ) )\r
+ element.removeStyle( 'width' );\r
+\r
+ !internalCommit && element.removeAttribute( 'width' );\r
}\r
else if ( type == PREVIEW )\r
{\r
- value = this.getValue();\r
var aMatch = value.match( regexGetSize );\r
if ( !aMatch )\r
{\r
}\r
else if ( type == CLEANUP )\r
{\r
- element.setStyle( 'width', '0px' ); // If removeAttribute doesn't work.\r
element.removeAttribute( 'width' );\r
element.removeStyle( 'width' );\r
}\r
labelLayout : 'horizontal',\r
label : editor.lang.image.height,\r
onKeyUp : onSizeChange,\r
+ onChange : function()\r
+ {\r
+ commitInternally.call( this, 'advanced:txtdlgGenStyle' );\r
+ },\r
validate: function()\r
{\r
var aMatch = this.getValue().match( regexGetSizeOrEmpty );\r
return !!aMatch;\r
},\r
setup : setupDimension,\r
- commit : function( type, element )\r
+ commit : function( type, element, internalCommit )\r
{\r
+ var value = this.getValue();\r
if ( type == IMAGE )\r
{\r
- var value = this.getValue();\r
if ( value )\r
- element.setAttribute( 'height', value );\r
- else if ( !value && this.isChanged() )\r
+ element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) );\r
+ else if ( !value && this.isChanged( ) )\r
+ element.removeStyle( 'height' );\r
+\r
+ if( !internalCommit && type == IMAGE )\r
element.removeAttribute( 'height' );\r
}\r
else if ( type == PREVIEW )\r
{\r
- value = this.getValue();\r
var aMatch = value.match( regexGetSize );\r
if ( !aMatch )\r
{\r
var oImageOriginal = this.getDialog().originalElement;\r
if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' )\r
- element.setStyle( 'height', oImageOriginal.$.height + 'px');\r
+ element.setStyle( 'height', oImageOriginal.$.height + 'px' );\r
}\r
else\r
- element.setStyle( 'height', value + 'px');\r
+ element.setStyle( 'height', value + 'px' );\r
}\r
else if ( type == CLEANUP )\r
{\r
- element.setStyle( 'height', '0px' ); // If removeAttribute doesn't work.\r
element.removeAttribute( 'height' );\r
element.removeStyle( 'height' );\r
}\r
{\r
updatePreview( this.getDialog() );\r
},\r
+ onChange : function()\r
+ {\r
+ commitInternally.call( this, 'advanced:txtdlgGenStyle' );\r
+ },\r
validate: function()\r
{\r
var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );\r
setup : function( type, element )\r
{\r
if ( type == IMAGE )\r
- this.setValue( element.getAttribute( 'border' ) );\r
- },\r
- commit : function( type, element )\r
- {\r
- if ( type == IMAGE )\r
{\r
- if ( this.getValue() || this.isChanged() )\r
- element.setAttribute( 'border', this.getValue() );\r
+ var value,\r
+ borderStyle = element.getStyle( 'border-width' );\r
+\r
+ borderStyle = borderStyle && borderStyle.match( /^(\d+px)(?: \1 \1 \1)?$/ );\r
+ value = borderStyle && parseInt( borderStyle[ 1 ], 10 );\r
+ !value && ( value = element.getAttribute( 'border' ) );\r
+\r
+ this.setValue( value );\r
}\r
- else if ( type == PREVIEW )\r
+ },\r
+ commit : function( type, element, internalCommit )\r
+ {\r
+ var value = parseInt( this.getValue(), 10 );\r
+ if ( type == IMAGE || type == PREVIEW )\r
{\r
- var value = parseInt( this.getValue(), 10 );\r
- value = isNaN( value ) ? 0 : value;\r
- element.setAttribute( 'border', value );\r
- element.setStyle( 'border', value + 'px solid black' );\r
+ if ( value )\r
+ {\r
+ element.setStyle( 'border-width', CKEDITOR.tools.cssLength( value ) );\r
+ element.setStyle( 'border-style', 'solid' );\r
+ }\r
+ else if ( !value && this.isChanged() )\r
+ {\r
+ element.removeStyle( 'border-width' );\r
+ element.removeStyle( 'border-style' );\r
+ element.removeStyle( 'border-color' );\r
+ }\r
+\r
+ if( !internalCommit && type == IMAGE )\r
+ element.removeAttribute( 'border' );\r
}\r
else if ( type == CLEANUP )\r
{\r
element.removeAttribute( 'border' );\r
- element.removeStyle( 'border' );\r
+ element.removeStyle( 'border-width' );\r
+ element.removeStyle( 'border-style' );\r
+ element.removeStyle( 'border-color' );\r
}\r
}\r
},\r
{\r
updatePreview( this.getDialog() );\r
},\r
+ onChange : function()\r
+ {\r
+ commitInternally.call( this, 'advanced:txtdlgGenStyle' );\r
+ },\r
validate: function()\r
{\r
var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );\r
{\r
if ( type == IMAGE )\r
{\r
- var value = element.getAttribute( 'hspace' );\r
- if ( value != -1 ) // In IE empty = -1.\r
- this.setValue( value );\r
+ var value,\r
+ marginLeftPx,\r
+ marginRightPx,\r
+ marginLeftStyle = element.getStyle( 'margin-left' ),\r
+ marginRightStyle = element.getStyle( 'margin-right' );\r
+\r
+ marginLeftStyle = marginLeftStyle && marginLeftStyle.match( pxLengthRegex );\r
+ marginRightStyle = marginRightStyle && marginRightStyle.match( pxLengthRegex );\r
+ marginLeftPx = parseInt( marginLeftStyle, 10 );\r
+ marginRightPx = parseInt( marginRightStyle, 10 );\r
+\r
+ value = ( marginLeftPx == marginRightPx ) && marginLeftPx;\r
+ !value && ( value = element.getAttribute( 'hspace' ) );\r
+\r
+ this.setValue( value );\r
}\r
},\r
- commit : function( type, element )\r
+ commit : function( type, element, internalCommit )\r
{\r
- if ( type == IMAGE )\r
- {\r
- if ( this.getValue() || this.isChanged() )\r
- element.setAttribute( 'hspace', this.getValue() );\r
- }\r
- else if ( type == PREVIEW )\r
+ var value = parseInt( this.getValue(), 10 );\r
+ if ( type == IMAGE || type == PREVIEW )\r
{\r
- var value = parseInt( this.getValue(), 10 );\r
- value = isNaN( value ) ? 0 : value;\r
- element.setAttribute( 'hspace', value );\r
- element.setStyle( 'margin-left', value + 'px' );\r
- element.setStyle( 'margin-right', value + 'px' );\r
+ if ( value )\r
+ {\r
+ element.setStyle( 'margin-left', CKEDITOR.tools.cssLength( value ) );\r
+ element.setStyle( 'margin-right', CKEDITOR.tools.cssLength( value ) );\r
+ }\r
+ else if ( !value && this.isChanged( ) )\r
+ {\r
+ element.removeStyle( 'margin-left' );\r
+ element.removeStyle( 'margin-right' );\r
+ }\r
+\r
+ if( !internalCommit && type == IMAGE )\r
+ element.removeAttribute( 'hspace' );\r
}\r
else if ( type == CLEANUP )\r
{\r
{\r
updatePreview( this.getDialog() );\r
},\r
+ onChange : function()\r
+ {\r
+ commitInternally.call( this, 'advanced:txtdlgGenStyle' );\r
+ },\r
validate: function()\r
{\r
var func = CKEDITOR.dialog.validate.integer( editor.lang.common.validateNumberFailed );\r
setup : function( type, element )\r
{\r
if ( type == IMAGE )\r
- this.setValue( element.getAttribute( 'vspace' ) );\r
- },\r
- commit : function( type, element )\r
- {\r
- if ( type == IMAGE )\r
{\r
- if ( this.getValue() || this.isChanged() )\r
- element.setAttribute( 'vspace', this.getValue() );\r
+ var value,\r
+ marginTopPx,\r
+ marginBottomPx,\r
+ marginTopStyle = element.getStyle( 'margin-top' ),\r
+ marginBottomStyle = element.getStyle( 'margin-bottom' );\r
+\r
+ marginTopStyle = marginTopStyle && marginTopStyle.match( pxLengthRegex );\r
+ marginBottomStyle = marginBottomStyle && marginBottomStyle.match( pxLengthRegex );\r
+ marginTopPx = parseInt( marginTopStyle, 10 );\r
+ marginBottomPx = parseInt( marginBottomStyle, 10 );\r
+\r
+ value = ( marginTopPx == marginBottomPx ) && marginTopPx;\r
+ !value && ( value = element.getAttribute( 'vspace' ) );\r
+ this.setValue( value );\r
}\r
- else if ( type == PREVIEW )\r
+ },\r
+ commit : function( type, element, internalCommit )\r
+ {\r
+ var value = parseInt( this.getValue(), 10 );\r
+ if ( type == IMAGE || type == PREVIEW )\r
{\r
- var value = parseInt( this.getValue(), 10 );\r
- value = isNaN( value ) ? 0 : value;\r
- element.setAttribute( 'vspace', this.getValue() );\r
- element.setStyle( 'margin-top', value + 'px' );\r
- element.setStyle( 'margin-bottom', value + 'px' );\r
+ if ( value )\r
+ {\r
+ element.setStyle( 'margin-top', CKEDITOR.tools.cssLength( value ) );\r
+ element.setStyle( 'margin-bottom', CKEDITOR.tools.cssLength( value ) );\r
+ }\r
+ else if ( !value && this.isChanged( ) )\r
+ {\r
+ element.removeStyle( 'margin-top' );\r
+ element.removeStyle( 'margin-bottom' );\r
+ }\r
+\r
+ if( !internalCommit && type == IMAGE )\r
+ element.removeAttribute( 'vspace' );\r
}\r
else if ( type == CLEANUP )\r
{\r
[\r
[ editor.lang.common.notSet , ''],\r
[ editor.lang.image.alignLeft , 'left'],\r
- [ editor.lang.image.alignAbsBottom , 'absBottom'],\r
- [ editor.lang.image.alignAbsMiddle , 'absMiddle'],\r
- [ editor.lang.image.alignBaseline , 'baseline'],\r
- [ editor.lang.image.alignBottom , 'bottom'],\r
- [ editor.lang.image.alignMiddle , 'middle'],\r
- [ editor.lang.image.alignRight , 'right'],\r
- [ editor.lang.image.alignTextTop , 'textTop'],\r
- [ editor.lang.image.alignTop , 'top']\r
+ [ editor.lang.image.alignRight , 'right']\r
+ // Backward compatible with v2 on setup when specified as attribute value,\r
+ // while these values are no more available as select options.\r
+ // [ editor.lang.image.alignAbsBottom , 'absBottom'],\r
+ // [ editor.lang.image.alignAbsMiddle , 'absMiddle'],\r
+ // [ editor.lang.image.alignBaseline , 'baseline'],\r
+ // [ editor.lang.image.alignTextTop , 'text-top'],\r
+ // [ editor.lang.image.alignBottom , 'bottom'],\r
+ // [ editor.lang.image.alignMiddle , 'middle'],\r
+ // [ editor.lang.image.alignTop , 'top']\r
],\r
onChange : function()\r
{\r
updatePreview( this.getDialog() );\r
+ commitInternally.call( this, 'advanced:txtdlgGenStyle' );\r
},\r
setup : function( type, element )\r
{\r
if ( type == IMAGE )\r
- this.setValue( element.getAttribute( 'align' ) );\r
+ {\r
+ var value = element.getStyle( 'float' );\r
+ switch( value )\r
+ {\r
+ // Ignore those unrelated values.\r
+ case 'inherit':\r
+ case 'none':\r
+ value = '';\r
+ }\r
+\r
+ !value && ( value = ( element.getAttribute( 'align' ) || '' ).toLowerCase() );\r
+ this.setValue( value );\r
+ }\r
},\r
- commit : function( type, element )\r
+ commit : function( type, element, internalCommit )\r
{\r
var value = this.getValue();\r
- if ( type == IMAGE )\r
+ if ( type == IMAGE || type == PREVIEW )\r
{\r
- if ( value || this.isChanged() )\r
- element.setAttribute( 'align', value );\r
- }\r
- else if ( type == PREVIEW )\r
- {\r
- element.setAttribute( 'align', this.getValue() );\r
-\r
- if ( value == 'absMiddle' || value == 'middle' )\r
- element.setStyle( 'vertical-align', 'middle' );\r
- else if ( value == 'top' || value == 'textTop' )\r
- element.setStyle( 'vertical-align', 'top' );\r
- else\r
- element.removeStyle( 'vertical-align' );\r
-\r
- if ( value == 'right' || value == 'left' )\r
- element.setStyle( 'styleFloat', value );\r
- else\r
- element.removeStyle( 'styleFloat' );\r
+ if ( value )\r
+ element.setStyle( 'float', value );\r
+ else if ( !value && this.isChanged( ) )\r
+ element.removeStyle( 'float' );\r
\r
+ if( !internalCommit && type == IMAGE )\r
+ {\r
+ value = ( element.getAttribute( 'align' ) || '' ).toLowerCase();\r
+ switch( value )\r
+ {\r
+ // we should remove it only if it matches "left" or "right",\r
+ // otherwise leave it intact.\r
+ case 'left':\r
+ case 'right':\r
+ element.removeAttribute( 'align' );\r
+ }\r
+ }\r
}\r
else if ( type == CLEANUP )\r
- {\r
- element.removeAttribute( 'align' );\r
- }\r
+ element.removeStyle( 'float' );\r
+\r
}\r
}\r
]\r
};\r
}\r
},\r
+ onChange : function ()\r
+ {\r
+ commitInternally.call( this,\r
+ [ 'info:cmbFloat', 'info:cmbAlign',\r
+ 'info:txtVSpace', 'info:txtHSpace',\r
+ 'info:txtBorder',\r
+ 'info:txtWidth', 'info:txtHeight' ] );\r
+ updatePreview( this );\r
+ },\r
commit : function( type, element )\r
{\r
if ( type == IMAGE && ( this.getValue() || this.isChanged() ) )\r
{\r
element.setAttribute( 'style', this.getValue() );\r
-\r
- // Set STYLE dimensions.\r
- var height = element.getAttribute( 'height' ),\r
- width = element.getAttribute( 'width' );\r
-\r
- if ( this.attributesInStyle && this.attributesInStyle.height )\r
- {\r
- if ( height )\r
- {\r
- if ( height.match( regexGetSize )[2] == '%' ) // % is allowed\r
- element.setStyle( 'height', height + '%' );\r
- else\r
- element.setStyle( 'height', height + 'px' );\r
- }\r
- else\r
- element.removeStyle( 'height' );\r
- }\r
- if ( this.attributesInStyle && this.attributesInStyle.width )\r
- {\r
- if ( width )\r
- {\r
- if ( width.match( regexGetSize )[2] == '%' ) // % is allowed\r
- element.setStyle( 'width', width + '%' );\r
- else\r
- element.setStyle( 'width', width + 'px' );\r
- }\r
- else\r
- element.removeStyle( 'width' );\r
- }\r
}\r
}\r
}\r