HeikoH: PHP Script mit Ajax für Smarty zerlegen

Hallo @,

ich habe hier ein PHP Script mit Ajax welches ich bei mir einbinden möchte. Dazu muss es aber für Smarty "zerlegt" werden.
Kann mir jemand dabei helfen, sprich mir Ansätze geben?

<?
if ( !defined( 'SMARTY_DIR' ) )
 include_once( 'init.php' );
require('js/xajax_core/xajax.inc.php');
$xajax = new xajax();
//$xajax->configure('debug',true);
class myXajaxResponse extends xajaxResponse {

function addCreateOptions($sSelectId, $options) {
    $this->script("document.getElementById('".$sSelectId."').length=0");
    if (sizeof($options) >0) {
       foreach ($options as $option) {
         $this->script("addOption('".$sSelectId."','".
$option['txt']."','".$option['val']."');");
       }
     }
  }
}

$modesRs = mysql_query("SELECT DISTINCT(name) FROM countries") or die(mysql_error());
while ($rs=mysql_fetch_assoc($modesRs)) {
 $modes[]=$rs["name"];
}

function addtxtstateprovince($selectId, $mode) {
        global $txtstateprovince;
        $objResponse = new myXajaxResponse();
        $txtstateprovinceRs = mysql_query(sprintf(
"SELECT DISTINCT(name) FROM states WHERE countrycode = '%s'", $mode));
 while ($rs=mysql_fetch_assoc($txtstateprovinceRs)) {
   $txtstateprovince[]=array("txt"=>$rs["name"], "val"=>$rs["name"]);
 }
        $objResponse->addCreateOptions($selectId, $txtstateprovince);
 return $objResponse;
      }
      function addtxtcity($selectId, $transport) {
        global $txtcity;
        $objResponse = new myXajaxResponse();
 $txtcityRs = mysql_query(sprintf
("SELECT name FROM cities WHERE statecode = '%s'", $transport));
 while ($rs=mysql_fetch_assoc($txtcityRs)) {
   $txtcity[]=array("txt"=>$rs["name"], "val"=>$rs["name"]);
 }
        $objResponse->addCreateOptions($selectId, $txtcity);
 return $objResponse;
      }
      $xajax->registerFunction("addtxtstateprovince");
      $xajax->registerFunction("addtxtcity");
      $xajax->processRequest();

// Testausgabe
      if (isset($_POST['send'])) {
        print_r($_POST);
      }
?>

<html>
      <?
      $xajax->printJavascript("js/");
      ?>
<script type="text/javascript">
  function addOption(selectId, txt, val) {
    var objOption = new Option(txt, val);
     document.getElementById(selectId).options.add(objOption);
   }
</script>
</head>
<body>
      <form name="frmPlan" method="post" action="">
      Land :
      <select name="txtfrom" id="txtfrom"
onchange="xajax_addtxtstateprovince('txtstateprovince', document.frmPlan.txtfrom.value)">
        <option value="">--select--</option>
        <? foreach ($modes as $mod) { ?>
        <option value="<?= $mod?>"><?= $mod?></option>
        <? } ?>
      </select>
      Bezirk :
      <select name="txtstateprovince" id="txtstateprovince"
onchange="xajax_addtxtcity('txtcity', document.frmPlan.txtstateprovince.value)">
<option value="">--select--</option>
      </select>
      Stadt :
      <select name="txtcity" id="txtcity"><option value="">--select--</option>
      </select>
      <input type="submit" value="Submit" name="send">
      </form>
</body>
</html>

Speziell weiss ich nicht wie ich die foreach Schleife im Template darstellen muss und die Ausgabe "$xajax->printJavascript("js/");".
Bei den anderen beiden Dropdownmenues müsste doch normalerweise (ohne den Gebrauch von Ajax) auch eine Variable für die Werte stehen. Wie wird das mit Smarty und Ajax gelöst?

HeikoH

  1. Lieber HeikoH,

    ich fürchte, ich kann Dir nicht wirklich "helfen", aber ich habe da so ein paar Ideen, die vielleicht nicht ganz unnütz sind.

    ich habe hier ein PHP Script mit Ajax welches ich bei mir einbinden möchte.

    Was machen Besucher/Nutzer Deiner Seite, wenn sie kein JavaScript verfügbar haben? Ist Deine Seite auch ohne dieses Benutzbar? Im Idealfall ergänzt JavaScript eine bestehende Funktion nur, z.B. vereinfacht die Interaktion (z.B. mit Formularen). Keinesfalls sollten wesentliche Funktionalitäten von JavaScript abhängig sein.

    <?
    if ( !defined( 'SMARTY_DIR' ) )

    Diese Shorttags sind nicht gut! Auch XML hat sie, weshalb der PHP-Interpreter in ungünstligen Fällen anspringt, um XML als PHP zu parsen. Daher wäre es besser, wenn Du keine Shorttags benutzt, sondern Deine Scripte immer mit "<?php" beginnen lässt. Vielleicht kannst Du mit ini_set() diese Einstellung am Anfang Deines Scripts entsprechend vornehmen, falls Du auf Deinem Webspace diese Option so vorfindest?

    // Testausgabe
          if (isset($_POST['send'])) {
            print_r($_POST);
          }
    ?>

    <html>
          <?
          $xajax->printJavascript("js/");
          ?>
    <script type="text/javascript">
      function addOption(selectId, txt, val) {
        var objOption = new Option(txt, val);
         document.getElementById(selectId).options.add(objOption);
       }
    </script>
    </head>

    Ich nehme an, dass Du genau solches mit Smarty jetzt besser machen möchtest?

    <select name="txtfrom" id="txtfrom"
    onchange="xajax_addtxtstateprovince('txtstateprovince', document.frmPlan.txtfrom.value)">

    Hier steigen diejenigen aus, die kein JavaScript verfügbar haben. Und die, die mit der Tastatur navigieren, können nur die zweite Option nutzen, da bereits dort das onchange feuert, ohne dass sie je eine Chance hätten, sich bis zur letzten Option durchzutippen. Also ist für Leute, die lieber nicht die Maus benutzen, hier eine Barriere. Willst Du das so?

    Desweiteren sollte JavaScript-Code mittels JavaScript ins Dokument geschrieben werden (Stichwort "unobtrusive"). Das bedeutet, dass Du im <head> der Datei Deine JavaScripte aus externen Dateien lädst, um mit den dortigen Scripten Deine Seite zu "bearbeiten", also um Deine onchange- oder sonstigen Eventhandler im Dokument einzutragen. Das macht übrigens auch das Pflegen des Codes wesentlich leichter!

    Liebe Grüße aus Ellwangen,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Danke Felix,

      es sind doch schon gute Ansätze

      <?

      Das war im Script so vorhanden, habe ich aber bei mir schon geändert in <?php

      // Testausgabe
            if (isset($_POST['send'])) {
              print_r($_POST);
            }

      das fliegt sowieso raus - ist nur zum Testen gedacht

      <?
            $xajax->printJavascript("js/");
            ?>

      hier weiss ich z.B. nicht ob das <? für PHP oder XML steht und wie stelle ich es dann im Template da.

      <script type="text/javascript">
        function addOption(selectId, txt, val) {
          var objOption = new Option(txt, val);
           document.getElementById(selectId).options.add(objOption);
         }
      </script>
      </head>

      Ich nehme an, dass Du genau solches mit Smarty jetzt besser machen möchtest?

      Ja, das meine ich. Kommt das nun ins Template oder bleibt es in der PHP Datei?

      <select name="txtfrom" id="txtfrom"
      onchange="xajax_addtxtstateprovince('txtstateprovince', document.frmPlan.txtfrom.value)">

      Hier steigen diejenigen aus, die kein JavaScript verfügbar haben. Und die, die mit der Tastatur navigieren, können nur die zweite Option nutzen, da bereits dort das onchange feuert, ohne dass sie je eine Chance hätten, sich bis zur letzten Option durchzutippen. Also ist für Leute, die lieber nicht die Maus benutzen, hier eine Barriere. Willst Du das so?

      Nein, das möchte ich nicht so. Habe es auch probiert, wenn ich mit der Maus es ändere funktioniert es, mit Tastatur nicht. Ich bin kein Profi und weiss nicht wie ich es anders, sprich für Tastaturnutzer, ändern kann.

      Desweiteren sollte JavaScript-Code mittels JavaScript ins Dokument geschrieben werden (Stichwort "unobtrusive").

      Das möchte ich machen wenn alles funktioniert. Du hast recht, es ist dann auch aufgeräumter. Aber bis dahin habe ich es lieber wenn alles "beisammen" ist.

      HeikoH

      1. Lieber HeikoH,

        ich habe nopch nie mit Smarty gearbeitet. Ich kenne es vom Hörensagen, habe aber weiter keine Ahnung davon. Ich baue mir meine Templates selbst.

        <?
              $xajax->printJavascript("js/");
              ?>
        hier weiss ich z.B. nicht ob das <? für PHP oder XML steht und wie stelle ich es dann im Template da.

        Du meinst da_r_stellen? *SCNR* Also meiner Meinung nach solltest Du den JavaScript-Code als externe Datei in Deine Seite einbauen. Du könntest dazu PHP benutzen, um diesen JavaScript-Code zu generieren, denn PHP kann nicht nur HTML-Dateien "erstellen"...

        Dazu kannst Du ja in der HTML-Datei Dein PHP-Script referenzieren, welches dann eben Deine JS-Datei erstellt. Wenn das JavaScript jedesmal individuell neu zusammengestellt werden soll, dann kannst Du einen URL-Parameter aus der aktuellen Serverzeit (Timestamp) hinten anfügen, damit das JavaScript nicht jedesmal aus dem Browsercache entnommen, sondern tatsächlich frisch vom Server geladen wird.
        <script src="/pfad/script.php?time=1234567"></script>

        function addOption(selectId, txt, val) {
            var objOption = new Option(txt, val);
             document.getElementById(selectId).options.add(objOption);
           }
        [...]
        Ja, das meine ich. Kommt das nun ins Template oder bleibt es in der PHP Datei?

        Weder noch. Das wird in einer externen JavaScript-Datei abgelegt, die als statische Datei auf dem Server bereitliegt. Feste Scriptbestandteile kannst Du in einer festen JS-Datei ablegen. Die dynamisch zu verändernden Bestandteile werden dann von einem PHP-Script generiert (s.o.). Dazu könnte es sich anbieten, dass man in JavaScript eine Art übergeordnetes Objekt definiert, dem man alle diese Funktionen als Methoden gibt, und dem man in der vom PHP-Script nachgelieferten Datei zusätzliche Eigenschaften verleiht.

        Ich improvisiere zu Anschauungszwecken einmal das, was ich meine an einem schlechten kleinen Beispiel:

        --- Datei 'fest.js' ---

        var MeineAjaxMaschine = {  
            values : {}, // leeres Objekt -> wird in anderer JS-Datei befüllt  
          
            addOption : function (selectId, txt, val) {  
                var objOption = new Option(txt, val),  
                    obj = document.getElementById(selectId);  
          
                if (obj) {  
                    obj.options.add(objOption);  
                }  
            }  
        };
        

        --- Ende der Datei ---

        --- Datei 'script.php?time=xyz' ---

        if (typeof(MeineAjaxMaschine) == "object") {  
            // MeineAjaxMaschine existiert, also die Werte vergeben  
            MeineAjaxMaschine.values = {  
                // das folgende hier wurde von PHP zusammengestellt  
                herkunftsland : 'string-Wert',  
                bundesland . ['array-wert1', 'array-wert2']  
            };  
        }
        

        --- Ende der Datei ---

        <select name="txtfrom" id="txtfrom"
        onchange="xajax_addtxtstateprovince('txtstateprovince', document.frmPlan.txtfrom.value)">
        [...]
        Desweiteren sollte JavaScript-Code mittels JavaScript ins Dokument geschrieben werden (Stichwort "unobtrusive").
        Das möchte ich machen wenn alles funktioniert. Du hast recht, es ist dann auch aufgeräumter. Aber bis dahin habe ich es lieber wenn alles "beisammen" ist.

        Du kannst ja den Script-Inhalt der in meinem Beispiel 'fest.js' genannten Datei direkt im Kopf Deines HTML-Dokumentes eintragen, um es dann später als externe Datei auszulagern. Das mit dem PHP-generierten JavaScript ist so eine Sache. Es muss als zusätzlicher Request nachgeladen werden und kann daher auch für Deine Testzwecken nicht in die HTML-Datei hinein.

        Du kannst ja eine HTML-Datei als Vorlage definieren, deren Inhalt dann in etwa so aussieht:
        --- Datei 'template.html' ---

        <!DOCTYPE ... (ich kürze hier ab) >  
        <html>  
            <head>  
                <title>Vorlage</title>  
                <script type="text/javascript">//<![CDATA[  
          
                var MeineAjaxMaschine = { (abgekürzt) };  
          
                //]]></script>  
                <script src="/pfad/script.php?time=124356789"></script>  
            </head>  
            <body>  
                <h1>Meine Überschrift</h1>  
                <p>Das folgende ist jedesmal anders...</p>  
        {content}  
                <p>Jetzt kommt wieder Template-Inhalt.</p>  
                <p>Copyright is alles meins!</p>  
            </body>  
        </html>
        

        --- Ende der Datei ---

        Die Zeichenfolge "{content}" kannst Du ja nach Abarbeiten Deines PHP-Scripts mittels str_replace() durch Deinen dynamischen Content ersetzen. Ganz ohne Smarty.

        Liebe Grüße aus Ellwangen,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)