2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
7 * @fileOverview The floating dialog plugin.
11 * No resize for this dialog.
14 CKEDITOR
.DIALOG_RESIZE_NONE
= 0;
17 * Only allow horizontal resizing for this dialog, disable vertical resizing.
20 CKEDITOR
.DIALOG_RESIZE_WIDTH
= 1;
23 * Only allow vertical resizing for this dialog, disable horizontal resizing.
26 CKEDITOR
.DIALOG_RESIZE_HEIGHT
= 2;
29 * Allow the dialog to be resized in both directions.
32 CKEDITOR
.DIALOG_RESIZE_BOTH
= 3;
36 var cssLength
= CKEDITOR
.tools
.cssLength
;
37 function isTabVisible( tabId
)
39 return !!this._
.tabs
[ tabId
][ 0 ].$.offsetHeight
;
42 function getPreviousVisibleTab()
44 var tabId
= this._
.currentTabId
,
45 length
= this._
.tabIdList
.length
,
46 tabIndex
= CKEDITOR
.tools
.indexOf( this._
.tabIdList
, tabId
) + length
;
48 for ( var i
= tabIndex
- 1 ; i
> tabIndex
- length
; i
-- )
50 if ( isTabVisible
.call( this, this._
.tabIdList
[ i
% length
] ) )
51 return this._
.tabIdList
[ i
% length
];
57 function getNextVisibleTab()
59 var tabId
= this._
.currentTabId
,
60 length
= this._
.tabIdList
.length
,
61 tabIndex
= CKEDITOR
.tools
.indexOf( this._
.tabIdList
, tabId
);
63 for ( var i
= tabIndex
+ 1 ; i
< tabIndex
+ length
; i
++ )
65 if ( isTabVisible
.call( this, this._
.tabIdList
[ i
% length
] ) )
66 return this._
.tabIdList
[ i
% length
];
73 function clearOrRecoverTextInputValue( container
, isRecover
)
75 var inputs
= container
.$.getElementsByTagName( 'input' );
76 for ( var i
= 0, length
= inputs
.length
; i
< length
; i
++ )
78 var item
= new CKEDITOR
.dom
.element( inputs
[ i
] );
80 if ( item
.getAttribute( 'type' ).toLowerCase() == 'text' )
84 item
.setAttribute( 'value', item
.getCustomData( 'fake_value' ) || '' );
85 item
.removeCustomData( 'fake_value' );
89 item
.setCustomData( 'fake_value', item
.getAttribute( 'value' ) );
90 item
.setAttribute( 'value', '' );
96 // Handle dialog element validation state UI changes.
97 function handleFieldValidated( isValid
, msg
)
99 var input
= this.getInputElement();
102 isValid
? input
.removeAttribute( 'aria-invalid' )
103 : input
.setAttribute( 'aria-invalid', true );
116 this.fire( 'validated', { valid
: isValid
, msg
: msg
} );
119 function resetField()
121 var input
= this.getInputElement();
122 input
&& input
.removeAttribute( 'aria-invalid' );
127 * This is the base class for runtime dialog objects. An instance of this
128 * class represents a single named dialog for a single editor instance.
129 * @param {Object} editor The editor which created the dialog.
130 * @param {String} dialogName The dialog's registered name.
133 * var dialogObj = new CKEDITOR.dialog( editor, 'smiley' );
135 CKEDITOR
.dialog = function( editor
, dialogName
)
137 // Load the dialog definition.
138 var definition
= CKEDITOR
.dialog
._
.dialogDefinitions
[ dialogName
],
139 defaultDefinition
= CKEDITOR
.tools
.clone( defaultDialogDefinition
),
140 buttonsOrder
= editor
.config
.dialog_buttonsOrder
|| 'OS',
141 dir
= editor
.lang
.dir
;
143 if ( ( buttonsOrder
== 'OS' && CKEDITOR
.env
.mac
) || // The buttons in MacOS Apps are in reverse order (#4750)
144 ( buttonsOrder
== 'rtl' && dir
== 'ltr' ) ||
145 ( buttonsOrder
== 'ltr' && dir
== 'rtl' ) )
146 defaultDefinition
.buttons
.reverse();
149 // Completes the definition with the default values.
150 definition
= CKEDITOR
.tools
.extend( definition( editor
), defaultDefinition
);
152 // Clone a functionally independent copy for this dialog.
153 definition
= CKEDITOR
.tools
.clone( definition
);
155 // Create a complex definition object, extending it with the API
157 definition
= new definitionObject( this, definition
);
159 var doc
= CKEDITOR
.document
;
161 var themeBuilt
= editor
.theme
.buildDialog( editor
);
163 // Initialize some basic parameters.
167 element
: themeBuilt
.element
,
169 contentSize
: { width
: 0, height
: 0 },
170 size
: { width
: 0, height
: 0 },
175 // Initialize the tab and page map.
179 currentTabIndex
: null,
184 // Initialize the tab order array for input widgets.
186 currentFocusIndex
: 0,
190 this.parts
= themeBuilt
.parts
;
192 CKEDITOR
.tools
.setTimeout( function()
194 editor
.fire( 'ariaWidget', this.parts
.contents
);
198 // Set the startup styles for the dialog, avoiding it enlarging the
199 // page size on the dialog creation.
201 position
: CKEDITOR
.env
.ie6Compat
? 'absolute' : 'fixed',
203 visibility
: 'hidden'
206 startStyles
[ dir
== 'rtl' ? 'right' : 'left' ] = 0;
207 this.parts
.dialog
.setStyles( startStyles
);
210 // Call the CKEDITOR.event constructor to initialize this instance.
211 CKEDITOR
.event
.call( this );
213 // Fire the "dialogDefinition" event, making it possible to customize
214 // the dialog definition.
215 this.definition
= definition
= CKEDITOR
.fire( 'dialogDefinition',
218 definition
: definition
220 , editor
).definition
;
222 var tabsToRemove
= {};
223 // Cache tabs that should be removed.
224 if ( !( 'removeDialogTabs' in editor
._
) && editor
.config
.removeDialogTabs
)
226 var removeContents
= editor
.config
.removeDialogTabs
.split( ';' );
228 for ( i
= 0; i
< removeContents
.length
; i
++ )
230 var parts
= removeContents
[ i
].split( ':' );
231 if ( parts
.length
== 2 )
233 var removeDialogName
= parts
[ 0 ];
234 if ( !tabsToRemove
[ removeDialogName
] )
235 tabsToRemove
[ removeDialogName
] = [];
236 tabsToRemove
[ removeDialogName
].push( parts
[ 1 ] );
239 editor
._
.removeDialogTabs
= tabsToRemove
;
242 // Remove tabs of this dialog.
243 if ( editor
._
.removeDialogTabs
&& ( tabsToRemove
= editor
._
.removeDialogTabs
[ dialogName
] ) )
245 for ( i
= 0; i
< tabsToRemove
.length
; i
++ )
246 definition
.removeContents( tabsToRemove
[ i
] );
249 // Initialize load, show, hide, ok and cancel events.
250 if ( definition
.onLoad
)
251 this.on( 'load', definition
.onLoad
);
253 if ( definition
.onShow
)
254 this.on( 'show', definition
.onShow
);
256 if ( definition
.onHide
)
257 this.on( 'hide', definition
.onHide
);
259 if ( definition
.onOk
)
261 this.on( 'ok', function( evt
)
263 // Dialog confirm might probably introduce content changes (#5415).
264 editor
.fire( 'saveSnapshot' );
265 setTimeout( function () { editor
.fire( 'saveSnapshot' ); }, 0 );
266 if ( definition
.onOk
.call( this, evt
) === false )
267 evt
.data
.hide
= false;
271 if ( definition
.onCancel
)
273 this.on( 'cancel', function( evt
)
275 if ( definition
.onCancel
.call( this, evt
) === false )
276 evt
.data
.hide
= false;
282 // Iterates over all items inside all content in the dialog, calling a
283 // function for each of them.
284 var iterContents = function( func
)
286 var contents
= me
._
.contents
,
289 for ( var i
in contents
)
291 for ( var j
in contents
[i
] )
293 stop
= func
.call( this, contents
[i
][j
] );
300 this.on( 'ok', function( evt
)
302 iterContents( function( item
)
306 var retval
= item
.validate( this ),
307 invalid
= typeof ( retval
) == 'string' || retval
=== false;
311 evt
.data
.hide
= false;
315 handleFieldValidated
.call( item
, !invalid
, typeof retval
== 'string' ? retval
: undefined );
321 this.on( 'cancel', function( evt
)
323 iterContents( function( item
)
325 if ( item
.isChanged() )
327 if ( !confirm( editor
.lang
.common
.confirmCancel
) )
328 evt
.data
.hide
= false;
334 this.parts
.close
.on( 'click', function( evt
)
336 if ( this.fire( 'cancel', { hide
: true } ).hide
!== false )
338 evt
.data
.preventDefault();
341 // Sort focus list according to tab order definitions.
342 function setupFocus()
344 var focusList
= me
._
.focusList
;
345 focusList
.sort( function( a
, b
)
347 // Mimics browser tab order logics;
348 if ( a
.tabIndex
!= b
.tabIndex
)
349 return b
.tabIndex
- a
.tabIndex
;
350 // Sort is not stable in some browsers,
351 // fall-back the comparator to 'focusIndex';
353 return a
.focusIndex
- b
.focusIndex
;
356 var size
= focusList
.length
;
357 for ( var i
= 0; i
< size
; i
++ )
358 focusList
[ i
].focusIndex
= i
;
361 function changeFocus( forward
)
363 var focusList
= me
._
.focusList
,
364 offset
= forward
? 1 : -1;
365 if ( focusList
.length
< 1 )
368 var current
= me
._
.currentFocusIndex
;
370 // Trigger the 'blur' event of any input element before anything,
371 // since certain UI updates may depend on it.
374 focusList
[ current
].getInputElement().$.blur();
378 var startIndex
= ( current
+ offset
+ focusList
.length
) % focusList
.length
,
379 currentIndex
= startIndex
;
380 while ( !focusList
[ currentIndex
].isFocusable() )
382 currentIndex
= ( currentIndex
+ offset
+ focusList
.length
) % focusList
.length
;
383 if ( currentIndex
== startIndex
)
386 focusList
[ currentIndex
].focus();
388 // Select whole field content.
389 if ( focusList
[ currentIndex
].type
== 'text' )
390 focusList
[ currentIndex
].select();
393 this.changeFocus
= changeFocus
;
397 function focusKeydownHandler( evt
)
399 // If I'm not the top dialog, ignore.
400 if ( me
!= CKEDITOR
.dialog
._
.currentTop
)
403 var keystroke
= evt
.data
.getKeystroke(),
404 rtl
= editor
.lang
.dir
== 'rtl';
407 if ( keystroke
== 9 || keystroke
== CKEDITOR
.SHIFT
+ 9 )
409 var shiftPressed
= ( keystroke
== CKEDITOR
.SHIFT
+ 9 );
411 // Handling Tab and Shift-Tab.
412 if ( me
._
.tabBarMode
)
415 var nextId
= shiftPressed
? getPreviousVisibleTab
.call( me
) : getNextVisibleTab
.call( me
);
416 me
.selectPage( nextId
);
417 me
._
.tabs
[ nextId
][ 0 ].focus();
421 // Change the focus of inputs.
422 changeFocus( !shiftPressed
);
427 else if ( keystroke
== CKEDITOR
.ALT
+ 121 && !me
._
.tabBarMode
&& me
.getPageCount() > 1 )
429 // Alt-F10 puts focus into the current tab item in the tab bar.
430 me
._
.tabBarMode
= true;
431 me
._
.tabs
[ me
._
.currentTabId
][ 0 ].focus();
434 else if ( ( keystroke
== 37 || keystroke
== 39 ) && me
._
.tabBarMode
)
436 // Arrow keys - used for changing tabs.
437 nextId
= ( keystroke
== ( rtl
? 39 : 37 ) ? getPreviousVisibleTab
.call( me
) : getNextVisibleTab
.call( me
) );
438 me
.selectPage( nextId
);
439 me
._
.tabs
[ nextId
][ 0 ].focus();
442 else if ( ( keystroke
== 13 || keystroke
== 32 ) && me
._
.tabBarMode
)
444 this.selectPage( this._
.currentTabId
);
445 this._
.tabBarMode
= false;
446 this._
.currentFocusIndex
= -1;
454 evt
.data
.preventDefault();
458 function focusKeyPressHandler( evt
)
460 processed
&& evt
.data
.preventDefault();
463 var dialogElement
= this._
.element
;
464 // Add the dialog keyboard handlers.
465 this.on( 'show', function()
467 dialogElement
.on( 'keydown', focusKeydownHandler
, this, null, 0 );
468 // Some browsers instead, don't cancel key events in the keydown, but in the
469 // keypress. So we must do a longer trip in those cases. (#4531)
470 if ( CKEDITOR
.env
.opera
|| ( CKEDITOR
.env
.gecko
&& CKEDITOR
.env
.mac
) )
471 dialogElement
.on( 'keypress', focusKeyPressHandler
, this );
474 this.on( 'hide', function()
476 dialogElement
.removeListener( 'keydown', focusKeydownHandler
);
477 if ( CKEDITOR
.env
.opera
|| ( CKEDITOR
.env
.gecko
&& CKEDITOR
.env
.mac
) )
478 dialogElement
.removeListener( 'keypress', focusKeyPressHandler
);
480 // Reset fields state when closing dialog.
481 iterContents( function( item
) { resetField
.apply( item
); } );
483 this.on( 'iframeAdded', function( evt
)
485 var doc
= new CKEDITOR
.dom
.document( evt
.data
.iframe
.$.contentWindow
.document
);
486 doc
.on( 'keydown', focusKeydownHandler
, this, null, 0 );
489 // Auto-focus logic in dialog.
490 this.on( 'show', function()
492 // Setup tabIndex on showing the dialog instead of on loading
493 // to allow dynamic tab order happen in dialog definition.
496 if ( editor
.config
.dialog_startupFocusTab
497 && me
._
.pageCount
> 1 )
499 me
._
.tabBarMode
= true;
500 me
._
.tabs
[ me
._
.currentTabId
][ 0 ].focus();
502 else if ( !this._
.hasFocus
)
504 this._
.currentFocusIndex
= -1;
506 // Decide where to put the initial focus.
507 if ( definition
.onFocus
)
509 var initialFocus
= definition
.onFocus
.call( this );
510 // Focus the field that the user specified.
511 initialFocus
&& initialFocus
.focus();
513 // Focus the first field in layout order.
518 * IE BUG: If the initial focus went into a non-text element (e.g. button),
519 * then IE would still leave the caret inside the editing area.
521 if ( this._
.editor
.mode
== 'wysiwyg' && CKEDITOR
.env
.ie
)
523 var $selection
= editor
.document
.$.selection
,
524 $range
= $selection
.createRange();
528 if ( $range
.parentElement
&& $range
.parentElement().ownerDocument
== editor
.document
.$
529 || $range
.item
&& $range
.item( 0 ).ownerDocument
== editor
.document
.$ )
531 var $myRange
= document
.body
.createTextRange();
532 $myRange
.moveToElementText( this.getElement().getFirst().$ );
533 $myRange
.collapse( true );
539 }, this, null, 0xffffffff );
541 // IE6 BUG: Text fields and text areas are only half-rendered the first time the dialog appears in IE6 (#2661).
542 // This is still needed after [2708] and [2709] because text fields in hidden TR tags are still broken.
543 if ( CKEDITOR
.env
.ie6Compat
)
545 this.on( 'load', function( evt
)
547 var outer
= this.getElement(),
548 inner
= outer
.getFirst();
550 inner
.appendTo( outer
);
554 initDragAndDrop( this );
555 initResizeHandles( this );
558 ( new CKEDITOR
.dom
.text( definition
.title
, CKEDITOR
.document
) ).appendTo( this.parts
.title
);
560 // Insert the tabs and contents.
561 for ( var i
= 0 ; i
< definition
.contents
.length
; i
++ )
563 var page
= definition
.contents
[i
];
564 page
&& this.addPage( page
);
567 this.parts
[ 'tabs' ].on( 'click', function( evt
)
569 var target
= evt
.data
.getTarget();
570 // If we aren't inside a tab, bail out.
571 if ( target
.hasClass( 'cke_dialog_tab' ) )
573 // Get the ID of the tab, without the 'cke_' prefix and the unique number suffix.
574 var id
= target
.$.id
;
575 this.selectPage( id
.substring( 4, id
.lastIndexOf( '_' ) ) );
577 if ( this._
.tabBarMode
)
579 this._
.tabBarMode
= false;
580 this._
.currentFocusIndex
= -1;
583 evt
.data
.preventDefault();
588 var buttonsHtml
= [],
589 buttons
= CKEDITOR
.dialog
._
.uiElementBuilders
.hbox
.build( this,
592 className
: 'cke_dialog_footer_buttons',
594 children
: definition
.buttons
595 }, buttonsHtml
).getChild();
596 this.parts
.footer
.setHtml( buttonsHtml
.join( '' ) );
598 for ( i
= 0 ; i
< buttons
.length
; i
++ )
599 this._
.buttons
[ buttons
[i
].id
] = buttons
[i
];
602 // Focusable interface. Use it via dialog.addFocusable.
603 function Focusable( dialog
, element
, index
)
605 this.element
= element
;
606 this.focusIndex
= index
;
607 // TODO: support tabIndex for focusables.
609 this.isFocusable = function()
611 return !element
.getAttribute( 'disabled' ) && element
.isVisible();
613 this.focus = function()
615 dialog
._
.currentFocusIndex
= this.focusIndex
;
616 this.element
.focus();
619 element
.on( 'keydown', function( e
)
621 if ( e
.data
.getKeystroke() in { 32:1, 13:1 } )
622 this.fire( 'click' );
624 element
.on( 'focus', function()
626 this.fire( 'mouseover' );
628 element
.on( 'blur', function()
630 this.fire( 'mouseout' );
634 CKEDITOR
.dialog
.prototype =
639 this._
.element
.remove();
643 * Resizes the dialog.
644 * @param {Number} width The width of the dialog in pixels.
645 * @param {Number} height The height of the dialog in pixels.
648 * dialogObj.resize( 800, 640 );
652 return function( width
, height
)
654 if ( this._
.contentSize
&& this._
.contentSize
.width
== width
&& this._
.contentSize
.height
== height
)
657 CKEDITOR
.dialog
.fire( 'resize',
660 skin
: this._
.editor
.skinName
,
667 skin
: this._
.editor
.skinName
,
672 // Update dialog position when dimension get changed in RTL.
673 if ( this._
.editor
.lang
.dir
== 'rtl' && this._
.position
)
674 this._
.position
.x
= CKEDITOR
.document
.getWindow().getViewPaneSize().width
-
675 this._
.contentSize
.width
- parseInt( this._
.element
.getFirst().getStyle( 'right' ), 10 );
677 this._
.contentSize
= { width
: width
, height
: height
};
682 * Gets the current size of the dialog in pixels.
683 * @returns {Object} An object with "width" and "height" properties.
685 * var width = dialogObj.getSize().width;
689 var element
= this._
.element
.getFirst();
690 return { width
: element
.$.offsetWidth
|| 0, height
: element
.$.offsetHeight
|| 0};
694 * Moves the dialog to an (x, y) coordinate relative to the window.
696 * @param {Number} x The target x-coordinate.
697 * @param {Number} y The target y-coordinate.
698 * @param {Boolean} save Flag indicate whether the dialog position should be remembered on next open up.
700 * dialogObj.move( 10, 40 );
705 return function( x
, y
, save
)
707 // The dialog may be fixed positioned or absolute positioned. Ask the
708 // browser what is the current situation first.
709 var element
= this._
.element
.getFirst(),
710 rtl
= this._
.editor
.lang
.dir
== 'rtl';
712 if ( isFixed
=== undefined )
713 isFixed
= element
.getComputedStyle( 'position' ) == 'fixed';
715 if ( isFixed
&& this._
.position
&& this._
.position
.x
== x
&& this._
.position
.y
== y
)
718 // Save the current position.
719 this._
.position
= { x
: x
, y
: y
};
721 // If not fixed positioned, add scroll position to the coordinates.
724 var scrollPosition
= CKEDITOR
.document
.getWindow().getScrollPosition();
725 x
+= scrollPosition
.x
;
726 y
+= scrollPosition
.y
;
729 // Translate coordinate for RTL.
732 var dialogSize
= this.getSize(),
733 viewPaneSize
= CKEDITOR
.document
.getWindow().getViewPaneSize();
734 x
= viewPaneSize
.width
- dialogSize
.width
- x
;
737 var styles
= { 'top' : ( y
> 0 ? y
: 0 ) + 'px' };
738 styles
[ rtl
? 'right' : 'left' ] = ( x
> 0 ? x
: 0 ) + 'px';
740 element
.setStyles( styles
);
742 save
&& ( this._
.moved
= 1 );
747 * Gets the dialog's position in the window.
748 * @returns {Object} An object with "x" and "y" properties.
750 * var dialogX = dialogObj.getPosition().x;
752 getPosition : function(){ return CKEDITOR
.tools
.extend( {}, this._
.position
); },
755 * Shows the dialog box.
761 // Insert the dialog's element to the root document.
762 var element
= this._
.element
;
763 var definition
= this.definition
;
764 if ( !( element
.getParent() && element
.getParent().equals( CKEDITOR
.document
.getBody() ) ) )
765 element
.appendTo( CKEDITOR
.document
.getBody() );
767 element
.setStyle( 'display', 'block' );
769 // FIREFOX BUG: Fix vanishing caret for Firefox 2 or Gecko 1.8.
770 if ( CKEDITOR
.env
.gecko
&& CKEDITOR
.env
.version
< 10900 )
772 var dialogElement
= this.parts
.dialog
;
773 dialogElement
.setStyle( 'position', 'absolute' );
774 setTimeout( function()
776 dialogElement
.setStyle( 'position', 'fixed' );
781 // First, set the dialog to an appropriate size.
782 this.resize( this._
.contentSize
&& this._
.contentSize
.width
|| definition
.width
|| definition
.minWidth
,
783 this._
.contentSize
&& this._
.contentSize
.height
|| definition
.height
|| definition
.minHeight
);
785 // Reset all inputs back to their default value.
788 // Select the first tab by default.
789 this.selectPage( this.definition
.contents
[0].id
);
792 if ( CKEDITOR
.dialog
._
.currentZIndex
=== null )
793 CKEDITOR
.dialog
._
.currentZIndex
= this._
.editor
.config
.baseFloatZIndex
;
794 this._
.element
.getFirst().setStyle( 'z-index', CKEDITOR
.dialog
._
.currentZIndex
+= 10 );
796 // Maintain the dialog ordering and dialog cover.
797 // Also register key handlers if first dialog.
798 if ( CKEDITOR
.dialog
._
.currentTop
=== null )
800 CKEDITOR
.dialog
._
.currentTop
= this;
801 this._
.parentDialog
= null;
802 showCover( this._
.editor
);
804 element
.on( 'keydown', accessKeyDownHandler
);
805 element
.on( CKEDITOR
.env
.opera
? 'keypress' : 'keyup', accessKeyUpHandler
);
807 // Prevent some keys from bubbling up. (#4269)
808 for ( var event
in { keyup
:1, keydown
:1, keypress
:1 } )
809 element
.on( event
, preventKeyBubbling
);
813 this._
.parentDialog
= CKEDITOR
.dialog
._
.currentTop
;
814 var parentElement
= this._
.parentDialog
.getElement().getFirst();
815 parentElement
.$.style
.zIndex
-= Math
.floor( this._
.editor
.config
.baseFloatZIndex
/ 2 );
816 CKEDITOR
.dialog
._
.currentTop
= this;
819 // Register the Esc hotkeys.
820 registerAccessKey( this, this, '\x1b', null, function()
822 this.getButton( 'cancel' ) && this.getButton( 'cancel' ).click();
825 // Reset the hasFocus state.
826 this._
.hasFocus
= false;
828 CKEDITOR
.tools
.setTimeout( function()
831 this.parts
.dialog
.setStyle( 'visibility', '' );
833 // Execute onLoad for the first show.
834 this.fireOnce( 'load', {} );
835 CKEDITOR
.ui
.fire( 'ready', this );
837 this.fire( 'show', {} );
838 this._
.editor
.fire( 'dialogShow', this );
840 // Save the initial values of the dialog.
841 this.foreach( function( contentObj
) { contentObj
.setInitValue
&& contentObj
.setInitValue(); } );
848 * Rearrange the dialog to its previous position or the middle of the window.
853 var viewSize
= CKEDITOR
.document
.getWindow().getViewPaneSize(),
854 dialogSize
= this.getSize();
856 this.move( this._
.moved
? this._
.position
.x
: ( viewSize
.width
- dialogSize
.width
) / 2,
857 this._
.moved
? this._
.position
.y
: ( viewSize
.height
- dialogSize
.height
) / 2 );
861 * Executes a function for each UI element.
862 * @param {Function} fn Function to execute for each UI element.
863 * @returns {CKEDITOR.dialog} The current dialog object.
865 foreach : function( fn
)
867 for ( var i
in this._
.contents
)
869 for ( var j
in this._
.contents
[i
] )
870 fn
.call( this, this._
.contents
[i
][j
] );
876 * Resets all input values in the dialog.
879 * @returns {CKEDITOR.dialog} The current dialog object.
883 var fn = function( widget
){ if ( widget
.reset
) widget
.reset( 1 ); };
884 return function(){ this.foreach( fn
); return this; };
889 * Calls the {@link CKEDITOR.dialog.definition.uiElement#setup} method of each of the UI elements, with the arguments passed through it.
890 * It is usually being called when the dialog is opened, to put the initial value inside the field.
892 * dialogObj.setupContent();
894 * var timestamp = ( new Date() ).valueOf();
895 * dialogObj.setupContent( timestamp );
897 setupContent : function()
899 var args
= arguments
;
900 this.foreach( function( widget
)
903 widget
.setup
.apply( widget
, args
);
908 * Calls the {@link CKEDITOR.dialog.definition.uiElement#commit} method of each of the UI elements, with the arguments passed through it.
909 * It is usually being called when the user confirms the dialog, to process the values.
911 * dialogObj.commitContent();
913 * var timestamp = ( new Date() ).valueOf();
914 * dialogObj.commitContent( timestamp );
916 commitContent : function()
918 var args
= arguments
;
919 this.foreach( function( widget
)
921 // Make sure IE triggers "change" event on last focused input before closing the dialog. (#7915)
922 if ( CKEDITOR
.env
.ie
&& this._
.currentFocusIndex
== widget
.focusIndex
)
923 widget
.getInputElement().$.blur();
926 widget
.commit
.apply( widget
, args
);
931 * Hides the dialog box.
937 if ( !this.parts
.dialog
.isVisible() )
940 this.fire( 'hide', {} );
941 this._
.editor
.fire( 'dialogHide', this );
942 var element
= this._
.element
;
943 element
.setStyle( 'display', 'none' );
944 this.parts
.dialog
.setStyle( 'visibility', 'hidden' );
945 // Unregister all access keys associated with this dialog.
946 unregisterAccessKey( this );
948 // Close any child(top) dialogs first.
949 while( CKEDITOR
.dialog
._
.currentTop
!= this )
950 CKEDITOR
.dialog
._
.currentTop
.hide();
952 // Maintain dialog ordering and remove cover if needed.
953 if ( !this._
.parentDialog
)
957 var parentElement
= this._
.parentDialog
.getElement().getFirst();
958 parentElement
.setStyle( 'z-index', parseInt( parentElement
.$.style
.zIndex
, 10 ) + Math
.floor( this._
.editor
.config
.baseFloatZIndex
/ 2 ) );
960 CKEDITOR
.dialog
._
.currentTop
= this._
.parentDialog
;
962 // Deduct or clear the z-index.
963 if ( !this._
.parentDialog
)
965 CKEDITOR
.dialog
._
.currentZIndex
= null;
967 // Remove access key handlers.
968 element
.removeListener( 'keydown', accessKeyDownHandler
);
969 element
.removeListener( CKEDITOR
.env
.opera
? 'keypress' : 'keyup', accessKeyUpHandler
);
971 // Remove bubbling-prevention handler. (#4269)
972 for ( var event
in { keyup
:1, keydown
:1, keypress
:1 } )
973 element
.removeListener( event
, preventKeyBubbling
);
975 var editor
= this._
.editor
;
978 if ( editor
.mode
== 'wysiwyg' && CKEDITOR
.env
.ie
)
980 var selection
= editor
.getSelection();
981 selection
&& selection
.unlock( true );
985 CKEDITOR
.dialog
._
.currentZIndex
-= 10;
987 delete this._
.parentDialog
;
988 // Reset the initial values of the dialog.
989 this.foreach( function( contentObj
) { contentObj
.resetInitValue
&& contentObj
.resetInitValue(); } );
993 * Adds a tabbed page into the dialog.
994 * @param {Object} contents Content definition.
997 addPage : function( contents
)
1000 titleHtml
= contents
.label
? ' title="' + CKEDITOR
.tools
.htmlEncode( contents
.label
) + '"' : '',
1001 elements
= contents
.elements
,
1002 vbox
= CKEDITOR
.dialog
._
.uiElementBuilders
.vbox
.build( this,
1005 className
: 'cke_dialog_page_contents',
1006 children
: contents
.elements
,
1007 expand
: !!contents
.expand
,
1008 padding
: contents
.padding
,
1009 style
: contents
.style
|| 'width: 100%;height:100%'
1012 // Create the HTML for the tab and the content block.
1013 var page
= CKEDITOR
.dom
.element
.createFromHtml( pageHtml
.join( '' ) );
1014 page
.setAttribute( 'role', 'tabpanel' );
1016 var env
= CKEDITOR
.env
;
1017 var tabId
= 'cke_' + contents
.id
+ '_' + CKEDITOR
.tools
.getNextNumber(),
1018 tab
= CKEDITOR
.dom
.element
.createFromHtml( [
1019 '<a class="cke_dialog_tab"',
1020 ( this._
.pageCount
> 0 ? ' cke_last' : 'cke_first' ),
1022 ( !!contents
.hidden
? ' style="display:none"' : '' ),
1023 ' id="', tabId
, '"',
1024 env
.gecko
&& env
.version
>= 10900 && !env
.hc
? '' : ' href="javascript:void(0)"',
1026 ' hidefocus="true"',
1032 page
.setAttribute( 'aria-labelledby', tabId
);
1034 // Take records for the tabs and elements created.
1035 this._
.tabs
[ contents
.id
] = [ tab
, page
];
1036 this._
.tabIdList
.push( contents
.id
);
1037 !contents
.hidden
&& this._
.pageCount
++;
1038 this._
.lastTab
= tab
;
1041 var contentMap
= this._
.contents
[ contents
.id
] = {},
1043 children
= vbox
.getChild();
1045 while ( ( cursor
= children
.shift() ) )
1047 contentMap
[ cursor
.id
] = cursor
;
1048 if ( typeof( cursor
.getChild
) == 'function' )
1049 children
.push
.apply( children
, cursor
.getChild() );
1052 // Attach the DOM nodes.
1054 page
.setAttribute( 'name', contents
.id
);
1055 page
.appendTo( this.parts
.contents
);
1058 this.parts
.tabs
.append( tab
);
1060 // Add access key handlers if access key is defined.
1061 if ( contents
.accessKey
)
1063 registerAccessKey( this, this, 'CTRL+' + contents
.accessKey
,
1064 tabAccessKeyDown
, tabAccessKeyUp
);
1065 this._
.accessKeyMap
[ 'CTRL+' + contents
.accessKey
] = contents
.id
;
1070 * Activates a tab page in the dialog by its id.
1071 * @param {String} id The id of the dialog tab to be activated.
1073 * dialogObj.selectPage( 'tab_1' );
1075 selectPage : function( id
)
1077 if ( this._
.currentTabId
== id
)
1080 // Returning true means that the event has been canceled
1081 if ( this.fire( 'selectPage', { page
: id
, currentPage
: this._
.currentTabId
} ) === true )
1084 // Hide the non-selected tabs and pages.
1085 for ( var i
in this._
.tabs
)
1087 var tab
= this._
.tabs
[i
][0],
1088 page
= this._
.tabs
[i
][1];
1091 tab
.removeClass( 'cke_dialog_tab_selected' );
1094 page
.setAttribute( 'aria-hidden', i
!= id
);
1097 var selected
= this._
.tabs
[ id
];
1098 selected
[ 0 ].addClass( 'cke_dialog_tab_selected' );
1100 // [IE] an invisible input[type='text'] will enlarge it's width
1101 // if it's value is long when it shows, so we clear it's value
1102 // before it shows and then recover it (#5649)
1103 if ( CKEDITOR
.env
.ie6Compat
|| CKEDITOR
.env
.ie7Compat
)
1105 clearOrRecoverTextInputValue( selected
[ 1 ] );
1106 selected
[ 1 ].show();
1107 setTimeout( function()
1109 clearOrRecoverTextInputValue( selected
[ 1 ], 1 );
1113 selected
[ 1 ].show();
1115 this._
.currentTabId
= id
;
1116 this._
.currentTabIndex
= CKEDITOR
.tools
.indexOf( this._
.tabIdList
, id
);
1119 // Dialog state-specific style updates.
1120 updateStyle : function()
1122 // If only a single page shown, a different style is used in the central pane.
1123 this.parts
.dialog
[ ( this._
.pageCount
=== 1 ? 'add' : 'remove' ) + 'Class' ]( 'cke_single_page' );
1127 * Hides a page's tab away from the dialog.
1128 * @param {String} id The page's Id.
1130 * dialog.hidePage( 'tab_3' );
1132 hidePage : function( id
)
1134 var tab
= this._
.tabs
[id
] && this._
.tabs
[id
][0];
1135 if ( !tab
|| this._
.pageCount
== 1 || !tab
.isVisible() )
1137 // Switch to other tab first when we're hiding the active tab.
1138 else if ( id
== this._
.currentTabId
)
1139 this.selectPage( getPreviousVisibleTab
.call( this ) );
1147 * Unhides a page's tab.
1148 * @param {String} id The page's Id.
1150 * dialog.showPage( 'tab_2' );
1152 showPage : function( id
)
1154 var tab
= this._
.tabs
[id
] && this._
.tabs
[id
][0];
1163 * Gets the root DOM element of the dialog.
1164 * @returns {CKEDITOR.dom.element} The <span> element containing this dialog.
1166 * var dialogElement = dialogObj.getElement().getFirst();
1167 * dialogElement.setStyle( 'padding', '5px' );
1169 getElement : function()
1171 return this._
.element
;
1175 * Gets the name of the dialog.
1176 * @returns {String} The name of this dialog.
1178 * var dialogName = dialogObj.getName();
1180 getName : function()
1186 * Gets a dialog UI element object from a dialog page.
1187 * @param {String} pageId id of dialog page.
1188 * @param {String} elementId id of UI element.
1190 * dialogObj.getContentElement( 'tabId', 'elementId' ).setValue( 'Example' );
1191 * @returns {CKEDITOR.ui.dialog.uiElement} The dialog UI element.
1193 getContentElement : function( pageId
, elementId
)
1195 var page
= this._
.contents
[ pageId
];
1196 return page
&& page
[ elementId
];
1200 * Gets the value of a dialog UI element.
1201 * @param {String} pageId id of dialog page.
1202 * @param {String} elementId id of UI element.
1204 * alert( dialogObj.getValueOf( 'tabId', 'elementId' ) );
1205 * @returns {Object} The value of the UI element.
1207 getValueOf : function( pageId
, elementId
)
1209 return this.getContentElement( pageId
, elementId
).getValue();
1213 * Sets the value of a dialog UI element.
1214 * @param {String} pageId id of the dialog page.
1215 * @param {String} elementId id of the UI element.
1216 * @param {Object} value The new value of the UI element.
1218 * dialogObj.setValueOf( 'tabId', 'elementId', 'Example' );
1220 setValueOf : function( pageId
, elementId
, value
)
1222 return this.getContentElement( pageId
, elementId
).setValue( value
);
1226 * Gets the UI element of a button in the dialog's button row.
1227 * @param {String} id The id of the button.
1229 * @returns {CKEDITOR.ui.dialog.button} The button object.
1231 getButton : function( id
)
1233 return this._
.buttons
[ id
];
1237 * Simulates a click to a dialog button in the dialog's button row.
1238 * @param {String} id The id of the button.
1240 * @returns The return value of the dialog's "click" event.
1242 click : function( id
)
1244 return this._
.buttons
[ id
].click();
1248 * Disables a dialog button.
1249 * @param {String} id The id of the button.
1252 disableButton : function( id
)
1254 return this._
.buttons
[ id
].disable();
1258 * Enables a dialog button.
1259 * @param {String} id The id of the button.
1262 enableButton : function( id
)
1264 return this._
.buttons
[ id
].enable();
1268 * Gets the number of pages in the dialog.
1269 * @returns {Number} Page count.
1271 getPageCount : function()
1273 return this._
.pageCount
;
1277 * Gets the editor instance which opened this dialog.
1278 * @returns {CKEDITOR.editor} Parent editor instances.
1280 getParentEditor : function()
1282 return this._
.editor
;
1286 * Gets the element that was selected when opening the dialog, if any.
1287 * @returns {CKEDITOR.dom.element} The element that was selected, or null.
1289 getSelectedElement : function()
1291 return this.getParentEditor().getSelection().getSelectedElement();
1295 * Adds element to dialog's focusable list.
1297 * @param {CKEDITOR.dom.element} element
1298 * @param {Number} [index]
1300 addFocusable: function( element
, index
) {
1301 if ( typeof index
== 'undefined' )
1303 index
= this._
.focusList
.length
;
1304 this._
.focusList
.push( new Focusable( this, element
, index
) );
1308 this._
.focusList
.splice( index
, 0, new Focusable( this, element
, index
) );
1309 for ( var i
= index
+ 1 ; i
< this._
.focusList
.length
; i
++ )
1310 this._
.focusList
[ i
].focusIndex
++;
1315 CKEDITOR
.tools
.extend( CKEDITOR
.dialog
,
1317 * @lends CKEDITOR.dialog
1321 * Registers a dialog.
1322 * @param {String} name The dialog's name.
1323 * @param {Function|String} dialogDefinition
1324 * A function returning the dialog's definition, or the URL to the .js file holding the function.
1325 * The function should accept an argument "editor" which is the current editor instance, and
1326 * return an object conforming to {@link CKEDITOR.dialog.definition}.
1327 * @see CKEDITOR.dialog.definition
1329 * // Full sample plugin, which does not only register a dialog window but also adds an item to the context menu.
1330 * // To open the dialog window, choose "Open dialog" in the context menu.
1331 * CKEDITOR.plugins.add( 'myplugin',
1333 * init: function( editor )
1335 * editor.addCommand( 'mydialog',new CKEDITOR.dialogCommand( 'mydialog' ) );
1337 * if ( editor.contextMenu )
1339 * editor.addMenuGroup( 'mygroup', 10 );
1340 * editor.addMenuItem( 'My Dialog',
1342 * label : 'Open dialog',
1343 * command : 'mydialog',
1346 * editor.contextMenu.addListener( function( element )
1348 * return { 'My Dialog' : CKEDITOR.TRISTATE_OFF };
1352 * <strong>CKEDITOR.dialog.add</strong>( 'mydialog', function( api )
1354 * // CKEDITOR.dialog.definition
1355 * var <strong>dialogDefinition</strong> =
1357 * title : 'Sample dialog',
1371 * html : '<p>This is some sample HTML content.</p>'
1374 * type : 'textarea',
1375 * id : 'textareaId',
1382 * buttons : [ CKEDITOR.dialog.okButton, CKEDITOR.dialog.cancelButton ],
1383 * onOk : function() {
1384 * // "this" is now a CKEDITOR.dialog object.
1385 * // Accessing dialog elements:
1386 * var textareaObj = this.<strong>getContentElement</strong>( 'tab1', 'textareaId' );
1387 * alert( "You have entered: " + textareaObj.getValue() );
1391 * return dialogDefinition;
1396 * CKEDITOR.replace( 'editor1', { extraPlugins : 'myplugin' } );
1398 add : function( name
, dialogDefinition
)
1400 // Avoid path registration from multiple instances override definition.
1401 if ( !this._
.dialogDefinitions
[name
]
1402 || typeof dialogDefinition
== 'function' )
1403 this._
.dialogDefinitions
[name
] = dialogDefinition
;
1406 exists : function( name
)
1408 return !!this._
.dialogDefinitions
[ name
];
1411 getCurrent : function()
1413 return CKEDITOR
.dialog
._
.currentTop
;
1417 * The default OK button for dialogs. Fires the "ok" event and closes the dialog if the event succeeds.
1423 okButton
: (function()
1425 var retval = function( editor
, override
)
1427 override
= override
|| {};
1428 return CKEDITOR
.tools
.extend( {
1431 label
: editor
.lang
.common
.ok
,
1432 'class' : 'cke_dialog_ui_button_ok',
1433 onClick : function( evt
)
1435 var dialog
= evt
.data
.dialog
;
1436 if ( dialog
.fire( 'ok', { hide
: true } ).hide
!== false )
1439 }, override
, true );
1441 retval
.type
= 'button';
1442 retval
.override = function( override
)
1444 return CKEDITOR
.tools
.extend( function( editor
){ return retval( editor
, override
); },
1445 { type
: 'button' }, true );
1451 * The default cancel button for dialogs. Fires the "cancel" event and closes the dialog if no UI element value changed.
1457 cancelButton
: (function()
1459 var retval = function( editor
, override
)
1461 override
= override
|| {};
1462 return CKEDITOR
.tools
.extend( {
1465 label
: editor
.lang
.common
.cancel
,
1466 'class' : 'cke_dialog_ui_button_cancel',
1467 onClick : function( evt
)
1469 var dialog
= evt
.data
.dialog
;
1470 if ( dialog
.fire( 'cancel', { hide
: true } ).hide
!== false )
1473 }, override
, true );
1475 retval
.type
= 'button';
1476 retval
.override = function( override
)
1478 return CKEDITOR
.tools
.extend( function( editor
){ return retval( editor
, override
); },
1479 { type
: 'button' }, true );
1485 * Registers a dialog UI element.
1486 * @param {String} typeName The name of the UI element.
1487 * @param {Function} builder The function to build the UI element.
1490 addUIElement : function( typeName
, builder
)
1492 this._
.uiElementBuilders
[ typeName
] = builder
;
1498 uiElementBuilders
: {},
1500 dialogDefinitions
: {},
1504 currentZIndex
: null
1507 // "Inherit" (copy actually) from CKEDITOR.event.
1508 CKEDITOR
.event
.implementOn( CKEDITOR
.dialog
);
1509 CKEDITOR
.event
.implementOn( CKEDITOR
.dialog
.prototype, true );
1511 var defaultDialogDefinition
=
1513 resizable
: CKEDITOR
.DIALOG_RESIZE_BOTH
,
1516 buttons
: [ CKEDITOR
.dialog
.okButton
, CKEDITOR
.dialog
.cancelButton
]
1519 // Tool function used to return an item from an array based on its id
1521 var getById = function( array
, id
, recurse
)
1523 for ( var i
= 0, item
; ( item
= array
[ i
] ) ; i
++ )
1525 if ( item
.id
== id
)
1527 if ( recurse
&& item
[ recurse
] )
1529 var retval
= getById( item
[ recurse
], id
, recurse
) ;
1537 // Tool function used to add an item into an array.
1538 var addById = function( array
, newItem
, nextSiblingId
, recurse
, nullIfNotFound
)
1540 if ( nextSiblingId
)
1542 for ( var i
= 0, item
; ( item
= array
[ i
] ) ; i
++ )
1544 if ( item
.id
== nextSiblingId
)
1546 array
.splice( i
, 0, newItem
);
1550 if ( recurse
&& item
[ recurse
] )
1552 var retval
= addById( item
[ recurse
], newItem
, nextSiblingId
, recurse
, true );
1558 if ( nullIfNotFound
)
1562 array
.push( newItem
);
1566 // Tool function used to remove an item from an array based on its id.
1567 var removeById = function( array
, id
, recurse
)
1569 for ( var i
= 0, item
; ( item
= array
[ i
] ) ; i
++ )
1571 if ( item
.id
== id
)
1572 return array
.splice( i
, 1 );
1573 if ( recurse
&& item
[ recurse
] )
1575 var retval
= removeById( item
[ recurse
], id
, recurse
);
1584 * This class is not really part of the API. It is the "definition" property value
1585 * passed to "dialogDefinition" event handlers.
1587 * @name CKEDITOR.dialog.definitionObject
1588 * @extends CKEDITOR.dialog.definition
1590 * CKEDITOR.on( 'dialogDefinition', function( evt )
1592 * var definition = evt.data.definition;
1593 * var content = definition.getContents( 'page1' );
1597 var definitionObject = function( dialog
, dialogDefinition
)
1599 // TODO : Check if needed.
1600 this.dialog
= dialog
;
1602 // Transform the contents entries in contentObjects.
1603 var contents
= dialogDefinition
.contents
;
1604 for ( var i
= 0, content
; ( content
= contents
[i
] ) ; i
++ )
1605 contents
[ i
] = content
&& new contentObject( dialog
, content
);
1607 CKEDITOR
.tools
.extend( this, dialogDefinition
);
1610 definitionObject
.prototype =
1611 /** @lends CKEDITOR.dialog.definitionObject.prototype */
1614 * Gets a content definition.
1615 * @param {String} id The id of the content definition.
1616 * @returns {CKEDITOR.dialog.definition.content} The content definition
1619 getContents : function( id
)
1621 return getById( this.contents
, id
);
1625 * Gets a button definition.
1626 * @param {String} id The id of the button definition.
1627 * @returns {CKEDITOR.dialog.definition.button} The button definition
1630 getButton : function( id
)
1632 return getById( this.buttons
, id
);
1636 * Adds a content definition object under this dialog definition.
1637 * @param {CKEDITOR.dialog.definition.content} contentDefinition The
1638 * content definition.
1639 * @param {String} [nextSiblingId] The id of an existing content
1640 * definition which the new content definition will be inserted
1641 * before. Omit if the new content definition is to be inserted as
1643 * @returns {CKEDITOR.dialog.definition.content} The inserted content
1646 addContents : function( contentDefinition
, nextSiblingId
)
1648 return addById( this.contents
, contentDefinition
, nextSiblingId
);
1652 * Adds a button definition object under this dialog definition.
1653 * @param {CKEDITOR.dialog.definition.button} buttonDefinition The
1654 * button definition.
1655 * @param {String} [nextSiblingId] The id of an existing button
1656 * definition which the new button definition will be inserted
1657 * before. Omit if the new button definition is to be inserted as
1659 * @returns {CKEDITOR.dialog.definition.button} The inserted button
1662 addButton : function( buttonDefinition
, nextSiblingId
)
1664 return addById( this.buttons
, buttonDefinition
, nextSiblingId
);
1668 * Removes a content definition from this dialog definition.
1669 * @param {String} id The id of the content definition to be removed.
1670 * @returns {CKEDITOR.dialog.definition.content} The removed content
1673 removeContents : function( id
)
1675 removeById( this.contents
, id
);
1679 * Removes a button definition from the dialog definition.
1680 * @param {String} id The id of the button definition to be removed.
1681 * @returns {CKEDITOR.dialog.definition.button} The removed button
1684 removeButton : function( id
)
1686 removeById( this.buttons
, id
);
1691 * This class is not really part of the API. It is the template of the
1692 * objects representing content pages inside the
1693 * CKEDITOR.dialog.definitionObject.
1695 * @name CKEDITOR.dialog.definition.contentObject
1697 * CKEDITOR.on( 'dialogDefinition', function( evt )
1699 * var definition = evt.data.definition;
1700 * var content = definition.getContents( 'page1' );
1701 * content.remove( 'textInput1' );
1705 function contentObject( dialog
, contentDefinition
)
1712 CKEDITOR
.tools
.extend( this, contentDefinition
);
1715 contentObject
.prototype =
1716 /** @lends CKEDITOR.dialog.definition.contentObject.prototype */
1719 * Gets a UI element definition under the content definition.
1720 * @param {String} id The id of the UI element definition.
1721 * @returns {CKEDITOR.dialog.definition.uiElement}
1723 get : function( id
)
1725 return getById( this.elements
, id
, 'children' );
1729 * Adds a UI element definition to the content definition.
1730 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition The
1731 * UI elemnet definition to be added.
1732 * @param {String} nextSiblingId The id of an existing UI element
1733 * definition which the new UI element definition will be inserted
1734 * before. Omit if the new button definition is to be inserted as
1736 * @returns {CKEDITOR.dialog.definition.uiElement} The element
1737 * definition inserted.
1739 add : function( elementDefinition
, nextSiblingId
)
1741 return addById( this.elements
, elementDefinition
, nextSiblingId
, 'children' );
1745 * Removes a UI element definition from the content definition.
1746 * @param {String} id The id of the UI element definition to be
1748 * @returns {CKEDITOR.dialog.definition.uiElement} The element
1749 * definition removed.
1752 remove : function( id
)
1754 removeById( this.elements
, id
, 'children' );
1758 function initDragAndDrop( dialog
)
1760 var lastCoords
= null,
1761 abstractDialogCoords
= null,
1762 element
= dialog
.getElement().getFirst(),
1763 editor
= dialog
.getParentEditor(),
1764 magnetDistance
= editor
.config
.dialog_magnetDistance
,
1765 margins
= editor
.skin
.margins
|| [ 0, 0, 0, 0 ];
1767 if ( typeof magnetDistance
== 'undefined' )
1768 magnetDistance
= 20;
1770 function mouseMoveHandler( evt
)
1772 var dialogSize
= dialog
.getSize(),
1773 viewPaneSize
= CKEDITOR
.document
.getWindow().getViewPaneSize(),
1774 x
= evt
.data
.$.screenX
,
1775 y
= evt
.data
.$.screenY
,
1776 dx
= x
- lastCoords
.x
,
1777 dy
= y
- lastCoords
.y
,
1780 lastCoords
= { x
: x
, y
: y
};
1781 abstractDialogCoords
.x
+= dx
;
1782 abstractDialogCoords
.y
+= dy
;
1784 if ( abstractDialogCoords
.x
+ margins
[3] < magnetDistance
)
1785 realX
= - margins
[3];
1786 else if ( abstractDialogCoords
.x
- margins
[1] > viewPaneSize
.width
- dialogSize
.width
- magnetDistance
)
1787 realX
= viewPaneSize
.width
- dialogSize
.width
+ ( editor
.lang
.dir
== 'rtl' ? 0 : margins
[1] );
1789 realX
= abstractDialogCoords
.x
;
1791 if ( abstractDialogCoords
.y
+ margins
[0] < magnetDistance
)
1792 realY
= - margins
[0];
1793 else if ( abstractDialogCoords
.y
- margins
[2] > viewPaneSize
.height
- dialogSize
.height
- magnetDistance
)
1794 realY
= viewPaneSize
.height
- dialogSize
.height
+ margins
[2];
1796 realY
= abstractDialogCoords
.y
;
1798 dialog
.move( realX
, realY
, 1 );
1800 evt
.data
.preventDefault();
1803 function mouseUpHandler( evt
)
1805 CKEDITOR
.document
.removeListener( 'mousemove', mouseMoveHandler
);
1806 CKEDITOR
.document
.removeListener( 'mouseup', mouseUpHandler
);
1808 if ( CKEDITOR
.env
.ie6Compat
)
1810 var coverDoc
= currentCover
.getChild( 0 ).getFrameDocument();
1811 coverDoc
.removeListener( 'mousemove', mouseMoveHandler
);
1812 coverDoc
.removeListener( 'mouseup', mouseUpHandler
);
1816 dialog
.parts
.title
.on( 'mousedown', function( evt
)
1818 lastCoords
= { x
: evt
.data
.$.screenX
, y
: evt
.data
.$.screenY
};
1820 CKEDITOR
.document
.on( 'mousemove', mouseMoveHandler
);
1821 CKEDITOR
.document
.on( 'mouseup', mouseUpHandler
);
1822 abstractDialogCoords
= dialog
.getPosition();
1824 if ( CKEDITOR
.env
.ie6Compat
)
1826 var coverDoc
= currentCover
.getChild( 0 ).getFrameDocument();
1827 coverDoc
.on( 'mousemove', mouseMoveHandler
);
1828 coverDoc
.on( 'mouseup', mouseUpHandler
);
1831 evt
.data
.preventDefault();
1835 function initResizeHandles( dialog
)
1837 var def
= dialog
.definition
,
1838 resizable
= def
.resizable
;
1840 if ( resizable
== CKEDITOR
.DIALOG_RESIZE_NONE
)
1843 var editor
= dialog
.getParentEditor();
1844 var wrapperWidth
, wrapperHeight
,
1845 viewSize
, origin
, startSize
,
1848 var mouseDownFn
= CKEDITOR
.tools
.addFunction( function( $event
)
1850 startSize
= dialog
.getSize();
1852 var content
= dialog
.parts
.contents
,
1853 iframeDialog
= content
.$.getElementsByTagName( 'iframe' ).length
;
1855 // Shim to help capturing "mousemove" over iframe.
1858 dialogCover
= CKEDITOR
.dom
.element
.createFromHtml( '<div class="cke_dialog_resize_cover" style="height: 100%; position: absolute; width: 100%;"></div>' );
1859 content
.append( dialogCover
);
1862 // Calculate the offset between content and chrome size.
1863 wrapperHeight
= startSize
.height
- dialog
.parts
.contents
.getSize( 'height', ! ( CKEDITOR
.env
.gecko
|| CKEDITOR
.env
.opera
|| CKEDITOR
.env
.ie
&& CKEDITOR
.env
.quirks
) );
1864 wrapperWidth
= startSize
.width
- dialog
.parts
.contents
.getSize( 'width', 1 );
1866 origin
= { x
: $event
.screenX
, y
: $event
.screenY
};
1868 viewSize
= CKEDITOR
.document
.getWindow().getViewPaneSize();
1870 CKEDITOR
.document
.on( 'mousemove', mouseMoveHandler
);
1871 CKEDITOR
.document
.on( 'mouseup', mouseUpHandler
);
1873 if ( CKEDITOR
.env
.ie6Compat
)
1875 var coverDoc
= currentCover
.getChild( 0 ).getFrameDocument();
1876 coverDoc
.on( 'mousemove', mouseMoveHandler
);
1877 coverDoc
.on( 'mouseup', mouseUpHandler
);
1880 $event
.preventDefault
&& $event
.preventDefault();
1883 // Prepend the grip to the dialog.
1884 dialog
.on( 'load', function()
1887 if ( resizable
== CKEDITOR
.DIALOG_RESIZE_WIDTH
)
1888 direction
= ' cke_resizer_horizontal';
1889 else if ( resizable
== CKEDITOR
.DIALOG_RESIZE_HEIGHT
)
1890 direction
= ' cke_resizer_vertical';
1891 var resizer
= CKEDITOR
.dom
.element
.createFromHtml( '<div' +
1892 ' class="cke_resizer' + direction
+ ' cke_resizer_' + editor
.lang
.dir
+ '"' +
1893 ' title="' + CKEDITOR
.tools
.htmlEncode( editor
.lang
.resize
) + '"' +
1894 ' onmousedown="CKEDITOR.tools.callFunction(' + mouseDownFn
+ ', event )"></div>' );
1895 dialog
.parts
.footer
.append( resizer
, 1 );
1897 editor
.on( 'destroy', function() { CKEDITOR
.tools
.removeFunction( mouseDownFn
); } );
1899 function mouseMoveHandler( evt
)
1901 var rtl
= editor
.lang
.dir
== 'rtl',
1902 dx
= ( evt
.data
.$.screenX
- origin
.x
) * ( rtl
? -1 : 1 ),
1903 dy
= evt
.data
.$.screenY
- origin
.y
,
1904 width
= startSize
.width
,
1905 height
= startSize
.height
,
1906 internalWidth
= width
+ dx
* ( dialog
._
.moved
? 1 : 2 ),
1907 internalHeight
= height
+ dy
* ( dialog
._
.moved
? 1 : 2 ),
1908 element
= dialog
._
.element
.getFirst(),
1909 right
= rtl
&& element
.getComputedStyle( 'right' ),
1910 position
= dialog
.getPosition();
1912 if ( position
.y
+ internalHeight
> viewSize
.height
)
1913 internalHeight
= viewSize
.height
- position
.y
;
1915 if ( ( rtl
? right
: position
.x
) + internalWidth
> viewSize
.width
)
1916 internalWidth
= viewSize
.width
- ( rtl
? right
: position
.x
);
1918 // Make sure the dialog will not be resized to the wrong side when it's in the leftmost position for RTL.
1919 if ( ( resizable
== CKEDITOR
.DIALOG_RESIZE_WIDTH
|| resizable
== CKEDITOR
.DIALOG_RESIZE_BOTH
) )
1920 width
= Math
.max( def
.minWidth
|| 0, internalWidth
- wrapperWidth
);
1922 if ( resizable
== CKEDITOR
.DIALOG_RESIZE_HEIGHT
|| resizable
== CKEDITOR
.DIALOG_RESIZE_BOTH
)
1923 height
= Math
.max( def
.minHeight
|| 0, internalHeight
- wrapperHeight
);
1925 dialog
.resize( width
, height
);
1927 if ( !dialog
._
.moved
)
1930 evt
.data
.preventDefault();
1933 function mouseUpHandler()
1935 CKEDITOR
.document
.removeListener( 'mouseup', mouseUpHandler
);
1936 CKEDITOR
.document
.removeListener( 'mousemove', mouseMoveHandler
);
1940 dialogCover
.remove();
1944 if ( CKEDITOR
.env
.ie6Compat
)
1946 var coverDoc
= currentCover
.getChild( 0 ).getFrameDocument();
1947 coverDoc
.removeListener( 'mouseup', mouseUpHandler
);
1948 coverDoc
.removeListener( 'mousemove', mouseMoveHandler
);
1954 // Caching resuable covers and allowing only one cover
1959 function cancelEvent( ev
)
1961 ev
.data
.preventDefault(1);
1964 function showCover( editor
)
1966 var win
= CKEDITOR
.document
.getWindow();
1967 var config
= editor
.config
,
1968 backgroundColorStyle
= config
.dialog_backgroundCoverColor
|| 'white',
1969 backgroundCoverOpacity
= config
.dialog_backgroundCoverOpacity
,
1970 baseFloatZIndex
= config
.baseFloatZIndex
,
1971 coverKey
= CKEDITOR
.tools
.genKey(
1972 backgroundColorStyle
,
1973 backgroundCoverOpacity
,
1975 coverElement
= covers
[ coverKey
];
1977 if ( !coverElement
)
1980 '<div tabIndex="-1" style="position: ', ( CKEDITOR
.env
.ie6Compat
? 'absolute' : 'fixed' ),
1981 '; z-index: ', baseFloatZIndex
,
1982 '; top: 0px; left: 0px; ',
1983 ( !CKEDITOR
.env
.ie6Compat
? 'background-color: ' + backgroundColorStyle
: '' ),
1984 '" class="cke_dialog_background_cover">'
1987 if ( CKEDITOR
.env
.ie6Compat
)
1989 // Support for custom document.domain in IE.
1990 var isCustomDomain
= CKEDITOR
.env
.isCustomDomain(),
1991 iframeHtml
= '<html><body style=\\\'background-color:' + backgroundColorStyle
+ ';\\\'></body></html>';
1995 ' hidefocus="true"' +
1996 ' frameborder="0"' +
1997 ' id="cke_dialog_background_iframe"' +
1998 ' src="javascript:' );
2000 html
.push( 'void((function(){' +
2001 'document.open();' +
2002 ( isCustomDomain
? 'document.domain=\'' + document
.domain
+ '\';' : '' ) +
2003 'document.write( \'' + iframeHtml
+ '\' );' +
2004 'document.close();' +
2010 'position:absolute;' +
2015 'progid:DXImageTransform.Microsoft.Alpha(opacity=0)">' +
2019 html
.push( '</div>' );
2021 coverElement
= CKEDITOR
.dom
.element
.createFromHtml( html
.join( '' ) );
2022 coverElement
.setOpacity( backgroundCoverOpacity
!= undefined ? backgroundCoverOpacity
: 0.5 );
2024 coverElement
.on( 'keydown', cancelEvent
);
2025 coverElement
.on( 'keypress', cancelEvent
);
2026 coverElement
.on( 'keyup', cancelEvent
);
2028 coverElement
.appendTo( CKEDITOR
.document
.getBody() );
2029 covers
[ coverKey
] = coverElement
;
2032 coverElement
. show();
2034 currentCover
= coverElement
;
2035 var resizeFunc = function()
2037 var size
= win
.getViewPaneSize();
2038 coverElement
.setStyles(
2040 width
: size
.width
+ 'px',
2041 height
: size
.height
+ 'px'
2045 var scrollFunc = function()
2047 var pos
= win
.getScrollPosition(),
2048 cursor
= CKEDITOR
.dialog
._
.currentTop
;
2049 coverElement
.setStyles(
2051 left
: pos
.x
+ 'px',
2059 var dialogPos
= cursor
.getPosition();
2060 cursor
.move( dialogPos
.x
, dialogPos
.y
);
2061 } while ( ( cursor
= cursor
._
.parentDialog
) );
2065 resizeCover
= resizeFunc
;
2066 win
.on( 'resize', resizeFunc
);
2068 // Using Safari/Mac, focus must be kept where it is (#7027)
2069 if ( !( CKEDITOR
.env
.mac
&& CKEDITOR
.env
.webkit
) )
2070 coverElement
.focus();
2072 if ( CKEDITOR
.env
.ie6Compat
)
2074 // IE BUG: win.$.onscroll assignment doesn't work.. it must be window.onscroll.
2075 // So we need to invent a really funny way to make it work.
2076 var myScrollHandler = function()
2079 arguments
.callee
.prevScrollHandler
.apply( this, arguments
);
2081 win
.$.setTimeout( function()
2083 myScrollHandler
.prevScrollHandler
= window
.onscroll
|| function(){};
2084 window
.onscroll
= myScrollHandler
;
2090 function hideCover()
2092 if ( !currentCover
)
2095 var win
= CKEDITOR
.document
.getWindow();
2096 currentCover
.hide();
2097 win
.removeListener( 'resize', resizeCover
);
2099 if ( CKEDITOR
.env
.ie6Compat
)
2101 win
.$.setTimeout( function()
2103 var prevScrollHandler
= window
.onscroll
&& window
.onscroll
.prevScrollHandler
;
2104 window
.onscroll
= prevScrollHandler
|| null;
2110 function removeCovers()
2112 for ( var coverId
in covers
)
2113 covers
[ coverId
].remove();
2117 var accessKeyProcessors
= {};
2119 var accessKeyDownHandler = function( evt
)
2121 var ctrl
= evt
.data
.$.ctrlKey
|| evt
.data
.$.metaKey
,
2122 alt
= evt
.data
.$.altKey
,
2123 shift
= evt
.data
.$.shiftKey
,
2124 key
= String
.fromCharCode( evt
.data
.$.keyCode
),
2125 keyProcessor
= accessKeyProcessors
[( ctrl
? 'CTRL+' : '' ) + ( alt
? 'ALT+' : '') + ( shift
? 'SHIFT+' : '' ) + key
];
2127 if ( !keyProcessor
|| !keyProcessor
.length
)
2130 keyProcessor
= keyProcessor
[keyProcessor
.length
- 1];
2131 keyProcessor
.keydown
&& keyProcessor
.keydown
.call( keyProcessor
.uiElement
, keyProcessor
.dialog
, keyProcessor
.key
);
2132 evt
.data
.preventDefault();
2135 var accessKeyUpHandler = function( evt
)
2137 var ctrl
= evt
.data
.$.ctrlKey
|| evt
.data
.$.metaKey
,
2138 alt
= evt
.data
.$.altKey
,
2139 shift
= evt
.data
.$.shiftKey
,
2140 key
= String
.fromCharCode( evt
.data
.$.keyCode
),
2141 keyProcessor
= accessKeyProcessors
[( ctrl
? 'CTRL+' : '' ) + ( alt
? 'ALT+' : '') + ( shift
? 'SHIFT+' : '' ) + key
];
2143 if ( !keyProcessor
|| !keyProcessor
.length
)
2146 keyProcessor
= keyProcessor
[keyProcessor
.length
- 1];
2147 if ( keyProcessor
.keyup
)
2149 keyProcessor
.keyup
.call( keyProcessor
.uiElement
, keyProcessor
.dialog
, keyProcessor
.key
);
2150 evt
.data
.preventDefault();
2154 var registerAccessKey = function( uiElement
, dialog
, key
, downFunc
, upFunc
)
2156 var procList
= accessKeyProcessors
[key
] || ( accessKeyProcessors
[key
] = [] );
2158 uiElement
: uiElement
,
2161 keyup
: upFunc
|| uiElement
.accessKeyUp
,
2162 keydown
: downFunc
|| uiElement
.accessKeyDown
2166 var unregisterAccessKey = function( obj
)
2168 for ( var i
in accessKeyProcessors
)
2170 var list
= accessKeyProcessors
[i
];
2171 for ( var j
= list
.length
- 1 ; j
>= 0 ; j
-- )
2173 if ( list
[j
].dialog
== obj
|| list
[j
].uiElement
== obj
)
2174 list
.splice( j
, 1 );
2176 if ( list
.length
=== 0 )
2177 delete accessKeyProcessors
[i
];
2181 var tabAccessKeyUp = function( dialog
, key
)
2183 if ( dialog
._
.accessKeyMap
[key
] )
2184 dialog
.selectPage( dialog
._
.accessKeyMap
[key
] );
2187 var tabAccessKeyDown = function( dialog
, key
)
2192 var preventKeyBubblingKeys
= { 27 :1, 13 :1 };
2193 var preventKeyBubbling = function( e
)
2195 if ( e
.data
.getKeystroke() in preventKeyBubblingKeys
)
2196 e
.data
.stopPropagation();
2201 CKEDITOR
.ui
.dialog
=
2204 * The base class of all dialog UI elements.
2206 * @param {CKEDITOR.dialog} dialog Parent dialog object.
2207 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition Element
2208 * definition. Accepted fields:
2210 * <li><strong>id</strong> (Required) The id of the UI element. See {@link
2211 * CKEDITOR.dialog#getContentElement}</li>
2212 * <li><strong>type</strong> (Required) The type of the UI element. The
2213 * value to this field specifies which UI element class will be used to
2214 * generate the final widget.</li>
2215 * <li><strong>title</strong> (Optional) The popup tooltip for the UI
2217 * <li><strong>hidden</strong> (Optional) A flag that tells if the element
2218 * should be initially visible.</li>
2219 * <li><strong>className</strong> (Optional) Additional CSS class names
2220 * to add to the UI element. Separated by space.</li>
2221 * <li><strong>style</strong> (Optional) Additional CSS inline styles
2222 * to add to the UI element. A semicolon (;) is required after the last
2223 * style declaration.</li>
2224 * <li><strong>accessKey</strong> (Optional) The alphanumeric access key
2225 * for this element. Access keys are automatically prefixed by CTRL.</li>
2226 * <li><strong>on*</strong> (Optional) Any UI element definition field that
2227 * starts with <em>on</em> followed immediately by a capital letter and
2228 * probably more letters is an event handler. Event handlers may be further
2229 * divided into registered event handlers and DOM event handlers. Please
2230 * refer to {@link CKEDITOR.ui.dialog.uiElement#registerEvents} and
2231 * {@link CKEDITOR.ui.dialog.uiElement#eventProcessors} for more
2234 * @param {Array} htmlList
2235 * List of HTML code to be added to the dialog's content area.
2236 * @param {Function|String} nodeNameArg
2237 * A function returning a string, or a simple string for the node name for
2238 * the root DOM node. Default is 'div'.
2239 * @param {Function|Object} stylesArg
2240 * A function returning an object, or a simple object for CSS styles applied
2241 * to the DOM node. Default is empty object.
2242 * @param {Function|Object} attributesArg
2243 * A fucntion returning an object, or a simple object for attributes applied
2244 * to the DOM node. Default is empty object.
2245 * @param {Function|String} contentsArg
2246 * A function returning a string, or a simple string for the HTML code inside
2247 * the root DOM node. Default is empty string.
2250 uiElement : function( dialog
, elementDefinition
, htmlList
, nodeNameArg
, stylesArg
, attributesArg
, contentsArg
)
2252 if ( arguments
.length
< 4 )
2255 var nodeName
= ( nodeNameArg
.call
? nodeNameArg( elementDefinition
) : nodeNameArg
) || 'div',
2256 html
= [ '<', nodeName
, ' ' ],
2257 styles
= ( stylesArg
&& stylesArg
.call
? stylesArg( elementDefinition
) : stylesArg
) || {},
2258 attributes
= ( attributesArg
&& attributesArg
.call
? attributesArg( elementDefinition
) : attributesArg
) || {},
2259 innerHTML
= ( contentsArg
&& contentsArg
.call
? contentsArg
.call( this, dialog
, elementDefinition
) : contentsArg
) || '',
2260 domId
= this.domId
= attributes
.id
|| CKEDITOR
.tools
.getNextId() + '_uiElement',
2261 id
= this.id
= elementDefinition
.id
,
2264 // Set the id, a unique id is required for getElement() to work.
2265 attributes
.id
= domId
;
2267 // Set the type and definition CSS class names.
2269 if ( elementDefinition
.type
)
2270 classes
[ 'cke_dialog_ui_' + elementDefinition
.type
] = 1;
2271 if ( elementDefinition
.className
)
2272 classes
[ elementDefinition
.className
] = 1;
2273 if ( elementDefinition
.disabled
)
2274 classes
[ 'cke_disabled' ] = 1;
2276 var attributeClasses
= ( attributes
['class'] && attributes
['class'].split
) ? attributes
['class'].split( ' ' ) : [];
2277 for ( i
= 0 ; i
< attributeClasses
.length
; i
++ )
2279 if ( attributeClasses
[i
] )
2280 classes
[ attributeClasses
[i
] ] = 1;
2282 var finalClasses
= [];
2283 for ( i
in classes
)
2284 finalClasses
.push( i
);
2285 attributes
['class'] = finalClasses
.join( ' ' );
2287 // Set the popup tooltop.
2288 if ( elementDefinition
.title
)
2289 attributes
.title
= elementDefinition
.title
;
2291 // Write the inline CSS styles.
2292 var styleStr
= ( elementDefinition
.style
|| '' ).split( ';' );
2294 // Element alignment support.
2295 if ( elementDefinition
.align
)
2297 var align
= elementDefinition
.align
;
2298 styles
[ 'margin-left' ] = align
== 'left' ? 0 : 'auto';
2299 styles
[ 'margin-right' ] = align
== 'right' ? 0 : 'auto';
2303 styleStr
.push( i
+ ':' + styles
[i
] );
2304 if ( elementDefinition
.hidden
)
2305 styleStr
.push( 'display:none' );
2306 for ( i
= styleStr
.length
- 1 ; i
>= 0 ; i
-- )
2308 if ( styleStr
[i
] === '' )
2309 styleStr
.splice( i
, 1 );
2311 if ( styleStr
.length
> 0 )
2312 attributes
.style
= ( attributes
.style
? ( attributes
.style
+ '; ' ) : '' ) + styleStr
.join( '; ' );
2314 // Write the attributes.
2315 for ( i
in attributes
)
2316 html
.push( i
+ '="' + CKEDITOR
.tools
.htmlEncode( attributes
[i
] ) + '" ');
2318 // Write the content HTML.
2319 html
.push( '>', innerHTML
, '</', nodeName
, '>' );
2321 // Add contents to the parent HTML array.
2322 htmlList
.push( html
.join( '' ) );
2324 ( this._
|| ( this._
= {} ) ).dialog
= dialog
;
2326 // Override isChanged if it is defined in element definition.
2327 if ( typeof( elementDefinition
.isChanged
) == 'boolean' )
2328 this.isChanged = function(){ return elementDefinition
.isChanged
; };
2329 if ( typeof( elementDefinition
.isChanged
) == 'function' )
2330 this.isChanged
= elementDefinition
.isChanged
;
2332 // Overload 'get(set)Value' on definition.
2333 if ( typeof( elementDefinition
.setValue
) == 'function' )
2335 this.setValue
= CKEDITOR
.tools
.override( this.setValue
, function( org
)
2337 return function( val
){ org
.call( this, elementDefinition
.setValue
.call( this, val
) ); };
2341 if ( typeof( elementDefinition
.getValue
) == 'function' )
2343 this.getValue
= CKEDITOR
.tools
.override( this.getValue
, function( org
)
2345 return function(){ return elementDefinition
.getValue
.call( this, org
.call( this ) ); };
2350 CKEDITOR
.event
.implementOn( this );
2352 this.registerEvents( elementDefinition
);
2353 if ( this.accessKeyUp
&& this.accessKeyDown
&& elementDefinition
.accessKey
)
2354 registerAccessKey( this, dialog
, 'CTRL+' + elementDefinition
.accessKey
);
2357 dialog
.on( 'load', function()
2359 if ( me
.getInputElement() )
2361 me
.getInputElement().on( 'focus', function()
2363 dialog
._
.tabBarMode
= false;
2364 dialog
._
.hasFocus
= true;
2370 // Register the object as a tab focus if it can be included.
2371 if ( this.keyboardFocusable
)
2373 this.tabIndex
= elementDefinition
.tabIndex
|| 0;
2375 this.focusIndex
= dialog
._
.focusList
.push( this ) - 1;
2376 this.on( 'focus', function()
2378 dialog
._
.currentFocusIndex
= me
.focusIndex
;
2382 // Completes this object with everything we have in the
2384 CKEDITOR
.tools
.extend( this, elementDefinition
);
2388 * Horizontal layout box for dialog UI elements, auto-expends to available width of container.
2390 * @extends CKEDITOR.ui.dialog.uiElement
2391 * @param {CKEDITOR.dialog} dialog
2392 * Parent dialog object.
2393 * @param {Array} childObjList
2394 * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this
2396 * @param {Array} childHtmlList
2397 * Array of HTML code that correspond to the HTML output of all the
2398 * objects in childObjList.
2399 * @param {Array} htmlList
2400 * Array of HTML code that this element will output to.
2401 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
2402 * The element definition. Accepted fields:
2404 * <li><strong>widths</strong> (Optional) The widths of child cells.</li>
2405 * <li><strong>height</strong> (Optional) The height of the layout.</li>
2406 * <li><strong>padding</strong> (Optional) The padding width inside child
2408 * <li><strong>align</strong> (Optional) The alignment of the whole layout
2413 hbox : function( dialog
, childObjList
, childHtmlList
, htmlList
, elementDefinition
)
2415 if ( arguments
.length
< 4 )
2418 this._
|| ( this._
= {} );
2420 var children
= this._
.children
= childObjList
,
2421 widths
= elementDefinition
&& elementDefinition
.widths
|| null,
2422 height
= elementDefinition
&& elementDefinition
.height
|| null,
2426 var innerHTML = function()
2428 var html
= [ '<tbody><tr class="cke_dialog_ui_hbox">' ];
2429 for ( i
= 0 ; i
< childHtmlList
.length
; i
++ )
2431 var className
= 'cke_dialog_ui_hbox_child',
2434 className
= 'cke_dialog_ui_hbox_first';
2435 if ( i
== childHtmlList
.length
- 1 )
2436 className
= 'cke_dialog_ui_hbox_last';
2437 html
.push( '<td class="', className
, '" role="presentation" ' );
2441 styles
.push( 'width:' + cssLength( widths
[i
] ) );
2444 styles
.push( 'width:' + Math
.floor( 100 / childHtmlList
.length
) + '%' );
2446 styles
.push( 'height:' + cssLength( height
) );
2447 if ( elementDefinition
&& elementDefinition
.padding
!= undefined )
2448 styles
.push( 'padding:' + cssLength( elementDefinition
.padding
) );
2449 // In IE Quirks alignment has to be done on table cells. (#7324)
2450 if ( CKEDITOR
.env
.ie
&& CKEDITOR
.env
.quirks
&& children
[ i
].align
)
2451 styles
.push( 'text-align:' + children
[ i
].align
);
2452 if ( styles
.length
> 0 )
2453 html
.push( 'style="' + styles
.join('; ') + '" ' );
2454 html
.push( '>', childHtmlList
[i
], '</td>' );
2456 html
.push( '</tr></tbody>' );
2457 return html
.join( '' );
2460 var attribs
= { role
: 'presentation' };
2461 elementDefinition
&& elementDefinition
.align
&& ( attribs
.align
= elementDefinition
.align
);
2463 CKEDITOR
.ui
.dialog
.uiElement
.call(
2466 elementDefinition
|| { type
: 'hbox' },
2475 * Vertical layout box for dialog UI elements.
2477 * @extends CKEDITOR.ui.dialog.hbox
2478 * @param {CKEDITOR.dialog} dialog
2479 * Parent dialog object.
2480 * @param {Array} childObjList
2481 * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this
2483 * @param {Array} childHtmlList
2484 * Array of HTML code that correspond to the HTML output of all the
2485 * objects in childObjList.
2486 * @param {Array} htmlList
2487 * Array of HTML code that this element will output to.
2488 * @param {CKEDITOR.dialog.definition.uiElement} elementDefinition
2489 * The element definition. Accepted fields:
2491 * <li><strong>width</strong> (Optional) The width of the layout.</li>
2492 * <li><strong>heights</strong> (Optional) The heights of individual cells.
2494 * <li><strong>align</strong> (Optional) The alignment of the layout.</li>
2495 * <li><strong>padding</strong> (Optional) The padding width inside child
2497 * <li><strong>expand</strong> (Optional) Whether the layout should expand
2498 * vertically to fill its container.</li>
2502 vbox : function( dialog
, childObjList
, childHtmlList
, htmlList
, elementDefinition
)
2504 if ( arguments
.length
< 3 )
2507 this._
|| ( this._
= {} );
2509 var children
= this._
.children
= childObjList
,
2510 width
= elementDefinition
&& elementDefinition
.width
|| null,
2511 heights
= elementDefinition
&& elementDefinition
.heights
|| null;
2513 var innerHTML = function()
2515 var html
= [ '<table role="presentation" cellspacing="0" border="0" ' ];
2516 html
.push( 'style="' );
2517 if ( elementDefinition
&& elementDefinition
.expand
)
2518 html
.push( 'height:100%;' );
2519 html
.push( 'width:' + cssLength( width
|| '100%' ), ';' );
2521 html
.push( 'align="', CKEDITOR
.tools
.htmlEncode(
2522 ( elementDefinition
&& elementDefinition
.align
) || ( dialog
.getParentEditor().lang
.dir
== 'ltr' ? 'left' : 'right' ) ), '" ' );
2524 html
.push( '><tbody>' );
2525 for ( var i
= 0 ; i
< childHtmlList
.length
; i
++ )
2528 html
.push( '<tr><td role="presentation" ' );
2530 styles
.push( 'width:' + cssLength( width
|| '100%' ) );
2532 styles
.push( 'height:' + cssLength( heights
[i
] ) );
2533 else if ( elementDefinition
&& elementDefinition
.expand
)
2534 styles
.push( 'height:' + Math
.floor( 100 / childHtmlList
.length
) + '%' );
2535 if ( elementDefinition
&& elementDefinition
.padding
!= undefined )
2536 styles
.push( 'padding:' + cssLength( elementDefinition
.padding
) );
2537 // In IE Quirks alignment has to be done on table cells. (#7324)
2538 if ( CKEDITOR
.env
.ie
&& CKEDITOR
.env
.quirks
&& children
[ i
].align
)
2539 styles
.push( 'text-align:' + children
[ i
].align
);
2540 if ( styles
.length
> 0 )
2541 html
.push( 'style="', styles
.join( '; ' ), '" ' );
2542 html
.push( ' class="cke_dialog_ui_vbox_child">', childHtmlList
[i
], '</td></tr>' );
2544 html
.push( '</tbody></table>' );
2545 return html
.join( '' );
2547 CKEDITOR
.ui
.dialog
.uiElement
.call( this, dialog
, elementDefinition
|| { type
: 'vbox' }, htmlList
, 'div', null, { role
: 'presentation' }, innerHTML
);
2552 CKEDITOR
.ui
.dialog
.uiElement
.prototype =
2555 * Gets the root DOM element of this dialog UI object.
2556 * @returns {CKEDITOR.dom.element} Root DOM element of UI object.
2558 * uiElement.getElement().hide();
2560 getElement : function()
2562 return CKEDITOR
.document
.getById( this.domId
);
2566 * Gets the DOM element that the user inputs values.
2567 * This function is used by setValue(), getValue() and focus(). It should
2568 * be overrided in child classes where the input element isn't the root
2570 * @returns {CKEDITOR.dom.element} The element where the user input values.
2572 * var rawValue = textInput.getInputElement().$.value;
2574 getInputElement : function()
2576 return this.getElement();
2580 * Gets the parent dialog object containing this UI element.
2581 * @returns {CKEDITOR.dialog} Parent dialog object.
2583 * var dialog = uiElement.getDialog();
2585 getDialog : function()
2587 return this._
.dialog
;
2591 * Sets the value of this dialog UI object.
2592 * @param {Object} value The new value.
2593 * @param {Boolean} noChangeEvent Internal commit, to supress 'change' event on this element.
2594 * @returns {CKEDITOR.dialog.uiElement} The current UI element.
2596 * uiElement.setValue( 'Dingo' );
2598 setValue : function( value
, noChangeEvent
)
2600 this.getInputElement().setValue( value
);
2601 !noChangeEvent
&& this.fire( 'change', { value
: value
} );
2606 * Gets the current value of this dialog UI object.
2607 * @returns {Object} The current value.
2609 * var myValue = uiElement.getValue();
2611 getValue : function()
2613 return this.getInputElement().getValue();
2617 * Tells whether the UI object's value has changed.
2618 * @returns {Boolean} true if changed, false if not changed.
2620 * if ( uiElement.isChanged() )
2621 * confirm( 'Value changed! Continue?' );
2623 isChanged : function()
2625 // Override in input classes.
2630 * Selects the parent tab of this element. Usually called by focus() or overridden focus() methods.
2631 * @returns {CKEDITOR.dialog.uiElement} The current UI element.
2633 * focus : function()
2635 * this.selectParentTab();
2636 * // do something else.
2639 selectParentTab : function()
2641 var element
= this.getInputElement(),
2644 while ( ( cursor
= cursor
.getParent() ) && cursor
.$.className
.search( 'cke_dialog_page_contents' ) == -1 )
2647 // Some widgets don't have parent tabs (e.g. OK and Cancel buttons).
2651 tabId
= cursor
.getAttribute( 'name' );
2652 // Avoid duplicate select.
2653 if ( this._
.dialog
._
.currentTabId
!= tabId
)
2654 this._
.dialog
.selectPage( tabId
);
2659 * Puts the focus to the UI object. Switches tabs if the UI object isn't in the active tab page.
2660 * @returns {CKEDITOR.dialog.uiElement} The current UI element.
2662 * uiElement.focus();
2666 this.selectParentTab().getInputElement().focus();
2671 * Registers the on* event handlers defined in the element definition.
2672 * The default behavior of this function is:
2675 * If the on* event is defined in the class's eventProcesors list,
2676 * then the registration is delegated to the corresponding function
2677 * in the eventProcessors list.
2680 * If the on* event is not defined in the eventProcessors list, then
2681 * register the event handler under the corresponding DOM event of
2682 * the UI element's input DOM element (as defined by the return value
2683 * of {@link CKEDITOR.ui.dialog.uiElement#getInputElement}).
2686 * This function is only called at UI element instantiation, but can
2687 * be overridded in child classes if they require more flexibility.
2688 * @param {CKEDITOR.dialog.definition.uiElement} definition The UI element
2690 * @returns {CKEDITOR.dialog.uiElement} The current UI element.
2693 registerEvents : function( definition
)
2695 var regex
= /^on([A-Z]\w+)/,
2698 var registerDomEvent = function( uiElement
, dialog
, eventName
, func
)
2700 dialog
.on( 'load', function()
2702 uiElement
.getInputElement().on( eventName
, func
, uiElement
);
2706 for ( var i
in definition
)
2708 if ( !( match
= i
.match( regex
) ) )
2710 if ( this.eventProcessors
[i
] )
2711 this.eventProcessors
[i
].call( this, this._
.dialog
, definition
[i
] );
2713 registerDomEvent( this, this._
.dialog
, match
[1].toLowerCase(), definition
[i
] );
2720 * The event processor list used by
2721 * {@link CKEDITOR.ui.dialog.uiElement#getInputElement} at UI element
2722 * instantiation. The default list defines three on* events:
2724 * <li>onLoad - Called when the element's parent dialog opens for the
2726 * <li>onShow - Called whenever the element's parent dialog opens.</li>
2727 * <li>onHide - Called whenever the element's parent dialog closes.</li>
2732 * // This connects the 'click' event in CKEDITOR.ui.dialog.button to onClick
2733 * // handlers in the UI element's definitions.
2734 * CKEDITOR.ui.dialog.button.eventProcessors = CKEDITOR.tools.extend( {},
2735 * CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors,
2736 * { onClick : function( dialog, func ) { this.on( 'click', func ); } },
2737 * true );
2741 onLoad : function( dialog
, func
)
2743 dialog
.on( 'load', func
, this );
2746 onShow : function( dialog
, func
)
2748 dialog
.on( 'show', func
, this );
2751 onHide : function( dialog
, func
)
2753 dialog
.on( 'hide', func
, this );
2758 * The default handler for a UI element's access key down event, which
2759 * tries to put focus to the UI element.<br />
2760 * Can be overridded in child classes for more sophisticaed behavior.
2761 * @param {CKEDITOR.dialog} dialog The parent dialog object.
2762 * @param {String} key The key combination pressed. Since access keys
2763 * are defined to always include the CTRL key, its value should always
2764 * include a 'CTRL+' prefix.
2767 accessKeyDown : function( dialog
, key
)
2773 * The default handler for a UI element's access key up event, which
2774 * does nothing.<br />
2775 * Can be overridded in child classes for more sophisticated behavior.
2776 * @param {CKEDITOR.dialog} dialog The parent dialog object.
2777 * @param {String} key The key combination pressed. Since access keys
2778 * are defined to always include the CTRL key, its value should always
2779 * include a 'CTRL+' prefix.
2782 accessKeyUp : function( dialog
, key
)
2787 * Disables a UI element.
2790 disable : function()
2792 var element
= this.getElement(),
2793 input
= this.getInputElement();
2794 input
.setAttribute( 'disabled', 'true' );
2795 element
.addClass( 'cke_disabled' );
2799 * Enables a UI element.
2804 var element
= this.getElement(),
2805 input
= this.getInputElement();
2806 input
.removeAttribute( 'disabled' );
2807 element
.removeClass( 'cke_disabled' );
2811 * Determines whether an UI element is enabled or not.
2812 * @returns {Boolean} Whether the UI element is enabled.
2815 isEnabled : function()
2817 return !this.getElement().hasClass( 'cke_disabled' );
2821 * Determines whether an UI element is visible or not.
2822 * @returns {Boolean} Whether the UI element is visible.
2825 isVisible : function()
2827 return this.getInputElement().isVisible();
2831 * Determines whether an UI element is focus-able or not.
2832 * Focus-able is defined as being both visible and enabled.
2833 * @returns {Boolean} Whether the UI element can be focused.
2836 isFocusable : function()
2838 if ( !this.isEnabled() || !this.isVisible() )
2844 CKEDITOR
.ui
.dialog
.hbox
.prototype = CKEDITOR
.tools
.extend( new CKEDITOR
.ui
.dialog
.uiElement
,
2846 * @lends CKEDITOR.ui.dialog.hbox.prototype
2850 * Gets a child UI element inside this container.
2851 * @param {Array|Number} indices An array or a single number to indicate the child's
2852 * position in the container's descendant tree. Omit to get all the children in an array.
2853 * @returns {Array|CKEDITOR.ui.dialog.uiElement} Array of all UI elements in the container
2854 * if no argument given, or the specified UI element if indices is given.
2856 * var checkbox = hbox.getChild( [0,1] );
2857 * checkbox.setValue( true );
2859 getChild : function( indices
)
2861 // If no arguments, return a clone of the children array.
2862 if ( arguments
.length
< 1 )
2863 return this._
.children
.concat();
2865 // If indices isn't array, make it one.
2866 if ( !indices
.splice
)
2867 indices
= [ indices
];
2869 // Retrieve the child element according to tree position.
2870 if ( indices
.length
< 2 )
2871 return this._
.children
[ indices
[0] ];
2873 return ( this._
.children
[ indices
[0] ] && this._
.children
[ indices
[0] ].getChild
) ?
2874 this._
.children
[ indices
[0] ].getChild( indices
.slice( 1, indices
.length
) ) :
2879 CKEDITOR
.ui
.dialog
.vbox
.prototype = new CKEDITOR
.ui
.dialog
.hbox();
2885 var commonBuilder
= {
2886 build : function( dialog
, elementDefinition
, output
)
2888 var children
= elementDefinition
.children
,
2892 for ( var i
= 0 ; ( i
< children
.length
&& ( child
= children
[i
] ) ) ; i
++ )
2895 childHtmlList
.push( childHtml
);
2896 childObjList
.push( CKEDITOR
.dialog
._
.uiElementBuilders
[ child
.type
].build( dialog
, child
, childHtml
) );
2898 return new CKEDITOR
.ui
.dialog
[elementDefinition
.type
]( dialog
, childObjList
, childHtmlList
, output
, elementDefinition
);
2902 CKEDITOR
.dialog
.addUIElement( 'hbox', commonBuilder
);
2903 CKEDITOR
.dialog
.addUIElement( 'vbox', commonBuilder
);
2907 * Generic dialog command. It opens a specific dialog when executed.
2909 * @augments CKEDITOR.commandDefinition
2910 * @param {string} dialogName The name of the dialog to open when executing
2913 * // Register the "link" command, which opens the "link" dialog.
2914 * editor.addCommand( 'link', <b>new CKEDITOR.dialogCommand( 'link' )</b> );
2916 CKEDITOR
.dialogCommand = function( dialogName
)
2918 this.dialogName
= dialogName
;
2921 CKEDITOR
.dialogCommand
.prototype =
2924 exec : function( editor
)
2926 editor
.openDialog( this.dialogName
);
2929 // Dialog commands just open a dialog ui, thus require no undo logic,
2930 // undo support should dedicate to specific dialog implementation.
2933 editorFocus
: CKEDITOR
.env
.ie
|| CKEDITOR
.env
.webkit
2938 var notEmptyRegex
= /^([a]|[^a])+$/,
2939 integerRegex
= /^\d*$/,
2940 numberRegex
= /^\d*(?:\.\d+)?$/,
2941 htmlLengthRegex
= /^(((\d*(\.\d+))|(\d*))(px|\%)?)?$/,
2942 cssLengthRegex
= /^(((\d*(\.\d+))|(\d*))(px|em|ex|in|cm|mm|pt|pc|\%)?)?$/i;
2944 CKEDITOR
.VALIDATE_OR
= 1;
2945 CKEDITOR
.VALIDATE_AND
= 2;
2947 CKEDITOR
.dialog
.validate
=
2949 functions : function()
2951 var args
= arguments
;
2955 * It's important for validate functions to be able to accept the value
2956 * as argument in addition to this.getValue(), so that it is possible to
2957 * combine validate functions together to make more sophisticated
2960 var value
= this && this.getValue
? this.getValue() : args
[ 0 ];
2962 var msg
= undefined,
2963 relation
= CKEDITOR
.VALIDATE_AND
,
2966 for ( i
= 0 ; i
< args
.length
; i
++ )
2968 if ( typeof( args
[i
] ) == 'function' )
2969 functions
.push( args
[i
] );
2974 if ( i
< args
.length
&& typeof( args
[i
] ) == 'string' )
2980 if ( i
< args
.length
&& typeof( args
[i
]) == 'number' )
2983 var passed
= ( relation
== CKEDITOR
.VALIDATE_AND
? true : false );
2984 for ( i
= 0 ; i
< functions
.length
; i
++ )
2986 if ( relation
== CKEDITOR
.VALIDATE_AND
)
2987 passed
= passed
&& functions
[i
]( value
);
2989 passed
= passed
|| functions
[i
]( value
);
2992 return !passed
? msg
: true;
2996 regex : function( regex
, msg
)
2999 * Can be greatly shortened by deriving from functions validator if code size
3000 * turns out to be more important than performance.
3004 var value
= this && this.getValue
? this.getValue() : arguments
[0];
3005 return !regex
.test( value
) ? msg
: true;
3009 notEmpty : function( msg
)
3011 return this.regex( notEmptyRegex
, msg
);
3014 integer : function( msg
)
3016 return this.regex( integerRegex
, msg
);
3019 'number' : function( msg
)
3021 return this.regex( numberRegex
, msg
);
3024 'cssLength' : function( msg
)
3026 return this.functions( function( val
){ return cssLengthRegex
.test( CKEDITOR
.tools
.trim( val
) ); }, msg
);
3029 'htmlLength' : function( msg
)
3031 return this.functions( function( val
){ return htmlLengthRegex
.test( CKEDITOR
.tools
.trim( val
) ); }, msg
);
3034 equals : function( value
, msg
)
3036 return this.functions( function( val
){ return val
== value
; }, msg
);
3039 notEqual : function( value
, msg
)
3041 return this.functions( function( val
){ return val
!= value
; }, msg
);
3045 CKEDITOR
.on( 'instanceDestroyed', function( evt
)
3047 // Remove dialog cover on last instance destroy.
3048 if ( CKEDITOR
.tools
.isEmpty( CKEDITOR
.instances
) )
3050 var currentTopDialog
;
3051 while ( ( currentTopDialog
= CKEDITOR
.dialog
._
.currentTop
) )
3052 currentTopDialog
.hide();
3056 var dialogs
= evt
.editor
._
.storedDialogs
;
3057 for ( var name
in dialogs
)
3058 dialogs
[ name
].destroy();
3064 // Extend the CKEDITOR.editor class with dialog specific functions.
3065 CKEDITOR
.tools
.extend( CKEDITOR
.editor
.prototype,
3066 /** @lends CKEDITOR.editor.prototype */
3069 * Loads and opens a registered dialog.
3070 * @param {String} dialogName The registered name of the dialog.
3071 * @param {Function} callback The function to be invoked after dialog instance created.
3072 * @see CKEDITOR.dialog.add
3074 * CKEDITOR.instances.editor1.openDialog( 'smiley' );
3075 * @returns {CKEDITOR.dialog} The dialog object corresponding to the dialog displayed. null if the dialog name is not registered.
3077 openDialog : function( dialogName
, callback
)
3079 if ( this.mode
== 'wysiwyg' && CKEDITOR
.env
.ie
)
3081 var selection
= this.getSelection();
3082 selection
&& selection
.lock();
3085 var dialogDefinitions
= CKEDITOR
.dialog
._
.dialogDefinitions
[ dialogName
],
3086 dialogSkin
= this.skin
.dialog
;
3088 if ( CKEDITOR
.dialog
._
.currentTop
=== null )
3091 // If the dialogDefinition is already loaded, open it immediately.
3092 if ( typeof dialogDefinitions
== 'function' && dialogSkin
._isLoaded
)
3094 var storedDialogs
= this._
.storedDialogs
||
3095 ( this._
.storedDialogs
= {} );
3097 var dialog
= storedDialogs
[ dialogName
] ||
3098 ( storedDialogs
[ dialogName
] = new CKEDITOR
.dialog( this, dialogName
) );
3100 callback
&& callback
.call( dialog
, dialog
);
3105 else if ( dialogDefinitions
== 'failed' )
3108 throw new Error( '[CKEDITOR.dialog.openDialog] Dialog "' + dialogName
+ '" failed when loading definition.' );
3113 function onDialogFileLoaded( success
)
3115 var dialogDefinition
= CKEDITOR
.dialog
._
.dialogDefinitions
[ dialogName
],
3116 skin
= me
.skin
.dialog
;
3118 // Check if both skin part and definition is loaded.
3119 if ( !skin
._isLoaded
|| loadDefinition
&& typeof success
== 'undefined' )
3122 // In case of plugin error, mark it as loading failed.
3123 if ( typeof dialogDefinition
!= 'function' )
3124 CKEDITOR
.dialog
._
.dialogDefinitions
[ dialogName
] = 'failed';
3126 me
.openDialog( dialogName
, callback
);
3129 if ( typeof dialogDefinitions
== 'string' )
3131 var loadDefinition
= 1;
3132 CKEDITOR
.scriptLoader
.load( CKEDITOR
.getUrl( dialogDefinitions
), onDialogFileLoaded
, null, 0, 1 );
3135 CKEDITOR
.skins
.load( this, 'dialog', onDialogFileLoaded
);
3142 CKEDITOR
.plugins
.add( 'dialog',
3144 requires
: [ 'dialogui' ]
3147 // Dialog related configurations.
3150 * The color of the dialog background cover. It should be a valid CSS color
3152 * @name CKEDITOR.config.dialog_backgroundCoverColor
3156 * config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)';
3160 * The opacity of the dialog background cover. It should be a number within the
3162 * @name CKEDITOR.config.dialog_backgroundCoverOpacity
3166 * config.dialog_backgroundCoverOpacity = 0.7;
3170 * If the dialog has more than one tab, put focus into the first tab as soon as dialog is opened.
3171 * @name CKEDITOR.config.dialog_startupFocusTab
3175 * config.dialog_startupFocusTab = true;
3179 * The distance of magnetic borders used in moving and resizing dialogs,
3180 * measured in pixels.
3181 * @name CKEDITOR.config.dialog_magnetDistance
3185 * config.dialog_magnetDistance = 30;
3189 * The guideline to follow when generating the dialog buttons. There are 3 possible options:
3191 * <li>'OS' - the buttons will be displayed in the default order of the user's OS;</li>
3192 * <li>'ltr' - for Left-To-Right order;</li>
3193 * <li>'rtl' - for Right-To-Left order.</li>
3195 * @name CKEDITOR.config.dialog_buttonsOrder
3200 * config.dialog_buttonsOrder = 'rtl';
3204 * The dialog contents to removed. It's a string composed by dialog name and tab name with a colon between them.
3205 * Separate each pair with semicolon (see example).
3206 * <b>Note: All names are case-sensitive.</b>
3207 * <b>Note: Be cautious when specifying dialog tabs that are mandatory, like "info", dialog functionality might be broken because of this!</b>
3208 * @name CKEDITOR.config.removeDialogTabs
3213 * config.removeDialogTabs = 'flash:advanced;image:Link';
3217 * Fired when a dialog definition is about to be used to create a dialog into
3218 * an editor instance. This event makes it possible to customize the definition
3219 * before creating it.
3220 * <p>Note that this event is called only the first time a specific dialog is
3221 * opened. Successive openings will use the cached dialog, and this event will
3222 * not get fired.</p>
3223 * @name CKEDITOR#dialogDefinition
3225 * @param {CKEDITOR.dialog.definition} data The dialog defination that
3227 * @param {CKEDITOR.editor} editor The editor instance that will use the
3232 * Fired when a tab is going to be selected in a dialog
3233 * @name CKEDITOR.dialog#selectPage
3235 * @param {String} page The id of the page that it's gonna be selected.
3236 * @param {String} currentPage The id of the current page.
3240 * Fired when the user tries to dismiss a dialog
3241 * @name CKEDITOR.dialog#cancel
3243 * @param {Boolean} hide Whether the event should proceed or not.
3247 * Fired when the user tries to confirm a dialog
3248 * @name CKEDITOR.dialog#ok
3250 * @param {Boolean} hide Whether the event should proceed or not.
3254 * Fired when a dialog is shown
3255 * @name CKEDITOR.dialog#show
3260 * Fired when a dialog is shown
3261 * @name CKEDITOR.editor#dialogShow
3266 * Fired when a dialog is hidden
3267 * @name CKEDITOR.dialog#hide
3272 * Fired when a dialog is hidden
3273 * @name CKEDITOR.editor#dialogHide
3278 * Fired when a dialog is being resized. The event is fired on
3279 * both the 'CKEDITOR.dialog' object and the dialog instance
3280 * since 3.5.3, previously it's available only in the global object.
3281 * @name CKEDITOR.dialog#resize
3284 * @param {CKEDITOR.dialog} dialog The dialog being resized (if
3285 * it's fired on the dialog itself, this parameter isn't sent).
3286 * @param {String} skin The skin name.
3287 * @param {Number} width The new width.
3288 * @param {Number} height The new height.