【问题标题】:GWT Drag and Drop File Upload not workingGWT拖放文件上传不起作用
【发布时间】:2019-08-28 22:50:28
【问题描述】:

所以我实现了一个非常简单的拖放文件上传小部件。基本上我的小部件是一个垂直面板,里面有几个标签和一个按钮。用户可以将文件拖入垂直面板或单击按钮并浏览文件。

我的问题是,当我将文件拖入垂直面板时,每次我将项目拖到标签或按钮占用的空间上时,它都会触发 DragLeaveEvent。我希望它知道该项目位于垂直面板中,即使它位于标签或按钮的顶部。我确定我错过了一些简单的东西。我通过将这些 dom 处理程序添加到垂直面板来提供拖动功能:

addDomHandler(new DragEnterHandler() {
            @Override
            public void onDragEnter(DragEnterEvent event) {
                System.out.println("drag enter");
                highlight(true);
            }
        }, DragEnterEvent.getType());

addDomHandler(new DragLeaveHandler() {
            @Override
            public void onDragLeave(DragLeaveEvent event) {
                System.out.println("drag leave");
                highlight(false);
            }
        }, DragLeaveEvent.getType());

addDomHandler(new DragOverHandler() {
            @Override
            public void onDragOver(DragOverEvent event) {
            }
        }, DragOverEvent.getType());

addDomHandler(new DropHandler() {
            @Override
            public void onDrop(DropEvent event) {
                System.out.println("drop");
                // stop default behaviour
                event.preventDefault();
                event.stopPropagation();

                // starts the fetching, reading and callbacks
                if (fileUploadHandler != null) {
                    handleFiles(event.getDataTransfer(), fileUploadHandler);
                }
                highlight(false);
            }
        }, DropEvent.getType());    

【问题讨论】:

    标签: gwt dom file-upload drag-and-drop


    【解决方案1】:

    检查事件目标是否是您面板的子(或孙子),或者在这种情况下,可能更确切地说事件目标是否正是您面板的元素:

    if (verticalPanel.getElement().isOrHasChild(Node.as(event.getNativeEvent().getEventTarget()))) {
       // within the panel (possibly on a child)
    }
    
    if (verticalPanel.getElement() == Node.as(event.getNativeEvent().getEventTarget())) {
       // targetting exactly the panel (e.g. leaving the panel, not one of its children)
    }
    

    【讨论】:

    • 我知道这如何向我展示了哪些元素是子元素,但我想要完成的是在垂直面板中的任意位置拖动文件并能够将其拖放,但是我无法这样做,因为拖动处理程序考虑不在面板中的标签和东西。我希望文件在垂直面板中被考虑,无论它是否跨越标签或按钮
    • 我想你会收到DragEnterDragOverDragLeave 的每个子元素(因为事件冒泡),所以你只想处理那些直接针对的事件小组;即忽略针对您的标签和按钮的事件。
    • 是的,但问题仍然存在,当我仍在面板内但越过标签时它会发送拖动离开事件,因为它认为它正在离开面板并输入标签,即使标签是面板内
    • 哦,我现在才明白:当鼠标进入标签时,您会收到面板的dragleave。这很奇怪,违反了the spec(和常识)。该规范有点神秘,但它说除非标签本身是 dropzone ,否则当您在面板上移动时,您不应该在子级上出现 dragleave 事件。你能在像 jsfiddle.net 这样的网站上用“纯 JS”重现它吗? (这将有助于确定它是浏览器错误、GWT 错误还是代码中某处的错误)
    【解决方案2】:

    通过大量研究,我找到了唯一能找到的解决方案。我在 dragover 处理程序中将 highlight 设置为 true 而不是拖动 enter。

        panel.addDomHandler(new DragEnterHandler() {
            @Override
            public void onDragEnter(DragEnterEvent event) {
            }
        }, DragEnterEvent.getType());
    
        panel.addDomHandler(new DragLeaveHandler() {
            @Override
            public void onDragLeave(DragLeaveEvent event) {
                highlight(false);
            }
        }, DragLeaveEvent.getType());
    
        panel.addDomHandler(new DragOverHandler() {
            @Override
            public void onDragOver(DragOverEvent event) {
                highlight(true);
            }
        }, DragOverEvent.getType());
    
        panel.addDomHandler(new DropHandler() {
            @Override
            public void onDrop(DropEvent event) {
                // stop default behaviour
                event.preventDefault();
                event.stopPropagation();
    
                // starts the fetching, reading and callbacks
                handleFiles(event.getDataTransfer());
                highlight(false);
            }
        }, DropEvent.getType());
    

    【讨论】:

      【解决方案3】:

      我复制粘贴了你的代码,还加了一句:

      RootPanel.get().addHandler(dropHandler, DropEvent.getType());
      

      我的 drophandler 看起来像这样:

      DropHandler dropHandler = new DropHandler() {
      
              @Override
              public void onDrop(DropEvent event) {
                  handleFiles(event.getDataTransfer(), new FileUploadHandler() {
                      @Override
                      public TYPE specifyFileType() {
                          return TYPE.BINARY;
                      }
      
                      @Override
                      public void handleFileContent(String fileName, String fileContent) {
                          // do stuff with filename and content
                      }
      
                      @Override
                      public boolean checkFileName(String fileName) {
                          return true;
                      }
                  });
                  event.preventDefault();
                  event.stopPropagation();
              }
          };
      

      和文件上传界面:

      public interface FileUploadHandler {
      
          static public enum TYPE {
               TEXT, BINARY, DATAURL
          };
      
          // check the filename and extension and return true if you are happy with
          // proceeding
          // returnning false will prevent the file from being read
          boolean checkFileName(String fileName);
      
          // tell the method to use to read this file
          TYPE specifyFileType();
      
          // do your stuff here, eg upload to a server
          void handleFileContent(String fileName, String fileContent);
      }
      

      以及句柄文件功能:(请注意,您必须将类路径更改为 FileUploadHandler 接口)

      // native method to make use of the HTML5 file API functionality
      private final native void handleFiles(JavaScriptObject dataTransfer, FileUploadHandler fileUploadHandler) /*-{
          var files = dataTransfer.files;
          var i;
          var file;
          var reader = new FileReader();
          for (i = 0; i < files.length; i++) {
              file = files[i];
              if (fileUploadHandler.@<classpath_to>.FileUploadHandler::checkFileName(Ljava/lang/String;)(file.name)) {
                  var type = fileUploadHandler.@<classpath_to>.FileUploadHandler::specifyFileType()();
                  reader.onload = function(e) {
                      fileUploadHandler.@<classpath_to>.FileUploadHandler::handleFileContent(Ljava/lang/String;Ljava/lang/String;)(file.name, e.target.result);
                  }
                  if (type == "TEXT") {
                      reader.readAsText(file);
                  } else if (type == "BINARY") {
                      reader.readAsBinaryString(file);
                  } else if (type == "DATAURL") {
                      reader.readAsDataURL(file);
                      // not supported
                  } else if (type == "ARRAYBUFFER") {
                      reader.readAsArrayBuffer(file);
                  } else {
                  }
              }
          }
      }-*/;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-25
        • 1970-01-01
        • 1970-01-01
        • 2019-04-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多