2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
6 CKEDITOR
.plugins
.add( 'richcombo',
8 requires
: [ 'floatpanel', 'listblock', 'button' ],
10 beforeInit : function( editor
)
12 editor
.ui
.addHandler( CKEDITOR
.UI_RICHCOMBO
, CKEDITOR
.ui
.richCombo
.handler
);
21 CKEDITOR
.UI_RICHCOMBO
= 'richcombo';
23 CKEDITOR
.ui
.richCombo
= CKEDITOR
.tools
.createClass(
25 $ : function( definition
)
27 // Copy all definition properties to this object.
28 CKEDITOR
.tools
.extend( this, definition
,
31 title
: definition
.label
,
32 modes
: { wysiwyg
: 1 }
35 // We don't want the panel definition in this object.
36 var panelDefinition
= this.panel
|| {};
39 this.id
= CKEDITOR
.tools
.getNextNumber();
41 this.document
= ( panelDefinition
42 && panelDefinition
.parent
43 && panelDefinition
.parent
.getDocument() )
46 panelDefinition
.className
= ( panelDefinition
.className
|| '' ) + ' cke_rcombopanel';
47 panelDefinition
.block
=
49 multiSelect
: panelDefinition
.multiSelect
,
50 attributes
: panelDefinition
.attributes
55 panelDefinition
: panelDefinition
,
57 state
: CKEDITOR
.TRISTATE_OFF
65 create : function( definition
)
67 return new CKEDITOR
.ui
.richCombo( definition
);
74 renderHtml : function( editor
)
77 this.render( editor
, output
);
78 return output
.join( '' );
83 * @param {CKEDITOR.editor} editor The editor instance which this button is
85 * @param {Array} output The output array to which append the HTML relative
89 render : function( editor
, output
)
91 var env
= CKEDITOR
.env
;
93 var id
= 'cke_' + this.id
;
94 var clickFn
= CKEDITOR
.tools
.addFunction( function( $element
)
98 if ( _
.state
== CKEDITOR
.TRISTATE_DISABLED
)
101 this.createPanel( editor
);
110 var value
= this.getValue();
112 _
.list
.mark( value
);
116 _
.panel
.showBlock( this.id
, new CKEDITOR
.dom
.element( $element
), 4 );
125 var element
= CKEDITOR
.document
.getById( id
).getChild( 1 );
131 function updateState()
133 var state
= this.modes
[ editor
.mode
] ? CKEDITOR
.TRISTATE_OFF
: CKEDITOR
.TRISTATE_DISABLED
;
134 this.setState( editor
.readOnly
&& !this.readOnly
? CKEDITOR
.TRISTATE_DISABLED
: state
);
138 editor
.on( 'mode', updateState
, this );
139 // If this combo is sensitive to readOnly state, update it accordingly.
140 !this.readOnly
&& editor
.on( 'readOnly', updateState
, this);
142 var keyDownFn
= CKEDITOR
.tools
.addFunction( function( ev
, element
)
144 ev
= new CKEDITOR
.dom
.event( ev
);
146 var keystroke
= ev
.getKeystroke();
151 case 40 : // ARROW-DOWN
153 CKEDITOR
.tools
.callFunction( clickFn
, element
);
156 // Delegate the default behavior to toolbar button key handling.
157 instance
.onkey( instance
, keystroke
);
160 // Avoid subsequent focus grab on editor document.
164 var focusFn
= CKEDITOR
.tools
.addFunction( function() { instance
.onfocus
&& instance
.onfocus(); } );
167 instance
.keyDownFn
= keyDownFn
;
170 '<span class="cke_rcombo" role="presentation">',
173 if ( this.className
)
174 output
.push( ' class="', this.className
, ' cke_off"');
177 ' role="presentation">',
178 '<span id="' + id
+ '_label" class=cke_label>', this.label
, '</span>',
179 '<a hidefocus=true title="', this.title
, '" tabindex="-1"',
180 env
.gecko
&& env
.version
>= 10900 && !env
.hc
? '' : ' href="javascript:void(\'' + this.label
+ '\')"',
181 ' role="button" aria-labelledby="', id
, '_label" aria-describedby="', id
, '_text" aria-haspopup="true"' );
183 // Some browsers don't cancel key events in the keydown but in the
185 // TODO: Check if really needed for Gecko+Mac.
186 if ( CKEDITOR
.env
.opera
|| ( CKEDITOR
.env
.gecko
&& CKEDITOR
.env
.mac
) )
189 ' onkeypress="return false;"' );
192 // With Firefox, we need to force it to redraw, otherwise it
193 // will remain in the focus state.
194 if ( CKEDITOR
.env
.gecko
)
197 ' onblur="this.style.cssText = this.style.cssText;"' );
201 ' onkeydown="CKEDITOR.tools.callFunction( ', keyDownFn
, ', event, this );"' +
202 ' onfocus="return CKEDITOR.tools.callFunction(', focusFn
, ', event);" ' +
203 ( CKEDITOR
.env
.ie
? 'onclick="return false;" onmouseup' : 'onclick' ) + // #188
204 '="CKEDITOR.tools.callFunction(', clickFn
, ', this); return false;">' +
206 '<span id="' + id
+ '_text" class="cke_text cke_inline_label">' + this.label
+ '</span>' +
208 '<span class=cke_openbutton><span class=cke_icon>' + ( CKEDITOR
.env
.hc
? '▼' : CKEDITOR
.env
.air
? ' ' : '' ) + '</span></span>' + // BLACK DOWN-POINTING TRIANGLE
219 createPanel : function( editor
)
224 var panelDefinition
= this._
.panelDefinition
,
225 panelBlockDefinition
= this._
.panelDefinition
.block
,
226 panelParentElement
= panelDefinition
.parent
|| CKEDITOR
.document
.getBody(),
227 panel
= new CKEDITOR
.ui
.floatPanel( editor
, panelParentElement
, panelDefinition
),
228 list
= panel
.addListBlock( this.id
, panelBlockDefinition
),
231 panel
.onShow = function()
234 this.element
.getFirst().addClass( me
.className
+ '_panel' );
236 me
.setState( CKEDITOR
.TRISTATE_ON
);
238 list
.focus( !me
.multiSelect
&& me
.getValue() );
246 panel
.onHide = function( preventOnClose
)
249 this.element
.getFirst().removeClass( me
.className
+ '_panel' );
251 me
.setState( me
.modes
&& me
.modes
[ editor
.mode
] ? CKEDITOR
.TRISTATE_OFF
: CKEDITOR
.TRISTATE_DISABLED
);
255 if ( !preventOnClose
&& me
.onClose
)
259 panel
.onEscape = function()
264 list
.onClick = function( value
, marked
)
266 // Move the focus to the main windows, otherwise it will stay
267 // into the floating panel, even if invisible, and Safari and
268 // Opera will go a bit crazy.
269 me
.document
.getWindow().focus();
272 me
.onClick
.call( me
, value
, marked
);
275 me
.setValue( value
, me
._
.items
[ value
] );
282 this._
.panel
= panel
;
285 panel
.getBlock( this.id
).onHide = function()
288 me
.setState( CKEDITOR
.TRISTATE_OFF
);
295 setValue : function( value
, text
)
297 this._
.value
= value
;
299 var textElement
= this.document
.getById( 'cke_' + this.id
+ '_text' );
302 if ( !( value
|| text
) )
305 textElement
.addClass( 'cke_inline_label' );
308 textElement
.removeClass( 'cke_inline_label' );
310 textElement
.setHtml( typeof text
!= 'undefined' ? text
: value
);
314 getValue : function()
316 return this._
.value
|| '';
319 unmarkAll : function()
321 this._
.list
.unmarkAll();
324 mark : function( value
)
326 this._
.list
.mark( value
);
329 hideItem : function( value
)
331 this._
.list
.hideItem( value
);
334 hideGroup : function( groupTitle
)
336 this._
.list
.hideGroup( groupTitle
);
341 this._
.list
.showAll();
344 add : function( value
, html
, text
)
346 this._
.items
[ value
] = text
|| value
;
347 this._
.list
.add( value
, html
, text
);
350 startGroup : function( title
)
352 this._
.list
.startGroup( title
);
357 if ( !this._
.committed
)
359 this._
.list
.commit();
360 this._
.committed
= 1;
361 CKEDITOR
.ui
.fire( 'ready', this );
363 this._
.committed
= 1;
366 setState : function( state
)
368 if ( this._
.state
== state
)
371 this.document
.getById( 'cke_' + this.id
).setState( state
);
373 this._
.state
= state
;
378 CKEDITOR
.ui
.prototype.addRichCombo = function( name
, definition
)
380 this.add( name
, CKEDITOR
.UI_RICHCOMBO
, definition
);