Barksalot: Bei Klick auf checkbox Update ausführen und Text durchstreichen

Hallo,

ich möchte gerne meine kleine ToDo Liste etwas erweitern.

<?php foreach($ToDoListeAusagabe as $array){ ?>
<div>
  <label>
    <input type="checkbox" 
           name="code" 
           value="<?php echo htmlspecialchars($array['pt_code']); ?>">
		<?php echo htmlspecialchars($array['pt_titel']); ?>
  </label>
</div>
<?php } ?>

Wenn ich jetzt auf eine Checkbox klicke möchte ich gerne im Hintergrund ein Update in meiner mySQL Tabelle ausführen. Der status soll von 0 auf 1 gesetzt werden. Gleichzeitig möchte ich gerne dass der Text durchgestrichen wird.

Wenn ich dien Haken wieder raus nehme, soll wieder ein Update ausgeführt werden, der Status soll von 1 wieder auf 0 gesetzt werden und der Text soll nicht weiter durchgestrichen sein.

Wie gehe ich da am besten vor? Brauche ich um das ganze ein <form>? In meinem Projekt ist jQuery im Einsatz und daher kann ich da auch zugreifen.

Bis bald!
Bernd

  1. Tach!

    Wenn ich jetzt auf eine Checkbox klicke möchte ich gerne im Hintergrund ein Update in meiner mySQL Tabelle ausführen. Der status soll von 0 auf 1 gesetzt werden. Gleichzeitig möchte ich gerne dass der Text durchgestrichen wird. [...] Wie gehe ich da am besten vor?

    Eventhandlers für den Einstieg. Ajax-Request absenden. Bei positiver Rückmeldung bei class ein "done" hinzufügen und im CSS eine entsprechende Regel dafür stehen haben. Beim Haken rausnehmen entspreched "done" entfernen.

    Brauche ich um das ganze ein <form>? In meinem Projekt ist jQuery im Einsatz und daher kann ich da auch zugreifen.

    Ein Form wird nicht zwingend benötigt, solange die Aktionen Javascript-Only sein sollen. Möchtest du aber auch eine Alternative für nicht aktiviertes Javascript bereitstellen, wäre ein Form günstig zum Absenden

    dedlfix.

    1. Hallo dedlfix,

      ich habe jetzt ein wenig dran gearbeitet. Mein HTML habe ich wie folgt geändert

      <?php foreach($ToDoListeAusagabe as $array){ ?>
      <div>
        <label>
          <input type="checkbox" 
                 class="todo" 
                 name="code[]" 
                 value="<?php echo htmlspecialchars($array['pt_status']); ?>" 
                 <?php if ($array['pt_status'] == 1) { ?> checked  <?php } ?>>
      		
          <span <?php if ($array['pt_status'] == 1) { ?> class="done" <?php } ?>>
           <?php echo htmlspecialchars($array['pt_titel']); ?>
          </span>
        </label>
      </div>
      <?php } ?>
      

      Und hier mein jQuery code

      $(document).ready(function() { 
      	
      	$('.todo').click(function() {
      
      		if($(this).val() == 0) {
      			$(this).next('span').addClass("done");
      		
      		}
      
      		if($(this).val() == 1) {
      			$(this).next('span').addClass("done");
      		
      		}
      
          }); 
      }); 
      

      Wenn ich jetzt auf einen Eintrag klicke wird dieser durchgestrichen, wenn ich wieder drauf klicke wird dieser nicht mehr entfernt. Irgendwie habe ich da noch ein Verständnissproblem.

      Bis bald!
      Bernd

      1. 		if($(this).val() == 0) {
        			$(this).next('span').addClass("done");
        		
        		}
        
        		if($(this).val() == 1) {
        			$(this).next('span').addClass("done");
        		
        		}
        

        Du wolltest einmal die Klasse "done" hinzufügen, einmal entfernen. Ich lese zweimal addClass. Das zweite mal soll wohl removeClass sein.

        Bitte lese meine Hinweise zum generellen Vorgehen. Gegenwärtig führst Du die Änderungen zu einem Zeitpunkt durch, zu dem nicht fest steht, ob die Änderung auch in der Datenbank steht. Das wird dann bei späteren Aufrufen zur Verwirrung führen.

        1. Hallo Regina,

          danke für den Hinweis, das war weil ich den oberen Teil kopiert habe. Laut der jquery Dokumentation sollte ich es lieber so machen?

          $(document).ready(function() { 
          	
          	$('.todo').click(function() {
          
          		if($("input:checked")){
          			$(this).next('span').addClass("done");
          		}
          
          		$( "input:not(:checked) + span" ).removeClass("done");
          
          
              }); 
          }); 
          

          Bezüglich deinem Hinweis zur Datenbank, bis jetzt hat sich da noch gar nichts getan. Muss erst mal schauen wie ich ein Update zustande bekomme. Dieses muss ich ja innerhalb meiner click Funktion ausführen?

          Bis bald!
          Bernd

          1. $(document).ready(function() { 
            	
            	$( '.todo' ).click( function() {
            
                var thisCheckbox = $( this );
            
                thisCheckbox.prop( 'disabled', true );
            
                xhttp.open( 'POST', 'changeStatus.php', true );
                xhttp.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );
                xhttp.onreadystatechange = function() {
            
                  if ( this.readyState == 4 && this.status == 200 ) {
            
               		  if( this.responseText == 'done' ) {
            		  	  thisCheckbox.next('span').addClass( 'done');
            		    } else {
              		    thisCheckbox.next( 'span' ).removeClass( 'done' );
                    }
                    thisCheckbox.prop( 'disabled', false );
                  }
            
                  xhttp.send( 'val=' + thisCheckbox.val() );
                }
              }); 
            }); 
            

            Da ich jquery vermeide können hier Syntaxfehler drin stehen.

            Das PHP-Skript "changeStatus.php" schreibt in die Datenbank und liefert nur dann(!) und nur(!) "done" zurück, wenn der Eintrag auf "erledigt" gesetzt wurde (oder es schon, z.B. durch eine Aktion in einer anderen Sitzung war). Ob es das soll steht in $_POST['val']. changeStatus.php muss die Authorisierung prüfen!

            1. Hallo Regina,

              puh, das ist ja eine ganz andere Schreibweise wie ich sie kennen. Muss ich mir erst mal anschauen. Das xhttp habe ich so noch nie gehört.

              Bis bald!
              Bernd

              1. Tach!

                puh, das ist ja eine ganz andere Schreibweise wie ich sie kennen. Muss ich mir erst mal anschauen. Das xhttp habe ich so noch nie gehört.

                xhttp ist ein Variablenname, die Definition dazu ist aber nicht im Code. Ansonsten ist das ein XMLHttpRequest-Objekt (XHR) und auch der Vanilla-Weg ohne jQuery. Wenn du schon jQuery nimmst, dann solltest du das auch mit dessen Möglichkeiten lösen. Das geht da auch einfacher als die recht betagte Arbeitsweise von XHR.

                dedlfix.

                1. Hallo dedlfix,

                  die Schreibweise die ich unter jQuery kenne ist folgende

                  $(document).ready(function() { 
                  	
                  	$('.todo').click(function() {
                  
                  		var formData = {
                           'todo': $('input[name=code]').val()
                          };
                  
                  		$.ajax({
                  			
                  			url:"updateToDo.php",
                  			type:"post",
                  			data:formData,
                  		 
                  			success:function(d) {
                  		  		
                  		  		if($("input:checked")){
                  					$(this).next('span').addClass("done");
                  				}
                  
                  				$( "input:not(:checked) + span" ).removeClass("done");
                  			}
                  		});
                      }); 
                  }); 
                  

                  Bis bald!
                  Bernd

                  1.   	success:function(d) {
                        		
                        		if($("input:checked")){
                      			$(this).next('span').addClass("done");
                      		}
                    
                      		$( "input:not(:checked) + span" ).removeClass("done");
                      	}
                    

                    Logisch falsch!

                    Du toggelst die Klasse anhand des Hakens. Das ist Mist, weil Du zu dem Zeitpunkt in der Rückgabe des Requests einen sicheren Anhaltspunkt dafür hast ob in der Datenbank der Eintrag geändert wurde, statt nur der Vermutung für die nur der Haken in der Checkbox spricht.

                    Wenn Du $.ajax verwenden willst, dann schaue nach, wie Du die Rückgaben auswertest. Außerdem hast Du die Checkbox nicht deaktiviert. Auch das führt zu Chaos.

                    1. Hallo Regina,

                      warum sollte ich die Checkbox deaktivieren? Bzw. ich weiß nicht genau was du meinst.

                      Bis bald!
                      Bernd

                        1. Hallo Regina,

                          naja, was ist wenn er sich verklickt hat? Dann muss ich ja die Möglichkeit haben den Vorgang rückgängig machen zu können?

                          Bis bald!
                          Bernd

                          1. naja, was ist wenn er sich verklickt hat?

                            Dann muss er eben 0,1 oder 0,2 Sekunden warten, denn ich hatte ja auch geschrieben, Du sollst die Checkbox wieder aktivieren. Wild rumklicken wird aber höchst chaotisch.

                          2. Tach!

                            naja, was ist wenn er sich verklickt hat? Dann muss ich ja die Möglichkeit haben den Vorgang rückgängig machen zu können?

                            Beim Clicken sperren, nach Abschluss der Datenbank-Handlung wieder freigeben. Nur zwischendrin sollte er gesperrt sein, damit nicht Rumklicken und Reaktion nach der Datenbank-Handlung wild durcheinander erfolgen. Sowas passiert im Labor nicht, weil du weißt, wie das System läuft und wartest. Aber Anwender wissen das nicht und klicken wie es ihnen beliebt.

                            dedlfix.

                            1. Hallo dedlfix,

                              ich habe jetzt erst mal ein ganz anderes Problem:

                              <div>
                                <label>
                                  <input type="checkbox" 
                                         class="todo" 
                                         name="code[]" 
                                         value="<?php echo htmlspecialchars($array['pt_status']); ?>" 
                                         <?php if ($array['pt_status'] == 1) { ?> checked  <?php } ?>>
                                  
                                  <span <?php if ($array['pt_status'] == 1) { ?> class="done" <?php } ?>>
                                  <?php echo htmlspecialchars($array['pt_titel']); ?>
                                  </span>
                                </label>
                              </div>
                              
                              $(document).ready(function() { 
                              	
                              	$('.todo').click(function() {
                              
                              		alert($(this).val())
                              
                              		var formData = {
                                          'todo': $(this).val()
                                      };
                              
                              		$.ajax({
                              			
                              			url:  "updateToDo.php",
                              			type: "post",
                              			data: formData,
                              		 
                              			success:function(d) {
                              		  		
                              			}
                              		});
                                  }); 
                              }); 
                              

                              Ich muss doch noch irgendwie die ID vom Datensatz mitgeben? Wie mache ich dieses in diesem Fall? Ein Hidden Feld einfügen?

                              Bis bald!
                              Bernd

                              1. Ich muss doch noch irgendwie die ID vom Datensatz mitgeben?

                                Ganz einfach:

                                'todo': $(this).val(),
                                'id': ID_vom_Datensatz
                                

                                Die muss in der Funktion

                                $('.todo').click(function() {
                                  var ID_vom_Datensatz = …;
                                  …
                                }
                                

                                mit gesetzt werden. Wie Du nun an diese rankommst ist aus Deinem HTML und der jquery-api ersichtlich.

                                1. Hallo Regina,

                                  danke. Ich mach es über

                                  data-id="<?php echo htmlspecialchars($array['pt_id']); ?>"
                                  

                                  und

                                  var ID_vom_Datensatz = $(this).data("id");
                                  

                                  Update: Ich kann die id auch direkt an formData übergeben

                                  var formData = {
                                        'todo': $(this).val(),
                                  			'id':   $(this).data("id")	
                                      };
                                  

                                  Bis bald!
                                  Bernd

                              2. Tach!

                                Ich muss doch noch irgendwie die ID vom Datensatz mitgeben? Wie mache ich dieses in diesem Fall?

                                Deine Checkbox hat als Namen code[] bekommen. Wenn alle so heißen, kann man sie nicht auseinanderhalten. Wenn man die ID in die Klammern schreibt, wird es eindeutig. Und man kann sie mit Javascript und etwas Stringverarbeitung extrahieren. Zudem gibt es data-Attribute, die sich auch mit jQuery auslesen lassen. <input type="checkbox" ... data-id="42">

                                dedlfix.

                                  1. Hallo,

                                    irgendwie habe ich ein Denkfehler in meinem Code

                                    <label>
                                     <input type="checkbox" 
                                            data-id="<?php echo htmlspecialchars($array['pt_id']); ?>" 
                                            class="todo" name="code[]" 
                                            value="<?php echo htmlspecialchars($array['pt_status']); ?>" 
                                            <?php if ($array['pt_status'] == 1) { ?> checked  <?php } ?>>
                                     
                                     <span <?php if ($array['pt_status'] == 1) { ?> class="done" <?php } ?>>
                                     <?php echo htmlspecialchars($array['pt_titel']); ?>
                                     </span>
                                    </label>
                                    

                                    In value steht ja immer der Wert drin, den ich aus meiner Datenbank auslese. Im aktuellen Fall eine 0.

                                    var formData = {
                                     'todo': $(this).val(),
                                      'id':   $(this).data("id")	
                                     };
                                    

                                    Hier frage ich den Wert ab, der im value steht, in diesem Fall wieder 0. Wenn ich den Krempel jetzt zur Datenbank schicke, übergebe ich auch wieder 0. Müsste es nicht irgendwie lauten, wenn eine 0 im value steht, übergebe ich eine 1 wenn eine 1 im value steht, übergebe ich eine 0? Denn ich wunderte mich, warum in der DB nichts ankommt. In Wirklichkeit kommt schon etwas an nur immer der gleiche Wert.

                                    EDIT: Ich habe es jetzt so gelöst, ist dieses der richtige Weg?

                                    if ($(this).val() == 0) {
                                    			var status = 1;
                                    		} else {
                                    			var status = 0;
                                    		}
                                    
                                    		var formData = {
                                          'todo': status,
                                    			'id':   $(this).data("id")	
                                        };
                                    

                                    Bis bald!
                                    Bernd

                                    1. Tach!

                                      Müsste es nicht irgendwie lauten, wenn eine 0 im value steht, übergebe ich eine 1 wenn eine 1 im value steht, übergebe ich eine 0?

                                      Ist das nicht logisch, dass man zum Umschalten den jeweils anderen Wert als bisher setzen muss?

                                      dedlfix.

                                      1. Hallo dedlfix,

                                        hier mal mein Ergebnis

                                        <?php foreach($ToDoListeAusagabe as $array){ ?>
                                        <div>
                                          <label>
                                           <input type="checkbox" 
                                                  data-id="<?php echo htmlspecialchars($array['pt_id']); ?>" 
                                                  class="todo" name="code[]" 
                                                  value="<?php echo htmlspecialchars($array['pt_status']); ?>" 
                                                  <?php if ($array['pt_status'] == 1) { ?> checked  <?php } ?>>
                                           <span <?php if ($array['pt_status'] == 1) { ?> class="done" <?php } ?>>
                                           <?php echo htmlspecialchars($array['pt_titel']); ?>
                                           </span>
                                         </label>
                                        </div>
                                        <?php } ?>
                                        

                                        Hier noch der Js Code

                                        $(document).ready(function() { 
                                        	
                                        	$('.todo').click(function() {
                                        
                                        		if($("input:checked")){
                                        			$(this).next('span').addClass("done");
                                        		}
                                        		
                                        		$( "input:not(:checked) + span" ).removeClass("done");
                                        
                                        		if ($(this).val() == 0) {
                                        			
                                        			var status = 1;
                                        		
                                        		} else {
                                        			
                                        			var status = 0;
                                        		}
                                        
                                        		var formData = {
                                              'todo': status,
                                        			'id':   $(this).data("id")	
                                            };
                                        
                                        		$.ajax({
                                        			
                                        			url:  "updateToDo.php",
                                        			type: "post",
                                        			data: formData,
                                        		 
                                        			success:function(d) {
                                        		  		
                                        			}
                                        		});
                                            }); 
                                        });
                                        

                                        Jetzt noch zum Thema https://forum.selfhtml.org/self/2018/sep/25/bei-klick-auf-checkbox-update-ausfuehren-und-text-durchstreichen/1732828#m1732828

                                        Wie kann ich während dem Update die Checkbos deaktivieren und ist dieses bei einer Checkbox wirklich nötig? Ich meine so ein Update geht keine Sekunde.

                                        Zum Thema durchstreichen bzw. nicht durchstreichen. Dieses kann ich bereits vor dem Update erledigen, selbst wenn etwas fehlschlägt, wird der Text beim neuladen einfach nicht geändert? Die tatsächliche Prüfung mache ich ja an dieser Stelle:

                                        <?php if ($array['pt_status'] == 1) { ?> checked  <?php } ?>
                                        

                                        Hätte ich denn die Möglichkeit einen Datensatz der gerade bearbeitet wurde, direkt danach zu aktualisieren ohne die Seite neu laden zu müssen? Ist dieses technisch möglich?

                                        Und benötige ich überhaupt die success:function?

                                        Bis bald!
                                        Bernd

                                        1. Und benötige ich überhaupt die success:function?

                                          Wenn Du ajax nimmst, dann dient die success-function GENAU dazu in GENAU DIESER nach dem Festellen des erfolgreichen Requests (Skript sendet "done" mit Status 200)

                                          • die Klasse "done" je nach Ergebnis des Requests (nicht) hinzufügen oder zu entfernen
                                          • die Checkbox wieder zu entsperren.
                                        2. Tach!

                                          Wie kann ich während dem Update die Checkbos deaktivieren und ist dieses bei einer Checkbox wirklich nötig? Ich meine so ein Update geht keine Sekunde.

                                          Kannst du das garantieren, dass es nie eine größere Verzögerung gibt? Und kannst du garantieren, dass Nutzer brav Einfachklicks machen, statt Doppelklicks? Und dass sie bei Mehrfachklicks sehen, wie der tatsächliche Stand am Ende ist?.

                                          Hätte ich denn die Möglichkeit einen Datensatz der gerade bearbeitet wurde, direkt danach zu aktualisieren ohne die Seite neu laden zu müssen? Ist dieses technisch möglich?

                                          Entweder verstehe ich die Frage nicht, oder: Genau dafür nimmt man ja Ajax, um nicht neu laden zu müssen.

                                          Und benötige ich überhaupt die success:function?

                                          Wenn dir das Ergebnis egal ist, dann natürlich nicht. Aber üblicherwiese möchte man den Nutzer über Erfolg oder Misserfolg informieren. Dazu braucht man dann nicht nur einen Success-Handler, sondern auch noch einen Error-Handler.

                                          dedlfix.

                  2. Tach!

                    die Schreibweise die ich unter jQuery kenne ist folgende

                    Sieht wie jQuery aus. Aber innerhalb des Success-Callbacks würde ich nicht nochmal die Elemente selektieren. Der Click-Handler bekommt eine Referenz auf das auslösende Element im this zur Verfügung gestellt. Die kannst du dir in einer lokalen Variable merken (am besten als jQuery-Objekt, also als $(this)), weil im Success-Callback das this anderswohin zeigen wird. Von dieser gemerkten Elementreferenz ausgehend, zuzüglich gegebenenfalls Navigation zu Kind- oder Vorfahrenelementen, würde ich die Klasse setzen oder löschen.

                    dedlfix.

            2. Hallo Regina,

              ich habe jetzt noch ein wenig getestet. Meine PHP Datei schaut so aus

              if ($stmt = $mysqli->prepare("Update todo SET pt_status=? WHERE pt_id=?")) {    
              	
              	$stmt->bind_param("ss", $_POST["todo"], $_POST["id"]);
              	$stmt->execute();
              	
              }
              
              if ($_POST["todo"] == 1) {
              	echo json_encode( array("readyState" => "4", "ok" => "200", "responseText" => "done"));
              }
              
              if ($_POST["todo"] == 0) {
              	echo json_encode( array("readyState" => "4", "ok" => "200", "responseText" => "nein"));
              }
              

              Und mein jQuery schaut so aus

              $(document).ready(function() { 
              	
              	$('.todo').click(function() {
              
              
              	    var thisCheckbox = $( this );
              
              	    thisCheckbox.prop( 'disabled', true );
              
              		if ($(this).val() == 0) {
              			
              			var status = 1;
              		
              		} else {
              			
              			var status = 0;
              		}
              
              		var formData = {
                          'todo': status,
              			'id':   $(this).data("id")	
                      };
              
              		$.ajax({
              			
              			url:  "updateToDo.php",
              			type: "post",
              			dataType: 'json',
              			data: formData,
              		 
              			success:function(d) {
              
              				if ( d.readyState == 4 && d.ok == 200 ) {
              
              					if( d.responseText == 'done' ) {
              					  	thisCheckbox.next('span').addClass( 'done');
              					} else {
              			  			thisCheckbox.next( 'span' ).removeClass( 'done' );    
              			        }
              
              			        if( d.responseText == 'leer' ) {
              					  	thisCheckbox.next('span').removeClass( 'done');
              					} 
              
              			        thisCheckbox.prop( 'disabled', false );
              
              				}
              		  		
              			}
              		});
                  }); 
              }); 
              

              Das hinzufügen funktioniert, aber das entfernen leider nicht. Das liegt wohl daran dass das value nach dem Klick nicht aktualisiert wird, richtig?

              und genau dieses habe ich im letzten Satz hier gefragt:
              https://forum.selfhtml.org/self/2018/sep/25/bei-klick-auf-checkbox-update-ausfuehren-und-text-durchstreichen/1732894#m1732894

              Bis bald!
              Bernd

              1. Tach!

                if ($_POST["todo"] == 1) {
                	echo json_encode( array("readyState" => "4", "ok" => "200", "responseText" => "done"));
                }
                
                if ($_POST["todo"] == 0) {
                	echo json_encode( array("readyState" => "4", "ok" => "200", "responseText" => "nein"));
                }
                

                Warum schickst du "readyState" => "4", "ok" => "200" als Antwort? Das ist völlig überflüssig. Beim XHR kann man einen readyState und einen status auswerten, aber ersterer wird vom XHR selbst gesetzt aufgrund seiner Arbeitsweise und der Status kommt vom HTTP. Wenn man jQuery verwendet muss man lediglich den Success-Handler bedienen, der Rest wird intern ausgewertet und der Sussess-Handler nur aufgerufen, wenn beides stimmt. Es besteht also keine Notwendigkeit, dass du selbst ähnliche Werte in der Response mitschickst, nur um sie dann nutzloserweise auszuwerten.

                Das hinzufügen funktioniert, aber das entfernen leider nicht. Das liegt wohl daran dass das value nach dem Klick nicht aktualisiert wird, richtig?

                Ja klar, das ändert sich ja nicht auf magische Weise. Das musst du schon selbst machen.

                dedlfix.

                1. Hallo dedlfix,

                  Ja klar, das ändert sich ja nicht auf magische Weise. Das musst du schon selbst machen.

                  und genau dieses ist mein Problem, ich weiß nicht wie ich den value Wert dynamisch austauschen kann ohne die Seite neu zu laden.

                  Bis bald!
                  Bernd

                  1. Tach!

                    Ja klar, das ändert sich ja nicht auf magische Weise. Das musst du schon selbst machen.

                    und genau dieses ist mein Problem, ich weiß nicht wie ich den value Wert dynamisch austauschen kann ohne die Seite neu zu laden.

                    Du kannst auf Elemente zugreifen, um Attribute zu lesen und zu setzen. Du kannst auf Input-Elemente zugreifen, und ihren Wert auslesen. .val() kann Werte nicht nur lesen, sondern auch schreiben. Eigentlich sollte das kein Problem darstellen, du kannst das bereits grundsätzlich.

                    dedlfix.

                    1. Hallo dedlfix,

                      danke, ich habe es glaube ich geschafft

                      success:function(d) {
                      
                      				if ( d.readyState == 4 && d.ok == 200 ) {
                      
                      					if( d.responseText == 'done' ) {
                      						thisCheckbox.val( "1" );
                      					  	thisCheckbox.next('span').addClass( 'done');
                      					  	
                      					} else {
                      			  			thisCheckbox.next( 'span' ).removeClass( 'done' );    
                      			        }
                      
                      			        if( d.responseText == 'nein' ) {
                      			        	thisCheckbox.val( "0" );
                      					  	thisCheckbox.next('span').removeClass( 'done');
                      					  	
                      					} 
                      
                      			        thisCheckbox.prop( 'disabled', false );
                      
                      				}
                      		
                      			}
                      

                      Bis bald!
                      Bernd

                2. Hallo dedlfix,

                  Warum schickst du "readyState" => "4", "ok" => "200" als Antwort? Das ist völlig überflüssig. Beim XHR kann man einen readyState und einen status auswerten, aber ersterer wird vom XHR selbst gesetzt aufgrund seiner Arbeitsweise und der Status kommt vom HTTP. Wenn man jQuery verwendet muss man lediglich den Success-Handler bedienen, der Rest wird intern ausgewertet und der Sussess-Handler nur aufgerufen, wenn beides stimmt. Es besteht also keine Notwendigkeit, dass du selbst ähnliche Werte in der Response mitschickst, nur um sie dann nutzloserweise auszuwerten.

                  ok, den Status habe ich geschafft auszulesen, wenn ich es richtig verstanden haben. Ich weiß nicht wie ich ein Fehler einbauen kann um zu prüfen ob ich einen anderen Status zurück bekomme

                  success:function(d, status, jqXHR) {
                    
                    var statusServer = jqXHR.status;
                    
                    if ( d.readyState == 4 && statusServer == 200 ) {
                  
                     //
                  
                    }
                  

                  Jetzt muss ich noch schauen wie ich an den readyState komme.

                  Bis bald!
                  Bernd

                  1. Hallo,

                    jetzt funktioniert es auch mit dem jqXHR.readyState, hier mein kompletter Code, passt dieser so?

                    $(document).ready(function() { 
                    	
                    	$('.todo').click(function() {
                    
                    
                    	    var thisCheckbox = $( this );
                    
                    	    thisCheckbox.prop( 'disabled', true );
                    
                    		if ($(this).val() == 0) {
                    			
                    			var status = 1;
                    		
                    		} else {
                    			
                    			var status = 0;
                    		}
                    
                    		var formData = {
                                'todo': status,
                    			'id':   $(this).data("id")	
                            };
                    
                    		$.ajax({
                    			
                    			url:  "updateToDo.php",
                    			type: "post",
                    			dataType: 'json',
                    			data: formData,
                    		 
                    			success:function(d, status, jqXHR) {
                    
                    				var statusServer = jqXHR.status;
                    				var State = jqXHR.readyState;
                    
                    				//alert(statusServer);
                    				//console.log(jqXHR.readyState);
                    
                    				if ( State == 4 && statusServer == 200 ) {
                    
                    					if( d.responseText == 'done' ) {
                    						thisCheckbox.val( "1" );
                    					  	thisCheckbox.next('span').addClass( 'done');
                    					  	
                    					} else {
                    			  			thisCheckbox.next( 'span' ).removeClass( 'done' );    
                    			        }
                    
                    			        if( d.responseText == 'nein' ) {
                    			        	thisCheckbox.val( "0" );
                    					  	thisCheckbox.next('span').removeClass( 'done');
                    					  	
                    					} 
                    
                    			        thisCheckbox.prop( 'disabled', false );
                    
                    				}
                    		
                    			}
                    		});
                        }); 
                    }); 
                    

                    Bis bald!
                    Bernd

                  2. Tach!

                    ok, den Status habe ich geschafft auszulesen, wenn ich es richtig verstanden haben.

                    Du musst das gar nicht tun. Success wird nur dann aufgerufen, wenn alles in Ordnung ist. Eine Prüfung deinerseits, ob alles in Ordnung ist, muss nicht mehr stattfinden. Wenn du auf den Zustand "nicht alles in Ordnung" reagieren möchtest, dann musst du zusätzlich zu success einen Handler für error anlegen.

                    success und error beziehen sich übrigens nur auf den Request selbst, also dass im Bereich HTTP alles in Ordnung war. Wenn deine serverseitige Anwendung hingegen festgestellt hat, dass ihr irgendwas nicht passt, dann ist das trotzdem eine ordentliche Antwort aus Sicht von HTTP (also mit Status 200). Die unterschiedlichen Zustände kannst du durch unterschiedliche Inhalte deiner Antwort repräsentieren.

                    Ich weiß nicht wie ich ein Fehler einbauen kann um zu prüfen ob ich einen anderen Status zurück bekomme

                    Wenn du ein HTTP-Problem simulieren möchtest, müsstest du einen von 200 abweichenden Status zurückgeben. Siehe PHPs header(), erstes Beispiel im Abschnitt Parameters beim Parameter "header". Oder einfach die Ziel-URL des Requests auf etwas nicht existierendes zeigen lassen, dann sollte der Server schon selbst einen 404 antworten. Dies führt jedenfalls dazu, dass der error-Callback aufgerufen wird, wenn du einen angegeben hast.

                    Wenn du hingegen selbst einen Fehler festgestellt hast (zum Beispiel: Datenbank-Problem, Wert nicht in Ordnung, …) dann, wie gesagt, ändere den Inhalt deiner Antwort. Du könntest beispielsweise dem JSON-Objekt ein Feld namens error spendieren und einen dir genehmen Inhalt einfügen (Fehlermeldungstext vielleicht). Ist das Feld nicht da oder leer, dann ist das im booleschen Sinn ein falsy Wert.

                    if (d.error) {
                      console.log(d.error);
                    } else {
                      // alles gut
                    }
                    

                    So zum Beispiel, oder was auch immer du zu tun gedenkst, in dem einen oder dem anderen Fall.

                    dedlfix.

  2. Wenn ich jetzt auf eine Checkbox klicke möchte ich gerne im Hintergrund ein Update in meiner mySQL Tabelle ausführen. Der status soll von 0 auf 1 gesetzt werden. Gleichzeitig möchte ich gerne dass der Text durchgestrichen wird.

    Nicht "gleichzeitig"!

    Der zu setzende Status bzw. die Klasse ergibt sich aus dem Value der Checkbox. Nach dem Change der Checkbox setzt Du die Checkbox auf disabled, ermittelst den Value, sendest den Ajax-Request ab, der dann zurückmeldet ob die Datenbankänderung geklappt hat. Nach der Prüfung der Antwort setzt Du für den Text die Klasse, die das "erledigt" bzw. "nicht erledigt" anzeigt (e.g. [nicht]durchgestrichener Text). Dann kannst Du die Checkbox wieder aktivieren. Ergibt sich aus der Prüfung der Antwort ein Fehler (Inhalt und/oder Header), dann mach was Du in dem Fall zu tun vorhast.

    Tipp: "Flagge" auch Codes für die möglichen Fehler der Datenbank in der Antwort auf den Request durch.

    Das Abschalten der Checkbox soll dafür sorgen, dass der Benutzer nicht wild auf der Ckeckbox rumklickt wenn es mal ein Zehntelsekündchen zu lange dauert.

    1. Hallo Regina,

      eine solche Antwort hatte ich auch schon auf den Fingern, aber keine Zeit zum Schreiben...

      Ich habe mich dann aber auch gefragt, wie da die Benutzererfahrung ist. Ich klicke auf die Box, sie graut sich aus und ist - wenn alles gut geht - kurz darauf wieder aktiv. Und wenn es nicht gut geht, schaltet sie auf den alten Wert zurück und es ploppt eine Fehlermeldung hoch.

      Wäre es nicht besser, die Checkbox komplett auszublenden und sie durch ein animiertes Symbol zu ersetzen (GIF oder CSS Animation)? Natürlich darf der Text dahinter sich dabei nicht verschieben, ein zappelndes UI ist eklig.

      Ich habe mal versucht, sowas zu simulieren. Der per setTimeout simulierte Ajax-Service im Fiddle ist extrem unzuverlässig, in 50% der Fälle rennt er auf einen Timeout.

      https://jsfiddle.net/b0ekyg4x/

      Rolf

      --
      sumpsi - posui - clusi
      1. Hallo Rolf,

        Wäre es nicht besser, die Checkbox komplett auszublenden und sie durch ein animiertes Symbol zu ersetzen (GIF oder CSS Animation)? Natürlich darf der Text dahinter sich dabei nicht verschieben, ein zappelndes UI ist eklig.

        lohnt sich so ein Aufwand wirklich? Ich meine wir reden hier von vielleicht einer halben Sekunde? Und selbst wenn er mehrfach daraufklickt warum auch immer, tut dieses der Datenbank nicht weh?

        Ich habe mal versucht, sowas zu simulieren. Der per setTimeout simulierte Ajax-Service im Fiddle ist extrem unzuverlässig, in 50% der Fälle rennt er auf einen Timeout.

        https://jsfiddle.net/b0ekyg4x/

        Geil ist deine Funktion mit dem Rädchen schon, wenn ich ehrlich bin ;) Es hat einfach etwas. Ob es nützlich ist oder nicht, ist ein anderes Thema. Danke für dein Beispiel.

        die Frage ist, wie bekomme ich deine Funktion in meine rein?
        https://forum.selfhtml.org/self/2018/sep/25/bei-klick-auf-checkbox-update-ausfuehren-und-text-durchstreichen/1732894#m1732894

        Gerne auch mit dem TimeOut dass es eine kleine Verzögerung gibt, dass man wenigstens etwas sieht, wenn ich deinen Code so verwenden darf.

        Bis bald!
        Bernd

        1. lohnt sich so ein Aufwand wirklich? Ich meine wir reden hier von vielleicht einer halben Sekunde? Und selbst wenn er mehrfach daraufklickt warum auch immer, tut dieses der Datenbank nicht weh?

          Das arbeitet Asyncron.

          Je nachdem wie Dein Gesamtssystem spinnt, kann die Aktion und Antwort auch mal 30 Sekunden dauern und "überholt" werden. Sprich der zweite Klick wird VOR dem ersten abgearbeitet. Du kannst so sehr merkwürdige Zustände erreichen, insbesondere auch den, dass nach kurzer Zeit plötzlich ein anderer Zustand angenommen wird.

          Bedenke auch, dass die Schalter der Maus prellen können. Ich hab "die Tage" so einen Nager weggeworfen, der Mehrfachklicks ausführte, wenn ich was einfach anklicken wollte. Das war ein "sehr hübsches" Arbeiten. Ein Klick hier in die Texteingabe führte zum Markieren eines Wortes...

        2. Hallo Barksalot,

          die Frage ist, wie bekomme ich deine Funktion in meine rein?

          Ich zitiere den Uni-Prof, den ich nie hatte:

          Das wird als einfache Übung dem Leser überlassen.

          Mein Fiddle hat 2 Bestandteile: Die Visualisierung des Ajax-Calls, und die Simulation des Ajax-Calls durch setTimeout. Die Simulation ist für Dich irrelevant, da musst Du den echten Call einsetzen.

          Die Visualisierung solltest Du Dir zu erschließen versuchen. Da ist ein bisschen CSS Selektor Hexenwerk drin; letztlich erfolgt die Umschaltung zwischen Checkbox und Platzhalter durch das Setzen und Entfernen der busy Klasse:

          label input[name=erledigt].busy, label input[name=erledigt]:not(.busy)+span  {
            display:none;
          }
          

          Je nachdem, ob .busy an dem Element mit name=erledigt gesetzt ist (der Checkbox), wird die Checkbox oder der darauf folgende span ausgeblendet (siehe Self-Wiki, Nachbarselektor). Diesen Selektor musst Du natürlich an dein Markup anpassen.

          Die Animation erfolgt mit dem Unicode-Zeichen ◠, dem eine 360-Grad Rotation zugeordnet wird. Dieses Zeichen ist zumindest in meinem Font sehr schön platziert, so dass die Rotation nicht eiert. Das CSS dazu sieht so aus:

          label input[name=erledigt].busy+span {
           animation: rotate 1s linear 0s infinite; 
          }
          @keyframes rotate { 
              from { transform: rotate(0deg); } to { transform: rotate(359deg) } 
          }
          

          Ich habe dem Selektor hier im Forum noch ein .busy hinzugefügt. Ob das der Performance nützt, weiß ich nicht, aber jedenfalls wird die Animation dann nur wirksam wenn der span auch sichtbar ist.

          Checkbox und Span habe ich gezielt auf gleiche Breite gezwungen und über die line-height des Label auch dafür gesorgt, dass die Zeilenhöhe festliegt. Ansonsten verschiebt sich bei mir der Text, wenn umgeschaltet wird. Aus dem gleichen Grund ist auch das font:inherit drin, weil sonst Checkbox und Platzhalter nicht gleich breit sind (Checkbox hat unter Chrome einen eigenen Font zugeordnet und ich wollte nicht mit Pixel arbeiten).

          Rolf

          --
          sumpsi - posui - clusi
      2. Ich habe mich dann aber auch gefragt, wie da die Benutzererfahrung ist. Ich klicke auf die Box, sie graut sich aus und ist - wenn alles gut geht - kurz darauf wieder aktiv. Und wenn es nicht gut geht, schaltet sie auf den alten Wert zurück und es ploppt eine Fehlermeldung hoch.

        Ja. Das geht freilich besser. Aber die Animation halte ich gegenwärtig noch für etwas, was gemacht werden kann (und sollte), wenn der TO einen Plan von dem hat, was er da überhaupt tut bzw. vorhat. Bis dahin sollte einfaches Deaktivieren reichen. Anders ausgedrückt: ich baue erst mal das Haus mit Fenstern, Türen und Schlössern und kümmere mich dann, wenn das alles steht und funktioniert, um die Verzierung des Giebels.

        Besser noch: Ich überlasse das den Frontendern. Aber wie gesagt: Vorher muss die Mechanik klar sein.

        1. Tach!

          Ja. Das geht freilich besser. Aber die Animation halte ich gegenwärtig noch für etwas, was gemacht werden kann (und sollte), wenn der TO einen Plan von dem hat, was er da überhaupt tut bzw. vorhat. Bis dahin sollte einfaches Deaktivieren reichen.

          Ja, nein, vielleicht. Im Code beschränkt sich das auf das Setzen und Entfernen einer Klasse oder alternativ das Setzen und Entfernen eines Attributes. Die Animation ist ein paar Zeilen CSS, das kann man sich kopieren, und das beeinflusst das Verständnis der Code-Logik nicht weiter.

          dedlfix.

          1. Hallo dedlfix,

            Jörg hat aber schon recht. Die Erfahrung hier im Forum besagt, dass Bernds Lernkurve immer noch recht steil ist und nicht in dem Maße abflacht, wie wir - und Bernd! - es gern hätten.

            Das hat aber Gründe, die Bernd genannt hat und die ich respektiere. Deswegen biete ich ihm gerne so ein Häppchen an - das austüfteln hat mir ja auch Spaß gemacht. Für ihn in seinen Code hineinschreiben will ich es aber nicht, den Job muss er selbst hinbekommen.

            Rolf

            --
            sumpsi - posui - clusi