Added image paste and drop to markdown editor
Only currently tested in chrome. Closes #128
Showing
2 changed files
with
82 additions
and
3 deletions
| ... | @@ -370,6 +370,83 @@ module.exports = function (ngApp, events) { | ... | @@ -370,6 +370,83 @@ module.exports = function (ngApp, events) { |
| 370 | }); | 370 | }); |
| 371 | }); | 371 | }); |
| 372 | 372 | ||
| 373 | + // Upload and insert image on paste | ||
| 374 | + function editorPaste(e) { | ||
| 375 | + e = e.originalEvent; | ||
| 376 | + if (!e.clipboardData) return | ||
| 377 | + var items = e.clipboardData.items; | ||
| 378 | + if (!items) return; | ||
| 379 | + for (var i = 0; i < items.length; i++) { | ||
| 380 | + uploadImage(items[i].getAsFile()); | ||
| 381 | + } | ||
| 382 | + } | ||
| 383 | + | ||
| 384 | + input.on('paste', editorPaste); | ||
| 385 | + | ||
| 386 | + // Handle image drop, Uploads images to BookStack. | ||
| 387 | + function handleImageDrop(event) { | ||
| 388 | + event.stopPropagation(); | ||
| 389 | + event.preventDefault(); | ||
| 390 | + let files = event.originalEvent.dataTransfer.files; | ||
| 391 | + for (let i = 0; i < files.length; i++) { | ||
| 392 | + uploadImage(files[i]); | ||
| 393 | + } | ||
| 394 | + } | ||
| 395 | + | ||
| 396 | + input.on('drop', handleImageDrop); | ||
| 397 | + | ||
| 398 | + // Handle image upload and add image into markdown content | ||
| 399 | + function uploadImage(file) { | ||
| 400 | + if (file.type.indexOf('image') !== 0) return; | ||
| 401 | + var formData = new FormData(); | ||
| 402 | + var ext = 'png'; | ||
| 403 | + var xhr = new XMLHttpRequest(); | ||
| 404 | + | ||
| 405 | + if (file.name) { | ||
| 406 | + var fileNameMatches = file.name.match(/\.(.+)$/); | ||
| 407 | + if (fileNameMatches) { | ||
| 408 | + ext = fileNameMatches[1]; | ||
| 409 | + } | ||
| 410 | + } | ||
| 411 | + | ||
| 412 | + // Insert image into markdown | ||
| 413 | + let id = "image-" + Math.random().toString(16).slice(2); | ||
| 414 | + let selectStart = input[0].selectionStart; | ||
| 415 | + let selectEnd = input[0].selectionEnd; | ||
| 416 | + let content = input[0].value; | ||
| 417 | + let selectText = content.substring(selectStart, selectEnd); | ||
| 418 | + let placeholderImage = `/loading.gif#upload${id}`; | ||
| 419 | + let innerContent = ((selectEnd > selectStart) ? `![${selectText}]` : '![]') + `(${placeholderImage})`; | ||
| 420 | + input[0].value = content.substring(0, selectStart) + innerContent + content.substring(selectEnd); | ||
| 421 | + | ||
| 422 | + input.focus(); | ||
| 423 | + input[0].selectionStart = selectStart; | ||
| 424 | + input[0].selectionEnd = selectStart; | ||
| 425 | + | ||
| 426 | + let remoteFilename = "image-" + Date.now() + "." + ext; | ||
| 427 | + formData.append('file', file, remoteFilename); | ||
| 428 | + formData.append('_token', document.querySelector('meta[name="token"]').getAttribute('content')); | ||
| 429 | + | ||
| 430 | + xhr.open('POST', window.baseUrl('/images/gallery/upload')); | ||
| 431 | + xhr.onload = function () { | ||
| 432 | + let selectStart = input[0].selectionStart; | ||
| 433 | + if (xhr.status === 200 || xhr.status === 201) { | ||
| 434 | + var result = JSON.parse(xhr.responseText); | ||
| 435 | + input[0].value = input[0].value.replace(placeholderImage, result.url); | ||
| 436 | + input.change(); | ||
| 437 | + } else { | ||
| 438 | + console.log('An error occurred uploading the image'); | ||
| 439 | + console.log(xhr.responseText); | ||
| 440 | + input[0].value = input[0].value.replace(innerContent, ''); | ||
| 441 | + input.change(); | ||
| 442 | + } | ||
| 443 | + input.focus(); | ||
| 444 | + input[0].selectionStart = selectStart; | ||
| 445 | + input[0].selectionEnd = selectStart; | ||
| 446 | + }; | ||
| 447 | + xhr.send(formData); | ||
| 448 | + } | ||
| 449 | + | ||
| 373 | } | 450 | } |
| 374 | } | 451 | } |
| 375 | }]); | 452 | }]); | ... | ... |
| 1 | "use strict"; | 1 | "use strict"; |
| 2 | 2 | ||
| 3 | -function editorPaste(e) { | 3 | +function editorPaste(e, editor) { |
| 4 | if (!e.clipboardData) return | 4 | if (!e.clipboardData) return |
| 5 | var items = e.clipboardData.items; | 5 | var items = e.clipboardData.items; |
| 6 | if (!items) return; | 6 | if (!items) return; |
| ... | @@ -32,7 +32,7 @@ function editorPaste(e) { | ... | @@ -32,7 +32,7 @@ function editorPaste(e) { |
| 32 | var result = JSON.parse(xhr.responseText); | 32 | var result = JSON.parse(xhr.responseText); |
| 33 | editor.dom.setAttrib(id, 'src', result.url); | 33 | editor.dom.setAttrib(id, 'src', result.url); |
| 34 | } else { | 34 | } else { |
| 35 | - console.log('An error occured uploading the image'); | 35 | + console.log('An error occurred uploading the image'); |
| 36 | console.log(xhr.responseText); | 36 | console.log(xhr.responseText); |
| 37 | editor.dom.remove(id); | 37 | editor.dom.remove(id); |
| 38 | } | 38 | } |
| ... | @@ -181,6 +181,8 @@ var mceOptions = module.exports = { | ... | @@ -181,6 +181,8 @@ var mceOptions = module.exports = { |
| 181 | }); | 181 | }); |
| 182 | 182 | ||
| 183 | // Paste image-uploads | 183 | // Paste image-uploads |
| 184 | - editor.on('paste', editorPaste); | 184 | + editor.on('paste', function(event) { |
| 185 | + editorPaste(event, editor); | ||
| 186 | + }); | ||
| 185 | } | 187 | } |
| 186 | }; | 188 | }; |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or sign in to post a comment