如何防止将 HTML 5 中的元素拖到地址栏上?

Posted

技术标签:

【中文标题】如何防止将 HTML 5 中的元素拖到地址栏上?【英文标题】:How to prevent element dragging in HTML 5 onto the address bar? 【发布时间】:2015-12-18 11:37:36 【问题描述】:

我正在使用带有 angular-drag-and-drop-lists 指令的 Angular。它使用 html5 API 来实现拖放。我注意到,当将一个元素拖到浏览器地址栏上时,地址会被元素的数据重写,并且驱动程序会离开我的站点。有没有办法防止元素被拖到地址栏上或限制它的拖拽区域?

【问题讨论】:

【参考方案1】:

这是特定于操作系统/浏览器的,并且级别低于您的代码允许的级别。所以你将无法从你的代码中做任何事情。

【讨论】:

如果在 HTML 5 中我能够限制文档边界之外的移动,它将解决问题。尚无法找到如何使用拖放处理程序执行此操作。 如果你想办法阻止这种情况,我会吃掉我的帽子:) 我在这里必须同意@GabrielKohen 的观点,尽管我最初和你一样认为这是不可能的,因为这是视口之外的事件(因此是操作系统端),并且有一个 hack 防止光标退出应该是可以的。 @tyler hat-eating time ;) 还有图片,否则它没有发生! @tatsu 给出的答案是特定于操作系统/浏览器的,而不是标准化的(仍然是 2.5 年后)。我认为这个问题需要一个普遍有效的解决方案,但不幸的是没有。【参考方案2】:

如果您控制 dragstart 事件,您可以定义拖动数据存储的 effectAllowed。这将定义您的系统如何处理您拖动的元素。您有不同的选择,它们的行为会根据您放置它们的位置和内容而有所不同。这也会影响它如何影响地址栏中的拖放。

以下是您可以设置的一些行为示例。例如,在 Chrome 上,当您将效果设置为 'none' 时,将元素拖到地址栏不会执行任何操作,但使用 'copy'将搜索类型为 'text/plain' 的文本。带有 'copy' effectAllowed 的图像将在浏览器中打开。

其他地方的行为也会有所不同。例如,如果您在查找器中拖动元素(在 Mac OS 上),它将创建图像或内容为 'text/plain' 的文本文件。在 Microsoft Word 中,图像将被插入到页面中,或者 'text/html' 将被插入,带有格式。

像这样:

document.getElementById('noneImg').addEventListener('dragstart', setEffect)

document.getElementById('copyImg').addEventListener('dragstart', setEffect)

document.getElementById('linkImg').addEventListener('dragstart', setEffect)

document.getElementById('noneText').addEventListener('dragstart', setEffect)

document.getElementById('copyText').addEventListener('dragstart', setEffect)

document.getElementById('linkText').addEventListener('dragstart', setEffect)


function setEffect(e) 
  if(e.target.tagName === 'DIV')
      e.dataTransfer.setData('text/plain', 'test');
      e.dataTransfer.setData('text/html', '<b>bold</b>');
  
	e.dataTransfer.effectAllowed = e.target.className;
img 
  width: 80px;
  height: 80px;
<img id="noneImg" class="none" src="http://koncha.890m.com/wp-content/uploads/2016/06/2.jpg"  />

<img id="copyImg" class="copy" src="http://koncha.890m.com/wp-content/uploads/2016/06/2.jpg"  />

<img id="linkImg" class="link" src="http://koncha.890m.com/wp-content/uploads/2016/06/2.jpg"  />

<div draggable="true" id="noneText" class="none">effect none</div>

<div draggable="true" id="copyText" class="copy">effect copy</div>

<div draggable="true" id="linkText" class="link">effect link</div>

见https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed

如果您不控制 dragstart 事件,那么您无能为力。这意味着从您的操作系统或其他窗口拖动的所有内容。

编辑:

澄清一下,drop 的行为方式取决于 3 件事:

拖动数据存储的内容允许的效果 以及进行 drop 的应用程序

您需要将每个浏览器视为不同的应用程序,因此行为会因浏览器而异,并且可能会因操作系统和浏览器版本而异。例如,在我可用的浏览器上,在 Chrome 上,effectAllowed none 不会做任何事情。但是在 Firefox 上它会触发一个 drop。

此外,拖动数据存储是一组复杂的数据,您可以在其中拥有多种数据类型,并且根据应用程序的不同,将使用不同的数据类型。因此,例如,如果您有一个“文本”数据类型,它会将文本数据类型的内容放在地址栏中(在 Chrome 上,这发生在“复制”效果允许,但不是“链接”。使用 Firefox将丢弃它,无论定义了 effectAllowed)。

调整行为的一种方法是使用 clearData。这将清除拖动数据存储。完成此操作后,您可以根据需要定义自己的类型。例如,使用自定义类型,您可以清除所有其他行为并仅在页面中保留您需要的行为。

因此,例如,您可以在此处放置,根据哪个放置,您可以访问不同的数据,并且没有与其他应用程序的交互。

document.getElementById('noneImg').addEventListener('dragstart', setEffect)

document.getElementById('copyImg').addEventListener('dragstart', setEffect)

document.getElementById('linkImg').addEventListener('dragstart', setEffect)

document.getElementById('noneText').addEventListener('dragstart', setEffect)

document.getElementById('copyText').addEventListener('dragstart', setEffect)

document.getElementById('linkText').addEventListener('dragstart', setEffect)

function setEffect(e) 
  e.dataTransfer.clearData();
  e.dataTransfer.setData('custom', 'custom data');
  e.dataTransfer.setData('custom2', 'other custom data');
  e.dataTransfer.effectAllowed = e.target.className;


document.getElementById('drop').addEventListener('dragover', (e) => 
  e.preventDefault();
  e.target.style.backgroundColor = 'blue';
);

document.getElementById('drop').addEventListener('dragleave', (e) => 
  e.preventDefault();
  e.target.style.backgroundColor = "";
);

document.getElementById('drop').addEventListener('drop', (e) => 
  console.log(e.dataTransfer.getData('custom'));
  e.target.style.backgroundColor = "";
  e.preventDefault();
);

document.getElementById('drop2').addEventListener('dragover', (e) => 
  e.preventDefault();
  e.target.style.backgroundColor = 'blue';
);

document.getElementById('drop2').addEventListener('dragleave', (e) => 
  e.preventDefault();
  e.target.style.backgroundColor = "";
)

document.getElementById('drop2').addEventListener('drop', (e) => 
  console.log(e.dataTransfer.getData('custom2'));
  e.target.style.backgroundColor = "";
  e.preventDefault();
);
img 
  width: 80px;
  height: 80px;


#drop,
#drop2,
#drop3 
  width: 200px;
  height: 200px;
  border: solid 1px black;
  float: left;
<img id="noneImg" class="none" src="http://koncha.890m.com/wp-content/uploads/2016/06/2.jpg" />

<img id="copyImg" class="copy" src="http://koncha.890m.com/wp-content/uploads/2016/06/2.jpg" />

<img id="linkImg" class="link" src="http://koncha.890m.com/wp-content/uploads/2016/06/2.jpg" />

<div draggable="true" id="noneText" class="none">effect none</div>

<div draggable="true" id="copyText" class="copy">effect copy</div>

<div draggable="true" id="linkText" class="link">effect link</div>

<div id="drop">

</div>

<div id="drop2">

</div>

【讨论】:

好吧,如果你有'none'作为效果,你还不如完全没有拖放......或者我错过了什么?使用此示例:visjs.org/examples/timeline/other/drag&drop.html 我将如何保留拖放功能但防止在地址栏上拖放? (您可以在该页面上使用检查器访问未编译的代码) 在您的示例中查看我的编辑,而不是使用 event.dataTransfer.setData("text", JSON.stringify(objectItem));使用 clearData 和 event.dataTransfer.setData("custom", JSON.stringify(objectItem));确保您在 bis.js 中也更改为 getData('custom') 好的,所以这确实是一个浏览器都没有达到速度的问题。我在三个浏览器中打开了这个答案,ie11、firefox50 和 chrome65。 firefox 根本无法在未损坏的状态下打开 ***,但这可能是我公司的防火墙在工作。但是我自己编写的测试证实,我确实可以在我的放置区域上正确触发拖放事件,并使用“无”,即使它没有重定向,它确实将 html 内容放入地址栏中。但它没有重定向,所以这更好。但我的目标是 ie11,这无济于事。 我还应该提到,在 IE 中,当我单击按钮时,上面的代码片段无法运行。因为你惊人的完整答案,我给你加分。非常感谢,这很有启发性。 哎呀,我刚刚意识到在 IE 中 link 做得很完美。谢谢!

以上是关于如何防止将 HTML 5 中的元素拖到地址栏上?的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 拖放无法正常工作

如何防止子元素干扰 HTML5 拖放事件?

当用户点击地址栏输入使用 JQuery 或 JS 时,如何防止网页重新加载

电脑应用拖到上边放大

jQuery UI - 防止对话框拖到 div 上方

如何将一个数组最佳地划分为两个子数组,以使两者中的元素之和相同,否则会出错?