-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
Copy pathsnippet.js
154 lines (125 loc) · 5.52 KB
/
snippet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/* globals window, document, setTimeout */
// Show clipboard input notification when user tries to paste a content from MS Word or Google Docs.
setTimeout( () => {
// Don't show the warning notification in "Paste from Office" and "Paste from Google Docs" demos.
if ( window.preventPasteFromOfficeNotification ) {
return;
}
const editables = document.querySelectorAll( '.ck-content' );
const googleDocsMatch = /id=("|')docs-internal-guid-[-0-9a-f]+("|')/i;
const msWordMatch1 = /<meta\s*name="?generator"?\s*content="?microsoft\s*word\s*\d+"?\/?>/i;
const msWordMatch2 = /xmlns:o="urn:schemas-microsoft-com/i;
// A state variable that indicates if the clipboard notification has been seen.
// We use the variable for displaying the notification only once per demo.
let hasNotificationBeenSeen = false;
editables.forEach( editable => {
const editor = editable.ckeditorInstance;
if ( !editor ) {
return;
}
editor.plugins.get( 'Clipboard' ).listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => {
const htmlString = data.dataTransfer.getData( 'text/html' );
const match = msWordMatch1.test( htmlString ) ||
msWordMatch2.test( htmlString ) ||
googleDocsMatch.test( htmlString );
if ( match && !hasNotificationBeenSeen ) {
createClipboardInputNotification();
hasNotificationBeenSeen = true;
}
} );
} );
}, 3000 );
// The notification should contain the links to the demos where user can test rich formatting from.
function createClipboardInputNotification() {
const title = 'Hello!';
const message = `
<p>We detected that you tried to paste content from <strong>Microsoft Word</strong> or <strong>Google Docs</strong>.</p>
<p>Please bear in mind that the editor demo to which you try to paste does not have all the features enabled.
Due to that, unsupported formatting is being stripped.</p>
<p>Check out the <a href="/docs/ckeditor5/latest/features/pasting/paste-from-office.html">Paste from Office</a> or
<a href="/docs/ckeditor5/latest/features/pasting/paste-from-google-docs.html">Paste from Google Docs</a>
demos for the best experience.</p>`;
window.createNotification( title, message );
}
/**
* Creates a notification and appends it to the `.main__content` element.
*
* @param {String} title A title of the notification.
* @param {String} message A message to display in the notification.
*
* @returns {Object} A notification element.
*/
window.createNotification = function( title, message ) {
const notificationTemplate = `
<h3 class="main__notification-title">${ title }</h3>
<div class="main__notification-body">
${ message }
</div>
`;
const notification = document.createElement( 'div' );
const close = document.createElement( 'button' );
close.classList.add( 'main__notification-close' );
close.innerText = '✕';
close.setAttribute( 'aria-label', 'Close the notification' );
notification.classList.add( 'main__notification', 'notice' );
notification.innerHTML = notificationTemplate;
// ATM we support only top-right position.
notification.style.top = window.getViewportTopOffsetConfig() + 10 + 'px';
notification.style.right = '10px';
notification.appendChild( close );
const activeNotifications = document.querySelectorAll( '.main__notification' );
// Translate the position of multiple notifications (just in case).
if ( activeNotifications.length > 0 ) {
const moveOffset = activeNotifications.length * 10;
notification.style.top = parseInt( notification.style.top ) + moveOffset + 'px';
notification.style.right = parseInt( notification.style.right ) + moveOffset + 'px';
}
// Append notification to the `.main__content` element.
const main = document.querySelector( '.main__content' );
main.appendChild( notification );
close.addEventListener( 'click', () => {
main.removeChild( notification );
} );
return notification;
};
/**
* Returns the `config.ui.viewportOffset.top` config value for editors using floating toolbars that
* stick to the top of the viewport to remain visible to the user.
*
* The value is determined in styles by the `--ck-snippet-viewport-top-offset` custom property
* and may differ e.g. according to the used media queries.
*
* @returns {Number} The value of the offset.
*/
window.getViewportTopOffsetConfig = function() {
const documentElement = document.documentElement;
return parseInt( window.getComputedStyle( documentElement ).getPropertyValue( '--ck-snippet-viewport-top-offset' ) );
};
/**
* Activates tabs in the given container.
*
* **Note**: The tabs container requires a proper markup to work correctly.
*
* @param {HTMLElement} tabsContainer
*/
window.createTabs = function( tabsContainer ) {
const tabTextElements = Array.from( tabsContainer.querySelectorAll( '.tabs__list__tab-text' ) );
const tabPanels = Array.from( tabsContainer.querySelectorAll( '.tabs__panel' ) );
tabTextElements.forEach( tabTextElement => {
tabTextElement.addEventListener( 'click', evt => {
const clickedIndex = tabTextElements.indexOf( tabTextElement );
tabTextElements.forEach( element => {
element.parentElement.classList.toggle( 'tabs__list__tab_selected', tabTextElement === element );
element.setAttribute( 'aria-selected', tabTextElement === element );
} );
tabPanels.forEach( panel => {
panel.classList.toggle( 'tabs__panel_selected', tabPanels.indexOf( panel ) === clickedIndex );
} );
evt.preventDefault();
} );
} );
};