ProcessWire Upload Formular mit Drag and Drop: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
Zeile 1: Zeile 1:
 
Dies ist die Fortsetzung von [[ProcessWire Upload Formular mit AJAX]] und damit der dritte Teil der Upload Formular-Serie.
 
Dies ist die Fortsetzung von [[ProcessWire Upload Formular mit AJAX]] und damit der dritte Teil der Upload Formular-Serie.
  
Diesesmal möchten wir das Upload Formular um eine Drag and Drop Area erweitern.
+
Links
 +
https://www.smashingmagazine.com/2018/01/drag-drop-file-uploader-vanilla-js/ Anleitung für Dieses Tutorial
 +
https://www.ab-heute-programmieren.de/drag-and-drop-upload-mit-html5/ Schönes Beispiel mit einfacherem aber kompatibleren Code.
 +
 
 +
Dieses mal möchten wir das Upload Formular um eine Drag and Drop Area erweitern.
  
 
== Drag and Drop Events ==
 
== Drag and Drop Events ==
 +
=== Einführung ===
 
Es gibt acht Events die der Browser abfeuert:  
 
Es gibt acht Events die der Browser abfeuert:  
 
  drag, dragend, dragenter, dragexit, dragleave, dragover, dragstart, drop
 
  drag, dragend, dragenter, dragexit, dragleave, dragover, dragstart, drop
Zeile 10: Zeile 15:
 
Nur für Seitenelemente wichtig sind die gezogen werden. Wir ziehen Elemente aus dem Dateisystem, daher brauchen wir diese nicht.
 
Nur für Seitenelemente wichtig sind die gezogen werden. Wir ziehen Elemente aus dem Dateisystem, daher brauchen wir diese nicht.
  
== Drop Area ==
+
Damit man die Events nutzen kann, registriert man ganz normal Handler.
Wir ergänzen einen Bereich #drop-area in die der User seine Dateien ziehen kann.
 
<div id="drop-area">
 
  <label for="images" id="images-label">Bilder</label><br/>
 
  <input type="file" name="images[]" id="images" multiple="multiple" size="40" accept="image/jpg,image/jpeg,image/gif,image/png"/>
 
</div>
 
 
 
== Handler ==
 
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
// DROP area  
 
// DROP area  
Zeile 30: Zeile 28:
  
 
Damit der Browser nachher auch die Datei hochlädt und nicht im öffnet, muss man auch noch mit event.preventDefault() in jedem Listener das Standardverhalten unterbinden.
 
Damit der Browser nachher auch die Datei hochlädt und nicht im öffnet, muss man auch noch mit event.preventDefault() in jedem Listener das Standardverhalten unterbinden.
 +
=== Handler für die Drop Area ===
 +
<syntaxhighlight lang="javascript">
 +
let dropArea = document.getElementById("drop-area")
 +
 +
// Prevent default drag behaviors
 +
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
 +
  dropArea.addEventListener(eventName, preventDefaults, false) 
 +
  document.body.addEventListener(eventName, preventDefaults, false)
 +
})
 +
</syntaxhighlight>
 +
 +
== HTML Drop Area ==
 +
Wir ergänzen einen Bereich #drop-area in die der User seine Dateien ziehen kann.
 +
 +
Außerdem bauen wir noch ein onchange Event ein. Dazu später mehr.
 +
<syntaxhighlight lang="html5">
 +
<div id="drop-area">
 +
  <input id="fileElem" type="file"  onchange="handleFiles(this.files)" name="images[]" id="images" multiple="multiple" size="40" accept="image/jpg,image/jpeg,image/gif,image/png"/>
 +
  <label for="fileElem" id="images-label">Select Images</label><br/>
 +
</div>
 +
</syntaxhighlight>
 +
  
 
=== JS ===
 
=== JS ===

Version vom 16. Februar 2019, 13:18 Uhr

Dies ist die Fortsetzung von ProcessWire Upload Formular mit AJAX und damit der dritte Teil der Upload Formular-Serie.

Links

https://www.smashingmagazine.com/2018/01/drag-drop-file-uploader-vanilla-js/ Anleitung für Dieses Tutorial
https://www.ab-heute-programmieren.de/drag-and-drop-upload-mit-html5/ Schönes Beispiel mit einfacherem aber kompatibleren Code.

Dieses mal möchten wir das Upload Formular um eine Drag and Drop Area erweitern.

Drag and Drop Events

Einführung

Es gibt acht Events die der Browser abfeuert:

drag, dragend, dragenter, dragexit, dragleave, dragover, dragstart, drop

Wobei

drag, dragend, dragexit und dragstart

Nur für Seitenelemente wichtig sind die gezogen werden. Wir ziehen Elemente aus dem Dateisystem, daher brauchen wir diese nicht.

Damit man die Events nutzen kann, registriert man ganz normal Handler.

// DROP area 
dropArea = document.getElementById('drop-area');
dropArea.addEventListener('dragenter', handlerFunction, false);
dropArea.addEventListener('dragleave', handlerFunction, false);
dropArea.addEventListener('dragover', handlerFunction, false);
dropArea.addEventListener('drop', handlerFunction, false);

Interessant hier. Wenn man über ein Kindelement der #drop-area zieht wird für die drop-area dragleave gefeuert und für das Kindelement dragenter. Wen man jetzt den Mausbutton losläßt wird trotzdem das dropevent für die drop-area gefeuert, weil sich der drag Event nach oben durchpropagiert.

Damit der Browser nachher auch die Datei hochlädt und nicht im öffnet, muss man auch noch mit event.preventDefault() in jedem Listener das Standardverhalten unterbinden.

Handler für die Drop Area

let dropArea = document.getElementById("drop-area")

// Prevent default drag behaviors
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
  dropArea.addEventListener(eventName, preventDefaults, false)   
  document.body.addEventListener(eventName, preventDefaults, false)
})

HTML Drop Area

Wir ergänzen einen Bereich #drop-area in die der User seine Dateien ziehen kann.

Außerdem bauen wir noch ein onchange Event ein. Dazu später mehr.

<div id="drop-area">
  <input id="fileElem" type="file"  onchange="handleFiles(this.files)" name="images[]" id="images" multiple="multiple" size="40" accept="image/jpg,image/jpeg,image/gif,image/png"/>
  <label for="fileElem" id="images-label">Select Images</label><br/>
</div>


JS

// ************************ Drag and drop ***************** //
let dropArea = document.getElementById("drop-area")

// Prevent default drag behaviors
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
  dropArea.addEventListener(eventName, preventDefaults, false)   
  document.body.addEventListener(eventName, preventDefaults, false)
})

// Highlight drop area when item is dragged over it
;['dragenter', 'dragover'].forEach(eventName => {
  dropArea.addEventListener(eventName, highlight, false)
})

;['dragleave', 'drop'].forEach(eventName => {
  dropArea.addEventListener(eventName, unhighlight, false)
})

// Handle dropped files
dropArea.addEventListener('drop', handleDrop, false)

function preventDefaults (e) {
  e.preventDefault()
  e.stopPropagation()
}

function highlight(e) {
  dropArea.classList.add('highlight')
}

function unhighlight(e) {
  dropArea.classList.remove('active')
}

function handleDrop(e) {
  var dt = e.dataTransfer
  var files = dt.files

  handleFiles(files)
}

let uploadProgress = []
let progressBar = document.getElementById('progress-bar')

function initializeProgress(numFiles) {
  progressBar.value = 0
  uploadProgress = []

  for(let i = numFiles; i > 0; i--) {
    uploadProgress.push(0)
  }
}

function updateProgress(fileNumber, percent) {
  uploadProgress[fileNumber] = percent
  let total = uploadProgress.reduce((tot, curr) => tot + curr, 0) / uploadProgress.length
  console.debug('update', fileNumber, percent, total)
  progressBar.value = total
}

function handleFiles(files) {
  files = [...files]
  initializeProgress(files.length)
  files.forEach(uploadFile)
  files.forEach(previewFile)
}

function previewFile(file) {
  let reader = new FileReader()
  reader.readAsDataURL(file)
  reader.onloadend = function() {
    let img = document.createElement('img')
    img.src = reader.result
    document.getElementById('gallery').appendChild(img)
  }
}

function uploadFile(file, i) {
  var url = 'https://api.cloudinary.com/v1_1/joezimim007/image/upload'
  var xhr = new XMLHttpRequest()
  var formData = new FormData()
  xhr.open('POST', url, true)
  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')

  // Update progress (can be used to show progress indicator)
  xhr.upload.addEventListener("progress", function(e) {
    updateProgress(i, (e.loaded * 100.0 / e.total) || 100)
  })

  xhr.addEventListener('readystatechange', function(e) {
    if (xhr.readyState == 4 && xhr.status == 200) {
      updateProgress(i, 100) // <- Add this
    }
    else if (xhr.readyState == 4 && xhr.status != 200) {
      // Error. Inform the user
    }
  })

  formData.append('upload_preset', 'ujpu6gyk')
  formData.append('file', file)
  xhr.send(formData)
}

CSS

/* Drop Area */
#drop-area{
	border: 2px dashed #ddd;
	border-radius: 12px;
	min-width: 200px;
	margin: 50px 0;
	padding: 12px;
	background: #FFF;
}
#drop-area.highlight{
	border-color: purple;
}
#gallery{
	margin-top: 12px;
}
#gallery img{
	width: 150px;
	margin: 5px;
}