2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
7 * @fileOverview The "Notification" plugin.
13 CKEDITOR
.plugins
.add( 'notification', {
14 lang: 'az,ca,cs,da,de,de-ch,en,eo,es,es-mx,eu,fr,gl,hr,hu,id,it,ja,km,ko,ku,nb,nl,oc,pl,pt,pt-br,ru,sk,sv,tr,ug,uk,zh,zh-cn', // %REMOVE_LINE_CORE%
16 init: function( editor
) {
17 editor
._
.notificationArea
= new Area( editor
);
19 // Overwrites default `editor.showNotification`.
20 editor
.showNotification = function( message
, type
, progressOrDuration
) {
21 var progress
, duration
;
23 if ( type
== 'progress' ) {
24 progress
= progressOrDuration
;
26 duration
= progressOrDuration
;
29 var notification
= new CKEDITOR
.plugins
.notification( editor
, {
41 // Close the last notification on ESC.
42 editor
.on( 'key', function( evt
) {
43 if ( evt
.data
.keyCode
== 27 ) { /* ESC */
44 var notifications
= editor
._
.notificationArea
.notifications
;
46 if ( !notifications
.length
) {
50 // As long as this is not a common practice to inform screen-reader users about actions, in this case
51 // this is the best solution (unfortunately there is no standard for accessibility for notifications).
52 // Notification has an `alert` aria role what means that it does not get a focus nor is needed to be
53 // closed (unlike `alertdialog`). However notification will capture ESC key so we need to inform user
54 // why it does not do other actions.
55 say( editor
.lang
.notification
.closed
);
58 notifications
[ notifications
.length
- 1 ].hide();
64 // Send the message to the screen readers.
65 function say( text
) {
66 var message
= new CKEDITOR
.dom
.element( 'div' );
69 'margin-left': '-9999px'
71 message
.setAttributes( {
72 'aria-live': 'assertive',
75 message
.setText( text
);
77 CKEDITOR
.document
.getBody().append( message
);
79 setTimeout( function() {
87 * Notification class. Notifications are used to display short messages to the user. They might be used to show the result of
88 * asynchronous actions or information about changes in the editor content. It is recommended to use them instead of
89 * alert dialogs. They should **not** be used if a user response is required nor with dialog windows (e.g. in dialog validation).
91 * There are four types of notifications available, see the {@link #type} property.
93 * Note that the notification constructor only creates a notification instance. To show it, use the {@link #show} method:
95 * var notification = new CKEDITOR.plugins.notification( editor, { message: 'Foo' } );
96 * notification.show();
98 * You can also use the {@link CKEDITOR.editor#showNotification} method:
100 * editor.showNotification( 'Foo' );
102 * All of the notification actions: ({@link #show}, {@link #update} and {@link #hide}) fire cancelable events
103 * on the related {@link CKEDITOR.editor} instance so you can integrate editor notifications with your website notifications.
105 * Refer to the [Notifications](http://docs.ckeditor.com/#!/guide/dev_notifications) article for more information about this feature.
108 * @class CKEDITOR.plugins.notification
109 * @constructor Create a notification object. Call {@link #show} to show the created notification.
110 * @param {CKEDITOR.editor} editor The editor instance.
111 * @param {Object} options
112 * @param {String} options.message The message displayed in the notification.
113 * @param {String} [options.type='info'] Notification type, see {@link #type}.
114 * @param {Number} [options.progress=0] If the type is `progress` this may be a progress from 0 to 1.
115 * @param {Number} [options.duration] How long the notification will be visible, see {@link #duration}.
117 function Notification( editor
, options
) {
118 CKEDITOR
.tools
.extend( this, options
, {
120 id: 'cke-' + CKEDITOR
.tools
.getUniqueId(),
121 area: editor
._
.notificationArea
124 if ( !options
.type
) {
128 this.element
= this._createElement();
130 // Don't allow dragging on notification (http://dev.ckeditor.com/ticket/13184).
131 editor
.plugins
.clipboard
&& CKEDITOR
.plugins
.clipboard
.preventDefaultDropOnElement( this.element
);
135 * The editor instance.
138 * @property {CKEDITOR.editor} editor
142 * Message displayed in the notification.
145 * @property {String} message
149 * Notification type. There are four types available:
151 * * `info` (default) – Information for the user (e.g. "File is uploading.", "ACF modified content."),
152 * * `warning` – Warning or error message (e.g. "This type of file is not supported.",
153 * "You cannot paste the script."),
154 * * `success` – Information that an operation finished successfully (e.g. "File uploaded.", "Data imported.").
155 * * `progress` – Information about the progress of an operation. When the operation is done, the notification
156 * type should be changed to `success`.
159 * @property {String} type
163 * If the notification {@link #type} is `'progress'`, this is the progress from `0` to `1`.
166 * @property {Number} progress
170 * Notification duration. Determines after how many milliseconds the notification should close automatically.
171 * `0` means that the notification will not close automatically and that the user needs to close it manually.
172 * The default value for `warning` and `progress` notifications is `0`. For `info` and `success` the value can
173 * either be set through the {@link CKEDITOR.config#notification_duration} configuration option or equals `5000`
174 * if the configuration option is not set.
177 * @property {Number} duration
181 * Unique notification ID.
184 * @property {Number} id
188 * Notification DOM element. There is one element per notification. It is created when the notification is created,
189 * even if it is not shown. If the notification is hidden, the element is detached from the document but not deleted.
190 * It will be reused if the notification is shown again.
193 * @property {CKEDITOR.dom.element} element
197 * {@link CKEDITOR.plugins.notification.area Notification area} reference.
200 * @property {CKEDITOR.plugins.notification.area} area
203 Notification
.prototype = {
205 * Adds the notification element to the notification area. The notification will be hidden automatically if
206 * {@link #duration} is set.
208 * Fires the {@link CKEDITOR.editor#notificationShow} event.
211 if ( this.editor
.fire( 'notificationShow', { notification: this } ) === false ) {
215 this.area
.add( this );
217 this._hideAfterTimeout();
221 * Updates the notification object and element.
223 * Fires the {@link CKEDITOR.editor#notificationUpdate} event.
225 * @param {Object} options
226 * @param {String} [options.message] {@link #message}
227 * @param {String} [options.type] {@link #type}
228 * @param {Number} [options.progress] {@link #progress}
229 * @param {Number} [options.duration] {@link #duration}
230 * @param {Boolean} [options.important=false] If the update is important, the notification will be shown
231 * if it was hidden and read by screen readers.
233 update: function( options
) {
236 if ( this.editor
.fire( 'notificationUpdate', { notification: this, options: options
} ) === false ) {
237 // The idea of cancelable event is to let user create his own way of displaying notification, so if
238 // `notificationUpdate` event will be canceled there will be no interaction with notification area, but on
239 // the other hand the logic should work anyway so object will be updated (including `element` property).
240 // Note: we can safely update the element's attributes below, because this element is created inside
241 // the constructor. If the notificatinShow event was canceled as well, the element is detached from DOM.
245 var element
= this.element
,
246 messageElement
= element
.findOne( '.cke_notification_message' ),
247 progressElement
= element
.findOne( '.cke_notification_progress' ),
250 element
.removeAttribute( 'role' );
252 // Change type to progress if `options.progress` is set.
253 if ( options
.progress
&& this.type
!= 'progress' ) {
258 element
.removeClass( this._getClass() );
259 element
.removeAttribute( 'aria-label' );
263 element
.addClass( this._getClass() );
264 element
.setAttribute( 'aria-label', this.type
);
266 if ( this.type
== 'progress' && !progressElement
) {
267 progressElement
= this._createProgressElement();
268 progressElement
.insertBefore( messageElement
);
269 } else if ( this.type
!= 'progress' && progressElement
) {
270 progressElement
.remove();
274 if ( options
.message
!== undefined ) {
275 this.message
= options
.message
;
276 messageElement
.setHtml( this.message
);
279 if ( options
.progress
!== undefined ) {
280 this.progress
= options
.progress
;
282 if ( progressElement
) {
283 progressElement
.setStyle( 'width', this._getPercentageProgress() );
287 if ( show
&& options
.important
) {
288 element
.setAttribute( 'role', 'alert' );
290 if ( !this.isVisible() ) {
291 this.area
.add( this );
295 // Overwrite even if it is undefined.
296 this.duration
= options
.duration
;
298 this._hideAfterTimeout();
302 * Removes the notification element from the notification area.
304 * Fires the {@link CKEDITOR.editor#notificationHide} event.
307 if ( this.editor
.fire( 'notificationHide', { notification: this } ) === false ) {
311 this.area
.remove( this );
315 * Returns `true` if the notification is in the notification area.
317 * @returns {Boolean} `true` if the notification is in the notification area.
319 isVisible: function() {
320 return CKEDITOR
.tools
.indexOf( this.area
.notifications
, this ) >= 0;
324 * Creates the notification DOM element.
327 * @returns {CKEDITOR.dom.element} Notification DOM element.
329 _createElement: function() {
330 var notification
= this,
331 notificationElement
, notificationMessageElement
, notificationCloseElement
,
332 close
= this.editor
.lang
.common
.close
;
334 notificationElement
= new CKEDITOR
.dom
.element( 'div' );
335 notificationElement
.addClass( 'cke_notification' );
336 notificationElement
.addClass( this._getClass() );
337 notificationElement
.setAttributes( {
340 'aria-label': this.type
343 if ( this.type
== 'progress' )
344 notificationElement
.append( this._createProgressElement() );
346 notificationMessageElement
= new CKEDITOR
.dom
.element( 'p' );
347 notificationMessageElement
.addClass( 'cke_notification_message' );
348 notificationMessageElement
.setHtml( this.message
);
349 notificationElement
.append( notificationMessageElement
);
351 notificationCloseElement
= CKEDITOR
.dom
.element
.createFromHtml(
352 '<a class="cke_notification_close" href="javascript:void(0)" title="' + close
+ '" role="button" tabindex="-1">' +
353 '<span class="cke_label">X</span>' +
355 notificationElement
.append( notificationCloseElement
);
357 notificationCloseElement
.on( 'click', function() {
358 // Focus editor on close (http://dev.ckeditor.com/ticket/12865)
359 notification
.editor
.focus();
364 return notificationElement
;
368 * Gets the notification CSS class.
371 * @returns {String} Notification CSS class.
373 _getClass: function() {
374 return ( this.type
== 'progress' ) ?
375 'cke_notification_info' :
376 ( 'cke_notification_' + this.type
);
380 * Creates a progress element for the notification element.
383 * @returns {CKEDITOR.dom.element} Progress element for the notification element.
385 _createProgressElement: function() {
386 var element
= new CKEDITOR
.dom
.element( 'span' );
387 element
.addClass( 'cke_notification_progress' );
388 element
.setStyle( 'width', this._getPercentageProgress() );
393 * Gets the progress as a percentage (ex. `0.3` -> `30%`).
396 * @returns {String} Progress as a percentage.
398 _getPercentageProgress: function() {
399 return Math
.round( ( this.progress
|| 0 ) * 100 ) + '%';
403 * Hides the notification after a timeout.
407 _hideAfterTimeout: function() {
408 var notification
= this,
411 if ( this._hideTimeoutId
) {
412 clearTimeout( this._hideTimeoutId
);
415 if ( typeof this.duration
== 'number' ) {
416 duration
= this.duration
;
417 } else if ( this.type
== 'info' || this.type
== 'success' ) {
418 duration
= ( typeof this.editor
.config
.notification_duration
== 'number' ) ?
419 this.editor
.config
.notification_duration :
424 notification
._hideTimeoutId
= setTimeout( function() {
432 * Notification area is an area where all notifications are put. The area is laid out dynamically.
433 * When the first notification is added, the area is shown and all listeners are added.
434 * When the last notification is removed, the area is hidden and all listeners are removed.
438 * @class CKEDITOR.plugins.notification.area
440 * @param {CKEDITOR.editor} editor The editor instance.
442 function Area( editor
) {
445 this.editor
= editor
;
446 this.notifications
= [];
447 this.element
= this._createElement();
448 this._uiBuffer
= CKEDITOR
.tools
.eventsBuffer( 10, this._layout
, this );
449 this._changeBuffer
= CKEDITOR
.tools
.eventsBuffer( 500, this._layout
, this );
451 editor
.on( 'destroy', function() {
452 that
._removeListeners();
453 that
.element
.remove();
458 * The editor instance.
461 * @property {CKEDITOR.editor} editor
465 * The array of added notifications.
468 * @property {Array} notifications
472 * Notification area DOM element. This element is created when the area object is created. It will be attached to the document
473 * when the first notification is added and removed when the last notification is removed.
476 * @property {CKEDITOR.dom.element} element
480 * Notification width. Cached for performance reasons.
483 * @property {CKEDITOR.dom.element} _notificationWidth
487 * Notification margin. Cached for performance reasons.
490 * @property {CKEDITOR.dom.element} _notificationMargin
494 * Event buffer object for UI events to optimize performance.
497 * @property {Object} _uiBuffer
501 * Event buffer object for editor change events to optimize performance.
504 * @property {Object} _changeBuffer
509 * Adds the notification to the notification area. If it is the first notification, the area will also be attached to
510 * the document and listeners will be attached.
512 * Note that the proper way to show a notification is to call the {@link CKEDITOR.plugins.notification#show} method.
514 * @param {CKEDITOR.plugins.notification} notification Notification to add.
516 add: function( notification
) {
517 this.notifications
.push( notification
);
519 this.element
.append( notification
.element
);
521 if ( this.element
.getChildCount() == 1 ) {
522 CKEDITOR
.document
.getBody().append( this.element
);
523 this._attachListeners();
530 * Removes the notification from the notification area. If it is the last notification, the area will also be
531 * detached from the document and listeners will be detached.
533 * Note that the proper way to hide a notification is to call the {@link CKEDITOR.plugins.notification#hide} method.
535 * @param {CKEDITOR.plugins.notification} notification Notification to remove.
537 remove: function( notification
) {
538 var i
= CKEDITOR
.tools
.indexOf( this.notifications
, notification
);
544 this.notifications
.splice( i
, 1 );
546 notification
.element
.remove();
548 if ( !this.element
.getChildCount() ) {
549 this._removeListeners();
550 this.element
.remove();
555 * Creates the notification area element.
558 * @returns {CKEDITOR.dom.element} Notification area element.
560 _createElement: function() {
561 var editor
= this.editor
,
562 config
= editor
.config
,
563 notificationArea
= new CKEDITOR
.dom
.element( 'div' );
565 notificationArea
.addClass( 'cke_notifications_area' );
566 notificationArea
.setAttribute( 'id', 'cke_notifications_area_' + editor
.name
);
567 notificationArea
.setStyle( 'z-index', config
.baseFloatZIndex
- 2 );
569 return notificationArea
;
573 * Attaches listeners to the notification area.
577 _attachListeners: function() {
578 var win
= CKEDITOR
.document
.getWindow(),
579 editor
= this.editor
;
581 win
.on( 'scroll', this._uiBuffer
.input
);
582 win
.on( 'resize', this._uiBuffer
.input
);
583 editor
.on( 'change', this._changeBuffer
.input
);
584 editor
.on( 'floatingSpaceLayout', this._layout
, this, null, 20 );
585 editor
.on( 'blur', this._layout
, this, null, 20 );
589 * Detaches listeners from the notification area.
593 _removeListeners: function() {
594 var win
= CKEDITOR
.document
.getWindow(),
595 editor
= this.editor
;
597 win
.removeListener( 'scroll', this._uiBuffer
.input
);
598 win
.removeListener( 'resize', this._uiBuffer
.input
);
599 editor
.removeListener( 'change', this._changeBuffer
.input
);
600 editor
.removeListener( 'floatingSpaceLayout', this._layout
);
601 editor
.removeListener( 'blur', this._layout
);
605 * Sets the position of the notification area based on the editor content, toolbar as well as
606 * viewport position and dimensions.
610 _layout: function() {
611 var area
= this.element
,
612 editor
= this.editor
,
613 contentsRect
= editor
.ui
.contentsElement
.getClientRect(),
614 contentsPos
= editor
.ui
.contentsElement
.getDocumentPosition(),
617 areaRect
= area
.getClientRect(),
619 notificationWidth
= this._notificationWidth
,
620 notificationMargin
= this._notificationMargin
,
621 win
= CKEDITOR
.document
.getWindow(),
622 scrollPos
= win
.getScrollPosition(),
623 viewRect
= win
.getViewPaneSize(),
624 body
= CKEDITOR
.document
.getBody(),
625 bodyPos
= body
.getDocumentPosition(),
626 cssLength
= CKEDITOR
.tools
.cssLength
;
628 // Cache for optimization
629 if ( !notificationWidth
|| !notificationMargin
) {
630 notification
= this.element
.getChild( 0 );
631 notificationWidth
= this._notificationWidth
= notification
.getClientRect().width
;
632 notificationMargin
= this._notificationMargin
=
633 parseInt( notification
.getComputedStyle( 'margin-left' ), 10 ) +
634 parseInt( notification
.getComputedStyle( 'margin-right' ), 10 );
637 // Check if toolbar exist and if so, then assign values to it (#491).
638 if ( editor
.toolbar
) {
639 top
= editor
.ui
.space( 'top' );
640 topRect
= top
.getClientRect();
644 // --------------------------------------- Horizontal layout ----------------------------------------
646 // +---Viewport-------------------------------+ +---Viewport-------------------------------+
648 // | +---Toolbar----------------------------+ | | +---Content----------------------------+ |
650 // | +---Content----------------------------+ | | | | |
651 // | | | | | +---Toolbar----------------------+ | |
652 // | | +------Notification------+ | | | | | | |
653 // | | | | OR | +--------------------------------+ | |
655 // | | | | | | +------Notification------+ | |
658 // | +--------------------------------------+ | | +--------------------------------------+ |
659 // +------------------------------------------+ +------------------------------------------+
660 if ( top
&& top
.isVisible() &&
661 topRect
.bottom
> contentsRect
.top
&&
662 topRect
.bottom
< contentsRect
.bottom
- areaRect
.height
) {
665 // +---Viewport-------------------------------+
667 // | +---Content----------------------------+ |
669 // | | +------Notification------+ | |
673 // | +--------------------------------------+ |
675 // +------------------------------------------+
676 } else if ( contentsRect
.top
> 0 ) {
679 // +---Content----------------------------+
681 // +---Viewport-------------------------------+
683 // | | +------Notification------+ | |
687 // | +--------------------------------------+ |
689 // +------------------------------------------+
690 } else if ( contentsPos
.y
+ contentsRect
.height
- areaRect
.height
> scrollPos
.y
) {
693 // +---Content----------------------------+ +---Content----------------------------+
696 // | | | +------Notification------+ |
698 // | | OR +--------------------------------------+
699 // +---Viewport-------------------------------+
700 // | | +------Notification------+ | | +---Viewport-------------------------------+
702 // | +--------------------------------------+ | | |
704 // +------------------------------------------+ +------------------------------------------+
709 function setTopStandard() {
711 position: 'absolute',
712 top: cssLength( contentsPos
.y
)
716 function setBelowToolbar() {
719 top: cssLength( topRect
.bottom
)
723 function setTopFixed() {
730 function setBottom() {
732 position: 'absolute',
733 top: cssLength( contentsPos
.y
+ contentsRect
.height
- areaRect
.height
)
737 // ---------------------------------------- Vertical layout -----------------------------------------
739 var leftBase
= area
.getStyle( 'position' ) == 'fixed' ?
741 body
.getComputedStyle( 'position' ) != 'static' ? contentsPos
.x
- bodyPos
.x : contentsPos
.x
;
743 // Content is narrower than notification
744 if ( contentsRect
.width
< notificationWidth
+ notificationMargin
) {
746 // +---Viewport-------------------------------+
748 // | +---Content------------+ |
750 // | +------Notification------+ | |
752 // | +----------------------+ |
754 // +------------------------------------------+
755 if ( contentsPos
.x
+ notificationWidth
+ notificationMargin
> scrollPos
.x
+ viewRect
.width
) {
758 // +---Viewport-------------------------------+ +---Viewport--------------------------+
760 // | +---Content------------+ | +---Content------------+ |
762 // | | +------Notification------+ | OR | +------Notification------+ |
764 // | +----------------------+ | +----------------------+ |
766 // +------------------------------------------+ +-------------------------------------+
771 // Content is wider than notification.
774 // +--+Viewport+------------------------+
776 // | +---Content-----------------------------------------+
778 // | | +-----+Notification+-----+ |
782 // | +---------------------------------------------------+
784 // +------------------------------------+
785 if ( contentsPos
.x
+ notificationWidth
+ notificationMargin
> scrollPos
.x
+ viewRect
.width
) {
788 // +---Viewport-------------------------+
790 // | +---Content----------------------------------------------+
792 // | | +------Notification------+ | |
795 // | +--------------------------------------------------------+
797 // +------------------------------------+
798 } else if ( contentsPos
.x
+ contentsRect
.width
/ 2 +
799 notificationWidth
/ 2 + notificationMargin
> scrollPos
.x
+ viewRect
.width
) {
802 // +---Viewport-------------------------+
804 // +---Content----------------------------+ |
806 // | +------Notification------+ | |
809 // +--------------------------------------+ |
811 // +------------------------------------+
812 } else if ( contentsRect
.left
+ contentsRect
.width
- notificationWidth
- notificationMargin
< 0 ) {
815 // +---Viewport-------------------------+
817 // +---Content---------------------------------------------+ |
819 // | | +------Notification------+ | |
822 // +-------------------------------------------------------+ |
824 // +------------------------------------+
825 } else if ( contentsRect
.left
+ contentsRect
.width
/ 2 - notificationWidth
/ 2 < 0 ) {
828 // +---Viewport-------------------------+
830 // | +---Content----------------------+ |
832 // | | +-----Notification-----+ | |
835 // | +--------------------------------+ |
837 // +------------------------------------+
844 area
.setStyle( 'left', cssLength( leftBase
) );
847 function setLeftFixed() {
848 area
.setStyle( 'left', cssLength( leftBase
- contentsPos
.x
+ scrollPos
.x
) );
851 function setCenter() {
852 area
.setStyle( 'left', cssLength( leftBase
+ contentsRect
.width
/ 2 - notificationWidth
/ 2 - notificationMargin
/ 2 ) );
855 function setRight() {
856 area
.setStyle( 'left', cssLength( leftBase
+ contentsRect
.width
- notificationWidth
- notificationMargin
) );
859 function setRightFixed() {
860 area
.setStyle( 'left', cssLength( leftBase
- contentsPos
.x
+ scrollPos
.x
+ viewRect
.width
-
861 notificationWidth
- notificationMargin
) );
866 CKEDITOR
.plugins
.notification
= Notification
;
869 * After how many milliseconds the notification of the `info` and `success`
870 * {@link CKEDITOR.plugins.notification#type type} should close automatically.
871 * `0` means that notifications will not close automatically.
872 * Note that `warning` and `progress` notifications will never close automatically.
874 * Refer to the [Notifications](http://docs.ckeditor.com/#!/guide/dev_notifications) article
875 * for more information about this feature.
878 * @cfg {Number} [notification_duration=5000]
879 * @member CKEDITOR.config
883 * Event fired when the {@link CKEDITOR.plugins.notification#show} method is called, before the
884 * notification is shown. If this event is canceled, the notification will not be shown.
886 * Using this event allows you to fully customize how a notification will be shown. It may be used to integrate
887 * the CKEditor notification system with your web page notifications.
890 * @event notificationShow
891 * @member CKEDITOR.editor
893 * @param {CKEDITOR.plugins.notification} data.notification Notification which will be shown.
894 * @param {CKEDITOR.editor} editor The editor instance.
898 * Event fired when the {@link CKEDITOR.plugins.notification#update} method is called, before the
899 * notification is updated. If this event is canceled, the notification will not be shown even if the update was important,
900 * but the object will be updated anyway. Note that canceling this event does not prevent updating {@link #element}
901 * attributes, but if {@link #notificationShow} was canceled as well, this element is detached from the DOM.
903 * Using this event allows you to fully customize how a notification will be updated. It may be used to integrate
904 * the CKEditor notification system with your web page notifications.
907 * @event notificationUpdate
908 * @member CKEDITOR.editor
910 * @param {CKEDITOR.plugins.notification} data.notification Notification which will be updated.
911 * Note that it contains the data that has not been updated yet.
912 * @param {Object} data.options Update options, see {@link CKEDITOR.plugins.notification#update}.
913 * @param {CKEDITOR.editor} editor The editor instance.
917 * Event fired when the {@link CKEDITOR.plugins.notification#hide} method is called, before the
918 * notification is hidden. If this event is canceled, the notification will not be hidden.
920 * Using this event allows you to fully customize how a notification will be hidden. It may be used to integrate
921 * the CKEditor notification system with your web page notifications.
924 * @event notificationHide
925 * @member CKEDITOR.editor
927 * @param {CKEDITOR.plugins.notification} data.notification Notification which will be hidden.
928 * @param {CKEDITOR.editor} editor The editor instance.