如何查找离单击位置最近的子项
How to find nearest child to a click location?
Fiddle:http://jsfiddle.net/1bgun0k0/1/
我有一个DIV和几个孩子SPAN。
<div id="parent">
<span class="child">Alpha</span>
<span class="child">Beta</span>
<span class="child">Gamma</span>
</div>
子元素有余量:
#parent { padding: 5px; }
.child { margin: 5px; }
当用户在子元素之间(或在子元素外的父DIV的任一端)单击时,我需要在那里插入一个新的子元素。
如何检测用户单击了哪些子元素?
更新:我需要支持多排孩子(谢谢Roko的提醒)。应忽略行之间的单击。应正确处理整行左右两侧的单击。
由于页边空白不接收点击事件,我可能建议使用5px占位符div而不是页边空白,这样在子级之间点击会导致点击占位符。
单击后,您将在下面插入一个新的子项(和一个新5px占位符)。
更新:由于您将问题从在之间单击改为在旁边单击,因此您可以使用伪元素尝试此技巧(以防止divitis)https://stackoverflow.com/a/23243996/1998238
另一种解决方案是使用CSS来屏蔽您正在单击的区域。你可以这样包装你的元素:
<div id="parent">
<div id="alpha" class="spacer">
<span class="child">Alpha</span>
</div>
<div id="beta" class="spacer">
<span class="child">Beta</span>
</div>
<div id="gamma" class="spacer">
<span class="child">Gamma</span>
</div>
</div>
这是代码:https://jsfiddle.net/theodin/5enfs52t/2/
点击:
-
遍历每个
child
,根据相对于光标的位置抓住左右两侧的子对象。(检查event.pageY以确保它们在正确的一行。) -
如果找到左侧的子项,请继续迭代到最后。最后一个留守儿童将是真正的留守儿童。
-
如果找到右侧的子项,请停止迭代。这就是你想要的。
-
如果找到了一个左边的孩子,请插入文本,并在后面插入一个空格。
-
如果找到合适的子项,请在其前面插入文本和一个空格。
代码段
var n = 0;
$('#parent').click(function(e) {
if(e.target.id === 'parent') {
var parent= $(this),
firstChild= $(this).find('.child').first(),
lastChild = $(this).find('.child').last(),
leftChild,
rightChild,
text= function() {return $('<span class="child new">New child '+(++n)+'</span>');}
parent.find('.child').each(function() {
var pos= $(this).offset(),
h= $(this).height();
if(pos.top <= e.pageY && pos.top+h >= e.pageY) {
if(pos.left <= e.pageX) {
leftChild= $(this);
}
else if(pos.left >= e.pageX) {
rightChild= $(this);
return false;
}
}
});
if(leftChild) {
leftChild.after(text()).after(' ');
}
else if(rightChild) {
rightChild.before(text()).before(' ');
}
else if(!firstChild.length || e.pageY < firstChild.offset().top) {
parent.prepend(text()).before(' ');
}
else if(e.pageY > lastChild.offset().top) {
lastChild.after(text()).after(' ');
}
//otherwise, we're between rows
}
});
body {
margin: 10px;
padding: 10px;
}
#parent {
padding: 5px;
background-color: green;
cursor: pointer;
width: 450px;
line-height: 2.7em;
}
.child {
margin: 5px;
white-space: nowrap;
background-color: yellow;
border: 1px solid black;
}
.new {
background-color: lightblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
<span class="child">Alpha</span>
<span class="child">Beta</span>
<span class="child">Gamma</span>
<span class="child">Delta</span>
<span class="child">Epsilon</span>
<span class="child">Zeta</span>
<span class="child">Eta</span>
<span class="child">Theta</span>
<span class="child">Iota</span>
<span class="child">Kappa</span>
<span class="child">Lambda</span>
<span class="child">Mu</span>
<span class="child">Nu</span>
<span class="child">Xi</span>
<span class="child">Omicron</span>
<span class="child">Pi</span>
<span class="child">Rho</span>
<span class="child">Sigma</span>
<span class="child">Tau</span>
<span class="child">Upsilon</span>
<span class="child">Phi</span>
<span class="child">Chi</span>
<span class="child">Psi</span>
<span class="child">Omega</span>
</div>
http://jsfiddle.net/tukqnujm/2
这是以前建议的,但您可以在其他元素之间添加透明的可点击元素,作为边距。
var parent = $("#parent");
parent.on("click", function(e) {
if(e.target.classList.contains("between")) {
var item = document.createElement("span");
item.classList.add("item");
var between = document.createElement("span");
between.classList.add("between");
e.target.parentNode.insertBefore(item, e.target);
e.target.parentNode.insertBefore(between, item);
}
});
但是要小心,如果元素之间有空格,内联块标记会在文档中添加一个空格,而这些空格是不可单击的。这就是为什么我把评论放在jsfiddle中。
<div id="parent"><!--
--><span class="between"></span><!--
--><span class="item"></span><!--
--><span class="between"></span><!--
--></div>
您可以跟踪光标的位置(因为光标不会立即位于任何.child
元素上,因此将单击事件绑定到它是无用的),然后检索该坐标左侧的.child
元素列表。获取满足此标准的最后一个.child
元素,在其后面添加新元素。
此外,您应该将.on()
用于.child
的点击事件绑定,因为新添加的元素不会注册点击事件(因为使用现有代码,您在运行时绑定点击事件,而页面上不存在新添加的元件)。
$('.child').on('click', function(e) {
e.stopImmediatePropagation();
$(".debug").removeClass("debug");
$(this).toggleClass("debug");
})
$("#parent").click(function(e) {
e.stopImmediatePropagation();
$(".debug").removeClass("debug");
$(this).toggleClass("debug");
// Get mouse position along x-axis
var xPos = e.pageX,
yPos = e.pageY;
// Get x-axis offset of child
// Return array of child elements that is to the left of mouseclick
// and get the last child, append new element after it
var $prevChild = $('.child').filter(function() {
return ($(this).offset().left < xPos && $(this).offset().top < yPos)
}),
$content = $('<span class="child">New child</span>');
// Additional logic from @AlexanderGladysh
if ($prevChild.length > 0) {
$content.insertAfter($prevChild.last());
} else {
$(this).prepend($content);
}
})
请在此处查看小提琴:http://jsfiddle.net/teddyrised/1bgun0k0/9/
- jquery试图按名称获取按钮位置
- 我可以获得相对于被点击元素的确切点击位置吗
- 如何查找离单击位置最近的子项
- 如何使用javascript显示离我所在位置最近的纬度和经度
- 点击一个按钮,谷歌地图应该至少适合3个离你当前位置点最近的标记
- 找到具有绝对位置的最近元素
- 在谷歌地图API JS V3上显示距离用户当前位置最近的多个标记,距离30公里
- 将滚动位置调整到最近的容器
- 按最近的位置过滤WordPress帖子
- 如何使用jQuery或JavaScript从用户位置返回3个最近的位置
- 返回离用户位置(地理位置)最近的3个位置,并列出这些位置
- 使用jQuery查找离滚动位置最近的HTML片段标识符
- 使用javascript查找元素相对于最近相对定位的父元素的位置
- 使用谷歌地图上的地理位置,将学生按离彼此最近的位置分组
- 根据地理位置获得最近的距离
- 从谷歌地图api获取最近的位置
- 最近的位置(标记)在谷歌地图
- 谷歌地图显示最近的数据库标记到我的位置
- 用户地理位置到最近地址的计算
- 从已知位置查找最近的列出(数组?)城市