2013-12-24 80 views
1

我想在jQuery中實現一個範圍選擇器插件。你可以看到有點工作的版本JavaScript中的範圍選擇器。範圍無效?

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的,我寧願不添加其他的依賴正因爲如此。

+0

您好像在這行上有一個錯誤'top:boxpos.top + event.pageY - mouse.pageY'其中boxpos沒有定義 – alnafie

+0

謝謝,但我也發現,在TypeError中說明:boxpos是undefined',但是我不確定它爲什麼沒有被定義。這就是我在這個問題中實際上要求的... –

回答

3

您收到是由於boxpos是在某些情況下undefinedonmousemove處理程序被觸發時的錯誤。

野兔一些問題,我用外掛注意:

  1. mini和馬克西應在onmousedown來計算,因爲如果你改變相對對象的位置(拖動箭頭)微型和馬克西您使用的將仍然具有初始值
  2. 嘗試在上下文功能中僅保存需要的值而不保存整個對象,如event,如果您不需要這樣做。最好保存鼠標的起始Y座標和箭頭偏移量所需的頂部值。
  3. 你應該注意你綁定的事件。例如,每次應用此插件時,您都會爲mousemovemouseup事件設置偵聽器,並且不會解除綁定。

點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"); 

這不是你想要獲得只是一個建議什麼的完整解決方案。

+0

雖然@MattiasBuelens的回答是正確的,但你更進一步地解決了我的問題,從而+1並接受了。在閱讀本文之前我已經注意到了第一點,第二點是由於許多嘗試/失敗和缺乏清理以及第三個我不知道的,謝謝你的一切。它不是一個完整的解決方案? –

+0

我想到了三件事:**我沒有在鉻以外的地方進行測試,箭頭應該到達頂部和底部(因此箭頭的位置到達了底部),並且,我並不喜歡那種需要緩存高度的多功能事物。 – tavi

1

問題是,您的插件不檢查被拖動的箭頭是否對應於此插件實例。更具體地說,$('.dragby')查詢返回兩個實例的相同元素,因此他們都認爲它們正在被拖動。當然,其中一個會失敗,因爲它還沒有設置boxpos

因此,您需要修改.dragby選擇器以確保它只檢查屬於當前實例的元素。現在,你現在,你只將dragby類應用到arrow變量。因此,一個解決辦法是檢查arrow元素具有dragby類:

if (arrow.hasClass('dragby')) { 
    arrow.offset({ ... }); 
    // ... 
} 

還有一個更簡單的解決方案,但:只保留一個布爾變量dragging周圍指示箭頭是否被拖動。 draggingmousedown上設置爲true,並在mouseup上覆位。然後,您可以在mousemove處理程序中檢查dragging

檢查出來:http://jsfiddle.net/MattiasBuelens/yHAY9/5/

+0

這只是以兩種不同的方式解決問題,同時讓我明白問題。現在我只動態地將maxi和mini設置爲其他箭頭。非常感謝! –