]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blob - sources/core/focusmanager.js
Validation initiale
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / core / focusmanager.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 /**
7 * @fileOverview Defines the {@link CKEDITOR.focusManager} class, which is used
8 * to handle the focus in editor instances.
9 */
10
11 ( function() {
12 /**
13 * Manages the focus activity in an editor instance. This class is to be
14 * used mainly by UI element coders when adding interface elements that need
15 * to set the focus state of the editor.
16 *
17 * var focusManager = new CKEDITOR.focusManager( editor );
18 * focusManager.focus();
19 *
20 * @class
21 * @constructor Creates a focusManager class instance.
22 * @param {CKEDITOR.editor} editor The editor instance.
23 */
24 CKEDITOR.focusManager = function( editor ) {
25 if ( editor.focusManager )
26 return editor.focusManager;
27
28 /**
29 * Indicates that the editor instance has focus.
30 *
31 * alert( CKEDITOR.instances.editor1.focusManager.hasFocus ); // e.g. true
32 */
33 this.hasFocus = false;
34
35 /**
36 * Indicates the currently focused DOM element that makes the editor activated.
37 *
38 * @property {CKEDITOR.dom.domObject}
39 */
40 this.currentActive = null;
41
42 /**
43 * Object used to store private stuff.
44 *
45 * @private
46 */
47 this._ = {
48 editor: editor
49 };
50
51 return this;
52 };
53
54 var SLOT_NAME = 'focusmanager',
55 SLOT_NAME_LISTENERS = 'focusmanager_handlers';
56
57 /**
58 * Object used to store private stuff.
59 *
60 * @private
61 * @class
62 * @singleton
63 */
64 CKEDITOR.focusManager._ = {
65 /**
66 * The delay (in milliseconds) to deactivate the editor when a UI DOM element has lost focus.
67 *
68 * @private
69 * @property {Number} [blurDelay=200]
70 * @member CKEDITOR.focusManager._
71 */
72 blurDelay: 200
73 };
74
75 CKEDITOR.focusManager.prototype = {
76
77 /**
78 * Indicates that this editor instance is activated (due to a DOM focus change).
79 * The `activated` state is a symbolic indicator of an active user
80 * interaction session.
81 *
82 * **Note:** This method will not introduce UI focus
83 * impact on DOM, it is here to record the editor UI focus state internally.
84 * If you want to make the cursor blink inside the editable, use
85 * {@link CKEDITOR.editor#method-focus} instead.
86 *
87 * var editor = CKEDITOR.instances.editor1;
88 * editor.focusManage.focus( editor.editable() );
89 *
90 * @param {CKEDITOR.dom.element} [currentActive] The new value of the {@link #currentActive} property.
91 * @member CKEDITOR.focusManager
92 */
93 focus: function( currentActive ) {
94 if ( this._.timer )
95 clearTimeout( this._.timer );
96
97 if ( currentActive )
98 this.currentActive = currentActive;
99
100 if ( !( this.hasFocus || this._.locked ) ) {
101 // If another editor has the current focus, we first "blur" it. In
102 // this way the events happen in a more logical sequence, like:
103 // "focus 1" > "blur 1" > "focus 2"
104 // ... instead of:
105 // "focus 1" > "focus 2" > "blur 1"
106 var current = CKEDITOR.currentInstance;
107 current && current.focusManager.blur( 1 );
108
109 this.hasFocus = true;
110
111 var ct = this._.editor.container;
112 ct && ct.addClass( 'cke_focus' );
113 this._.editor.fire( 'focus' );
114 }
115 },
116
117 /**
118 * Prevents from changing the focus manager state until the next {@link #unlock} is called.
119 *
120 * @member CKEDITOR.focusManager
121 */
122 lock: function() {
123 this._.locked = 1;
124 },
125
126 /**
127 * Restores the automatic focus management if {@link #lock} is called.
128 *
129 * @member CKEDITOR.focusManager
130 */
131 unlock: function() {
132 delete this._.locked;
133 },
134
135 /**
136 * Used to indicate that the editor instance has been deactivated by the specified
137 * element which has just lost focus.
138 *
139 * **Note:** This function acts asynchronously with a delay of 100ms to
140 * avoid temporary deactivation. Use the `noDelay` parameter instead
141 * to deactivate immediately.
142 *
143 * var editor = CKEDITOR.instances.editor1;
144 * editor.focusManager.blur();
145 *
146 * @param {Boolean} [noDelay=false] Immediately deactivate the editor instance synchronously.
147 * @member CKEDITOR.focusManager
148 */
149 blur: function( noDelay ) {
150 if ( this._.locked )
151 return;
152
153 function doBlur() {
154 var editor = this._.editor;
155
156 if ( this.hasFocus ) {
157 this.hasFocus = false;
158
159 // Blink browsers leave selection in `[contenteditable=true]`
160 // when it's blurred and it's neccessary to remove it manually for inline editor. (#13446)
161 if ( CKEDITOR.env.chrome && editor.editable().isInline() ) {
162 editor.window.$.getSelection().removeAllRanges();
163 }
164
165 var ct = this._.editor.container;
166 ct && ct.removeClass( 'cke_focus' );
167 this._.editor.fire( 'blur' );
168 }
169 }
170
171 if ( this._.timer )
172 clearTimeout( this._.timer );
173
174 var delay = CKEDITOR.focusManager._.blurDelay;
175 if ( noDelay || !delay )
176 doBlur.call( this );
177 else {
178 this._.timer = CKEDITOR.tools.setTimeout( function() {
179 delete this._.timer;
180 doBlur.call( this );
181 }, delay, this );
182 }
183 },
184
185 /**
186 * Registers a UI DOM element to the focus manager, which will make the focus manager "hasFocus"
187 * once the input focus is relieved on the element.
188 * This method is designed to be used by plugins to expand the jurisdiction of the editor focus.
189 *
190 * @param {CKEDITOR.dom.element} element The container (topmost) element of one UI part.
191 * @param {Boolean} isCapture If specified, {@link CKEDITOR.event#useCapture} will be used when listening to the focus event.
192 * @member CKEDITOR.focusManager
193 */
194 add: function( element, isCapture ) {
195 var fm = element.getCustomData( SLOT_NAME );
196 if ( !fm || fm != this ) {
197 // If this element is already taken by another instance, dismiss it first.
198 fm && fm.remove( element );
199
200 var focusEvent = 'focus',
201 blurEvent = 'blur';
202
203 // Bypass the element's internal DOM focus change.
204 if ( isCapture ) {
205
206 // Use "focusin/focusout" events instead of capture phase in IEs,
207 // which fires synchronously.
208 if ( CKEDITOR.env.ie ) {
209 focusEvent = 'focusin';
210 blurEvent = 'focusout';
211 } else {
212 CKEDITOR.event.useCapture = 1;
213 }
214 }
215
216 var listeners = {
217 blur: function() {
218 if ( element.equals( this.currentActive ) )
219 this.blur();
220 },
221 focus: function() {
222 this.focus( element );
223 }
224 };
225
226 element.on( focusEvent, listeners.focus, this );
227 element.on( blurEvent, listeners.blur, this );
228
229 if ( isCapture )
230 CKEDITOR.event.useCapture = 0;
231
232 element.setCustomData( SLOT_NAME, this );
233 element.setCustomData( SLOT_NAME_LISTENERS, listeners );
234 }
235 },
236
237 /**
238 * Dismisses an element from the focus manager delegations added by {@link #add}.
239 *
240 * @param {CKEDITOR.dom.element} element The element to be removed from the focus manager.
241 * @member CKEDITOR.focusManager
242 */
243 remove: function( element ) {
244 element.removeCustomData( SLOT_NAME );
245 var listeners = element.removeCustomData( SLOT_NAME_LISTENERS );
246 element.removeListener( 'blur', listeners.blur );
247 element.removeListener( 'focus', listeners.focus );
248 }
249
250 };
251
252 } )();
253
254 /**
255 * Fired when the editor instance receives the input focus.
256 *
257 * editor.on( 'focus', function( e ) {
258 * alert( 'The editor named ' + e.editor.name + ' is now focused' );
259 * } );
260 *
261 * @event focus
262 * @member CKEDITOR.editor
263 * @param {CKEDITOR.editor} editor The editor instance.
264 */
265
266 /**
267 * Fired when the editor instance loses the input focus.
268 *
269 * **Note:** This event will **NOT** be triggered when focus is moved internally, e.g. from
270 * an editable to another part of the editor UI like a dialog window.
271 * If you are interested only in the focus state of the editable, listen to the `focus`
272 * and `blur` events of the {@link CKEDITOR.editable} instead.
273 *
274 * editor.on( 'blur', function( e ) {
275 * alert( 'The editor named ' + e.editor.name + ' lost the focus' );
276 * } );
277 *
278 * @event blur
279 * @member CKEDITOR.editor
280 * @param {CKEDITOR.editor} editor The editor instance.
281 */