1class DiagramsForm extends KeyValueForm { 2 3 /** {DiagramsView} The view of the currently selected node */ 4 #view = null; 5 6 constructor(name = 'diagrams-form', fields = []) { 7 if (fields.length === 0) { 8 fields = [ 9 { 10 label: LANG.plugins.diagrams.mediaSource, name: 'src' 11 }, 12 { 13 type: 'select', 'label': LANG.plugins.diagrams.alignment, 'options': 14 [ 15 {name: 'alignment', value: '', label: ''}, 16 {name: 'alignment', value: 'left', label: LANG.plugins.diagrams.left}, 17 {name: 'alignment', value: 'right', label: LANG.plugins.diagrams.right}, 18 {name: 'alignment', value: 'center', label: LANG.plugins.diagrams.center} 19 ] 20 } 21 ]; 22 } 23 24 super(name, fields); 25 26 this.$form.on('submit', (event) => { 27 event.preventDefault(); // prevent form submission 28 this.updateViewFromForm(); 29 this.#view.deselectNode(); 30 }); 31 32 if (!this.instance) { 33 // media manager button 34 const selectButton = document.createElement('button'); 35 selectButton.innerText = LANG.plugins.diagrams.selectSource; 36 selectButton.className = 'diagrams-btn-select'; 37 selectButton.addEventListener('click', DiagramsForm.openMediaManager); 38 this.$form.find('fieldset').prepend(selectButton); 39 window.dMediaSelect = this.mediaSelect.bind(this); 40 41 // editor button 42 const editButton = document.createElement('button'); 43 editButton.className = 'diagrams-btn-edit'; 44 editButton.id = 'diagrams__btn-edit'; 45 editButton.innerText = LANG.plugins.diagrams.editButton; 46 this.$form.find('fieldset').prepend(editButton); 47 48 editButton.addEventListener('click', event => { 49 event.preventDefault(); // prevent form submission 50 51 const url = this.#view.node.attrs.url; 52 const mediaid = this.#view.node.attrs.id; 53 54 if(this.#view.node.attrs.type === 'mediafile') { 55 const diagramsEditor = new DiagramsEditor(this.onSavedMediaFile.bind(this, url)); 56 diagramsEditor.editMediaFile(mediaid); 57 } else { 58 const diagramsEditor = new DiagramsEditor(); 59 diagramsEditor.editMemory(url, this.onSaveEmbed.bind(this)); 60 } 61 62 }); 63 } 64 65 return this.instance; 66 } 67 68 /** 69 * Update the form to reflect the new selected nodeView 70 * 71 * @param {DiagramsView} view 72 */ 73 updateFormFromView(view) { 74 this.#view = view; 75 76 // update form fields to reflect new node 77 78 this.$form.find('[name="src"]').val(view.node.attrs.id); 79 80 // this.dForm.setWidth(view.node.attrs.width); 81 // this.dForm.setHeight(view.node.attrs.height); 82 83 84 const align = view.node.attrs.align; 85 this.$form.find('[name="alignment"]').prop('selected', ''); 86 this.$form.find(`[name="alignment"][value="${align}"]`).prop('selected', 'selected'); 87 } 88 89 updateViewFromForm() { 90 const newAttrs = this.getAttributes(); 91 console.log('updateViewFromForm', newAttrs); 92 this.#view.dispatchNodeUpdate(newAttrs); 93 } 94 95 getAttributes() { 96 const attrs = {}; 97 attrs.id = this.$form.find('[name="src"]').val(); 98 attrs.align = this.$form.find('[name="alignment"]:selected').val(); 99 attrs.type = this.#view.node.attrs.type; 100 101 // fixme this is only correct for media files 102 if(this.#view.node.attrs.type === 'embed') { 103 attrs.url = this.#view.node.attrs.url; // keep the data uri 104 } else { 105 attrs.url = `${DOKU_BASE}lib/exe/fetch.php?cache=nocache&media=` + attrs.id; 106 } 107 return attrs; 108 } 109 110 111 /** 112 * After svaing a media file reload the src for all images using it 113 * 114 * @see https://stackoverflow.com/a/66312176 115 * @param {string} url 116 * @returns {Promise<void>} 117 */ 118 async onSavedMediaFile(url) { 119 await fetch(url, {cache: 'reload', mode: 'no-cors'}); 120 document.body.querySelectorAll(`img[src='${url}']`) 121 .forEach(img => img.src = url) 122 } 123 124 /** 125 * Save an embedded diagram back to the editor 126 */ 127 onSaveEmbed(svg) { 128 // FIXME how do we update the diagram? 129 const url = 'data:image/svg+xml;base64,' + btoa(svg); 130 131 this.#view.node.attrs.url = url; 132 this.updateViewFromForm(); 133 134 return true; 135 } 136 137 setEditButtonUrl(id, url) { 138 const $editButton = jQuery(this.$form.find('#diagrams__btn-edit')); 139 // FIXME show/hide button depending on set url 140 $editButton.attr('data-id', id); 141 $editButton.attr('data-url', url); 142 } 143 144 setSource(id = '') { 145 this.$form.find('[name="src"]').val(id); 146 } 147 148 getSource() { 149 return this.$form.find('[name="src"]').val(); 150 } 151 152 setAlignment(align = '') { 153 } 154 155 getAlignment() { 156 return this.$form.find('[name="alignment"]:checked').val(); 157 } 158 159 resetForm() { 160 this.setSource(); 161 this.setAlignment(); 162 } 163 164 static resolveSubmittedLinkData(initialAttrs, $diagramsForm, callback) { 165 return (event) => { 166 event.preventDefault(); 167 const newAttrs = { ...initialAttrs }; 168 newAttrs.id = $diagramsForm.getSource(); 169 // FIXME is this conditional? 170 newAttrs.url = `${DOKU_BASE}lib/exe/fetch.php?cache=nocache&media=` + $diagramsForm.getSource(); 171 newAttrs.align = $diagramsForm.getAlignment(); 172 173 callback(newAttrs); 174 }; 175 } 176 177 static openMediaManager() { 178 window.open( 179 `${DOKU_BASE}lib/exe/mediamanager.php?ns=${encodeURIComponent(JSINFO.namespace)}&onselect=dMediaSelect`, 180 'mediaselect', 181 'width=750,height=500,left=20,top=20,scrollbars=yes,resizable=yes', 182 ); 183 } 184 185 mediaSelect(edid, mediaid, opts, align) { 186 this.setSource(mediaid); 187 } 188} 189