2016-07-30 66 views
0

Auf iPad Safari (und Desktop-Safari und Chrome), müssen horizontale Schieberegler auf einer Seite, die vertikal scrollt, wo die Schieberegler nicht versehentlich verschoben werden. Leider reagieren jQuery mobile Slider auf (unvollständige) vertikale Swipes auf dem iPad.Beschränken Sie den jQuery Mobile-Schieberegler auf Drücken-Halten-Ziehen

Ein guter Weg, um dies zu beheben, ist, die Schieberegler so einzustellen, dass der Knopf nur durch Drücken-Halten und Ziehen gedrückt werden kann. Hier ist, was ich habe zusammen gehackt (Anmerkung: dies funktioniert nur auf Touch-Interfaces):

<!DOCTYPE html> 
<html> 
<head> 
<meta name="viewport" content="width=device-width, initial-scale=1"> 
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css"> 
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> 
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script> 
<style> 
div.input-container { 
    -webkit-user-select: none; 
    -webkit-touch-callout: none; 
    -webkit-tap-highlight-color: rgba(0,0,0,0); 
} 
</style> 
</head> 
<body> 

<div id="top"> 
    <div> 
     <h1>Sliders for iPad</h1> 
    </div> 
    <div> 
     <label for="test1">Test:</label> 
     <div class="input-container"> 
      <input type="range" name="test1" value="50" min="0" max="100" disabled> 
     </div> 
    </div> 
    <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> 
    <div> 
     <label for="test2">Test:</label> 
     <div class="input-container"> 
      <input type="range" name="test2" value="50" min="0" max="100" disabled> 
     </div> 
    </div> 
    <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> 
    <div> 
     <label for="test3">Test:</label> 
     <div class="input-container"> 
      <input type="range" name="test3" value="50" min="0" max="100" disabled> 
     </div> 
    </div> 
</div> 

<script> 
$(function() { 

$(".input-container").addClass("disable-drag") 
    .on("taphold", tapholdHandler) 
    .on('touchmove', moveHandler) 
    .on('touchend', endHandler) 
; 

function moveHandler(event) { 
    var containingDiv = $(".input-container"); 
    if (!containingDiv.hasClass('disable-drag')) { 
     /// 
     console.log(event); 
     $('a').offset({left: event.originalEvent.targetTouches[0].clientX}); 
     var left = 68;///parseInt($('.ui-slider-track')[0].css('margin-left')); 
     var w = event.originalEvent.target.offsetWidth - left; 
     var percent = ((event.originalEvent.targetTouches[0].clientX - left)/w) * 100; 
     $('input').val(percent).slider('refresh'); 
     /// 
    } 
} 

function tapholdHandler(event) { 
    console.log(event) 
    var containingDiv = $(".input-container"); 
    if (containingDiv.hasClass('disable-drag')) { 
     containingDiv.removeClass("disable-drag"); 
     event.preventDefault(); 
     event.stopPropagation(); 
     $('input').slider('enable').slider('refresh'); 
    } 
} 

function endHandler(event) { 
    $('input').slider('disable').slider('refresh'); 
    $(".input-container").addClass("disable-drag") 
} 

}); 
</script> 
</body> 
</html> 

Der Schieber ist deaktiviert, bis ein Druckhalte erkannt wird, zu welchem ​​Zeitpunkt sie zum Leben entspringt, aktualisiert die Knopfposition und Wert, während der Benutzer zieht, und kehrt zurück, wenn die Berührung beendet wird. Es funktioniert irgendwie, aber ist zu spröde und ich möchte nicht im Wesentlichen die gleichen Kalkulationen machen, die der Slider schon macht. Zwischen den /// Markern möchte ich programmatisch auf die aktuelle Mausposition klicken, so dass sich der Knopf zu dieser Stelle bewegt - ohne die Geste "Drücken-Halten-Ziehen" zu unterbrechen. Ist das möglich? Hier ist, was ich versuchte, aber es funktioniert nicht:

/// 
$(".ui-slider-track").trigger('click'); //todo: narrow the selector to the target slider 
/// 

und

/// 
$(document.elementFromPoint(event.originalEvent.targetTouches[0].clientX, event.originalEvent.targetTouches[0].clientY)).click(); 
/// 

... oder gibt es eine andere mobile UI-Bibliothek mit Schiebern, die nicht auf vertikalen Seitenhiebe reagieren?

Antwort

0

Ok, ich fand eine ziemlich saubere einfache Lösung. Getestet auf iPad Safari. Außerdem wird das Textfeld aktiviert, sodass es direkt bearbeitet werden kann.

<script> 
    // The following manages the sliders so that vertical swiping (scrolling) never inadvertently changes a slider value 
    $(function() { 
     var timerId; 
     $.event.special.tap.tapholdThreshold = 250; // default is 750, but that seems too long for this scenario 

     $(".input-container") 
      .on('taphold', tapholdHandler) 
      .on('touchmove', moveHandler) 
      .on('touchend', endHandler) 
     ; 
     $('.input-container input') 
      .prop('disabled', false).removeClass('ui-state-disabled') // allow the user to edit the displayed value 
      .on('change', function() { 
       $(this).slider('refresh'); 
       $(this).prop('disabled', false).removeClass('ui-state-disabled'); // override the above line's disabling of the text field 
       $(this).blur(); 
      }) 
     ; 

     function tapholdHandler(event) { 
      $(event.currentTarget).find('input').slider('enable').slider('refresh'); 
     } 

     function moveHandler(event) { 
      if (timerId) 
       clearTimeout(timerId); // as long as the user is interacting with the slider, don't revert it to disabled 
      $(document.elementFromPoint(event.originalEvent.targetTouches[0].clientX, event.originalEvent.targetTouches[0].clientY)).trigger('vmousedown'); 
     } 

     function endHandler(event) { 
      $(document.elementFromPoint(event.originalEvent.changedTouches[0].clientX, event.originalEvent.changedTouches[0].clientY)).trigger('vmousedown').trigger('vmouseup'); // the purpose of this is to move the slider knob even if the user's touch didn't move 
      timerId = setTimeout(function() { // give the above induced event time to run the associated handler 
        $(event.currentTarget).find('input').slider('disable').slider('refresh'); 
        $(event.currentTarget).find('input').prop('disabled', false).removeClass('ui-state-disabled'); // allow the user to edit the displayed value 
      }, 2000); 
     } 
    }); 
</script>