X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fplugins%2Fimage%2Fdialogs%2Fimage.js;h=0fa8827885bda2296a7e71cf5efe9f0ae3ca92ce;hb=e371ddf8abcb89013e20e6d0dd746adec344d0e5;hp=c65a8aa1c0c8e1e15249b661699f9365ad9d9ce6;hpb=8761695d9b70afe75905deaac88f78c1f8aeb32d;p=ckeditor.git diff --git a/_source/plugins/image/dialogs/image.js b/_source/plugins/image/dialogs/image.js index c65a8aa..0fa8827 100644 --- a/_source/plugins/image/dialogs/image.js +++ b/_source/plugins/image/dialogs/image.js @@ -1,150 +1,213 @@ /* -Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ (function() { - // Load image preview. - var IMAGE = 1, - LINK = 2, - PREVIEW = 4, - CLEANUP = 8, - regexGetSize = /^\s*(\d+)((px)|\%)?\s*$/i, - regexGetSizeOrEmpty = /(^\s*(\d+)((px)|\%)?\s*$)|^$/i; - - var onSizeChange = function() + var imageDialog = function( editor, dialogType ) { - var value = this.getValue(), // This = input element. - dialog = this.getDialog(), - aMatch = value.match( regexGetSize ); // Check value - if ( aMatch ) - { - if ( aMatch[2] == '%' ) // % is allowed - > unlock ratio. - switchLockRatio( dialog, false ); // Unlock. - value = aMatch[1]; - } + // Load image preview. + var IMAGE = 1, + LINK = 2, + PREVIEW = 4, + CLEANUP = 8, + regexGetSize = /^\s*(\d+)((px)|\%)?\s*$/i, + regexGetSizeOrEmpty = /(^\s*(\d+)((px)|\%)?\s*$)|^$/i, + pxLengthRegex = /^\d+px$/; - // Only if ratio is locked - if ( dialog.lockRatio ) + var onSizeChange = function() { - var oImageOriginal = dialog.originalElement; - if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) + var value = this.getValue(), // This = input element. + dialog = this.getDialog(), + aMatch = value.match( regexGetSize ); // Check value + if ( aMatch ) { - if ( this.id == 'txtHeight' ) + if ( aMatch[2] == '%' ) // % is allowed - > unlock ratio. + switchLockRatio( dialog, false ); // Unlock. + value = aMatch[1]; + } + + // Only if ratio is locked + if ( dialog.lockRatio ) + { + var oImageOriginal = dialog.originalElement; + if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) { - if ( value && value != '0' ) - value = Math.round( oImageOriginal.$.width * ( value / oImageOriginal.$.height ) ); - if ( !isNaN( value ) ) - dialog.setValueOf( 'info', 'txtWidth', value ); + if ( this.id == 'txtHeight' ) + { + if ( value && value != '0' ) + value = Math.round( oImageOriginal.$.width * ( value / oImageOriginal.$.height ) ); + if ( !isNaN( value ) ) + dialog.setValueOf( 'info', 'txtWidth', value ); + } + else //this.id = txtWidth. + { + if ( value && value != '0' ) + value = Math.round( oImageOriginal.$.height * ( value / oImageOriginal.$.width ) ); + if ( !isNaN( value ) ) + dialog.setValueOf( 'info', 'txtHeight', value ); + } } - else //this.id = txtWidth. + } + updatePreview( dialog ); + }; + + var updatePreview = function( dialog ) + { + //Don't load before onShow. + if ( !dialog.originalElement || !dialog.preview ) + return 1; + + // Read attributes and update imagePreview; + dialog.commitContent( PREVIEW, dialog.preview ); + return 0; + }; + + // Custom commit dialog logic, where we're intended to give inline style + // field (txtdlgGenStyle) higher priority to avoid overwriting styles contribute + // by other fields. + function commitContent() + { + var args = arguments; + var inlineStyleField = this.getContentElement( 'advanced', 'txtdlgGenStyle' ); + inlineStyleField && inlineStyleField.commit.apply( inlineStyleField, args ); + + this.foreach( function( widget ) + { + if ( widget.commit && widget.id != 'txtdlgGenStyle' ) + widget.commit.apply( widget, args ); + }); + } + + // Avoid recursions. + var incommit; + + // Synchronous field values to other impacted fields is required, e.g. border + // size change should alter inline-style text as well. + function commitInternally( targetFields ) + { + if ( incommit ) + return; + + incommit = 1; + + var dialog = this.getDialog(), + element = dialog.imageElement; + if ( element ) + { + // Commit this field and broadcast to target fields. + this.commit( IMAGE, element ); + + targetFields = [].concat( targetFields ); + var length = targetFields.length, + field; + for ( var i = 0; i < length; i++ ) { - if ( value && value != '0' ) - value = Math.round( oImageOriginal.$.height * ( value / oImageOriginal.$.width ) ); - if ( !isNaN( value ) ) - dialog.setValueOf( 'info', 'txtHeight', value ); + field = dialog.getContentElement.apply( dialog, targetFields[ i ].split( ':' ) ); + // May cause recursion. + field && field.setup( IMAGE, element ); } } + + incommit = 0; } - updatePreview( dialog ); - }; - var updatePreview = function( dialog ) - { - //Don't load before onShow. - if ( !dialog.originalElement || !dialog.preview ) - return 1; + var switchLockRatio = function( dialog, value ) + { + var oImageOriginal = dialog.originalElement; - // Read attributes and update imagePreview; - dialog.commitContent( PREVIEW, dialog.preview ); - return 0; - }; + // Dialog may already closed. (#5505) + if( !oImageOriginal ) + return null; - var switchLockRatio = function( dialog, value ) - { - var oImageOriginal = dialog.originalElement, - ratioButton = CKEDITOR.document.getById( 'btnLockSizes' ); + var ratioButton = CKEDITOR.document.getById( btnLockSizesId ); - if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) - { - if ( value == 'check' ) // Check image ratio and original image ratio. + if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) { - var width = dialog.getValueOf( 'info', 'txtWidth' ), - height = dialog.getValueOf( 'info', 'txtHeight' ), - originalRatio = oImageOriginal.$.width * 1000 / oImageOriginal.$.height, - thisRatio = width * 1000 / height; - dialog.lockRatio = false; // Default: unlock ratio - - if ( !width && !height ) - dialog.lockRatio = true; - else if ( !isNaN( originalRatio ) && !isNaN( thisRatio ) ) + if ( value == 'check' ) // Check image ratio and original image ratio. { - if ( Math.round( originalRatio ) == Math.round( thisRatio ) ) + var width = dialog.getValueOf( 'info', 'txtWidth' ), + height = dialog.getValueOf( 'info', 'txtHeight' ), + originalRatio = oImageOriginal.$.width * 1000 / oImageOriginal.$.height, + thisRatio = width * 1000 / height; + dialog.lockRatio = false; // Default: unlock ratio + + if ( !width && !height ) dialog.lockRatio = true; + else if ( !isNaN( originalRatio ) && !isNaN( thisRatio ) ) + { + if ( Math.round( originalRatio ) == Math.round( thisRatio ) ) + dialog.lockRatio = true; + } } + else if ( value != undefined ) + dialog.lockRatio = value; + else + dialog.lockRatio = !dialog.lockRatio; } - else if ( value != undefined ) - dialog.lockRatio = value; + else if ( value != 'check' ) // I can't lock ratio if ratio is unknown. + dialog.lockRatio = false; + + if ( dialog.lockRatio ) + ratioButton.removeClass( 'cke_btn_unlocked' ); else - dialog.lockRatio = !dialog.lockRatio; - } - else if ( value != 'check' ) // I can't lock ratio if ratio is unknown. - dialog.lockRatio = false; + ratioButton.addClass( 'cke_btn_unlocked' ); - if ( dialog.lockRatio ) - ratioButton.removeClass( 'cke_btn_unlocked' ); - else - ratioButton.addClass( 'cke_btn_unlocked' ); + var lang = dialog._.editor.lang.image, + label = lang[ dialog.lockRatio ? 'unlockRatio' : 'lockRatio' ]; - return dialog.lockRatio; - }; + ratioButton.setAttribute( 'title', label ); + ratioButton.getFirst().setText( label ); - var resetSize = function( dialog ) - { - var oImageOriginal = dialog.originalElement; - if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) - { - dialog.setValueOf( 'info', 'txtWidth', oImageOriginal.$.width ); - dialog.setValueOf( 'info', 'txtHeight', oImageOriginal.$.height ); - } - updatePreview( dialog ); - }; + return dialog.lockRatio; + }; - var setupDimension = function( type, element ) - { - if ( type != IMAGE ) - return; + var resetSize = function( dialog ) + { + var oImageOriginal = dialog.originalElement; + if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) + { + dialog.setValueOf( 'info', 'txtWidth', oImageOriginal.$.width ); + dialog.setValueOf( 'info', 'txtHeight', oImageOriginal.$.height ); + } + updatePreview( dialog ); + }; - function checkDimension( size, defaultValue ) + var setupDimension = function( type, element ) { - var aMatch = size.match( regexGetSize ); - if ( aMatch ) + if ( type != IMAGE ) + return; + + function checkDimension( size, defaultValue ) { - if ( aMatch[2] == '%' ) // % is allowed. + var aMatch = size.match( regexGetSize ); + if ( aMatch ) { - aMatch[1] += '%'; - switchLockRatio( dialog, false ); // Unlock ratio + if ( aMatch[2] == '%' ) // % is allowed. + { + aMatch[1] += '%'; + switchLockRatio( dialog, false ); // Unlock ratio + } + return aMatch[1]; } - return aMatch[1]; + return defaultValue; } - return defaultValue; - } - var dialog = this.getDialog(), - value = '', - dimension = (( this.id == 'txtWidth' )? 'width' : 'height' ), - size = element.getAttribute( dimension ); + var dialog = this.getDialog(), + value = '', + dimension = (( this.id == 'txtWidth' )? 'width' : 'height' ), + size = element.getAttribute( dimension ); - if ( size ) - value = checkDimension( size, value ); - value = checkDimension( element.$.style[ dimension ], value ); + if ( size ) + value = checkDimension( size, value ); + value = checkDimension( element.getStyle( dimension ), value ); - this.setValue( value ); - }; + this.setValue( value ); + }; + + var previewPreloader; - var imageDialog = function( editor, dialogType ) - { var onImgLoadEvent = function() { // Image is ready. @@ -155,14 +218,15 @@ For licensing, see LICENSE.html or http://ckeditor.com/license original.removeListener( 'abort', onImgLoadErrorEvent ); // Hide loader - CKEDITOR.document.getById( 'ImagePreviewLoader' ).setStyle( 'display', 'none' ); + CKEDITOR.document.getById( imagePreviewLoaderId ).setStyle( 'display', 'none' ); // New image -> new domensions if ( !this.dontResetSize ) resetSize( this ); if ( this.firstLoad ) - switchLockRatio( this, 'check' ); + CKEDITOR.tools.setTimeout( function(){ switchLockRatio( this, 'check' ); }, 0, this ); + this.firstLoad = false; this.dontResetSize = false; }; @@ -182,9 +246,21 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.preview.setAttribute( 'src', noimage ); // Hide loader - CKEDITOR.document.getById( 'ImagePreviewLoader' ).setStyle( 'display', 'none' ); + CKEDITOR.document.getById( imagePreviewLoaderId ).setStyle( 'display', 'none' ); switchLockRatio( this, false ); // Unlock. }; + + var numbering = function( id ) + { + return CKEDITOR.tools.getNextId() + '_' + id; + }, + btnLockSizesId = numbering( 'btnLockSizes' ), + btnResetSizeId = numbering( 'btnResetSize' ), + imagePreviewLoaderId = numbering( 'ImagePreviewLoader' ), + imagePreviewBoxId = numbering( 'ImagePreviewBox' ), + previewLinkId = numbering( 'previewLink' ), + previewImageId = numbering( 'previewImage' ); + return { title : ( dialogType == 'image' ) ? editor.lang.image.title : editor.lang.image.titleButton, minWidth : 420, @@ -203,16 +279,17 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.firstLoad = true; this.addLink = false; - //Hide loader. - CKEDITOR.document.getById( 'ImagePreviewLoader' ).setStyle( 'display', 'none' ); - // Preview - this.preview = CKEDITOR.document.getById( 'previewImage' ); - var editor = this.getParentEditor(), sel = this.getParentEditor().getSelection(), element = sel.getSelectedElement(), link = element && element.getAscendant( 'a' ); + //Hide loader. + CKEDITOR.document.getById( imagePreviewLoaderId ).setStyle( 'display', 'none' ); + // Create the preview before setup the dialog contents. + previewPreloader = new CKEDITOR.dom.element( 'img', editor.document ); + this.preview = CKEDITOR.document.getById( previewImageId ); + // Copy of the image this.originalElement = editor.document.createElement( 'img' ); this.originalElement.setAttribute( 'alt', '' ); @@ -242,15 +319,19 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.setupContent( LINK, link ); } - if ( element && element.getName() == 'img' && !element.getAttribute( '_cke_protected_html' ) ) - this.imageEditMode = 'img'; - else if ( element && element.getName() == 'input' && element.getAttribute( 'type' ) && element.getAttribute( 'type' ) == 'image' ) - this.imageEditMode = 'input'; + if ( element && element.getName() == 'img' && !element.getAttribute( '_cke_realelement' ) + || element && element.getName() == 'input' && element.getAttribute( 'type' ) == 'image' ) + { + this.imageEditMode = element.getName(); + this.imageElement = element; + } - if ( this.imageEditMode || this.imageElement ) + if ( this.imageEditMode ) { - if ( !this.imageElement ) - this.imageElement = element; + // Use the original element as a buffer from since we don't want + // temporary changes to be committed, e.g. if the dialog is canceled. + this.cleanImageElement = this.imageElement; + this.imageElement = this.cleanImageElement.clone( true, true ); // Fill out all fields. this.setupContent( IMAGE, this.imageElement ); @@ -258,6 +339,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Refresh LockRatio button switchLockRatio ( this, true ); } + else + this.imageElement = editor.document.createElement( 'img' ); // Dont show preview if no URL given. if ( !CKEDITOR.tools.trim( this.getValueOf( 'info', 'txtUrl' ) ) ) @@ -296,6 +379,12 @@ For licensing, see LICENSE.html or http://ckeditor.com/license ); editor.insertElement( this.imageElement ); } + else + { + // Restore the original element before all commits. + this.imageElement = this.cleanImageElement; + delete this.cleanImageElement; + } } else // Create a new image. { @@ -318,6 +407,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.commitContent( IMAGE, this.imageElement ); this.commitContent( LINK, this.linkElement ); + // Remove empty style attribute. + if ( !this.imageElement.getAttribute( 'style' ) ) + this.imageElement.removeAttribute( 'style' ); + // Insert a new Image. if ( !this.imageEditMode ) { @@ -356,8 +449,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license if ( dialogType != 'image' ) this.hidePage( 'Link' ); //Hide Link tab. var doc = this._.element.getDocument(); - this.addFocusable( doc.getById( 'btnResetSize' ), 5 ); - this.addFocusable( doc.getById( 'btnLockSizes' ), 5 ); + this.addFocusable( doc.getById( btnResetSizeId ), 5 ); + this.addFocusable( doc.getById( btnLockSizesId ), 5 ); + + this.commitContent = commitContent; }, onHide : function() { @@ -372,6 +467,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.originalElement.remove(); this.originalElement = false; // Dialog is closed. } + + delete this.imageElement; }, contents : [ { @@ -386,10 +483,6 @@ For licensing, see LICENSE.html or http://ckeditor.com/license children : [ { - type : 'html', - html : '' + CKEDITOR.tools.htmlEncode( editor.lang.image.url ) + '' - }, - { type : 'hbox', widths : [ '280px', '110px' ], align : 'right', @@ -398,7 +491,8 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { id : 'txtUrl', type : 'text', - label : '', + label : editor.lang.common.url, + required: true, onChange : function() { var dialog = this.getDialog(), @@ -414,7 +508,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license original.setCustomData( 'isReady', 'false' ); // Show loader - var loader = CKEDITOR.document.getById( 'ImagePreviewLoader' ); + var loader = CKEDITOR.document.getById( imagePreviewLoaderId ); if ( loader ) loader.setStyle( 'display', '' ); @@ -422,8 +516,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license original.on( 'error', onImgLoadErrorEvent, dialog ); original.on( 'abort', onImgLoadErrorEvent, dialog ); original.setAttribute( 'src', newUrl ); - dialog.preview.setAttribute( 'src', newUrl ); + // Query the preloader to figure out the url impacted by based href. + previewPreloader.setAttribute( 'src', newUrl ); + dialog.preview.setAttribute( 'src', previewPreloader.$.src ); updatePreview( dialog ); } // Dont show preview if no URL given. @@ -442,15 +538,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license this.getDialog().dontResetSize = true; - // In IE7 the dialog is being rendered improperly when loading - // an image with a long URL. So we need to delay it a bit. (#4122) - setTimeout( function() - { - field.setValue( url ); // And call this.onChange() - // Manually set the initial value.(#4191) - field.setInitValue(); - field.focus(); - }, 0 ); + field.setValue( url ); // And call this.onChange() + // Manually set the initial value.(#4191) + field.setInitValue(); + field.focus(); } }, commit : function( type, element ) @@ -471,6 +562,9 @@ For licensing, see LICENSE.html or http://ckeditor.com/license { type : 'button', id : 'browse', + // v-align with the 'txtUrl' field. + // TODO: We need something better than a fixed size here. + style : 'display:inline-block;margin-top:10px;', align : 'center', label : editor.lang.common.browseServer, hidden : true, @@ -484,7 +578,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license id : 'txtAlt', type : 'text', label : editor.lang.image.alt, - accessKey : 'A', + accessKey : 'T', 'default' : '', onChange : function() { @@ -539,27 +633,32 @@ For licensing, see LICENSE.html or http://ckeditor.com/license labelLayout : 'horizontal', label : editor.lang.image.width, onKeyUp : onSizeChange, - validate: function() + onChange : function() + { + commitInternally.call( this, 'advanced:txtdlgGenStyle' ); + }, + validate : function() { var aMatch = this.getValue().match( regexGetSizeOrEmpty ); if ( !aMatch ) - alert( editor.lang.common.validateNumberFailed ); + alert( editor.lang.image.validateWidth ); return !!aMatch; }, setup : setupDimension, - commit : function( type, element ) + commit : function( type, element, internalCommit ) { + var value = this.getValue(); if ( type == IMAGE ) { - var value = this.getValue(); if ( value ) - element.setAttribute( 'width', value ); - else if ( !value && this.isChanged() ) - element.removeAttribute( 'width' ); + element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) ); + else if ( !value && this.isChanged( ) ) + element.removeStyle( 'width' ); + + !internalCommit && element.removeAttribute( 'width' ); } else if ( type == PREVIEW ) { - value = this.getValue(); var aMatch = value.match( regexGetSize ); if ( !aMatch ) { @@ -568,11 +667,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license element.setStyle( 'width', oImageOriginal.$.width + 'px'); } else - element.setStyle( 'width', value + 'px'); + element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) ); } else if ( type == CLEANUP ) { - element.setStyle( 'width', '0px' ); // If removeAttribute doesn't work. element.removeAttribute( 'width' ); element.removeStyle( 'width' ); } @@ -585,40 +683,45 @@ For licensing, see LICENSE.html or http://ckeditor.com/license labelLayout : 'horizontal', label : editor.lang.image.height, onKeyUp : onSizeChange, - validate: function() + onChange : function() + { + commitInternally.call( this, 'advanced:txtdlgGenStyle' ); + }, + validate : function() { var aMatch = this.getValue().match( regexGetSizeOrEmpty ); if ( !aMatch ) - alert( editor.lang.common.validateNumberFailed ); + alert( editor.lang.image.validateHeight ); return !!aMatch; }, setup : setupDimension, - commit : function( type, element ) + commit : function( type, element, internalCommit ) { + var value = this.getValue(); if ( type == IMAGE ) { - var value = this.getValue(); if ( value ) - element.setAttribute( 'height', value ); - else if ( !value && this.isChanged() ) + element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) ); + else if ( !value && this.isChanged( ) ) + element.removeStyle( 'height' ); + + if ( !internalCommit && type == IMAGE ) element.removeAttribute( 'height' ); } else if ( type == PREVIEW ) { - value = this.getValue(); var aMatch = value.match( regexGetSize ); if ( !aMatch ) { var oImageOriginal = this.getDialog().originalElement; if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) - element.setStyle( 'height', oImageOriginal.$.height + 'px'); + element.setStyle( 'height', oImageOriginal.$.height + 'px' ); } else - element.setStyle( 'height', value + 'px'); + element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) ); } else if ( type == CLEANUP ) { - element.setStyle( 'height', '0px' ); // If removeAttribute doesn't work. element.removeAttribute( 'height' ); element.removeStyle( 'height' ); } @@ -632,13 +735,14 @@ For licensing, see LICENSE.html or http://ckeditor.com/license onLoad : function() { // Activate Reset button - var resetButton = CKEDITOR.document.getById( 'btnResetSize' ), - ratioButton = CKEDITOR.document.getById( 'btnLockSizes' ); + var resetButton = CKEDITOR.document.getById( btnResetSizeId ), + ratioButton = CKEDITOR.document.getById( btnLockSizesId ); if ( resetButton ) { - resetButton.on( 'click', function() + resetButton.on( 'click', function(evt) { resetSize( this ); + evt.data.preventDefault(); }, this.getDialog() ); resetButton.on( 'mouseover', function() { @@ -652,7 +756,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license // Activate (Un)LockRatio button if ( ratioButton ) { - ratioButton.on( 'click', function() + ratioButton.on( 'click', function(evt) { var locked = switchLockRatio( this ), oImageOriginal = this.originalElement, @@ -667,6 +771,7 @@ For licensing, see LICENSE.html or http://ckeditor.com/license updatePreview( this ); } } + evt.data.preventDefault(); }, this.getDialog() ); ratioButton.on( 'mouseover', function() { @@ -679,10 +784,10 @@ For licensing, see LICENSE.html or http://ckeditor.com/license } }, html : '
'+
+ ''+
+ ' |