123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- /**
- * @file
- * Provides styles for CKEditor inside off-canvas dialogs.
- */
- (($, CKEDITOR) => {
- /**
- * Takes a string of CKEditor CSS and modifies it for use in off-canvas.
- *
- * @param {string} originalCss
- * The CSS rules from CKEditor.
- * @return {string}
- * The rules from originalCss with extra specificity for off-canvas.
- */
- const convertToOffCanvasCss = originalCss => {
- const selectorPrefix = '#drupal-off-canvas ';
- const skinPath = `${CKEDITOR.basePath}${CKEDITOR.skinName}/`;
- const css = originalCss
- .substring(originalCss.indexOf('*/') + 2)
- .trim()
- .replace(/}/g, `}${selectorPrefix}`)
- .replace(/,/g, `,${selectorPrefix}`)
- .replace(/url\(/g, skinPath);
- return `${selectorPrefix}${css}`;
- };
- /**
- * Inserts CSS rules into DOM.
- *
- * @param {string} cssToInsert
- * CSS rules to be inserted
- */
- const insertCss = cssToInsert => {
- const offCanvasCss = document.createElement('style');
- offCanvasCss.innerHTML = cssToInsert;
- offCanvasCss.setAttribute('id', 'ckeditor-off-canvas-reset');
- document.body.appendChild(offCanvasCss);
- };
- /**
- * Adds CSS so CKEditor is styled properly in off-canvas.
- */
- const addCkeditorOffCanvasCss = () => {
- // If #ckeditor-off-canvas-reset exists, this has already run.
- if (document.getElementById('ckeditor-off-canvas-reset')) {
- return;
- }
- // CKEDITOR.skin.getPath() requires the CKEDITOR.skinName property.
- // @see https://stackoverflow.com/a/17336982
- CKEDITOR.skinName = CKEDITOR.skin.name;
- // Get the paths to the css CKEditor is using.
- const editorCssPath = CKEDITOR.skin.getPath('editor');
- const dialogCssPath = CKEDITOR.skin.getPath('dialog');
- // The key for cached CSS in localStorage is based on the CSS paths.
- const storedOffCanvasCss = window.localStorage.getItem(
- `Drupal.off-canvas.css.${editorCssPath}${dialogCssPath}`,
- );
- // See if CSS is cached in localStorage, and use that when available.
- if (storedOffCanvasCss) {
- insertCss(storedOffCanvasCss);
- return;
- }
- // If CSS unavailable in localStorage, get the files via AJAX and parse.
- $.when($.get(editorCssPath), $.get(dialogCssPath)).done(
- (editorCss, dialogCss) => {
- const offCanvasEditorCss = convertToOffCanvasCss(editorCss[0]);
- const offCanvasDialogCss = convertToOffCanvasCss(dialogCss[0]);
- const cssToInsert = `#drupal-off-canvas .cke_inner * {background: transparent;}
- ${offCanvasEditorCss}
- ${offCanvasDialogCss}`;
- insertCss(cssToInsert);
- // The localStorage key for accessing the cached CSS is based on the
- // paths of the CKEditor CSS files. This prevents localStorage from
- // providing outdated CSS. If new files are used due to using a new
- // skin, a new localStorage key is created.
- //
- // The CSS paths also include the cache-busting query string that is
- // stored in state and CKEDITOR.timestamp. This query string changes on
- // update and cache clear and prevents localStorage from providing
- // stale CKEditor CSS.
- //
- // Before adding the CSS rules to localStorage, there is a check that
- // confirms the cache-busting query (CKEDITOR.timestamp) is in the CSS
- // paths. This prevents localStorage from caching something unbustable.
- //
- // @see ckeditor_library_info_alter()
- if (
- CKEDITOR.timestamp &&
- editorCssPath.indexOf(CKEDITOR.timestamp) !== -1 &&
- dialogCssPath.indexOf(CKEDITOR.timestamp) !== -1
- ) {
- Object.keys(window.localStorage).forEach(key => {
- if (key.indexOf('Drupal.off-canvas.css.') === 0) {
- window.localStorage.removeItem(key);
- }
- });
- window.localStorage.setItem(
- `Drupal.off-canvas.css.${editorCssPath}${dialogCssPath}`,
- cssToInsert,
- );
- }
- },
- );
- };
- addCkeditorOffCanvasCss();
- })(jQuery, CKEDITOR);
|