/*\r
-Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.\r
For licensing, see LICENSE.html or http://ckeditor.com/license\r
*/\r
\r
\r
(function()\r
{\r
+ var cssLength = CKEDITOR.tools.cssLength;\r
function isTabVisible( tabId )\r
{\r
return !!this._.tabs[ tabId ][ 0 ].$.offsetHeight;\r
return null;\r
}\r
\r
+\r
+ function clearOrRecoverTextInputValue( container, isRecover )\r
+ {\r
+ var inputs = container.$.getElementsByTagName( 'input' );\r
+ for ( var i = 0, length = inputs.length; i < length ; i++ )\r
+ {\r
+ var item = new CKEDITOR.dom.element( inputs[ i ] );\r
+\r
+ if ( item.getAttribute( 'type' ).toLowerCase() == 'text' )\r
+ {\r
+ if ( isRecover )\r
+ {\r
+ item.setAttribute( 'value', item.getCustomData( 'fake_value' ) || '' );\r
+ item.removeCustomData( 'fake_value' );\r
+ }\r
+ else\r
+ {\r
+ item.setCustomData( 'fake_value', item.getAttribute( 'value' ) );\r
+ item.setAttribute( 'value', '' );\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
/**\r
* This is the base class for runtime dialog objects. An instance of this\r
* class represents a single named dialog for a single editor instance.\r
CKEDITOR.dialog = function( editor, dialogName )\r
{\r
// Load the dialog definition.\r
- var definition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ];\r
+ var definition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ],\r
+ defaultDefinition = CKEDITOR.tools.clone( defaultDialogDefinition ),\r
+ buttonsOrder = editor.config.dialog_buttonsOrder || 'OS',\r
+ dir = editor.lang.dir;\r
+\r
+ if ( ( buttonsOrder == 'OS' && CKEDITOR.env.mac ) || // The buttons in MacOS Apps are in reverse order (#4750)\r
+ ( buttonsOrder == 'rtl' && dir == 'ltr' ) ||\r
+ ( buttonsOrder == 'ltr' && dir == 'rtl' ) )\r
+ defaultDefinition.buttons.reverse();\r
+\r
\r
// Completes the definition with the default values.\r
- definition = CKEDITOR.tools.extend( definition( editor ), defaultDialogDefinition );\r
+ definition = CKEDITOR.tools.extend( definition( editor ), defaultDefinition );\r
\r
// Clone a functionally independent copy for this dialog.\r
definition = CKEDITOR.tools.clone( definition );\r
// functions.\r
definition = new definitionObject( this, definition );\r
\r
-\r
var doc = CKEDITOR.document;\r
\r
var themeBuilt = editor.theme.buildDialog( editor );\r
name : dialogName,\r
contentSize : { width : 0, height : 0 },\r
size : { width : 0, height : 0 },\r
- updateSize : false,\r
contents : {},\r
buttons : {},\r
accessKeyMap : {},\r
definition : definition\r
}\r
, editor ).definition;\r
+\r
+ var tabsToRemove = {};\r
+ // Cache tabs that should be removed.\r
+ if ( !( 'removeDialogTabs' in editor._ ) && editor.config.removeDialogTabs )\r
+ {\r
+ var removeContents = editor.config.removeDialogTabs.split( ';' );\r
+\r
+ for ( i = 0; i < removeContents.length; i++ )\r
+ {\r
+ var parts = removeContents[ i ].split( ':' );\r
+ if ( parts.length == 2 )\r
+ {\r
+ var removeDialogName = parts[ 0 ];\r
+ if ( !tabsToRemove[ removeDialogName ] )\r
+ tabsToRemove[ removeDialogName ] = [];\r
+ tabsToRemove[ removeDialogName ].push( parts[ 1 ] );\r
+ }\r
+ }\r
+ editor._.removeDialogTabs = tabsToRemove;\r
+ }\r
+\r
+ // Remove tabs of this dialog.\r
+ if ( editor._.removeDialogTabs && ( tabsToRemove = editor._.removeDialogTabs[ dialogName ] ) )\r
+ {\r
+ for ( i = 0; i < tabsToRemove.length; i++ )\r
+ definition.removeContents( tabsToRemove[ i ] );\r
+ }\r
+\r
// Initialize load, show, hide, ok and cancel events.\r
if ( definition.onLoad )\r
this.on( 'load', definition.onLoad );\r
page && this.addPage( page );\r
}\r
\r
- this.parts['tabs'].on( 'click', function( evt )\r
+ this.parts[ 'tabs' ].on( 'click', function( evt )\r
{\r
var target = evt.data.getTarget();\r
// If we aren't inside a tab, bail out.\r
}, this._.editor );\r
\r
this._.contentSize = { width : width, height : height };\r
- this._.updateSize = true;\r
};\r
})(),\r
\r
*/\r
getSize : function()\r
{\r
- if ( !this._.updateSize )\r
- return this._.size;\r
var element = this._.element.getFirst();\r
- var size = this._.size = { width : element.$.offsetWidth || 0, height : element.$.offsetHeight || 0};\r
-\r
- // If either the offsetWidth or offsetHeight is 0, the element isn't visible.\r
- this._.updateSize = !size.width || !size.height;\r
-\r
- return size;\r
+ return { width : element.$.offsetWidth || 0, height : element.$.offsetHeight || 0};\r
},\r
\r
/**\r
* @function\r
* @param {Number} x The target x-coordinate.\r
* @param {Number} y The target y-coordinate.\r
+ * @param {Boolean} save Flag indicate whether the dialog position should be remembered on next open up.\r
* @example\r
* dialogObj.move( 10, 40 );\r
*/\r
move : (function()\r
{\r
var isFixed;\r
- return function( x, y )\r
+ return function( x, y, save )\r
{\r
// The dialog may be fixed positioned or absolute positioned. Ask the\r
// browser what is the current situation first.\r
'left' : ( x > 0 ? x : 0 ) + 'px',\r
'top' : ( y > 0 ? y : 0 ) + 'px'\r
});\r
+\r
+ save && ( this._.moved = 1 );\r
};\r
})(),\r
\r
*/\r
show : function()\r
{\r
- var editor = this._.editor;\r
- if ( editor.mode == 'wysiwyg' && CKEDITOR.env.ie )\r
- {\r
- var selection = editor.getSelection();\r
- selection && selection.lock();\r
- }\r
-\r
// Insert the dialog's element to the root document.\r
var element = this._.element;\r
var definition = this.definition;\r
\r
\r
// First, set the dialog to an appropriate size.\r
- this.resize( definition.minWidth, definition.minHeight );\r
-\r
- // Select the first tab by default.\r
- this.selectPage( this.definition.contents[0].id );\r
+ this.resize( this._.contentSize && this._.contentSize.width || definition.minWidth,\r
+ this._.contentSize && this._.contentSize.height || definition.minHeight );\r
\r
// Reset all inputs back to their default value.\r
this.reset();\r
\r
+ // Select the first tab by default.\r
+ this.selectPage( this.definition.contents[0].id );\r
+\r
// Set z-index.\r
if ( CKEDITOR.dialog._.currentZIndex === null )\r
CKEDITOR.dialog._.currentZIndex = this._.editor.config.baseFloatZIndex;\r
// Reset the hasFocus state.\r
this._.hasFocus = false;\r
\r
- // Rearrange the dialog to the middle of the window.\r
CKEDITOR.tools.setTimeout( function()\r
{\r
- var viewSize = CKEDITOR.document.getWindow().getViewPaneSize();\r
- var dialogSize = this.getSize();\r
-\r
- // We're using definition size for initial position because of\r
- // offten corrupted data in offsetWidth at this point. (#4084)\r
- this.move( ( viewSize.width - definition.minWidth ) / 2, ( viewSize.height - dialogSize.height ) / 2 );\r
-\r
+ this.layout();\r
this.parts.dialog.setStyle( 'visibility', '' );\r
\r
// Execute onLoad for the first show.\r
this.fireOnce( 'load', {} );\r
+ CKEDITOR.ui.fire( 'ready', this );\r
+\r
this.fire( 'show', {} );\r
this._.editor.fire( 'dialogShow', this );\r
\r
},\r
\r
/**\r
+ * Rearrange the dialog to its previous position or the middle of the window.\r
+ * @since 3.5\r
+ */\r
+ layout : function()\r
+ {\r
+ var viewSize = CKEDITOR.document.getWindow().getViewPaneSize(),\r
+ dialogSize = this.getSize();\r
+\r
+ this.move( this._.moved ? this._.position.x : ( viewSize.width - dialogSize.width ) / 2,\r
+ this._.moved ? this._.position.y : ( viewSize.height - dialogSize.height ) / 2 );\r
+ },\r
+\r
+ /**\r
* Executes a function for each UI element.\r
* @param {Function} fn Function to execute for each UI element.\r
* @returns {CKEDITOR.dialog} The current dialog object.\r
for ( var i in this._.contents )\r
{\r
for ( var j in this._.contents[i] )\r
- fn( this._.contents[i][j]);\r
+ fn( this._.contents[i][j] );\r
}\r
return this;\r
},\r
*/\r
reset : (function()\r
{\r
- var fn = function( widget ){ if ( widget.reset ) widget.reset(); };\r
+ var fn = function( widget ){ if ( widget.reset ) widget.reset( 1 ); };\r
return function(){ this.foreach( fn ); return this; };\r
})(),\r
\r
children : contents.elements,\r
expand : !!contents.expand,\r
padding : contents.padding,\r
- style : contents.style || 'width: 100%; height: 100%;'\r
+ style : contents.style || 'width: 100%;'\r
}, pageHtml );\r
\r
// Create the HTML for the tab and the content block.\r
page.setAttribute( 'aria-hidden', i != id );\r
}\r
\r
- var selected = this._.tabs[id];\r
- selected[0].addClass( 'cke_dialog_tab_selected' );\r
- selected[1].show();\r
+ var selected = this._.tabs[ id ];\r
+ selected[ 0 ].addClass( 'cke_dialog_tab_selected' );\r
+\r
+ // [IE] an invisible input[type='text'] will enlarge it's width\r
+ // if it's value is long when it shows, so we clear it's value\r
+ // before it shows and then recover it (#5649)\r
+ if ( CKEDITOR.env.ie6Compat || CKEDITOR.env.ie7Compat )\r
+ {\r
+ clearOrRecoverTextInputValue( selected[ 1 ] );\r
+ selected[ 1 ].show();\r
+ setTimeout( function()\r
+ {\r
+ clearOrRecoverTextInputValue( selected[ 1 ], 1 );\r
+ }, 0 );\r
+ }\r
+ else\r
+ selected[ 1 ].show();\r
+\r
this._.currentTabId = id;\r
this._.currentTabIndex = CKEDITOR.tools.indexOf( this._.tabIdList, id );\r
},\r
hidePage : function( id )\r
{\r
var tab = this._.tabs[id] && this._.tabs[id][0];\r
- if ( !tab || this._.pageCount == 1 )\r
+ if ( !tab || this._.pageCount == 1 || !tab.isVisible() )\r
return;\r
// Switch to other tab first when we're hiding the active tab.\r
else if ( id == this._.currentTabId )\r
buttons : [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ]\r
};\r
\r
- // The buttons in MacOS Apps are in reverse order #4750\r
- CKEDITOR.env.mac && defaultDialogDefinition.buttons.reverse();\r
-\r
// Tool function used to return an item from an array based on its id\r
// property.\r
var getById = function( array, id, recurse )\r
if ( abstractDialogCoords.x + margins[3] < magnetDistance )\r
realX = - margins[3];\r
else if ( abstractDialogCoords.x - margins[1] > viewPaneSize.width - dialogSize.width - magnetDistance )\r
- realX = viewPaneSize.width - dialogSize.width + margins[1];\r
+ realX = viewPaneSize.width - dialogSize.width + ( editor.lang.dir == 'rtl' ? 0 : margins[1] );\r
else\r
realX = abstractDialogCoords.x;\r
\r
else\r
realY = abstractDialogCoords.y;\r
\r
- dialog.move( realX, realY );\r
+ dialog.move( realX, realY, 1 );\r
\r
evt.data.preventDefault();\r
}\r
\r
dialog.parts.title.on( 'mousedown', function( evt )\r
{\r
- dialog._.updateSize = true;\r
-\r
lastCoords = { x : evt.data.$.screenX, y : evt.data.$.screenY };\r
\r
CKEDITOR.document.on( 'mousemove', mouseMoveHandler );\r
\r
function initResizeHandles( dialog )\r
{\r
- var definition = dialog.definition,\r
- minWidth = definition.minWidth || 0,\r
- minHeight = definition.minHeight || 0,\r
- resizable = definition.resizable,\r
- margins = dialog.getParentEditor().skin.margins || [ 0, 0, 0, 0 ];\r
+ var def = dialog.definition,\r
+ resizable = def.resizable;\r
\r
- function topSizer( coords, dy )\r
- {\r
- coords.y += dy;\r
- }\r
+ if ( resizable == CKEDITOR.DIALOG_RESIZE_NONE )\r
+ return;\r
\r
- function rightSizer( coords, dx )\r
- {\r
- coords.x2 += dx;\r
- }\r
+ var editor = dialog.getParentEditor();\r
+ var wrapperWidth, wrapperHeight,\r
+ viewSize, origin, startSize,\r
+ dialogCover;\r
\r
- function bottomSizer( coords, dy )\r
+ function positionDialog( right )\r
{\r
- coords.y2 += dy;\r
+ // Maintain righthand sizing in RTL.\r
+ if ( dialog._.moved && editor.lang.dir == 'rtl' )\r
+ {\r
+ var element = dialog._.element.getFirst();\r
+ element.setStyle( 'right', right + "px" );\r
+ element.removeStyle( 'left' );\r
+ }\r
+ else if ( !dialog._.moved )\r
+ dialog.layout();\r
}\r
\r
- function leftSizer( coords, dx )\r
+ var mouseDownFn = CKEDITOR.tools.addFunction( function( $event )\r
{\r
- coords.x += dx;\r
- }\r
+ startSize = dialog.getSize();\r
\r
- var lastCoords = null,\r
- abstractDialogCoords = null,\r
- magnetDistance = dialog._.editor.config.magnetDistance,\r
- parts = [ 'tl', 't', 'tr', 'l', 'r', 'bl', 'b', 'br' ];\r
+ var content = dialog.parts.contents,\r
+ iframeDialog = content.$.getElementsByTagName( 'iframe' ).length;\r
\r
- function mouseDownHandler( evt )\r
- {\r
- var partName = evt.listenerData.part, size = dialog.getSize();\r
- abstractDialogCoords = dialog.getPosition();\r
- CKEDITOR.tools.extend( abstractDialogCoords,\r
- {\r
- x2 : abstractDialogCoords.x + size.width,\r
- y2 : abstractDialogCoords.y + size.height\r
- } );\r
- lastCoords = { x : evt.data.$.screenX, y : evt.data.$.screenY };\r
+ // Shim to help capturing "mousemove" over iframe.\r
+ if ( iframeDialog )\r
+ {\r
+ dialogCover = CKEDITOR.dom.element.createFromHtml( '<div class="cke_dialog_resize_cover" style="height: 100%; position: absolute; width: 100%;"></div>' );\r
+ content.append( dialogCover );\r
+ }\r
+\r
+ // Calculate the offset between content and chrome size.\r
+ wrapperHeight = startSize.height - dialog.parts.contents.getSize( 'height', ! ( CKEDITOR.env.gecko || CKEDITOR.env.opera || CKEDITOR.env.ie && CKEDITOR.env.quirks ) );\r
+ wrapperWidth = startSize.width - dialog.parts.contents.getSize( 'width', 1 );\r
\r
- CKEDITOR.document.on( 'mousemove', mouseMoveHandler, dialog, { part : partName } );\r
- CKEDITOR.document.on( 'mouseup', mouseUpHandler, dialog, { part : partName } );\r
+ origin = { x : $event.screenX, y : $event.screenY };\r
+\r
+ viewSize = CKEDITOR.document.getWindow().getViewPaneSize();\r
+\r
+ CKEDITOR.document.on( 'mousemove', mouseMoveHandler );\r
+ CKEDITOR.document.on( 'mouseup', mouseUpHandler );\r
\r
if ( CKEDITOR.env.ie6Compat )\r
{\r
var coverDoc = currentCover.getChild( 0 ).getFrameDocument();\r
- coverDoc.on( 'mousemove', mouseMoveHandler, dialog, { part : partName } );\r
- coverDoc.on( 'mouseup', mouseUpHandler, dialog, { part : partName } );\r
+ coverDoc.on( 'mousemove', mouseMoveHandler );\r
+ coverDoc.on( 'mouseup', mouseUpHandler );\r
}\r
\r
- evt.data.preventDefault();\r
- }\r
+ $event.preventDefault && $event.preventDefault();\r
+ });\r
+\r
+ // Prepend the grip to the dialog.\r
+ dialog.on( 'load', function()\r
+ {\r
+ var direction = '';\r
+ if ( resizable == CKEDITOR.DIALOG_RESIZE_WIDTH )\r
+ direction = ' cke_resizer_horizontal';\r
+ else if ( resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT )\r
+ direction = ' cke_resizer_vertical';\r
+ var resizer = CKEDITOR.dom.element.createFromHtml( '<div class="cke_resizer' + direction + '"' +\r
+ ' title="' + CKEDITOR.tools.htmlEncode( editor.lang.resize ) + '"' +\r
+ ' onmousedown="CKEDITOR.tools.callFunction(' + mouseDownFn + ', event )"></div>' );\r
+ dialog.parts.footer.append( resizer, 1 );\r
+ });\r
+ editor.on( 'destroy', function() { CKEDITOR.tools.removeFunction( mouseDownFn ); } );\r
\r
function mouseMoveHandler( evt )\r
{\r
- var x = evt.data.$.screenX,\r
- y = evt.data.$.screenY,\r
- dx = x - lastCoords.x,\r
- dy = y - lastCoords.y,\r
- viewPaneSize = CKEDITOR.document.getWindow().getViewPaneSize(),\r
- partName = evt.listenerData.part;\r
+ var rtl = editor.lang.dir == 'rtl',\r
+ dx = ( evt.data.$.screenX - origin.x ) * ( rtl ? -1 : 1 ),\r
+ dy = evt.data.$.screenY - origin.y,\r
+ width = startSize.width,\r
+ height = startSize.height,\r
+ internalWidth = width + dx * ( dialog._.moved ? 1 : 2 ),\r
+ internalHeight = height + dy * ( dialog._.moved ? 1 : 2 ),\r
+ element = dialog._.element.getFirst(),\r
+ right = rtl && element.getComputedStyle( 'right' ),\r
+ position = dialog.getPosition();\r
\r
- if ( partName.search( 't' ) != -1 )\r
- topSizer( abstractDialogCoords, dy );\r
- if ( partName.search( 'l' ) != -1 )\r
- leftSizer( abstractDialogCoords, dx );\r
- if ( partName.search( 'b' ) != -1 )\r
- bottomSizer( abstractDialogCoords, dy );\r
- if ( partName.search( 'r' ) != -1 )\r
- rightSizer( abstractDialogCoords, dx );\r
+ // IE might return "auto", we need exact position.\r
+ if ( right )\r
+ right = right == 'auto' ? viewSize.width - ( position.x || 0 ) - element.getSize( 'width' ) : parseInt( right, 10 );\r
\r
- lastCoords = { x : x, y : y };\r
+ if ( position.y + internalHeight > viewSize.height )\r
+ internalHeight = viewSize.height - position.y;\r
\r
- var realX, realY, realX2, realY2;\r
+ if ( ( rtl ? right : position.x ) + internalWidth > viewSize.width )\r
+ internalWidth = viewSize.width - ( rtl ? right : position.x );\r
\r
- if ( abstractDialogCoords.x + margins[3] < magnetDistance )\r
- realX = - margins[3];\r
- else if ( partName.search( 'l' ) != -1 && abstractDialogCoords.x2 - abstractDialogCoords.x < minWidth + magnetDistance )\r
- realX = abstractDialogCoords.x2 - minWidth;\r
- else\r
- realX = abstractDialogCoords.x;\r
+ // Make sure the dialog will not be resized to the wrong side when it's in the leftmost position for RTL.\r
+ if ( ( resizable == CKEDITOR.DIALOG_RESIZE_WIDTH || resizable == CKEDITOR.DIALOG_RESIZE_BOTH ) && !( rtl && dx > 0 && !position.x ) )\r
+ width = Math.max( def.minWidth || 0, internalWidth - wrapperWidth );\r
\r
- if ( abstractDialogCoords.y + margins[0] < magnetDistance )\r
- realY = - margins[0];\r
- else if ( partName.search( 't' ) != -1 && abstractDialogCoords.y2 - abstractDialogCoords.y < minHeight + magnetDistance )\r
- realY = abstractDialogCoords.y2 - minHeight;\r
- else\r
- realY = abstractDialogCoords.y;\r
-\r
- if ( abstractDialogCoords.x2 - margins[1] > viewPaneSize.width - magnetDistance )\r
- realX2 = viewPaneSize.width + margins[1] ;\r
- else if ( partName.search( 'r' ) != -1 && abstractDialogCoords.x2 - abstractDialogCoords.x < minWidth + magnetDistance )\r
- realX2 = abstractDialogCoords.x + minWidth;\r
- else\r
- realX2 = abstractDialogCoords.x2;\r
-\r
- if ( abstractDialogCoords.y2 - margins[2] > viewPaneSize.height - magnetDistance )\r
- realY2= viewPaneSize.height + margins[2] ;\r
- else if ( partName.search( 'b' ) != -1 && abstractDialogCoords.y2 - abstractDialogCoords.y < minHeight + magnetDistance )\r
- realY2 = abstractDialogCoords.y + minHeight;\r
- else\r
- realY2 = abstractDialogCoords.y2 ;\r
+ if ( resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT || resizable == CKEDITOR.DIALOG_RESIZE_BOTH )\r
+ height = Math.max( def.minHeight || 0, internalHeight - wrapperHeight );\r
\r
- dialog.move( realX, realY );\r
- dialog.resize( realX2 - realX, realY2 - realY );\r
+ dialog.resize( width, height );\r
+ // The right property might get broken during resizing, so computing it before the resizing.\r
+ positionDialog( right );\r
\r
evt.data.preventDefault();\r
}\r
\r
- function mouseUpHandler( evt )\r
+ function mouseUpHandler()\r
{\r
CKEDITOR.document.removeListener( 'mouseup', mouseUpHandler );\r
CKEDITOR.document.removeListener( 'mousemove', mouseMoveHandler );\r
\r
+ if ( dialogCover )\r
+ {\r
+ dialogCover.remove();\r
+ dialogCover = null;\r
+ }\r
+\r
if ( CKEDITOR.env.ie6Compat )\r
{\r
var coverDoc = currentCover.getChild( 0 ).getFrameDocument();\r
coverDoc.removeListener( 'mouseup', mouseUpHandler );\r
coverDoc.removeListener( 'mousemove', mouseMoveHandler );\r
}\r
- }\r
\r
-// TODO : Simplify the resize logic, having just a single resize grip <div>.\r
-// var widthTest = /[lr]/,\r
-// heightTest = /[tb]/;\r
-// for ( var i = 0 ; i < parts.length ; i++ )\r
-// {\r
-// var element = dialog.parts[ parts[i] + '_resize' ];\r
-// if ( resizable == CKEDITOR.DIALOG_RESIZE_NONE ||\r
-// resizable == CKEDITOR.DIALOG_RESIZE_HEIGHT && widthTest.test( parts[i] ) ||\r
-// resizable == CKEDITOR.DIALOG_RESIZE_WIDTH && heightTest.test( parts[i] ) )\r
-// {\r
-// element.hide();\r
-// continue;\r
-// }\r
-// element.on( 'mousedown', mouseDownHandler, dialog, { part : parts[i] } );\r
-// }\r
+ // Switch back to use the left property, if RTL is used.\r
+ if ( editor.lang.dir == 'rtl' )\r
+ {\r
+ var element = dialog._.element.getFirst(),\r
+ left = element.getComputedStyle( 'left' );\r
+\r
+ // IE might return "auto", we need exact position.\r
+ if ( left == 'auto' )\r
+ left = viewSize.width - parseInt( element.getStyle( 'right' ), 10 ) - dialog.getSize().width;\r
+ else\r
+ left = parseInt( left, 10 );\r
+\r
+ element.removeStyle( 'right' );\r
+ // Make sure the left property gets applied, even if it is the same as previously.\r
+ dialog._.position.x += 1;\r
+ dialog.move( left, dialog._.position.y );\r
+ }\r
+ }\r
}\r
\r
var resizeCover;\r
function showCover( editor )\r
{\r
var win = CKEDITOR.document.getWindow();\r
- var backgroundColorStyle = editor.config.dialog_backgroundCoverColor || 'white',\r
- backgroundCoverOpacity = editor.config.dialog_backgroundCoverOpacity,\r
- baseFloatZIndex = editor.config.baseFloatZIndex,\r
+ var config = editor.config,\r
+ backgroundColorStyle = config.dialog_backgroundCoverColor || 'white',\r
+ backgroundCoverOpacity = config.dialog_backgroundCoverOpacity,\r
+ baseFloatZIndex = config.baseFloatZIndex,\r
coverKey = CKEDITOR.tools.genKey(\r
backgroundColorStyle,\r
backgroundCoverOpacity,\r
if ( !coverElement )\r
{\r
var html = [\r
- '<div style="position: ', ( CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed' ),\r
+ '<div tabIndex="-1" style="position: ', ( CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed' ),\r
'; z-index: ', baseFloatZIndex,\r
'; top: 0px; left: 0px; ',\r
( !CKEDITOR.env.ie6Compat ? 'background-color: ' + backgroundColorStyle : '' ),\r
top : pos.y + 'px'\r
});\r
\r
- do\r
+ if ( cursor )\r
{\r
- var dialogPos = cursor.getPosition();\r
- cursor.move( dialogPos.x, dialogPos.y );\r
- } while ( ( cursor = cursor._.parentDialog ) );\r
+ do\r
+ {\r
+ var dialogPos = cursor.getPosition();\r
+ cursor.move( dialogPos.x, dialogPos.y );\r
+ } while ( ( cursor = cursor._.parentDialog ) );\r
+ }\r
};\r
\r
resizeCover = resizeFunc;\r
win.on( 'resize', resizeFunc );\r
resizeFunc();\r
+ // Using Safari/Mac, focus must be kept where it is (#7027)\r
+ if ( !( CKEDITOR.env.mac && CKEDITOR.env.webkit ) )\r
+ coverElement.focus();\r
+\r
if ( CKEDITOR.env.ie6Compat )\r
{\r
// IE BUG: win.$.onscroll assignment doesn't work.. it must be window.onscroll.\r
if ( widths )\r
{\r
if ( widths[i] )\r
- styles.push( 'width:' + CKEDITOR.tools.cssLength( widths[i] ) );\r
+ styles.push( 'width:' + cssLength( widths[i] ) );\r
}\r
else\r
styles.push( 'width:' + Math.floor( 100 / childHtmlList.length ) + '%' );\r
if ( height )\r
- styles.push( 'height:' + CKEDITOR.tools.cssLength( height ) );\r
+ styles.push( 'height:' + cssLength( height ) );\r
if ( elementDefinition && elementDefinition.padding != undefined )\r
- styles.push( 'padding:' + CKEDITOR.tools.cssLength( elementDefinition.padding ) );\r
+ styles.push( 'padding:' + cssLength( elementDefinition.padding ) );\r
if ( styles.length > 0 )\r
html.push( 'style="' + styles.join('; ') + '" ' );\r
html.push( '>', childHtmlList[i], '</td>' );\r
*/\r
vbox : function( dialog, childObjList, childHtmlList, htmlList, elementDefinition )\r
{\r
- if (arguments.length < 3 )\r
+ if ( arguments.length < 3 )\r
return;\r
\r
this._ || ( this._ = {} );\r
html.push( 'style="' );\r
if ( elementDefinition && elementDefinition.expand )\r
html.push( 'height:100%;' );\r
- html.push( 'width:' + CKEDITOR.tools.cssLength( width || '100%' ), ';' );\r
+ html.push( 'width:' + cssLength( width || '100%' ), ';' );\r
html.push( '"' );\r
html.push( 'align="', CKEDITOR.tools.htmlEncode(\r
( elementDefinition && elementDefinition.align ) || ( dialog.getParentEditor().lang.dir == 'ltr' ? 'left' : 'right' ) ), '" ' );\r
var styles = [];\r
html.push( '<tr><td role="presentation" ' );\r
if ( width )\r
- styles.push( 'width:' + CKEDITOR.tools.cssLength( width || '100%' ) );\r
+ styles.push( 'width:' + cssLength( width || '100%' ) );\r
if ( heights )\r
- styles.push( 'height:' + CKEDITOR.tools.cssLength( heights[i] ) );\r
+ styles.push( 'height:' + cssLength( heights[i] ) );\r
else if ( elementDefinition && elementDefinition.expand )\r
styles.push( 'height:' + Math.floor( 100 / childHtmlList.length ) + '%' );\r
if ( elementDefinition && elementDefinition.padding != undefined )\r
- styles.push( 'padding:' + CKEDITOR.tools.cssLength( elementDefinition.padding ) );\r
+ styles.push( 'padding:' + cssLength( elementDefinition.padding ) );\r
if ( styles.length > 0 )\r
html.push( 'style="', styles.join( '; ' ), '" ' );\r
html.push( ' class="cke_dialog_ui_vbox_child">', childHtmlList[i], '</td></tr>' );\r
/**\r
* Sets the value of this dialog UI object.\r
* @param {Object} value The new value.\r
+ * @param {Boolean} noChangeEvent Internal commit, to supress 'change' event on this element.\r
* @returns {CKEDITOR.dialog.uiElement} The current UI element.\r
* @example\r
* uiElement.setValue( 'Dingo' );\r
*/\r
- setValue : function( value )\r
+ setValue : function( value, noChangeEvent )\r
{\r
this.getInputElement().setValue( value );\r
- this.fire( 'change', { value : value } );\r
+ !noChangeEvent && this.fire( 'change', { value : value } );\r
return this;\r
},\r
\r
});\r
\r
})();\r
-})();\r
\r
-// Extend the CKEDITOR.editor class with dialog specific functions.\r
-CKEDITOR.tools.extend( CKEDITOR.editor.prototype,\r
- /** @lends CKEDITOR.editor.prototype */\r
- {\r
- /**\r
- * Loads and opens a registered dialog.\r
- * @param {String} dialogName The registered name of the dialog.\r
- * @param {Function} callback The function to be invoked after dialog instance created.\r
- * @see CKEDITOR.dialog.add\r
- * @example\r
- * CKEDITOR.instances.editor1.openDialog( 'smiley' );\r
- * @returns {CKEDITOR.dialog} The dialog object corresponding to the dialog displayed. null if the dialog name is not registered.\r
- */\r
- openDialog : function( dialogName, callback )\r
+ // Extend the CKEDITOR.editor class with dialog specific functions.\r
+ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,\r
+ /** @lends CKEDITOR.editor.prototype */\r
{\r
- var dialogDefinitions = CKEDITOR.dialog._.dialogDefinitions[ dialogName ],\r
- dialogSkin = this.skin.dialog;\r
-\r
- // If the dialogDefinition is already loaded, open it immediately.\r
- if ( typeof dialogDefinitions == 'function' && dialogSkin._isLoaded )\r
+ /**\r
+ * Loads and opens a registered dialog.\r
+ * @param {String} dialogName The registered name of the dialog.\r
+ * @param {Function} callback The function to be invoked after dialog instance created.\r
+ * @see CKEDITOR.dialog.add\r
+ * @example\r
+ * CKEDITOR.instances.editor1.openDialog( 'smiley' );\r
+ * @returns {CKEDITOR.dialog} The dialog object corresponding to the dialog displayed. null if the dialog name is not registered.\r
+ */\r
+ openDialog : function( dialogName, callback )\r
{\r
- var storedDialogs = this._.storedDialogs ||\r
- ( this._.storedDialogs = {} );\r
+ if ( this.mode == 'wysiwyg' && CKEDITOR.env.ie )\r
+ {\r
+ var selection = this.getSelection();\r
+ selection && selection.lock();\r
+ }\r
\r
- var dialog = storedDialogs[ dialogName ] ||\r
- ( storedDialogs[ dialogName ] = new CKEDITOR.dialog( this, dialogName ) );\r
+ var dialogDefinitions = CKEDITOR.dialog._.dialogDefinitions[ dialogName ],\r
+ dialogSkin = this.skin.dialog;\r
\r
- callback && callback.call( dialog, dialog );\r
- dialog.show();\r
+ if ( CKEDITOR.dialog._.currentTop === null )\r
+ showCover( this );\r
\r
- return dialog;\r
- }\r
- else if ( dialogDefinitions == 'failed' )\r
- throw new Error( '[CKEDITOR.dialog.openDialog] Dialog "' + dialogName + '" failed when loading definition.' );\r
+ // If the dialogDefinition is already loaded, open it immediately.\r
+ if ( typeof dialogDefinitions == 'function' && dialogSkin._isLoaded )\r
+ {\r
+ var storedDialogs = this._.storedDialogs ||\r
+ ( this._.storedDialogs = {} );\r
\r
- // Not loaded? Load the .js file first.\r
- var body = CKEDITOR.document.getBody(),\r
- cursor = body.$.style.cursor,\r
- me = this;\r
+ var dialog = storedDialogs[ dialogName ] ||\r
+ ( storedDialogs[ dialogName ] = new CKEDITOR.dialog( this, dialogName ) );\r
\r
- body.setStyle( 'cursor', 'wait' );\r
+ callback && callback.call( dialog, dialog );\r
+ dialog.show();\r
\r
- function onDialogFileLoaded( success )\r
- {\r
- var dialogDefinition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ],\r
- skin = me.skin.dialog;\r
+ return dialog;\r
+ }\r
+ else if ( dialogDefinitions == 'failed' )\r
+ throw new Error( '[CKEDITOR.dialog.openDialog] Dialog "' + dialogName + '" failed when loading definition.' );\r
\r
- // Check if both skin part and definition is loaded.\r
- if ( !skin._isLoaded || loadDefinition && typeof success == 'undefined' )\r
- return;\r
+ var me = this;\r
\r
- // In case of plugin error, mark it as loading failed.\r
- if ( typeof dialogDefinition != 'function' )\r
- CKEDITOR.dialog._.dialogDefinitions[ dialogName ] = 'failed';\r
+ function onDialogFileLoaded( success )\r
+ {\r
+ var dialogDefinition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ],\r
+ skin = me.skin.dialog;\r
\r
- me.openDialog( dialogName, callback );\r
- body.setStyle( 'cursor', cursor );\r
- }\r
+ // Check if both skin part and definition is loaded.\r
+ if ( !skin._isLoaded || loadDefinition && typeof success == 'undefined' )\r
+ return;\r
\r
- if ( typeof dialogDefinitions == 'string' )\r
- {\r
- var loadDefinition = 1;\r
- CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( dialogDefinitions ), onDialogFileLoaded );\r
- }\r
+ // In case of plugin error, mark it as loading failed.\r
+ if ( typeof dialogDefinition != 'function' )\r
+ CKEDITOR.dialog._.dialogDefinitions[ dialogName ] = 'failed';\r
\r
- CKEDITOR.skins.load( this, 'dialog', onDialogFileLoaded );\r
+ me.openDialog( dialogName, callback );\r
+ }\r
\r
- return null;\r
- }\r
- });\r
+ if ( typeof dialogDefinitions == 'string' )\r
+ {\r
+ var loadDefinition = 1;\r
+ CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( dialogDefinitions ), onDialogFileLoaded, null, 0, 1 );\r
+ }\r
+\r
+ CKEDITOR.skins.load( this, 'dialog', onDialogFileLoaded );\r
+\r
+ return null;\r
+ }\r
+ });\r
+})();\r
\r
CKEDITOR.plugins.add( 'dialog',\r
{\r
*/\r
\r
/**\r
+ * The guideline to follow when generating the dialog buttons. There are 3 possible options:\r
+ * <ul>\r
+ * <li>'OS' - the buttons will be displayed in the default order of the user's OS;</li>\r
+ * <li>'ltr' - for Left-To-Right order;</li>\r
+ * <li>'rtl' - for Right-To-Left order.</li>\r
+ * </ul>\r
+ * @name CKEDITOR.config.dialog_buttonsOrder\r
+ * @type String\r
+ * @default 'OS'\r
+ * @since 3.5\r
+ * @example\r
+ * config.dialog_buttonsOrder = 'rtl';\r
+ */\r
+\r
+/**\r
+ * The dialog contents to removed. It's a string composed by dialog name and tab name with a colon between them.\r
+ * Separate each pair with semicolon (see example).\r
+ * <b>Note: All names are case-sensitive.</b>\r
+ * <b>Note: Be cautious when specifying dialog tabs that are mandatory, like "info", dialog functionality might be broken because of this!</b>\r
+ * @name CKEDITOR.config.removeDialogTabs\r
+ * @type String\r
+ * @since 3.5\r
+ * @default ''\r
+ * @example\r
+ * config.removeDialogTabs = 'flash:advanced;image:Link';\r
+ */\r
+\r
+/**\r
* Fired when a dialog definition is about to be used to create a dialog into\r
* an editor instance. This event makes it possible to customize the definition\r
* before creating it.\r
\r
/**\r
* Fired when a tab is going to be selected in a dialog\r
- * @name dialog#selectPage\r
+ * @name CKEDITOR.dialog#selectPage\r
+ * @event\r
+ * @param {String} page The id of the page that it's gonna be selected.\r
+ * @param {String} currentPage The id of the current page.\r
+ */\r
+\r
+/**\r
+ * Fired when the user tries to dismiss a dialog\r
+ * @name CKEDITOR.dialog#cancel\r
+ * @event\r
+ * @param {Boolean} hide Whether the event should proceed or not.\r
+ */\r
+\r
+/**\r
+ * Fired when the user tries to confirm a dialog\r
+ * @name CKEDITOR.dialog#ok\r
+ * @event\r
+ * @param {Boolean} hide Whether the event should proceed or not.\r
+ */\r
+\r
+/**\r
+ * Fired when a dialog is shown\r
+ * @name CKEDITOR.dialog#show\r
+ * @event\r
+ */\r
+\r
+/**\r
+ * Fired when a dialog is shown\r
+ * @name CKEDITOR.editor#dialogShow\r
+ * @event\r
+ */\r
+\r
+/**\r
+ * Fired when a dialog is hidden\r
+ * @name CKEDITOR.dialog#hide\r
+ * @event\r
+ */\r
+\r
+/**\r
+ * Fired when a dialog is hidden\r
+ * @name CKEDITOR.editor#dialogHide\r
+ * @event\r
+ */\r
+\r
+/**\r
+ * Fired when a dialog is being resized. The event is fired on\r
+ * the 'CKEDITOR.dialog' object, not a dialog instance.\r
+ * @name CKEDITOR.dialog#resize\r
+ * @since 3.5\r
* @event\r
- * @param String page The id of the page that it's gonna be selected.\r
- * @param String currentPage The id of the current page.\r
+ * @param {CKEDITOR.dialog} dialog The dialog being resized.\r
+ * @param {String} skin The skin name.\r
+ * @param {Number} width The new width.\r
+ * @param {Number} height The new height.\r
*/\r