X-Git-Url: https://jasonwoof.com/gitweb/?p=ckeditor.git;a=blobdiff_plain;f=_source%2Fplugins%2Fdialog%2Fplugin.js;h=b5aab8182c2060c5e27b7863ba76f6b848dce35b;hp=26d8a8d406c083afd2faee11b32678c719c11bb0;hb=9afde8772159bd3436f1f5b7862960307710ae5a;hpb=614511639979907ceb0da3614122a4d8eb963ad4 diff --git a/_source/plugins/dialog/plugin.js b/_source/plugins/dialog/plugin.js index 26d8a8d..b5aab81 100644 --- a/_source/plugins/dialog/plugin.js +++ b/_source/plugins/dialog/plugin.js @@ -105,10 +105,19 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; CKEDITOR.dialog = function( editor, dialogName ) { // Load the dialog definition. - var definition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ]; + var definition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ], + defaultDefinition = CKEDITOR.tools.clone( defaultDialogDefinition ), + buttonsOrder = editor.config.dialog_buttonsOrder || 'OS', + dir = editor.lang.dir; + + if ( ( buttonsOrder == 'OS' && CKEDITOR.env.mac ) || // The buttons in MacOS Apps are in reverse order (#4750) + ( buttonsOrder == 'rtl' && dir == 'ltr' ) || + ( buttonsOrder == 'ltr' && dir == 'rtl' ) ) + defaultDefinition.buttons.reverse(); + // Completes the definition with the default values. - definition = CKEDITOR.tools.extend( definition( editor ), defaultDialogDefinition ); + definition = CKEDITOR.tools.extend( definition( editor ), defaultDefinition ); // Clone a functionally independent copy for this dialog. definition = CKEDITOR.tools.clone( definition ); @@ -117,7 +126,6 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; // functions. definition = new definitionObject( this, definition ); - var doc = CKEDITOR.document; var themeBuilt = editor.theme.buildDialog( editor ); @@ -130,7 +138,6 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; name : dialogName, contentSize : { width : 0, height : 0 }, size : { width : 0, height : 0 }, - updateSize : false, contents : {}, buttons : {}, accessKeyMap : {}, @@ -179,6 +186,34 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; definition : definition } , editor ).definition; + + var tabsToRemove = {}; + // Cache tabs that should be removed. + if ( !( 'removeDialogTabs' in editor._ ) && editor.config.removeDialogTabs ) + { + var removeContents = editor.config.removeDialogTabs.split( ';' ); + + for ( i = 0; i < removeContents.length; i++ ) + { + var parts = removeContents[ i ].split( ':' ); + if ( parts.length == 2 ) + { + var removeDialogName = parts[ 0 ]; + if ( !tabsToRemove[ removeDialogName ] ) + tabsToRemove[ removeDialogName ] = []; + tabsToRemove[ removeDialogName ].push( parts[ 1 ] ); + } + } + editor._.removeDialogTabs = tabsToRemove; + } + + // Remove tabs of this dialog. + if ( editor._.removeDialogTabs && ( tabsToRemove = editor._.removeDialogTabs[ dialogName ] ) ) + { + for ( i = 0; i < tabsToRemove.length; i++ ) + definition.removeContents( tabsToRemove[ i ] ); + } + // Initialize load, show, hide, ok and cancel events. if ( definition.onLoad ) this.on( 'load', definition.onLoad ); @@ -601,7 +636,6 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; }, this._.editor ); this._.contentSize = { width : width, height : height }; - this._.updateSize = true; }; })(), @@ -613,15 +647,8 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; */ getSize : function() { - if ( !this._.updateSize ) - return this._.size; var element = this._.element.getFirst(); - var size = this._.size = { width : element.$.offsetWidth || 0, height : element.$.offsetHeight || 0}; - - // If either the offsetWidth or offsetHeight is 0, the element isn't visible. - this._.updateSize = !size.width || !size.height; - - return size; + return { width : element.$.offsetWidth || 0, height : element.$.offsetHeight || 0}; }, /** @@ -629,13 +656,14 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; * @function * @param {Number} x The target x-coordinate. * @param {Number} y The target y-coordinate. + * @param {Boolean} save Flag indicate whether the dialog position should be remembered on next open up. * @example * dialogObj.move( 10, 40 ); */ move : (function() { var isFixed; - return function( x, y ) + return function( x, y, save ) { // The dialog may be fixed positioned or absolute positioned. Ask the // browser what is the current situation first. @@ -662,6 +690,8 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; 'left' : ( x > 0 ? x : 0 ) + 'px', 'top' : ( y > 0 ? y : 0 ) + 'px' }); + + save && ( this._.moved = 1 ); }; })(), @@ -708,7 +738,8 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; // First, set the dialog to an appropriate size. - this.resize( definition.minWidth, definition.minHeight ); + this.resize( this._.contentSize && this._.contentSize.width || definition.minWidth, + this._.contentSize && this._.contentSize.height || definition.minHeight ); // Reset all inputs back to their default value. this.reset(); @@ -753,20 +784,15 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; // Reset the hasFocus state. this._.hasFocus = false; - // Rearrange the dialog to the middle of the window. CKEDITOR.tools.setTimeout( function() { - var viewSize = CKEDITOR.document.getWindow().getViewPaneSize(); - var dialogSize = this.getSize(); - - // We're using definition size for initial position because of - // offten corrupted data in offsetWidth at this point. (#4084) - this.move( ( viewSize.width - definition.minWidth ) / 2, ( viewSize.height - dialogSize.height ) / 2 ); - + this.layout(); this.parts.dialog.setStyle( 'visibility', '' ); // Execute onLoad for the first show. this.fireOnce( 'load', {} ); + CKEDITOR.ui.fire( 'ready', this ); + this.fire( 'show', {} ); this._.editor.fire( 'dialogShow', this ); @@ -778,6 +804,19 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; }, /** + * Rearrange the dialog to its previous position or the middle of the window. + * @since 3.5 + */ + layout : function() + { + var viewSize = CKEDITOR.document.getWindow().getViewPaneSize(), + dialogSize = this.getSize(); + + this.move( this._.moved ? this._.position.x : ( viewSize.width - dialogSize.width ) / 2, + this._.moved ? this._.position.y : ( viewSize.height - dialogSize.height ) / 2 ); + }, + + /** * Executes a function for each UI element. * @param {Function} fn Function to execute for each UI element. * @returns {CKEDITOR.dialog} The current dialog object. @@ -903,7 +942,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; children : contents.elements, expand : !!contents.expand, padding : contents.padding, - style : contents.style || 'width: 100%; height: 100%;' + style : contents.style || 'width: 100%;' }, pageHtml ); // Create the HTML for the tab and the content block. @@ -1342,9 +1381,6 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; buttons : [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ] }; - // The buttons in MacOS Apps are in reverse order #4750 - CKEDITOR.env.mac && defaultDialogDefinition.buttons.reverse(); - // Tool function used to return an item from an array based on its id // property. var getById = function( array, id, recurse ) @@ -1613,7 +1649,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; if ( abstractDialogCoords.x + margins[3] < magnetDistance ) realX = - margins[3]; else if ( abstractDialogCoords.x - margins[1] > viewPaneSize.width - dialogSize.width - magnetDistance ) - realX = viewPaneSize.width - dialogSize.width + margins[1]; + realX = viewPaneSize.width - dialogSize.width + ( editor.lang.dir == 'rtl' ? 0 : margins[1] ); else realX = abstractDialogCoords.x; @@ -1624,7 +1660,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; else realY = abstractDialogCoords.y; - dialog.move( realX, realY ); + dialog.move( realX, realY, 1 ); evt.data.preventDefault(); } @@ -1644,8 +1680,6 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; dialog.parts.title.on( 'mousedown', function( evt ) { - dialog._.updateSize = true; - lastCoords = { x : evt.data.$.screenX, y : evt.data.$.screenY }; CKEDITOR.document.on( 'mousemove', mouseMoveHandler ); @@ -1665,118 +1699,106 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; function initResizeHandles( dialog ) { - var definition = dialog.definition, - minWidth = definition.minWidth || 0, - minHeight = definition.minHeight || 0, - resizable = definition.resizable, - margins = dialog.getParentEditor().skin.margins || [ 0, 0, 0, 0 ]; + var def = dialog.definition, + resizable = def.resizable; - function topSizer( coords, dy ) - { - coords.y += dy; - } + if ( resizable == CKEDITOR.DIALOG_RESIZE_NONE ) + return; - function rightSizer( coords, dx ) - { - coords.x2 += dx; - } + var editor = dialog.getParentEditor(); + var wrapperWidth, wrapperHeight, viewSize, origin, startSize; - function bottomSizer( coords, dy ) + function positionDialog( right ) { - coords.y2 += dy; + // Maintain righthand sizing in RTL. + if ( dialog._.moved && editor.lang.dir == 'rtl' ) + { + var element = dialog._.element.getFirst(); + element.setStyle( 'right', right + "px" ); + element.removeStyle( 'left' ); + } + else if ( !dialog._.moved ) + dialog.layout(); } - function leftSizer( coords, dx ) + var mouseDownFn = CKEDITOR.tools.addFunction( function( $event ) { - coords.x += dx; - } + startSize = dialog.getSize(); - var lastCoords = null, - abstractDialogCoords = null, - magnetDistance = dialog._.editor.config.magnetDistance, - parts = [ 'tl', 't', 'tr', 'l', 'r', 'bl', 'b', 'br' ]; + // Calculate the offset between content and chrome size. + wrapperHeight = startSize.height - dialog.parts.contents.getSize( 'height', ! ( CKEDITOR.env.gecko || CKEDITOR.env.opera || CKEDITOR.env.ie && CKEDITOR.env.quirks ) ); + wrapperWidth = startSize.width - dialog.parts.contents.getSize( 'width', 1 ); - function mouseDownHandler( evt ) - { - var partName = evt.listenerData.part, size = dialog.getSize(); - abstractDialogCoords = dialog.getPosition(); - CKEDITOR.tools.extend( abstractDialogCoords, - { - x2 : abstractDialogCoords.x + size.width, - y2 : abstractDialogCoords.y + size.height - } ); - lastCoords = { x : evt.data.$.screenX, y : evt.data.$.screenY }; + origin = { x : $event.screenX, y : $event.screenY }; - CKEDITOR.document.on( 'mousemove', mouseMoveHandler, dialog, { part : partName } ); - CKEDITOR.document.on( 'mouseup', mouseUpHandler, dialog, { part : partName } ); + viewSize = CKEDITOR.document.getWindow().getViewPaneSize(); + + CKEDITOR.document.on( 'mousemove', mouseMoveHandler ); + CKEDITOR.document.on( 'mouseup', mouseUpHandler ); if ( CKEDITOR.env.ie6Compat ) { var coverDoc = currentCover.getChild( 0 ).getFrameDocument(); - coverDoc.on( 'mousemove', mouseMoveHandler, dialog, { part : partName } ); - coverDoc.on( 'mouseup', mouseUpHandler, dialog, { part : partName } ); + coverDoc.on( 'mousemove', mouseMoveHandler ); + coverDoc.on( 'mouseup', mouseUpHandler ); } - evt.data.preventDefault(); - } + $event.preventDefault && $event.preventDefault(); + }); + + // Prepend the grip to the dialog. + dialog.on( 'load', function() + { + var direction = ''; + if ( resizable == CKEDITOR.DIALOG_RESIZE_WIDTH ) + direction = ' cke_resizer_horizontal'; + else if ( resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT ) + direction = ' cke_resizer_vertical'; + var resizer = CKEDITOR.dom.element.createFromHtml( '
' ); + dialog.parts.footer.append( resizer, 1 ); + }); + editor.on( 'destroy', function() { CKEDITOR.tools.removeFunction( mouseDownFn ); } ); function mouseMoveHandler( evt ) { - var x = evt.data.$.screenX, - y = evt.data.$.screenY, - dx = x - lastCoords.x, - dy = y - lastCoords.y, - viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize(), - partName = evt.listenerData.part; + var rtl = editor.lang.dir == 'rtl', + dx = ( evt.data.$.screenX - origin.x ) * ( rtl ? -1 : 1 ), + dy = evt.data.$.screenY - origin.y, + width = startSize.width, + height = startSize.height, + internalWidth = width + dx * ( dialog._.moved ? 1 : 2 ), + internalHeight = height + dy * ( dialog._.moved ? 1 : 2 ), + element = dialog._.element.getFirst(), + right = rtl && element.getComputedStyle( 'right' ), + position = dialog.getPosition(); - if ( partName.search( 't' ) != -1 ) - topSizer( abstractDialogCoords, dy ); - if ( partName.search( 'l' ) != -1 ) - leftSizer( abstractDialogCoords, dx ); - if ( partName.search( 'b' ) != -1 ) - bottomSizer( abstractDialogCoords, dy ); - if ( partName.search( 'r' ) != -1 ) - rightSizer( abstractDialogCoords, dx ); + // IE might return "auto", we need exact position. + if ( right ) + right = right == 'auto' ? viewSize.width - ( position.x || 0 ) - element.getSize( 'width' ) : parseInt( right, 10 ); - lastCoords = { x : x, y : y }; + if ( position.y + internalHeight > viewSize.height ) + internalHeight = viewSize.height - position.y; - var realX, realY, realX2, realY2; + if ( ( rtl ? right : position.x ) + internalWidth > viewSize.width ) + internalWidth = viewSize.width - ( rtl ? right : position.x ); - if ( abstractDialogCoords.x + margins[3] < magnetDistance ) - realX = - margins[3]; - else if ( partName.search( 'l' ) != -1 && abstractDialogCoords.x2 - abstractDialogCoords.x < minWidth + magnetDistance ) - realX = abstractDialogCoords.x2 - minWidth; - else - realX = abstractDialogCoords.x; + // Make sure the dialog will not be resized to the wrong side when it's in the leftmost position for RTL. + if ( ( resizable == CKEDITOR.DIALOG_RESIZE_WIDTH || resizable == CKEDITOR.DIALOG_RESIZE_BOTH ) && !( rtl && dx > 0 && !position.x ) ) + width = Math.max( def.minWidth || 0, internalWidth - wrapperWidth ); - if ( abstractDialogCoords.y + margins[0] < magnetDistance ) - realY = - margins[0]; - else if ( partName.search( 't' ) != -1 && abstractDialogCoords.y2 - abstractDialogCoords.y < minHeight + magnetDistance ) - realY = abstractDialogCoords.y2 - minHeight; - else - realY = abstractDialogCoords.y; + if ( resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT || resizable == CKEDITOR.DIALOG_RESIZE_BOTH ) + height = Math.max( def.minHeight || 0, internalHeight - wrapperHeight ); - if ( abstractDialogCoords.x2 - margins[1] > viewPaneSize.width - magnetDistance ) - realX2 = viewPaneSize.width + margins[1] ; - else if ( partName.search( 'r' ) != -1 && abstractDialogCoords.x2 - abstractDialogCoords.x < minWidth + magnetDistance ) - realX2 = abstractDialogCoords.x + minWidth; - else - realX2 = abstractDialogCoords.x2; - - if ( abstractDialogCoords.y2 - margins[2] > viewPaneSize.height - magnetDistance ) - realY2= viewPaneSize.height + margins[2] ; - else if ( partName.search( 'b' ) != -1 && abstractDialogCoords.y2 - abstractDialogCoords.y < minHeight + magnetDistance ) - realY2 = abstractDialogCoords.y + minHeight; - else - realY2 = abstractDialogCoords.y2 ; - - dialog.move( realX, realY ); - dialog.resize( realX2 - realX, realY2 - realY ); + dialog.resize( width, height ); + // The right property might get broken during resizing, so computing it before the resizing. + positionDialog( right ); evt.data.preventDefault(); } - function mouseUpHandler( evt ) + function mouseUpHandler() { CKEDITOR.document.removeListener( 'mouseup', mouseUpHandler ); CKEDITOR.document.removeListener( 'mousemove', mouseMoveHandler ); @@ -1787,23 +1809,25 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; coverDoc.removeListener( 'mouseup', mouseUpHandler ); coverDoc.removeListener( 'mousemove', mouseMoveHandler ); } - } -// TODO : Simplify the resize logic, having just a single resize grip
. -// var widthTest = /[lr]/, -// heightTest = /[tb]/; -// for ( var i = 0 ; i < parts.length ; i++ ) -// { -// var element = dialog.parts[ parts[i] + '_resize' ]; -// if ( resizable == CKEDITOR.DIALOG_RESIZE_NONE || -// resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT && widthTest.test( parts[i] ) || -// resizable == CKEDITOR.DIALOG_RESIZE_WIDTH && heightTest.test( parts[i] ) ) -// { -// element.hide(); -// continue; -// } -// element.on( 'mousedown', mouseDownHandler, dialog, { part : parts[i] } ); -// } + // Switch back to use the left property, if RTL is used. + if ( editor.lang.dir == 'rtl' ) + { + var element = dialog._.element.getFirst(), + left = element.getComputedStyle( 'left' ); + + // IE might return "auto", we need exact position. + if ( left == 'auto' ) + left = viewSize.width - parseInt( element.getStyle( 'right' ), 10 ) - dialog.getSize().width; + else + left = parseInt( left, 10 ); + + element.removeStyle( 'right' ); + // Make sure the left property gets applied, even if it is the same as previously. + dialog._.position.x += 1; + dialog.move( left, dialog._.position.y ); + } + } } var resizeCover; @@ -2992,6 +3016,34 @@ CKEDITOR.plugins.add( 'dialog', */ /** + * The guildeline to follow when generating the dialog buttons. There are 3 possible options: + * + * @name CKEDITOR.config.dialog_buttonsOrder + * @type String + * @default 'OS' + * @since 3.5 + * @example + * config.dialog_buttonsOrder = 'rtl'; + */ + +/** + * The dialog contents to removed. It's a string composed by dialog name and tab name with a colon between them. + * Separate each pair with semicolon (see example). + * Note: All names are case-sensitive. + * Note: Be cautious when specifying dialog tabs that are mandatory, like "info", dialog functionality might be broken because of this! + * @name CKEDITOR.config.removeDialogTabs + * @type String + * @since 3.5 + * @default '' + * @example + * config.removeDialogTabs = 'flash:advanced;image:Link'; + */ + +/** * Fired when a dialog definition is about to be used to create a dialog into * an editor instance. This event makes it possible to customize the definition * before creating it.