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