jQueryUi und moment.js aus Rangeslider wird ein Timeslider


Da ich für ein privates Projekt einen Zeitslider benötigte habe, habe ich mich einfach bei dem bereits vorhandenen Slider von jqueryUi bedient und diesen dementsprechend angepasst, das dieser jetzt die Uhrzeit “anzeigt”. Das ganze sieht dann z.B. mit Twitter Bootstrap folgendermaßen aus:

image

Mit dem Slider kann die jeweils passende Uhrzeit ausgewählt werden und auch über die “Plus” und “Minus” Symbole an den jeweiligen enden lässt sich die Zeit einstellen. Die Uhrzeit wird in zwei getrennten Textboxen angezeigt und entsprechend aktualisiert.

Damit ich mich nicht groß um das Umrechnen und Anzeigen der Uhrzeit kümmern muss habe ich hier noch auf das NuGet Package von “moment.js” zurückgegriffen. Es wird außerdem die aktuellste Version von jQuery und jQueryUi inkl. der passenden jQueryUiStyles benötigt.

Das folgende HTML Konstrukt dient als Grundlage für den JavaScriptCode

<label for="amount">Timerange: </label>
<input id="StartTime" readonly="readonly" class="text-box single-line input-mini uneditable-input"
    type="time" value="07:00" name="StartTime" data-val="true">
bis
<input id="EndTime" readonly="readonly" class="text-box single-line input-mini uneditable-input"
     type="time" value="16:00" name="EndTime" data-val="true">
Uhr

    <div style="margin-top: 5px; height: 23px;" class="well">
        <div class="row">
            <div class="span11">
                <div id="slider-range"></div>
            </div>
            <div class="row">
                <div style="padding-left: 20px;" class="span1">
                    <i id="addOneStart" class="icon-plus"></i>
                    <i id="subOneStart" class="icon-minus"></i>
                </div>
                <div class="span9"></div>
                <div style="margin-right: -10px" class="span1 pull-right">
                    <i id="subOneEnde" class="icon-minus"></i>
                    <i id="addOneEnde" class="icon-plus"></i>
                </div>
            </div>
        </div>
    </div>

Den Slider definierten und die Startwerte in den Textboxen auslesen. Unter “values” werden im Slider die Standardstartwerte angegeben in Minuten. Außerdem ist der “max” wert mit 1440 belegt, was 24 Stunden * 60 Minuten entspricht und die Minuten für einen Ganzen Tag ergibt. Die Stepsize kann extra definiert werden, da wir auf diese später noch zugreifen.

var stepSize = 5; //anzahl der Minuten die gesetzt werden sollen

//Slider definieren
var slider = $("#slider-range").slider({
    range: true,
    min: 0,
    max: 1440,
    step: stepSize,
    values: [420, 900],
    slide: function (event, ui) {
        //Die Start und Endezeit des Sliders ermitteln die gerade ausgeählt sind.
        var start = moment("HH:mm", "00:00").minutes(ui.values[0]),
            ende = moment("HH:mm", "00:00").minutes(ui.values[1]);
        $("#StartTime").val(start.format("HH:mm"));
        $("#EndTime").val(ende.format("HH:mm"));
    }
});

//Beim Start des Programm die passende Start und Endezeit in die Textboxen eintragen.
var start = moment("HH:mm", "00:00").minutes($("#slider-range").slider("values", 0)),
    ende = moment("HH:mm", "00:00").minutes($("#slider-range").slider("values", 1));
$("#StartTime").val(start.format("HH:mm"));
$("#EndTime").val(ende.format("HH:mm"));

Hinzufügen unserer Click Eventhandler für die “Plus” und “Minus” Zeichen am Slider. Diese rufen die jeweils passende Funktion zum setzten des Linken bzw. Rechten Sliders auf.

 //Eventhandler erstellen für die + und - Bilder zum setzten der passenden Zeiten
 $("#addOneStart").on("click",function () {
     setSliderStart(0, '#StartTime', stepSize);
 });
 
 $("#subOneStart").on("click", function () {
     setSliderStart(0, '#StartTime', -1 * stepSize);
 });
 
 $("#addOneEnde").on("click", function () {
     setSliderEnde(1, '#EndTime', stepSize);
 });

 $("#subOneEnde").on("click", function () {
     setSliderEnde(1, '#EndTime', -1 * stepSize);
 });

Dann fehlen noch unsere beiden Funktionen die die jeweiligen “Plus” und “Minus” Operationen für den Linken und Rechten Slider ausführen. Wir benötigen in beiden Funktionen immer die aktuelle Start- und Endezeit des Sliders, damit wir überprüfen können ob der Slider auch nicht zu weit nach rechts oder links bewegt wird und damit ein ungültiger Zustand entsteht.

Für das Setzten des linken Sliders wird die Funktion “slider.slider(‘values’, 0, startMinutes + diff);” verwendet und für das Setzten des rechten Sliders wird die Funktion “slider.slider(‘values’, 1, startMinutes + diff);” verwendet (ich übergebe hier den passenden ‘index’).

//Den Startzeitslider setzten
function setSliderStart(index, timeId, diff) {
    //Auslesen der aktuellen Oberflächenwerte
    var startTime = $("#StartTime").val(),
    endTime = $("#EndTime").val(),
    ende = moment(endTime, "HH:mm"),
    start = moment(startTime, "HH:mm"),
        //die passenden Start und Endeminuten berechnen die aktuell angezeigt werden.
    startMinutes = start.hours() * 60 + start.minutes(),
    endMinutes = ende.hours() * 60 + ende.minutes();
    //Prüfen das die Slider sich nicht "vertauschen" Min und Max Value prüfen
    if ((startMinutes + diff) <= endMinutes && (startMinutes + diff) >= 0) {
        //http://stackoverflow.com/questions/2833396/jquery-ui-slider-setting-programatically
        //der Index gibt an welcher Slider gesetzt werden soll der für Min oder Max
        slider.slider("values", index, startMinutes + diff);
        //Prüfen ob die Minuten addiert oder Subtrahiert werden sollen
        if (diff < 0) {
            $(timeId).val(start.subtract("m", stepSize).format("HH:mm"));
        } else {
            $(timeId).val(start.add("m", stepSize).format("HH:mm"));
        }
    }
}

//Den Endezeitslider setzten
function setSliderEnde(index, timeId, diff) {
    var startTime = $("#StartTime").val(),
    endTime = $("#EndTime").val(),
    ende = moment(endTime, "HH:mm"),
    start = moment(startTime, "HH:mm"),
    startMinutes = start.hours() * 60 + start.minutes(),
    endMinutes = ende.hours() * 60 + ende.minutes();
    if (startMinutes <= (endMinutes + diff) && (endMinutes + diff) < 1440) {
        slider.slider("values", index, endMinutes + diff);
        if (diff < 0) {
            $(timeId).val(ende.subtract("m", stepSize).format("HH:mm"));
        } else {
            $(timeId).val(ende.add("m", stepSize).format("HH:mm"));
        }
    }
}

Leider funktioniert der Slider noch nicht auf Touchgeräten, daher habe ich auch die “Plus” und “Minus” Zeichen eingefügt. Es sollte auch kein Problem darstellen das Projekt zu erweitern und die Textfelder bearbeitbar zu machen für Touchgeräte.

Quellen:

http://stackoverflow.com/questions/2833396/jquery-ui-slider-setting-programatically

http://jqueryui.com/slider/#range

Codeplex:

Dann unter “Source Code” –> “Browse” –> “Testprojekte” –> “Mvc4WebApiKoTb” hier dann die Wichtigste Datei im Webprojekt unter “Views/Home/TimeSlider.cshtml”. Das Projekt sollte auch so lauffähig sein.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s