JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.1
[ckeditor.git] / _source / plugins / dialog / plugin.js
index b41cd10..706c92b 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
 For licensing, see LICENSE.html or http://ckeditor.com/license\r
 */\r
 \r
@@ -7,11 +7,6 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
  * @fileOverview The floating dialog plugin.\r
  */\r
 \r
-CKEDITOR.plugins.add( 'dialog',\r
-       {\r
-               requires : [ 'dialogui' ]\r
-       });\r
-\r
 /**\r
  * No resize for this dialog.\r
  * @constant\r
@@ -73,9 +68,6 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                return null;\r
        }\r
 \r
-       // Stores dialog related data from skin definitions. e.g. margin sizes.\r
-       var skinData = {};\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
@@ -89,11 +81,6 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
        {\r
                // Load the dialog definition.\r
                var definition = CKEDITOR.dialog._.dialogDefinitions[ dialogName ];\r
-               if ( !definition )\r
-               {\r
-                       console.log( 'Error: The dialog "' + dialogName + '" is not defined.' );\r
-                       return;\r
-               }\r
 \r
                // Completes the definition with the default values.\r
                definition = CKEDITOR.tools.extend( definition( editor ), defaultDialogDefinition );\r
@@ -264,11 +251,12 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                        if ( focusList.length < 1 )\r
                                return;\r
 \r
-                       var currentIndex = ( me._.currentFocusIndex + offset + focusList.length ) % focusList.length;\r
+                       var startIndex = ( me._.currentFocusIndex + offset + focusList.length ) % focusList.length,\r
+                               currentIndex = startIndex;\r
                        while ( !focusList[ currentIndex ].isFocusable() )\r
                        {\r
                                currentIndex = ( currentIndex + offset + focusList.length ) % focusList.length;\r
-                               if ( currentIndex == me._.currentFocusIndex )\r
+                               if ( currentIndex == startIndex )\r
                                        break;\r
                        }\r
                        focusList[ currentIndex ].focus();\r
@@ -278,14 +266,17 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                                focusList[ currentIndex ].select();\r
                }\r
 \r
+               var processed;\r
+\r
                function focusKeydownHandler( evt )\r
                {\r
                        // If I'm not the top dialog, ignore.\r
                        if ( me != CKEDITOR.dialog._.currentTop )\r
                                return;\r
 \r
-                       var keystroke = evt.data.getKeystroke(),\r
-                               processed = false;\r
+                       var keystroke = evt.data.getKeystroke();\r
+\r
+                       processed = 0;\r
                        if ( keystroke == 9 || keystroke == CKEDITOR.SHIFT + 9 )\r
                        {\r
                                var shiftPressed = ( keystroke == CKEDITOR.SHIFT + 9 );\r
@@ -304,14 +295,14 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                                        changeFocus( !shiftPressed );\r
                                }\r
 \r
-                               processed = true;\r
+                               processed = 1;\r
                        }\r
                        else if ( keystroke == CKEDITOR.ALT + 121 && !me._.tabBarMode )\r
                        {\r
                                // Alt-F10 puts focus into the current tab item in the tab bar.\r
                                me._.tabBarMode = true;\r
                                me._.tabs[ me._.currentTabId ][ 0 ].focus();\r
-                               processed = true;\r
+                               processed = 1;\r
                        }\r
                        else if ( ( keystroke == 37 || keystroke == 39 ) && me._.tabBarMode )\r
                        {\r
@@ -319,7 +310,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                                nextId = ( keystroke == 37 ? getPreviousVisibleTab.call( me ) : getNextVisibleTab.call( me ) );\r
                                me.selectPage( nextId );\r
                                me._.tabs[ nextId ][ 0 ].focus();\r
-                               processed = true;\r
+                               processed = 1;\r
                        }\r
 \r
                        if ( processed )\r
@@ -329,10 +320,19 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                        }\r
                }\r
 \r
+               function focusKeyPressHandler( evt )\r
+               {\r
+                       processed && evt.data.preventDefault();\r
+               }\r
+\r
                // Add the dialog keyboard handlers.\r
                this.on( 'show', function()\r
                        {\r
                                CKEDITOR.document.on( 'keydown', focusKeydownHandler, this, null, 0 );\r
+                               // Some browsers instead, don't cancel key events in the keydown, but in the\r
+                               // keypress. So we must do a longer trip in those cases. (#4531)\r
+                               if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) )\r
+                                       CKEDITOR.document.on( 'keypress', focusKeyPressHandler, this );\r
 \r
                                if ( CKEDITOR.env.ie6Compat )\r
                                {\r
@@ -343,6 +343,8 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                this.on( 'hide', function()\r
                        {\r
                                CKEDITOR.document.removeListener( 'keydown', focusKeydownHandler );\r
+                               if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) )\r
+                                       CKEDITOR.document.removeListener( 'keypress', focusKeyPressHandler );\r
                        } );\r
                this.on( 'iframeAdded', function( evt )\r
                        {\r
@@ -447,12 +449,13 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
        };\r
 \r
        // Focusable interface. Use it via dialog.addFocusable.\r
-       function Focusable( dialog, element, index ) {\r
+       function Focusable( dialog, element, index )\r
+       {\r
                this.element = element;\r
                this.focusIndex = index;\r
                this.isFocusable = function()\r
                {\r
-                       return true;\r
+                       return !element.getAttribute( 'disabled' ) && element.isVisible();\r
                };\r
                this.focus = function()\r
                {\r
@@ -580,8 +583,12 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                 */\r
                show : function()\r
                {\r
-                       if ( this._.editor.mode == 'wysiwyg' && CKEDITOR.env.ie )\r
-                               this._.editor.getSelection().lock();\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
@@ -625,12 +632,12 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                                this._.parentDialog = null;\r
                                addCover( this._.editor );\r
 \r
-                               CKEDITOR.document.on( 'keydown', accessKeyDownHandler );\r
-                               CKEDITOR.document.on( 'keyup', accessKeyUpHandler );\r
+                               element.on( 'keydown', accessKeyDownHandler );\r
+                               element.on( CKEDITOR.env.opera ? 'keypress' : 'keyup', accessKeyUpHandler );\r
 \r
                                // Prevent some keys from bubbling up. (#4269)\r
                                for ( var event in { keyup :1, keydown :1, keypress :1 } )\r
-                                       CKEDITOR.document.on( event, preventKeyBubbling );\r
+                                       element.on( event, preventKeyBubbling );\r
                        }\r
                        else\r
                        {\r
@@ -664,6 +671,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                                        // Execute onLoad for the first show.\r
                                        this.fireOnce( 'load', {} );\r
                                        this.fire( 'show', {} );\r
+                                       this._.editor.fire( 'dialogShow', this );\r
 \r
                                        // Save the initial values of the dialog.\r
                                        this.foreach( function( contentObj ) { contentObj.setInitValue && contentObj.setInitValue(); } );\r
@@ -727,6 +735,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                hide : function()\r
                {\r
                        this.fire( 'hide', {} );\r
+                       this._.editor.fire( 'dialogHide', this );\r
 \r
                        // Remove the dialog's element from the root document.\r
                        var element = this._.element;\r
@@ -755,19 +764,21 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                                CKEDITOR.dialog._.currentZIndex = null;\r
 \r
                                // Remove access key handlers.\r
-                               CKEDITOR.document.removeListener( 'keydown', accessKeyDownHandler );\r
-                               CKEDITOR.document.removeListener( 'keyup', accessKeyUpHandler );\r
-                               CKEDITOR.document.removeListener( 'keypress', accessKeyUpHandler );\r
+                               element.removeListener( 'keydown', accessKeyDownHandler );\r
+                               element.removeListener( CKEDITOR.env.opera ? 'keypress' : 'keyup', accessKeyUpHandler );\r
 \r
                                // Remove bubbling-prevention handler. (#4269)\r
                                for ( var event in { keyup :1, keydown :1, keypress :1 } )\r
-                                       CKEDITOR.document.removeListener( event, preventKeyBubbling );\r
+                                       element.removeListener( event, preventKeyBubbling );\r
 \r
                                var editor = this._.editor;\r
                                editor.focus();\r
 \r
                                if ( editor.mode == 'wysiwyg' && CKEDITOR.env.ie )\r
-                                       editor.getSelection().unlock( true );\r
+                               {\r
+                                       var selection = editor.getSelection();\r
+                                       selection && selection.unlock( true );\r
+                               }\r
                        }\r
                        else\r
                                CKEDITOR.dialog._.currentZIndex -= 10;\r
@@ -794,7 +805,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                                                        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
@@ -1437,7 +1448,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                        element = dialog.getElement().getFirst(),\r
                        editor = dialog.getParentEditor(),\r
                        magnetDistance = editor.config.dialog_magnetDistance,\r
-                       margins = skinData[ editor.skinName ].margins || [ 0, 0, 0, 0 ];\r
+                       margins = editor.skin.margins || [ 0, 0, 0, 0 ];\r
 \r
                if ( typeof magnetDistance == 'undefined' )\r
                        magnetDistance = 20;\r
@@ -1515,7 +1526,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                        minWidth = definition.minWidth || 0,\r
                        minHeight = definition.minHeight || 0,\r
                        resizable = definition.resizable,\r
-                       margins = skinData[ dialog.getParentEditor().skinName ].margins || [ 0, 0, 0, 0 ];\r
+                       margins = dialog.getParentEditor().skin.margins || [ 0, 0, 0, 0 ];\r
 \r
                function topSizer( coords, dy )\r
                {\r
@@ -1661,11 +1672,13 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
 \r
                if ( !coverElement )\r
                {\r
+                       var backgroundColorStyle = editor.config.dialog_backgroundCoverColor || 'white';\r
+\r
                        var html = [\r
                                        '<div style="position: ', ( CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed' ),\r
                                        '; z-index: ', editor.config.baseFloatZIndex,\r
                                        '; top: 0px; left: 0px; ',\r
-                                       'background-color: ', editor.config.dialog_backgroundCoverColor || 'white',\r
+                                       ( !CKEDITOR.env.ie6Compat ? 'background-color: ' + backgroundColorStyle : '' ),\r
                                        '" id="cke_dialog_background_cover">'\r
                                ];\r
 \r
@@ -1673,7 +1686,8 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                        if ( CKEDITOR.env.ie6Compat )\r
                        {\r
                                // Support for custom document.domain in IE.\r
-                               var isCustomDomain = CKEDITOR.env.isCustomDomain();\r
+                               var isCustomDomain = CKEDITOR.env.isCustomDomain(),\r
+                                       iframeHtml = '<html><body style=\\\'background-color:' + backgroundColorStyle + ';\\\'></body></html>';\r
 \r
                                html.push(\r
                                        '<iframe' +\r
@@ -1682,15 +1696,12 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                                                ' id="cke_dialog_background_iframe"' +\r
                                                ' src="javascript:' );\r
 \r
-                               html.push(\r
-                                               isCustomDomain ?\r
-                                                       'void((function(){' +\r
+                               html.push( 'void((function(){' +\r
                                                                'document.open();' +\r
-                                                               'document.domain=\'' + document.domain + '\';' +\r
+                                                               ( isCustomDomain ? 'document.domain=\'' + document.domain + '\';' : '' ) +\r
+                                                               'document.write( \'' + iframeHtml + '\' );' +\r
                                                                'document.close();' +\r
-                                                       '})())'\r
-                                               :\r
-                                                       '\'\'' );\r
+                                                       '})())' );\r
 \r
                                html.push(\r
                                                '"' +\r
@@ -1814,8 +1825,11 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                        return;\r
 \r
                keyProcessor = keyProcessor[keyProcessor.length - 1];\r
-               keyProcessor.keyup && keyProcessor.keyup.call( keyProcessor.uiElement, keyProcessor.dialog, keyProcessor.key );\r
-               evt.data.preventDefault();\r
+               if ( keyProcessor.keyup )\r
+               {\r
+                       keyProcessor.keyup.call( keyProcessor.uiElement, keyProcessor.dialog, keyProcessor.key );\r
+                       evt.data.preventDefault();\r
+               }\r
        };\r
 \r
        var registerAccessKey = function( uiElement, dialog, key, downFunc, upFunc )\r
@@ -2448,7 +2462,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                 */\r
                isVisible : function()\r
                {\r
-                       return !!this.getInputElement().$.offsetHeight;\r
+                       return this.getInputElement().isVisible();\r
                },\r
 \r
                /**\r
@@ -2672,17 +2686,6 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3;
                        }\r
                };\r
        })();\r
-\r
-       // Grab the margin data from skin definition and store it away.\r
-       CKEDITOR.skins.add = ( function()\r
-       {\r
-               var original = CKEDITOR.skins.add;\r
-               return function( skinName, skinDefinition )\r
-               {\r
-                       skinData[ skinName ] = { margins : skinDefinition.margins };\r
-                       return original.apply( this, arguments );\r
-               };\r
-       } )();\r
 })();\r
 \r
 // Extend the CKEDITOR.editor class with dialog specific functions.\r
@@ -2692,12 +2695,13 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                /**\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 )\r
+               openDialog : function( dialogName, callback )\r
                {\r
                        var dialogDefinitions = CKEDITOR.dialog._.dialogDefinitions[ dialogName ];\r
 \r
@@ -2710,6 +2714,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                                var dialog = storedDialogs[ dialogName ] ||\r
                                        ( storedDialogs[ dialogName ] = new CKEDITOR.dialog( this, dialogName ) );\r
 \r
+                               callback && callback.call( dialog, dialog );\r
                                dialog.show();\r
 \r
                                return dialog;\r
@@ -2728,7 +2733,7 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                                        // In case of plugin error, mark it as loading failed.\r
                                        if ( typeof CKEDITOR.dialog._.dialogDefinitions[ dialogName ] != 'function' )\r
                                                        CKEDITOR.dialog._.dialogDefinitions[ dialogName ] =  'failed';\r
-                                       me.openDialog( dialogName );\r
+                                       me.openDialog( dialogName, callback );\r
                                        body.setStyle( 'cursor', cursor );\r
                                } );\r
 \r
@@ -2736,6 +2741,11 @@ CKEDITOR.tools.extend( CKEDITOR.editor.prototype,
                }\r
        });\r
 \r
+CKEDITOR.plugins.add( 'dialog',\r
+       {\r
+               requires : [ 'dialogui' ]\r
+       });\r
+\r
 // Dialog related configurations.\r
 \r
 /**\r