我正在尝试在jquery中实现一个范围选择器插件。你可以在
中看到有些工作的版本然而,它没有正常工作。上面的箭头必须(最大)到下面箭头的位置,反之亦然。此外,在控制台日志中,当我仅移动顶部箭头时,它显示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 ,我不想因为这个原因而添加另一个依赖项。
答案 0 :(得分:3)
您收到的错误是由于在某些情况下触发undefined
处理程序时,邮箱是onmousemove
。
Hare是我注意到插件的一些问题:
onmousedown
中计算,因为如果您更改相对对象的位置(拖动箭头),您使用的迷你和最大值仍将具有初始值event
之类的整个对象。最好只保存鼠标的起始Y坐标和箭头偏移所需的最高值。mousemove
和mouseup
事件设置侦听器,而不是取消绑定它们。第2点和第3点的混合是导致undefined
错误(Here is a version where the errors are not triggered because only the value is saved)的原因。
请看这个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");
这不是您想要获得建议的完整解决方案。
答案 1 :(得分:1)
问题是您的插件不会检查被拖动的箭头是否与此插件实例相对应。更具体地说,$('.dragby')
查询返回两个实例的相同元素,因此他们都认为它们被拖动了。当然,其中一个会失败,因为它还没有设置boxpos
。
因此,您需要调整.dragby
选择器以确保它仅检查属于当前实例的元素。现在,您现在表示您只将dragby
类应用于arrow
变量。因此,一种解决方案是检查arrow
元素是否具有dragby
类:
if (arrow.hasClass('dragby')) {
arrow.offset({ ... });
// ...
}
但是有一个更简单的解决方案:只需保留一个布尔变量dragging
,指示是否正在拖动箭头。 dragging
上的true
设置为mousedown
,并在mouseup
上重置。然后,您只需检查dragging
处理程序中的mousemove
。