我正在尝试在jquery中实现范围选择器插件。您可以在以下位置看到有些工作的版本
http://jsfiddle.net/franciscop/yHAY9/2/
但是它无法正常工作。上面的箭头必须(最大)到下面箭头的位置,反之亦然。此外,在控制台日志中,当我只移动顶部箭头时,它会显示TypeError: boxpos is undefined
.我想我正确地定义了范围,是因为我没有,还是因为同一个插件有两个元素相互干扰?这是 html:
<div class = "range">
<div class = "start">◀</div>
<div class = "show"></div>
<div class = "end">◀</div>
</div>
还有javascript:
// Make the main form to be draggable
(function ($, window) {
$.fn.range = function(mini, maxi) {
// The element to be clicked
var arrow = this;
// The current position when clicked
var boxpos;
// Minimum position that it can achieve
var mini = $(mini).offset().top;
var maxi = $(maxi).offset().top + $(maxi).height();
// The position of the mouse
var mouse;
$(arrow).mousedown(function(event){
arrow.addClass("dragby");
boxpos = arrow.offset();
mouse = event;
// Avoid selecting text
event.preventDefault();
});
$(window).on("mousemove", function(event){
// Is there anything to be dragged
if($('.dragby').length)
{
$('.dragby').offset({
top: boxpos.top + event.pageY - mouse.pageY
});
if (event.pageY < mini)
$('.dragby').offset({
top: mini
});
if (event.pageY > maxi)
$('.dragby').offset({
top: maxi
});
}
});
$(window).mouseup(function(event){
arrow.removeClass("dragby");
// Avoid any link/anything that could be there
event.preventDefault();
});
return this;
}
}(jQuery, window));
// END OF PLUGIN
$(".range .start").range(".range", ".end");
$(".range .end").range(".start", ".range");
注意:如果可能的话,尝试在没有jquery ui的情况下回答,我不想仅仅因为这个而添加另一个依赖项。
您收到的错误是由于在某些情况下触发onmousemove
处理程序时undefined
boxpos。
野兔是我在插件中注意到的一些问题:
- 迷你和最大应该在
onmousedown
中计算,因为如果您更改相对对象的位置(拖动箭头),您使用的迷你和最大仍将具有初始值 - 如果不需要,请尝试在上下文函数中仅保存所需的值,而不是像
event
那样保存整个对象。最好只保存鼠标的起始 Y 坐标和箭头偏移量所需的最高值。 - 您应该注意绑定到的事件。例如,每次应用此插件时,您都会为
mousemove
和mouseup
事件设置侦听器,并且不会取消绑定它们。
第 2 点和第 3 点的混合是您收到undefined
错误的原因(这是一个不会触发错误的版本,因为仅保存了值)。
看看这个 http://jsfiddle.net/dragulceo/yHAY9/8/,我把你的代码改成了这个(修复了我上面提到的问题):
// DRAGBY jQuery plugin
// Make the main form to be draggable
(function ($, window) {
$.fn.range = function (miniSel, maxiSel) {
// The element to be clicked
var arrow = this;
// The current position when clicked
var startTop;
var thisHeight = $(arrow).height();
// Minimum position that it can achieve
var mini;
var maxi;
// Cache the size of the maxi height because it seams that it changes if called after changing the top (because css bottom remains 0)
var maxiHeight = $(maxiSel).height();
// The position of the mouse when starting to drag
var mouseY;
var mouseMoveHandler = function (event) {
// Should the arrow be dragged
if (arrow.hasClass('dragby')) {
var newPos = startTop + event.pageY - mouseY;
if (newPos < mini) {
newPos = mini
}
if (newPos > maxi) {
newPos = maxi
}
// Set the new position
arrow.offset({
top: newPos,
});
}
};
var mouseUpHandler = function (event) {
arrow.removeClass("dragby");
// Avoid any link/anything that could be there
event.preventDefault();
$(window).off("mousemove", mouseMoveHandler);
$(window).off("mouseup", mouseUpHandler);
};
$(arrow).mousedown(function (event) {
arrow.addClass("dragby");
startTop = arrow.offset().top;
mini = $(miniSel).offset().top;
maxi = $(maxiSel).offset().top + maxiHeight - thisHeight;
mouseY = event.pageY;
// Avoid selecting text
event.preventDefault();
$(window).on("mousemove", mouseMoveHandler);
$(window).on("mouseup", mouseUpHandler);
});
return this;
}
}(jQuery, window));
// END OF PLUGIN
$(".range .start").range(".range", ".end");
$(".range .end").range(".start", ".range");
这不是您想要获得的建议的完整解决方案。
问题是您的插件没有检查正在拖动的箭头是否与此插件实例相对应。更具体地说,$('.dragby')
查询为两个实例返回相同的元素,因此它们都认为它们被拖动了。当然,其中一个会失败,因为它还没有设定boxpos
。
因此,您需要调整.dragby
选择器,以确保它只检查属于当前实例的元素。现在,您现在仅将dragby
类应用于arrow
变量。因此,一种解决方案是检查arrow
元素是否具有dragby
类:
if (arrow.hasClass('dragby')) {
arrow.offset({ ... });
// ...
}
不过,还有一个更简单的解决方案:只需保留一个布尔变量dragging
,指示箭头是否被拖动。dragging
设置为mousedown
时true
,mouseup
时重置。然后,您可以在mousemove
处理程序中检查dragging
。
看看吧: http://jsfiddle.net/MattiasBuelens/yHAY9/5/