]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blame - sources/plugins/button/plugin.js
Update to 4.7.3
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / plugins / button / 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
6( function() {\r
7 var template = '<a id="{id}"' +\r
8 ' class="cke_button cke_button__{name} cke_button_{state} {cls}"' +\r
9 ( CKEDITOR.env.gecko && !CKEDITOR.env.hc ? '' : ' href="javascript:void(\'{titleJs}\')"' ) +\r
10 ' title="{title}"' +\r
11 ' tabindex="-1"' +\r
12 ' hidefocus="true"' +\r
13 ' role="button"' +\r
14 ' aria-labelledby="{id}_label"' +\r
15 ' aria-describedby="{id}_description"' +\r
16 ' aria-haspopup="{hasArrow}"' +\r
17 ' aria-disabled="{ariaDisabled}"';\r
18\r
19 // Some browsers don't cancel key events in the keydown but in the\r
20 // keypress.\r
21 // TODO: Check if really needed.\r
22 if ( CKEDITOR.env.gecko && CKEDITOR.env.mac )\r
23 template += ' onkeypress="return false;"';\r
24\r
25 // With Firefox, we need to force the button to redraw, otherwise it\r
26 // will remain in the focus state.\r
27 if ( CKEDITOR.env.gecko )\r
28 template += ' onblur="this.style.cssText = this.style.cssText;"';\r
29\r
30 template += ' onkeydown="return CKEDITOR.tools.callFunction({keydownFn},event);"' +\r
31 ' onfocus="return CKEDITOR.tools.callFunction({focusFn},event);" ' +\r
1794320d 32 ( CKEDITOR.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // http://dev.ckeditor.com/ticket/188\r
c63493c8
IB
33 '="CKEDITOR.tools.callFunction({clickFn},this);return false;">' +\r
34 '<span class="cke_button_icon cke_button__{iconName}_icon" style="{style}"';\r
35\r
36\r
37 template += '>&nbsp;</span>' +\r
38 '<span id="{id}_label" class="cke_button_label cke_button__{name}_label" aria-hidden="false">{label}</span>' +\r
39 '<span id="{id}_description" class="cke_button_label" aria-hidden="false">{ariaShortcut}</span>' +\r
40 '{arrowHtml}' +\r
41 '</a>';\r
42\r
43 var templateArrow = '<span class="cke_button_arrow">' +\r
44 // BLACK DOWN-POINTING TRIANGLE\r
45 ( CKEDITOR.env.hc ? '&#9660;' : '' ) +\r
46 '</span>';\r
47\r
48 var btnArrowTpl = CKEDITOR.addTemplate( 'buttonArrow', templateArrow ),\r
49 btnTpl = CKEDITOR.addTemplate( 'button', template );\r
50\r
51 CKEDITOR.plugins.add( 'button', {\r
1794320d 52 lang: 'af,ar,az,bg,ca,cs,da,de,de-ch,el,en,en-gb,eo,es,es-mx,eu,fa,fi,fr,gl,he,hr,hu,id,it,ja,km,ko,ku,lt,nb,nl,no,oc,pl,pt,pt-br,ro,ru,sk,sl,sq,sv,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%\r
c63493c8
IB
53 beforeInit: function( editor ) {\r
54 editor.ui.addHandler( CKEDITOR.UI_BUTTON, CKEDITOR.ui.button.handler );\r
55 }\r
56 } );\r
57\r
58 /**\r
59 * Button UI element.\r
60 *\r
61 * @readonly\r
62 * @property {String} [='button']\r
63 * @member CKEDITOR\r
64 */\r
65 CKEDITOR.UI_BUTTON = 'button';\r
66\r
67 /**\r
68 * Represents a button UI element. This class should not be called directly. To\r
69 * create new buttons use {@link CKEDITOR.ui#addButton} instead.\r
70 *\r
71 * @class\r
72 * @constructor Creates a button class instance.\r
73 * @param {Object} definition The button definition.\r
74 */\r
75 CKEDITOR.ui.button = function( definition ) {\r
76 CKEDITOR.tools.extend( this, definition,\r
77 // Set defaults.\r
78 {\r
79 title: definition.label,\r
80 click: definition.click ||\r
81 function( editor ) {\r
82 editor.execCommand( definition.command );\r
83 }\r
84 } );\r
85\r
86 this._ = {};\r
87 };\r
88\r
89 /**\r
90 * Represents the button handler object.\r
91 *\r
92 * @class\r
93 * @singleton\r
94 * @extends CKEDITOR.ui.handlerDefinition\r
95 */\r
96 CKEDITOR.ui.button.handler = {\r
97 /**\r
98 * Transforms a button definition in a {@link CKEDITOR.ui.button} instance.\r
99 *\r
100 * @member CKEDITOR.ui.button.handler\r
101 * @param {Object} definition\r
102 * @returns {CKEDITOR.ui.button}\r
103 */\r
104 create: function( definition ) {\r
105 return new CKEDITOR.ui.button( definition );\r
106 }\r
107 };\r
108\r
109 /** @class CKEDITOR.ui.button */\r
110 CKEDITOR.ui.button.prototype = {\r
111 /**\r
112 * Renders the button.\r
113 *\r
114 * @param {CKEDITOR.editor} editor The editor instance which this button is\r
115 * to be used by.\r
116 * @param {Array} output The output array to which the HTML code related to\r
117 * this button should be appended.\r
118 */\r
119 render: function( editor, output ) {\r
120 function updateState() {\r
121 // "this" is a CKEDITOR.ui.button instance.\r
122 var mode = editor.mode;\r
123\r
124 if ( mode ) {\r
125 // Restore saved button state.\r
126 var state = this.modes[ mode ] ? modeStates[ mode ] !== undefined ? modeStates[ mode ] : CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;\r
127\r
128 state = editor.readOnly && !this.readOnly ? CKEDITOR.TRISTATE_DISABLED : state;\r
129\r
130 this.setState( state );\r
131\r
132 // Let plugin to disable button.\r
133 if ( this.refresh )\r
134 this.refresh();\r
135 }\r
136 }\r
137\r
138 var env = CKEDITOR.env,\r
139 id = this._.id = CKEDITOR.tools.getNextId(),\r
140 stateName = '',\r
141 command = this.command,\r
142 // Get the command name.\r
143 clickFn,\r
144 keystroke,\r
145 shortcut;\r
146\r
147 this._.editor = editor;\r
148\r
149 var instance = {\r
150 id: id,\r
151 button: this,\r
152 editor: editor,\r
153 focus: function() {\r
154 var element = CKEDITOR.document.getById( id );\r
155 element.focus();\r
156 },\r
157 execute: function() {\r
158 this.button.click( editor );\r
159 },\r
160 attach: function( editor ) {\r
161 this.button.attach( editor );\r
162 }\r
163 };\r
164\r
165 var keydownFn = CKEDITOR.tools.addFunction( function( ev ) {\r
166 if ( instance.onkey ) {\r
167 ev = new CKEDITOR.dom.event( ev );\r
168 return ( instance.onkey( instance, ev.getKeystroke() ) !== false );\r
169 }\r
170 } );\r
171\r
172 var focusFn = CKEDITOR.tools.addFunction( function( ev ) {\r
173 var retVal;\r
174\r
175 if ( instance.onfocus )\r
176 retVal = ( instance.onfocus( instance, new CKEDITOR.dom.event( ev ) ) !== false );\r
177\r
178 return retVal;\r
179 } );\r
180\r
181 var selLocked = 0;\r
182\r
183 instance.clickFn = clickFn = CKEDITOR.tools.addFunction( function() {\r
184\r
185 // Restore locked selection in Opera.\r
186 if ( selLocked ) {\r
187 editor.unlockSelection( 1 );\r
188 selLocked = 0;\r
189 }\r
190 instance.execute();\r
191\r
1794320d 192 // Fixed iOS focus issue when your press disabled button (http://dev.ckeditor.com/ticket/12381).\r
c63493c8
IB
193 if ( env.iOS ) {\r
194 editor.focus();\r
195 }\r
196 } );\r
197\r
198\r
199 // Indicate a mode sensitive button.\r
200 if ( this.modes ) {\r
201 var modeStates = {};\r
202\r
203 editor.on( 'beforeModeUnload', function() {\r
204 if ( editor.mode && this._.state != CKEDITOR.TRISTATE_DISABLED )\r
205 modeStates[ editor.mode ] = this._.state;\r
206 }, this );\r
207\r
208 // Update status when activeFilter, mode or readOnly changes.\r
209 editor.on( 'activeFilterChange', updateState, this );\r
210 editor.on( 'mode', updateState, this );\r
211 // If this button is sensitive to readOnly state, update it accordingly.\r
212 !this.readOnly && editor.on( 'readOnly', updateState, this );\r
213\r
214 } else if ( command ) {\r
215 // Get the command instance.\r
216 command = editor.getCommand( command );\r
217\r
218 if ( command ) {\r
219 command.on( 'state', function() {\r
220 this.setState( command.state );\r
221 }, this );\r
222\r
223 stateName += ( command.state == CKEDITOR.TRISTATE_ON ? 'on' : command.state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' : 'off' );\r
224 }\r
225 }\r
226\r
227 // For button that has text-direction awareness on selection path.\r
228 if ( this.directional ) {\r
229 editor.on( 'contentDirChanged', function( evt ) {\r
230 var el = CKEDITOR.document.getById( this._.id ),\r
231 icon = el.getFirst();\r
232\r
233 var pathDir = evt.data;\r
234\r
235 // Make a minor direction change to become style-able for the skin icon.\r
236 if ( pathDir != editor.lang.dir )\r
237 el.addClass( 'cke_' + pathDir );\r
238 else\r
239 el.removeClass( 'cke_ltr' ).removeClass( 'cke_rtl' );\r
240\r
241 // Inline style update for the plugin icon.\r
242 icon.setAttribute( 'style', CKEDITOR.skin.getIconStyle( iconName, pathDir == 'rtl', this.icon, this.iconOffset ) );\r
243 }, this );\r
244 }\r
245\r
246 if ( !command ) {\r
247 stateName += 'off';\r
248 } else {\r
249 keystroke = editor.getCommandKeystroke( command );\r
250\r
251 if ( keystroke ) {\r
252 shortcut = CKEDITOR.tools.keystrokeToString( editor.lang.common.keyboard, keystroke );\r
253 }\r
254 }\r
255\r
256 var name = this.name || this.command,\r
257 iconName = name;\r
258\r
1794320d 259 // Check if we're pointing to an icon defined by another command. (http://dev.ckeditor.com/ticket/9555)\r
c63493c8
IB
260 if ( this.icon && !( /\./ ).test( this.icon ) ) {\r
261 iconName = this.icon;\r
262 this.icon = null;\r
263 }\r
264\r
265 var params = {\r
266 id: id,\r
267 name: name,\r
268 iconName: iconName,\r
269 label: this.label,\r
270 cls: this.className || '',\r
271 state: stateName,\r
272 ariaDisabled: stateName == 'disabled' ? 'true' : 'false',\r
273 title: this.title + ( shortcut ? ' (' + shortcut.display + ')' : '' ),\r
274 ariaShortcut: shortcut ? editor.lang.common.keyboardShortcut + ' ' + shortcut.aria : '',\r
275 titleJs: env.gecko && !env.hc ? '' : ( this.title || '' ).replace( "'", '' ),\r
276 hasArrow: this.hasArrow ? 'true' : 'false',\r
277 keydownFn: keydownFn,\r
278 focusFn: focusFn,\r
279 clickFn: clickFn,\r
280 style: CKEDITOR.skin.getIconStyle( iconName, ( editor.lang.dir == 'rtl' ), this.icon, this.iconOffset ),\r
281 arrowHtml: this.hasArrow ? btnArrowTpl.output() : ''\r
282 };\r
283\r
284 btnTpl.output( params, output );\r
285\r
286 if ( this.onRender )\r
287 this.onRender();\r
288\r
289 return instance;\r
290 },\r
291\r
292 /**\r
293 * Sets the button state.\r
294 *\r
295 * @param {Number} state Indicates the button state. One of {@link CKEDITOR#TRISTATE_ON},\r
296 * {@link CKEDITOR#TRISTATE_OFF}, or {@link CKEDITOR#TRISTATE_DISABLED}.\r
297 */\r
298 setState: function( state ) {\r
299 if ( this._.state == state )\r
300 return false;\r
301\r
302 this._.state = state;\r
303\r
304 var element = CKEDITOR.document.getById( this._.id );\r
305\r
306 if ( element ) {\r
307 element.setState( state, 'cke_button' );\r
308\r
309 state == CKEDITOR.TRISTATE_DISABLED ?\r
310 element.setAttribute( 'aria-disabled', true ) :\r
311 element.removeAttribute( 'aria-disabled' );\r
312\r
313 if ( !this.hasArrow ) {\r
1794320d 314 // Note: aria-pressed attribute should not be added to menuButton instances. (http://dev.ckeditor.com/ticket/11331)\r
c63493c8
IB
315 state == CKEDITOR.TRISTATE_ON ?\r
316 element.setAttribute( 'aria-pressed', true ) :\r
317 element.removeAttribute( 'aria-pressed' );\r
318 } else {\r
319 var newLabel = state == CKEDITOR.TRISTATE_ON ?\r
320 this._.editor.lang.button.selectedLabel.replace( /%1/g, this.label ) : this.label;\r
321 CKEDITOR.document.getById( this._.id + '_label' ).setText( newLabel );\r
322 }\r
323\r
324 return true;\r
325 } else {\r
326 return false;\r
327 }\r
328 },\r
329\r
330 /**\r
331 * Gets the button state.\r
332 *\r
333 * @returns {Number} The button state. One of {@link CKEDITOR#TRISTATE_ON},\r
334 * {@link CKEDITOR#TRISTATE_OFF}, or {@link CKEDITOR#TRISTATE_DISABLED}.\r
335 */\r
336 getState: function() {\r
337 return this._.state;\r
338 },\r
339\r
340 /**\r
341 * Returns this button's {@link CKEDITOR.feature} instance.\r
342 *\r
343 * It may be this button instance if it has at least one of\r
344 * `allowedContent` and `requiredContent` properties. Otherwise,\r
345 * if a command is bound to this button by the `command` property, then\r
346 * that command will be returned.\r
347 *\r
348 * This method implements the {@link CKEDITOR.feature#toFeature} interface method.\r
349 *\r
350 * @since 4.1\r
351 * @param {CKEDITOR.editor} Editor instance.\r
352 * @returns {CKEDITOR.feature} The feature.\r
353 */\r
354 toFeature: function( editor ) {\r
355 if ( this._.feature )\r
356 return this._.feature;\r
357\r
358 var feature = this;\r
359\r
360 // If button isn't a feature, return command if is bound.\r
361 if ( !this.allowedContent && !this.requiredContent && this.command )\r
362 feature = editor.getCommand( this.command ) || feature;\r
363\r
364 return this._.feature = feature;\r
365 }\r
366 };\r
367\r
368 /**\r
369 * Adds a button definition to the UI elements list.\r
370 *\r
371 * editorInstance.ui.addButton( 'MyBold', {\r
372 * label: 'My Bold',\r
373 * command: 'bold',\r
374 * toolbar: 'basicstyles,1'\r
375 * } );\r
376 *\r
377 * @member CKEDITOR.ui\r
378 * @param {String} name The button name.\r
379 * @param {Object} definition The button definition.\r
380 * @param {String} definition.label The textual part of the button (if visible) and its tooltip.\r
381 * @param {String} definition.command The command to be executed once the button is activated.\r
382 * @param {String} definition.toolbar The {@link CKEDITOR.config#toolbarGroups toolbar group} into which\r
383 * the button will be added. An optional index value (separated by a comma) determines the button position within the group.\r
384 */\r
385 CKEDITOR.ui.prototype.addButton = function( name, definition ) {\r
386 this.add( name, CKEDITOR.UI_BUTTON, definition );\r
387 };\r
388\r
389} )();\r