Amit J: Form Events in jQuery datepicker() benutzen

Hallo,

ich stehe mit jquery mal wieder auf Kriegsfuß. Ich habe ein formular mit mehrere Inputfelder und möchte mit datepicker bzw. timepicker einen Datum bzw. eine uhrzeit auswählen.

Mein Formular:

<form class="form-horizontal" role="form" id='frm_addAppointment_type' name='frm_addAppointment_type'>

                <div class="modal-body">
                    <div class="form-group">
                        <label for="frm_lbl_day" class="col-sm-2 control-label">Date</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_appointmentday' id='frm_appointmentday' value='' onchange="myFunction()">
                        </div>
                    </div> 
                    <div class="form-group">
                        <label for="frm_lbl_descr" class="col-sm-2 control-label">Description</label>
                        <div class="col-sm-8 required">
                            <input  name='frm_description' id='frm_description' value=''>
                        </div>
                    </div> 
                    <div class="form-group">
                        <label for="frm_lbl_start" class="col-sm-2 control-label">Start</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_appointmentstart' id='frm_appointmentstart' value=''>
                        </div>
                    </div> 
                    <div class="form-group">
                        <label for="frm_lbl_end" class="col-sm-2 control-label">End</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_appointmentend' id='frm_appointmentend' value='' >
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="frm_lbl_delay" class="col-sm-2 control-label">Delay</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_delay' id='frm_delay' value=''>
                        </div>
                    </div> 
                    <div class="form-group">
                        <label for="frm_lbl_logoname" class="col-sm-2 control-label">Logoname</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_logoname' id='frm_logoname' value=''>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="frm_lbl_docname" class="col-sm-2 control-label">Docname</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_docname' id='frm_doconame' value=''>
                        </div>
                    </div> 
                    <div class="form-group">
                        <label for="frm_lbl_deadline" class="col-sm-2 control-label">Deadline</label>
                        <div class="col-sm-8 required">
                            <p> 
                                <input type='text' name='frm_deadline_date' id='frm_deadline_date' value=''>
                                <input type='text' name='frm_deadline_time' id='frm_deadline_time' value=''>
                            </p> 
                        </div>
                    </div> 
                    <div class="form-group">
                        <label for="frm_lbl_pause" class="col-sm-2 control-label">Pause</label>
                        <div class="col-sm-8 required">
                            <input type='checkbox' name='frm_pause' id='frm_pause' value='1'>
                        </div>
                    </div>

                    <div class="form-group reveal-if-active">
                        <label for="frm_lbl_pausestart" class="col-sm-2 control-label">Pausestart</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_pausestart' id='frm_pausestart' value='' class="require-if-active" data-require-pair="#frm_pause">
                        </div>
                    </div> 
                    <div class="form-group">
                        <label for="frm_lbl_pauseend" class="col-sm-2 control-label">Pauseend</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_pauseend' id='frm_pauseend' value='' class="require-if-active" data-require-pair="#frm_pause">
                        </div>
                    </div> 
                    <div class="form-group">
                        <label for="frm_lbl_multiple" class="col-sm-2 control-label">Teilnehmerzahl</label>
                        <div class="col-sm-8 required">
                            <input type='text' name='frm_multiple' id='frm_multiple' value=''>
                        </div>
                    </div>
                    <input type='hidden' name='frm_tID' id='frm_tID' value=''>
                    <!--                Hier weitere forms-->
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                    <button type="button" class="btn btn-primary" id="add-appointment-type-save-btn" >Save</button>
                </div>

            </form>
   $("#frm_appointmentstart").timepicker();
   $("#frm_appointmentend").timepicker();
   $("#frm_deadline_time").timepicker();
   $("#frm_pausestart").timepicker();
   $("#frm_pauseend").timepicker();
   $( "#frm_appointmentday" ).datepicker();
   $( "#frm_deadline_date" ).datepicker();

Nun soll die Auswahl mancher Felder durch die Auswahl anderer Felder limitiert werden, doch egal was für ein event ich auswähle, die funktion wird nicht ausgeführt.

     $( "#frm_appointmentday" ).datepicker({
    
     onchange: function() {
          alert("test");
//        $( "#frm_deadline_date" ).datepicker( "option", "minDate", selectedDate );
        
      }
    });

Kann mir bitte jemand sagen woran das liegt?

Vielen Dank

Amit

  1. Hallo Amit J,

    Ich habe ein formular mit mehrere Inputfelder und möchte mit datepicker bzw. timepicker einen Datum bzw. eine uhrzeit auswählen.

    Nimm die richtigen Input-Typen und du solltest auf JQuery verzichten können. Bitter ist nur, dass bei CanIUse noch ziemlich viel rot ist. Daher ist meine Antwort nicht hilfreich.

    Bis demnächst
    Matthias

    --
    Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
    1. Ich habe es ebenfalls mit type="date" probiert. Hat irgendwie nichts geändert, verwende allerdings Firefox.

  2. Tach!

    Nun soll die Auswahl mancher Felder durch die Auswahl anderer Felder limitiert werden, doch egal was für ein event ich auswähle, die funktion wird nicht ausgeführt.

    Kannst du bitte deinen Problemfall auf das Nötigste reduzieren, das für die Nachstellung des Problems benötigt wird? Zum Beispiel ein oder zwei Formularfelder ohne unnötigen Ballast drumherum. Dieses Minimalbeispiel bitte bei jsfiddle oder ähnlich präsentieren. Und dann genau beschreiben, was bei welcher Bedienhandlung passieren soll und was nicht und was stattdessen passiert.

    dedlfix.

    1. Ich habe das jetzt so schlank gehalten wie das geht:

      Code in jsfiddle

      Ich habe im prinzip 2 inputfelder und ich möchte in Feld 2 Eingaben unterbinden, die größer sind als in Feld 1. Weil das eben nicht funktioniert hat, habe ich noch ein paar andere sachen probiert, die ebenfalls nicht funktionierten.

           $( "#frm_appointmentday" ).datepicker({
              onChange: function() {   alert("test");    },//wird nicht ausgefuehrt
              startDate: '2d'  //wird ausgefuehrt
          });
      
           $( "#frm_appointmentday" ).datepicker({
                 startDate: '2d',  //wird ausgefuehrt
                 onChange: function() {   alert("test");    }//wird nicht ausgefuehrt
          });
      
           $( "#frm_appointmentday" ).datepicker({
                 onChange: function() {   alert("test");    }//wird nicht ausgefuehrt
          });
      

      Ich habe das problem auch mit andere events. onSelect, onClose und oninput funktionieren ebenfalls nicht

      1. Hallo,

             $( "#frm_appointmentday" ).datepicker({
                onChange: function() {   alert("test");    },//wird nicht ausgefuehrt
                startDate: '2d'  //wird ausgefuehrt
            });
        
             $( "#frm_appointmentday" ).datepicker({
                   startDate: '2d',  //wird ausgefuehrt
                   onChange: function() {   alert("test");    }//wird nicht ausgefuehrt
            });
        
             $( "#frm_appointmentday" ).datepicker({
                   onChange: function() {   alert("test");    }//wird nicht ausgefuehrt
            });
        

        Ich habe das problem auch mit andere events. onSelect, onClose und oninput funktionieren ebenfalls nicht

        also ich weiß ja nicht, ob jQuery da sein eigenes Ding macht - aber in reinem Javascript werden die Evanthandler durchgehend klein geschrieben. Also onchange, nicht onChange.
        Es würde mich sehr wundern, wenn jQuery von dieser Konvention abweicht, das wäre dann wirklich verwirrend.

        So long,
         Martin

        --
        Es gibt eine Theorie, die besagt, dass das Universum augenblicklich durch etwas noch Komplizierteres und Verrücktes ersetzt wird, sobald jemand herausfindet, wie es wirklich funktioniert. Es gibt eine weitere Theorie, derzufolge das bereits geschehen ist.
        - (frei übersetzt nach Douglas Adams)
      2. Tach!

        Ich habe das jetzt so schlank gehalten wie das geht:

        Code in jsfiddle

        So ist das schon viel übersichtlicher.

        Ich habe im prinzip 2 inputfelder und ich möchte in Feld 2 Eingaben unterbinden, die größer sind als in Feld 1.

        Ich habe das problem auch mit andere events. onSelect, onClose und oninput funktionieren ebenfalls nicht

        Nun, wenn ich mir die Datepicker-Dokumentation so anschaue, dann gibt es das Event onChange gar nicht. onClose und onSelect hingegen schon, auch wenn sie sich unter options verstecken. Und onClose bekomme ich auf die von dir gezeigte Weise zum Laufen. Im Fiddle fehlte allerdings die Einbindung von jQuery und jQueryUI: neues Fiddle mit jQuery/UI. Die Browserkonsole, die man immer beim Entwickeln offenhaben muss, zeigte das Nichtvorhandensein von $ an.

        dedlfix.

      3. Das Fiddle hast Du aber nicht getestet, oder? Zumindest ist mal jQuery gar nicht als JavaScript-Extension gesetzt, und das reicht auch noch nicht, weil du auch jQuery UI verwendet. Welche Versionen bitte?

        1. Update:

          Ich habe mal die jeweils neuesten Versionen eingesetzt (wobei man jQueryUI von deren CDN holen muss, die Adresse trägt man unter External Resources ein. JQuery selbst kannst Du im JavaScript Fenster mit dem Zahnrad aktivieren). Gespeichert habe ich das nicht.

          Der DatePicker hat kein onChange Event, nur onSelect, onClose und onChangeMonthYear - letzteres fliegt vermutlich wenn Du prev/next drückst.

          Besser geht es so:

           $("#frm_appointmentday").datepicker().change(function(eventData) {
             
                 $("#frm_deadline_date").datepicker("option", "minDate", eventData.currentTarget.value);
           });
          
           $("#frm_deadline_date").datepicker();
          

          Allerdings weiß ich nicht was passiert, wenn der User ein Freiformat-Datum eingegeben hat, das keins ist. Ggf. brauchst Du noch eine Validierung; aber dafür gibt's ja Werkzeug genug ist der Kiste.

          Gruß
          Rolf

          1. Tach!

            Allerdings weiß ich nicht was passiert, wenn der User ein Freiformat-Datum eingegeben hat, das keins ist.

            Dann, kann ich mir vorstellen, wird das onchange-Event feuern, aber nicht das vom Datepicker sondern vom darunterliegenden input-Element.

            dedlfix.

            1. Danke erstmal für die Hilfen.

              kleiner Update: Ich jetzt die ganze Zeit versucht irgendwelche jquery bibliotheken einzubinden, was nicht geholfen hat. Ich verwende anscheinend den timepicker von bootstrap, was anscheinend nichts mit jquery zu tun hat. Ich verstehe nicht ganz was es damit auf sich hat, aber mit jetzt funktioniert es teilweise.

              $( "#frm_appointmentday" ).datepicker().on("changeDate", function(e) 
                      {
                      alert(e.currentTarget.value); // funktioniert
                      $("#frm_deadline_date").datepicker("option", "minDate", e); //funktioniert nicht
                      } );
              
              1. Tach!

                Ich verwende anscheinend den timepicker von bootstrap, was anscheinend nichts mit jquery zu tun hat.

                Es ist immer gut, wenn man weiß, was man verwendet, damit man in die passende Dokumentation schauen kann. ;)

                        $("#frm_deadline_date").datepicker("option", "minDate", e); //funktioniert nicht
                

                In der verlinkten Dokumentation sind andere Parameternamen genannt, in dem Fall startDate. Und die Übergabe erfolgt wohl auch anders, als Objekt: .datepicker({optionsName: wert, optionsName: wert, ...})

                dedlfix.

                1. Es ist immer gut, wenn man weiß, was man verwendet, damit man in die passende Dokumentation schauen kann. ;)

                  Das stimmt. Jetzt klappt es soweit.

                          $( "#frm_appointmentday" ).datepicker({startDate : '+1w'}).on("changeDate", function(e) 
                          {
                          alert(e.currentTarget.value);
                          $("#frm_deadline_date").datepicker({ 
                               startDate : '+2d', 
                               endDate :  e.currentTarget.value});
                          } );  
                  

                  timepicker funktioniert allerdings nicht analog, bzw ich habe wieder die falsche Dokumentation?

                     $("#frm_appointmentstart").timepicker({defaultTime: false}).on('hide.timepicker', function(e) {
                        $("#frm_appointmentend").timepicker({
                            defaultTime: false,   //funktioniert
                            minTime: e.time.value // funktioniert nicht
                        });
                        console.log('The time is ' + e.time.value);//"The time is 1:15 PM"
                    });
                  
                  1. Tach!

                    timepicker funktioniert allerdings nicht analog, bzw ich habe wieder die falsche Dokumentation?

                    Das weiß ich nicht. Bootstrap hat weder Date- noch Timepicker an Bord. Du musst da wohl da schauen, wo du die Komponenten herbekommen hast. Vielleicht steht das in den Dateien, die du für diese Komponenten einbindest.

                    dedlfix.

                  2. WTF? timepicker.co liefert eine Doku für ein jQuery Plugin?

                    timepicker.co ist eine Seite mit der TLD von Kolumbien, der Besitzer der URL versteckt sich hinter einem Guard-Dienst aus Panama - diese Seite ist offenbar ein Abrufgenerator für Werbung.

                    Die Doku für jQuery UI steht hier: http://api.jqueryui.com - allerdings hat jQuery UI keinen TimePicker. D.h. du verwendest zumindest noch eine weitere Komponente.

                    Die Plugin-Registry für jQuery steht hier: https://plugins.jquery.com/ - zu den Plugins sollte es jeweils auch eine Doku geben.

                    So. Und jetzt gehe in Dich, bzw. in deine Seite, und erforsche die Inklusionen deines Script-Dschungels.

                    Rolf

                    1. Ich habe das jetzt einfach mit Select gemacht und das funktioniert ganz gut, obwohl ich irgendwo gelesen habe, dass man in jQuery keine for-Schleifen benutzen sollte. Hier nochmal der fertige code.

                      $(document).ready(function() {
                          //disable alle selects, die von "frm_appointmentstart" abhaengen
                          $("#frm_appointmentend").attr('disabled','disabled');
                          $("#frm_pausestart").attr('disabled','disabled');
                          $("#frm_pauseend").attr('disabled','disabled');
                      
                      
                         $("#frm_appointmentstart").on( "change", function(){
                                  
                                 var index = document.getElementById("frm_appointmentstart").selectedIndex;
                                 var length=document.getElementById("frm_appointmentstart").length;
                                 var start = document.getElementById("frm_appointmentstart");
                                 var end = document.getElementById("frm_appointmentend");
                                 var p_start = document.getElementById("frm_pausestart");
                                 var p_end = document.getElementById("frm_pauseend");
                                 //enable end
                                 $("#frm_appointmentend").attr('disabled', false);
                                 $('select').not(this).prop('selectedIndex',0);   
                                //disable options depended by start
                                 for(var i=1; i<length; i++){
                                     if(i<=index){
                                         end.options[i].disabled=true;
                                         p_start.options[i].disabled=true;
                                     }
                                 }
                                
                                 $("#frm_appointmentend").on( "change", function(){
                                         var index = document.getElementById("frm_appointmentend").selectedIndex;
                                         //enable p_start
                                         $("#frm_pausestart").attr('disabled', false);
                                         $('#frm_pausestart').prop('selectedIndex',0);
                                        //disable options depended by end
                                         for(var i = 1; i < length; i++){                      
                                             if(i >= index){
                                                
                                                 p_start.options[i].disabled=true;
                                                 p_end.options[i].disabled=true;
                                             }
                                         }
                                                         
                      
                                          $("#frm_pausestart").on( "change", function(){
                                            
                                             var index = document.getElementById("frm_pausestart").selectedIndex;
                                             //enable p_end
                                             $("#frm_pauseend").attr('disabled', false);   
                                             $('#frm_pauseend').prop('selectedIndex',0);
                                             // disable options depended by p_start   
                                             for(var i = 1; i < length; i++){
                                                 if(i <= index){
                                                     p_end.options[i].disabled=true;
                                                 }
                                             }
                                         });    
                                 });  
                      
                         }); 
                      
                      //alle Felder auf default zurücksetzen
                       $("#add-appointment-type-reset-btn").on('click', function(){
                                 var length=document.getElementById("frm_appointmentstart").length;
                                 var start = document.getElementById("frm_appointmentstart");
                                 var end = document.getElementById("frm_appointmentend");
                                 var p_start = document.getElementById("frm_pausestart");
                                 var p_end = document.getElementById("frm_pauseend");
                                 $("#frm_appointmentend").attr('disabled', true);
                                 $("#frm_pauseend").attr('disabled', true);
                                 $("#frm_pausestart").attr('disabled', true);
                                 $('select').each(function(){
                                    $(this). prop('selectedIndex',0)
                                 }); 
                      
                                 $('input').each(function(){
                                     $(this).val("");
                                 });  
                                 for(var i=1; i<length; i++){
                                      start.options[i].disabled=false;
                                      end.options[i].disabled=false;
                                      p_start.options[i].disabled=false;
                                      p_end.options[i].disabled=false;
                                     }      
                       });
                      });    
                      
                      1. Tach!

                        Ich habe das jetzt einfach mit Select gemacht und das funktioniert ganz gut, obwohl ich irgendwo gelesen habe, dass man in jQuery keine for-Schleifen benutzen sollte.

                        Das glaube ich nicht, dass das so eine pauschale Aussage war. Du mixt hier fröhlich jQuery und direkte Elementzugriffe. Das ist nicht konsistent, kann man aber machen. Deine for-Schleifen lässt du jedoch nur auf die nativen Elemente los und für jQuery nimmst du dessen each(). Also hast du auch keine for-Schleife mit jQuery verwendet.

                        dedlfix.

                      2. Mit dem for(;;) habe ich keine Probleme. Gewaltige Probleme bekommt dein Browser aber mit dem on im on im on. Jeder Change auf frm_appointmentstart registriert einen weiteren change-Handler auf frm_appointmentend. Nach 20 Changes auf start hast du 20 Change-Handler auf end. Und jeder von denen registriert einen weiteren Change-Handler auf pausestart. Wenn Du also 20 Handler auf end hast und 20 mal das change-Event auf end ausgelöst wurde, fliegen da 400 change-Handler auf pausestart herum.

                        Diese Registrierungen müssten wohl eher nacheinander als ineinander erfolgen.

                        Sodann würde ich Dir empfehlen, deinen Code gründlich aufzuräumen.

                        1. Erzeuge die Zugriffsvariablen für die frm_-Elemente direkt in der ready-Function statt in den on Handlern. Ich habe mich zwar vor einiger Zeit dagegen ausgesprochen, aber solange keiner am DOM rumfummelt und diese Elemente rausschmeißt, wird das funktionieren.
                        2. index und length solltest du dagegen in den on-Handlern belassen. Und du kannst die anderen Zugriffsvariablen dafür benutzen, also z.B. var index = start.selectedIndex;
                        3. Statt das disabled-Attribut mit $('#id1').attr('disabled', 'disabled') zu setzen kannst Du, wenn Du ohnehin eine Referenz auf das Element mit der ID in einer Variablen hast, direkt auf das DOM Property zugreifen und frm_id1.disabled = true schreiben. Analoges gilt für Property-Modifikationen mit .prop(): p_start.selectedIndex = 0 ist doch viel schöner als dieser jQuery-Klumpen.
                        4. Lagere die Schleife, die die Options disabled, in eine eigene Funktion aus. Die Funktionsdeklaration kannst Du an den Anfang oder das Ende deines Ready-Handlers stellen. Nur nicht in die change-Handler hinein (sonst musst Du sie dreimal schreiben und das ist nicht Sinn der Sache).

                        D.h. skelettartig sähe dein Ready-Handler dann so aus:

                        // kurzform von $(document).ready(function(){ ... })
                        $(function() {
                           function enableOptions(element, enable, from, to) {
                              for (var i=from; i<=to; i++) {
                                 element.options[i].disabled = enable;
                              } 
                           }
                           var start=document.getElementById("frm_appointmentstart"),
                           var end = ..., p_start = ..., p_end = ...;
                           end.disabled = true;
                           p_start.disabled = true;
                           p_end.disabled = true;
                        
                           // jQuery versteht auch DOM Referenzen.
                           // Vermeidet die Wiederholung der ID und ist einen Tick schneller.
                           $(start).on("change", function() {
                              var index = start.selectedIndex;
                              var length = start.length;
                              end.disabled = false;
                              $('select').not(this).prop('selectedIndex',0);   // hm, der muss vermutlich bleiben
                              enableOptions(end, false, 1, index);
                              enableOptions(p_start, false, 1, index);
                           });
                           $(end).on("change", function() {
                              var index = ...
                              p_start.disabled = false;
                              p_start.selectedIndex = 0;
                              disableOptions(p_start, false, index, length-1);
                              disableOptions(p_end, false, index, length-1);
                           });
                           $(p_start).on("change", function() {
                              // analog
                           });
                           $("#add-appointment-type-reset-btn").on('click', function() {
                              // start, end, p_start, p_end sind schon da
                              // length hier ermitteln
                              // disable und selectedIndex=0 
                              $('input').val('');  // nicht each(function(){...})
                              $('select').prop('selectedIndex', 0); // nicht each(function(){...})
                        // oder $('select').each(function() { this.selectedIndex = 0; });
                        // oder $('select').each((i,x) => x.selectedIndex = 0);
                        
                              // jetzt noch 4x enableOptions(xxx, false, 1, length-1) aufrufen
                           });
                        });
                        

                        Hinweis zu dem each((i,x)=>x.selectedIndex=0) - das ist eine Arrow-Function, eine Kurzschreibweise für function(i,x) { x.selectedIndex=0; }.

                        Gruß Rolf