草庐IT

javascript - 一次拖放多个 html 元素

coder 2023-07-31 原文

是否有一种 HTML5 默认方法可以将多个元素拖放到同一页面上的另一个 html 元素中?

似乎适用于一个元素的 HTML5 属性 draggable 说:“你可以拖动我,但你需要多个输入设备同时选择另一个可拖动元素。”

作为一种解决方法,可以使用 js 向选定元素添加标识符,并在特定事件上获取所有选定元素,然后执行我们想要的操作。但这真的是“正确”的方式吗?

当您检查 drop 事件时,在处理文件拖放时会有一个用于多个文件的接口(interface)。还有 items 属性——至少在 Chrome 中是这样。

浏览器之间存在差异。

在 Chrome 中

drop 事件包含 items 属性

dataTransfer: DataTransfer
    items: DataTransferItemList
        length: 0

Items 似乎是 0,不管你是否拖动了一个项目。

在火狐中

drop 事件包含 mozItemCount 属性

dataTransfer: DataTransfer
    mozItemCount: 1

mozItemCount 似乎至少为 1。


这是一个小演示

您可以在哪里查看您的开发者工具控制台:

此来源取自此处:http://www.html5rocks.com/en/tutorials/dnd/basics/

$(function(){
  // Copied from: http://www.html5rocks.com/en/tutorials/dnd/basics/
  var cols_ = document.querySelectorAll('.column');
  var dragSrcEl_ = null;

  handleDragStart = function(e) {
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/html', this.innerHTML);

    dragSrcEl_ = this;

    this.style.opacity = '0.4';

    // this/e.target is the source node.
    $(this).addClass('moving');
  };

  handleDragOver = function(e) {
    if (e.preventDefault) {
      e.preventDefault(); // Allows us to drop.
    }

    e.dataTransfer.dropEffect = 'move';

    return false;
  };

  handleDragEnter = function(e) {
    $(this).addClass('over');
  };

  handleDragLeave = function(e) {
    // this/e.target is previous target element.

    $(this).removeClass('over');
  };

  handleDrop = function(e) {
    // this/e.target is current target element.
    console.log(e.dataTransfer);

    if (e.stopPropagation) {
      e.stopPropagation(); // stops the browser from redirecting.
    }

    // Don't do anything if we're dropping on the same column we're dragging.
    if (dragSrcEl_ != this) {
      dragSrcEl_.innerHTML = this.innerHTML;
      this.innerHTML = e.dataTransfer.getData('text/html');
    }

    return false;
  };

  handleDragEnd = function(e) {
    // this/e.target is the source node.
    this.style.opacity = '1';

    [].forEach.call(cols_, function (col) {
      $(col).removeClass('over');
      $(col).removeClass('moving');
    });
  };

  [].forEach.call(cols_, function (col) {
    col.setAttribute('draggable', 'true');  // Enable columns to be draggable.
    col.addEventListener('dragstart', this.handleDragStart, false);
    col.addEventListener('dragenter', this.handleDragEnter, false);
    col.addEventListener('dragover', this.handleDragOver, false);
    col.addEventListener('dragleave', this.handleDragLeave, false);
    col.addEventListener('drop', this.handleDrop, false);
    col.addEventListener('dragend', this.handleDragEnd, false);
  });
});
.column {
  height: 150px;
  width: 150px;
  float: left;
  border: 2px solid #666666;
  background-color: #ccc;
  margin-right: 5px;
  border-radius: 10px;
  box-shadow: inset 0 0 3px #000;
  text-align: center;
  cursor: move;
  margin-bottom: 30px;
}
.column header {
  color: #fff;
  text-shadow: #000 0 1px;
  box-shadow: 5px;
  padding: 5px;
  background: linear-gradient(left center, rgb(0,0,0), rgb(79,79,79), rgb(21,21,21));
  border-bottom: 1px solid #ddd;
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
}
.column {
 transition: transform 0.2s ease-out;
}
.column.over {
  border: 2px dashed #000;
}
.column.moving {
  opacity: 0.25;
  transform: scale(0.8);
}
.column .count {
  padding-top: 15px;
  font-weight: bold;
  text-shadow: #fff 0 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
 
<div class="cols">
  <div class="column">
    <header>C</header>
  </div>
  <div class="column">
    <header>B</header>
  </div>
  <div class="column">
    <header>A</header>
  </div>
</div>


所以看起来 vendor 正在准备多项目拖放,但似乎没有默认。如果我错了,请纠正我。

我读了这些文章是为了更好地理解dnd

进一步阅读:

最佳答案

首先,items 长度以及 files 长度在 Chrome 中是有效的。你总是得到 0 长度,因为拖动数据存储中的信息受到保护,除了放置事件。因此,当您记录该对象并在之后查看它时,您无权访问该信息。但是如果你这样记录它:

console.log(e.dataTransfer.items.length);

然后您将可以访问实际长度。请参阅此处关于保护模式:

https://html.spec.whatwg.org/multipage/interaction.html#the-drag-data-store

这并不是说它会为您提供拖动元素的数量,原因有几个:

首先是原生的 drag and drop API 也用于 从浏览器拖动到其他应用程序,反之亦然。所以 其中的许多功能都可以处理这些情况。

另一件事是拖放 API 让您可以访问那些 是浏览器在拖拽方面的默认行为。例如,在浏览器中拖动一个链接将打开该链接。什么时候 您使用 API,您正在访问这些行为。

此 API 的许多行为都是由此产生的结果,从这个意义上讲,并不是真的要拖动 DOM 元素。为此,其他图书馆可能更合适,或者只是通过它提供的不同事件来管理内容本身。

由于您可以从其他应用程序中拖放元素,因此很多信息都与此有关。例如,在 dataTransferItem 中,您可以访问 fileList 对象。这仅在将文件从您的操作系统拖到浏览器中时有效。所以你有一个文件的数量,以及拖拽的不同文件。但这与拖动 DOM 元素无关。

您也可以从浏览器中拖动。非常有用,例如,如果您想将 HTML 内容拖到 Word 中。但是要传输的信息比简单的 DOM 元素更复杂。在那种情况下,您正在拖动 items,但这些 items 并不是所谓的 DOM 元素。它们是可以转移的不同类型的东西。

可以传输的东西类型在实现上有很大差异,但基本上你可以有纯文本、html 内容和链接。所以项目的长度将是可用类型的长度。例如,在下面的 jsfiddle 中,在 Chrome 上,你可以拖动图像、链接和纯文本(对于这个你只需要选择文本)。结果:

 console.log(e.dataTransfer.items.length, 
e.dataTransfer.getData('text/plain'), 
e.dataTransfer.getData('text/uri-list'), 
e.dataTransfer.getData('text/html'));

当拖动灰色目标上的每个元素时是这样的:

输入的纯文本:

length: 1 
 plain text: text 
 link:  
 html content: 

来自图片:

length: 2 
    plain text:  
     link: http://www.exiv2.org/include/img_1771.jpg 
     html content: <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><img id="image1" src="http://www.exiv2.org/include/img_1771.jpg">

来自链接:

length: 3 
 plain text: http://google.com/ 
 link: http://google.com/ 
 html content: <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><a href="http://google.com/">link 1</a>

参见此处:http://jsfiddle.net/ztj6t2ff/9/

您会看到 html 与您页面上的内容不完全相同。这是为了允许传输到其他应用程序并尽可能保持最佳格式。

因此,一般来说,此 API 允许您干扰默认行为,即几乎可以将您在操作系统中可以拖动的任何内容拖入浏览器或从浏览器中拖出。从这个意义上说,它相当复杂,但大多数功能与在同一页面内拖动 DOM 元素无关。

事实上,几乎所有通过拖放操作的 DOM 操作都是在不使用此 API 的情况下进行的。例如,jquery-ui draggable 根本不依赖此 API。

关于javascript - 一次拖放多个 html 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32781394/

有关javascript - 一次拖放多个 html 元素的更多相关文章

  1. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  7. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  8. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  9. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  10. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

随机推荐