]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blob - sources/plugins/font/plugin.js
Update to 4.7.3
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / plugins / font / plugin.js
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
6 ( function() {
7 function addCombo( editor, comboName, styleType, lang, entries, defaultLabel, styleDefinition, order ) {
8 var config = editor.config,
9 style = new CKEDITOR.style( styleDefinition );
10
11 // Gets the list of fonts from the settings.
12 var names = entries.split( ';' ),
13 values = [];
14
15 // Create style objects for all fonts.
16 var styles = {};
17 for ( var i = 0; i < names.length; i++ ) {
18 var parts = names[ i ];
19
20 if ( parts ) {
21 parts = parts.split( '/' );
22
23 var vars = {},
24 name = names[ i ] = parts[ 0 ];
25
26 vars[ styleType ] = values[ i ] = parts[ 1 ] || name;
27
28 styles[ name ] = new CKEDITOR.style( styleDefinition, vars );
29 styles[ name ]._.definition.name = name;
30 } else {
31 names.splice( i--, 1 );
32 }
33 }
34
35 editor.ui.addRichCombo( comboName, {
36 label: lang.label,
37 title: lang.panelTitle,
38 toolbar: 'styles,' + order,
39 allowedContent: style,
40 requiredContent: style,
41 contentTransformations: [
42 [
43 {
44 element: 'font',
45 check: 'span',
46 left: function( element ) {
47 return !!element.attributes.size ||
48 !!element.attributes.align ||
49 !!element.attributes.face;
50 },
51 right: function( element ) {
52 var sizes = [
53 '', // Non-existent size "0"
54 'x-small',
55 'small',
56 'medium',
57 'large',
58 'x-large',
59 'xx-large',
60 '48px' // Closest value to what size="7" might mean.
61 ];
62
63 element.name = 'span';
64
65 if ( element.attributes.size ) {
66 element.styles[ 'font-size' ] = sizes[ element.attributes.size ];
67 delete element.attributes.size;
68 }
69
70 if ( element.attributes.align ) {
71 element.styles[ 'text-align' ] = element.attributes.align;
72 delete element.attributes.align;
73 }
74
75 if ( element.attributes.face ) {
76 element.styles[ 'font-family' ] = element.attributes.face;
77 delete element.attributes.face;
78 }
79 }
80 }
81 ]
82 ],
83 panel: {
84 css: [ CKEDITOR.skin.getPath( 'editor' ) ].concat( config.contentsCss ),
85 multiSelect: false,
86 attributes: { 'aria-label': lang.panelTitle }
87 },
88
89 init: function() {
90 this.startGroup( lang.panelTitle );
91
92 for ( var i = 0; i < names.length; i++ ) {
93 var name = names[ i ];
94
95 // Add the tag entry to the panel list.
96 this.add( name, styles[ name ].buildPreview(), name );
97 }
98 },
99
100 onClick: function( value ) {
101 editor.focus();
102 editor.fire( 'saveSnapshot' );
103
104 var previousValue = this.getValue(),
105 style = styles[ value ];
106
107 // When applying one style over another, first remove the previous one (http://dev.ckeditor.com/ticket/12403).
108 // NOTE: This is only a temporary fix. It will be moved to the styles system (http://dev.ckeditor.com/ticket/12687).
109 if ( previousValue && value != previousValue ) {
110 var previousStyle = styles[ previousValue ],
111 range = editor.getSelection().getRanges()[ 0 ];
112
113 // If the range is collapsed we can't simply use the editor.removeStyle method
114 // because it will remove the entire element and we want to split it instead.
115 if ( range.collapsed ) {
116 var path = editor.elementPath(),
117 // Find the style element.
118 matching = path.contains( function( el ) {
119 return previousStyle.checkElementRemovable( el );
120 } );
121
122 if ( matching ) {
123 var startBoundary = range.checkBoundaryOfElement( matching, CKEDITOR.START ),
124 endBoundary = range.checkBoundaryOfElement( matching, CKEDITOR.END ),
125 node, bm;
126
127 // If we are at both boundaries it means that the element is empty.
128 // Remove it but in a way that we won't lose other empty inline elements inside it.
129 // Example: <p>x<span style="font-size:48px"><em>[]</em></span>x</p>
130 // Result: <p>x<em>[]</em>x</p>
131 if ( startBoundary && endBoundary ) {
132 bm = range.createBookmark();
133 // Replace the element with its children (TODO element.replaceWithChildren).
134 while ( ( node = matching.getFirst() ) ) {
135 node.insertBefore( matching );
136 }
137 matching.remove();
138 range.moveToBookmark( bm );
139
140 // If we are at the boundary of the style element, move out and copy nested styles/elements.
141 } else if ( startBoundary || endBoundary ) {
142 range.moveToPosition( matching, startBoundary ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_END );
143 cloneSubtreeIntoRange( range, path.elements.slice(), matching );
144 } else {
145 // Split the element and clone the elements that were in the path
146 // (between the startContainer and the matching element)
147 // into the new place.
148 range.splitElement( matching );
149 range.moveToPosition( matching, CKEDITOR.POSITION_AFTER_END );
150 cloneSubtreeIntoRange( range, path.elements.slice(), matching );
151 }
152
153 editor.getSelection().selectRanges( [ range ] );
154 }
155 } else {
156 editor.removeStyle( previousStyle );
157 }
158 }
159
160 editor[ previousValue == value ? 'removeStyle' : 'applyStyle' ]( style );
161
162 editor.fire( 'saveSnapshot' );
163 },
164
165 onRender: function() {
166 editor.on( 'selectionChange', function( ev ) {
167 var currentValue = this.getValue();
168
169 var elementPath = ev.data.path,
170 elements = elementPath.elements;
171
172 // For each element into the elements path.
173 for ( var i = 0, element; i < elements.length; i++ ) {
174 element = elements[ i ];
175
176 // Check if the element is removable by any of
177 // the styles.
178 for ( var value in styles ) {
179 if ( styles[ value ].checkElementMatch( element, true, editor ) ) {
180 if ( value != currentValue )
181 this.setValue( value );
182 return;
183 }
184 }
185 }
186
187 // If no styles match, just empty it.
188 this.setValue( '', defaultLabel );
189 }, this );
190 },
191
192 refresh: function() {
193 if ( !editor.activeFilter.check( style ) )
194 this.setState( CKEDITOR.TRISTATE_DISABLED );
195 }
196 } );
197 }
198
199 // Clones the subtree between subtreeStart (exclusive) and the
200 // leaf (inclusive) and inserts it into the range.
201 //
202 // @param range
203 // @param {CKEDITOR.dom.element[]} elements Elements path in the standard order: leaf -> root.
204 // @param {CKEDITOR.dom.element/null} substreeStart The start of the subtree.
205 // If null, then the leaf belongs to the subtree.
206 function cloneSubtreeIntoRange( range, elements, subtreeStart ) {
207 var current = elements.pop();
208 if ( !current ) {
209 return;
210 }
211 // Rewind the elements array up to the subtreeStart and then start the real cloning.
212 if ( subtreeStart ) {
213 return cloneSubtreeIntoRange( range, elements, current.equals( subtreeStart ) ? null : subtreeStart );
214 }
215
216 var clone = current.clone();
217 range.insertNode( clone );
218 range.moveToPosition( clone, CKEDITOR.POSITION_AFTER_START );
219
220 cloneSubtreeIntoRange( range, elements );
221 }
222
223 CKEDITOR.plugins.add( 'font', {
224 requires: 'richcombo',
225 // jscs:disable maximumLineLength
226 lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
227 // jscs:enable maximumLineLength
228 init: function( editor ) {
229 var config = editor.config;
230
231 addCombo( editor, 'Font', 'family', editor.lang.font, config.font_names, config.font_defaultLabel, config.font_style, 30 );
232 addCombo( editor, 'FontSize', 'size', editor.lang.font.fontSize, config.fontSize_sizes, config.fontSize_defaultLabel, config.fontSize_style, 40 );
233 }
234 } );
235 } )();
236
237 /**
238 * The list of fonts names to be displayed in the Font combo in the toolbar.
239 * Entries are separated by semi-colons (`';'`), while it's possible to have more
240 * than one font for each entry, in the HTML way (separated by comma).
241 *
242 * A display name may be optionally defined by prefixing the entries with the
243 * name and the slash character. For example, `'Arial/Arial, Helvetica, sans-serif'`
244 * will be displayed as `'Arial'` in the list, but will be outputted as
245 * `'Arial, Helvetica, sans-serif'`.
246 *
247 * config.font_names =
248 * 'Arial/Arial, Helvetica, sans-serif;' +
249 * 'Times New Roman/Times New Roman, Times, serif;' +
250 * 'Verdana';
251 *
252 * config.font_names = 'Arial;Times New Roman;Verdana';
253 *
254 * @cfg {String} [font_names=see source]
255 * @member CKEDITOR.config
256 */
257 CKEDITOR.config.font_names = 'Arial/Arial, Helvetica, sans-serif;' +
258 'Comic Sans MS/Comic Sans MS, cursive;' +
259 'Courier New/Courier New, Courier, monospace;' +
260 'Georgia/Georgia, serif;' +
261 'Lucida Sans Unicode/Lucida Sans Unicode, Lucida Grande, sans-serif;' +
262 'Tahoma/Tahoma, Geneva, sans-serif;' +
263 'Times New Roman/Times New Roman, Times, serif;' +
264 'Trebuchet MS/Trebuchet MS, Helvetica, sans-serif;' +
265 'Verdana/Verdana, Geneva, sans-serif';
266
267 /**
268 * The text to be displayed in the Font combo is none of the available values
269 * matches the current cursor position or text selection.
270 *
271 * // If the default site font is Arial, we may making it more explicit to the end user.
272 * config.font_defaultLabel = 'Arial';
273 *
274 * @cfg {String} [font_defaultLabel='']
275 * @member CKEDITOR.config
276 */
277 CKEDITOR.config.font_defaultLabel = '';
278
279 /**
280 * The style definition to be used to apply the font in the text.
281 *
282 * // This is actually the default value for it.
283 * config.font_style = {
284 * element: 'span',
285 * styles: { 'font-family': '#(family)' },
286 * overrides: [ { element: 'font', attributes: { 'face': null } } ]
287 * };
288 *
289 * @cfg {Object} [font_style=see example]
290 * @member CKEDITOR.config
291 */
292 CKEDITOR.config.font_style = {
293 element: 'span',
294 styles: { 'font-family': '#(family)' },
295 overrides: [ {
296 element: 'font', attributes: { 'face': null }
297 } ]
298 };
299
300 /**
301 * The list of fonts size to be displayed in the Font Size combo in the
302 * toolbar. Entries are separated by semi-colons (`';'`).
303 *
304 * Any kind of "CSS like" size can be used, like `'12px'`, `'2.3em'`, `'130%'`,
305 * `'larger'` or `'x-small'`.
306 *
307 * A display name may be optionally defined by prefixing the entries with the
308 * name and the slash character. For example, `'Bigger Font/14px'` will be
309 * displayed as `'Bigger Font'` in the list, but will be outputted as `'14px'`.
310 *
311 * config.fontSize_sizes = '16/16px;24/24px;48/48px;';
312 *
313 * config.fontSize_sizes = '12px;2.3em;130%;larger;x-small';
314 *
315 * config.fontSize_sizes = '12 Pixels/12px;Big/2.3em;30 Percent More/130%;Bigger/larger;Very Small/x-small';
316 *
317 * @cfg {String} [fontSize_sizes=see source]
318 * @member CKEDITOR.config
319 */
320 CKEDITOR.config.fontSize_sizes = '8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/18px;20/20px;22/22px;24/24px;26/26px;28/28px;36/36px;48/48px;72/72px';
321
322 /**
323 * The text to be displayed in the Font Size combo is none of the available
324 * values matches the current cursor position or text selection.
325 *
326 * // If the default site font size is 12px, we may making it more explicit to the end user.
327 * config.fontSize_defaultLabel = '12px';
328 *
329 * @cfg {String} [fontSize_defaultLabel='']
330 * @member CKEDITOR.config
331 */
332 CKEDITOR.config.fontSize_defaultLabel = '';
333
334 /**
335 * The style definition to be used to apply the font size in the text.
336 *
337 * // This is actually the default value for it.
338 * config.fontSize_style = {
339 * element: 'span',
340 * styles: { 'font-size': '#(size)' },
341 * overrides: [ { element: 'font', attributes: { 'size': null } } ]
342 * };
343 *
344 * @cfg {Object} [fontSize_style=see example]
345 * @member CKEDITOR.config
346 */
347 CKEDITOR.config.fontSize_style = {
348 element: 'span',
349 styles: { 'font-size': '#(size)' },
350 overrides: [ {
351 element: 'font', attributes: { 'size': null }
352 } ]
353 };