]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blame - sources/plugins/richcombo/plugin.js
Validation initiale
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / plugins / richcombo / plugin.js
CommitLineData
c63493c8
IB
1/**\r
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.\r
3 * For licensing, see LICENSE.md or http://ckeditor.com/license\r
4 */\r
5\r
6CKEDITOR.plugins.add( 'richcombo', {\r
7 requires: 'floatpanel,listblock,button',\r
8\r
9 beforeInit: function( editor ) {\r
10 editor.ui.addHandler( CKEDITOR.UI_RICHCOMBO, CKEDITOR.ui.richCombo.handler );\r
11 }\r
12} );\r
13\r
14( function() {\r
15 var template = '<span id="{id}"' +\r
16 ' class="cke_combo cke_combo__{name} {cls}"' +\r
17 ' role="presentation">' +\r
18 '<span id="{id}_label" class="cke_combo_label">{label}</span>' +\r
19 '<a class="cke_combo_button" title="{title}" tabindex="-1"' +\r
20 ( CKEDITOR.env.gecko && !CKEDITOR.env.hc ? '' : ' href="javascript:void(\'{titleJs}\')"' ) +\r
21 ' hidefocus="true"' +\r
22 ' role="button"' +\r
23 ' aria-labelledby="{id}_label"' +\r
24 ' aria-haspopup="true"';\r
25\r
26 // Some browsers don't cancel key events in the keydown but in the\r
27 // keypress.\r
28 // TODO: Check if really needed.\r
29 if ( CKEDITOR.env.gecko && CKEDITOR.env.mac )\r
30 template += ' onkeypress="return false;"';\r
31\r
32 // With Firefox, we need to force the button to redraw, otherwise it\r
33 // will remain in the focus state.\r
34 if ( CKEDITOR.env.gecko )\r
35 template += ' onblur="this.style.cssText = this.style.cssText;"';\r
36\r
37 template +=\r
38 ' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event,this);"' +\r
39 ' onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" ' +\r
40 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // #188\r
41 '="CKEDITOR.tools.callFunction({clickFn},this);return false;">' +\r
42 '<span id="{id}_text" class="cke_combo_text cke_combo_inlinelabel">{label}</span>' +\r
43 '<span class="cke_combo_open">' +\r
44 '<span class="cke_combo_arrow">' +\r
45 // BLACK DOWN-POINTING TRIANGLE\r
46 ( CKEDITOR.env.hc ? '&#9660;' : CKEDITOR.env.air ? '&nbsp;' : '' ) +\r
47 '</span>' +\r
48 '</span>' +\r
49 '</a>' +\r
50 '</span>';\r
51\r
52 var rcomboTpl = CKEDITOR.addTemplate( 'combo', template );\r
53\r
54 /**\r
55 * Button UI element.\r
56 *\r
57 * @readonly\r
58 * @property {String} [='richcombo']\r
59 * @member CKEDITOR\r
60 */\r
61 CKEDITOR.UI_RICHCOMBO = 'richcombo';\r
62\r
63 /**\r
64 * @class\r
65 * @todo\r
66 */\r
67 CKEDITOR.ui.richCombo = CKEDITOR.tools.createClass( {\r
68 $: function( definition ) {\r
69 // Copy all definition properties to this object.\r
70 CKEDITOR.tools.extend( this, definition,\r
71 // Set defaults.\r
72 {\r
73 // The combo won't participate in toolbar grouping.\r
74 canGroup: false,\r
75 title: definition.label,\r
76 modes: { wysiwyg: 1 },\r
77 editorFocus: 1\r
78 } );\r
79\r
80 // We don't want the panel definition in this object.\r
81 var panelDefinition = this.panel || {};\r
82 delete this.panel;\r
83\r
84 this.id = CKEDITOR.tools.getNextNumber();\r
85\r
86 this.document = ( panelDefinition.parent && panelDefinition.parent.getDocument() ) || CKEDITOR.document;\r
87\r
88 panelDefinition.className = 'cke_combopanel';\r
89 panelDefinition.block = {\r
90 multiSelect: panelDefinition.multiSelect,\r
91 attributes: panelDefinition.attributes\r
92 };\r
93 panelDefinition.toolbarRelated = true;\r
94\r
95 this._ = {\r
96 panelDefinition: panelDefinition,\r
97 items: {}\r
98 };\r
99 },\r
100\r
101 proto: {\r
102 renderHtml: function( editor ) {\r
103 var output = [];\r
104 this.render( editor, output );\r
105 return output.join( '' );\r
106 },\r
107\r
108 /**\r
109 * Renders the combo.\r
110 *\r
111 * @param {CKEDITOR.editor} editor The editor instance which this button is\r
112 * to be used by.\r
113 * @param {Array} output The output array to which append the HTML relative\r
114 * to this button.\r
115 */\r
116 render: function( editor, output ) {\r
117 var env = CKEDITOR.env;\r
118\r
119 var id = 'cke_' + this.id;\r
120 var clickFn = CKEDITOR.tools.addFunction( function( el ) {\r
121 // Restore locked selection in Opera.\r
122 if ( selLocked ) {\r
123 editor.unlockSelection( 1 );\r
124 selLocked = 0;\r
125 }\r
126 instance.execute( el );\r
127 }, this );\r
128\r
129 var combo = this;\r
130 var instance = {\r
131 id: id,\r
132 combo: this,\r
133 focus: function() {\r
134 var element = CKEDITOR.document.getById( id ).getChild( 1 );\r
135 element.focus();\r
136 },\r
137 execute: function( el ) {\r
138 var _ = combo._;\r
139\r
140 if ( _.state == CKEDITOR.TRISTATE_DISABLED )\r
141 return;\r
142\r
143 combo.createPanel( editor );\r
144\r
145 if ( _.on ) {\r
146 _.panel.hide();\r
147 return;\r
148 }\r
149\r
150 combo.commit();\r
151 var value = combo.getValue();\r
152 if ( value )\r
153 _.list.mark( value );\r
154 else\r
155 _.list.unmarkAll();\r
156\r
157 _.panel.showBlock( combo.id, new CKEDITOR.dom.element( el ), 4 );\r
158 },\r
159 clickFn: clickFn\r
160 };\r
161\r
162 function updateState() {\r
163 // Don't change state while richcombo is active (#11793).\r
164 if ( this.getState() == CKEDITOR.TRISTATE_ON )\r
165 return;\r
166\r
167 var state = this.modes[ editor.mode ] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;\r
168\r
169 if ( editor.readOnly && !this.readOnly )\r
170 state = CKEDITOR.TRISTATE_DISABLED;\r
171\r
172 this.setState( state );\r
173 this.setValue( '' );\r
174\r
175 // Let plugin to disable button.\r
176 if ( state != CKEDITOR.TRISTATE_DISABLED && this.refresh )\r
177 this.refresh();\r
178 }\r
179\r
180 // Update status when activeFilter, mode, selection or readOnly changes.\r
181 editor.on( 'activeFilterChange', updateState, this );\r
182 editor.on( 'mode', updateState, this );\r
183 editor.on( 'selectionChange', updateState, this );\r
184 // If this combo is sensitive to readOnly state, update it accordingly.\r
185 !this.readOnly && editor.on( 'readOnly', updateState, this );\r
186\r
187 var keyDownFn = CKEDITOR.tools.addFunction( function( ev, element ) {\r
188 ev = new CKEDITOR.dom.event( ev );\r
189\r
190 var keystroke = ev.getKeystroke();\r
191\r
192 // ARROW-DOWN\r
193 // This call is duplicated in plugins/toolbar/plugin.js in itemKeystroke().\r
194 // Move focus to the first element after drop down was opened by the arrow down key.\r
195 if ( keystroke == 40 ) {\r
196 editor.once( 'panelShow', function( evt ) {\r
197 evt.data._.panel._.currentBlock.onKeyDown( 40 );\r
198 } );\r
199 }\r
200\r
201 switch ( keystroke ) {\r
202 case 13: // ENTER\r
203 case 32: // SPACE\r
204 case 40: // ARROW-DOWN\r
205 // Show panel\r
206 CKEDITOR.tools.callFunction( clickFn, element );\r
207 break;\r
208 default:\r
209 // Delegate the default behavior to toolbar button key handling.\r
210 instance.onkey( instance, keystroke );\r
211 }\r
212\r
213 // Avoid subsequent focus grab on editor document.\r
214 ev.preventDefault();\r
215 } );\r
216\r
217 var focusFn = CKEDITOR.tools.addFunction( function() {\r
218 instance.onfocus && instance.onfocus();\r
219 } );\r
220\r
221 var selLocked = 0;\r
222\r
223 // For clean up\r
224 instance.keyDownFn = keyDownFn;\r
225\r
226 var params = {\r
227 id: id,\r
228 name: this.name || this.command,\r
229 label: this.label,\r
230 title: this.title,\r
231 cls: this.className || '',\r
232 titleJs: env.gecko && !env.hc ? '' : ( this.title || '' ).replace( "'", '' ),\r
233 keydownFn: keyDownFn,\r
234 focusFn: focusFn,\r
235 clickFn: clickFn\r
236 };\r
237\r
238 rcomboTpl.output( params, output );\r
239\r
240 if ( this.onRender )\r
241 this.onRender();\r
242\r
243 return instance;\r
244 },\r
245\r
246 createPanel: function( editor ) {\r
247 if ( this._.panel )\r
248 return;\r
249\r
250 var panelDefinition = this._.panelDefinition,\r
251 panelBlockDefinition = this._.panelDefinition.block,\r
252 panelParentElement = panelDefinition.parent || CKEDITOR.document.getBody(),\r
253 namedPanelCls = 'cke_combopanel__' + this.name,\r
254 panel = new CKEDITOR.ui.floatPanel( editor, panelParentElement, panelDefinition ),\r
255 list = panel.addListBlock( this.id, panelBlockDefinition ),\r
256 me = this;\r
257\r
258 panel.onShow = function() {\r
259 this.element.addClass( namedPanelCls );\r
260\r
261 me.setState( CKEDITOR.TRISTATE_ON );\r
262\r
263 me._.on = 1;\r
264\r
265 me.editorFocus && !editor.focusManager.hasFocus && editor.focus();\r
266\r
267 if ( me.onOpen )\r
268 me.onOpen();\r
269\r
270 // The "panelShow" event is fired assinchronously, after the\r
271 // onShow method call.\r
272 editor.once( 'panelShow', function() {\r
273 list.focus( !list.multiSelect && me.getValue() );\r
274 } );\r
275 };\r
276\r
277 panel.onHide = function( preventOnClose ) {\r
278 this.element.removeClass( namedPanelCls );\r
279\r
280 me.setState( me.modes && me.modes[ editor.mode ] ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED );\r
281\r
282 me._.on = 0;\r
283\r
284 if ( !preventOnClose && me.onClose )\r
285 me.onClose();\r
286 };\r
287\r
288 panel.onEscape = function() {\r
289 // Hide drop-down with focus returned.\r
290 panel.hide( 1 );\r
291 };\r
292\r
293 list.onClick = function( value, marked ) {\r
294\r
295 if ( me.onClick )\r
296 me.onClick.call( me, value, marked );\r
297\r
298 panel.hide();\r
299 };\r
300\r
301 this._.panel = panel;\r
302 this._.list = list;\r
303\r
304 panel.getBlock( this.id ).onHide = function() {\r
305 me._.on = 0;\r
306 me.setState( CKEDITOR.TRISTATE_OFF );\r
307 };\r
308\r
309 if ( this.init )\r
310 this.init();\r
311 },\r
312\r
313 setValue: function( value, text ) {\r
314 this._.value = value;\r
315\r
316 var textElement = this.document.getById( 'cke_' + this.id + '_text' );\r
317 if ( textElement ) {\r
318 if ( !( value || text ) ) {\r
319 text = this.label;\r
320 textElement.addClass( 'cke_combo_inlinelabel' );\r
321 } else {\r
322 textElement.removeClass( 'cke_combo_inlinelabel' );\r
323 }\r
324\r
325 textElement.setText( typeof text != 'undefined' ? text : value );\r
326 }\r
327 },\r
328\r
329 getValue: function() {\r
330 return this._.value || '';\r
331 },\r
332\r
333 unmarkAll: function() {\r
334 this._.list.unmarkAll();\r
335 },\r
336\r
337 mark: function( value ) {\r
338 this._.list.mark( value );\r
339 },\r
340\r
341 hideItem: function( value ) {\r
342 this._.list.hideItem( value );\r
343 },\r
344\r
345 hideGroup: function( groupTitle ) {\r
346 this._.list.hideGroup( groupTitle );\r
347 },\r
348\r
349 showAll: function() {\r
350 this._.list.showAll();\r
351 },\r
352\r
353 add: function( value, html, text ) {\r
354 this._.items[ value ] = text || value;\r
355 this._.list.add( value, html, text );\r
356 },\r
357\r
358 startGroup: function( title ) {\r
359 this._.list.startGroup( title );\r
360 },\r
361\r
362 commit: function() {\r
363 if ( !this._.committed ) {\r
364 this._.list.commit();\r
365 this._.committed = 1;\r
366 CKEDITOR.ui.fire( 'ready', this );\r
367 }\r
368 this._.committed = 1;\r
369 },\r
370\r
371 setState: function( state ) {\r
372 if ( this._.state == state )\r
373 return;\r
374\r
375 var el = this.document.getById( 'cke_' + this.id );\r
376 el.setState( state, 'cke_combo' );\r
377\r
378 state == CKEDITOR.TRISTATE_DISABLED ?\r
379 el.setAttribute( 'aria-disabled', true ) :\r
380 el.removeAttribute( 'aria-disabled' );\r
381\r
382 this._.state = state;\r
383 },\r
384\r
385 getState: function() {\r
386 return this._.state;\r
387 },\r
388\r
389 enable: function() {\r
390 if ( this._.state == CKEDITOR.TRISTATE_DISABLED )\r
391 this.setState( this._.lastState );\r
392 },\r
393\r
394 disable: function() {\r
395 if ( this._.state != CKEDITOR.TRISTATE_DISABLED ) {\r
396 this._.lastState = this._.state;\r
397 this.setState( CKEDITOR.TRISTATE_DISABLED );\r
398 }\r
399 }\r
400 },\r
401\r
402 /**\r
403 * Represents richCombo handler object.\r
404 *\r
405 * @class CKEDITOR.ui.richCombo.handler\r
406 * @singleton\r
407 * @extends CKEDITOR.ui.handlerDefinition\r
408 */\r
409 statics: {\r
410 handler: {\r
411 /**\r
412 * Transforms a richCombo definition in a {@link CKEDITOR.ui.richCombo} instance.\r
413 *\r
414 * @param {Object} definition\r
415 * @returns {CKEDITOR.ui.richCombo}\r
416 */\r
417 create: function( definition ) {\r
418 return new CKEDITOR.ui.richCombo( definition );\r
419 }\r
420 }\r
421 }\r
422 } );\r
423\r
424 /**\r
425 * @param {String} name\r
426 * @param {Object} definition\r
427 * @member CKEDITOR.ui\r
428 * @todo\r
429 */\r
430 CKEDITOR.ui.prototype.addRichCombo = function( name, definition ) {\r
431 this.add( name, CKEDITOR.UI_RICHCOMBO, definition );\r
432 };\r
433\r
434} )();\r