如何检测鼠标是否在:在元素的一部分之前或之后:

时间:2018-01-03 08:32:48

标签: javascript jquery css3 pseudo-element

我有这个CSS来定义拖放区域,用户可以在现有部分之前或之后删除部分。

.section:before,
.section:after {
    content: "[insert here]";
    height: 64px;
    line-height: 56px;
    width: 100%;
    display: block;
    border: 3px dashed #aaa;
}

使用JavaScript + JQuery这里是drop listener,它检测当前鼠标下的元素:

elem.on('drop', function(e) {
  e.preventDefault();

  var container = $(elem[0].elementFromPoint(e.clientX, e.clientY));
});

然而container对于:before和:after case都是相同的元素。

我如何能够知道用户在该部分之前或之后是否已经掉线?

4 个答案:

答案 0 :(得分:3)

::before::after是jss不知道的css伪元素。对于javascript,它们都是它们的父元素。

您可能希望使用真正的html元素来执行此操作。

答案 1 :(得分:2)

:before和:after不是DOM的一部分,因此任何Javascript都无法访问它们。

然而,我能想到的唯一解决方案是计算截面的高度,然后将其与下降的x和y坐标进行比较,以确定它是在之前还是之后被丢弃。

答案 2 :(得分:2)

我认为你不能操纵伪元素::before::after,因为技术上没有DOM,因此任何JavaScript都无法访问它。

答案 3 :(得分:1)

这实际上是可能的。

(虽然 - 正如其他人所说 - 可能不是最好的主意)

假设内容一个堆叠在另一个之上,其中:before - >内容 - >之后

我们可以计算相对于容器的丢弃点,然后 - 根据生成的内容的高度,我们可以确定元素是在区域之前还是之后被删除。

是的,javascript can actually access css properties of pseudo-elements

这是通过Window.getComputedStyle()

完成的

语法:(来自MDN

var style = window.getComputedStyle(element[, pseudoElt]);
  

pseudoElt可选

     

指定要匹配的伪元素的字符串。   对于常规元素,必须省略(或为null)。

因此,例如,要在部分之前获取生成内容的高度(让我们称之为' target'):

window.getComputedStyle(target, ':before').height 

这是一个演示片段:



var elem = document.getElementById("el");
var target = document.getElementById("target");
  
var targetHeight = parseFloat(window.getComputedStyle(target).height);
var beforeHeight = parseFloat(window.getComputedStyle(target, ':before').height);
var afterHeight = parseFloat(window.getComputedStyle(target, ':after').height);

elem.addEventListener("drag", function(e) {
  document.body.classList.remove('dropped');
});

target.addEventListener("dragover", function(e) {
  this.textContent = "dragging over section";
  document.body.classList.add('dragging-over');
  addBeforeAfterClasses(e);
});

target.addEventListener("dragleave", function(e) {
  document.body.classList.remove('dragging-over');
  this.textContent = "section";
  e.currentTarget.style.background = "none";
});

target.addEventListener("drop", function(e) {
  document.body.classList.add('dropped');
  addBeforeAfterClasses(e);
  this.textContent = "successfully dropped!";
});

function addBeforeAfterClasses(e) {
  var dropOffsetTopWithRespectToContainer = e.clientY - target.offsetTop;
  if(dropOffsetTopWithRespectToContainer <= beforeHeight) {
    document.body.classList.add('before');
  } else {
    document.body.classList.remove('before');
  }
  if(dropOffsetTopWithRespectToContainer > targetHeight - beforeHeight) {
    document.body.classList.add('after');
  } else {
    document.body.classList.remove('after');
  }
}

target.ondrop = drop_handler;
target.ondragover = dragover_handler;

function drop_handler(e) {
  e.preventDefault();
}

function dragover_handler(e) {
  e.preventDefault();
}
&#13;
.section {
  margin: 10px;
  position: relative;
}
.section:before,
.section:after {
    content: "[insert here]";
    height: 64px;
    line-height: 56px;
    width: 100%;
    display: block;
    border: 3px dashed #aaa;
}

.dragging-over.before .section:before {
  content: "[drop into before]";
  border-color: green;
}

.dragging-over.after .section:after {
  content: "[drop into after]";
  border-color: green;
}

.dropped.before .section:before {
  content: "[dropped into before]";
  background-color: green;
  color: white;
}

.dropped.after .section:after {
  content: "[dropped into after]";
  background-color: green;
  color: white;
}

.elem {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background-color: maroon;
  margin: 0 20px;
  display: inline-block;
}
&#13;
<div id="target" class="section">section</div>
<span>drag me:</span>
<div id="el" draggable="true" class="elem"></div>
&#13;
&#13;
&#13;

Codepen demo