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