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