xref: /plugin/diagrams/script.js (revision a1ebce0b08b0c342962cf94edf6a3193652e713b)
1jQuery( document ).ready( function() {
2
3    const serviceUrl = 'https://embed.diagrams.net/?embed=1&proto=json&spin=1';
4    const doctypeXML = '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
5
6    // check if name/id of new diagram is valid
7    function validId(id) {
8        return id.length > 0 && /^[\w][\w\.\-]*$/.test( id )
9    }
10
11    // return URL to fetch existing diagram from DW
12    function getLocalDiagramUrl(ns, id) {
13        return DOKU_BASE + 'lib/exe/ajax.php?call=mediaupload&ow=true&ns=' + ns + '&qqfile=' + id + '&sectok=' + JSINFO['sectok'];
14    }
15
16    // split full id into ns and id parts
17    function splitFullId(fullId) {
18        let id = fullId;
19        let ns = '';
20        const idParts = id.split(':');
21        if (idParts.length > 1) {
22            ns = idParts[0];
23            id = idParts.slice(1).join(':');
24        }
25         return {ns: ns, id: id};
26    }
27
28    /**
29     * Launch diagram editor's iframe
30     *
31     * @param fullId
32     */
33    const launchEditor = function(fullId) {
34        if (!jQuery('#drawio-frame')[0]) {
35
36            jQuery('body').append('<iframe id="drawio-frame" style="border: 0;position: fixed; top: 0; left: 0; right:0; bottom: 0; width:100%; height:100%; z-index: 9999;"></iframe>');
37
38            jQuery(window).on('message', {fullId: fullId}, handleServiceMessages);
39            jQuery('#drawio-frame').attr('src', serviceUrl);
40        }
41    };
42
43    /**
44     * Handle messages from diagramming service
45     *
46     * @param e
47     */
48    const handleServiceMessages = function( e ) {
49        // get diagram info passed to the function
50        const fullId = e.data.fullId;
51        const {ns, id} = splitFullId(fullId);
52
53        const msg = JSON.parse( e.originalEvent.data );
54        const drawio = jQuery( '#drawio-frame' )[0].contentWindow;
55        if( msg.event === 'init' ) {
56            // try loading existing diagram file
57            jQuery.get(DOKU_BASE + 'lib/exe/fetch.php?media=' + fullId, function (data) {
58                drawio.postMessage(JSON.stringify({action: 'load', xml: data}), '*');
59            }, 'text')
60            .fail(function () { // catch 404, file does not exist yet locally
61                drawio.postMessage(JSON.stringify({action: 'load', xml: ''}), '*');
62            });
63        } else if ( msg.event === 'save' ) {
64            drawio.postMessage(
65                JSON.stringify( {action: 'export', format: 'xmlsvg', spin: 'Speichern' } ),
66                '*'
67            );
68        } else if ( msg.event === 'export' ) {
69            if ( msg.format !== 'svg' ) {
70                alert( 'Nicht unterstützt!' );
71            } else {
72                const datastr = doctypeXML + '\n' +
73                    decodeURIComponent( atob( msg.data.split( ',' )[1] ).split( '' ).map( function( c ) {
74                        return '%' + ( '00' + c.charCodeAt( 0 ).toString( 16 ) ).slice( -2 );
75                    } ).join( '' ) );
76                jQuery.post( getLocalDiagramUrl(ns, id), datastr )
77                    .done( function() {
78                        jQuery( window ).off( 'message', handleServiceMessages );
79                        jQuery( '#drawio-frame' ).remove();
80                        setTimeout( function() {
81                            location.reload();
82                        }, 200 );
83                    } ).fail( function() {
84                    alert( 'Fehler beim Speichern' );
85                } );
86            }
87        } else if( msg.event === 'exit' ) {
88            jQuery( window ).off( 'message', handleServiceMessages );
89            jQuery( '#drawio-frame' ).remove();
90        }
91    };
92
93    // add diagram edit button to all SVGs included in wiki pages
94    if( JSINFO['iseditor'] ) {
95        jQuery( 'img, object' ).filter( '.media, .medialeft, .mediacenter, .mediaright' ).add( 'iframe.svgpureinsert' ).each( function() {
96            const current = jQuery( this );
97            const src = this.nodeName === 'OBJECT' ? current.attr( 'data' ) : current.attr( 'src' );
98            const extension = src.split( '.' ).pop().toLowerCase();
99            if( extension === 'svg' ) {
100                const editlink = '<br><button class="drawio-btn btn btn-default btn-xs" style="clear:both" data-id="' + src.split('media=')[1].split('&')[0] + '">Editieren</button>';
101                if( current.parent()[0].nodeName === 'A' ) {
102                    current.parent().after( editlink );
103                } else {
104                    current.after( editlink );
105                }
106            }
107        } );
108    }
109
110    // attach diagram editing function to the button rendered on pages
111    jQuery( 'button.drawio-btn' ).on( 'click', function () {
112        const fullId = jQuery( this ).data( 'id' );
113        launchEditor(fullId);
114    });
115
116    // create a new diagram, triggered by click on page tools item
117    jQuery( 'a#drawio-newfile-create' ).on( 'click', function( e ) {
118        e.preventDefault();
119        const ns = NS;
120        let id = prompt( 'Name des neuen Diagramms' );
121        if( !validId(id) ) {
122            alert( 'Dateiname ist leer oder enthält ungültige Zeichen' );
123            return;
124        }
125        id += '.svg';
126        const datastr = doctypeXML +
127            '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1px" height="1px" version="1.1" content="&lt;mxfile userAgent=&quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36&quot; version=&quot;7.9.5&quot; editor=&quot;www.draw.io&quot;&gt;&lt;diagram id=&quot;8c846276-93cf-00fc-3101-d1fabb6ae99a&quot; name=&quot;Seite-1&quot;&gt;dZHBEoIgEIafhrtCNXY2q0snD51JEJjQdRBH6+nTwIyxuLB8/7+7sCCSVsPJ0EZegHGNcMQGRA4I43iDd+M2kYcjSbJ3QBjFvGkBuXpyDyNPO8V4GxgtgLaqCWEBdc0LGzBqDPShrQQddm2o4CuQF1Sv6VUxK/0rttHCz1wJOXeOI6/caHEXBrra90OYlO/l5IrOtby/lZRB/4VIhkhqAKyLqiHleprtPDaXd/yjfu5teG1/JIzBUns8BB9Ishc=&lt;/diagram&gt;&lt;/mxfile&gt;" style="background-color: rgb(255, 255, 255);"><defs/><g transform="translate(0.5,0.5)"/></svg>';
128        jQuery.post( getLocalDiagramUrl(ns, id), datastr )
129            .done( function( response ) {
130                if( response.error ) {
131                    alert( 'Fehler beim Speichern: ' + response.error );
132                } else {
133                    alert( 'Diagramm ' + response.id + ' angelegt' );
134                }
135            } ).fail( function() {
136                alert( 'Fehler beim Speichern' );
137            } );
138    } );
139
140    /**
141     * Launch the editor and create a new diagram
142     *
143     * @param event
144     */
145    function createDiagram(event) {
146        event.preventDefault();
147
148        let href;
149        // FIXME does this really work?
150        // get namespace selected in ns tree
151        $selectedNSLink = jQuery('.idx_dir.selected');
152        if ($selectedNSLink && $selectedNSLink.length > 0) {
153            href = $selectedNSLink.attr('href');
154        } else {
155            // FIXME url rewriting?
156            href = location.href;
157        }
158        const ns = extractNs(href);
159        const id = jQuery('#drawio__create-filename').val();
160
161        if (!validId(id)) {
162            alert('name is empty or contains invalid characters!');
163            return;
164        }
165
166        const fullIdArray = [ns, id];
167        launchEditor(fullIdArray.join(':') + '.svg');
168    }
169
170    // extract ns param from URL
171    function extractNs(url) {
172        urlParam = function(name) {
173            var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(url);
174            return results[1] || '';
175        };
176        return decodeURIComponent(urlParam('ns'));
177    }
178
179    // returns a diagram creation form as jQuery object
180    function newDiagramForm() {
181        currentNs = extractNs(location.href);
182        $drawioCreateForm = jQuery(
183            '<form>' +
184            '<p>Create draw.io diagram in current namespace <strong><span id="drawio__current-ns">' +
185            currentNs +
186            '</strong></span></p>' +
187            '<input type="text" name="drawio-create-filename" id="drawio__create-filename" />' +
188            '<button id="drawio__create">Create</button>' +
189            '</form>'
190        );
191
192        jQuery( $drawioCreateForm ).on( 'submit', createDiagram );
193
194        return $drawioCreateForm;
195    }
196
197    /**
198     * Full-page media manager
199     */
200    const $mm_page = jQuery('#mediamanager__page');
201    if (!$mm_page.length) return;
202
203    const $mm_tree = jQuery("#media__tree");
204    $mm_tree.prepend(newDiagramForm());
205
206    $mm_tree.find('a.idx_dir').each(function (e) {
207        const $this = jQuery( this );
208        $this.on('click', function (e) {
209            e.preventDefault();
210            ns = extractNs(e.target);
211            const $nsSpan = jQuery('#drawio__current-ns');
212            $nsSpan.text(ns);
213        });
214    });
215
216    // TODO pop-up media manager
217} );
218