# Ajax in Modul, Fehler Joomla



## =fire= (12. Juli 2009)

Guten Tag,

ich habe mir ein Modul geschrieben das einfach nur immer den Datenbank eintrag anzeigen soll.

*Leider kommt der Fehler: *

Der Request wurde abgeschlossen, ist aber nicht OK
Fehler:404

Sobald ich das Script direkt aufrufe kommt der Fehler nicht. Dann klappt alles prima.

Ich habe das Module mit {module AJAX} in den Artikel der Startseite eingebunden.

Das Script:
mod_AJAX.php

```
<script type="text/javascript">
  <!--
      var aktiv = window.setInterval("setRequest()", 1000);
    var request = false;

    // Request senden
    function setRequest() {
        // Request erzeugen
        if (window.XMLHttpRequest) {
            request = new XMLHttpRequest(); // Mozilla, Safari, Opera
        } else if (window.ActiveXObject) {
            try {
                request = new ActiveXObject('Msxml2.XMLHTTP'); // IE 5
            } catch (e) {
                try {
                    request = new ActiveXObject('Microsoft.XMLHTTP'); // IE 6
                } catch (e) {}
            }
        }

        // überprüfen, ob Request erzeugt wurde
        if (!request) {
            alert("Kann keine XMLHTTP-Instanz erzeugen");
            return false;
        } else {
            var url = "current.php";
            // Request öffnen
            request.open('post', url, true);
            // Request senden
            request.send(null);
            // Request auswerten
            request.onreadystatechange = interpretRequest;
        }
    }

    // Request auswerten
    function interpretRequest() {
        switch (request.readyState) {
            // wenn der readyState 4 und der request.status 200 ist, dann ist alles korrekt gelaufen
            case 4:
                if (request.status != 200) {
                    alert("Der Request wurde abgeschlossen, ist aber nicht OK\nFehler:"+request.status);
                } else {
                    var content = request.responseText;
                    // den Inhalt des Requests in das <div> schreiben
                    document.getElementById('content').innerHTML = content;
                }
                break;
            default:
                break;
        }
    }
  //-->
  </script>
  <div id="content"></div>
```

current.php

```
<?php
header('Content-Type: text/html; charset=utf-8'); // sorgt für die korrekte Kodierung
header('Cache-Control: must-revalidate, pre-check=0, no-store, no-cache, max-age=0, post-check=0'); // ist mal wieder wichtig wegen IE
include('config.php');
$sql = mysql_query("SELECT u.username FROM jos_users as u LEFT JOIN jos_sl_bit as b ON u.id=b.user_id WHERE b.article_id='".$id."' ORDER by b.bit_id DESC LIMIT 1", $verbindung);

$row1 = mysql_fetch_array($sql);
echo $row1['username'];
?>
```


Vielen Dank im voraus, Gruß fire


----------



## Sven Mintel (12. Juli 2009)

Moin,

der Fehlertext  ist ja eindeutig....der Pfad stimmt nicht.

Falls du Firebug nutzt, schaue mal im Netzwerktab nach, dort sollte der komplette Pfad stehen, der angefragt wird....und dich der Lösung näher bringen.

Ein Verzicht auf relative Pfade wäre dabei wohl das sicherste.


----------



## Sven Mintel (13. Juli 2009)

Firesimon hat gesagt.:
			
		

> Wenn ich auf der Seite auf ein Link oder Button klicke kommt manchmal
> 
> Der Request wurde abgeschlossen, ist aber nicht OK
> Fehler: ()



Woran es da hapert, kann ich ohne mehr Details nicht sagen.
Das Skript prüft ja, ob dort mit einem HTTP-Statuscode 200 geantwortet wird, und sieht alles andere als Fehler an(was nicht unbedingt sein muss)

Wenn der Status 404 ist, dann stimmt halt der Pfad nicht...welche Statuscodes bekommst du denn bei den Links&Buttons?


Was das nicht funktionierende betrifft:
JS-Code in Antworten von AJAX-Requests wird nicht gezwungenermassen interpretiert, auch nicht, wenn man ihn per innerHTML ins Dokument einfügt.
Selbst wenn es so wäre, wird deine Aktion ja beim onload angestossen:

```
window.onload = function () {
          new countdown();
    };
```
...dieser Zeitpunkt ist zu dem Moment, wo die Antwort vom Server kommt, jedoch höchstwahrscheinlich verstrichen.

Ich würde so herangehen:
Lese in der current.php die Daten(Jahr, Monat, etc) aus, und gebe sie als JSON-String aus. Die Daten kannst du dann im anfragenden Skript wieder verarbeiten, z.B. indem du sie der (auch im anfragenden Skript notierten Funktion countdown) als Parameter übergibst.


----------



## Sven Mintel (13. Juli 2009)

Jo, kann ich.

Erzähl doch erstmal ein paar Details über deine Anwendung 

Du hast da den Countdown.... soll das immer nur einer bleiben pro Seite, oder auch mal mehr.

Der Countdown soll ja, soweit ich es verstanden habe, die restliche Laufzeit einer Auktion anzeigen...warum holst du bspw. das Enddatum per AJAX ab, und nicht direkt in dem Skript?


----------



## =fire= (13. Juli 2009)

Hi,

richtig. Das Enddatum der Auktion lese ich mit PHP aus. Da sich das Datum in der datenbank aber ändern kann soll AJAX überprüfen ob ein neues Datum vorhanden ist ohne das die Seite aktualisiert werden muss.

Mfg Simon


----------



## Sven Mintel (13. Juli 2009)

Ok, das leuchtet ein.

Und wie sieht es mit der Anzahl der Countdowns pro Seite aus?


----------



## Sven Mintel (14. Juli 2009)

Firesimon hat gesagt.:
			
		

> Das ist nur ein Countdown.



Mir doch egal :suspekt:

Hier eine Variante, die mit mehreren Countdowns umgehen kann(nicht erschrecken, sieht vielleicht anfangs nach sehr viel aus)
	
	
	



```
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; 
                                charset=utf-8"   />
<meta name="author"             content="doktormolle" />
<meta name="date"               content="2009-07-13" />
<title>Test</title>
<script type="text/javascript">
<!--
AJAX=function(args)
{
      //das Basis-Objekt:
    var ajax = args;

  /**
    * Erweiterung des Basis-Objektes 
    * um die Methode zum Ausführen des Requests
    **/
  ajax.request = function() 
  {
    try{
    
            //Erstellen [XMLHttpRequest]-Objekt
          this.xhr = window.XMLHttpRequest
                    ? new XMLHttpRequest()
                    : new ActiveXObject("Microsoft.XMLHTTP"); 
			  
            //Setzen der Übermittlungsmethode
          this.method=(typeof this.method == 'undefined')
                        ? 'GET'
                        : this.method;
			  
            //Aufbereiten der Daten		
          this.data=(this.data || '');
			  
          this.postData=(this.method=='GET')
                          ? null
                          : this.data;
			            
            //Aufbereiten der URL			                   
          this.URL=(this.method=='POST' || this.data=='')
                      ? this.URL
                      : (
                          (this.URL.indexOf('?')==-1)
                            ? this.URL+'?'+this.data
                            : this.URL+'&'+this.data
                          );
			   
            //Initialisieren des Requests
          this.xhr.open(this.method,this.URL,true);
			  
            //Senden den bei POST erforderlichen Request-Header     
          if(this.method=='POST')
            {
              this.xhr.setRequestHeader("Content-type", 
                                        "application/x-www-form-urlencoded");
              this.xhr.setRequestHeader("Content-length", 
                                         this.postData.length);
              this.xhr.setRequestHeader("Connection", 
                                        "close");
            }
			    
            //Bei Bedarf Nutzung des Cache verhindern
          if(!typeof this.nocache || this.nocache)
            {
              this.xhr.setRequestHeader("If-Modified-Since",
                                        "Thu, 01 Jan 1970 00:00:00 GMT");
            }
			  
            //Zuweisen der verarbeitenden Funktion
          if(typeof this.callback == 'function')
          {
            this.xhr.onreadystatechange = 
                                  function()
                                  { 
                                    
                                    var r=ajax.xhr.readyState;
                                    var s=(r==4)?ajax.xhr.status:null
                                    ajax.callback(ajax,r,s);
                                      
                                  };
          }

            //Senden   
          this.xhr.send(this.postData);    
    }
    catch(e)
    {
      try{console.log('Fehler:AJAX.request()');}
      catch(e){}
    }
  
    
  }
	
      //Rückgabe Basis-Objekt
    return ajax;
}



Number.prototype.formatSpareTime=function(f)
{
  sec=this;
  var t={'d':0,'h':0,'m':0,'s':0};
  t.d=Math.floor(sec/86400);
  sec=sec%86400;
  t.h=Math.floor(sec/3600);
  sec=sec%3600;
 t.m=Math.floor(sec/60);
  t.s=sec%60;
  var r=[];
  for(var k in f)
  {
    if(t[k] || !f[k][4])
    {
      a=(t[k]<10)
          ? [(t[k]===1)
                  ? f[k][1]
                  : f[k][0],
              (f[k][3])
                  ? '0'+t[k]
                  : t[k]
            ]
          : [f[k][0],t[k]]
      
      if(f[k][1]){a.reverse()}
      r.push(a.join(' '));
      
    }
  }
  return(r.join(''));
}

function countdown_artikel()
{
  
  ajax=countdown_artikel.arguments[0];
  request=ajax.xhr;
  if(ajax.xhr.readyState==4)
  {
    window[ajax.prefix+ajax.artikelid]=
    {
    'ajax':ajax,
    'format':{'d':['Tage,','Tag,',1,0,1],
              'h':['Stunden:','Stunden:',1],
              'm':[':',':',1,1],
              's':['','',1,1]
             },
    'start':Math.floor(new Date().getTime()/1000),
    'i':0,
    timer:function()
            {
              elapsed=Math.floor(new Date().getTime()/1000)-this.start;
              spare=this.end-elapsed;
              if(spare<0)
              {
                this.target.innerHTML="die Auktion ist beendet";
              }
              else
              {
                this.i++;
               
                if(this.i%this.ajax.refresh==0)
                {
                  AJAX(this.ajax).request();
                }
                else
                {
                  window.setTimeout(this.id+".timer()",this.ajax.interval);
                }
                 this.target.innerHTML=Number(spare).formatSpareTime(this.format);
              }
            },
    'init':function()
            {
            
              this.id=this.ajax.prefix+this.ajax.artikelid;
              this.target=document.getElementById(this.id);
              this.end=this.ajax.xhr.responseText;
              window.setTimeout(this.id+".timer()",this.ajax.interval);
              return this;
            }
     
    }.init();
  }
  
}

//-->
</script>
<style type="text/css">
<!--
-->
</style>
</head>
<body>
<div id="countdown4711"></div>
<script type="text/javascript">
<!--
AJAX(
      {'method':'POST',
       'artikelid':'4711',
       'prefix':'countdown',
       'interval':1000,
       'refresh':10,
       'data':'artikelid='+4711,
       'URL':'current.php',
       'callback':countdown_artikel}
).request();
//-->
</script>
<div id="countdown4712"></div>
<script type="text/javascript">
<!--
AJAX(
      {'method':'POST',
       'artikelid':'4712',
       'prefix':'countdown',
       'interval':1000,
       'refresh':10,
       'data':'artikelid='+4712,
       'URL':'current.php',
       'callback':countdown_artikel}
).request();
//-->
</script>
<div id="countdown4713"></div>
<script type="text/javascript">
<!--
AJAX(
      {'method':'POST',
       'artikelid':'4713',
       'prefix':'countdown',
       'interval':1000,
       'refresh':10,
       'data':'artikelid='+4713,
       'URL':'current.php',
       'callback':countdown_artikel}
).request();
//-->
</script>


</body>
</html>
```

Erstmal ein paar Grundgedanken:

Deine bisherige AJAX-Lösung kann nur mit einem einzigen Request gleichzeitig umgehen, ich nutze daher eine andere Möglichkeit, die Beschreibung dazu findest du hier: http://www.tutorials.de/forum/javas...x-http-requests-unter-kontrolle-behalten.html

Du hast da serverseitig ein Datum gespeichert, und benutzt das zu Berechnungen in JS...da gibt es ein grosses Problem: JS arbeitet mit der Clientzeit und nicht mit der Serverzeit.
Bei einem Besucher aus Peking wird die Auktion somit(zumindest in der Ausgabe im Browser) früher beendet sein, als bei einem Besucher aus Rio.
Daher erwartet  meine Lösung nicht eine Datumsangabe, sondern eine Zeitdifferenz(in Sekunden) bis zum Ablauf der Auktion.
Du müsstest also serverseitig von dem in der DB gespeicherten Timestamp die aktuelle* Server*-Zeit abziehen.

Noch ein paar Erläuterungen zum Aufruf:


```
<div id="countdown4711"></div>
<script type="text/javascript">
<!--
AJAX(
      {'method':'POST',
       'artikelid':'4711',
       'prefix':'countdown',
       'interval':1000,
       'refresh':10,
       'data':'artikelid='+4711,
       'URL':'current.php',
       'callback':countdown_artikel}
).request();
//-->
</script>
```
Die Parameter:

*method:*sollte klar sein
*artikelid:* du fragst ja einen Artikel aus der DB ab...hier gebe seine ID an
*prefix:*da auch mehrere Countdowns möglich sein sollen, gebe hier ein Prefix an, welches der ID des Countdowns vorrangestellt wird(du siehst das an der ID des <div>...countdown4711, diese setzt sich aus dem Prefix und der Artikel-ID zusammen, so findet jeder Countdown sein richtiges Zielelement)
*interval:* die Millisekunden, nach denen der Coundown aktualisiert werden soll(Werte unter 1000 sind da eigentlich sinnlos, da du ja eh nur Sekundenschritte anzeigst)
*refresh: *Zähler, der angibt, nach wievielen Intervallen per AJAX auf dem Server nachgeschaut werden soll, ob sich am Endtermin etwas geändert hat.
Mit der Einstellung dort von 10 und dem Interval von 1000 wäre das also alle 10 Sekunden(übertreibs dort nicht, so ein Server ist auch nur ein Mensch, und dort jede Sekunde einen Request abzuschicken, kann ihn bei vielen Besuchern recht sauer machen  )
*data: *das sind die Daten, die gesendet werden sollen, im Beispiel würde ein $_POST['artikelid'] mit dem Wert 4711 an den Server gesendet...also die Artikel-ID für die DB-Abfrage.
*URL: *sollte klar sein
*callback: *die Funktion, die die Coundowns erstellt und das ganze Aktualisieren übernimmt...du findest sie im Code.

Das wärs...falls du Fragen hast, frag(aber nicht heute, ich  bin erst nachts wieder daheim  )


----------



## =fire= (14. Juli 2009)

Hallo,

wie sollen denn dann die PHP Datei aussehen? einfach nur das Datum mit echo ausgeben?

Mfg Simon


----------



## Sven Mintel (15. Juli 2009)

Nicht das Datum...somdern die Sekunden bis zum Ablauf der Auktion, also einen Integer-Wert ausgeben.


----------



## =fire= (15. Juli 2009)

Okay, das klappt wunderbar danke. Kann man da noch was ergänzen das sobald der Countdown = 0 ist eine PHP Datei ausgeführt wird?

Mfg Simon


----------



## Sven Mintel (15. Juli 2009)

Was verstehst du unter "PHP-Datei ausführen"?


----------



## =fire= (16. Juli 2009)

Hallo,

hat sich geklärt, mache das mit PHP.

Kannst du mein Script dir nochmal vornehmen und es verbessern, so das es auch im Internet Explorer geht. Und es stabiler läuft. Brauche insgesamt rund 5 Abfragen auf einer Seite. kann man das optimieren?

Mfg Simon


----------



## =fire= (21. Juli 2009)

Guten Tag,

wie kann ich das Format ändern, sodass immer die voranstehende Null da ist.

Z.b. so: 00:00:11:24


----------



## Sven Mintel (22. Juli 2009)

Moin,

Das Format kannst du hier einstellen:
	
	
	



```
'format':{'d':['Tage,','Tag,',1,0,1],
              'h':['Stunden:','Stunden:',1],
              'm':[':',':',1,1],
              's':['','',1,1]
             },
```
wenn das jeweils 4. Element der dort enthaltenen Arrays d,h,m,s den Wert true hat, dann gibts eine führende Null, also bspw:
	
	
	



```
'format':{'d':[':',':',1,1,1],
              'h':[':',':',1,1],
              'm':[':',':',1,1],
              's':['','',1,1]
             }
```

...bewirkt die Ausgabe nach dem von dir geposteten Format.


----------



## =fire= (22. Juli 2009)

Moin,

ja fast 

Ich möchte aucher wenn es nur 2 Stunden sind das z.b. es so angezeigt wird
00 : 02 : 00 : 00

Also auch die Tage als 00 wenn es null Tage sind.


----------



## Sven Mintel (22. Juli 2009)

Dann lasse beim Format für *d*(ay) das 5.Element weg...wie bei den anderen


----------



## =fire= (23. Juli 2009)

Hallo,

ein Problem habe ich noch mit dem Countdown und zwar rechnet der die Minuten erst bei 30 Sekunden neu und nicht bei 00 Sekunden.

Danke,


----------



## Sven Mintel (23. Juli 2009)

Ersetze das hier:
	
	
	



```
t.m=Math.round(sec/60);
```

hierdurch:
	
	
	



```
t.m=Math.floor(sec/60);
```


----------

