1(function (Drupal, CKEditor5) { 2 /** 3 * @file 4 * Defines Imce plugins for CKEditor5. 5 */ 6 7 /** 8 * Defines imce.ImceSelector plugin. 9 * 10 * Integrates Imce button into image/link url fields. 11 */ 12 class ImceSelector extends CKEditor5.core.Plugin { 13 init() { 14 this.editor.ui.on('ready', function () { 15 const plugins = this.editor.plugins; 16 // Image -- v44.0.0+. 17 if (plugins.has('ImageInsertViaUrlUI')) { 18 const dialog = plugins.get('Dialog'); 19 if (dialog) { 20 dialog.once('show:insertImageViaUrl', (evt, data) => { 21 const el = data.content.element.getElementsByClassName('ck-input-text')[0]; 22 imceInput.processCKEditor5Input(el, 'image'); 23 }); 24 } 25 } 26 // Image. 27 if (plugins.has('ImageInsertUI')) { 28 const view = plugins.get('ImageInsertUI').dropdownView; 29 if (view) { 30 view.once('change:isOpen', function () { 31 const el = 32 view.element.getElementsByClassName('ck-input-text')[0]; 33 imceInput.processCKEditor5Input(el, 'image'); 34 }); 35 } 36 } 37 // Link. 38 if (plugins.has('LinkUI')) { 39 const ui = plugins.get('LinkUI'); 40 const process = () => { 41 const el = ui.formView?.urlInputView?.fieldView?.element; 42 if (el) { 43 ui._balloon?.view?.off('change:isVisible', process); 44 imceInput.processCKEditor5Input(el, 'link'); 45 return true; 46 } 47 }; 48 process() || ui._balloon?.view?.on('change:isVisible', process); 49 } 50 }); 51 } 52 } 53 54 /** 55 * Defines imce.ImceImage plugin. 56 * 57 * Provides a button that inserts multiple images from Imce. 58 */ 59 class ImceImage extends CKEditor5.core.Plugin { 60 init() { 61 const label = Drupal.t('Insert images using Imce File Manager'); 62 imceInput.ckeditor5PluginInit(this.editor, 'image', label); 63 } 64 } 65 66 /** 67 * Defines imce.ImceLink plugin. 68 * 69 * Provides a button that inserts multiple file links from Imce. 70 */ 71 class ImceLink extends CKEditor5.core.Plugin { 72 init() { 73 const label = Drupal.t('Insert file links using Imce File Manager'); 74 imceInput.ckeditor5PluginInit(this.editor, 'link', label); 75 } 76 } 77 78 /** 79 * Add imce namespace. 80 */ 81 CKEditor5.imce = CKEditor5.imce || { 82 ImceSelector, 83 ImceImage, 84 ImceLink, 85 }; 86 87 /** 88 * Extend window.imceInput. 89 */ 90 const imceInput = window.imceInput || {}; 91 92 /** 93 * Init ckeditor5 image/link plugin. 94 */ 95 imceInput.ckeditor5PluginInit = function (editor, type, label) { 96 editor.ui.componentFactory.add('imce_' + type, function () { 97 const button = new CKEditor5.ui.ButtonView(); 98 button.set({ 99 label, 100 class: 'ck-imce-button ck-imce-' + type + '-button', 101 tooltip: true, 102 }); 103 button.on('execute', function () { 104 const id = editor.sourceElement.getAttribute('data-ckeditor5-id'); 105 return imceInput.openImce('imceInput.sendtoCKEditor5', type, 'ckid=' + id); 106 }); 107 return button; 108 }); 109 }; 110 111 /** 112 * Integrates Imce into a CKEditor5 url input. 113 */ 114 imceInput.processCKEditor5Input = function (el, type) { 115 if (!el) { 116 return; 117 } 118 // Create a custom sento handler. 119 const name = 'sendtoCKEditor5' + (Math.random() + '').substring(2); 120 imceInput[name] = function (File, win) { 121 el.value = File.getUrl(); 122 win.close(); 123 el.focus(); 124 el.dispatchEvent(new CustomEvent('input')); 125 // Auto submit. 126 if (el.form) { 127 const button = el.form.getElementsByClassName('ck-button-save')[0]; 128 if (button) { 129 button.click(); 130 } 131 } 132 }; 133 const button = imceInput.createUrlButton(el.id, type); 134 button.className += ' imce-selector-button'; 135 button.onclick = function () { 136 imceInput.openImce('imceInput.' + name, type); 137 return false; 138 }; 139 el.insertAdjacentElement('afterend', button); 140 el.parentNode.className += ' ck-imce-wrp ck-imce-' + type + '-wrp'; 141 return button; 142 }; 143 144 /** 145 * Imce sendto handler for inserting files/images into CKEditor5. 146 */ 147 imceInput.sendtoCKEditor5 = function (File, win) { 148 const imce = win.imce; 149 const editor = Drupal.CKEditor5Instances.get(imce.getQuery('ckid')); 150 if (!editor) { 151 win.close(); 152 return; 153 } 154 const type = imce.getQuery('type'); 155 const isImg = type === 'image'; 156 const selected = imce.getSelection(); 157 const finish = function () {
158 const inner = isImg ? '' : imceInput.ckeditor5GetSelection(editor); 159 const html = imce.itemsHtml(selected, type, inner); 160 imceInput.ckeditor5SetSelection(editor, html); 161 win.close(); 162 }; 163 if (isImg) { 164 imce.loadItemUuids(selected, finish); 165 } 166 else { 167 finish(); 168 } 169 }; 170 171 /** 172 * Returns selected html from CKEditor5. 173 */ 174 imceInput.ckeditor5GetSelection = function (editor) { 175 let html = ''; 176 try { 177 const model = editor.model; 178 const content = model.getSelectedContent(model.document.selection); 179 html = editor.data.stringify(content); 180 } catch (err) { 181 console.error(err); 182 } 183 return html; 184 }; 185 186 /** 187 * Inserts html into CKEditor5 selection. 188 */ 189 imceInput.ckeditor5SetSelection = function (editor, html, skipFocus) { 190 try { 191 const viewFragment = editor.data.processor.toView(html); 192 const modelFragment = editor.data.toModel(viewFragment); 193 editor.model.insertContent(modelFragment); 194 if (!skipFocus) { 195 editor.editing.view.focus(); 196 } 197 } catch (err) { 198 console.error(err); 199 } 200 }; 201})(Drupal, CKEditor5);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.