diff options
Diffstat (limited to 'sources/plugins/font/plugin.js')
-rw-r--r-- | sources/plugins/font/plugin.js | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/sources/plugins/font/plugin.js b/sources/plugins/font/plugin.js new file mode 100644 index 00000000..9db04108 --- /dev/null +++ b/sources/plugins/font/plugin.js | |||
@@ -0,0 +1,313 @@ | |||
1 | /** | ||
2 | * @license Copyright (c) 2003-2015, 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 | |||
42 | panel: { | ||
43 | css: [ CKEDITOR.skin.getPath( 'editor' ) ].concat( config.contentsCss ), | ||
44 | multiSelect: false, | ||
45 | attributes: { 'aria-label': lang.panelTitle } | ||
46 | }, | ||
47 | |||
48 | init: function() { | ||
49 | this.startGroup( lang.panelTitle ); | ||
50 | |||
51 | for ( var i = 0; i < names.length; i++ ) { | ||
52 | var name = names[ i ]; | ||
53 | |||
54 | // Add the tag entry to the panel list. | ||
55 | this.add( name, styles[ name ].buildPreview(), name ); | ||
56 | } | ||
57 | }, | ||
58 | |||
59 | onClick: function( value ) { | ||
60 | editor.focus(); | ||
61 | editor.fire( 'saveSnapshot' ); | ||
62 | |||
63 | var previousValue = this.getValue(), | ||
64 | style = styles[ value ]; | ||
65 | |||
66 | // When applying one style over another, first remove the previous one (#12403). | ||
67 | // NOTE: This is only a temporary fix. It will be moved to the styles system (#12687). | ||
68 | if ( previousValue && value != previousValue ) { | ||
69 | var previousStyle = styles[ previousValue ], | ||
70 | range = editor.getSelection().getRanges()[ 0 ]; | ||
71 | |||
72 | // If the range is collapsed we can't simply use the editor.removeStyle method | ||
73 | // because it will remove the entire element and we want to split it instead. | ||
74 | if ( range.collapsed ) { | ||
75 | var path = editor.elementPath(), | ||
76 | // Find the style element. | ||
77 | matching = path.contains( function( el ) { | ||
78 | return previousStyle.checkElementRemovable( el ); | ||
79 | } ); | ||
80 | |||
81 | if ( matching ) { | ||
82 | var startBoundary = range.checkBoundaryOfElement( matching, CKEDITOR.START ), | ||
83 | endBoundary = range.checkBoundaryOfElement( matching, CKEDITOR.END ), | ||
84 | node, bm; | ||
85 | |||
86 | // If we are at both boundaries it means that the element is empty. | ||
87 | // Remove it but in a way that we won't lose other empty inline elements inside it. | ||
88 | // Example: <p>x<span style="font-size:48px"><em>[]</em></span>x</p> | ||
89 | // Result: <p>x<em>[]</em>x</p> | ||
90 | if ( startBoundary && endBoundary ) { | ||
91 | bm = range.createBookmark(); | ||
92 | // Replace the element with its children (TODO element.replaceWithChildren). | ||
93 | while ( ( node = matching.getFirst() ) ) { | ||
94 | node.insertBefore( matching ); | ||
95 | } | ||
96 | matching.remove(); | ||
97 | range.moveToBookmark( bm ); | ||
98 | |||
99 | // If we are at the boundary of the style element, just move out. | ||
100 | } else if ( startBoundary ) { | ||
101 | range.moveToPosition( matching, CKEDITOR.POSITION_BEFORE_START ); | ||
102 | } else if ( endBoundary ) { | ||
103 | range.moveToPosition( matching, CKEDITOR.POSITION_AFTER_END ); | ||
104 | } else { | ||
105 | // Split the element and clone the elements that were in the path | ||
106 | // (between the startContainer and the matching element) | ||
107 | // into the new place. | ||
108 | range.splitElement( matching ); | ||
109 | range.moveToPosition( matching, CKEDITOR.POSITION_AFTER_END ); | ||
110 | cloneSubtreeIntoRange( range, path.elements.slice(), matching ); | ||
111 | } | ||
112 | |||
113 | editor.getSelection().selectRanges( [ range ] ); | ||
114 | } | ||
115 | } else { | ||
116 | editor.removeStyle( previousStyle ); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | editor[ previousValue == value ? 'removeStyle' : 'applyStyle' ]( style ); | ||
121 | |||
122 | editor.fire( 'saveSnapshot' ); | ||
123 | }, | ||
124 | |||
125 | onRender: function() { | ||
126 | editor.on( 'selectionChange', function( ev ) { | ||
127 | var currentValue = this.getValue(); | ||
128 | |||
129 | var elementPath = ev.data.path, | ||
130 | elements = elementPath.elements; | ||
131 | |||
132 | // For each element into the elements path. | ||
133 | for ( var i = 0, element; i < elements.length; i++ ) { | ||
134 | element = elements[ i ]; | ||
135 | |||
136 | // Check if the element is removable by any of | ||
137 | // the styles. | ||
138 | for ( var value in styles ) { | ||
139 | if ( styles[ value ].checkElementMatch( element, true, editor ) ) { | ||
140 | if ( value != currentValue ) | ||
141 | this.setValue( value ); | ||
142 | return; | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | |||
147 | // If no styles match, just empty it. | ||
148 | this.setValue( '', defaultLabel ); | ||
149 | }, this ); | ||
150 | }, | ||
151 | |||
152 | refresh: function() { | ||
153 | if ( !editor.activeFilter.check( style ) ) | ||
154 | this.setState( CKEDITOR.TRISTATE_DISABLED ); | ||
155 | } | ||
156 | } ); | ||
157 | } | ||
158 | |||
159 | // Clones the subtree between subtreeStart (exclusive) and the | ||
160 | // leaf (inclusive) and inserts it into the range. | ||
161 | // | ||
162 | // @param range | ||
163 | // @param {CKEDITOR.dom.element[]} elements Elements path in the standard order: leaf -> root. | ||
164 | // @param {CKEDITOR.dom.element/null} substreeStart The start of the subtree. | ||
165 | // If null, then the leaf belongs to the subtree. | ||
166 | function cloneSubtreeIntoRange( range, elements, subtreeStart ) { | ||
167 | var current = elements.pop(); | ||
168 | if ( !current ) { | ||
169 | return; | ||
170 | } | ||
171 | // Rewind the elements array up to the subtreeStart and then start the real cloning. | ||
172 | if ( subtreeStart ) { | ||
173 | return cloneSubtreeIntoRange( range, elements, current.equals( subtreeStart ) ? null : subtreeStart ); | ||
174 | } | ||
175 | |||
176 | var clone = current.clone(); | ||
177 | range.insertNode( clone ); | ||
178 | range.moveToPosition( clone, CKEDITOR.POSITION_AFTER_START ); | ||
179 | |||
180 | cloneSubtreeIntoRange( range, elements ); | ||
181 | } | ||
182 | |||
183 | CKEDITOR.plugins.add( 'font', { | ||
184 | requires: 'richcombo', | ||
185 | // jscs:disable maximumLineLength | ||
186 | lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,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,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% | ||
187 | // jscs:enable maximumLineLength | ||
188 | init: function( editor ) { | ||
189 | var config = editor.config; | ||
190 | |||
191 | addCombo( editor, 'Font', 'family', editor.lang.font, config.font_names, config.font_defaultLabel, config.font_style, 30 ); | ||
192 | addCombo( editor, 'FontSize', 'size', editor.lang.font.fontSize, config.fontSize_sizes, config.fontSize_defaultLabel, config.fontSize_style, 40 ); | ||
193 | } | ||
194 | } ); | ||
195 | } )(); | ||
196 | |||
197 | /** | ||
198 | * The list of fonts names to be displayed in the Font combo in the toolbar. | ||
199 | * Entries are separated by semi-colons (`';'`), while it's possible to have more | ||
200 | * than one font for each entry, in the HTML way (separated by comma). | ||
201 | * | ||
202 | * A display name may be optionally defined by prefixing the entries with the | ||
203 | * name and the slash character. For example, `'Arial/Arial, Helvetica, sans-serif'` | ||
204 | * will be displayed as `'Arial'` in the list, but will be outputted as | ||
205 | * `'Arial, Helvetica, sans-serif'`. | ||
206 | * | ||
207 | * config.font_names = | ||
208 | * 'Arial/Arial, Helvetica, sans-serif;' + | ||
209 | * 'Times New Roman/Times New Roman, Times, serif;' + | ||
210 | * 'Verdana'; | ||
211 | * | ||
212 | * config.font_names = 'Arial;Times New Roman;Verdana'; | ||
213 | * | ||
214 | * @cfg {String} [font_names=see source] | ||
215 | * @member CKEDITOR.config | ||
216 | */ | ||
217 | CKEDITOR.config.font_names = 'Arial/Arial, Helvetica, sans-serif;' + | ||
218 | 'Comic Sans MS/Comic Sans MS, cursive;' + | ||
219 | 'Courier New/Courier New, Courier, monospace;' + | ||
220 | 'Georgia/Georgia, serif;' + | ||
221 | 'Lucida Sans Unicode/Lucida Sans Unicode, Lucida Grande, sans-serif;' + | ||
222 | 'Tahoma/Tahoma, Geneva, sans-serif;' + | ||
223 | 'Times New Roman/Times New Roman, Times, serif;' + | ||
224 | 'Trebuchet MS/Trebuchet MS, Helvetica, sans-serif;' + | ||
225 | 'Verdana/Verdana, Geneva, sans-serif'; | ||
226 | |||
227 | /** | ||
228 | * The text to be displayed in the Font combo is none of the available values | ||
229 | * matches the current cursor position or text selection. | ||
230 | * | ||
231 | * // If the default site font is Arial, we may making it more explicit to the end user. | ||
232 | * config.font_defaultLabel = 'Arial'; | ||
233 | * | ||
234 | * @cfg {String} [font_defaultLabel=''] | ||
235 | * @member CKEDITOR.config | ||
236 | */ | ||
237 | CKEDITOR.config.font_defaultLabel = ''; | ||
238 | |||
239 | /** | ||
240 | * The style definition to be used to apply the font in the text. | ||
241 | * | ||
242 | * // This is actually the default value for it. | ||
243 | * config.font_style = { | ||
244 | * element: 'span', | ||
245 | * styles: { 'font-family': '#(family)' }, | ||
246 | * overrides: [ { element: 'font', attributes: { 'face': null } } ] | ||
247 | * }; | ||
248 | * | ||
249 | * @cfg {Object} [font_style=see example] | ||
250 | * @member CKEDITOR.config | ||
251 | */ | ||
252 | CKEDITOR.config.font_style = { | ||
253 | element: 'span', | ||
254 | styles: { 'font-family': '#(family)' }, | ||
255 | overrides: [ { | ||
256 | element: 'font', attributes: { 'face': null } | ||
257 | } ] | ||
258 | }; | ||
259 | |||
260 | /** | ||
261 | * The list of fonts size to be displayed in the Font Size combo in the | ||
262 | * toolbar. Entries are separated by semi-colons (`';'`). | ||
263 | * | ||
264 | * Any kind of "CSS like" size can be used, like `'12px'`, `'2.3em'`, `'130%'`, | ||
265 | * `'larger'` or `'x-small'`. | ||
266 | * | ||
267 | * A display name may be optionally defined by prefixing the entries with the | ||
268 | * name and the slash character. For example, `'Bigger Font/14px'` will be | ||
269 | * displayed as `'Bigger Font'` in the list, but will be outputted as `'14px'`. | ||
270 | * | ||
271 | * config.fontSize_sizes = '16/16px;24/24px;48/48px;'; | ||
272 | * | ||
273 | * config.fontSize_sizes = '12px;2.3em;130%;larger;x-small'; | ||
274 | * | ||
275 | * config.fontSize_sizes = '12 Pixels/12px;Big/2.3em;30 Percent More/130%;Bigger/larger;Very Small/x-small'; | ||
276 | * | ||
277 | * @cfg {String} [fontSize_sizes=see source] | ||
278 | * @member CKEDITOR.config | ||
279 | */ | ||
280 | 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'; | ||
281 | |||
282 | /** | ||
283 | * The text to be displayed in the Font Size combo is none of the available | ||
284 | * values matches the current cursor position or text selection. | ||
285 | * | ||
286 | * // If the default site font size is 12px, we may making it more explicit to the end user. | ||
287 | * config.fontSize_defaultLabel = '12px'; | ||
288 | * | ||
289 | * @cfg {String} [fontSize_defaultLabel=''] | ||
290 | * @member CKEDITOR.config | ||
291 | */ | ||
292 | CKEDITOR.config.fontSize_defaultLabel = ''; | ||
293 | |||
294 | /** | ||
295 | * The style definition to be used to apply the font size in the text. | ||
296 | * | ||
297 | * // This is actually the default value for it. | ||
298 | * config.fontSize_style = { | ||
299 | * element: 'span', | ||
300 | * styles: { 'font-size': '#(size)' }, | ||
301 | * overrides: [ { element :'font', attributes: { 'size': null } } ] | ||
302 | * }; | ||
303 | * | ||
304 | * @cfg {Object} [fontSize_style=see example] | ||
305 | * @member CKEDITOR.config | ||
306 | */ | ||
307 | CKEDITOR.config.fontSize_style = { | ||
308 | element: 'span', | ||
309 | styles: { 'font-size': '#(size)' }, | ||
310 | overrides: [ { | ||
311 | element: 'font', attributes: { 'size': null } | ||
312 | } ] | ||
313 | }; | ||