Skip to content

Instantly share code, notes, and snippets.

@RomainMazB
Last active September 12, 2022 11:07
Show Gist options
  • Select an option

  • Save RomainMazB/b93fa2d1df7f93730c2f67ef13a6bed6 to your computer and use it in GitHub Desktop.

Select an option

Save RomainMazB/b93fa2d1df7f93730c2f67ef13a6bed6 to your computer and use it in GitHub Desktop.
Exemple of implementation for sunlab/wn-forumupload-plugin
<!-- Needed to postpone deferred bindings -->
<input type="hidden" id="session-key" />
<!-- A basic textarea which will listen for drag'n'drop events -->
<textarea id="post-content"></textarea>
<!-- A paragraph to display upload guide -->
<p id="upload-informations"></p>
{% put scripts %}
<script>
window.addEventListener('DOMContentLoaded', function() {
initFileDrop('#post-content', '#upload-informations', '#session-key')
})
</script>
{% endput %}
const initialText = "🖼️ Drag'n'Drop files directly to the text field to upload them."
function dropHandler(ev, $dropZoneEl, $textZoneEl, $sessionKeyEl) {
let files = []
let dataTransfer = ev.originalEvent.dataTransfer
/**
* Multi-browser supports, see: https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop#process_the_drop
*/
if (dataTransfer.items) {
[...dataTransfer.items].forEach(item => {
if (item.kind === 'file')
files.push(item.getAsFile())
})
} else {
files = dataTransfer.files
}
$.request('onFileUpload', {
/**
* Adds a beforeSend callback to inject some "loading strings" into the textarea.
*/
beforeSend: () => {
files.forEach(file => {
let curPos = $dropZoneEl.selectionStart ?? 0
let textareaValue = $dropZoneEl.value
let textToInsert = getLoadingStringFor(file.name) + "\r\n"
$dropZoneEl.value =textareaValue.slice(0,curPos)+textToInsert+textareaValue.slice(curPos)
})
displayDropText('Processing upload...', $textZoneEl)
},
files: true,
data: {
...files,
sessionKey: $sessionKeyEl.value
},
success: (data) => {
// Store the session key to postpone the deferred bindings
$sessionKeyEl.value = data.sessionKey
// Replace the "loading strings" by the definitive markdown image insertion
data.files.forEach(file => {
let dropZoneCurrentVal = $dropZoneEl.value
$dropZoneEl.value = dropZoneCurrentVal.replace(getLoadingStringFor(file.originalName), getMarkdownStringFor(file.name, file.url))
})
displayDropText(initialText, $textZoneEl)
}
})
ev.preventDefault()
}
/**
* Add a onDragOver event to support file drop,
* see: https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop#prevent_the_browsers_default_drag_behavior
* @param ev
*/
function dragOverHandler(ev) {
ev.preventDefault()
}
/**
* Updates the informational text
* @param ev
* @param $textZoneEl
*/
function dragEnterHandler(ev, $textZoneEl) {
displayDropText('Drop the files to upload them.', $textZoneEl)
ev.preventDefault()
}
/**
* Reinitialize the informational text to its default value
* @param ev
* @param $textZoneEl
*/
function dragLeaveHandler(ev, $textZoneEl) {
displayDropText(initialText, $textZoneEl)
ev.preventDefault()
}
/**
* Update the informational text
* @param text
* @param $textZoneEl
*/
function displayDropText(text, $textZoneEl) {
$textZoneEl.value = text
}
/**
* Return the markdown loading string
* @param filename
* @returns {string}
*/
function getLoadingStringFor(filename) {
return getMarkdownStringFor('Processing upload: '+ filename + '...')
}
/**
* Return the markdown equivalent for a filename and url
* @param filename
* @param url
* @returns {string}
*/
function getMarkdownStringFor(filename, url = '') {
return '!['+ filename + '](' + url + ')'
}
/**
* Initialize the textarea drag n drop events.
* @param dropZoneSelector
* @param textZoneSelector
* @param sessionKeySelector
*/
function initFileDrop(dropZoneSelector, textZoneSelector, sessionKeySelector) {
let $dropZone = $(dropZoneSelector),
$dropZoneEl = $dropZone.get(0),
$sessionKeyEl = $(sessionKeySelector).get(0),
$textZoneEl = $(textZoneSelector).get(0)
$dropZone.on('drop', ev => dropHandler(ev, $dropZoneEl, $textZoneEl, $sessionKeyEl))
$dropZone.on('dragover', dragOverHandler)
$dropZone.on('dragenter', ev => dragEnterHandler(ev, $textZoneEl))
$dropZone.on('dragleave', ev => dragLeaveHandler(ev, $textZoneEl))
// Set the informational text to its default value
displayDropText(initialText, $textZoneEl)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment