如果使用 JavaScript,我如何检测图像是否被粘贴或放入内容可编辑区域?

How do I detect, with JavaScript, if an image was pasted or dropped into a contenteditable area?

我有一个脚本可以防止用户将拖动的图像粘贴或拖放到内容编辑区域。当用户试图做这两件事之一时,我想要一个警告,告诉他他不能那样做。我尝试在最后一次休息之前添加 alert("custom message")。但它在两种情况下(粘贴和删除)都会被触发。我怎么能有两个不同的警报:一个是当用户粘贴图像时(“你不能在此处粘贴图像”),另一个是当用户放下拖动的图像时(“你不能在我的代码中将图像放在此处”?

https://jsfiddle.net/36cfdpoh/

window.onload = function() {
    document.getElementById("editDiv").oninput = function() {
        var thisElement = this;
        var currentElementChildren, currentElementChildrenLength;
        var elements = this.children;
        var elementsLength = elements.length;
        if (elementsLength > 0) {
            for (i = 0; i < elementsLength; i++) {
                if (elements[i].tagName == "IMG") {
                    thisElement.children[i].remove();
                    break;
                } else {
                    currentElementChildren = elements[i].children;
                    currentElementChildrenLength = currentElementChildren.length;
                    if (currentElementChildrenLength > 0) {
                        for (ii = 0; ii < currentElementChildrenLength; ii++) {
                            if (currentElementChildren[ii].tagName == "IMG") {
                                thisElement.children[i].children[ii].remove();
                                alert("you cannot drop images here");
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}
#editDiv {
    width: 250px;
    height: 50px;
    border: solid 1px #000;
    margin-bottom: 20px;
  }

img {
    width: 250px;
}
<div id="editDiv" contenteditable="true">
    <p>Try to drop or paste that image here.</p>
</div>
    
<img src="https://i7.pngguru.com/preview/134/138/533/star-golden-stars.jpg">

您可以单独将 paste & drop 事件附加到 dom,然后检查哪个正在触发

有两种解决方法。使用 input 事件或使用 droppaste 事件:

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <link rel="stylesheet" type="text/css" href="styles.css">
  <title>Image phobia</title>
</head>

<body>
  <h1>Image phobia</h1>

  <div id="editDiv" contenteditable="true">
    <p>Try to drop or paste that image here.</p>
  </div>

  <img height="100" width="100" src="https://i7.pngguru.com/preview/134/138/533/star-golden-stars.jpg">
  <img height="100" width="100" src="https://i7.pngguru.com/preview/134/138/533/star-golden-stars.jpg">

  <script src="main.js" />
</body>

</html>

input事件解决方案:

main.js

"use strict";
(function() {
  window.addEventListener("load", () => {
    const editDiv = document.getElementById("editDiv");

    // return a message depending on input type
    function alertMessage(type) {
      switch (type) {
        case "insertFromPaste":
          return "You can't paste images here";
        case "insertFromDrop":
          return "You can't drop images here";
      }
    }

    // recursive function to delete image from an element's children
    function removeImages(children) {
      let hadImage = false;
      for (let i = children.length - 1; i >= 0; i--) {
        const child = children[i];
        if (child.tagName === "IMG") {
          child.remove();
          hadImage = true;
          continue;
        }
        if (child.children.length) {
          hadImage = removeImages(child.children);
          if (hadImage) {
            break;
          }
        }
      }
      return hadImage;
    }

    function preventImageInput(e) {
      const inputType = e.inputType;
      if (inputType === "insertFromDrop" || inputType === "insertFromPaste") {
        if (e.target.children.length) {
          const hadImage = removeImages(e.target.children);
          if (hadImage) {
            alert(alertMessage(inputType));
          }
        }
      }
    }

    editDiv.addEventListener("input", preventImageInput);
  });
})();

droppaste事件解决方案:

main.js

"use strict";
(function() {
  window.addEventListener("load", () => {
    const editDiv = document.getElementById("editDiv");

    // return message depending on event type
    function alertMessage(type) {
      switch (type) {
        case "paste":
          return "You can't paste images here";
        case "drop":
          return "You can't drop images here";
      }
    }

    function preventImageInput(e) {
      // you must use setTimeout because when both the paste or drop events are fired
      // the content isn't changed yet and you won't have access to the new content
      setTimeout(() => {
        const images = e.target.querySelectorAll("img");
        if (images.length) {
          for (let i = images.length - 1; i >= 0; i--) {
            const image = images[i];
            image.remove();
          }
          alert(alertMessage(e.type));
        }
      });
    }

    editDiv.addEventListener("paste", preventImageInput);
    editDiv.addEventListener("drop", preventImageInput);
  });
})();