/* Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ /** @fileoverview The "dialogui" plugin. */ CKEDITOR.plugins.add( 'dialogui' ); (function() { var initPrivateObject = function( elementDefinition ) { this._ || ( this._ = {} ); this._['default'] = this._.initValue = elementDefinition['default'] || ''; var args = [ this._ ]; for ( var i = 1 ; i < arguments.length ; i++ ) args.push( arguments[i] ); args.push( true ); CKEDITOR.tools.extend.apply( CKEDITOR.tools, args ); return this._; }, textBuilder = { build : function( dialog, elementDefinition, output ) { return new CKEDITOR.ui.dialog.textInput( dialog, elementDefinition, output ); } }, commonBuilder = { build : function( dialog, elementDefinition, output ) { return new CKEDITOR.ui.dialog[elementDefinition.type]( dialog, elementDefinition, output ); } }, commonPrototype = { isChanged : function() { return this.getValue() != this.getInitValue(); }, reset : function() { this.setValue( this.getInitValue() ); }, setInitValue : function() { this._.initValue = this.getValue(); }, resetInitValue : function() { this._.initValue = this._['default']; }, getInitValue : function() { return this._.initValue; } }, commonEventProcessors = CKEDITOR.tools.extend( {}, CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors, { onChange : function( dialog, func ) { if ( !this._.domOnChangeRegistered ) { dialog.on( 'load', function() { this.getInputElement().on( 'change', function(){ this.fire( 'change', { value : this.getValue() } ); }, this ); }, this ); this._.domOnChangeRegistered = true; } this.on( 'change', func ); } }, true ), eventRegex = /^on([A-Z]\w+)/, cleanInnerDefinition = function( def ) { // An inner UI element should not have the parent's type, title or events. for ( var i in def ) { if ( eventRegex.test( i ) || i == 'title' || i == 'type' ) delete def[i]; } return def; }; CKEDITOR.tools.extend( CKEDITOR.ui.dialog, /** @lends CKEDITOR.ui.dialog */ { /** * Base class for all dialog elements with a textual label on the left. * @constructor * @example * @extends CKEDITOR.ui.dialog.uiElement * @param {CKEDITOR.dialog} dialog * Parent dialog object. * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition * The element definition. Accepted fields: * * @param {Array} htmlList * List of HTML code to output to. * @param {Function} contentHtml * A function returning the HTML code string to be added inside the content * cell. */ labeledElement : function( dialog, elementDefinition, htmlList, contentHtml ) { if ( arguments.length < 4 ) return; var _ = initPrivateObject.call( this, elementDefinition ); _.labelId = CKEDITOR.tools.getNextNumber() + '_label'; var children = this._.children = []; /** @ignore */ var innerHTML = function() { var html = []; if ( elementDefinition.labelLayout != 'horizontal' ) html.push( '
', elementDefinition.label, '
', '
', contentHtml( dialog, elementDefinition ), '
' ); else { var hboxDefinition = { type : 'hbox', widths : elementDefinition.widths, padding : 0, children : [ { type : 'html', html : '' + CKEDITOR.tools.htmlEncode( elementDefinition.label ) + '' }, { type : 'html', html : '' + contentHtml( dialog, elementDefinition ) + '' } ] }; CKEDITOR.dialog._.uiElementBuilders.hbox.build( dialog, hboxDefinition, html ); } return html.join( '' ); }; CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, htmlList, 'div', null, null, innerHTML ); }, /** * A text input with a label. This UI element class represents both the * single-line text inputs and password inputs in dialog boxes. * @constructor * @example * @extends CKEDITOR.ui.dialog.labeledElement * @param {CKEDITOR.dialog} dialog * Parent dialog object. * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition * The element definition. Accepted fields: * * @param {Array} htmlList * List of HTML code to output to. */ textInput : function( dialog, elementDefinition, htmlList ) { if ( arguments.length < 3 ) return; initPrivateObject.call( this, elementDefinition ); var domId = this._.inputId = CKEDITOR.tools.getNextNumber() + '_textInput', attributes = { 'class' : 'cke_dialog_ui_input_' + elementDefinition.type, id : domId, type : 'text' }, i; // Set the validator, if any. if ( elementDefinition.validate ) this.validate = elementDefinition.validate; // Set the max length and size. if ( elementDefinition.maxLength ) attributes.maxlength = elementDefinition.maxLength; if ( elementDefinition.size ) attributes.size = elementDefinition.size; // If user presses Enter in a text box, it implies clicking OK for the dialog. var me = this, keyPressedOnMe = false; dialog.on( 'load', function() { me.getInputElement().on( 'keydown', function( evt ) { if ( evt.data.getKeystroke() == 13 ) keyPressedOnMe = true; } ); // Lower the priority this 'keyup' since 'ok' will close the dialog.(#3749) me.getInputElement().on( 'keyup', function( evt ) { if ( evt.data.getKeystroke() == 13 && keyPressedOnMe ) { dialog.getButton( 'ok' ) && dialog.getButton( 'ok' ).click(); keyPressedOnMe = false; } }, null, null, 1000 ); } ); /** @ignore */ var innerHTML = function() { // IE BUG: Text input fields in IE at 100% would exceed a or inline // container's width, so need to wrap it inside a
. var html = [ '
' ); return html.join( '' ); }; CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML ); }, /** * A text area with a label on the top or left. * @constructor * @extends CKEDITOR.ui.dialog.labeledElement * @example * @param {CKEDITOR.dialog} dialog * Parent dialog object. * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition * The element definition. Accepted fields: * * @param {Array} htmlList * List of HTML code to output to. */ textarea : function( dialog, elementDefinition, htmlList ) { if ( arguments.length < 3 ) return; initPrivateObject.call( this, elementDefinition ); var me = this, domId = this._.inputId = CKEDITOR.tools.getNextNumber() + '_textarea', attributes = {}; if ( elementDefinition.validate ) this.validate = elementDefinition.validate; // Generates the essential attributes for the textarea tag. attributes.rows = elementDefinition.rows || 5; attributes.cols = elementDefinition.cols || 20; /** @ignore */ var innerHTML = function() { var html = [ '
' ); return html.join( '' ); }; CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML ); }, /** * A single checkbox with a label on the right. * @constructor * @extends CKEDITOR.ui.dialog.uiElement * @example * @param {CKEDITOR.dialog} dialog * Parent dialog object. * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition * The element definition. Accepted fields: * * @param {Array} htmlList * List of HTML code to output to. */ checkbox : function( dialog, elementDefinition, htmlList ) { if ( arguments.length < 3 ) return; var _ = initPrivateObject.call( this, elementDefinition, { 'default' : !!elementDefinition[ 'default' ] } ); if ( elementDefinition.validate ) this.validate = elementDefinition.validate; /** @ignore */ var innerHTML = function() { var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition, { id : elementDefinition.id ? elementDefinition.id + '_checkbox' : CKEDITOR.tools.getNextNumber() + '_checkbox' }, true ), html = [], attributes = { 'class' : 'cke_dialog_ui_checkbox_input', type : 'checkbox' }; cleanInnerDefinition( myDefinition ); if ( elementDefinition[ 'default' ] ) attributes.checked = 'checked'; _.checkbox = new CKEDITOR.ui.dialog.uiElement( dialog, myDefinition, html, 'input', null, attributes ); html.push( ' ' ); return html.join( '' ); }; CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, htmlList, 'span', null, null, innerHTML ); }, /** * A group of radio buttons. * @constructor * @example * @extends CKEDITOR.ui.dialog.labeledElement * @param {CKEDITOR.dialog} dialog * Parent dialog object. * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition * The element definition. Accepted fields: * * @param {Array} htmlList * List of HTML code to output to. */ radio : function( dialog, elementDefinition, htmlList ) { if ( arguments.length < 3) return; initPrivateObject.call( this, elementDefinition ); if ( !this._['default'] ) this._['default'] = this._.initValue = elementDefinition.items[0][1]; if ( elementDefinition.validate ) this.validate = elementDefinition.valdiate; var children = [], me = this; /** @ignore */ var innerHTML = function() { var inputHtmlList = [], html = [], commonAttributes = { 'class' : 'cke_dialog_ui_radio_item' }, commonName = elementDefinition.id ? elementDefinition.id + '_radio' : CKEDITOR.tools.getNextNumber() + '_radio'; for ( var i = 0 ; i < elementDefinition.items.length ; i++ ) { var item = elementDefinition.items[i], title = item[2] !== undefined ? item[2] : item[0], value = item[1] !== undefined ? item[1] : item[0], inputDefinition = CKEDITOR.tools.extend( {}, elementDefinition, { id : CKEDITOR.tools.getNextNumber() + '_radio_input', title : null, type : null }, true ), labelDefinition = CKEDITOR.tools.extend( {}, inputDefinition, { id : null, title : title }, true ), inputAttributes = { type : 'radio', 'class' : 'cke_dialog_ui_radio_input', name : commonName, value : value }, inputHtml = []; if ( me._['default'] == value ) inputAttributes.checked = 'checked'; cleanInnerDefinition( inputDefinition ); cleanInnerDefinition( labelDefinition ); children.push( new CKEDITOR.ui.dialog.uiElement( dialog, inputDefinition, inputHtml, 'input', null, inputAttributes ) ); inputHtml.push( ' ' ); new CKEDITOR.ui.dialog.uiElement( dialog, labelDefinition, inputHtml, 'label', null, { 'for' : inputAttributes.id }, item[0] ); inputHtmlList.push( inputHtml.join( '' ) ); } new CKEDITOR.ui.dialog.hbox( dialog, [], inputHtmlList, html ); return html.join( '' ); }; CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML ); this._.children = children; }, /** * A button with a label inside. * @constructor * @example * @extends CKEDITOR.ui.dialog.uiElement * @param {CKEDITOR.dialog} dialog * Parent dialog object. * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition * The element definition. Accepted fields: * * @param {Array} htmlList * List of HTML code to output to. */ button : function( dialog, elementDefinition, htmlList ) { if ( !arguments.length ) return; if ( typeof elementDefinition == 'function' ) elementDefinition = elementDefinition( dialog.getParentEditor() ); initPrivateObject.call( this, elementDefinition, { disabled : elementDefinition.disabled || false } ); // Add OnClick event to this input. CKEDITOR.event.implementOn( this ); var me = this; // Register an event handler for processing button clicks. dialog.on( 'load', function( eventInfo ) { var element = this.getElement(); (function() { element.on( 'click', function( evt ) { me.fire( 'click', { dialog : me.getDialog() } ); evt.data.preventDefault(); } ); })(); element.unselectable(); }, this ); var outerDefinition = CKEDITOR.tools.extend( {}, elementDefinition ); delete outerDefinition.style; CKEDITOR.ui.dialog.uiElement.call( this, dialog, outerDefinition, htmlList, 'a', null, { style : elementDefinition.style, href : 'javascript:void(0)', title : elementDefinition.label, hidefocus : 'true', 'class' : elementDefinition['class'] }, '' + CKEDITOR.tools.htmlEncode( elementDefinition.label ) + '' ); }, /** * A select box. * @extends CKEDITOR.ui.dialog.uiElement * @example * @constructor * @param {CKEDITOR.dialog} dialog * Parent dialog object. * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition * The element definition. Accepted fields: * * @param {Array} htmlList * List of HTML code to output to. */ select : function( dialog, elementDefinition, htmlList ) { if ( arguments.length < 3 ) return; var _ = initPrivateObject.call( this, elementDefinition ); if ( elementDefinition.validate ) this.validate = elementDefinition.validate; /** @ignore */ var innerHTML = function() { var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition, { id : elementDefinition.id ? elementDefinition.id + '_select' : CKEDITOR.tools.getNextNumber() + '_select' }, true ), html = [], innerHTML = [], attributes = { 'class' : 'cke_dialog_ui_input_select' }; // Add multiple and size attributes from element definition. if ( elementDefinition.size != undefined ) attributes.size = elementDefinition.size; if ( elementDefinition.multiple != undefined ) attributes.multiple = elementDefinition.multiple; cleanInnerDefinition( myDefinition ); for ( var i = 0, item ; i < elementDefinition.items.length && ( item = elementDefinition.items[i] ) ; i++ ) { innerHTML.push( '