JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.4
[ckeditor.git] / _source / plugins / dialogui / plugin.js
index fc3a7f4..7875b5b 100644 (file)
@@ -59,9 +59,9 @@ CKEDITOR.plugins.add( 'dialogui' );
                        return this.getValue() != this.getInitValue();\r
                },\r
 \r
-               reset : function()\r
+               reset : function( noChangeEvent )\r
                {\r
-                       this.setValue( this.getInitValue() );\r
+                       this.setValue( this.getInitValue(), noChangeEvent );\r
                },\r
 \r
                setInitValue : function()\r
@@ -147,14 +147,15 @@ CKEDITOR.plugins.add( 'dialogui' );
                                        return;\r
 \r
                                var _ = initPrivateObject.call( this, elementDefinition );\r
-                               _.labelId = CKEDITOR.tools.getNextNumber() + '_label';\r
+                               _.labelId = CKEDITOR.tools.getNextId() + '_label';\r
                                var children = this._.children = [];\r
                                /** @ignore */\r
                                var innerHTML = function()\r
                                {\r
-                                       var html = [];\r
+                                       var html = [],\r
+                                               requiredClass = elementDefinition.required ? ' cke_required' : '' ;\r
                                        if ( elementDefinition.labelLayout != 'horizontal' )\r
-                                               html.push( '<label class="cke_dialog_ui_labeled_label" ',\r
+                                               html.push( '<label class="cke_dialog_ui_labeled_label' + requiredClass + '" ',\r
                                                                ' id="'+  _.labelId + '"',\r
                                                                ' for="' + _.inputId + '"',\r
                                                                ' style="' + elementDefinition.labelStyle + '">',\r
@@ -173,7 +174,7 @@ CKEDITOR.plugins.add( 'dialogui' );
                                                        [\r
                                                                {\r
                                                                        type : 'html',\r
-                                                                       html : '<label class="cke_dialog_ui_labeled_label"' +\r
+                                                                       html : '<label class="cke_dialog_ui_labeled_label' + requiredClass + '"' +\r
                                                                                ' id="' + _.labelId + '"' +\r
                                                                                ' for="' + _.inputId + '"' +\r
                                                                                ' style="' + elementDefinition.labelStyle + '">' +\r
@@ -222,7 +223,7 @@ CKEDITOR.plugins.add( 'dialogui' );
                                        return;\r
 \r
                                initPrivateObject.call( this, elementDefinition );\r
-                               var domId = this._.inputId = CKEDITOR.tools.getNextNumber() + '_textInput',\r
+                               var domId = this._.inputId = CKEDITOR.tools.getNextId() + '_textInput',\r
                                        attributes = { 'class' : 'cke_dialog_ui_input_' + elementDefinition.type, id : domId, type : 'text' },\r
                                        i;\r
 \r
@@ -236,6 +237,9 @@ CKEDITOR.plugins.add( 'dialogui' );
                                if ( elementDefinition.size )\r
                                        attributes.size = elementDefinition.size;\r
 \r
+                               if ( elementDefinition.controlStyle )\r
+                                       attributes.style = elementDefinition.controlStyle;\r
+\r
                                // If user presses Enter in a text box, it implies clicking OK for the dialog.\r
                                var me = this, keyPressedOnMe = false;\r
                                dialog.on( 'load', function()\r
@@ -309,7 +313,7 @@ CKEDITOR.plugins.add( 'dialogui' );
 \r
                                initPrivateObject.call( this, elementDefinition );\r
                                var me = this,\r
-                                       domId = this._.inputId = CKEDITOR.tools.getNextNumber() + '_textarea',\r
+                                       domId = this._.inputId = CKEDITOR.tools.getNextId() + '_textarea',\r
                                        attributes = {};\r
 \r
                                if ( elementDefinition.validate )\r
@@ -366,15 +370,19 @@ CKEDITOR.plugins.add( 'dialogui' );
                                {\r
                                        var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition,\r
                                                        {\r
-                                                               id : elementDefinition.id ? elementDefinition.id + '_checkbox' : CKEDITOR.tools.getNextNumber() + '_checkbox'\r
+                                                               id : elementDefinition.id ? elementDefinition.id + '_checkbox' : CKEDITOR.tools.getNextId() + '_checkbox'\r
                                                        }, true ),\r
                                                html = [];\r
 \r
-                                       var labelId = CKEDITOR.tools.getNextNumber() + '_label';\r
+                                       var labelId = CKEDITOR.tools.getNextId() + '_label';\r
                                        var attributes = { 'class' : 'cke_dialog_ui_checkbox_input', type : 'checkbox', 'aria-labelledby' : labelId };\r
                                        cleanInnerDefinition( myDefinition );\r
                                        if ( elementDefinition[ 'default' ] )\r
                                                attributes.checked = 'checked';\r
+\r
+                                       if (typeof myDefinition.controlStyle != 'undefined')\r
+                                               myDefinition.style = myDefinition.controlStyle;\r
+\r
                                        _.checkbox = new CKEDITOR.ui.dialog.uiElement( dialog, myDefinition, html, 'input', null, attributes );\r
                                        html.push( ' <label id="', labelId, '" for="', attributes.id, '">',\r
                                                        CKEDITOR.tools.htmlEncode( elementDefinition.label ),\r
@@ -422,13 +430,13 @@ CKEDITOR.plugins.add( 'dialogui' );
                                {\r
                                        var inputHtmlList = [], html = [],\r
                                                commonAttributes = { 'class' : 'cke_dialog_ui_radio_item', 'aria-labelledby' : this._.labelId },\r
-                                               commonName = elementDefinition.id ? elementDefinition.id + '_radio' : CKEDITOR.tools.getNextNumber() + '_radio';\r
+                                               commonName = elementDefinition.id ? elementDefinition.id + '_radio' : CKEDITOR.tools.getNextId() + '_radio';\r
                                        for ( var i = 0 ; i < elementDefinition.items.length ; i++ )\r
                                        {\r
                                                var item = elementDefinition.items[i],\r
                                                        title = item[2] !== undefined ? item[2] : item[0],\r
                                                        value = item[1] !== undefined ? item[1] : item[0],\r
-                                                       inputId = CKEDITOR.tools.getNextNumber() + '_radio_input',\r
+                                                       inputId = CKEDITOR.tools.getNextId() + '_radio_input',\r
                                                        labelId = inputId + '_label',\r
                                                        inputDefinition = CKEDITOR.tools.extend( {}, elementDefinition,\r
                                                                        {\r
@@ -453,6 +461,10 @@ CKEDITOR.plugins.add( 'dialogui' );
                                                        inputAttributes.checked = 'checked';\r
                                                cleanInnerDefinition( inputDefinition );\r
                                                cleanInnerDefinition( labelDefinition );\r
+\r
+                                               if (typeof inputDefinition.controlStyle != 'undefined')\r
+                                                       inputDefinition.style = inputDefinition.controlStyle;\r
+\r
                                                children.push( new CKEDITOR.ui.dialog.uiElement( dialog, inputDefinition, inputHtml, 'input', null, inputAttributes ) );\r
                                                inputHtml.push( ' ' );\r
                                                new CKEDITOR.ui.dialog.uiElement( dialog, labelDefinition, inputHtml, 'label', null, { id : labelId, 'for' : inputAttributes.id },\r
@@ -528,7 +540,7 @@ CKEDITOR.plugins.add( 'dialogui' );
                                var outerDefinition = CKEDITOR.tools.extend( {}, elementDefinition );\r
                                delete outerDefinition.style;\r
 \r
-                               var labelId = CKEDITOR.tools.getNextNumber() + '_label';\r
+                               var labelId = CKEDITOR.tools.getNextId() + '_label';\r
                                CKEDITOR.ui.dialog.uiElement.call(\r
                                        this,\r
                                        dialog,\r
@@ -584,13 +596,13 @@ CKEDITOR.plugins.add( 'dialogui' );
                                if ( elementDefinition.validate )\r
                                        this.validate = elementDefinition.validate;\r
 \r
-                               _.inputId = CKEDITOR.tools.getNextNumber() + '_select';\r
+                               _.inputId = CKEDITOR.tools.getNextId() + '_select';\r
                                /** @ignore */\r
                                var innerHTML = function()\r
                                {\r
                                        var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition,\r
                                                        {\r
-                                                               id : elementDefinition.id ? elementDefinition.id + '_select' : CKEDITOR.tools.getNextNumber() + '_select'\r
+                                                               id : elementDefinition.id ? elementDefinition.id + '_select' : CKEDITOR.tools.getNextId() + '_select'\r
                                                        }, true ),\r
                                                html = [],\r
                                                innerHTML = [],\r
@@ -610,6 +622,9 @@ CKEDITOR.plugins.add( 'dialogui' );
                                                        CKEDITOR.tools.htmlEncode( item[0] ) );\r
                                        }\r
 \r
+                                       if (typeof myDefinition.controlStyle != 'undefined')\r
+                                               myDefinition.style = myDefinition.controlStyle;\r
+\r
                                        _.select = new CKEDITOR.ui.dialog.uiElement( dialog, myDefinition, html, 'select', null, attributes, innerHTML.join( '' ) );\r
                                        return html.join( '' );\r
                                };\r
@@ -648,7 +663,7 @@ CKEDITOR.plugins.add( 'dialogui' );
                                /** @ignore */\r
                                var innerHTML = function()\r
                                {\r
-                                       _.frameId = CKEDITOR.tools.getNextNumber() + '_fileInput';\r
+                                       _.frameId = CKEDITOR.tools.getNextId() + '_fileInput';\r
 \r
                                        // Support for custom document.domain in IE.\r
                                        var isCustomDomain = CKEDITOR.env.isCustomDomain();\r
@@ -1046,7 +1061,7 @@ CKEDITOR.plugins.add( 'dialogui' );
                                setValue : function( value )\r
                                {\r
                                        !value && ( value = '' );\r
-                                       return CKEDITOR.ui.dialog.uiElement.prototype.setValue.call( this, value );\r
+                                       return CKEDITOR.ui.dialog.uiElement.prototype.setValue.apply( this, arguments );\r
                                },\r
 \r
                                keyboardFocusable : true\r
@@ -1141,11 +1156,12 @@ CKEDITOR.plugins.add( 'dialogui' );
                                 * Sets the state of the checkbox.\r
                                 * @example\r
                                 * @param {Boolean} true to tick the checkbox, false to untick it.\r
+                                * @param {Boolean} noChangeEvent Internal commit, to supress 'change' event on this element.\r
                                 */\r
-                               setValue : function( checked )\r
+                               setValue : function( checked, noChangeEvent )\r
                                {\r
                                        this.getInputElement().$.checked = checked;\r
-                                       this.fire( 'change', { value : checked } );\r
+                                       !noChangeEvent && this.fire( 'change', { value : checked } );\r
                                },\r
 \r
                                /**\r
@@ -1207,14 +1223,15 @@ CKEDITOR.plugins.add( 'dialogui' );
                                 * Checks one of the radio buttons in this button group.\r
                                 * @example\r
                                 * @param {String} value The value of the button to be chcked.\r
+                                * @param {Boolean} noChangeEvent Internal commit, to supress 'change' event on this element.\r
                                 */\r
-                               setValue : function( value )\r
+                               setValue : function( value, noChangeEvent )\r
                                {\r
                                        var children = this._.children,\r
                                                item;\r
                                        for ( var i = 0 ; ( i < children.length ) && ( item = children[i] ) ; i++ )\r
                                                item.getElement().$.checked = ( item.getValue() == value );\r
-                                       this.fire( 'change', { value : value } );\r
+                                       !noChangeEvent && this.fire( 'change', { value : value } );\r
                                },\r
 \r
                                /**\r
@@ -1323,12 +1340,43 @@ CKEDITOR.plugins.add( 'dialogui' );
                                 * @returns {String} The value of the action.\r
                                 * @example\r
                                 */\r
-                               getAction : function( action )\r
+                               getAction : function()\r
                                {\r
                                        return this.getInputElement().getParent().$.action;\r
                                },\r
 \r
                                /**\r
+                                * The events must be applied on the inner input element, and\r
+                                * that must be done when the iframe & form has been loaded\r
+                                */\r
+                               registerEvents : function( definition )\r
+                               {\r
+                                       var regex = /^on([A-Z]\w+)/,\r
+                                               match;\r
+\r
+                                       var registerDomEvent = function( uiElement, dialog, eventName, func )\r
+                                       {\r
+                                               uiElement.on( 'formLoaded', function()\r
+                                               {\r
+                                                       uiElement.getInputElement().on( eventName, func, uiElement );\r
+                                               });\r
+                                       };\r
+\r
+                                       for ( var i in definition )\r
+                                       {\r
+                                               if ( !( match = i.match( regex ) ) )\r
+                                                       continue;\r
+\r
+                                               if ( this.eventProcessors[i] )\r
+                                                       this.eventProcessors[i].call( this, this._.dialog, definition[i] );\r
+                                               else\r
+                                                       registerDomEvent( this, this._.dialog, match[1].toLowerCase(), definition[i] );\r
+                                       }\r
+\r
+                                       return this;\r
+                               },\r
+\r
+                               /**\r
                                 * Redraws the file input and resets the file path in the file input.\r
                                 * The redraw logic is necessary because non-IE browsers tend to clear\r
                                 * the &lt;iframe&gt; containing the file input after closing the dialog.\r
@@ -1339,7 +1387,36 @@ CKEDITOR.plugins.add( 'dialogui' );
                                        var frameElement = CKEDITOR.document.getById( this._.frameId ),\r
                                                frameDocument = frameElement.getFrameDocument(),\r
                                                elementDefinition = this._.definition,\r
-                                               buttons = this._.buttons;\r
+                                               buttons = this._.buttons,\r
+                                               callNumber = this.formLoadedNumber,\r
+                                               unloadNumber = this.formUnloadNumber,\r
+                                               langDir = this._.dialog._.editor.lang.dir,\r
+                                               langCode = this._.dialog._.editor.langCode;\r
+\r
+                                       // The callback function for the iframe, but we must call tools.addFunction only once\r
+                                       // so we store the function number in this.formLoadedNumber\r
+                                       if (!callNumber)\r
+                                       {\r
+                                               callNumber = this.formLoadedNumber = CKEDITOR.tools.addFunction(\r
+                                                       function()\r
+                                                       {\r
+                                                               // Now we can apply the events to the input type=file\r
+                                                               this.fire( 'formLoaded' ) ;\r
+                                                       }, this ) ;\r
+\r
+                                               // Remove listeners attached to the content of the iframe (the file input)\r
+                                               unloadNumber = this.formUnloadNumber = CKEDITOR.tools.addFunction(\r
+                                                       function()\r
+                                                       {\r
+                                                               this.getInputElement().clearCustomData();\r
+                                                       }, this ) ;\r
+\r
+                                               this.getDialog()._.editor.on( 'destroy', function()\r
+                                                               {\r
+                                                                       CKEDITOR.tools.removeFunction( callNumber );\r
+                                                                       CKEDITOR.tools.removeFunction( unloadNumber );\r
+                                                               } );\r
+                                       }\r
 \r
                                        function generateFormField()\r
                                        {\r
@@ -1353,8 +1430,8 @@ CKEDITOR.plugins.add( 'dialogui' );
                                                if ( elementDefinition.size )\r
                                                        size = elementDefinition.size - ( CKEDITOR.env.ie  ? 7 : 0 );   // "Browse" button is bigger in IE.\r
 \r
-                                               frameDocument.$.write( [ '<html><head><title></title></head><body style="margin: 0; overflow: hidden; background: transparent;">',\r
-                                                               '<form enctype="multipart/form-data" method="POST" action="',\r
+                                               frameDocument.$.write( [ '<html dir="' + langDir + '" lang="' + langCode + '"><head><title></title></head><body style="margin: 0; overflow: hidden; background: transparent;">',\r
+                                                               '<form enctype="multipart/form-data" method="POST" dir="' + langDir + '" lang="' + langCode + '" action="',\r
                                                                CKEDITOR.tools.htmlEncode( elementDefinition.action ),\r
                                                                '">',\r
                                                                '<input type="file" name="',\r
@@ -1363,7 +1440,9 @@ CKEDITOR.plugins.add( 'dialogui' );
                                                                CKEDITOR.tools.htmlEncode( size > 0 ? size : "" ),\r
                                                                '" />',\r
                                                                '</form>',\r
-                                                               '</body></html>' ].join( '' ) );\r
+                                                               '</body></html>',\r
+                                                               '<script>window.parent.CKEDITOR.tools.callFunction(' + callNumber + ');',\r
+                                                               'window.onbeforeunload = function() {window.parent.CKEDITOR.tools.callFunction(' + unloadNumber + ')}</script>' ].join( '' ) );\r
 \r
                                                frameDocument.$.close();\r
 \r
@@ -1380,10 +1459,18 @@ CKEDITOR.plugins.add( 'dialogui' );
 \r
                                getValue : function()\r
                                {\r
-                                       // The file path returned from the input tag is incomplete anyway, so it's\r
-                                       // safe to ignore it and prevent the confirmation dialog from appearing.\r
-                                       // (Part of #3465)\r
-                                       return '';\r
+                                       return this.getInputElement().$.value;\r
+                               },\r
+\r
+                               /***\r
+                                * The default value of input type="file" is an empty string, but during initialization\r
+                                * of this UI element, the iframe still isn't ready so it can't be read from that object\r
+                                * Setting it manually prevents later issues about the current value ("") being different\r
+                                * of the initial value (undefined as it asked for .value of a div)\r
+                                */\r
+                               setInitValue : function()\r
+                               {\r
+                                       this._.initValue = '';\r
                                },\r
 \r
                                /**\r
@@ -1392,7 +1479,27 @@ CKEDITOR.plugins.add( 'dialogui' );
                                 * @type Object\r
                                 * @example\r
                                 */\r
-                               eventProcessors : commonEventProcessors,\r
+                               eventProcessors :\r
+                               {\r
+                                       onChange : function( dialog, func )\r
+                                       {\r
+                                               // If this method is called several times (I'm not sure about how this can happen but the default\r
+                                               // onChange processor includes this protection)\r
+                                               // In order to reapply to the new element, the property is deleted at the beggining of the registerEvents method\r
+                                               if ( !this._.domOnChangeRegistered )\r
+                                               {\r
+                                                       // By listening for the formLoaded event, this handler will get reapplied when a new\r
+                                                       // form is created\r
+                                                       this.on( 'formLoaded', function()\r
+                                                       {\r
+                                                               this.getInputElement().on( 'change', function(){ this.fire( 'change', { value : this.getValue() } ); }, this );\r
+                                                       }, this );\r
+                                                       this._.domOnChangeRegistered = true;\r
+                                               }\r
+\r
+                                               this.on( 'change', func );\r
+                                       }\r
+                               },\r
 \r
                                keyboardFocusable : true\r
                        }, true );\r