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