Changes for page EditSheet

Last modified by superadmin on 2025/10/09 09:51

From version 14.1
edited by superadmin
on 2025/10/09 09:51
Change comment: Install extension [org.xwiki.platform:xwiki-platform-ckeditor-ui/17.8.0]
To version 7.1
edited by Thomas Coelho (local)
on 2023/07/26 11:23
Change comment: Install extension [org.xwiki.platform:xwiki-platform-ckeditor-ui/15.5]

Summary

Details

Page properties
Author
... ... @@ -1,1 +1,1 @@
1 -XWiki.superadmin
1 +XWiki.coelho
Content
... ... @@ -1,0 +1,38 @@
1 +{{include reference="CKEditor.VelocityMacros"/}}
2 +
3 +{{velocity}}
4 +#if ($doc.fullName == 'CKEditor.EditSheet')
5 + This is a sheet for editing the document content using [[CKEditor>>http://ckeditor.com/]].
6 +#else
7 + {{html clean="false"}}
8 + ## Include the auto-save styles.
9 + #set ($discard = $xwiki.ssfx.use('js/xwiki/editors/autosave.css', true))
10 + #if ("$!request.section" != '')
11 + <div class="hidden">
12 + <input type="hidden" name="section" value="$!escapetool.xml($request.section)"/>
13 + </div>
14 + #end
15 + <div class="row">
16 + <div class="cke-editMeta col-xs-12 col-md-7">
17 + ## Add support for editing the page title (which is not available by default in Inline Form edit mode).
18 + #set ($editor = 'wiki')
19 + #template('editmeta.vm')
20 + #set ($editor = 'inline')
21 + </div>
22 + </div>
23 + ## The xwikieditcontent id is needed for the auto-save feature.
24 + <div id="xwikieditcontent" data-autosave="true">
25 + #set ($parameters = {
26 + 'content': $tdoc.content,
27 + 'attributes': {
28 + 'id': 'content',
29 + 'name': 'content',
30 + 'rows': 25,
31 + 'cols': 80
32 + }
33 + })
34 + #ckeditor($parameters)
35 + </div>
36 + {{/html}}
37 +#end
38 +{{/velocity}}
XWiki.JavaScriptExtension[0]
Code
... ... @@ -54,12 +54,40 @@
54 54   }
55 55  
56 56   var uploadDisabled = element.hasAttribute('data-upload-disabled');
57 - var startupFocus = element.hasAttribute('data-startup-focus');
58 58  
59 59   var config = {
60 60   filebrowserUploadUrl: uploadDisabled ? '' : getUploadURL(sourceDocument, 'filebrowser'),
61 - startupFocus,
62 62   height: $(element).height(),
61 + mentions: [
62 + {
63 + // We use the source document to compute the feed URL because we want the suggested link references to be
64 + // relative to the edited document (we want the editor to output relative references as much as possible).
65 + feed: sourceDocument.getURL('get', $.param({
66 + sheet: 'CKEditor.LinkSuggestions',
67 + outputSyntax: 'plain',
68 + language: XWiki.locale
69 + // Prevent the curly brackets from being URL encoded because they mark a placeholder that will be replaced
70 + // with the text typed by the user (and CKEditor takes care of URL encoding it).
71 + }) + '&input={encodedQuery}'),
72 + itemTemplate: [
73 + '<li data-id="{id}" class="ckeditor-autocomplete-item">',
74 + '<div>',
75 + '<span class="ckeditor-autocomplete-item-icon-wrapper">',
76 + // We have to output both icon types but normally only one is defined and the other is hidden.
77 + '<img src="{iconURL}"/>',
78 + '<span class="{iconClass}"></span>',
79 + '</span>',
80 + '<span class="ckeditor-autocomplete-item-label">{label}</span>',
81 + '</div>',
82 + '<div class="ckeditor-autocomplete-item-hint">{hint}</div>',
83 + '</li>'].join(''),
84 + outputTemplate: '<a href="{url}" data-reference="{typed}|-|{type}|-|{reference}">{label}</a>',
85 + followingSpace: true,
86 + marker: '[',
87 + minChars: 0,
88 + itemsLimit: 6
89 + }
90 + ],
63 63   // Used to resolve and serialize relative references. Also used to make HTTP requests with the right context.
64 64   sourceDocument: sourceDocument,
65 65   // The syntax of the edited content is not always the same as the syntax of the source document (which applies to
... ... @@ -129,49 +129,5 @@
129 129   object[key] = newValue;
130 130   };
131 131  
132 - // See XWIKI-21351: Macros using RequireJS are not properly displayed by the standalone WYSIWYG editor even when
133 - // JavaScript is enabled.
134 - //
135 - // For each CKEditor instance that uses a separate DOM document for the edited content (i.e. classical iframe-based
136 - // editor) we overwrite the appendChild and insertBefore functions of the initial HEAD element in order to make sure
137 - // that RequireJS appends the script tags to the current HEAD element (because the HEAD element is overwritten each
138 - // time the edited content is reloaded, like when inserting a macro or switching between Source and WYSIWYG modes).
139 - //
140 - // We have to overwrite both appendChild and insertBefore because depending on the presence of the BASE element
141 - // RequireJS uses one or the other.
142 - ckeditor.on('instanceReady', ({editor}) => {
143 - if (editor.document.$ !== document) {
144 - // This editor instance is using a separate DOM document for editing which means it's a standalone editor.
145 - const initialHead = editor.document.$.head;
146 - const originalAppendChild = initialHead.appendChild;
147 - initialHead.appendChild = function() {
148 - const currentHead = editor.document.$.head;
149 - if (currentHead !== initialHead) {
150 - // The edited content has been reloaded. Append to the current HEAD.
151 - return currentHead.appendChild.apply(currentHead, arguments);
152 - } else {
153 - // Still using the initial HEAD so preserve the default behavior.
154 - originalAppendChild.apply(initialHead, arguments);
155 - }
156 - };
157 - const originalInsertBefore = initialHead.insertBefore;
158 - initialHead.insertBefore = function(newChild, existingChild) {
159 - const currentHead = editor.document.$.head;
160 - if (currentHead !== initialHead) {
161 - // The edited content has been reloaded. Normally the given existingChild should be a child of the initial
162 - // HEAD element (not the current one), but better check to be sure.
163 - if (existingChild.parentNode === currentHead) {
164 - return currentHead.insertBefore(newChild, existingChild);
165 - } else {
166 - return currentHead.appendChild.apply(newChild);
167 - }
168 - } else {
169 - // Still using the initial HEAD so preserve the default behavior.
170 - return originalInsertBefore.apply(initialHead, arguments);
171 - }
172 - };
173 - }
174 - });
175 -
176 176   return $.Deferred().resolve(ckeditor).promise();
177 177  });
XWiki.JavaScriptExtension[2]
Code
... ... @@ -10,9 +10,7 @@
10 10   container.find('.ckeditor-textarea').each(function() {
11 11   // Wrap in try/catch so that a failure to load one editor doesn't affect the other editors.
12 12   try {
13 - createEditor(ckeditor, this).then(() => {
14 - this.classList.remove('loading');
15 - });
13 + createEditor(ckeditor, this);
16 16   } catch(e) {
17 17   console.log(e);
18 18   }
XWiki.StyleSheetExtension[0]
Code
... ... @@ -12,13 +12,6 @@
12 12   resize: none;
13 13  }
14 14  
15 -/* Hide the form action bar while the editor is loading in order to avoid UI flickering (because the editor may enhance
16 - or replace the form action bar). */
17 -main > div:has(.ckeditor-textarea.loading) ~ .bottom-editor,
18 -#xwikicontent.loading ~ form#inplace-editing {
19 - visibility: hidden;
20 -}
21 -
22 22  /* Show the modal above the CKEditor dialogs */
23 23  body > .modal-backdrop {
24 24   z-index: 10040;
... ... @@ -179,25 +179,6 @@
179 179  }
180 180  
181 181  /**
182 - * Handle the layout and display of the warning message for headerless tables.
183 - * This message is added by the xwiki-table plugin.
184 - * Some of the default styles are just overridden by the CKEditor reset.
185 - */
186 -.cke_dialog_container span.box.warningmessage {
187 - .alert-warning;
188 - /* Default warning boxes are not meant to be used in a strict layout like the one of this table dialog.
189 - * We need an extra customization to avoid breaking this layout. */
190 - white-space: break-spaces;
191 - /* By default, the warning is not shown. */
192 - display: none;
193 -}
194 -
195 -/* When the value of the previous field is the one we want to avoid, we show the warning. */
196 -.cke_dialog_container tr:has(select [value=""]:checked) + tr span.box.warningmessage {
197 - display: unset;
198 -}
199 -
200 -/**
201 201   * Link Options Toggle
202 202   */
203 203  
... ... @@ -230,6 +230,8 @@
230 230  a.cke_button.cke_button__xwiki-macro-edit > span.cke_button_icon.cke_button__xwiki-macro-edit_icon,
231 231  a.cke_button.cke_button__xwiki-link-open > span.cke_button_icon.cke_button__xwiki-link-open_icon,
232 232  a.cke_button.cke_button__insert > span.cke_button_icon.cke_button__insert_icon {
207 + /* This is needed for XWiki versions older than 7.1M1 where we overwrite the icons path (see above). */
208 + background-image: none !important;
233 233   font-family: 'Glyphicons Halflings';
234 234   position: relative;
235 235   top: 1px;
... ... @@ -260,7 +260,7 @@
260 260   */
261 261  ul.cke_autocomplete_panel {
262 262   border: 1px solid rgba(0, 0, 0, 0.15);
263 - border-radius: @border-radius-base;
239 + border-radius: 4px;
264 264   box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
265 265   font: inherit;
266 266   padding: 5px 0;
... ... @@ -312,33 +312,13 @@
312 312   width: 14px;
313 313  }
314 314  .ckeditor-autocomplete-item-icon-wrapper img {
315 - border-radius: @border-radius-small;
291 + border-radius: 3px;
316 316   max-height: 14px;
317 317   max-width: 14px;
318 318   vertical-align: text-top;
319 319  }
320 -.ckeditor-autocomplete-item-preview-wrapper {
321 - display: flex;
322 - align-items: center;
323 - justify-content: space-around;
324 - height: 64px;
325 - margin-right: .5em;
326 - text-align: center;
327 - vertical-align: middle;
328 - width: 64px;
329 -}
330 -.ckeditor-autocomplete-centered {
331 - justify-content: center;
332 -}
333 -.ckeditor-autocomplete-item-preview-wrapper img {
334 - border-radius: @border-radius-small;
335 - max-height: 64px;
336 - max-width: 64px;
337 - vertical-align: text-top;
338 -}
339 -/* The image still takes some space in all browsers even if there's no source specified. Let's make sure it's hidden.
296 +/* The image still takes some space in IE11 even if there's no source specified. Let's make sure it's hidden.
340 340   See CKEDITOR-389: Missing space in the suggestions that appear while using the autocomplete function on IE 11 */
341 -.ckeditor-autocomplete-item-preview-wrapper img[src=""],
342 342  .ckeditor-autocomplete-item-icon-wrapper img[src=""] {
343 343   display: none;
344 344  }
... ... @@ -389,89 +389,29 @@
389 389  }
390 390  
391 391  .cke_contents > textarea.cke_source.cke_editable_inline {
348 + border: 1px solid transparent;
349 + border-radius: 0;
392 392   box-shadow: none;
351 + margin-top: -1px;
352 + margin-left: -1px;
353 +
354 + .form-control-focus();
393 393  }
394 394  
357 +.cke_contents.fake {
358 + /* We need this to have the box shadow visible when the source area is focused. */
359 + overflow: visible;
360 +}
361 +
395 395  #xwikicontent + .cke_contents > textarea.cke_source.cke_editable_inline {
396 396   /* Don't take the padding and the margin into account when computing the 100% width. */
397 397   box-sizing: content-box;
398 398   /* Make sure the Source area has the same width as the WYSIWYG area. */
399 - margin-left: -@grid-gutter-width / 2;
400 - margin-right: -@grid-gutter-width / 2;
366 + margin-left: -@grid-gutter-width / 2 - 1px;
367 + margin-right: -@grid-gutter-width / 2 - 1px;
401 401  }
402 402  
403 403  /**
404 - * Custom styles to match XWiki's Look & Feel
405 - */
406 -.cke_chrome,
407 -.cke_chrome > .cke_inner {
408 - border-radius: @border-radius-base;
409 -}
410 -
411 -.cke_chrome > .cke_inner > .cke_top {
412 - border-top-right-radius: @border-radius-base;
413 - border-top-left-radius: @border-radius-base;
414 -}
415 -
416 -.cke_chrome > .cke_inner > .cke_bottom {
417 - border-bottom-right-radius: @border-radius-base;
418 - border-bottom-left-radius: @border-radius-base;
419 -}
420 -
421 -/* The standalone WYSIWYG edit mode shows the form action toolbar right below the CKEditor instance used to edit the
422 - document content. We make the bottom border rounded on the form action toolbar instead. */
423 -#xwikieditcontent > .cke_chrome,
424 -#xwikieditcontent > .cke_chrome > .cke_inner,
425 -#xwikieditcontent > .cke_chrome > .cke_inner > .cke_bottom {
426 - border-bottom-right-radius: 0;
427 - border-bottom-left-radius: 0;
428 -}
429 -
430 -a.cke_button,
431 -a.cke_combo_button {
432 - border-radius: @border-radius-small;
433 -}
434 -
435 -.cke_panel,
436 -.cke_dialog_body,
437 -.cke_dialog a.cke_dialog_ui_button,
438 -.cke_dialog input.cke_dialog_ui_input_text,
439 -.cke_dialog select.cke_dialog_ui_input_select,
440 -.cke_dialog fieldset.cke_dialog_ui_fieldset,
441 -.cke_notification {
442 - border-radius: @border-radius-base;
443 -}
444 -
445 -.cke_panel.cke_menu_panel,
446 -.cke_panel.cke_combopanel {
447 - margin: 2px 0;
448 -}
449 -
450 -.cke_dialog_title,
451 -.cke_dialog a.cke_dialog_tab {
452 - border-top-right-radius: @border-radius-base;
453 - border-top-left-radius: @border-radius-base;
454 -}
455 -
456 -.cke_dialog_contents,
457 -.cke_dialog_footer {
458 - border-bottom-right-radius: @border-radius-base;
459 - border-bottom-left-radius: @border-radius-base;
460 -}
461 -
462 -/**
463 - * Custom styles for the in-line editor
464 - */
465 -.viewbody > .cke_float {
466 - /* Shift the floating toolbar in order to match the content padding. */
467 - margin-right: floor((@grid-gutter-width / 2));
468 - margin-left: ceil((@grid-gutter-width / 2));
469 -}
470 -.cke_float .cke_top {
471 - border-radius: @border-radius-base;
472 -}
473 -
474 -/**
475 475   * Full-screen styles for the in-line editor
476 476   */
477 477  body[data-maximized="true"] {
... ... @@ -507,6 +507,12 @@
507 507   margin: 0 !important;
508 508   overflow-y: auto !important;
509 509   z-index: 9995;
406 +
407 + &:focus {
408 + /* Remove the focus border. */
409 + border-color: transparent !important;
410 + box-shadow: none !important;
411 + }
510 510   }
511 511   .cke_maximize_backdrop {
512 512   top: 0;
... ... @@ -526,37 +526,3 @@
526 526   z-index: 9995;
527 527   }
528 528  }
529 -
530 -/*
531 - * Override the CKEditor reset for the table border color.
532 - * The default border color from CKEditor is quite lacking on contrast.
533 - */
534 -.cke_editable.cke_show_borders table.cke_show_border,
535 -.cke_editable.cke_show_borders table.cke_show_border > tr > th,
536 -.cke_editable.cke_show_borders table.cke_show_border > tr > td,
537 -.cke_editable.cke_show_borders table.cke_show_border > thead > tr > th,
538 -.cke_editable.cke_show_borders table.cke_show_border > thead > tr > td,
539 -.cke_editable.cke_show_borders table.cke_show_border > tbody > tr > th,
540 -.cke_editable.cke_show_borders table.cke_show_border > tbody > tr > td,
541 -.cke_editable.cke_show_borders table.cke_show_border > tfoot > tr > th,
542 -.cke_editable.cke_show_borders table.cke_show_border > tfoot > tr > td {
543 - border-color: @table-border-color;
544 - border-style: solid;
545 -}
546 -
547 -/* CKEditor contains a CSS reset. It works with its own style sheets and does not use the ones in XWiki.
548 -However, we want `.sr-only` from XWiki to still be usable in our CKEditor environment.
549 -We need to redefine the XWiki styles of this class to have better priority than the CKEditor CSS reset.
550 -Without this, the elements with this class are still shown which would be different from the behaviour
551 -of `.sr-only` anywhere else in XWiki (as described in our doc).
552 -This redefinition allows for a more consistent behaviour of the `.sr-only` class. */
553 -.cke_reset_all .sr-only {
554 - position: absolute;
555 - width: 1px;
556 - height: 1px;
557 - padding: 0;
558 - margin: -1px;
559 - overflow: hidden;
560 - clip: rect(0, 0, 0, 0);
561 - border: 0;
562 -}