]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blob - sources/plugins/floatingspace/plugin.js
Update to 4.7.3
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / plugins / floatingspace / 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 var win = CKEDITOR.document.getWindow(),
8 pixelate = CKEDITOR.tools.cssLength;
9
10 CKEDITOR.plugins.add( 'floatingspace', {
11 init: function( editor ) {
12 // Add listener with lower priority than that in themedui creator.
13 // Thereby floatingspace will be created only if themedui wasn't used.
14 editor.on( 'loaded', function() {
15 attach( this );
16 }, null, null, 20 );
17 }
18 } );
19
20 function scrollOffset( side ) {
21 var pageOffset = side == 'left' ? 'pageXOffset' : 'pageYOffset',
22 docScrollOffset = side == 'left' ? 'scrollLeft' : 'scrollTop';
23
24 return ( pageOffset in win.$ ) ? win.$[ pageOffset ] : CKEDITOR.document.$.documentElement[ docScrollOffset ];
25 }
26
27 function attach( editor ) {
28 var config = editor.config,
29
30 // Get the HTML for the predefined spaces.
31 topHtml = editor.fire( 'uiSpace', { space: 'top', html: '' } ).html,
32
33 // Re-positioning of the space.
34 layout = ( function() {
35 // Mode indicates the vertical aligning mode.
36 var mode, editable,
37 spaceRect, editorRect, viewRect, spaceHeight, pageScrollX,
38
39 // Allow minor adjustments of the float space from custom configs.
40 dockedOffsetX = config.floatSpaceDockedOffsetX || 0,
41 dockedOffsetY = config.floatSpaceDockedOffsetY || 0,
42 pinnedOffsetX = config.floatSpacePinnedOffsetX || 0,
43 pinnedOffsetY = config.floatSpacePinnedOffsetY || 0;
44
45 // Update the float space position.
46 function updatePos( pos, prop, val ) {
47 floatSpace.setStyle( prop, pixelate( val ) );
48 floatSpace.setStyle( 'position', pos );
49 }
50
51 // Change the current mode and update float space position accordingly.
52 function changeMode( newMode ) {
53 var editorPos = editable.getDocumentPosition();
54
55 switch ( newMode ) {
56 case 'top':
57 updatePos( 'absolute', 'top', editorPos.y - spaceHeight - dockedOffsetY );
58 break;
59 case 'pin':
60 updatePos( 'fixed', 'top', pinnedOffsetY );
61 break;
62 case 'bottom':
63 updatePos( 'absolute', 'top', editorPos.y + ( editorRect.height || editorRect.bottom - editorRect.top ) + dockedOffsetY );
64 break;
65 }
66
67 mode = newMode;
68 }
69
70 return function( evt ) {
71 // http://dev.ckeditor.com/ticket/10112 Do not fail on editable-less editor.
72 if ( !( editable = editor.editable() ) )
73 return;
74
75 var show = ( evt && evt.name == 'focus' );
76
77 // Show up the space on focus gain.
78 if ( show ) {
79 floatSpace.show();
80 }
81
82 editor.fire( 'floatingSpaceLayout', { show: show } );
83
84 // Reset the horizontal position for below measurement.
85 floatSpace.removeStyle( 'left' );
86 floatSpace.removeStyle( 'right' );
87
88 // Compute the screen position from the TextRectangle object would
89 // be very simple, even though the "width"/"height" property is not
90 // available for all, it's safe to figure that out from the rest.
91
92 // http://help.dottoro.com/ljgupwlp.php
93 spaceRect = floatSpace.getClientRect();
94 editorRect = editable.getClientRect();
95 viewRect = win.getViewPaneSize();
96 spaceHeight = spaceRect.height;
97 pageScrollX = scrollOffset( 'left' );
98
99 // We initialize it as pin mode.
100 if ( !mode ) {
101 mode = 'pin';
102 changeMode( 'pin' );
103 // Call for a refresh to the actual layout.
104 layout( evt );
105 return;
106 }
107
108 // +------------------------ Viewport -+ \
109 // | | |-> floatSpaceDockedOffsetY
110 // | ................................. | /
111 // | |
112 // | +------ Space -+ |
113 // | | | |
114 // | +--------------+ |
115 // | +------------------ Editor -+ |
116 // | | | |
117 //
118 if ( spaceHeight + dockedOffsetY <= editorRect.top )
119 changeMode( 'top' );
120
121 // +- - - - - - - - - Editor -+
122 // | |
123 // +------------------------ Viewport -+ \
124 // | | | | |-> floatSpacePinnedOffsetY
125 // | ................................. | /
126 // | +------ Space -+ | |
127 // | | | | |
128 // | +--------------+ | |
129 // | | | |
130 // | +---------------------------+ |
131 // +-----------------------------------+
132 //
133 else if ( spaceHeight + dockedOffsetY > viewRect.height - editorRect.bottom )
134 changeMode( 'pin' );
135
136 // +- - - - - - - - - Editor -+
137 // | |
138 // +------------------------ Viewport -+ \
139 // | | | | |-> floatSpacePinnedOffsetY
140 // | ................................. | /
141 // | | | |
142 // | | | |
143 // | +---------------------------+ |
144 // | +------ Space -+ |
145 // | | | |
146 // | +--------------+ |
147 //
148 else
149 changeMode( 'bottom' );
150
151 var mid = viewRect.width / 2,
152 alignSide, offset;
153
154 if ( config.floatSpacePreferRight ) {
155 alignSide = 'right';
156 } else if ( editorRect.left > 0 && editorRect.right < viewRect.width && editorRect.width > spaceRect.width ) {
157 alignSide = config.contentsLangDirection == 'rtl' ? 'right' : 'left';
158 } else {
159 alignSide = mid - editorRect.left > editorRect.right - mid ? 'left' : 'right';
160 }
161
162 // (http://dev.ckeditor.com/ticket/9769) If viewport width is less than space width,
163 // make sure space never cross the left boundary of the viewport.
164 // In other words: top-left corner of the space is always visible.
165 if ( spaceRect.width > viewRect.width ) {
166 alignSide = 'left';
167 offset = 0;
168 }
169 else {
170 if ( alignSide == 'left' ) {
171 // If the space rect fits into viewport, align it
172 // to the left edge of editor:
173 //
174 // +------------------------ Viewport -+
175 // | |
176 // | +------------- Space -+ |
177 // | | | |
178 // | +---------------------+ |
179 // | +------------------ Editor -+ |
180 // | | | |
181 //
182 if ( editorRect.left > 0 )
183 offset = editorRect.left;
184
185 // If the left part of the editor is cut off by the left
186 // edge of the viewport, stick the space to the viewport:
187 //
188 // +------------------------ Viewport -+
189 // | |
190 // +---------------- Space -+ |
191 // | | |
192 // +------------------------+ |
193 // +----|------------- Editor -+ |
194 // | | | |
195 //
196 else
197 offset = 0;
198 }
199 else {
200 // If the space rect fits into viewport, align it
201 // to the right edge of editor:
202 //
203 // +------------------------ Viewport -+
204 // | |
205 // | +------------- Space -+ |
206 // | | | |
207 // | +---------------------+ |
208 // | +------------------ Editor -+ |
209 // | | | |
210 //
211 if ( editorRect.right < viewRect.width )
212 offset = viewRect.width - editorRect.right;
213
214 // If the right part of the editor is cut off by the right
215 // edge of the viewport, stick the space to the viewport:
216 //
217 // +------------------------ Viewport -+
218 // | |
219 // | +------------- Space -+
220 // | | |
221 // | +---------------------+
222 // | +-----------------|- Editor -+
223 // | | | |
224 //
225 else
226 offset = 0;
227 }
228
229 // (http://dev.ckeditor.com/ticket/9769) Finally, stick the space to the opposite side of
230 // the viewport when it's cut off horizontally on the left/right
231 // side like below.
232 //
233 // This trick reveals cut off space in some edge cases and
234 // hence it improves accessibility.
235 //
236 // +------------------------ Viewport -+
237 // | |
238 // | +--------------------|-- Space -+
239 // | | | |
240 // | +--------------------|----------+
241 // | +------- Editor -+ |
242 // | | | |
243 //
244 // becomes:
245 //
246 // +------------------------ Viewport -+
247 // | |
248 // | +----------------------- Space -+
249 // | | |
250 // | +-------------------------------+
251 // | +------- Editor -+ |
252 // | | | |
253 //
254 if ( offset + spaceRect.width > viewRect.width ) {
255 alignSide = alignSide == 'left' ? 'right' : 'left';
256 offset = 0;
257 }
258 }
259
260 // Pin mode is fixed, so don't include scroll-x.
261 // (http://dev.ckeditor.com/ticket/9903) For mode is "top" or "bottom", add opposite scroll-x for right-aligned space.
262 var scroll = mode == 'pin' ? 0 : alignSide == 'left' ? pageScrollX : -pageScrollX;
263
264 floatSpace.setStyle( alignSide, pixelate( ( mode == 'pin' ? pinnedOffsetX : dockedOffsetX ) + offset + scroll ) );
265 };
266 } )();
267
268 if ( topHtml ) {
269 var floatSpaceTpl = new CKEDITOR.template(
270 '<div' +
271 ' id="cke_{name}"' +
272 ' class="cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_float cke_{langDir} ' + CKEDITOR.env.cssClass + '"' +
273 ' dir="{langDir}"' +
274 ' title="' + ( CKEDITOR.env.gecko ? ' ' : '' ) + '"' +
275 ' lang="{langCode}"' +
276 ' role="application"' +
277 ' style="{style}"' +
278 ( editor.title ? ' aria-labelledby="cke_{name}_arialbl"' : ' ' ) +
279 '>' +
280 ( editor.title ? '<span id="cke_{name}_arialbl" class="cke_voice_label">{voiceLabel}</span>' : ' ' ) +
281 '<div class="cke_inner">' +
282 '<div id="{topId}" class="cke_top" role="presentation">{content}</div>' +
283 '</div>' +
284 '</div>' ),
285 floatSpace = CKEDITOR.document.getBody().append( CKEDITOR.dom.element.createFromHtml( floatSpaceTpl.output( {
286 content: topHtml,
287 id: editor.id,
288 langDir: editor.lang.dir,
289 langCode: editor.langCode,
290 name: editor.name,
291 style: 'display:none;z-index:' + ( config.baseFloatZIndex - 1 ),
292 topId: editor.ui.spaceId( 'top' ),
293 voiceLabel: editor.title
294 } ) ) ),
295
296 // Use event buffers to reduce CPU load when tons of events are fired.
297 changeBuffer = CKEDITOR.tools.eventsBuffer( 500, layout ),
298 uiBuffer = CKEDITOR.tools.eventsBuffer( 100, layout );
299
300 // There's no need for the floatSpace to be selectable.
301 floatSpace.unselectable();
302
303 // Prevent clicking on non-buttons area of the space from blurring editor.
304 floatSpace.on( 'mousedown', function( evt ) {
305 evt = evt.data;
306 if ( !evt.getTarget().hasAscendant( 'a', 1 ) )
307 evt.preventDefault();
308 } );
309
310 editor.on( 'focus', function( evt ) {
311 layout( evt );
312 editor.on( 'change', changeBuffer.input );
313 win.on( 'scroll', uiBuffer.input );
314 win.on( 'resize', uiBuffer.input );
315 } );
316
317 editor.on( 'blur', function() {
318 floatSpace.hide();
319 editor.removeListener( 'change', changeBuffer.input );
320 win.removeListener( 'scroll', uiBuffer.input );
321 win.removeListener( 'resize', uiBuffer.input );
322 } );
323
324 editor.on( 'destroy', function() {
325 win.removeListener( 'scroll', uiBuffer.input );
326 win.removeListener( 'resize', uiBuffer.input );
327 floatSpace.clearCustomData();
328 floatSpace.remove();
329 } );
330
331 // Handle initial focus.
332 if ( editor.focusManager.hasFocus )
333 floatSpace.show();
334
335 // Register this UI space to the focus manager.
336 editor.focusManager.add( floatSpace, 1 );
337 }
338 }
339 } )();
340
341 /**
342 * Along with {@link #floatSpaceDockedOffsetY} it defines the
343 * amount of offset (in pixels) between the float space and the editable left/right
344 * boundaries when the space element is docked on either side of the editable.
345 *
346 * config.floatSpaceDockedOffsetX = 10;
347 *
348 * @cfg {Number} [floatSpaceDockedOffsetX=0]
349 * @member CKEDITOR.config
350 */
351
352 /**
353 * Along with {@link #floatSpaceDockedOffsetX} it defines the
354 * amount of offset (in pixels) between the float space and the editable top/bottom
355 * boundaries when the space element is docked on either side of the editable.
356 *
357 * config.floatSpaceDockedOffsetY = 10;
358 *
359 * @cfg {Number} [floatSpaceDockedOffsetY=0]
360 * @member CKEDITOR.config
361 */
362
363 /**
364 * Along with {@link #floatSpacePinnedOffsetY} it defines the
365 * amount of offset (in pixels) between the float space and the viewport boundaries
366 * when the space element is pinned.
367 *
368 * config.floatSpacePinnedOffsetX = 20;
369 *
370 * @cfg {Number} [floatSpacePinnedOffsetX=0]
371 * @member CKEDITOR.config
372 */
373
374 /**
375 * Along with {@link #floatSpacePinnedOffsetX} it defines the
376 * amount of offset (in pixels) between the float space and the viewport boundaries
377 * when the space element is pinned.
378 *
379 * config.floatSpacePinnedOffsetY = 20;
380 *
381 * @cfg {Number} [floatSpacePinnedOffsetY=0]
382 * @member CKEDITOR.config
383 */
384
385 /**
386 * Indicates that the float space should be aligned to the right side
387 * of the editable area rather than to the left (if possible).
388 *
389 * config.floatSpacePreferRight = true;
390 *
391 * @since 4.5
392 * @cfg {Boolean} [floatSpacePreferRight=false]
393 * @member CKEDITOR.config
394 */
395
396 /**
397 * Fired when the viewport or editor parameters change and the floating space needs to check and
398 * eventually update its position and dimensions.
399 *
400 * @since 4.5
401 * @event floatingSpaceLayout
402 * @member CKEDITOR.editor
403 * @param {CKEDITOR.editor} editor The editor instance.
404 * @param data
405 * @param {Boolean} data.show True if the float space should show up as a result of this event.
406 */