X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=_source%2Fplugins%2Fdialog%2Fplugin.js;h=13ee0efc588c4c65befbc4702895ca6ae7dea745;hb=refs%2Ftags%2Fv3.6.2;hp=ce287993adac365a2a90fbc64d0e7a273cf81640;hpb=4e90e78dc97789709ee7404359a5517540c27553;p=ckeditor.git diff --git a/_source/plugins/dialog/plugin.js b/_source/plugins/dialog/plugin.js index ce28799..13ee0ef 100644 --- a/_source/plugins/dialog/plugin.js +++ b/_source/plugins/dialog/plugin.js @@ -93,6 +93,36 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; } } + // Handle dialog element validation state UI changes. + function handleFieldValidated( isValid, msg ) + { + var input = this.getInputElement(); + if ( input ) + { + isValid ? input.removeAttribute( 'aria-invalid' ) + : input.setAttribute( 'aria-invalid', true ); + } + + if ( !isValid ) + { + if ( this.select ) + this.select(); + else + this.focus(); + } + + msg && alert( msg ); + + this.fire( 'validated', { valid : isValid, msg : msg } ); + } + + function resetField() + { + var input = this.getInputElement(); + input && input.removeAttribute( 'aria-invalid' ); + } + + /** * This is the base class for runtime dialog objects. An instance of this * class represents a single named dialog for a single editor instance. @@ -273,25 +303,17 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; { if ( item.validate ) { - var isValid = item.validate( this ); - - if ( typeof isValid == 'string' ) - { - alert( isValid ); - isValid = false; - } + var retval = item.validate( this ), + invalid = typeof ( retval ) == 'string' || retval === false; - if ( isValid === false ) + if ( invalid ) { - if ( item.select ) - item.select(); - else - item.focus(); - evt.data.hide = false; evt.stop(); - return true; } + + handleFieldValidated.call( item, !invalid, typeof retval == 'string' ? retval : undefined ); + return invalid; } }); }, this, null, 0 ); @@ -454,6 +476,9 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; dialogElement.removeListener( 'keydown', focusKeydownHandler ); if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) ) dialogElement.removeListener( 'keypress', focusKeyPressHandler ); + + // Reset fields state when closing dialog. + iterContents( function( item ) { resetField.apply( item ); } ); } ); this.on( 'iframeAdded', function( evt ) { @@ -842,7 +867,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; for ( var i in this._.contents ) { for ( var j in this._.contents[i] ) - fn( this._.contents[i][j] ); + fn.call( this, this._.contents[i][j] ); } return this; }, @@ -859,6 +884,16 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; return function(){ this.foreach( fn ); return this; }; })(), + + /** + * Calls the {@link CKEDITOR.dialog.definition.uiElement#setup} method of each of the UI elements, with the arguments passed through it. + * It is usually being called when the dialog is opened, to put the initial value inside the field. + * @example + * dialogObj.setupContent(); + * @example + * var timestamp = ( new Date() ).valueOf(); + * dialogObj.setupContent( timestamp ); + */ setupContent : function() { var args = arguments; @@ -869,11 +904,24 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; }); }, + /** + * Calls the {@link CKEDITOR.dialog.definition.uiElement#commit} method of each of the UI elements, with the arguments passed through it. + * It is usually being called when the user confirms the dialog, to process the values. + * @example + * dialogObj.commitContent(); + * @example + * var timestamp = ( new Date() ).valueOf(); + * dialogObj.commitContent( timestamp ); + */ commitContent : function() { var args = arguments; this.foreach( function( widget ) { + // Make sure IE triggers "change" event on last focused input before closing the dialog. (#7915) + if ( CKEDITOR.env.ie && this._.currentFocusIndex == widget.focusIndex ) + widget.getInputElement().$.blur(); + if ( widget.commit ) widget.commit.apply( widget, args ); }); @@ -1139,6 +1187,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; * @param {String} pageId id of dialog page. * @param {String} elementId id of UI element. * @example + * dialogObj.getContentElement( 'tabId', 'elementId' ).setValue( 'Example' ); * @returns {CKEDITOR.ui.dialog.uiElement} The dialog UI element. */ getContentElement : function( pageId, elementId ) @@ -1152,6 +1201,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; * @param {String} pageId id of dialog page. * @param {String} elementId id of UI element. * @example + * alert( dialogObj.getValueOf( 'tabId', 'elementId' ) ); * @returns {Object} The value of the UI element. */ getValueOf : function( pageId, elementId ) @@ -1165,6 +1215,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; * @param {String} elementId id of the UI element. * @param {Object} value The new value of the UI element. * @example + * dialogObj.setValueOf( 'tabId', 'elementId', 'Example' ); */ setValueOf : function( pageId, elementId, value ) { @@ -1905,6 +1956,11 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; var covers = {}, currentCover; + function cancelEvent( ev ) + { + ev.data.preventDefault(1); + } + function showCover( editor ) { var win = CKEDITOR.document.getWindow(); @@ -1965,6 +2021,10 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; coverElement = CKEDITOR.dom.element.createFromHtml( html.join( '' ) ); coverElement.setOpacity( backgroundCoverOpacity != undefined ? backgroundCoverOpacity : 0.5 ); + coverElement.on( 'keydown', cancelEvent ); + coverElement.on( 'keypress', cancelEvent ); + coverElement.on( 'keyup', cancelEvent ); + coverElement.appendTo( CKEDITOR.document.getBody() ); covers[ coverKey ] = coverElement; } @@ -2210,6 +2270,9 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; classes[ 'cke_dialog_ui_' + elementDefinition.type ] = 1; if ( elementDefinition.className ) classes[ elementDefinition.className ] = 1; + if ( elementDefinition.disabled ) + classes[ 'cke_disabled' ] = 1; + var attributeClasses = ( attributes['class'] && attributes['class'].split ) ? attributes['class'].split( ' ' ) : []; for ( i = 0 ; i < attributeClasses.length ; i++ ) { @@ -2227,6 +2290,15 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; // Write the inline CSS styles. var styleStr = ( elementDefinition.style || '' ).split( ';' ); + + // Element alignment support. + if ( elementDefinition.align ) + { + var align = elementDefinition.align; + styles[ 'margin-left' ] = align == 'left' ? 0 : 'auto'; + styles[ 'margin-right' ] = align == 'right' ? 0 : 'auto'; + } + for ( i in styles ) styleStr.push( i + ':' + styles[i] ); if ( elementDefinition.hidden ) @@ -2257,6 +2329,23 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; if ( typeof( elementDefinition.isChanged ) == 'function' ) this.isChanged = elementDefinition.isChanged; + // Overload 'get(set)Value' on definition. + if ( typeof( elementDefinition.setValue ) == 'function' ) + { + this.setValue = CKEDITOR.tools.override( this.setValue, function( org ) + { + return function( val ){ org.call( this, elementDefinition.setValue.call( this, val ) ); }; + } ); + } + + if ( typeof( elementDefinition.getValue ) == 'function' ) + { + this.getValue = CKEDITOR.tools.override( this.getValue, function( org ) + { + return function(){ return elementDefinition.getValue.call( this, org.call( this ) ); }; + } ); + } + // Add events. CKEDITOR.event.implementOn( this ); @@ -2267,14 +2356,24 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; var me = this; dialog.on( 'load', function() { - if ( me.getInputElement() ) + var input = me.getInputElement(); + if ( input ) { - me.getInputElement().on( 'focus', function() + var focusClass = me.type in { 'checkbox' : 1, 'ratio' : 1 } && CKEDITOR.env.ie && CKEDITOR.env.version < 8 ? 'cke_dialog_ui_focused' : ''; + input.on( 'focus', function() { dialog._.tabBarMode = false; dialog._.hasFocus = true; me.fire( 'focus' ); - }, me ); + focusClass && this.addClass( focusClass ); + + }); + + input.on( 'blur', function() + { + me.fire( 'blur' ); + focusClass && this.removeClass( focusClass ); + }); } } ); @@ -2357,6 +2456,9 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; styles.push( 'height:' + cssLength( height ) ); if ( elementDefinition && elementDefinition.padding != undefined ) styles.push( 'padding:' + cssLength( elementDefinition.padding ) ); + // In IE Quirks alignment has to be done on table cells. (#7324) + if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && children[ i ].align ) + styles.push( 'text-align:' + children[ i ].align ); if ( styles.length > 0 ) html.push( 'style="' + styles.join('; ') + '" ' ); html.push( '>', childHtmlList[i], '' ); @@ -2442,6 +2544,9 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; styles.push( 'height:' + Math.floor( 100 / childHtmlList.length ) + '%' ); if ( elementDefinition && elementDefinition.padding != undefined ) styles.push( 'padding:' + cssLength( elementDefinition.padding ) ); + // In IE Quirks alignment has to be done on table cells. (#7324) + if ( CKEDITOR.env.ie && CKEDITOR.env.quirks && children[ i ].align ) + styles.push( 'text-align:' + children[ i ].align ); if ( styles.length > 0 ) html.push( 'style="', styles.join( '; ' ), '" ' ); html.push( ' class="cke_dialog_ui_vbox_child">', childHtmlList[i], '' ); @@ -2694,8 +2799,9 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; */ disable : function() { - var element = this.getInputElement(); - element.setAttribute( 'disabled', 'true' ); + var element = this.getElement(), + input = this.getInputElement(); + input.setAttribute( 'disabled', 'true' ); element.addClass( 'cke_disabled' ); }, @@ -2705,8 +2811,9 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; */ enable : function() { - var element = this.getInputElement(); - element.removeAttribute( 'disabled' ); + var element = this.getElement(), + input = this.getInputElement(); + input.removeAttribute( 'disabled' ); element.removeClass( 'cke_disabled' ); }, @@ -2717,7 +2824,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; */ isEnabled : function() { - return !this.getInputElement().getAttribute( 'disabled' ); + return !this.getElement().hasClass( 'cke_disabled' ); }, /** @@ -2826,7 +2933,10 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; /** @ignore */ exec : function( editor ) { - editor.openDialog( this.dialogName ); + // Special treatment for Opera. (#8031) + CKEDITOR.env.opera ? + CKEDITOR.tools.setTimeout( function() { editor.openDialog( this.dialogName ) }, 0, this ) + : editor.openDialog( this.dialogName ); }, // Dialog commands just open a dialog ui, thus require no undo logic, @@ -2840,7 +2950,10 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; { var notEmptyRegex = /^([a]|[^a])+$/, integerRegex = /^\d*$/, - numberRegex = /^\d*(?:\.\d+)?$/; + numberRegex = /^\d*(?:\.\d+)?$/, + htmlLengthRegex = /^(((\d*(\.\d+))|(\d*))(px|\%)?)?$/, + cssLengthRegex = /^(((\d*(\.\d+))|(\d*))(px|em|ex|in|cm|mm|pt|pc|\%)?)?$/i, + inlineStyleRegex = /^(\s*[\w-]+\s*:\s*[^:;]+(?:;|$))*$/; CKEDITOR.VALIDATE_OR = 1; CKEDITOR.VALIDATE_AND = 2; @@ -2849,6 +2962,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; { functions : function() { + var args = arguments; return function() { /** @@ -2857,28 +2971,28 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; * combine validate functions together to make more sophisticated * validators. */ - var value = this && this.getValue ? this.getValue() : arguments[0]; + var value = this && this.getValue ? this.getValue() : args[ 0 ]; var msg = undefined, relation = CKEDITOR.VALIDATE_AND, functions = [], i; - for ( i = 0 ; i < arguments.length ; i++ ) + for ( i = 0 ; i < args.length ; i++ ) { - if ( typeof( arguments[i] ) == 'function' ) - functions.push( arguments[i] ); + if ( typeof( args[i] ) == 'function' ) + functions.push( args[i] ); else break; } - if ( i < arguments.length && typeof( arguments[i] ) == 'string' ) + if ( i < args.length && typeof( args[i] ) == 'string' ) { - msg = arguments[i]; + msg = args[i]; i++; } - if ( i < arguments.length && typeof( arguments[i]) == 'number' ) - relation = arguments[i]; + if ( i < args.length && typeof( args[i]) == 'number' ) + relation = args[i]; var passed = ( relation == CKEDITOR.VALIDATE_AND ? true : false ); for ( i = 0 ; i < functions.length ; i++ ) @@ -2889,16 +3003,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; passed = passed || functions[i]( value ); } - if ( !passed ) - { - if ( msg !== undefined ) - alert( msg ); - if ( this && ( this.select || this.focus ) ) - ( this.select || this.focus )(); - return false; - } - - return true; + return !passed ? msg : true; }; }, @@ -2911,20 +3016,7 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; return function() { var value = this && this.getValue ? this.getValue() : arguments[0]; - if ( !regex.test( value ) ) - { - if ( msg !== undefined ) - alert( msg ); - if ( this && ( this.select || this.focus ) ) - { - if ( this.select ) - this.select(); - else - this.focus(); - } - return false; - } - return true; + return !regex.test( value ) ? msg : true; }; }, @@ -2943,6 +3035,21 @@ CKEDITOR.DIALOG_RESIZE_BOTH = 3; return this.regex( numberRegex, msg ); }, + 'cssLength' : function( msg ) + { + return this.functions( function( val ){ return cssLengthRegex.test( CKEDITOR.tools.trim( val ) ); }, msg ); + }, + + 'htmlLength' : function( msg ) + { + return this.functions( function( val ){ return htmlLengthRegex.test( CKEDITOR.tools.trim( val ) ); }, msg ); + }, + + 'inlineStyle' : function( msg ) + { + return this.functions( function( val ){ return inlineStyleRegex.test( CKEDITOR.tools.trim( val ) ); }, msg ); + }, + equals : function( value, msg ) { return this.functions( function( val ){ return val == value; }, msg );