Änderungen von Dokument DiagramEditSheet

Zuletzt geändert von Daniel Herrmann am 2026/02/04 20:25

Von Version Icon 2.1
bearbeitet von Daniel Herrmann
am 2026/02/04 20:25
Änderungskommentar: Install extension [com.xwiki.diagram:application-diagram/1.22.11]
Auf Version 1.1 Icon
bearbeitet von Mike Schneider
am 2025/12/30 10:37
Änderungskommentar: Install extension [org.xwiki.contrib:application-diagram/1.3]

Zusammenfassung

Details

Icon Seiteneigenschaften
Dokument-Autor
... ... @@ -1,1 +1,1 @@
1 -XWiki.dherrman
1 +XWiki.mschneide
Inhalt
... ... @@ -1,34 +32,3 @@
1 -{{include reference="Diagram.ResourceSelector.WebHome" /}}
2 -
3 -{{velocity output="false"}}
4 -#macro (diagramLinkModal)
5 - <div class="modal" id="diagramLinkModal" tabindex="-1" role="dialog"
6 - aria-labelledby="diagramLinkModal-label" data-backdrop="static" data-keyboard="false">
7 - <div class="modal-dialog modal-lg" role="document">
8 - <div class="modal-content">
9 - <div class="modal-header">
10 - <button type="button" class="close" data-dismiss="modal" aria-label="Close">
11 - <span aria-hidden="true">&times;</span>
12 - </button>
13 - <div class="modal-title" id="diagramLinkModal-label">
14 - Link
15 - </div>
16 - </div>
17 - <div class="modal-body xform">
18 - #resourceSelector()
19 - </div>
20 - <div class="modal-footer">
21 - <button type="button" class="btn btn-default" data-dismiss="modal">
22 - $escapetool.xml($services.localization.render('cancel'))
23 - </button>
24 - <button type="button" class="btn btn-primary"></button>
25 - </div>
26 - </div>
27 - </div>
28 - </div>
29 -#end
30 -{{/velocity}}
31 -
32 32  {{velocity}}
33 33  {{html clean="false"}}
34 34  #if ($doc.getObject('Diagram.DiagramClass'))
... ... @@ -35,28 +35,13 @@
35 35   ## Disable the keyboard shortcuts because they prevent the user from typing text inside the diagram (the diagram
36 36   ## editor doesn't use standard text fields for entering the labels for the various shapes the diagram is made of)
37 37   #set ($keyboardShortcutsEnabled = false)
38 - #set ($discard = $xwiki.ssx.use('Diagram.DiagramSheet'))
7 + #set ($discard = $xwiki.ssx.use('Diagram.DiagramEditSheet'))
39 39   #set ($discard = $xwiki.jsx.use('Diagram.DiagramEditSheet'))
40 - ## Issue #219: Cannot modify diagram title in diagram editor
41 - <div class="row xform">
42 - <div class="col-xs-12">
43 - <dl>
44 - <dt>
45 - <label for="xwikidoctitleinput">
46 - $escapetool.xml($services.localization.render('core.editors.content.titleField.label'))
47 - </label>
48 - </dt>
49 - <dd>
50 - <input id="xwikidoctitleinput" type="text" name="title" value="$escapetool.xml($tdoc.title)">
51 - </dd>
52 - </dl>
53 - </div>
54 - </div>
55 -
56 - <div class="diagram-editor loading" data-diagram-config="$escapetool.xml($jsontool.serialize($diagramConfig))">
9 + <div class="diagram-editor loading">
57 57   <input class="diagram-content" type="hidden" name="content" value="$escapetool.xml($tdoc.content)" />
11 + <input class="diagram-svg" type="hidden" name="Diagram.DiagramClass_0_svg"
12 + value="$!escapetool.xml($doc.getValue('svg'))" />
58 58   </div>
59 - #diagramLinkModal()
60 60  #end
61 61  {{/html}}
62 62  {{/velocity}}
Icon XWiki.JavaScriptExtension[1]
Code
... ... @@ -1,29 +1,19 @@
1 1  /**
2 2   * Adds support for editing diagrams stored in XWiki pages.
3 3   */
4 -define('diagramEditTranslations', {
5 - prefix: 'diagram.editor.',
6 - keys: [
7 - 'saveAsImageAttachmentError'
8 - ]
9 -});
10 -
11 -define('diagram-store', ['jquery', 'xwiki-meta', 'xwiki-utils', 'diagram-utils', 'diagram-config',
12 - 'xwiki-l10n!diagramEditTranslations', 'draw.io',
13 - 'xwiki-events-bridge'], function($, xm, xutils, diagramUtils, diagramConfig, l10n) {
4 +define('diagramStore', ['jquery', 'draw.io', 'xwiki-events-bridge'], function($) {
14 14   var files = [];
15 15   window._xfiles = files;
16 - var createFile = function(ui, input, title, documentReference) {
17 - var file = new XWikiFile(ui, input, title, documentReference);
7 + var createFile = function(ui, input, title) {
8 + var file = new XWikiFile(ui, input, title);
18 18   files.push(file);
19 19   return file;
20 20   };
21 21  
22 - var XWikiFile = function(ui, input, title, documentReference) {
13 + var XWikiFile = function(ui, input, title) {
14 + DrawioFile.call(this, ui);
23 23   this.input = input;
24 - DrawioFile.call(this, ui, input.val());
25 25   this.title = title;
26 - this.documentReference = documentReference;
27 27   };
28 28  
29 29   mxUtils.extend(XWikiFile, DrawioFile);
... ... @@ -41,40 +41,13 @@
41 41   setData: function(data) {
42 42   this.input.val(data);
43 43   },
44 - isCompressed: function() {
45 - return false;
34 + updateFileData: function() {
35 + // We overwrite the base implementation because we don't want to support files that contain multiple diagrams.
36 + this.setData(mxUtils.getPrettyXml(this.ui.editor.getGraphXml()));
46 46   },
47 - // TODO: When upgrading the drawio version, ensure that this method is copied from the drawio code and the
48 - // `resolveReferences` parameter of the getFileData is set to `true` to prevent incorrect formatting of links to
49 - // wiki pages in the diagram content. https://github.com/xwikisas/application-diagram/issues/295
50 - createData: function() {
51 - var actualPages = this.ui.pages;
52 -
53 - if (this.isRealtime()) {
54 - // Uses ownPages for getting file data below
55 - this.ui.pages = this.ownPages;
56 -
57 - // Updates view state in own current page
58 - if (this.ui.currentPage != null) {
59 - var ownPage = this.ui.getPageById(
60 - this.ui.currentPage.getId(),
61 - this.ownPages);
62 -
63 - if (ownPage != null) {
64 - ownPage.viewState = this.ui.editor.graph.getViewState();
65 - ownPage.needsUpdate = true;
66 - }
67 - }
68 - }
69 -
70 - var result = this.ui.getFileData(null, null, null, null, null, null, null, null, this,
71 - !this.isCompressed(), true);
72 - this.ui.pages = actualPages;
73 - return result;
74 - },
75 75   open: function() {
76 76   var graphXML = this.getData() || '<mxGraphModel/>';
77 - this.ui.setFileData(graphXML);
40 + this.ui.editor.setGraphXml(mxUtils.parseXml(graphXML).documentElement);
78 78   this.changeListener = mxUtils.bind(this, function(sender, eventObject) {
79 79   this.setModified(true);
80 80   });
... ... @@ -92,9 +92,6 @@
92 92  
93 93   var updateFormFields = function(event) {
94 94   forEachOpenedFile(function(file) {
95 - // This is a workaround for https://github.com/jgraph/drawio/issues/490
96 - // Stop editing for getting the latest content from diagram
97 - file.ui.editor.graph.stopEditing(false);
98 98   file.updateFileData();
99 99   });
100 100   };
... ... @@ -105,143 +105,19 @@
105 105   });
106 106   };
107 107  
108 - var pipeDeferred = function(left, right) {
109 - left.done($.proxy(right, 'resolve')).fail($.proxy(right, 'reject'));
110 - };
68 + // We need to update the form fields before the form is validated (for Preview, Save and Save & Continue).
69 + $(document).on('xwiki:actions:beforePreview xwiki:actions:beforeSave', updateFormFields);
111 111  
112 - var saveBlobAsImageAttachment = function(blob, fileName, documentReference) {
113 - var attachmentReference = new XWiki.AttachmentReference(fileName, documentReference);
114 - var uploadMethod = (diagramConfig.isTemporaryUploadSupported) ? xutils.temporaryUploadAttachment : xutils.uploadAttachment;
115 - var uploadAttachment = $.proxy(uploadMethod, null, blob, attachmentReference);
116 - return uploadAttachment();
117 - };
118 -
119 - var imageCache = {};
120 - var saveFileAsPNGImageAttachment = function(file, index, originalPage) {
121 - var deferred = $.Deferred();
122 - let page = file.ui.pages[index];
123 - file.ui.selectPage(page, true, null);
124 - file.getUi().exportToCanvas(/* callback */ function (canvas) {
125 - if (canvas) {
126 - try {
127 - canvas.toBlob(function (blob) {
128 - pipeDeferred(saveBlobAsImageAttachment(blob, `${getXWikiAttachmentName(index)}.png`, file.documentReference), deferred);
129 - });
130 - } catch(err) {
131 - deferred.reject();
132 - }
133 - } else {
134 - deferred.reject();
71 + $(document).on('xwiki:actions:beforeSave', function() {
72 + forEachOpenedFile(function(file) {
73 + var svgInput = file.input.next('.diagram-svg');
74 + if (svgInput.length > 0) {
75 + var svgRoot = file.getUi().editor.graph.getSvg('#ffffff', true, false, false, null, true);
76 + svgInput.val(mxUtils.getXml(svgRoot));
135 135   }
136 - }, /* width */ null, /* imageCache */ imageCache, /* background */ null, /* error */ function(e) {
137 - new XWiki.widgets.Notification(
138 - l10n['saveAsImageAttachmentError'], 'error');
139 - deferred.reject();
140 - }, /* limitHeight */ null, /* ignoreSelection */ true, /* scale */ diagramConfig.pdfImageExportZoom);
141 - file.ui.selectPage(originalPage, true, null);
142 - return deferred.promise();
143 - };
144 -
145 - var saveFileAsSVGImageAttachment = function(file, index, originalPage) {
146 - var deferred = $.Deferred()
147 - let page = file.ui.pages[index];
148 - file.ui.selectPage(page, true, null);
149 - var svgRoot = file.ui.editor.graph.getSvg(/* background: */ '#ffffff', /* scale: */ null, /* border: */ null,
150 - /* nocrop: */ true, /* crisp: */ null, /* ignoreSelection: */ true);
151 - file.ui.selectPage(originalPage, true, null);
152 - // Embed the images because the PDF exporter might not be able to access them.
153 - file.ui.convertImages(svgRoot, function() {
154 - var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' +
155 - '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
156 - mxUtils.getXml(svgRoot);
157 - var blob = new Blob([svg], {type: 'image/svg+xml'});
158 - pipeDeferred(saveBlobAsImageAttachment(blob, `${getXWikiAttachmentName(index)}.svg`, file.documentReference),
159 - deferred);
160 - }, imageCache);
161 - return deferred.promise();
162 - };
163 -
164 - var saveFileAsImageAttachments = function(file, index, originalPage) {
165 - // This is a workaround for https://github.com/jgraph/drawio/issues/490
166 - // Stop editing for getting the latest content from diagram
167 - file.ui.editor.graph.stopEditing(false);
168 - // We upload the PNG image even if the SVG upload has failed.
169 - var pngUpload = $.proxy(saveFileAsPNGImageAttachment, null, file, index, originalPage);
170 - return saveFileAsSVGImageAttachment(file, index, originalPage).then(pngUpload, pngUpload);
171 - };
172 -
173 - var getXWikiAttachmentName = function (index) {
174 - if (index == 0)
175 - {
176 - // If is the first page we keep the old naming strategy -> diagram.png / diagram.svg
177 - return "diagram";
178 - }
179 - return `diagram${index+1}`;
180 - };
181 -
182 - var deleteAllDiagrams = function() {
183 - let baseUrl = `${XWiki.contextPath}/rest/diagram/deleteDiagramAttachments`;
184 - let queryString = $.param({
185 - "form_token": xm.form_token,
186 - "documentReference": encodeURIComponent(xm.documentReference.toString())
187 187   });
188 - return $.post(`${baseUrl}?${queryString}`);
189 - };
190 -
191 - var saveFilesAsImageAttachments = function() {
192 - var uploadDeferredList = []
193 -
194 - forEachOpenedFile(function (file) {
195 - var uploadDeferred = $.Deferred().resolve();
196 - // Get the current page so we know where to return after saving.
197 - let originalPage = file.ui.currentPage;
198 -
199 - file.ui.pages.forEach(function (page, index) {
200 - // We do the next upload even if the previous uploads have failed.
201 - var nextUpload = $.proxy(saveFileAsImageAttachments, null, file, index,originalPage);
202 - uploadDeferred = uploadDeferred.then(nextUpload, nextUpload);
203 - uploadDeferredList.push(uploadDeferred.promise());
204 - });
205 - });
206 - // Wait for all deferreds to complete.
207 - return $.when.apply($, uploadDeferredList).then(
208 - function () {
209 - // Resolve the overall promise if all succeeded.
210 - return { status: 'success' };
211 - },
212 - function () {
213 - // Reject the overall promise if any failed.
214 - return $.Deferred().reject({ status: 'fail' });
215 - }
216 - ).promise();
217 - };
218 -
219 - var uploadInProgress = false;
220 - // Attach the diagram SVG to the diagram page in order to use it for viewing the diagram and for exporting the diagram
221 - // to PDF. For this we need to stop the default save until the upload action is completed and trigger it after.
222 - $(document).on('xwiki:actions:beforeSave', function(event, data) {
223 - if (!uploadInProgress) {
224 - uploadInProgress = true;
225 - event.stopPropagation();
226 - var saveButton = $(event.target);
227 - saveButton.prop('disabled', true);
228 - deleteAllDiagrams()
229 - .then(saveFilesAsImageAttachments)
230 - .catch(function(e) {
231 - new XWiki.widgets.Notification(
232 - l10n['saveAsImageAttachmentError'], 'error');
233 - })
234 - .always(function() {
235 - saveButton.prop('disabled', false).click();
236 - });
237 - } else {
238 - uploadInProgress = false;
239 - }
240 240   });
241 241  
242 - // We need to update the form fields before the form is validated (for Preview, Save and Save & Continue).
243 - $(document).on('xwiki:actions:beforePreview xwiki:actions:beforeSave', updateFormFields);
244 -
245 245   var submitInProgress = false;
246 246   // Disable the leave confirmation when the form action buttons are used.
247 247   $(document).on('xwiki:actions:cancel xwiki:actions:preview xwiki:actions:save xwiki:document:saved',
Inhalt parsen
... ... @@ -1,1 +1,1 @@
1 -Nein
1 +Ja
Icon XWiki.JavaScriptExtension[2]
Code
... ... @@ -1,384 +1,20 @@
1 -/**
2 - * Overrides the link dialog in order to support creating links to wiki pages.
3 - */
4 -define('diagram-link-editor', [
5 - 'jquery',
6 - 'diagram-link-handler',
7 - 'draw.io',
8 - 'resourceSelector'
9 -], function($, diagramLinkHandler) {
10 - /**
11 - * Override in order to change the Element type check from a.constructor !== Element, which was failing due to a
12 - * collision with the PrototypeJS's own implementation of the standard Element.
13 - * See http://api.prototypejs.org/dom/Element/new/index.html. This code is taken from the minified version of
14 - * mxClient.js and should be removed after PrototypeJS is no longer loaded.
15 - */
16 - mxUtils.isNode = function(a, b, c, d) {
17 - return null == a || a.nodeType !== Node.ELEMENT_NODE || null != b &&
18 - a.nodeName.toLowerCase() != b.toLowerCase() ? !1 : null == c || a.getAttribute(c) == d;
19 - };
20 -
21 -/**
22 - * TODO: When upgrading, make sure to check if this method has changed.
23 - * This method was copied directly from draw.io, and the only change made was the call to this.showDialog.
24 - * Both the width and height were modified to fit better within the XWiki UI.
25 - */
26 -EditorUi.prototype.showBackgroundImageDialog = function (apply, img, color, showColor) {
27 - apply = (apply != null) ? apply : mxUtils.bind(this, function (image, failed, color, shadowVisible) {
28 - if (!failed) {
29 - var change = new ChangePageSetup(this, (showColor) ? color : null, image);
30 - change.ignoreColor = !showColor;
31 - if (shadowVisible != null && showColor) {
32 - change.shadowVisible = shadowVisible;
33 - }
34 - this.editor.graph.model.execute(change);
35 - }
36 - });
37 -
38 - var dlg = new BackgroundImageDialog(this, apply, img, color, showColor);
39 - this.showDialog(dlg.container, 420, (showColor) ? 260 : 240, true, true);
40 - dlg.init();
41 -};
42 -
43 -
44 - EditorUi.prototype.showLinkDialog = function(value, selectLabel, callback, showNewWindowOption, linkTarget) {
45 - var resourceReference = diagramLinkHandler.getResourceReferenceFromCustomLink(value);
46 - // We append the modal to the body element in order to fix Issue #108: "Inserting a link in full screen mode is not
47 - // possible".
48 - $('#diagramLinkModal').appendTo('body').selectResource(resourceReference, {
49 - selectLabel: selectLabel
50 - }).done(function(resourceReference) {
51 - callback(diagramLinkHandler.getCustomLinkFromResourceReference(resourceReference), null, linkTarget);
52 - });
53 - };
54 -
55 - // For some cases, to consider wrapping or overflow, w might be altered and we need to keep the initial value as
56 - // it was from bounds.width of the base mxText node.
57 - var originalText = mxSvgCanvas2D.prototype.text;
58 - mxSvgCanvas2D.prototype.text = function(x, y, w, h, str, align, valign, wrap, format, overflow, clip, rotation, dir) {
59 - this.state.initialWidth = w;
60 - return originalText.apply(this, arguments);
61 - };
62 -
63 - // Don't add warning when the viewer doesn't support SVG 1.1, since we create a fallback for foreignObjects.
64 - Graph.prototype.addForeignObjectWarning = function(canvas, root) {
65 - // Do nothing.
66 - }
67 -
68 - // Override the Graph.updateSvgLinks method to ensure that the links are preserved in the final SVG.
69 - // We need to directly modify the original method because drawio does not provide a parameter to override the default
70 - // behavior or a smaller method that only performs the replacement.
71 - Graph.prototype.updateSvgLinks = function (node, target, removeCustom) {
72 - var links = node.getElementsByTagName('a');
73 - for (var i = 0; i < links.length; i++) {
74 - if (links[i].getAttribute('target') == null) {
75 - var href = links[i].getAttribute('href');
76 - if (href == null) {
77 - href = links[i].getAttribute('xlink:href');
78 - }
79 -
80 - if (href != null) {
81 - if (target != null && /^https?:\/\//.test(href)) {
82 - // If the href starts with http or https, set the target attribute.
83 - links[i].setAttribute('target', target);
84 - } else if (this.isCustomLink(href)) {
85 - // Handle custom links
86 - let absoluteLink = $('<a/>').attr('href', diagramLinkHandler.getURLFromCustomLink(href)).prop('href');
87 - links[i].setAttribute('href', absoluteLink);
88 - }
89 - }
90 - }
91 - }
92 - };
93 -
94 - // Overwrite Graph.getSvg in order to replace XWiki custom links with absolute URLs.
95 - // Also fix the text fallback for viewers with no support for foreignObjects.
96 - var originalGraphGetSVG = Graph.prototype.getSvg;
97 - Graph.prototype.getSvg = function(background, scale, border, nocrop, crisp, ignoreSelection, showText, imgExport,
98 - linkTarget, hasShadow, incExtFonts, keepTheme, exportType, cells) {
99 - imgExport = imgExport || this.createSvgImageExport();
100 - var originalGetLinkForCellState = imgExport.getLinkForCellState;
101 - imgExport.getLinkForCellState = function() {
102 - var result = originalGetLinkForCellState.apply(this, arguments);
103 - if (diagramLinkHandler.isXWikiCustomLink(result)) {
104 - result = diagramLinkHandler.getURLFromCustomLink(result);
105 - // Use the absolute URL because this SVG is used for PDF export which needs to be portable.
106 - result = $('<a/>').attr('href', result).prop('href');
107 - }
108 - return result;
109 - }
110 - var originalDrawState = imgExport.drawState;
111 - imgExport.drawState = function(state, canvas) {
112 - var originalCreateAlternateContent = canvas.createAlternateContent;
113 - canvas.createAlternateContent = function(fo, x, y, w, h, str, align, valign, wrap, format, overflow, clip,
114 - rotation) {
115 - if (format === 'html') {
116 - // Keep only the text content.
117 - str = $('<div/>').html(str).text() || this.foAltText;
118 - }
119 - return originalCreateAlternateContent.call(this, fo, x, y, w, h, str, align, valign, wrap, format, overflow,
120 - clip, rotation);
121 - };
122 - return originalDrawState.apply(this, arguments);
123 - };
124 - try {
125 - return originalGraphGetSVG.call(this, background, scale, border, nocrop, crisp, ignoreSelection, showText,
126 - imgExport, linkTarget, hasShadow, incExtFonts, keepTheme, exportType, cells);
127 - } finally {
128 - imgExport.getLinkForCellState = originalGetLinkForCellState;
129 - imgExport.drawState = originalDrawState;
130 - }
131 - };
132 -});
133 -
134 -/**
135 - * Adds support for using XWiki image attachments in diagrams.
136 - */
137 -define('diagram-image-editor', ['xwiki-utils', 'diagram-link-handler', 'draw.io'], function(xutils, diagramLinkHandler) {
138 - // Fix the base URL used when exporting the diagram as image.
139 - var originalCreateImageUrlConverter = EditorUi.prototype.createImageUrlConverter;
140 - EditorUi.prototype.createImageUrlConverter = function() {
141 - var converter = originalCreateImageUrlConverter.call(this);
142 - converter.convert = function(src) {
143 - // Use baseDomain instead of baseUrl to detect external URLs.
144 - if (src && (src.substr(0, 7) === 'http://' || src.substr(0, 8) === 'https://') &&
145 - src.substr(0, converter.baseDomain.length) !== converter.baseDomain) {
146 - src = PROXY_URL + '?url=' + encodeURIComponent(src);
147 - }
148 - return src;
149 - };
150 - return converter;
151 - };
152 -
153 - // Override for uploading the image as attachment instead of encode it to Base64.
154 - var originalImportFiles = EditorUi.prototype.importFiles;
155 - EditorUi.prototype.importFiles = function(files, x, y, maxSize, fn, resultFn, filterFn, barrierFn, resizeDialog,
156 - maxBytes, resampleThreshold, ignoreEmbeddedXml, evt) {
157 - let importFilesArgs = arguments;
158 - if (fn) {
159 - let editorUi = this;
160 - importFilesArgs = Array.prototype.slice.call(arguments);
161 - // This is the call back function responsible to insert the image.
162 - importFilesArgs[4] = function(data, mimeType, x, y, w, h, filename) {
163 - if (data.substring(0, 5) == 'data:') {
164 - let fnArgs = Array.prototype.slice.call(arguments);
165 - let fileBase64Data = data.substring(data.indexOf(',') + 1);
166 - xutils.uploadAttachment(editorUi.base64ToBlob(fileBase64Data, mimeType), filename).done(function() {
167 - // Include the attachment reference in the URL using the fragment identifier in order to be able to use it
168 - // when saving the diagram (we want to save the attachment reference not the attachment URL).
169 - let resourceReference = {
170 - type: 'attach',
171 - reference: XWiki.Model.serialize(new XWiki.AttachmentReference(filename))
172 - };
173 - let customLink = diagramLinkHandler.getCustomLinkFromResourceReference(resourceReference);
174 - fnArgs[0] = xutils.getAttachmentURL(filename) + '#' + encodeURIComponent(customLink);
175 - fn.apply(this, fnArgs);
176 - });
177 - } else {
178 - fn.apply(this, arguments);
179 - }
180 - };
181 - }
182 - originalImportFiles.apply(this, importFilesArgs);
183 - };
184 -
185 - // Add support for inserting images by specifying the XWiki attachment reference.
186 - var originalShowImageDialog = EditorUi.prototype.showImageDialog;
187 - EditorUi.prototype.showImageDialog = function(title, value, fn, ignoreExisting, convertDataUri, withCrop,
188 - initClipPath) {
189 - var showImageDialogArgs = Array.prototype.slice.call(arguments);
190 - var customLink = diagramLinkHandler.getCustomLinkFromURL(value);
191 - if (customLink) {
192 - // Edit the XWiki custom link instead of the actual URL.
193 - showImageDialogArgs[1] = customLink;
194 - }
195 - if (typeof fn === 'function') {
196 - showImageDialogArgs[2] = function(newValue, width, height) {
197 - var fnArgs = Array.prototype.slice.call(arguments);
198 - if (diagramLinkHandler.isXWikiCustomLink(newValue)) {
199 - // Save the actual URL, but keep the custom link as fragment identifier.
200 - fnArgs[0] = diagramLinkHandler.getURLFromCustomLink(newValue) + '#' + encodeURIComponent(newValue);
201 - }
202 - fn.apply(this, fnArgs);
203 - };
204 - }
205 - originalShowImageDialog.apply(this, showImageDialogArgs);
206 - };
207 -
208 - // This function is used by the image dialog to preload the images before inserting them. We have to overwrite it in
209 - // order to make it use the actual URL for XWiki image attachments.
210 - var originalLoadImage = EditorUi.prototype.loadImage;
211 - EditorUi.prototype.loadImage = function(uri, onload, onerror) {
212 - var loadImageArgs = Array.prototype.slice.call(arguments);
213 - if (diagramLinkHandler.isXWikiCustomLink(uri)) {
214 - loadImageArgs[0] = diagramLinkHandler.getURLFromCustomLink(uri);
215 - }
216 - originalLoadImage.apply(this, loadImageArgs);
217 - };
218 -});
219 -
220 -/**
221 - * Customizes the diagram export as URL and the diagram import from URL.
222 - */
223 -define('diagram-url-io', ['diagram-utils', 'draw.io'], function(diagramUtils) {
224 - var urlParam = function(parameter, url) {
225 - var results = new RegExp('[\?&]' + parameter + '=([^&#]*)').exec(url);
226 - if (results === null) {
227 - return null;
228 - }
229 - return decodeURIComponent(results[1]);
230 - };
231 -
232 - var getParameterValueFromURL = function(parameter, url) {
233 - if (typeof URLSearchParams === 'function') {
234 - return new URL(url, window.location.href).searchParams.get(parameter);
235 - }
236 - // IE will get here since it's not supporting URLSearchParams.
237 - return urlParam(parameter, url);
238 - };
239 -
240 - // Custom diagram import from URL.
241 - var loadUrl = function(url) {
242 - var diagramXML = null;
243 - let exportedUrl = getParameterValueFromURL('url', url);
244 - if (exportedUrl) {
245 - diagramXML = diagramUtils.getDiagramXMLFromURL(exportedUrl);
246 - }
247 - return diagramXML;
248 - };
249 -
250 - // Custom diagram export as URL (using the current host).
251 - var originalCreateLink = EditorUi.prototype.createLink;
252 - EditorUi.prototype.createLink = function(linkTarget, linkColor, allPages, lightbox, editLink, layers, url, ignoreFile,
253 - params, useOpenParameter) {
254 - let rawURL = originalCreateLink.apply(this, arguments);
255 - // Do not include '#' because it's automatically added by getURL function below.
256 - let documentFragmentIndex = rawURL.indexOf('#');
257 - let documentFragment = rawURL.substring(documentFragmentIndex + 1);
258 - if (documentFragment.substring(0, 1) == 'R') {
259 - let queryString = '';
260 - let queryStringIndex = rawURL.indexOf('?');
261 - if (queryStringIndex > -1) {
262 - queryString = rawURL.substring (queryStringIndex + 1, documentFragmentIndex);
263 - }
264 - // Append source parameter to the query
265 - queryString += '&source=url';
266 - return window.location.protocol + '//' + window.location.host +
267 - new XWiki.Document('DiagramViewSheet', 'Diagram').getURL('view', queryString, documentFragment);
268 - }
269 - return rawURL;
270 - }
271 -
272 - return {
273 - loadUrl: loadUrl
274 - };
275 -});
276 -
277 -/**
278 - * In case external services are disabled, stop the features that require it (online shape search, help section
279 - * external links) and show an info dialog.
280 - */
281 -define('diagram-external-services', ['jquery', 'diagram-config', 'draw.io'], function($, diagramConfig) {
282 - var showDisabledServicesDialog = function(editorUi) {
283 - var errorMessage = $('<div></div')
284 - .html($jsontool.serialize($services.localization.render('diagram.editor.disabledExternalServices')));
285 -
286 - errorMessage.addClass('externalServicesDialog');
287 - var dlg = new CustomDialog(/*editorUi*/ editorUi, /*content*/ errorMessage[0], /*okFn*/ null, /*cancelFn*/ null,
288 - /*okButtonText*/ mxResources.get('ok'), /*helpLink*/ null, /*buttonsContent*/ null,
289 - /*hideCancel*/ true);
290 - editorUi.showDialog(dlg.container, 250, 75, true, true);
291 - };
292 -
293 - var originalIsOfflineApp = EditorUi.prototype.isOfflineApp;
294 - EditorUi.prototype.isOfflineApp = function() {
295 - return diagramConfig.disableExternalServices || originalIsOfflineApp();
296 - };
297 -});
298 -
299 -define('diagramMenuTranslations', {
300 - prefix: 'diagram.editor.menu.',
301 - keys: [
302 - // File menu.
303 - 'print.label',
304 - 'print.title'
305 - ]
306 -});
307 -
308 -/**
309 - * Integrates draw.io diagram editor in XWiki.
310 - */
311 -define('diagram-editor', [
312 - 'jquery',
313 - 'diagram-store',
314 - 'diagram-utils',
315 - 'diagram-url-io',
316 - 'diagram-config',
317 - 'xwiki-l10n!diagramMenuTranslations',
318 - 'diagram-graph-xml-filter',
319 - 'diagram-link-editor',
320 - 'diagram-image-editor',
321 - 'diagram-external-services'
322 -], function($, diagramStore, diagramUtils, diagramUrlIO, diagramConfig, l10n) {
323 - var diagramEditorKeyboardShortcutsPath = "$services.webjars.url('org.xwiki.contrib:draw.io', 'shortcuts.svg')";
324 - // These variables are used to decide if an image should be uploaded at original resolution or
325 - // should be declined for being too big.
326 - // Default values:
327 - // EditorUi.prototype.maxImageSize = 520;
328 - // EditorUi.prototype.maxImageBytes = 1000000;
329 -
1 +define('diagramEditor', ['jquery', 'diagramStore'], function($, diagramStore) {
330 330   //
331 331   // Diagram Editor Constructor.
332 332   //
333 333   var createDiagramEditor = function(options) {
334 334   options = options || {};
335 - // This is needed since we do not use drafts and it would create the file to soon, leading to the file being opened
336 - // in a new window.
337 - EditorUi.enableDrafts = false;
338 - var editor = new Editor(/* chromeless: */ uiTheme === 'min', options.themes, /* model: */ null, /* graph: */ null,
339 - /* editable: */ true);
340 - var editorUI = new App(editor, options.container);
341 - // This is usefull for debugging the diagram editor from the JavaScript console.
342 - $(editorUI.container).data('diagramEditor', editorUI).trigger('diagramEditorCreated', editorUI);
343 - // Fix the editor UI before loading the diagram because layout changes can influence the way the shapes are drawn.
344 - fixEditorUI(editorUI);
345 - fixLoadUrl(editorUI);
346 - var file = diagramStore.createFile(editorUI, options.input, options.fileName, options.documentReference);
347 - // The first letter of the file name is used to determine the storage type. Let's use 'X' for XWiki storage.
348 - editorUI.loadFile('X' + options.fileName, true, file);
7 + var editorUI = new App(new Editor(false, options.themes), options.container);
8 + var file = diagramStore.createFile(editorUI, options.input, options.fileName);
9 + editorUI.loadFile(options.fileName, true, file);
349 349   return editorUI;
350 350   };
351 351  
352 - var fixEditorUI = function(editorUI) {
353 - cleanMenu(editorUI);
354 - renameMenu(editorUI);
355 - fixKeyboardShortcutsAction(editorUI);
356 - fixEditorButtons($(editorUI.container));
357 - removeThemeButton();
358 - // These are not present on mobile.
359 - if (editorUI.menubar != null) {
360 - removeCompactModeToggle(editorUI);
361 - fixFullScreenToggle(editorUI);
362 - }
363 - };
364 -
365 - var fixLoadUrl = function(editorUI) {
366 - // Custom diagram import from URL.
367 - var originalLoadUrl = editorUI.editor.loadUrl;
368 - editorUI.editor.loadUrl = function(url, success, error, forceBinary, retry, dataUriPrefix, noBinary, headers) {
369 - var diagramXML = diagramUrlIO.loadUrl(url);
370 - if (diagramXML != null) {
371 - return success(diagramXML);
372 - }
373 - return originalLoadUrl.apply(this, arguments);
374 - };
375 - };
376 -
377 377   //
378 - // Change the service name in order to disable notifications.
14 + // Disable the tabbed UI (setting urlParams['pages'] to '0' is not enough..)
379 379   //
380 - EditorUi.prototype.getServiceName = function() {
381 - return 'xwiki.com';
16 + EditorUi.prototype.initPages = function() {
17 + // Do nothing.
382 382   };
383 383  
384 384   // Don't change the document title.
... ... @@ -388,70 +388,24 @@
388 388   // Add support for disabling an entire sub-menu.
389 389   //
390 390   var originalAddSubmenu = Menus.prototype.addSubmenu;
391 - Menus.prototype.addSubmenu = function(name, menu, parent, label) {
27 + Menus.prototype.addSubmenu = function(name, menu, parent) {
392 392   var subMenu = this.get(name);
393 - if (subMenu && subMenu.isEnabled() !== false) {
394 - return originalAddSubmenu.apply(this, arguments);
29 + if (subMenu && subMenu.visible !== false) {
30 + originalAddSubmenu.apply(this, arguments);
395 395   }
396 396   };
397 397  
398 -
399 - /*
400 - * Map with all the menu items that we want to have a title.
401 - */
402 - const titleMap = new Map([
403 - ['print', l10n['print.title']]
404 - ]);
405 -
406 - /*
407 - * Update the title of the menu items.
408 - */
409 - var originalAddMenuItem = Menus.prototype.addMenuItem;
410 - Menus.prototype.addMenuItem = function(menu, key, parent, trigger, sprite, label) {
411 - let item = originalAddMenuItem.apply(this, arguments);
412 - if (item != null && titleMap.has(key)) {
413 - item.title = titleMap.get(key);
414 - }
415 - return item;
416 - };
417 -
418 - // Remove the language picker because the diagram editor is configured to use the XWiki language.
419 - var originalCreateMenubar = Menus.prototype.createMenubar;
420 - Menus.prototype.createMenubar = function(container) {
421 - delete this.menus['language'];
422 - return originalCreateMenubar.apply(this, arguments);
423 - }
424 -
425 425   //
426 - // Add support for not displaying 'browser' option from 'Import from' sub-menu
35 + // Hide the editor footer.
427 427   //
428 - var originalAddItem = mxPopupMenu.prototype.addItem;
429 - mxPopupMenu.prototype.addItem = function(title, image, funct, parent, iconCls, enabled, active) {
430 - if (title === (mxResources.get('browser') + '...') && parent && parent.innerText === 'Import from') {
431 - return null;
432 - }
433 - return originalAddItem.apply(this, arguments);
37 + var hideFooter = function(editorUI) {
38 + // We call this just in case the footer is visible.
39 + editorUI.hideFooter();
40 + // Make sure the diagram editor doesn't leave space for the footer.
41 + editorUI.footerHeight = 0;
434 434   };
435 435  
436 436   //
437 - // Rename menu options to fit our needs.
438 - //
439 - var renameMenu = function(editorUI) {
440 - const menuItems = [
441 - // File menu
442 - ['print', l10n['print.label']]
443 - ];
444 -
445 - // Iterate over the array of tuples
446 - menuItems.forEach(function([menuKey, newLabel]) {
447 - var action = editorUI.actions.actions[menuKey];
448 - if (action) {
449 - action.label = newLabel;
450 - }
451 - });
452 - };
453 -
454 - //
455 455   // Clean the editor menu by removing the features that are not needed.
456 456   //
457 457   var cleanMenu = function(editorUI) {
... ... @@ -458,13 +458,11 @@
458 458   // Disable and hide some of the menu entries.
459 459   [
460 460   // File menu
461 - 'synchronize', 'new', 'open', 'save', 'saveAs', 'rename', 'makeCopy', 'close',
51 + 'new', 'open', 'save', 'saveAs', 'rename', 'makeCopy', 'close',
462 462   // Extras menu
463 463   'autosave', 'showStartScreen', 'plugins', 'offline', 'chromeApp',
464 - // Help menu
465 - 'downloadDesktop', 'useOffline',
466 - // ExportAs
467 - 'exportHtml', 'exportPdf'
54 + // Help menu (Graph Editor)
55 + 'help'
468 468   ].forEach(function(actionName) {
469 469   var action = editorUI.actions.actions[actionName];
470 470   if (action) {
... ... @@ -486,26 +486,51 @@
486 486   });
487 487   };
488 488  
489 - //
490 - // Fix the side bar tool tip: the tool tip position is computed as if the editor takes the full screen.
491 - //
492 - var originalGetTooltipOffset = Sidebar.prototype.getTooltipOffset;
493 - Sidebar.prototype.getTooltipOffset = function(elt, bounds) {
494 - var fullScreenCoordinates = originalGetTooltipOffset.apply(this, arguments);
495 - // Adjust the tool tip coordinates with the editor offset.
496 - var offset = $(this.editorUi.container).offsetParent().offset();
497 - return new mxPoint(fullScreenCoordinates.x + offset.left, fullScreenCoordinates.y + offset.top);
77 + // Fix the base URL used when exporting the diagram as image.
78 + var oldCreateImageUrlConverter = EditorUi.prototype.createImageUrlConverter;
79 + EditorUi.prototype.createImageUrlConverter = function() {
80 + var converter = oldCreateImageUrlConverter.call(this);
81 + converter.convert = function(src) {
82 + // Use baseDomain instead of baseUrl to detect external URLs.
83 + if (src && (src.substr(0, 7) === 'http://' || src.substr(0, 8) === 'https://') &&
84 + src.substr(0, converter.baseDomain.length) !== converter.baseDomain) {
85 + src = PROXY_URL + '?url=' + encodeURIComponent(src);
86 + }
87 + return src;
88 + };
89 + return converter;
498 498   };
499 499  
500 500   //
501 - // Consider the basePath for the shapes added in the left panel.
93 + // Fix the side bar tool tip: the tool tip position is computed as if the editor takes the full screen.
502 502   //
503 - var oldCreateVertexTemplateEntry = Sidebar.prototype.createVertexTemplateEntry;
504 - Sidebar.prototype.createVertexTemplateEntry = function(style, width, height, value, title, showLabel, showTitle,
505 - allowCellsInserted, showTooltip, clickFn, thumbWidth, thumbHeight) {
506 - style = style.replace(/(image=)(img\/lib)/g, '$1' + diagramConfig.drawIOBasePath + '$2');
507 - return oldCreateVertexTemplateEntry.call(this, style, width, height, value, title, showLabel, showTitle,
508 - allowCellsInserted, showTooltip, clickFn, thumbWidth, thumbHeight);
95 + var oldShowTooltip = Sidebar.prototype.showTooltip;
96 + Sidebar.prototype.showTooltip = function(elt) {
97 + if (this.enableTooltips && this.showTooltips && this.currentElt != elt) {
98 + // The next usage of mxUtils.bind() is to bind the (private) show function to the side bar object.
99 + // We need to overwrite the show function.
100 + var oldBind = mxUtils.bind;
101 + mxUtils.bind = function(object, method) {
102 + // Restore the original function.
103 + mxUtils.bind = oldBind;
104 + return oldBind(object, function() {
105 + var result = method.apply(this, arguments);
106 + // Adjust the tool tip coordinates because they are computed as if the editor takes the full screen.
107 + // Thus we need to add the editor offset.
108 + var offset = $(this.container).parent().offsetParent().offset();
109 + $(this.tooltip).css({
110 + left: (offset.left + parseInt(this.tooltip.style.left)) + 'px',
111 + top: (offset.top + parseInt(this.tooltip.style.top)) + 'px'
112 + });
113 + $(this.tooltipImage).css({
114 + left: (offset.left + parseInt(this.tooltipImage.style.left)) + 'px',
115 + top: (offset.top + parseInt(this.tooltipImage.style.top)) + 'px'
116 + });
117 + return result;
118 + });
119 + };
120 + }
121 + oldShowTooltip.apply(this, arguments);
509 509   };
510 510  
511 511   //
... ... @@ -514,12 +514,12 @@
514 514   var fixKeyboardShortcutsAction = function(editorUI) {
515 515   var keyboardShortcutsAction = editorUI.actions.get('keyboardShortcuts');
516 516   if (keyboardShortcutsAction) {
517 - var originalFunct = keyboardShortcutsAction.funct;
130 + var oldFunct = keyboardShortcutsAction.funct;
518 518   keyboardShortcutsAction.funct = function() {
519 519   if (mxClient.IS_SVG) {
520 - window.open(diagramEditorKeyboardShortcutsPath);
133 + window.open(diagramEditorBasePath + 'shortcuts.svg');
521 521   } else {
522 - originalFunct.apply(this, arguments);
135 + oldFunct.apply(this, arguments);
523 523   }
524 524   };
525 525   }
... ... @@ -530,7 +530,7 @@
530 530   //
531 531   var removeCompactModeToggle = function(editorUI) {
532 532   if (typeof editorUI.toggleCompactMode === 'function') {
533 - editorUI.toggleCompactMode(/* visible: */ false);
146 + editorUI.toggleCompactMode(true);
534 534   var buttons = $(editorUI.container).find('.geToolbarContainer > a.geButton');
535 535   buttons.last().remove();
536 536   buttons.css('right', function(index, value) {
... ... @@ -540,11 +540,6 @@
540 540   };
541 541  
542 542   var fullScreen = new XWiki.widgets.FullScreen();
543 - // We only call the init in versions that have the function defined so we don't get an error in the console.
544 - // The 'if' should be removed after upgrading the app to a parent >= 17.10.2.
545 - if (typeof fullScreen.initDom === 'function') {
546 - fullScreen.initDom();
547 - }
548 548   var fixFullScreenToggle = function(editorUI) {
549 549   mxEvent.removeAllListeners(editorUI.fullscreenElement);
550 550   editorUI.container._x_fullScreenActivator = editorUI.fullscreenElement;
... ... @@ -554,7 +554,7 @@
554 554   if (isFullScreen) {
555 555   // Exit full screen mode.
556 556   fullScreen.closeFullScreen();
557 - editorUI.refresh();
165 + editorUI.toggleCompactMode(true);
558 558   } else {
559 559   // Enter full screen mode.
560 560   fullScreen.makeFullScreen(editorUI.container);
... ... @@ -561,78 +561,54 @@
561 561   // The previous line hides the 'fullScreenActivator' and shows the 'Exit Full Screen' button. We want to use the
562 562   // 'fullScreenActivator' for exiting the full screen mode. The 'Exit Full Screen' button is hidden from CSS.
563 563   $(editorUI.fullscreenElement).show();
564 - editorUI.refresh();
172 + editorUI.toggleCompactMode();
565 565   }
566 566   });
567 567   };
568 568  
569 569   //
570 - // Add the type of the buttons manually to stop the default submit. The preventDefault used in editDiagram is not
571 - // working for these since in draw.io code is called stopPropagation.
572 - //
573 - var fixEditorButtons = function(editor) {
574 - editor.find('button:not([type])').each(function() {
575 - $(this).attr('type', 'button');
576 - });
577 - };
578 -
579 - var removeThemeButton = function() {
580 - $('.geAdaptiveAsset[title="Theme"]').remove();
581 - };
582 -
583 - // mxRuler adds the ruler to the document body instead of adding it to the editor container.
584 - var originalMxDualRuler = mxDualRuler;
585 - mxDualRuler = function(editorUI, unit) {
586 - originalMxDualRuler.apply(this, arguments);
587 - $([this.hRuler.container, this.vRuler.container]).appendTo(editorUI.container);
588 - };
589 - mxDualRuler.prototype = Object.create(originalMxDualRuler.prototype);
590 - mxDualRuler.prototype.constructor = mxDualRuler;
591 -
592 - var themes = {};
593 - var getDiagramEditorConfig = function(container) {
594 - var input = $(container).children('input.diagram-content');
595 - var documentReference = input.data('reference') || '';
596 - if (typeof documentReference === 'string') {
597 - documentReference = XWiki.Model.resolve(documentReference, XWiki.EntityType.DOCUMENT,
598 - XWiki.currentDocument.documentReference);
599 - }
600 - var fileName = input.data('title') || $('#document-title').text();
601 - if (!fileName) {
602 - fileName = documentReference.name == 'WebHome' ? documentReference.parent.name : documentReference.name;
603 - }
604 - return {
605 - container: container,
606 - themes: themes,
607 - fileName: fileName,
608 - input: input,
609 - documentReference: documentReference
610 - };
611 - };
612 -
613 - //
614 614   // jQuery plugin
615 615   //
180 + var themes = {};
616 616   $.fn.editDiagram = function(options) {
617 617   return this.on('click', 'button', function(event) {
618 618   // Make sure the buttons from the editor UI don't submit the edit form.
619 619   event.preventDefault();
620 - }).on('keydown keyup keypress', '.geContentEditable', function(event) {
621 - // Make sure the keyboard events triggered from the nested editable sections are not propagated as they may
622 - // trigger shortcut keys (the nested editable sections need to behave like input fields).
623 - // See issue #15: If you install XWebIDE Application you can't use "W" letter in the diagram text.
624 - event.stopPropagation();
625 625   }).each(function() {
626 - // We need this CSS class on the body element in order to have proper styling for the UI elements (menus, dialogs,
627 - // tooltips) that are added directly under the body element.
628 - $(document.body).addClass('geEditor');
629 - createDiagramEditor($.extend(getDiagramEditorConfig(this), options));
186 + var editorUI = createDiagramEditor($.extend({
187 + container: this,
188 + themes: themes,
189 + fileName: $('#document-title').text() || XWiki.currentPage,
190 + input: $(this).children('input.diagram-content')
191 + }, options));
630 630   $(this).removeClass('loading');
193 + hideFooter(editorUI);
194 + cleanMenu(editorUI);
195 + fixKeyboardShortcutsAction(editorUI);
196 + removeCompactModeToggle(editorUI);
197 + fixFullScreenToggle(editorUI);
631 631   });
632 632   };
633 633  
634 - return diagramUtils.loadTranslationAndTheme().done(function(theme) {
635 - // Configure the default editor theme.
636 - themes[Graph.prototype.defaultThemeName] = theme;
201 + //
202 + // Load the translation files.
203 + //
204 + var diagramEditorDeferred = $.Deferred();
205 + mxResources.loadDefaultBundle = false;
206 + var bundle = mxResources.getDefaultBundle(RESOURCE_BASE, mxLanguage) ||
207 + mxResources.getSpecialBundle(RESOURCE_BASE, mxLanguage);
208 + mxUtils.getAll([bundle, STYLE_PATH + '/default.xml'], function(response) {
209 + // Adds bundle text to resources.
210 + mxResources.parse(response[0].getText());
211 +
212 + // Configures the default editor theme.
213 + themes[Graph.prototype.defaultThemeName] = response[1].getDocumentElement();
214 +
215 + diagramEditorDeferred.resolve();
216 + }, function() {
217 + // Failed to load resources.
218 + diagramEditorDeferred.reject();
637 637   });
220 +
221 + return diagramEditorDeferred.promise();
638 638  });
Icon XWiki.JavaScriptExtension[3]
Code
... ... @@ -1,37 +1,5 @@
1 -/*!
2 -## Make sure that the version loaded with RequireJS is not a cached one.
3 -#set ($version = $services.extension.installed.getInstalledExtension('com.xwiki.diagram:application-diagram',
4 - "wiki:$xcontext.database").version.value)
5 -#set ($params = $escapetool.url({
6 - 'minify': $!services.debug.minify,
7 - 'appVersion': $version
8 -}))
9 -#[[*/
10 -// Start JavaScript-only code.
11 -(function(params) {
12 - "use strict";
13 -
14 -require.config({
15 - paths: {
16 - 'diagram-setup': new XWiki.Document('DiagramSheet', 'Diagram').getURL('jsx', params)
17 - },
18 - map: {
19 - 'diagram-utils': {
20 - 'mxgraph-common': 'mxgraph-editor'
21 - },
22 - 'diagram-link-handler': {
23 - 'draw.io.common': 'draw.io'
24 - }
25 - }
26 -});
27 -
28 -require(['diagram-setup'], function() {
29 - require(['jquery', 'diagram-editor'], function($, diagramEditorPromise) {
30 - diagramEditorPromise.done(function() {
31 - $('.diagram-editor').editDiagram();
32 - });
1 +require(['jquery', 'diagramEditor'], function($, diagramEditorPromise) {
2 + diagramEditorPromise.done(function() {
3 + $('.diagram-editor').editDiagram();
33 33   });
34 34  });
35 -
36 -// End JavaScript-only code.
37 -}).apply(']]#', $jsontool.serialize([$params]));
Icon XWiki.JavaScriptExtension[0]
Pufferstrategie
... ... @@ -1,0 +1,1 @@
1 +long
Code
... ... @@ -1,0 +1,84 @@
1 +// mxGraph Client Configuration
2 +var mxBasePath = "$services.webjars.url('org.xwiki.contrib:mxgraph-client', '')";
3 +var mxLanguage = '$xcontext.locale';
4 +
5 +var mxGraphEditorBasePath = "$services.webjars.url('org.xwiki.contrib:mxgraph-editor', '')";
6 +
7 +// Diagram Editor Configuration
8 +var diagramEditorBasePath = "$services.webjars.url('org.xwiki.contrib:draw.io', '')";
9 +var RESOURCES_PATH = diagramEditorBasePath + 'resources';
10 +// Comment out the following line when using the basic mxGraph Editor.
11 +var RESOURCE_BASE = RESOURCES_PATH + '/dia';
12 +var STENCIL_PATH = diagramEditorBasePath + 'stencils';
13 +var IMAGE_PATH = diagramEditorBasePath + 'images';
14 +var STYLE_PATH = CSS_PATH = diagramEditorBasePath + 'styles';
15 +
16 +var SHAPES_PATH = diagramEditorBasePath + 'shapes';
17 +var GRAPH_IMAGE_PATH = diagramEditorBasePath + 'img';
18 +var TEMPLATE_PATH = diagramEditorBasePath + 'templates';
19 +
20 +var isLocalStorage = true;
21 +
22 +var urlParams = (function(params) {
23 + var pairs = window.location.search.substr(1).split('&');
24 + pairs.forEach(function(pair) {
25 + var parts = pair.split('=', 2);
26 + if (parts.length === 2) {
27 + params[parts[0]] = decodeURIComponent(parts[1].replace(/\+/g, " "));
28 + }
29 + });
30 + return params;
31 +})({
32 + // Don't show the splash screen.
33 + 'splash': '0',
34 + // Disable the tabbed UI.
35 + 'pages': '0',
36 + // Disable the GitHub integration.
37 + 'gh': '0',
38 + // Disable the Dropbox integration.
39 + 'db': '0',
40 + // Disable the Google Drive integration.
41 + 'gapi': '0',
42 + // Disable Google Analytics.
43 + 'analytics': '0',
44 + // Disable the One Drive integration.
45 + 'od': '0'
46 +});
47 +
48 +// Disabling the integration with these external services is not enough because the draw.io code has hard-coded references.
49 +var DriveFile = DropboxFile = GitHubFile = OneDriveFile = false;
50 +
51 +require.config({
52 + paths: {
53 + 'mxgraph-init': diagramEditorBasePath + 'js/draw.io.init.min',
54 + 'mxgraph-client': mxBasePath + 'mxClient.min',
55 + 'jscolor': mxGraphEditorBasePath + 'jscolor/jscolor.min',
56 + 'sanitizer': mxGraphEditorBasePath + 'sanitizer/sanitizer.min',
57 + 'mxgraph-editor': mxGraphEditorBasePath + 'mxGraphEditor.min',
58 + 'base64': diagramEditorBasePath + 'js/deflate/base64.min',
59 + 'pako': diagramEditorBasePath + 'js/deflate/pako.min',
60 + 'spin': diagramEditorBasePath + 'js/spin/spin.min',
61 + 'draw.io': diagramEditorBasePath + 'js/draw.io.min',
62 + },
63 + shim: {
64 + 'mxgraph-client': {
65 + deps: ['mxgraph-init']
66 + },
67 + 'mxgraph-editor': {
68 + deps: ['mxgraph-client', 'jscolor', 'sanitizer']
69 + },
70 + 'draw.io': {
71 + deps: ['mxgraph-editor', 'base64', 'pako-global', 'spin-global']
72 + }
73 + }
74 +})
75 +
76 +define('pako-global', ['pako'], function(pako) {
77 + // draw.io expects a global variable.
78 + window.pako = pako;
79 +});
80 +
81 +define('spin-global', ['spin'], function(spin) {
82 + // draw.io expects a global variable.
83 + window.Spinner = spin;
84 +});
Name
... ... @@ -1,0 +1,1 @@
1 +Configuration
Inhalt parsen
... ... @@ -1,0 +1,1 @@
1 +Ja
Benutze diese Erweiterung
... ... @@ -1,0 +1,1 @@
1 +onDemand
Icon XWiki.StyleSheetExtension[0]
Pufferstrategie
... ... @@ -1,0 +1,1 @@
1 +long
Code
... ... @@ -1,0 +1,87 @@
1 +/* The diagram editor styles should be loaded after the skin and before our overwrites. */
2 +@import url("$services.webjars.url('org.xwiki.contrib:mxgraph-editor', 'styles/grapheditor.css')");
3 +
4 +.diagram-editor {
5 + height: 600px;
6 + min-height: 20px;
7 + position: relative;
8 +}
9 +
10 +.diagram-editor input[type="checkbox"], .diagram-editor input[type="radio"],
11 +.mxPopupMenu input[type="checkbox"], .mxPopupMenu input[type="radio"],
12 +.mxWindow input[type="checkbox"], .mxWindow input[type="radio"],
13 +.geDialog input[type="checkbox"], .geDialog input[type="radio"] {
14 + vertical-align: text-bottom;
15 +}
16 +
17 +.fullScreenWrapper .buttons > .buttonwrapper:first-child {
18 + /* Hide the "Exit Full Screen" button. We have a tool bar entry for this. */
19 + display: none !important;
20 +}
21 +
22 +/**
23 + * Overwrite XWiki skin styles
24 + */
25 +.diagram-editor *,
26 +.mxPopupMenu *,
27 +.mxWindow *,
28 +.geDialog,
29 +.geDialog * {
30 + box-sizing: content-box;
31 +}
32 +
33 +.mxPopupMenu,
34 +.mxWindow,
35 +.geDialog {
36 + /* We need the same font size as on draw.io because the dialog height is hard-coded. */
37 + font-size: 10pt;
38 +}
39 +
40 +.diagram-editor button, .diagram-editor select,
41 +.mxPopupMenu button, .mxPopupMenu select,
42 +.mxWindow button, .mxWindow select,
43 +.geDialog button, .geDialog select {
44 + box-sizing: border-box;
45 +}
46 +
47 +.diagram-editor input[type="text"],
48 +.mxPopupMenu input[type="text"],
49 +.mxWindow input[type="text"],
50 +.geDialog input[type="text"] {
51 + font-size: inherit;
52 + height: auto;
53 + padding: 1px;
54 +}
55 +
56 +.diagram-editor img,
57 +.mxPopupMenu img,
58 +.mxWindow img,
59 +.geDialog img {
60 + vertical-align: baseline;
61 +}
62 +
63 +.diagram-editor hr,
64 +.mxPopupMenu hr,
65 +.mxWindow hr,
66 +.geDialog hr {
67 + margin: 0;
68 +}
69 +
70 +.mxPopupMenu table,
71 +.mxWindow table,
72 +.geDialog table {
73 + margin-bottom: 0;
74 + width: auto;
75 +}
76 +
77 +.diagram-editor table > tbody > tr > td,
78 +.mxPopupMenu table > tbody > tr > td,
79 +.mxWindow table > tbody > tr > td,
80 +.geDialog table > tbody > tr > td {
81 + border-top: 0 none;
82 +}
83 +
84 +.geDialog table > tbody > tr > td {
85 + padding: 0;
86 + vertical-align: baseline;
87 +}
Content Type
... ... @@ -1,0 +1,1 @@
1 +CSS
Inhalt parsen
... ... @@ -1,0 +1,1 @@
1 +Ja
Benutze diese Erweiterung
... ... @@ -1,0 +1,1 @@
1 +onDemand