首页 > 解决方案 > jQuery - 具有多个实例的文件上传器

问题描述

我正在尝试将工作的 codepen 从 Javascript 转换为 jQuery,以便运行图像上传器的多个实例。问题可能是我尝试迭代每一个.item,但也可能是从addEventListener到的转换.on()https://codepen.io/moofawsaw/pen/dyPdpGy

我在转换中哪里出错了?

这是我尝试的 jQuery 转换(不工作):

$(document).ready(function() {
  function ekUpload() {
    var $item = $(".item");

    function fileDragHover(e) {
      var fileDrag = $item.find(".file-drag");

      e.stopPropagation();
      e.preventDefault();

      fileDrag.className =
        e.type === "dragover" ? "hover" : "modal-body file-upload";
    }

    async function fileSelectHandler(e) {
      // Fetch FileList object
      var files = e.target.files || e.dataTransfer.files;

      // Cancel event and hover styling
      fileDragHover(e);

      // Process all File objects
      for (let i = 0; i < files.length; i++) {
        const f = files[i];
        if (await hasAlpha(f)) {
          console.log("Selected image is transparent");
          parseFile(f);
          uploadFile(f);
        } else {
          console.log("Selected image is not transparent");
          $item.find(".response").removeClass("hidden");
          $item.find(".error-image").removeClass("hidden");
          $item.find(".file-image").addClass("hidden");
          output(
            '<strong class="warning">Image background is not transparent</strong>'
          );
        }
      }
    }
    // Output
    function output(msg) {
      // Response
      var m = $item.find(".messages");
      m.innerHTML = msg;
    }

    function Init() {
      console.log("Upload Initialised");

      var fileSelect = $item.find(".file-upload"),
        fileDrag = $item.find(".file-drag"),
        submitButton = $item.find(".submit-button");

      fileSelect.on("change", function(e) {
        fileSelectHandler(e);
      });

      // Is XHR2 available?
      var xhr = new XMLHttpRequest();
      if (xhr.upload) {
        // File Drop
        fileDrag.on("change dragleave", function(e) {
          fileDragHover(e);
        });
        fileDrag.on("drop", function(e) {
          fileSelectHandler(e);
        });
      }
    }

    function hasAlpha(file) {
      return new Promise((resolve, reject) => {
        let hasAlpha = false;
        const canvas = $item.find("canvas");
        const ctx = canvas.getContext("2d");

        const img = new Image();
        img.crossOrigin = "Anonymous";
        img.onerror = reject;
        img.onload = function() {
          canvas.width = img.width;
          canvas.height = img.height;

          ctx.drawImage(img, 0, 0);
          const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
            .data;

          for (let j = 0; j < imgData.length; j += 4) {
            if (imgData[j + 3] < 255) {
              hasAlpha = true;
              break;
            }
          }
          resolve(hasAlpha);
        };
        img.src = URL.createObjectURL(file);
      });
    }

    function parseFile(file) {
      console.log(file.name);
      output("<strong>" + encodeURI(file.name) + "</strong>");

      // var fileType = file.type;
      // console.log(fileType);
      var imageName = file.name;

      var isGood = /\.(?=svg|jpg|png|jpeg)/gi.test(imageName);
      if (isGood) {
        $item.find(".start").addClass("hidden");
        $item.find(".response").removeClass("hidden");
        $item.find(".notimage").addClass("hidden");
        // Thumbnail Preview
        $item.find(".error-image").addClass("hidden");
        $item.find(".file-image").removeClass("hidden");
        $item.find(".file-image").src = URL.createObjectURL(file);
      } else {
        $item.find(".error-image").removeClass("hidden");
        $item.find(".file-image").addClass("hidden");
        $item.find(".notimage").removeClass("hidden");
        $item.find(".start").removeClass("hidden");
        $item.find(".response").addClass("hidden");
        $item.find(".file-upload-form").reset();
      }
    }

    function uploadFile(file) {
      var xhr = new XMLHttpRequest(),
        fileInput = $this.find(".class-roster-file"),
        fileSizeLimit = 1024; // In MB

      if (xhr.upload) {
        // Check if file is less than x MB
        if (file.size <= fileSizeLimit * 1024 * 1024) {
          // File received / failed
          xhr.onreadystatechange = function(e) {
            if (xhr.readyState == 4) {
              // Everything is good!
              // document.location.reload(true);
            }
          };

          // Start upload
          xhr.open(
            "POST",
            document.getElementById("file-upload-form").action,
            true
          );
          xhr.setRequestHeader("X-File-Name", file.name);
          xhr.setRequestHeader("X-File-Size", file.size);
          xhr.setRequestHeader("Content-Type", "multipart/form-data");
          xhr.send(file);
        } else {
          output("Please upload a smaller file (< " + fileSizeLimit + " MB).");
        }
      }
    }

    // Check for the various File API support.
    if (window.File && window.FileList && window.FileReader) {
      Init();
    } else {
      $item.find("file-drag").css("display", "none");
    }
  }
  $(".item").each(function() {
    ekUpload();
  });
});
@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css);
@import url("https://fonts.googleapis.com/css?family=Roboto");
html,
body,
* {
  box-sizing: border-box;
  font-size: 16px;
}

html,
body {
  height: 100%;
  text-align: center;
}

body {
  padding: 2rem;
  background: #f8f8f8;
}

h2 {
  font-family: "Roboto", sans-serif;
  font-size: 26px;
  line-height: 1;
  color: #454cad;
  margin-bottom: 0;
}

p {
  font-family: "Roboto", sans-serif;
  font-size: 18px;
  color: #5f6982;
}

.uploader {
  display: block;
  clear: both;
  margin: 0 auto;
  width: 100%;
  max-width: 600px;
}

.uploader label {
  float: left;
  clear: both;
  width: 100%;
  padding: 2rem 1.5rem;
  text-align: center;
  background: #fff;
  border-radius: 7px;
  border: 3px solid #eee;
  transition: all .2s ease;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.uploader label:hover {
  border-color: #454cad;
}

.uploader label.hover {
  border: 3px solid #454cad;
  box-shadow: inset 0 0 0 6px #eee;
}

.uploader label.hover #start i.fa {
  -webkit-transform: scale(0.8);
  transform: scale(0.8);
  opacity: 0.3;
}

.uploader #start {
  float: left;
  clear: both;
  width: 100%;
}

.uploader #start.hidden {
  display: none;
}

.uploader #start i.fa {
  font-size: 50px;
  margin-bottom: 1rem;
  transition: all .2s ease-in-out;
}

.uploader #response {
  float: left;
  clear: both;
  width: 100%;
}

.uploader #response.hidden {
  display: none;
}

.uploader #response #messages {
  margin-bottom: .5rem;
}

.uploader #file-image {
  display: inline;
  margin: 0 auto .5rem auto;
  width: auto;
  height: auto;
  max-width: 180px;
}

.uploader #file-image.hidden {
  display: none;
}

.uploader #notimage {
  display: block;
  float: left;
  clear: both;
  width: 100%;
}

.uploader #notimage.hidden {
  display: none;
}

.uploader progress,
.uploader .progress {
  display: inline;
  clear: both;
  margin: 0 auto;
  width: 100%;
  max-width: 180px;
  height: 8px;
  border: 0;
  border-radius: 4px;
  background-color: #eee;
  overflow: hidden;
}

.uploader .progress[value]::-webkit-progress-bar {
  border-radius: 4px;
  background-color: #eee;
}

.uploader .progress[value]::-webkit-progress-value {
  background: linear-gradient(to right, #393f90 0%, #454cad 50%);
  border-radius: 4px;
}

.uploader .progress[value]::-moz-progress-bar {
  background: linear-gradient(to right, #393f90 0%, #454cad 50%);
  border-radius: 4px;
}

.uploader input[type="file"] {
  display: none;
}

.uploader div {
  margin: 0 0 .5rem 0;
  color: #5f6982;
}

.uploader .btn {
  display: inline-block;
  margin: .5rem .5rem 1rem .5rem;
  clear: both;
  font-family: inherit;
  font-weight: 700;
  font-size: 14px;
  text-decoration: none;
  text-transform: initial;
  border: none;
  border-radius: .2rem;
  outline: none;
  padding: 0 1rem;
  height: 36px;
  line-height: 36px;
  color: #fff;
  transition: all 0.2s ease-in-out;
  box-sizing: border-box;
  background: #454cad;
  border-color: #454cad;
  cursor: pointer;
}

.uploader input[type="file"],
.hidden {
  display: none;
}

.warning {
  color: red;
  font-weight: bold;
}

canvas {
  position: absolute;
  top: -2000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Upload  -->
<div class="item">
  <form class="uploader file-upload-form">
    <input class="file-upload" type="file" name="fileUpload" accept="image/*" />
    <label for="file-upload" class="file-drag">
    <img src="#" alt="Preview" class="file-image hidden">
    <img src="https://cdn3.iconfinder.com/data/icons/online-states/150/Snooze-512.png" class="error-image hidden">
    <div class="start">
      <i class="fa fa-download" aria-hidden="true"></i>
      <div>Select a file or drag here</div>
      <div class="notimage hidden">Please select an image</div>
    </div>
    <div class="response hidden">
      <div class="messages"></div>
    </div>
  </label>
  </form>
  <div class="filename"></div>
  <canvas></canvas>
</div>
<div class="item">
  <form class="uploader file-upload-form">
    <input class="file-upload" type="file" name="fileUpload" accept="image/*" />
    <label for="file-upload" class="file-drag">
    <img src="#" alt="Preview" class="file-image hidden">
    <img src="https://cdn3.iconfinder.com/data/icons/online-states/150/Snooze-512.png" class="error-image hidden">
    <div class="start">
      <i class="fa fa-download" aria-hidden="true"></i>
      <div>Select a file or drag here</div>
      <div class="notimage hidden">Please select an image</div>
    </div>
    <div class="response hidden">
      <div class="messages"></div>
    </div>
  </label>
  </form>
  <div class="filename"></div>
  <canvas></canvas>
</div>

标签: jquery

解决方案


干得好。这可以用来清理一下,但它应该让你朝着正确的方向前进。

很抱歉没有详细解释我所做的更改,但是其中有很多,所以请将您的代码与我的代码进行比较,看看有什么不同。

// File Upload
//
$(function() {
  console.log("_________________________");

  $(".file-drag").click(function(event) {
    $(this)
      .siblings(".file-upload")
      .click();
  });

  function ekUpload(item) {

    var form = $(this).find('form.uploader'),
      fileSelect = $(this).find(".file-upload"),
      fileDrag = $(this).find(".file-drag"),
      submitButton = $(this).find(".submit-button");

    function Init() {
      // console.log("Init()");

      // fileSelect.addEventListener("change", fileSelectHandler, false);
      $(document).on('change', 'form', function(e) {
        fileSelectHandler(e);
      });

      // Is XHR2 available?
      var xhr = new XMLHttpRequest();
      if (xhr.upload) {
        // File Drop
        // fileDrag.addEventListener("dragover", fileDragHover, false);
        // fileDrag.addEventListener("dragleave", fileDragHover, false);
        // fileDrag.addEventListener("drop", fileSelectHandler, false);

        if (isAdvancedUpload) {

          $(document).on('drag dragstart dragend dragover dragenter dragleave', 'form', function(e) {
              // fileDragHover(e);
              e.preventDefault();
              e.stopPropagation();
            })
            .on('dragover dragenter', 'form', function(e) {
              e.preventDefault();
              e.stopPropagation();
              $(e.target).addClass('is-dragover');
            })
            .on('dragleave dragend drop', 'form', function(e) {
              e.preventDefault();
              e.stopPropagation();
              $(e.target).removeClass('is-dragover');
            })
            .on('drop dragover', 'body', function(e) {
              e.preventDefault();
              e.stopPropagation();
            })
            .on('drop', 'form', function(e) {
              e.preventDefault();
              e.stopPropagation();
              fileSelectHandler(e);
            });

        }
      }
    }

    function fileDragHover(e) {
      // var fileDrag = $(".file-drag");

      e.stopPropagation();
      e.preventDefault();

      e.target.className =
        e.type === "dragover" ? "hover" : "modal-body file-upload";
    }

    async function fileSelectHandler(e) {

      var theForm = $(e.target).parent('form.uploader');

      // var files = e.target.files || e.dataTransfer.files;      
      var files = e.target.files || e.originalEvent.dataTransfer.files;

      // Process all File objects
      for (let i = 0; i < files.length; i++) {
        const f = files[i];
        if (await hasAlpha(f)) {
          console.log("Selected image is transparent");
          parseFile(f, theForm);
          uploadFile(f, theForm);
        } else {
          console.log("Selected image is not transparent");
          // document.querySelector(".response").classList.remove("hidden");
          // document.querySelector(".error-image").classList.remove("hidden");
          // document.querySelector(".file-image").classList.add("hidden");
          $(theForm)
            .find(".response, .error-image, .file-image")
            .removeClass("hidden");
          output(
            '<strong class="warning">Image background is not transparent</strong>'
          );
        }
      }
    }

    // Output
    function output(msg) {
      // Response
      // var m = document.getElementById("messages");
      var m = $(item).find(".messages");
      // m.innerHTML = msg;
      m.html(msg);
    }

    function hasAlpha(file) {
      return new Promise((resolve, reject) => {
        let hasAlpha = false;
        const canvas = document.querySelector("canvas");
        const ctx = canvas.getContext("2d");

        const img = new Image();
        img.crossOrigin = "Anonymous";
        img.onerror = reject;
        img.onload = function() {
          canvas.width = img.width;
          canvas.height = img.height;

          ctx.drawImage(img, 0, 0);
          const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
            .data;

          for (let j = 0; j < imgData.length; j += 4) {
            if (imgData[j + 3] < 255) {
              hasAlpha = true;
              break;
            }
          }
          resolve(hasAlpha);
        };
        img.src = URL.createObjectURL(file);
      });
    }

    function parseFile(file, thisForm) {
      console.log(file.name);
      output("<strong>" + encodeURI(file.name) + "</strong>");

      // var fileType = file.type;
      // console.log(fileType);
      var imageName = file.name;

      var isGood = /\.(?=svg|jpg|png|jpeg)/gi.test(imageName);
      if (isGood) {
        // document.getElementById("start").classList.add("hidden");
        // document.getElementById("response").classList.remove("hidden");
        // document.getElementById("notimage").classList.add("hidden");
        $(thisForm)
          .find(".start", ".notimage")
          .addClass("hidden");
        $(thisForm)
          .find(".response")
          .removeClass("hidden");
        // Thumbnail Preview
        // document.querySelector("#error-image").classList.add("hidden");
        // document.getElementById("file-image").classList.remove("hidden");
        // document.getElementById("file-image").src = URL.createObjectURL(file);
        $(thisForm)
          .find(".error-image")
          .addClass("hidden");
        $(thisForm).find('label.has-advanced-upload').removeClass('has-advanced-upload');
        $(thisForm)
          .find(".file-image")
          .removeClass("hidden")
          .attr("src", URL.createObjectURL(file));
      } else {
        // document.querySelector("#error-image").classList.remove("hidden");
        // document.getElementById("file-image").classList.add("hidden");
        // document.getElementById("notimage").classList.remove("hidden");
        // document.getElementById("start").classList.remove("hidden");
        // document.getElementById("response").classList.add("hidden");
        // document.getElementById("file-upload-form").reset();
        $(thisForm)
          .find(".error-image, .notimage, .start")
          .removeClass("hidden");
        $(thisForm)
          .find(".file-image, .response")
          .addClass("hidden");
        $(thisForm)
          .find(".file-upload-form")
          .trigger("reset");
        $(thisForm).find('label[for="file-upload"]').addClass('has-advanced-upload');
      }
    }

    function uploadFile(file, thisForm) {
      // var xhr = new XMLHttpRequest(),
      // fileInput = document.getElementById("class-roster-file"),
      //   fileSizeLimit = 1024; // In MB
      var xhr = new XMLHttpRequest(),
        // fileInput = $(item).find('.class-roster-file'),
        fileSizeLimit = 1024; // in MB

      if (xhr.upload) {
        // Check if file is less than x MB
        if (file.size <= fileSizeLimit * 1024 * 1024) {
          // File received / failed
          xhr.onreadystatechange = function(e) {
            if (xhr.readyState == 4) {
              // Everything is good!
              // document.location.reload(true);
              console.log("everything is good");
            }
          };

          // Start upload
          xhr.open(
            "POST",
            // document.getElementById("file-upload-form").action,
            $(thisForm)
            .find(".file-upload-form")
            .attr("action"),
            true
          );
          xhr.setRequestHeader("X-File-Name", file.name);
          xhr.setRequestHeader("X-File-Size", file.size);
          xhr.setRequestHeader("Content-Type", "multipart/form-data");
          xhr.send(file);
        } else {
          output("Please upload a smaller file (< " + fileSizeLimit + " MB).");
        }
      }
    }

    // Check for the various File API support.
    if (window.File && window.FileList && window.FileReader) {
      Init();
    } else {
      document.getElementById("file-drag").style.display = "none";
    }
  }

  var isAdvancedUpload = (function() {
    var div = document.createElement("div");
    return (
      ("draggable" in div || ("ondragstart" in div && "ondrop" in div)) &&
      "FormData" in window &&
      "FileReader" in window
    );
  })();

  if (isAdvancedUpload) {
    $('.file-drag').addClass('has-advanced-upload');
  }

  $(".item").each(function() {
    ekUpload(this);
  });
});
@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css);
@import url("https://fonts.googleapis.com/css?family=Roboto");
html, body, * {
  box-sizing: border-box;
  font-size: 16px;
}

html, body {
  height: 100%;
  text-align: center;
}

body {
  padding: 2rem;
  background: #f8f8f8;
}

h2 {
  font-family: "Roboto", sans-serif;
  font-size: 26px;
  line-height: 1;
  color: #454cad;
  margin-bottom: 0;
}

p {
  font-family: "Roboto", sans-serif;
  font-size: 18px;
  color: #5f6982;
}

.uploader {
  display: block;
  clear: both;
  margin: 0 auto;
  width: 100%;
  max-width: 600px;
}
.uploader label {
  float: left;
  clear: both;
  width: 100%;
  padding: 2rem 1.5rem;
  text-align: center;
  background: #fff;
  border-radius: 7px;
  border: 3px solid #eee;
  transition: all .2s ease;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  cursor: pointer;
}

.uploader label.has-advanced-upload {
  background-color: white;
  outline: 2px dashed lightgrey;
  outline-offset: -10px;
}

.uploader label:hover {
  border: 3px solid #454cad;
  box-shadow: inset 0 0 0 6px #eee;
}
.uploader label.is-dragover,
.uploader label.is-dragover:hover {
  background-color: #eef;
}

.uploader label:hover {
  border: 3px solid #454cad;
  box-shadow: inset 0 0 0 6px #eee;
}
.uploader label:hover .start i.fa {
  -webkit-transform: scale(0.8);
          transform: scale(0.8);
  opacity: 0.3;
}
.uploader .start {
  float: left;
  clear: both;
  width: 100%;
  pointer-events: none;
}
.uploader .start.hidden {
  display: none;
}
.uploader .start i.fa {
  font-size: 50px;
  margin-bottom: 1rem;
  transition: all .2s ease-in-out;
}
.uploader .response {
  float: left;
  clear: both;
  width: 100%;
}
.uploader .response.hidden {
  display: none;
}
.uploader .response .messages {
  margin-bottom: .5rem;
}
.uploader .file-image {
  display: inline;
  margin: 0 auto .5rem auto;
  width: auto;
  height: auto;
  max-width: 180px;
}
.uploader .file-image.hidden {
  display: none;
}
.uploader .notimage {
  display: block;
  float: left;
  clear: both;
  width: 100%;
}
.uploader .notimage.hidden {
  display: none;
}
.uploader progress,
.uploader .progress {
  display: inline;
  clear: both;
  margin: 0 auto;
  width: 100%;
  max-width: 180px;
  height: 8px;
  border: 0;
  border-radius: 4px;
  background-color: #eee;
  overflow: hidden;
}
.uploader .progress[value]::-webkit-progress-bar {
  border-radius: 4px;
  background-color: #eee;
}
.uploader .progress[value]::-webkit-progress-value {
  background: linear-gradient(to right, #393f90 0%, #454cad 50%);
  border-radius: 4px;
}
.uploader .progress[value]::-moz-progress-bar {
  background: linear-gradient(to right, #393f90 0%, #454cad 50%);
  border-radius: 4px;
}
.uploader input[type="file"] {
  display: none;
}
.uploader div {
  margin: 0 0 .5rem 0;
  color: #5f6982;
}
.uploader .btn {
  display: inline-block;
  margin: .5rem .5rem 1rem .5rem;
  clear: both;
  font-family: inherit;
  font-weight: 700;
  font-size: 14px;
  text-decoration: none;
  text-transform: initial;
  border: none;
  border-radius: .2rem;
  outline: none;
  padding: 0 1rem;
  height: 36px;
  line-height: 36px;
  color: #fff;
  transition: all 0.2s ease-in-out;
  box-sizing: border-box;
  background: #454cad;
  border-color: #454cad;
  cursor: pointer;
}
.uploader input[type="file"],
.hidden {
  display: none;
}

input[type="file"].hidden {
  display: block;
  width: 0.1px;
  height: 0.1px;
  opacity: 0;
  overflow: hidden;
  position: absolute;
  z-index: -1;
}

.warning {
  color: red;
  font-weight: bold;
}
canvas {
  position: absolute;
  top: -2000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Upload  -->
<div class="item">
  <form class="file-upload-form uploader">
    <input class="file-upload" type="file" name="fileUpload" accept="image/*" />
    <label for="file-upload" class="file-drag">  	
	    <img class="file-image hidden" src="#" alt="Preview">
	    <img class="error-image hidden" src="https://cdn3.iconfinder.com/data/icons/online-states/150/Snooze-512.png">
	    <div class="start">
	      <i class="fa fa-download" aria-hidden="true"></i>
	      <div>Select a file or drag here</div>
	      <div class="notimage hidden">Please select an image</div>
	    </div>
	    <div class="response hidden">
	      <div class="messages"></div>
	    </div>
	  </label>
  </form>
  <div class="filename"></div>
  <canvas></canvas>
</div>
<div class="item">
  <form class="file-upload-form uploader">
    <input class="file-upload" type="file" name="fileUpload" accept="image/*" />
    <label for="file-upload" class="file-drag">  	
	    <img class="file-image hidden" src="#" alt="Preview">
	    <img class="error-image hidden" src="https://cdn3.iconfinder.com/data/icons/online-states/150/Snooze-512.png">
	    <div class="start">
	      <i class="fa fa-download" aria-hidden="true"></i>
	      <div>Select a file or drag here</div>
	      <div class="notimage hidden">Please select an image</div>
	    </div>
	    <div class="response hidden">
	      <div class="messages"></div>
	    </div>
	  </label>
  </form>
  <div class="filename"></div>
  <canvas></canvas>
</div>


推荐阅读