JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.2
[ckeditor.git] / _source / plugins / dialogui / plugin.js
1 /*\r
2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 /** @fileoverview The "dialogui" plugin. */\r
7 \r
8 CKEDITOR.plugins.add( 'dialogui' );\r
9 \r
10 (function()\r
11 {\r
12         var initPrivateObject = function( elementDefinition )\r
13         {\r
14                 this._ || ( this._ = {} );\r
15                 this._['default'] = this._.initValue = elementDefinition['default'] || '';\r
16                 this._.required = elementDefinition[ 'required' ] || false;\r
17                 var args = [ this._ ];\r
18                 for ( var i = 1 ; i < arguments.length ; i++ )\r
19                         args.push( arguments[i] );\r
20                 args.push( true );\r
21                 CKEDITOR.tools.extend.apply( CKEDITOR.tools, args );\r
22                 return this._;\r
23         },\r
24         textBuilder =\r
25         {\r
26                 build : function( dialog, elementDefinition, output )\r
27                 {\r
28                         return new CKEDITOR.ui.dialog.textInput( dialog, elementDefinition, output );\r
29                 }\r
30         },\r
31         commonBuilder =\r
32         {\r
33                 build : function( dialog, elementDefinition, output )\r
34                 {\r
35                         return new CKEDITOR.ui.dialog[elementDefinition.type]( dialog, elementDefinition, output );\r
36                 }\r
37         },\r
38         containerBuilder =\r
39         {\r
40                 build : function( dialog, elementDefinition, output )\r
41                 {\r
42                         var children = elementDefinition.children,\r
43                                 child,\r
44                                 childHtmlList = [],\r
45                                 childObjList = [];\r
46                         for ( var i = 0 ; ( i < children.length && ( child = children[i] ) ) ; i++ )\r
47                         {\r
48                                 var childHtml = [];\r
49                                 childHtmlList.push( childHtml );\r
50                                 childObjList.push( CKEDITOR.dialog._.uiElementBuilders[ child.type ].build( dialog, child, childHtml ) );\r
51                         }\r
52                         return new CKEDITOR.ui.dialog[ elementDefinition.type ]( dialog, childObjList, childHtmlList, output, elementDefinition );\r
53                 }\r
54         },\r
55         commonPrototype =\r
56         {\r
57                 isChanged : function()\r
58                 {\r
59                         return this.getValue() != this.getInitValue();\r
60                 },\r
61 \r
62                 reset : function()\r
63                 {\r
64                         this.setValue( this.getInitValue() );\r
65                 },\r
66 \r
67                 setInitValue : function()\r
68                 {\r
69                         this._.initValue = this.getValue();\r
70                 },\r
71 \r
72                 resetInitValue : function()\r
73                 {\r
74                         this._.initValue = this._['default'];\r
75                 },\r
76 \r
77                 getInitValue : function()\r
78                 {\r
79                         return this._.initValue;\r
80                 }\r
81         },\r
82         commonEventProcessors = CKEDITOR.tools.extend( {}, CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors,\r
83                 {\r
84                         onChange : function( dialog, func )\r
85                         {\r
86                                 if ( !this._.domOnChangeRegistered )\r
87                                 {\r
88                                         dialog.on( 'load', function()\r
89                                                 {\r
90                                                         this.getInputElement().on( 'change', function(){ this.fire( 'change', { value : this.getValue() } ); }, this );\r
91                                                 }, this );\r
92                                         this._.domOnChangeRegistered = true;\r
93                                 }\r
94 \r
95                                 this.on( 'change', func );\r
96                         }\r
97                 }, true ),\r
98         eventRegex = /^on([A-Z]\w+)/,\r
99         cleanInnerDefinition = function( def )\r
100         {\r
101                 // An inner UI element should not have the parent's type, title or events.\r
102                 for ( var i in def )\r
103                 {\r
104                         if ( eventRegex.test( i ) || i == 'title' || i == 'type' )\r
105                                 delete def[i];\r
106                 }\r
107                 return def;\r
108         };\r
109 \r
110         CKEDITOR.tools.extend( CKEDITOR.ui.dialog,\r
111                 /** @lends CKEDITOR.ui.dialog */\r
112                 {\r
113                         /**\r
114                          * Base class for all dialog elements with a textual label on the left.\r
115                          * @constructor\r
116                          * @example\r
117                          * @extends CKEDITOR.ui.dialog.uiElement\r
118                          * @param {CKEDITOR.dialog} dialog\r
119                          * Parent dialog object.\r
120                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
121                          * The element definition. Accepted fields:\r
122                          * <ul>\r
123                          *      <li><strong>label</strong> (Required) The label string.</li>\r
124                          *      <li><strong>labelLayout</strong> (Optional) Put 'horizontal' here if the\r
125                          *      label element is to be layed out horizontally. Otherwise a vertical\r
126                          *      layout will be used.</li>\r
127                          *      <li><strong>widths</strong> (Optional) This applies only for horizontal\r
128                          *      layouts - an 2-element array of lengths to specify the widths of the\r
129                          *      label and the content element.</li>\r
130                          * </ul>\r
131                          * @param {Array} htmlList\r
132                          * List of HTML code to output to.\r
133                          * @param {Function} contentHtml\r
134                          * A function returning the HTML code string to be added inside the content\r
135                          * cell.\r
136                          */\r
137                         labeledElement : function( dialog, elementDefinition, htmlList, contentHtml )\r
138                         {\r
139                                 if ( arguments.length < 4 )\r
140                                         return;\r
141 \r
142                                 var _ = initPrivateObject.call( this, elementDefinition );\r
143                                 _.labelId = CKEDITOR.tools.getNextNumber() + '_label';\r
144                                 var children = this._.children = [];\r
145                                 /** @ignore */\r
146                                 var innerHTML = function()\r
147                                 {\r
148                                         var html = [];\r
149                                         if ( elementDefinition.labelLayout != 'horizontal' )\r
150                                                 html.push( '<label class="cke_dialog_ui_labeled_label" ',\r
151                                                                 ' id="'+  _.labelId + '"',\r
152                                                                 ' for="' + _.inputId + '"',\r
153                                                                 ' style="' + elementDefinition.labelStyle + '">',\r
154                                                                 elementDefinition.label,\r
155                                                                 '</label>',\r
156                                                                 '<div class="cke_dialog_ui_labeled_content" role="presentation">',\r
157                                                                 contentHtml.call( this, dialog, elementDefinition ),\r
158                                                                 '</div>' );\r
159                                         else\r
160                                         {\r
161                                                 var hboxDefinition = {\r
162                                                         type : 'hbox',\r
163                                                         widths : elementDefinition.widths,\r
164                                                         padding : 0,\r
165                                                         children :\r
166                                                         [\r
167                                                                 {\r
168                                                                         type : 'html',\r
169                                                                         html : '<label class="cke_dialog_ui_labeled_label"' +\r
170                                                                                 ' id="' + _.labelId + '"' +\r
171                                                                                 ' for="' + _.inputId + '"' +\r
172                                                                                 ' style="' + elementDefinition.labelStyle + '">' +\r
173                                                                                    CKEDITOR.tools.htmlEncode( elementDefinition.label ) +\r
174                                                                                 '</span>'\r
175                                                                 },\r
176                                                                 {\r
177                                                                         type : 'html',\r
178                                                                         html : '<span class="cke_dialog_ui_labeled_content">' +\r
179                                                                                 contentHtml.call( this, dialog, elementDefinition ) +\r
180                                                                                 '</span>'\r
181                                                                 }\r
182                                                         ]\r
183                                                 };\r
184                                                 CKEDITOR.dialog._.uiElementBuilders.hbox.build( dialog, hboxDefinition, html );\r
185                                         }\r
186                                         return html.join( '' );\r
187                                 };\r
188                                 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, htmlList, 'div', null, { role : 'presentation' }, innerHTML );\r
189                         },\r
190 \r
191                         /**\r
192                          * A text input with a label. This UI element class represents both the\r
193                          * single-line text inputs and password inputs in dialog boxes.\r
194                          * @constructor\r
195                          * @example\r
196                          * @extends CKEDITOR.ui.dialog.labeledElement\r
197                          * @param {CKEDITOR.dialog} dialog\r
198                          * Parent dialog object.\r
199                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
200                          * The element definition. Accepted fields:\r
201                          * <ul>\r
202                          *      <li><strong>default</strong> (Optional) The default value.</li>\r
203                          *      <li><strong>validate</strong> (Optional) The validation function. </li>\r
204                          *      <li><strong>maxLength</strong> (Optional) The maximum length of text box\r
205                          *      contents.</li>\r
206                          *      <li><strong>size</strong> (Optional) The size of the text box. This is\r
207                          *      usually overridden by the size defined by the skin, however.</li>\r
208                          * </ul>\r
209                          * @param {Array} htmlList\r
210                          * List of HTML code to output to.\r
211                          */\r
212                         textInput : function( dialog, elementDefinition, htmlList )\r
213                         {\r
214                                 if ( arguments.length < 3 )\r
215                                         return;\r
216 \r
217                                 initPrivateObject.call( this, elementDefinition );\r
218                                 var domId = this._.inputId = CKEDITOR.tools.getNextNumber() + '_textInput',\r
219                                         attributes = { 'class' : 'cke_dialog_ui_input_' + elementDefinition.type, id : domId, type : 'text' },\r
220                                         i;\r
221 \r
222                                 // Set the validator, if any.\r
223                                 if ( elementDefinition.validate )\r
224                                         this.validate = elementDefinition.validate;\r
225 \r
226                                 // Set the max length and size.\r
227                                 if ( elementDefinition.maxLength )\r
228                                         attributes.maxlength = elementDefinition.maxLength;\r
229                                 if ( elementDefinition.size )\r
230                                         attributes.size = elementDefinition.size;\r
231 \r
232                                 // If user presses Enter in a text box, it implies clicking OK for the dialog.\r
233                                 var me = this, keyPressedOnMe = false;\r
234                                 dialog.on( 'load', function()\r
235                                         {\r
236                                                 me.getInputElement().on( 'keydown', function( evt )\r
237                                                         {\r
238                                                                 if ( evt.data.getKeystroke() == 13 )\r
239                                                                         keyPressedOnMe = true;\r
240                                                         } );\r
241 \r
242                                                 // Lower the priority this 'keyup' since 'ok' will close the dialog.(#3749)\r
243                                                 me.getInputElement().on( 'keyup', function( evt )\r
244                                                         {\r
245                                                                 if ( evt.data.getKeystroke() == 13 && keyPressedOnMe )\r
246                                                                 {\r
247                                                                         dialog.getButton( 'ok' ) && setTimeout( function ()\r
248                                                                         {\r
249                                                                                 dialog.getButton( 'ok' ).click();\r
250                                                                         }, 0 );\r
251                                                                         keyPressedOnMe = false;\r
252                                                                 }\r
253                                                         }, null, null, 1000 );\r
254                                         } );\r
255 \r
256                                 /** @ignore */\r
257                                 var innerHTML = function()\r
258                                 {\r
259                                         // IE BUG: Text input fields in IE at 100% would exceed a <td> or inline\r
260                                         // container's width, so need to wrap it inside a <div>.\r
261                                         var html = [ '<div class="cke_dialog_ui_input_', elementDefinition.type, '" role="presentation"' ];\r
262 \r
263                                         if ( elementDefinition.width )\r
264                                                 html.push( 'style="width:'+ elementDefinition.width +'" ' );\r
265 \r
266                                         html.push( '><input ' );\r
267 \r
268                                         attributes[ 'aria-labelledby' ] = this._.labelId;\r
269                                         this._.required && ( attributes[ 'aria-required' ] = this._.required );\r
270                                         for ( var i in attributes )\r
271                                                 html.push( i + '="' + attributes[i] + '" ' );\r
272                                         html.push( ' /></div>' );\r
273                                         return html.join( '' );\r
274                                 };\r
275                                 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );\r
276                         },\r
277 \r
278                         /**\r
279                          * A text area with a label on the top or left.\r
280                          * @constructor\r
281                          * @extends CKEDITOR.ui.dialog.labeledElement\r
282                          * @example\r
283                          * @param {CKEDITOR.dialog} dialog\r
284                          * Parent dialog object.\r
285                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
286                          * The element definition. Accepted fields:\r
287                          * <ul>\r
288                          *      <li><strong>rows</strong> (Optional) The number of rows displayed.\r
289                          *      Defaults to 5 if not defined.</li>\r
290                          *      <li><strong>cols</strong> (Optional) The number of cols displayed.\r
291                          *      Defaults to 20 if not defined. Usually overridden by skins.</li>\r
292                          *      <li><strong>default</strong> (Optional) The default value.</li>\r
293                          *      <li><strong>validate</strong> (Optional) The validation function. </li>\r
294                          * </ul>\r
295                          * @param {Array} htmlList\r
296                          * List of HTML code to output to.\r
297                          */\r
298                         textarea : function( dialog, elementDefinition, htmlList )\r
299                         {\r
300                                 if ( arguments.length < 3 )\r
301                                         return;\r
302 \r
303                                 initPrivateObject.call( this, elementDefinition );\r
304                                 var me = this,\r
305                                         domId = this._.inputId = CKEDITOR.tools.getNextNumber() + '_textarea',\r
306                                         attributes = {};\r
307 \r
308                                 if ( elementDefinition.validate )\r
309                                         this.validate = elementDefinition.validate;\r
310 \r
311                                 // Generates the essential attributes for the textarea tag.\r
312                                 attributes.rows = elementDefinition.rows || 5;\r
313                                 attributes.cols = elementDefinition.cols || 20;\r
314 \r
315                                 /** @ignore */\r
316                                 var innerHTML = function()\r
317                                 {\r
318                                         attributes[ 'aria-labelledby' ] = this._.labelId;\r
319                                         this._.required && ( attributes[ 'aria-required' ] = this._.required );\r
320                                         var html = [ '<div class="cke_dialog_ui_input_textarea" role="presentation"><textarea class="cke_dialog_ui_input_textarea" id="', domId, '" ' ];\r
321                                         for ( var i in attributes )\r
322                                                 html.push( i + '="' + CKEDITOR.tools.htmlEncode( attributes[i] ) + '" ' );\r
323                                         html.push( '>', CKEDITOR.tools.htmlEncode( me._['default'] ), '</textarea></div>' );\r
324                                         return html.join( '' );\r
325                                 };\r
326                                 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );\r
327                         },\r
328 \r
329                         /**\r
330                          * A single checkbox with a label on the right.\r
331                          * @constructor\r
332                          * @extends CKEDITOR.ui.dialog.uiElement\r
333                          * @example\r
334                          * @param {CKEDITOR.dialog} dialog\r
335                          * Parent dialog object.\r
336                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
337                          * The element definition. Accepted fields:\r
338                          * <ul>\r
339                          *      <li><strong>checked</strong> (Optional) Whether the checkbox is checked\r
340                          *      on instantiation. Defaults to false.</li>\r
341                          *      <li><strong>validate</strong> (Optional) The validation function.</li>\r
342                          *      <li><strong>label</strong> (Optional) The checkbox label.</li>\r
343                          * </ul>\r
344                          * @param {Array} htmlList\r
345                          * List of HTML code to output to.\r
346                          */\r
347                         checkbox : function( dialog, elementDefinition, htmlList )\r
348                         {\r
349                                 if ( arguments.length < 3 )\r
350                                         return;\r
351 \r
352                                 var _ = initPrivateObject.call( this, elementDefinition, { 'default' : !!elementDefinition[ 'default' ] } );\r
353 \r
354                                 if ( elementDefinition.validate )\r
355                                         this.validate = elementDefinition.validate;\r
356 \r
357                                 /** @ignore */\r
358                                 var innerHTML = function()\r
359                                 {\r
360                                         var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition,\r
361                                                         {\r
362                                                                 id : elementDefinition.id ? elementDefinition.id + '_checkbox' : CKEDITOR.tools.getNextNumber() + '_checkbox'\r
363                                                         }, true ),\r
364                                                 html = [];\r
365 \r
366                                         var labelId = CKEDITOR.tools.getNextNumber() + '_label';\r
367                                         var attributes = { 'class' : 'cke_dialog_ui_checkbox_input', type : 'checkbox', 'aria-labelledby' : labelId };\r
368                                         cleanInnerDefinition( myDefinition );\r
369                                         if ( elementDefinition[ 'default' ] )\r
370                                                 attributes.checked = 'checked';\r
371                                         _.checkbox = new CKEDITOR.ui.dialog.uiElement( dialog, myDefinition, html, 'input', null, attributes );\r
372                                         html.push( ' <label id="', labelId, '" for="', attributes.id, '">',\r
373                                                         CKEDITOR.tools.htmlEncode( elementDefinition.label ),\r
374                                                         '</label>' );\r
375                                         return html.join( '' );\r
376                                 };\r
377 \r
378                                 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, htmlList, 'span', null, null, innerHTML );\r
379                         },\r
380 \r
381                         /**\r
382                          * A group of radio buttons.\r
383                          * @constructor\r
384                          * @example\r
385                          * @extends CKEDITOR.ui.dialog.labeledElement\r
386                          * @param {CKEDITOR.dialog} dialog\r
387                          * Parent dialog object.\r
388                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
389                          * The element definition. Accepted fields:\r
390                          * <ul>\r
391                          *      <li><strong>default</strong> (Required) The default value.</li>\r
392                          *      <li><strong>validate</strong> (Optional) The validation function.</li>\r
393                          *      <li><strong>items</strong> (Required) An array of options. Each option\r
394                          *      is a 1- or 2-item array of format [ 'Description', 'Value' ]. If 'Value'\r
395                          *      is missing, then the value would be assumed to be the same as the\r
396                          *      description.</li>\r
397                          * </ul>\r
398                          * @param {Array} htmlList\r
399                          * List of HTML code to output to.\r
400                          */\r
401                         radio : function( dialog, elementDefinition, htmlList )\r
402                         {\r
403                                 if ( arguments.length < 3)\r
404                                         return;\r
405 \r
406                                 initPrivateObject.call( this, elementDefinition );\r
407                                 if ( !this._['default'] )\r
408                                         this._['default'] = this._.initValue = elementDefinition.items[0][1];\r
409                                 if ( elementDefinition.validate )\r
410                                         this.validate = elementDefinition.valdiate;\r
411                                 var children = [], me = this;\r
412 \r
413                                 /** @ignore */\r
414                                 var innerHTML = function()\r
415                                 {\r
416                                         var inputHtmlList = [], html = [],\r
417                                                 commonAttributes = { 'class' : 'cke_dialog_ui_radio_item', 'aria-labelledby' : this._.labelId },\r
418                                                 commonName = elementDefinition.id ? elementDefinition.id + '_radio' : CKEDITOR.tools.getNextNumber() + '_radio';\r
419                                         for ( var i = 0 ; i < elementDefinition.items.length ; i++ )\r
420                                         {\r
421                                                 var item = elementDefinition.items[i],\r
422                                                         title = item[2] !== undefined ? item[2] : item[0],\r
423                                                         value = item[1] !== undefined ? item[1] : item[0],\r
424                                                         inputId = CKEDITOR.tools.getNextNumber() + '_radio_input',\r
425                                                         labelId = inputId + '_label',\r
426                                                         inputDefinition = CKEDITOR.tools.extend( {}, elementDefinition,\r
427                                                                         {\r
428                                                                                 id : inputId,\r
429                                                                                 title : null,\r
430                                                                                 type : null\r
431                                                                         }, true ),\r
432                                                         labelDefinition = CKEDITOR.tools.extend( {}, inputDefinition,\r
433                                                                         {\r
434                                                                                 title : title\r
435                                                                         }, true ),\r
436                                                         inputAttributes =\r
437                                                         {\r
438                                                                 type : 'radio',\r
439                                                                 'class' : 'cke_dialog_ui_radio_input',\r
440                                                                 name : commonName,\r
441                                                                 value : value,\r
442                                                                 'aria-labelledby' : labelId\r
443                                                         },\r
444                                                         inputHtml = [];\r
445                                                 if ( me._['default'] == value )\r
446                                                         inputAttributes.checked = 'checked';\r
447                                                 cleanInnerDefinition( inputDefinition );\r
448                                                 cleanInnerDefinition( labelDefinition );\r
449                                                 children.push( new CKEDITOR.ui.dialog.uiElement( dialog, inputDefinition, inputHtml, 'input', null, inputAttributes ) );\r
450                                                 inputHtml.push( ' ' );\r
451                                                 new CKEDITOR.ui.dialog.uiElement( dialog, labelDefinition, inputHtml, 'label', null, { id : labelId, 'for' : inputAttributes.id },\r
452                                                            item[0] );\r
453                                                 inputHtmlList.push( inputHtml.join( '' ) );\r
454                                         }\r
455                                         new CKEDITOR.ui.dialog.hbox( dialog, [], inputHtmlList, html );\r
456                                         return html.join( '' );\r
457                                 };\r
458 \r
459                                 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );\r
460                                 this._.children = children;\r
461                         },\r
462 \r
463                         /**\r
464                          * A button with a label inside.\r
465                          * @constructor\r
466                          * @example\r
467                          * @extends CKEDITOR.ui.dialog.uiElement\r
468                          * @param {CKEDITOR.dialog} dialog\r
469                          * Parent dialog object.\r
470                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
471                          * The element definition. Accepted fields:\r
472                          * <ul>\r
473                          *      <li><strong>label</strong> (Required) The button label.</li>\r
474                          *      <li><strong>disabled</strong> (Optional) Set to true if you want the\r
475                          *      button to appear in disabled state.</li>\r
476                          * </ul>\r
477                          * @param {Array} htmlList\r
478                          * List of HTML code to output to.\r
479                          */\r
480                         button : function( dialog, elementDefinition, htmlList )\r
481                         {\r
482                                 if ( !arguments.length )\r
483                                         return;\r
484 \r
485                                 if ( typeof elementDefinition == 'function' )\r
486                                         elementDefinition = elementDefinition( dialog.getParentEditor() );\r
487 \r
488                                 initPrivateObject.call( this, elementDefinition, { disabled : elementDefinition.disabled || false } );\r
489 \r
490                                 // Add OnClick event to this input.\r
491                                 CKEDITOR.event.implementOn( this );\r
492 \r
493                                 var me = this;\r
494 \r
495                                 // Register an event handler for processing button clicks.\r
496                                 dialog.on( 'load', function( eventInfo )\r
497                                         {\r
498                                                 var element = this.getElement();\r
499 \r
500                                                 (function()\r
501                                                 {\r
502                                                         element.on( 'click', function( evt )\r
503                                                                 {\r
504                                                                         me.fire( 'click', { dialog : me.getDialog() } );\r
505                                                                         evt.data.preventDefault();\r
506                                                                 } );\r
507 \r
508                                                         element.on( 'keydown', function( evt )\r
509                                                                 {\r
510                                                                         if ( evt.data.getKeystroke() in { 32:1, 13:1 } )\r
511                                                                         {\r
512                                                                                 me.click();\r
513                                                                                 evt.data.preventDefault();\r
514                                                                         }\r
515                                                                 } );\r
516                                                 })();\r
517 \r
518                                                 element.unselectable();\r
519                                         }, this );\r
520 \r
521                                 var outerDefinition = CKEDITOR.tools.extend( {}, elementDefinition );\r
522                                 delete outerDefinition.style;\r
523 \r
524                                 var labelId = CKEDITOR.tools.getNextNumber() + '_label';\r
525                                 CKEDITOR.ui.dialog.uiElement.call(\r
526                                         this,\r
527                                         dialog,\r
528                                         outerDefinition,\r
529                                         htmlList,\r
530                                         'a',\r
531                                         null,\r
532                                         {\r
533                                                 style : elementDefinition.style,\r
534                                                 href : 'javascript:void(0)',\r
535                                                 title : elementDefinition.label,\r
536                                                 hidefocus : 'true',\r
537                                                 'class' : elementDefinition['class'],\r
538                                                 role : 'button',\r
539                                                 'aria-labelledby' : labelId\r
540                                         },\r
541                                         '<span id="' + labelId + '" class="cke_dialog_ui_button">' +\r
542                                                 CKEDITOR.tools.htmlEncode( elementDefinition.label ) +\r
543                                         '</span>' );\r
544                         },\r
545 \r
546                         /**\r
547                          * A select box.\r
548                          * @extends CKEDITOR.ui.dialog.uiElement\r
549                          * @example\r
550                          * @constructor\r
551                          * @param {CKEDITOR.dialog} dialog\r
552                          * Parent dialog object.\r
553                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
554                          * The element definition. Accepted fields:\r
555                          * <ul>\r
556                          *      <li><strong>default</strong> (Required) The default value.</li>\r
557                          *      <li><strong>validate</strong> (Optional) The validation function.</li>\r
558                          *      <li><strong>items</strong> (Required) An array of options. Each option\r
559                          *      is a 1- or 2-item array of format [ 'Description', 'Value' ]. If 'Value'\r
560                          *      is missing, then the value would be assumed to be the same as the\r
561                          *      description.</li>\r
562                          *      <li><strong>multiple</strong> (Optional) Set this to true if you'd like\r
563                          *      to have a multiple-choice select box.</li>\r
564                          *      <li><strong>size</strong> (Optional) The number of items to display in\r
565                          *      the select box.</li>\r
566                          * </ul>\r
567                          * @param {Array} htmlList\r
568                          * List of HTML code to output to.\r
569                          */\r
570                         select : function( dialog, elementDefinition, htmlList )\r
571                         {\r
572                                 if ( arguments.length < 3 )\r
573                                         return;\r
574 \r
575                                 var _ = initPrivateObject.call( this, elementDefinition );\r
576 \r
577                                 if ( elementDefinition.validate )\r
578                                         this.validate = elementDefinition.validate;\r
579 \r
580                                 _.inputId = CKEDITOR.tools.getNextNumber() + '_select';\r
581                                 /** @ignore */\r
582                                 var innerHTML = function()\r
583                                 {\r
584                                         var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition,\r
585                                                         {\r
586                                                                 id : elementDefinition.id ? elementDefinition.id + '_select' : CKEDITOR.tools.getNextNumber() + '_select'\r
587                                                         }, true ),\r
588                                                 html = [],\r
589                                                 innerHTML = [],\r
590                                                 attributes = { 'id' : _.inputId, 'class' : 'cke_dialog_ui_input_select', 'aria-labelledby' : this._.labelId };\r
591 \r
592                                         // Add multiple and size attributes from element definition.\r
593                                         if ( elementDefinition.size != undefined )\r
594                                                 attributes.size = elementDefinition.size;\r
595                                         if ( elementDefinition.multiple != undefined )\r
596                                                 attributes.multiple = elementDefinition.multiple;\r
597 \r
598                                         cleanInnerDefinition( myDefinition );\r
599                                         for ( var i = 0, item ; i < elementDefinition.items.length && ( item = elementDefinition.items[i] ) ; i++ )\r
600                                         {\r
601                                                 innerHTML.push( '<option value="',\r
602                                                         CKEDITOR.tools.htmlEncode( item[1] !== undefined ? item[1] : item[0] ), '" /> ',\r
603                                                         CKEDITOR.tools.htmlEncode( item[0] ) );\r
604                                         }\r
605 \r
606                                         _.select = new CKEDITOR.ui.dialog.uiElement( dialog, myDefinition, html, 'select', null, attributes, innerHTML.join( '' ) );\r
607                                         return html.join( '' );\r
608                                 };\r
609 \r
610                                 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );\r
611                         },\r
612 \r
613                         /**\r
614                          * A file upload input.\r
615                          * @extends CKEDITOR.ui.dialog.labeledElement\r
616                          * @example\r
617                          * @constructor\r
618                          * @param {CKEDITOR.dialog} dialog\r
619                          * Parent dialog object.\r
620                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
621                          * The element definition. Accepted fields:\r
622                          * <ul>\r
623                          *      <li><strong>validate</strong> (Optional) The validation function.</li>\r
624                          * </ul>\r
625                          * @param {Array} htmlList\r
626                          * List of HTML code to output to.\r
627                          */\r
628                         file : function( dialog, elementDefinition, htmlList )\r
629                         {\r
630                                 if ( arguments.length < 3 )\r
631                                         return;\r
632 \r
633                                 if ( elementDefinition['default'] === undefined )\r
634                                         elementDefinition['default'] = '';\r
635 \r
636                                 var _ = CKEDITOR.tools.extend( initPrivateObject.call( this, elementDefinition ), { definition : elementDefinition, buttons : [] } );\r
637 \r
638                                 if ( elementDefinition.validate )\r
639                                         this.validate = elementDefinition.validate;\r
640 \r
641                                 /** @ignore */\r
642                                 var innerHTML = function()\r
643                                 {\r
644                                         _.frameId = CKEDITOR.tools.getNextNumber() + '_fileInput';\r
645 \r
646                                         // Support for custom document.domain in IE.\r
647                                         var isCustomDomain = CKEDITOR.env.isCustomDomain();\r
648 \r
649                                         var html = [\r
650                                                 '<iframe' +\r
651                                                         ' frameborder="0"' +\r
652                                                         ' allowtransparency="0"' +\r
653                                                         ' class="cke_dialog_ui_input_file"' +\r
654                                                         ' id="', _.frameId, '"' +\r
655                                                         ' title="', elementDefinition.label, '"' +\r
656                                                         ' src="javascript:void(' ];\r
657 \r
658                                         html.push(\r
659                                                         isCustomDomain ?\r
660                                                                 '(function(){' +\r
661                                                                         'document.open();' +\r
662                                                                         'document.domain=\'' + document.domain + '\';' +\r
663                                                                         'document.close();' +\r
664                                                                 '})()'\r
665                                                         :\r
666                                                                 '0' );\r
667 \r
668                                         html.push(\r
669                                                         ')">' +\r
670                                                 '</iframe>' );\r
671 \r
672                                         return html.join( '' );\r
673                                 };\r
674 \r
675                                 // IE BUG: Parent container does not resize to contain the iframe automatically.\r
676                                 dialog.on( 'load', function()\r
677                                         {\r
678                                                 var iframe = CKEDITOR.document.getById( _.frameId ),\r
679                                                         contentDiv = iframe.getParent();\r
680                                                 contentDiv.addClass( 'cke_dialog_ui_input_file' );\r
681                                         } );\r
682 \r
683                                 CKEDITOR.ui.dialog.labeledElement.call( this, dialog, elementDefinition, htmlList, innerHTML );\r
684                         },\r
685 \r
686                         /**\r
687                          * A button for submitting the file in a file upload input.\r
688                          * @extends CKEDITOR.ui.dialog.button\r
689                          * @example\r
690                          * @constructor\r
691                          * @param {CKEDITOR.dialog} dialog\r
692                          * Parent dialog object.\r
693                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
694                          * The element definition. Accepted fields:\r
695                          * <ul>\r
696                          *      <li><strong>for</strong> (Required) The file input's page and element Id\r
697                          *      to associate to, in a 2-item array format: [ 'page_id', 'element_id' ].\r
698                          *      </li>\r
699                          *      <li><strong>validate</strong> (Optional) The validation function.</li>\r
700                          * </ul>\r
701                          * @param {Array} htmlList\r
702                          * List of HTML code to output to.\r
703                          */\r
704                         fileButton : function( dialog, elementDefinition, htmlList )\r
705                         {\r
706                                 if ( arguments.length < 3 )\r
707                                         return;\r
708 \r
709                                 var _ = initPrivateObject.call( this, elementDefinition ),\r
710                                         me = this;\r
711 \r
712                                 if ( elementDefinition.validate )\r
713                                         this.validate = elementDefinition.validate;\r
714 \r
715                                 var myDefinition = CKEDITOR.tools.extend( {}, elementDefinition );\r
716                                 var onClick = myDefinition.onClick;\r
717                                 myDefinition.className = ( myDefinition.className ? myDefinition.className + ' ' : '' ) + 'cke_dialog_ui_button';\r
718                                 myDefinition.onClick = function( evt )\r
719                                 {\r
720                                         var target = elementDefinition[ 'for' ];                // [ pageId, elementId ]\r
721                                         if ( !onClick || onClick.call( this, evt ) !== false )\r
722                                         {\r
723                                                 dialog.getContentElement( target[0], target[1] ).submit();\r
724                                                 this.disable();\r
725                                         }\r
726                                 };\r
727 \r
728                                 dialog.on( 'load', function()\r
729                                                 {\r
730                                                         dialog.getContentElement( elementDefinition[ 'for' ][0], elementDefinition[ 'for' ][1] )._.buttons.push( me );\r
731                                                 } );\r
732 \r
733                                 CKEDITOR.ui.dialog.button.call( this, dialog, myDefinition, htmlList );\r
734                         },\r
735 \r
736                         html : (function()\r
737                         {\r
738                                 var myHtmlRe = /^\s*<[\w:]+\s+([^>]*)?>/,\r
739                                         theirHtmlRe = /^(\s*<[\w:]+(?:\s+[^>]*)?)((?:.|\r|\n)+)$/,\r
740                                         emptyTagRe = /\/$/;\r
741                                 /**\r
742                                  * A dialog element made from raw HTML code.\r
743                                  * @extends CKEDITOR.ui.dialog.uiElement\r
744                                  * @name CKEDITOR.ui.dialog.html\r
745                                  * @param {CKEDITOR.dialog} dialog Parent dialog object.\r
746                                  * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition Element definition.\r
747                                  * Accepted fields:\r
748                                  * <ul>\r
749                                  *      <li><strong>html</strong> (Required) HTML code of this element.</li>\r
750                                  * </ul>\r
751                                  * @param {Array} htmlList List of HTML code to be added to the dialog's content area.\r
752                                  * @example\r
753                                  * @constructor\r
754                                  */\r
755                                 return function( dialog, elementDefinition, htmlList )\r
756                                 {\r
757                                         if ( arguments.length < 3 )\r
758                                                 return;\r
759 \r
760                                         var myHtmlList = [],\r
761                                                 myHtml,\r
762                                                 theirHtml = elementDefinition.html,\r
763                                                 myMatch, theirMatch;\r
764 \r
765                                         // If the HTML input doesn't contain any tags at the beginning, add a <span> tag around it.\r
766                                         if ( theirHtml.charAt( 0 ) != '<' )\r
767                                                 theirHtml = '<span>' + theirHtml + '</span>';\r
768 \r
769                                         // Look for focus function in definition.\r
770                                         var focus = elementDefinition.focus;\r
771                                         if ( focus )\r
772                                         {\r
773                                                 var oldFocus = this.focus;\r
774                                                 this.focus = function()\r
775                                                 {\r
776                                                         oldFocus.call( this );\r
777                                                         typeof focus == 'function' && focus.call( this );\r
778                                                         this.fire( 'focus' );\r
779                                                 };\r
780                                                 if ( elementDefinition.isFocusable )\r
781                                                 {\r
782                                                         var oldIsFocusable = this.isFocusable;\r
783                                                         this.isFocusable = oldIsFocusable;\r
784                                                 }\r
785                                                 this.keyboardFocusable = true;\r
786                                         }\r
787 \r
788                                         CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, myHtmlList, 'span', null, null, '' );\r
789 \r
790                                         // Append the attributes created by the uiElement call to the real HTML.\r
791                                         myHtml = myHtmlList.join( '' );\r
792                                         myMatch = myHtml.match( myHtmlRe );\r
793                                         theirMatch = theirHtml.match( theirHtmlRe ) || [ '', '', '' ];\r
794 \r
795                                         if ( emptyTagRe.test( theirMatch[1] ) )\r
796                                         {\r
797                                                 theirMatch[1] = theirMatch[1].slice( 0, -1 );\r
798                                                 theirMatch[2] = '/' + theirMatch[2];\r
799                                         }\r
800 \r
801                                         htmlList.push( [ theirMatch[1], ' ', myMatch[1] || '', theirMatch[2] ].join( '' ) );\r
802                                 };\r
803                         })(),\r
804 \r
805                         /**\r
806                          * Form fieldset for grouping dialog UI elements.\r
807                          * @constructor\r
808                          * @extends CKEDITOR.ui.dialog.uiElement\r
809                          * @param {CKEDITOR.dialog} dialog Parent dialog object.\r
810                          * @param {Array} childObjList\r
811                          * Array of {@link CKEDITOR.ui.dialog.uiElement} objects inside this\r
812                          * container.\r
813                          * @param {Array} childHtmlList\r
814                          * Array of HTML code that correspond to the HTML output of all the\r
815                          * objects in childObjList.\r
816                          * @param {Array} htmlList\r
817                          * Array of HTML code that this element will output to.\r
818                          * @param {CKEDITOR.dialog.uiElementDefinition} elementDefinition\r
819                          * The element definition. Accepted fields:\r
820                          * <ul>\r
821                          *      <li><strong>label</strong> (Optional) The legend of the this fieldset.</li>\r
822                          *      <li><strong>children</strong> (Required) An array of dialog field definitions which will be grouped inside this fieldset. </li>\r
823                          * </ul>\r
824                          */\r
825                         fieldset : function( dialog, childObjList, childHtmlList, htmlList, elementDefinition )\r
826                         {\r
827                                 var legendLabel = elementDefinition.label;\r
828                                 /** @ignore */\r
829                                 var innerHTML = function()\r
830                                 {\r
831                                         var html = [];\r
832                                         legendLabel && html.push( '<legend>' + legendLabel + '</legend>' );\r
833                                         for ( var i = 0; i < childHtmlList.length; i++ )\r
834                                                 html.push( childHtmlList[ i ] );\r
835                                         return html.join( '' );\r
836                                 };\r
837 \r
838                                 this._ = { children : childObjList };\r
839                                 CKEDITOR.ui.dialog.uiElement.call( this, dialog, elementDefinition, htmlList, 'fieldset', null, null, innerHTML );\r
840                         }\r
841 \r
842                 }, true );\r
843 \r
844         CKEDITOR.ui.dialog.html.prototype = new CKEDITOR.ui.dialog.uiElement;\r
845 \r
846         CKEDITOR.ui.dialog.labeledElement.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement,\r
847                         /** @lends CKEDITOR.ui.dialog.labeledElement.prototype */\r
848                         {\r
849                                 /**\r
850                                  * Sets the label text of the element.\r
851                                  * @param {String} label The new label text.\r
852                                  * @returns {CKEDITOR.ui.dialog.labeledElement} The current labeled element.\r
853                                  * @example\r
854                                  */\r
855                                 setLabel : function( label )\r
856                                 {\r
857                                         var node = CKEDITOR.document.getById( this._.labelId );\r
858                                         if ( node.getChildCount() < 1 )\r
859                                                 ( new CKEDITOR.dom.text( label, CKEDITOR.document ) ).appendTo( node );\r
860                                         else\r
861                                                 node.getChild( 0 ).$.nodeValue = label;\r
862                                         return this;\r
863                                 },\r
864 \r
865                                 /**\r
866                                  * Retrieves the current label text of the elment.\r
867                                  * @returns {String} The current label text.\r
868                                  * @example\r
869                                  */\r
870                                 getLabel : function()\r
871                                 {\r
872                                         var node = CKEDITOR.document.getById( this._.labelId );\r
873                                         if ( !node || node.getChildCount() < 1 )\r
874                                                 return '';\r
875                                         else\r
876                                                 return node.getChild( 0 ).getText();\r
877                                 },\r
878 \r
879                                 /**\r
880                                  * Defines the onChange event for UI element definitions.\r
881                                  * @field\r
882                                  * @type Object\r
883                                  * @example\r
884                                  */\r
885                                 eventProcessors : commonEventProcessors\r
886                         }, true );\r
887 \r
888         CKEDITOR.ui.dialog.button.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement,\r
889                         /** @lends CKEDITOR.ui.dialog.button.prototype */\r
890                         {\r
891                                 /**\r
892                                  * Simulates a click to the button.\r
893                                  * @example\r
894                                  * @returns {Object} Return value of the 'click' event.\r
895                                  */\r
896                                 click : function()\r
897                                 {\r
898                                         if ( !this._.disabled )\r
899                                                 return this.fire( 'click', { dialog : this._.dialog } );\r
900                                         this.getElement().$.blur();\r
901                                         return false;\r
902                                 },\r
903 \r
904                                 /**\r
905                                  * Enables the button.\r
906                                  * @example\r
907                                  */\r
908                                 enable : function()\r
909                                 {\r
910                                         this._.disabled = false;\r
911                                         var element = this.getElement();\r
912                                         element && element.removeClass( 'disabled' );\r
913                                 },\r
914 \r
915                                 /**\r
916                                  * Disables the button.\r
917                                  * @example\r
918                                  */\r
919                                 disable : function()\r
920                                 {\r
921                                         this._.disabled = true;\r
922                                         this.getElement().addClass( 'disabled' );\r
923                                 },\r
924 \r
925                                 isVisible : function()\r
926                                 {\r
927                                         return this.getElement().getFirst().isVisible();\r
928                                 },\r
929 \r
930                                 isEnabled : function()\r
931                                 {\r
932                                         return !this._.disabled;\r
933                                 },\r
934 \r
935                                 /**\r
936                                  * Defines the onChange event and onClick for button element definitions.\r
937                                  * @field\r
938                                  * @type Object\r
939                                  * @example\r
940                                  */\r
941                                 eventProcessors : CKEDITOR.tools.extend( {}, CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors,\r
942                                         {\r
943                                                 /** @ignore */\r
944                                                 onClick : function( dialog, func )\r
945                                                 {\r
946                                                         this.on( 'click', func );\r
947                                                 }\r
948                                         }, true ),\r
949 \r
950                                 /**\r
951                                  * Handler for the element's access key up event. Simulates a click to\r
952                                  * the button.\r
953                                  * @example\r
954                                  */\r
955                                 accessKeyUp : function()\r
956                                 {\r
957                                         this.click();\r
958                                 },\r
959 \r
960                                 /**\r
961                                  * Handler for the element's access key down event. Simulates a mouse\r
962                                  * down to the button.\r
963                                  * @example\r
964                                  */\r
965                                 accessKeyDown : function()\r
966                                 {\r
967                                         this.focus();\r
968                                 },\r
969 \r
970                                 keyboardFocusable : true\r
971                         }, true );\r
972 \r
973         CKEDITOR.ui.dialog.textInput.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.labeledElement,\r
974                         /** @lends CKEDITOR.ui.dialog.textInput.prototype */\r
975                         {\r
976                                 /**\r
977                                  * Gets the text input DOM element under this UI object.\r
978                                  * @example\r
979                                  * @returns {CKEDITOR.dom.element} The DOM element of the text input.\r
980                                  */\r
981                                 getInputElement : function()\r
982                                 {\r
983                                         return CKEDITOR.document.getById( this._.inputId );\r
984                                 },\r
985 \r
986                                 /**\r
987                                  * Puts focus into the text input.\r
988                                  * @example\r
989                                  */\r
990                                 focus : function()\r
991                                 {\r
992                                         var me = this.selectParentTab();\r
993 \r
994                                         // GECKO BUG: setTimeout() is needed to workaround invisible selections.\r
995                                         setTimeout( function()\r
996                                                 {\r
997                                                         var element = me.getInputElement();\r
998                                                         element && element.$.focus();\r
999                                                 }, 0 );\r
1000                                 },\r
1001 \r
1002                                 /**\r
1003                                  * Selects all the text in the text input.\r
1004                                  * @example\r
1005                                  */\r
1006                                 select : function()\r
1007                                 {\r
1008                                         var me = this.selectParentTab();\r
1009 \r
1010                                         // GECKO BUG: setTimeout() is needed to workaround invisible selections.\r
1011                                         setTimeout( function()\r
1012                                                 {\r
1013                                                         var e = me.getInputElement();\r
1014                                                         if ( e )\r
1015                                                         {\r
1016                                                                 e.$.focus();\r
1017                                                                 e.$.select();\r
1018                                                         }\r
1019                                                 }, 0 );\r
1020                                 },\r
1021 \r
1022                                 /**\r
1023                                  * Handler for the text input's access key up event. Makes a select()\r
1024                                  * call to the text input.\r
1025                                  * @example\r
1026                                  */\r
1027                                 accessKeyUp : function()\r
1028                                 {\r
1029                                         this.select();\r
1030                                 },\r
1031 \r
1032                                 /**\r
1033                                  * Sets the value of this text input object.\r
1034                                  * @param {Object} value The new value.\r
1035                                  * @returns {CKEDITOR.ui.dialog.textInput} The current UI element.\r
1036                                  * @example\r
1037                                  * uiElement.setValue( 'Blamo' );\r
1038                                  */\r
1039                                 setValue : function( value )\r
1040                                 {\r
1041                                         !value && ( value = '' );\r
1042                                         return CKEDITOR.ui.dialog.uiElement.prototype.setValue.call( this, value );\r
1043                                 },\r
1044 \r
1045                                 keyboardFocusable : true\r
1046                         }, commonPrototype, true );\r
1047 \r
1048         CKEDITOR.ui.dialog.textarea.prototype = new CKEDITOR.ui.dialog.textInput();\r
1049 \r
1050         CKEDITOR.ui.dialog.select.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.labeledElement,\r
1051                         /** @lends CKEDITOR.ui.dialog.select.prototype */\r
1052                         {\r
1053                                 /**\r
1054                                  * Gets the DOM element of the select box.\r
1055                                  * @returns {CKEDITOR.dom.element} The &lt;select&gt; element of this UI\r
1056                                  * element.\r
1057                                  * @example\r
1058                                  */\r
1059                                 getInputElement : function()\r
1060                                 {\r
1061                                         return this._.select.getElement();\r
1062                                 },\r
1063 \r
1064                                 /**\r
1065                                  * Adds an option to the select box.\r
1066                                  * @param {String} label Option label.\r
1067                                  * @param {String} value (Optional) Option value, if not defined it'll be\r
1068                                  * assumed to be the same as the label.\r
1069                                  * @param {Number} index (Optional) Position of the option to be inserted\r
1070                                  * to. If not defined the new option will be inserted to the end of list.\r
1071                                  * @example\r
1072                                  * @returns {CKEDITOR.ui.dialog.select} The current select UI element.\r
1073                                  */\r
1074                                 add : function( label, value, index )\r
1075                                 {\r
1076                                         var option = new CKEDITOR.dom.element( 'option', this.getDialog().getParentEditor().document ),\r
1077                                                 selectElement = this.getInputElement().$;\r
1078                                         option.$.text = label;\r
1079                                         option.$.value = ( value === undefined || value === null ) ? label : value;\r
1080                                         if ( index === undefined || index === null )\r
1081                                         {\r
1082                                                 if ( CKEDITOR.env.ie )\r
1083                                                         selectElement.add( option.$ );\r
1084                                                 else\r
1085                                                         selectElement.add( option.$, null );\r
1086                                         }\r
1087                                         else\r
1088                                                 selectElement.add( option.$, index );\r
1089                                         return this;\r
1090                                 },\r
1091 \r
1092                                 /**\r
1093                                  * Removes an option from the selection list.\r
1094                                  * @param {Number} index Index of the option to be removed.\r
1095                                  * @example\r
1096                                  * @returns {CKEDITOR.ui.dialog.select} The current select UI element.\r
1097                                  */\r
1098                                 remove : function( index )\r
1099                                 {\r
1100                                         var selectElement = this.getInputElement().$;\r
1101                                         selectElement.remove( index );\r
1102                                         return this;\r
1103                                 },\r
1104 \r
1105                                 /**\r
1106                                  * Clears all options out of the selection list.\r
1107                                  * @returns {CKEDITOR.ui.dialog.select} The current select UI element.\r
1108                                  */\r
1109                                 clear : function()\r
1110                                 {\r
1111                                         var selectElement = this.getInputElement().$;\r
1112                                         while ( selectElement.length > 0 )\r
1113                                                 selectElement.remove( 0 );\r
1114                                         return this;\r
1115                                 },\r
1116 \r
1117                                 keyboardFocusable : true\r
1118                         }, commonPrototype, true );\r
1119 \r
1120         CKEDITOR.ui.dialog.checkbox.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement,\r
1121                         /** @lends CKEDITOR.ui.dialog.checkbox.prototype */\r
1122                         {\r
1123                                 /**\r
1124                                  * Gets the checkbox DOM element.\r
1125                                  * @example\r
1126                                  * @returns {CKEDITOR.dom.element} The DOM element of the checkbox.\r
1127                                  */\r
1128                                 getInputElement : function()\r
1129                                 {\r
1130                                         return this._.checkbox.getElement();\r
1131                                 },\r
1132 \r
1133                                 /**\r
1134                                  * Sets the state of the checkbox.\r
1135                                  * @example\r
1136                                  * @param {Boolean} true to tick the checkbox, false to untick it.\r
1137                                  */\r
1138                                 setValue : function( checked )\r
1139                                 {\r
1140                                         this.getInputElement().$.checked = checked;\r
1141                                         this.fire( 'change', { value : checked } );\r
1142                                 },\r
1143 \r
1144                                 /**\r
1145                                  * Gets the state of the checkbox.\r
1146                                  * @example\r
1147                                  * @returns {Boolean} true means the checkbox is ticked, false means it's not ticked.\r
1148                                  */\r
1149                                 getValue : function()\r
1150                                 {\r
1151                                         return this.getInputElement().$.checked;\r
1152                                 },\r
1153 \r
1154                                 /**\r
1155                                  * Handler for the access key up event. Toggles the checkbox.\r
1156                                  * @example\r
1157                                  */\r
1158                                 accessKeyUp : function()\r
1159                                 {\r
1160                                         this.setValue( !this.getValue() );\r
1161                                 },\r
1162 \r
1163                                 /**\r
1164                                  * Defines the onChange event for UI element definitions.\r
1165                                  * @field\r
1166                                  * @type Object\r
1167                                  * @example\r
1168                                  */\r
1169                                 eventProcessors :\r
1170                                 {\r
1171                                         onChange : function( dialog, func )\r
1172                                         {\r
1173                                                 if ( !CKEDITOR.env.ie )\r
1174                                                         return commonEventProcessors.onChange.apply( this, arguments );\r
1175                                                 else\r
1176                                                 {\r
1177                                                         dialog.on( 'load', function()\r
1178                                                                 {\r
1179                                                                         var element = this._.checkbox.getElement();\r
1180                                                                         element.on( 'propertychange', function( evt )\r
1181                                                                                 {\r
1182                                                                                         evt = evt.data.$;\r
1183                                                                                         if ( evt.propertyName == 'checked' )\r
1184                                                                                                 this.fire( 'change', { value : element.$.checked } );\r
1185                                                                                 }, this );\r
1186                                                                 }, this );\r
1187                                                         this.on( 'change', func );\r
1188                                                 }\r
1189                                                 return null;\r
1190                                         }\r
1191                                 },\r
1192 \r
1193                                 keyboardFocusable : true\r
1194                         }, commonPrototype, true );\r
1195 \r
1196         CKEDITOR.ui.dialog.radio.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.uiElement,\r
1197                         /** @lends CKEDITOR.ui.dialog.radio.prototype */\r
1198                         {\r
1199                                 /**\r
1200                                  * Checks one of the radio buttons in this button group.\r
1201                                  * @example\r
1202                                  * @param {String} value The value of the button to be chcked.\r
1203                                  */\r
1204                                 setValue : function( value )\r
1205                                 {\r
1206                                         var children = this._.children,\r
1207                                                 item;\r
1208                                         for ( var i = 0 ; ( i < children.length ) && ( item = children[i] ) ; i++ )\r
1209                                                 item.getElement().$.checked = ( item.getValue() == value );\r
1210                                         this.fire( 'change', { value : value } );\r
1211                                 },\r
1212 \r
1213                                 /**\r
1214                                  * Gets the value of the currently checked radio button.\r
1215                                  * @example\r
1216                                  * @returns {String} The currently checked button's value.\r
1217                                  */\r
1218                                 getValue : function()\r
1219                                 {\r
1220                                         var children = this._.children;\r
1221                                         for ( var i = 0 ; i < children.length ; i++ )\r
1222                                         {\r
1223                                                 if ( children[i].getElement().$.checked )\r
1224                                                         return children[i].getValue();\r
1225                                         }\r
1226                                         return null;\r
1227                                 },\r
1228 \r
1229                                 /**\r
1230                                  * Handler for the access key up event. Focuses the currently\r
1231                                  * selected radio button, or the first radio button if none is\r
1232                                  * selected.\r
1233                                  * @example\r
1234                                  */\r
1235                                 accessKeyUp : function()\r
1236                                 {\r
1237                                         var children = this._.children, i;\r
1238                                         for ( i = 0 ; i < children.length ; i++ )\r
1239                                         {\r
1240                                                 if ( children[i].getElement().$.checked )\r
1241                                                 {\r
1242                                                         children[i].getElement().focus();\r
1243                                                         return;\r
1244                                                 }\r
1245                                         }\r
1246                                         children[0].getElement().focus();\r
1247                                 },\r
1248 \r
1249                                 /**\r
1250                                  * Defines the onChange event for UI element definitions.\r
1251                                  * @field\r
1252                                  * @type Object\r
1253                                  * @example\r
1254                                  */\r
1255                                 eventProcessors :\r
1256                                 {\r
1257                                         onChange : function( dialog, func )\r
1258                                         {\r
1259                                                 if ( !CKEDITOR.env.ie )\r
1260                                                         return commonEventProcessors.onChange.apply( this, arguments );\r
1261                                                 else\r
1262                                                 {\r
1263                                                         dialog.on( 'load', function()\r
1264                                                                 {\r
1265                                                                         var children = this._.children, me = this;\r
1266                                                                         for ( var i = 0 ; i < children.length ; i++ )\r
1267                                                                         {\r
1268                                                                                 var element = children[i].getElement();\r
1269                                                                                 element.on( 'propertychange', function( evt )\r
1270                                                                                         {\r
1271                                                                                                 evt = evt.data.$;\r
1272                                                                                                 if ( evt.propertyName == 'checked' && this.$.checked )\r
1273                                                                                                         me.fire( 'change', { value : this.getAttribute( 'value' ) } );\r
1274                                                                                         } );\r
1275                                                                         }\r
1276                                                                 }, this );\r
1277                                                         this.on( 'change', func );\r
1278                                                 }\r
1279                                                 return null;\r
1280                                         }\r
1281                                 },\r
1282 \r
1283                                 keyboardFocusable : true\r
1284                         }, commonPrototype, true );\r
1285 \r
1286         CKEDITOR.ui.dialog.file.prototype = CKEDITOR.tools.extend( new CKEDITOR.ui.dialog.labeledElement,\r
1287                         commonPrototype,\r
1288                         /** @lends CKEDITOR.ui.dialog.file.prototype */\r
1289                         {\r
1290                                 /**\r
1291                                  * Gets the &lt;input&gt; element of this file input.\r
1292                                  * @returns {CKEDITOR.dom.element} The file input element.\r
1293                                  * @example\r
1294                                  */\r
1295                                 getInputElement : function()\r
1296                                 {\r
1297                                         var frameDocument = CKEDITOR.document.getById( this._.frameId ).getFrameDocument();\r
1298                                         return frameDocument.$.forms.length > 0 ?\r
1299                                                 new CKEDITOR.dom.element( frameDocument.$.forms[0].elements[0] ) :\r
1300                                                 this.getElement();\r
1301                                 },\r
1302 \r
1303                                 /**\r
1304                                  * Uploads the file in the file input.\r
1305                                  * @returns {CKEDITOR.ui.dialog.file} This object.\r
1306                                  * @example\r
1307                                  */\r
1308                                 submit : function()\r
1309                                 {\r
1310                                         this.getInputElement().getParent().$.submit();\r
1311                                         return this;\r
1312                                 },\r
1313 \r
1314                                 /**\r
1315                                  * Get the action assigned to the form.\r
1316                                  * @returns {String} The value of the action.\r
1317                                  * @example\r
1318                                  */\r
1319                                 getAction : function( action )\r
1320                                 {\r
1321                                         return this.getInputElement().getParent().$.action;\r
1322                                 },\r
1323 \r
1324                                 /**\r
1325                                  * Redraws the file input and resets the file path in the file input.\r
1326                                  * The redraw logic is necessary because non-IE browsers tend to clear\r
1327                                  * the &lt;iframe&gt; containing the file input after closing the dialog.\r
1328                                  * @example\r
1329                                  */\r
1330                                 reset : function()\r
1331                                 {\r
1332                                         var frameElement = CKEDITOR.document.getById( this._.frameId ),\r
1333                                                 frameDocument = frameElement.getFrameDocument(),\r
1334                                                 elementDefinition = this._.definition,\r
1335                                                 buttons = this._.buttons;\r
1336 \r
1337                                         function generateFormField()\r
1338                                         {\r
1339                                                 frameDocument.$.open();\r
1340 \r
1341                                                 // Support for custom document.domain in IE.\r
1342                                                 if ( CKEDITOR.env.isCustomDomain() )\r
1343                                                         frameDocument.$.domain = document.domain;\r
1344 \r
1345                                                 var size = '';\r
1346                                                 if ( elementDefinition.size )\r
1347                                                         size = elementDefinition.size - ( CKEDITOR.env.ie  ? 7 : 0 );   // "Browse" button is bigger in IE.\r
1348 \r
1349                                                 frameDocument.$.write( [ '<html><head><title></title></head><body style="margin: 0; overflow: hidden; background: transparent;">',\r
1350                                                                 '<form enctype="multipart/form-data" method="POST" action="',\r
1351                                                                 CKEDITOR.tools.htmlEncode( elementDefinition.action ),\r
1352                                                                 '">',\r
1353                                                                 '<input type="file" name="',\r
1354                                                                 CKEDITOR.tools.htmlEncode( elementDefinition.id || 'cke_upload' ),\r
1355                                                                 '" size="',\r
1356                                                                 CKEDITOR.tools.htmlEncode( size > 0 ? size : "" ),\r
1357                                                                 '" />',\r
1358                                                                 '</form>',\r
1359                                                                 '</body></html>' ].join( '' ) );\r
1360 \r
1361                                                 frameDocument.$.close();\r
1362 \r
1363                                                 for ( var i = 0 ; i < buttons.length ; i++ )\r
1364                                                         buttons[i].enable();\r
1365                                         }\r
1366 \r
1367                                         // #3465: Wait for the browser to finish rendering the dialog first.\r
1368                                         if ( CKEDITOR.env.gecko )\r
1369                                                 setTimeout( generateFormField, 500 );\r
1370                                         else\r
1371                                                 generateFormField();\r
1372                                 },\r
1373 \r
1374                                 getValue : function()\r
1375                                 {\r
1376                                         // The file path returned from the input tag is incomplete anyway, so it's\r
1377                                         // safe to ignore it and prevent the confirmation dialog from appearing.\r
1378                                         // (Part of #3465)\r
1379                                         return '';\r
1380                                 },\r
1381 \r
1382                                 /**\r
1383                                  * Defines the onChange event for UI element definitions.\r
1384                                  * @field\r
1385                                  * @type Object\r
1386                                  * @example\r
1387                                  */\r
1388                                 eventProcessors : commonEventProcessors,\r
1389 \r
1390                                 keyboardFocusable : true\r
1391                         }, true );\r
1392 \r
1393         CKEDITOR.ui.dialog.fileButton.prototype = new CKEDITOR.ui.dialog.button;\r
1394 \r
1395         CKEDITOR.ui.dialog.fieldset.prototype = CKEDITOR.tools.clone( CKEDITOR.ui.dialog.hbox.prototype );\r
1396 \r
1397         CKEDITOR.dialog.addUIElement( 'text', textBuilder );\r
1398         CKEDITOR.dialog.addUIElement( 'password', textBuilder );\r
1399         CKEDITOR.dialog.addUIElement( 'textarea', commonBuilder );\r
1400         CKEDITOR.dialog.addUIElement( 'checkbox', commonBuilder );\r
1401         CKEDITOR.dialog.addUIElement( 'radio', commonBuilder );\r
1402         CKEDITOR.dialog.addUIElement( 'button', commonBuilder );\r
1403         CKEDITOR.dialog.addUIElement( 'select', commonBuilder );\r
1404         CKEDITOR.dialog.addUIElement( 'file', commonBuilder );\r
1405         CKEDITOR.dialog.addUIElement( 'fileButton', commonBuilder );\r
1406         CKEDITOR.dialog.addUIElement( 'html', commonBuilder );\r
1407         CKEDITOR.dialog.addUIElement( 'fieldset', containerBuilder );\r
1408 })();\r