script42: Variable an schon geladenes JQuery übertragen

Hallo, liebe Forumsmitglieder,

ich bin Programmieranfängerin und versuche gerade, die folgende Situation zu lösen:

Für die Auftragszuweisung von Fototerminen habe ich in einem Formular ein dynamisch generiertes Auswahlfeld (<select>) von Fotografen, die in einem bestimmten Umkreis des Auftragsortes wohnen und daher für den Auftrag in Frage kommen.

//Abfrage aller Fotografen, die im ermittelten PLZ-Bereich wohnen und Präsentation in Auswahlmenü:
	$sqlselectFg = "SELECT FotografenID, FotografVorname, FotografNachname FROM tbl_Fotografen WHERE (Aktivitaet = 'aktiv') AND (FotografPLZ IN $plzliste);";
	$resultFg = mysqli_query($conn, $sqlselectFg);
	$resultCheckFg = mysqli_num_rows($resultFg);
	echo '<select class="form-control select" name="Fotografen" id="Fotografen">';
	$fgliste = array();
	while ($rowFg = mysqli_fetch_assoc($resultFg)) {
				$fgliste[]=$rowFg['FotografenID'];
				echo '<option value="'.$rowFg['FotografenID'].'">'.$rowFg['FotografenID'].' - '.$rowFg['FotografVorname'].' '.$rowFg['FotografNachname'].'</option>';
			}
	echo '</select>';
?>

Von diesen (meist 2-3) Fotografen werden in der Datenbank alle Termine abgefragt, für die diese Fotografen dieses Jahr schon gebucht ist und über PHP in ein Array geschrieben. Dieses Array lasse ich mir dann als JS-Array echoen:

<script>
	//Umschreiben der PHP-Arrays ${"allefototage".$fid}[] in Javascript-Arrays $disabledDates[][]:
	var $disabledDates = [];
<?php
	foreach($fgliste as $fid) {
		echo '$disabledDates['.$fid.'] = [';
		if(!empty(${"allefototage".$fid})){
			foreach(${"allefototage".$fid} as $ft) {
				echo "'".$ft."', "; 
			} 
		}
		echo '] ;';
	}
?>

Dem Anwender soll nun in einem Eingabefeld ein Kalender präsentiert werden, in dem die schon belegten Tage ausgeblendet sind. Das möchte ich über den JQuery-Kalender realisieren:

$('#datepicker<?php echo $notizzahl;?>').datepicker({
		language: "de",
	    startDate: "+0d",
	    daysOfWeekDisabled: "0,6",
	    autoclose: true,
	    todayHighlight: true,
	    datesDisabled: $disabledDates[fid],
	    toggleActive: true
	});

Mein Problem ist jetzt, dass ich nicht weiß, wie ich die Variable fid (FotografenID aus dem Array, ausgewählt in <select>) in den Value $disabledDates[fid] hineinbringe, nachdem das JQuery schon geladen ist.

Ich habe es probiert mit:

document.getElementById("Fotografen").addEventListener('change', selectOption, false);

function selectOption() {
	    var fotografenID = this.options[this.selectedIndex].value;
	    return fotografenID;
	}
var fid = fotografenID;

Doch lädt der Datepicker deshalb ja noch lange nicht die Variable erneut. Selbst, wenn ich den Datepicker in die Funktion selectOption mit hineintue, geht es nicht. Ich gehe davon aus, dass die Variable auch hier schon vorher verarbeitet wird.

Jetzt habe ich gelesen, dass ich per AJAX eine Variable an PHP übergeben kann und könnte natürlich nun in einen zweiten File die Übertragung per POST in den Datepicker machen und diese Daten dann per AJAX laden. Das erscheint mir aber sehr "von hinten durch die Brust ins Auge" und ich wollte fragen, ob es da nicht eine viel einfachere Möglichkeit gibt.

Danke für Eure Hilfe, Kerstin

akzeptierte Antworten

  1. Hallo Kerstin,

    der Rückgabewert aus einem Eventhandler wird vom Eventsystem verarbeitet. Das ist zwar historisch, aber früher gab's preventDefault() noch nicht. Ein return false; soll das gleiche tun wie der Aufruf von event.preventDefault();. D.h. dein return fotografenID; muss definitiv weg.

    Wie macht man's richtig? Du musst den Datepicker nach dem Select eines Fotografen im change-Eventhandler umkonfigurieren. Der Datepicker hat ja nur eine Liste von gesperrten Datümern bekommen und weiß nichts davon, dass da eine Beziehung zu $disabledDates oder fid besteht.

    Ich nehme an, dass das ist nicht der jQueryUI Datepicker ist, den Du da verwendest, sondern der von Bootstrap. Zumindest finde ich beim jQueryUI-Datepicker keine disabled dates. Bei dem von Bootstrap dagegen schon.

    Bootstrap kennt eine verquere Art von Methodenaufrufen auf seinen Widgets. Eine davon heißt setDatesDisabled. Der übergibst Du die zu deaktivieren Datumswerte, analog zum Konstruktoraufruf.

    function selectOption() {
       var fid = this.options[this.selectedIndex].value;
    	 $('#datepicker1234>').datepicker("setDatesDisabled",  $disabledDates[fid]);
    }
    

    Problem ist dieses "1234" in der datepicker-ID. Im PHP setzt Du hier den Wert von $notizzahl ein. Hast Du mehr als einen Datepicker im HTML? Wenn ja, musst Du nun noch das Problem lösen, wie Du den richtigen Datepicker auswählst. Andernfalls kannst Du einfach aus dem PHP heraus $notizzahl in den JS-Code hineingenerieren, hast Du ja anderswo auch schon gemacht.

    Dein PHP Code kommt mir übrigens recht umständlich vor. Möchtest Du dazu Tipps?

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo Rolf,
      vielen Dank für Deine schnelle Antwort!
      Tatsächlich ist der Datepicker derjenige von Bootstrap.
      Die Funktion habe ich gerade ausprobiert. Funktioniert super! Danke! Die Notizzahl habe ich zu Testzwecken jetzt mal konstant gesetzt, doch in Wirklichkeit gibt es für die verschiedenen Aufträge, von denen jeder dem Anwender mit den verschiedenen Einstellungsmöglichkeiten auf einem "Notizzettel" zum Abarbeiten auf dem Bildschirm erscheint, jeweils eine andere Notizzahl, pro Seite ca. 30.
      Eigentlich gibt es diese Notizzahl auch schon im Select: <select class="form-control select" name="Fotografen'.$notizzahl.'" id="Fotografen'.$notizzahl.'"> Ich hatte sie für diese Frage hier erst einmal rausgelöscht, um das Problem zu verkleinern, doch vergessen, das auch im Datepicker zu tun. Momentan würde ich den Datepicker für jede Notizzahl mit der Seite laden. Aber wahrscheinlich ist das auch nicht optimal, oder?

      Gerne nehme ich Tipps zum PHP-Code entgegen.
      Ich kann mir vorstellen, dass ich statt der Sache mit den geschweiften Klammern mehrdimensionale Arrays verwenden könnte, aber da ich mir nicht sicher war, ob mir dann nicht beim Umwandeln nach Javascript der Überblick verloren geht, habe ich es vorerst lieber erst mal so gemacht. Aber wenn das - oder auch etwas anderes - besser ist, mache ich es gerne anders.

      Herzliche Grüße
      Kerstin

      1. Hallo Kerstin,

        mal angenommen, $allefototage wäre ein zweidimensionales Array. Auf der ersten Indexstufe die fid, auf der zweiten Indexstufe die Fototage. $allefototage[42][3] wäre dann der vierte Eintrag für den Fotografen mit ID 42.

        Es ist übrigens nicht so sinnvoll, JavaScript-Variablen mit einem $ beginnen zu lassen. In PHP ist das Pflicht, in JavaScript machen das manche, um anzuzeigen, dass die Variable ein von jQuery geliefertes Set enthält. Aber im Normalfall setzt man kein $ vorneweg.

        Was einem auch gelegentlich das Leben leichter macht ist die String-Interpolation von PHP (String parsing). In Strings, die in doppelte Anführungszeichen gesetzt sind, sucht PHP nach Variablennamen und ersetzt sie durch ihren Wert. Das ist besser lesbar als viele Stringverkettungen mit .

        Die Funktion implode ist nützlich, um alle Einträge in einem Array zu einem String zusammenzufassen. In deinem Fall müssen die Array-Einträge in einfache Anführungszeichen gesetzt sein, deswegen muss man ein bisschen zaubern.

        <script>
        	//Umschreiben der PHP-Arrays $allefototage[$fid][] in Javascript-Arrays $disabledDates[][]:
        	var disabledDates = [];
        <?php
        	foreach($fgliste as $fid) {
        		if (!empty($allefototage[$fid])) {
              $dd = "'" . implode("', '", $allefototage[$fid]) . "'";
            }
            echo "disabledDates[$fid] = [$dd];"; 
        	}
        ?>
        </script>
        

        Solange Du sicher bist, dass in deinen Werten kein doppeltes Anführungszeichen vorkommt, kannst Du es Dir mit den JSON-Funktionen von PHP und JavaScript noch leichter machen. json_encode erzeugt im PHP aus $allefototage einen JSON-codierten String. JSON_HEX_APOS sorgt dafür, dass ein eventuelles ' Zeichen so codiert wird dass es keinen JavaScript-Error gibt. Dieser String wird in JSON.parse('...') eingesetzt und vom JSON-Interpreter in JavaScript in ein Array zurückverwandelt. Es mag bei leeren Einträgen zu Unterschieden kommen - das hängt davon ab wie deine $allefototage Einträge für unverbuchte Fotografen aussehen. Ggf. braucht dein change-Handler dann eine Anpassung dazu, wie man mit Fotografen ohne Eintrag umgeht.

        <?= ... ?> ist übrigens die Kurzform von <?php echo ...; ?>

        <script>
           var disabledDates = JSON.parse('<?= json_encode($allefototage, JSON_HEX_APOS) ?>');
        </script>
        

        Noch ein Hinweis zum Zusammenbauen deiner <option> Elemente. Das ist sehr schwer lesbar, weil da HTML und PHP intensiv vermischt werden. Hier empfehle ich eine Trennung in Aufbereitung und Ausgabe.

            while(...) {
               $fgID = $rowFg['FotografenID'];
               $fgName= $rowFg['FotografVorname'] . ' ' . $rowFg['FotografNachname'];
               $fgliste[] = $fgID;
               echo "<option value='$fgID'>$fgID - $fgName</option>";
            }
        

        Rolf

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

          vielen Dank für die vielen nützlichen Tipps!
          Dann werde ich mich also doch an die 2-dimensionalen Arrays wagen, und den Weg mal so beschreiten, wie Du es vorschlägst! Ist ja tatsächlich deutlich übersichtlicher.
          JSON sagte mir bis jetzt gar nichts - werde mich gleich mal ein bisschen mit den Grundlagen dazu beschäftigen und dann das umsetzen, was Du geschrieben hast.

          Herzliche Grüße
          Kerstin

          1. Hallo Kerstin,

            JSON Lesestoff

            Rolf

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

              vielen Dank! Also so etwas wie das Esperanto der Programmiersprachen... 😉

              Kerstin