Advitum.de auf Google+

Nutzeroberflächen fürs iPad – jQuery UI Slider

Nutzeroberflächen fürs iPad – jQuery UI Slider
VN:F [1.9.22_1171]
Bewertung: 3.5/5 (8 Stimmen abgegeben)
Von am
Kategorien: Arbeit, jQuery, Quick-Tips, Tipps, Tutorials

Mittlerweile sollte ja bekannt sein das ich ein jQuery-Junkie bin. Und mit »Junkie« meine ich, dass ich alles nur noch mit jQuery mache – dynamische Nutzeroberflächen, Webanwendungen ohne ein einziges Neuladen der Seite oder eben auch intuitive Bedienelemente wie zum Beispiel Slider. Für Nutzeroberflächen und Slider benutze ich, ganz konkret gesagt, das jQuery-Plugin jQuery UI. Wer jQuery kennt kennt vermutlich auch jQuery UI – das soll ja auch nicht das Thema des Artikels werden – ein paar Links zum Thema findet ihr am Ende aber trotzdem dazu.

Nutzeroberflächen fürs iPad - jQuery UI Slider, 3.5 out of 5 based on 8 ratings

Jedenfalls arbeitete ich neulich an einer Nutzeroberfläche mit Schiebereglern – alles sollte intuitiv bedienbar sein. Die Obefläche war fertig und wurde zum Testen freigegeben. Doch dann das vernichtende Urteil. »Das läuft ja überhaupt nicht bei mir« teilte uns der Kunde mit. Was war passiert? Bei unseren Test hatte alles so wunderbar funktioniert. Schuld war das iPad. Während sich die Nutzeroberfläche super mit einer Maus bedienen ließ, funktionierte der Slider aus dem jQueryUI-Repertoire auf dem iPad.

Sechs Slider, einer horizontal und fünf vertikal.
Slider sind zwar eine feine Sache und mit jQueryUI sehr leicht zu realisieren, aber leider funktionieren sie nicht auf dem iPad.

Im Internet bin ich auf einige jQuery-Plugins gestoßen, welche den vollen Funktionsumfang von jQuery UI boten und auf dem iPad funktionierten, allerdings arbeiteten sie nicht reibungslos mit dem Rest der Nutzeroberfläche zusammen, das Ergebnis war alles andere als zufriedenstellend. Außerdem erschien es mir übertrieben, ein weiteres Monster-Plugin zu verwenden, wo doch lediglich die Slider nicht iPad-tauglich waren. Kurzerhand entschloss ich mich, die Funktionalität der Slider auf das iPad zu portieren.

Was ist eigentlich das Problem? Warum funktioniert der Slider auf dem PC aber nicht auf einem iPad? Im Grunde liegt die Antwort recht nahe und macht auch recht viel Sinn, ist allerdings auch ziemlich ärgerlich für Webentwickler, die auch für das iPad entwickeln. Das iPad arbeitet nämlich mit Gesten des Nutzers. Tippt er einmal mit dem Finger auf die Oberfläche, wird ein Klick ausgeführt. Klicken und Ziehen ist aber nicht möglich, denn diese »Wischbewegung« wird vom iPad als Scrollen interpretiert. Deshalb werden bei dem Slider nicht die nötigen Klick-Events ausgelöst und der Griff des Schiebereglers lässt sich nicht bewegen.

Glücklicherweise lässt sich dieses Problem mit ein wenig Tüftelei recht leicht beheben. Wir müssen nur die Touch-Events, die auf dem iPad ausgelöst werden, abfangen und manuell den neuen Wert an den Slider senden.

$('.ui-slider-handle').bind('touchmove', function(event)
{
	//Dieses Event wird beim Ziehen des Sliders auf dem iPad ausgelöst.
});

Hier müssen wir jetzt nichts weiter tun als aus der Position des Griffs auf dem Slider den neuen Wert zu errechnen und diesen an den Slider zu übergeben.

$('#slider.ui-slider-handle').bind('touchmove', function(event)
{
	// Wir brauchen die X- und Y-Position des Fingers, jQuery unterstützt diese Eigenschaft noch nicht, deshalb brauchen wir das Original-Event
	var e = event.originalEvent;
	
	// Ermitteln der Position des Sliders
	var left = $('#slider').offset().left;
	var right = left + $("#slider").width();
	
	// Minimaler und maximaler Wert des Sliders
	var min = $("#slider").slider('option', 'min');
	var max = $("#slider").slider('option', 'max');
	
	// Mithilfe von einfachem Dreisatz können wir berechnen, welchen Wert die neue Position ergibt
	var newvalue = min + (e.touches.item(0).clientX-left)/(right-left)*(max-min);

	// Jetzt setzen wir den neuen Wert
	$('#slider').slider('value', newvalue);
});

Und schon funktioniert der Slider auch auf dem iPad.

Jetzt seid ihr dran!

Ich hoffe, dieses Script erspart irgendwem ein wenig Arbeit. Über Feedback würde ich mich freuen. Wie findet ihr das Snippet? Welche Erfahrungen habt ihr mit dem iPad gemacht? Hinterlasst mir einen Kommentar!

Nutzeroberflächen fürs iPad - jQuery UI Slider, 3.5 out of 5 based on 8 ratings

Links zum Thema

Jetzt seid ihr dran!

Teilt eure Meinung mit uns in den Kommentaren, gebt eine Bewertung für diesen Artikel ab und teilt ihn in Social Networks!

Über

Ich bin ein junger Webdesigner und Programmierer aus Siegen und blogge auf Advitum.de über meine Erfahrungen im Web. Meine Themenschwerpunkte liegen im Bereich der Web-Entwicklung mit PHP, JavaScript, HTML und anderen Script-, Programmier- und Markup-Sprachen, der Nutzung von Content Management System wie Typo3, Wordpress etc. und der Effekt-Hascherei mit Photoshop. Seit 2008 blogge ich auf Advitum.de – mal mehr, mal weniger regelmäßig – über alles, was mich so interessiert. Wenn dir mein Blog gefällt, freue ich mich immer sehr über Feedback in Form von Kommentaren und E-Mails.

Kommentare zu diese Artikel

Schreibe jetzt einen Kommentar!

keschmidt schrieb am Antworten

Cool! Das ist die beste Lösung, die ich bisher zum jquery slider gefunden habe.

Leider gelingt es mir nicht, damit mehrere Slider unabhängig voneinander zu verschieben. Deine Grafik lässt aber vermuten, dass es doch geht. Hast du eine funktionierende Lösung?

    Lars Ebert schrieb am Antworten

    Dafür haben wir zwei Möglichkeiten:

    Zum einen können wir jedem Slider eine eindeutige ID geben (macht ja sowieso Sinn wenn man mit den Werten arbeiten will) und schreibt das Snippet für jede ID neu.

    Zu anderen, und das ist die bessere Variante, könnte man den Code etwas abändern:

    $('.ui-slider-handle').bind('touchmove', function(event)
    {
    	// Wir brauchen die X- und Y-Position des Fingers, jQuery unterstützt diese Eigenschaft noch nicht, deshalb brauchen wir das Original-Event
    	var e = event.originalEvent;
    
    	// Ermitteln der Position des Sliders
    	var left = this.parent().offset().left;
    	var right = left + this.parent().width();
    
    	// Minimaler und maximaler Wert des Sliders
    	var min = this.parent().slider('option', 'min');
    	var max = this.parent().slider('option', 'max');
    
    	// Mithilfe von einfachem Dreisatz können wir berechnen, welchen Wert die neue Position ergibt
    	var newvalue = min + (e.touches.item(0).clientX-left)/(right-left)*(max-min);
    
    	// Jetzt setzen wir den neuen Wert
    	this.parent().slider('value', newvalue);
    });
    

    So funktioniert der Code automatisch mit allen Slidern.

Thorsten schrieb am Antworten

Hi,

super Tutorial, jedoch will es bei mir nicht funktionieren.

Mal mein Code anbei:

Slider:
$(function() {
// Inhalt laden
aktualisieren();
$( "#slider-rabatt" ).slider({
range: true,
min: 0,
max: $('input[name=highestrabatt]').val(),
values: [ 0, 100 ],
change: function( event, ui ) {
$('#img_loading').fadeIn('slow', function() {
loadIn();
});

aktualisieren();

$('#img_loading').fadeOut('slow', function() {
loadOut();
});
},
slide: function( event, ui ) {
$( "#rabatt" ).val( ui.values[ 0 ] + " % - " + ui.values[ 1 ] + " %" );
}
});
$( "#rabatt" ).val( $( "#slider-rabatt" ).slider( "values", 0 ) +
" % - " + $( "#slider-rabatt" ).slider( "values", 1 ) + " %" );

if( $('input[name=highestrabatt]').val().length == 0 ) {
$( "#slider-rabatt" ).slider({ disabled: true });
}
});

Und dann dein Code angepasst:
$('.ui-slider-handle').bind('touchmove', function(event) {
// Wir brauchen die X- und Y-Position des Fingers, jQuery unterstützt diese Eigenschaft noch nicht, deshalb brauchen wir das Original-Event
var e = event.originalEvent;

// Ermitteln der Position des Sliders
var left = $('#slider-rabatt').offset().left;
var right = left + $("#slider-rabatt").width();

// Minimaler und maximaler Wert des Sliders
var min = $("#slider-rabatt").slider('option', 'min');
var max = $("#slider-rabatt").slider('option', 'max');

// Mithilfe von einfachem Dreisatz können wir berechnen, welchen Wert die neue Position ergibt
var newvalue = min + (e.touches.item(0).clientX-left)/(right-left)*(max-min);

// Jetzt setzen wir den neuen Wert
$('#slider-rabatt').slider('value', newvalue);
});

Aber auf dem iPad tut sich leider gar nichts.
Hast du einen Tipp?

    Lars Ebert schrieb am Antworten

    Am besten checkst du mal alle Klassennamen bzw. IDs durch, ob die auch stimmen. Wird denn ein Fehler ausgeworfen vom Browser? Was genau passiert denn?

Mi schrieb am Antworten

Hallo,
danke für die Tipps aber leider klappt das ganze bei mir mit eine Vertical-Slider nicht kannst du mir helfen bitte?

    Lars Ebert schrieb am Antworten

    Der Code arbeitet mit den horizontalen Abständen. Um ihn für vertikale Slider anzupassen, musst du folgenden Code benutzen:

    [js]$(‚#slider.ui-slider-handle‘).bind(‚touchmove‘, function(event)
    {
    // Wir brauchen die X- und Y-Position des Fingers, jQuery unterstützt diese Eigenschaft noch nicht, deshalb brauchen wir das Original-Event
    var e = event.originalEvent;

    // Ermitteln der Position des Sliders
    var top = $(‚#slider‘).offset().top;
    var bottom = top + $("#slider").height();

    // Minimaler und maximaler Wert des Sliders
    var min = $("#slider").slider(‚option‘, ‚min‘);
    var max = $("#slider").slider(‚option‘, ‚max‘);

    // Mithilfe von einfachem Dreisatz können wir berechnen, welchen Wert die neue Position ergibt
    var newvalue = max – (e.touches.item(0).clientY – top)/(bottom – top)*(max – min);

    // Jetzt setzen wir den neuen Wert
    $(‚#slider‘).slider(‚value‘, newvalue);
    });[/js]

Cheesi schrieb am Antworten

Danke Danke Danke du bist Gott und ein Heiliger gleichzeitig 😉
Funktioniert auch unter Anroid wenn auch nur recht mager. Um anständige Klicks hinzubekommen muss ziemlich nahe ran zoomen. Zudem erfasst es auch nicht jeden Klick. Allerdings besser als nichts 🙂 Nochmal vielen Dank

    Cheesi schrieb am Antworten

    Ach ja was ich vorhin vergessen habe sliden selber funktioniert nicht, aber man kann es mit klicken bestimmen (Anroid).

Titus schrieb am Antworten

Hab mich sehr gefreut… aber es nicht wirklich zum Laufen bekommen.
Das Tippen auf dem Slider funktioniert doch auch auf dem iPad.
Nur das „Ziehen“ geht nicht. Ich bekomme den Handle aber nicht gezogen.
Hast Du ne Demo irgendwo? Oder funktioniert das nicht mit allen Slider-Optionen? Hier mein Aufruf des Sliders:

$( „#familie-slider1“ ).slider({
range: „max“,
min: 0,
max: 10,
value: 0,
slide: function( event, ui ) {
$( „#familie-wichtigkeit“ ).val( ui.value );
}
});

    Lars Ebert schrieb am Antworten

    Eigentlich sollte das so funktionieren. Lass dir mal in der callback-Funktion für das Event irgendwas per alert() ausgeben und schau, ob das Event überhaupt ausgelöst wird.

Jörg schrieb am Antworten

nachdem das mit dem Bind bei mir im ersten Anlauf nicht funktioniert hat, habe ich ein leerzeichen nach dem „#slider“ eingefügt ..
also aus:
$(‚#slider.ui-slider-handle‘).bind(‚touchmove‘, function(event)
das gemacht:
$(‚#slider .ui-slider-handle‘).bind(‚touchmove‘, function(event)

dann hat der Zugriff auf den Bind funktioniert.

zusätzlich hab ich auch noch das nachfolgende eingefügt…

$(‚#slider .ui-slider-handle‘).bind(‚touchstart‘, function(event)
{
event.preventDefault();
console.log(„touchstart erfolgreich“);
});

Tom schrieb am Antworten

Vielen Dank, hast mir ein paar Stunden Arbeit erspart 🙂

    Tom schrieb am Antworten

    Funktioniert zwar auf ipad, aber leider nicht auf anderen mobilen Geräten wie meinem SGS2, Hier meine aktuelle Lösung für die Suchenden:

    slider.on(‚touchstart touchmove touchend‘, ‚a.ui-slider-handle‘, function (event) {
    //mousevents to simulate on touch
    var touchEvents = {
    touchstart: ‚mousedown‘,
    touchmove: ‚mousemove‘,
    touchend: ‚mouseup‘
    };

    //get element and type of event to simulate
    var simulatedEvent = touchEvents[event.originalEvent.type],
    touch = event.originalEvent.changedTouches[0],
    mouseEvent = document.createEvent(‚MouseEvent‘);

    //return if no mouse event is matched
    if (typeof simulatedEvent === ‚undefined‘) {
    return;
    }

    //init the mousevent if we have a matched event
    mouseEvent.initMouseEvent(
    simulatedEvent, //type
    true, //bubbles
    true, //cancelable
    window, //view
    1, //detail
    touch.screenX, //screenX
    touch.screenY, //screenY
    touch.clientX, //clientX
    touch.clientY, //clientY
    false, //ctrlKey
    false, //altKey
    false, //shiftKey
    false, //metaKey
    0, //button
    null //related target
    );

    //dispatch event on touched element
    touch.target.dispatchEvent(mouseEvent);
    event.preventDefault();
    });

    Ich habe die Touchevents quasi in Mouseevents übersetzt, funktioniert in ersten Tests recht gut.

Diese Artikel könnten dir auch gefallen