javascript中的范围选择器。范围无效?

时间:2013-12-24 05:02:21

标签: javascript jquery plugins graphics range

我正在尝试在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 ,我不想因为这个原因而添加另一个依赖项。

2 个答案:

答案 0 :(得分:3)

您收到的错误是由于在某些情况下触发undefined处理程序时,邮箱是onmousemove

Hare是我注意到插件的一些问题:

  1. mini和maxi应该在onmousedown中计算,因为如果您更改相对对象的位置(拖动箭头),您使用的迷你和最大值仍将具有初始值
  2. 如果您不需要,请尝试在上下文功能中仅保存所需的值,而不是event之类的整个对象。最好只保存鼠标的起始Y坐标和箭头偏移所需的最高值。
  3. 您应该注意绑定的事件。例如,每次应用此插件时,都会为mousemovemouseup事件设置侦听器,而不是取消绑定它们。
  4. 第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

检查出来:http://jsfiddle.net/MattiasBuelens/yHAY9/5/