mark: Ajax testen ob Datei existiert problem

Hallo ich bin am verzweifeln ... Folgendes ist meine Javascript Funktion.
Diese funktioniert auch einwandfrei, solange ich sie mit alert "debugge".
Versuche ich jedoch statt des "alert(...);" ein return zu setzen (wie in meinem Code kommentiert ZEILE 35) so gibt mir die Funktion immer ein "undefined" zurück.

Leider bin ich in Ajax nicht allzusehr bewandert, um den Fehler selbst zu
erkennen daher bitte ich um Hilfe.

function file_exist(url){  
	var xmlHttp = null;  
	var fe = null;  
	//Mozilla, Opera, Safari sowie Internet Explorer (ab v7)  
	if (typeof XMLHttpRequest != 'undefined') {  
		xmlHttp = new XMLHttpRequest();  
	}  
	if (!xmlHttp) {  
		// Internet Explorer 6 und älter  
		try {  
			xmlHttp  = new ActiveXObject("Msxml2.XMLHTTP");  
		}catch(e){  
			try {  
				xmlHttp  = new ActiveXObject("Microsoft.XMLHTTP");  
			} catch(e) {  
				xmlHttp  = null;  
			}  
		}  
	}  
	  
	if (xmlHttp) {  
		xmlHttp.open("HEAD",url, true);  
		xmlHttp.send(null);  
		xmlHttp.onreadystatechange = function () {  
			if(xmlHttp.readyState == 4) {  
				switch(xmlHttp.status){  
				case 200: fe = true;  break;  
				case 400: fe = false;  break;  
				case 404: fe = false; break;  
				default : fe = null;  break;  
				}  
				  
				//return fe;  
				alert("status: "+fe+"  url: "+url+" ready:"+xmlHttp.readyState);  
			}  
		}  
	}  
}
  1. Hi,

    Versuche ich jedoch statt des "alert(...);" ein return zu setzen (wie in meinem Code kommentiert ZEILE 35) so gibt mir die Funktion immer ein "undefined" zurück.

    Du machst einen *A*synchronen Request, also wird die Funktion mittels onreadystatechange aus dem linearen Ablauf des restlichen Scriptcodes herausgelöst später aufgerufen.
    Und damit gibt es auch keine Stelle, "an die" du mittels return etwas zurückgeben könntest.
    Deine Funktion file_exist endet, bevor der readystatehandler überhaupt zum Zuge kommt - und da sie selber keinen return-Wert liefert, bekommst du an der aufrufenden Stelle höchstens ein undefined, wenn du dort einen solche in Empfang zu nehmen versuchst.

    Entweder stellst du deinen Request auf synchron um - das ist aber wenig empfehlenswert, weil du damit für die Laufzeit des Request den Client bildlich "lahmlegst";
    oder du verarbeitest das Ergebnis bereits in deiner Handlerfunktion wie gewünscht, bzw. übergibst ihr auch noch eine Referenz auf eine weitere Funktion, die nach dem Eintrudeln des Ergebnisses aufgerufen werden soll, und die dann mit dem Ergebnis etwas machen kann.

    MfG ChrisB

    --
    Light travels faster than sound - that's why most people appear bright until you hear them speak.
    1. Hallo ChrisB,

      Du machst einen *A*synchronen Request, also wird die Funktion mittels onreadystatechange aus dem linearen Ablauf des restlichen Scriptcodes herausgelöst später aufgerufen.
      Und damit gibt es auch keine Stelle, "an die" du mittels return etwas zurückgeben könntest.
      Deine Funktion file_exist endet, bevor der readystatehandler überhaupt zum Zuge kommt - und da sie selber keinen return-Wert liefert, bekommst du an der aufrufenden Stelle höchstens ein undefined, wenn du dort einen solche in Empfang zu nehmen versuchst.

      die Begründung kannte ich bis jetzt noch gar nicht, sie scheint mir aber nicht zutreffend zu sein. Der Aufruf von alert(fe) zeigt klar und deutlich, das die Variable "fe" zum einen existiert und einen Wert hat, und zum anderen nach Deiner Darstellung entsprechend die Funktion Geschichte ist. Dennoch wird fe korrekt ausgegeben.
      Weiterhin besteht beschriebenes Problem im FF 3.0.11 nicht. Auch das spricht gegen Deinen Ansatz.

      Aber noch eine andere Anmerkung an Mark:

                                      case 400: fe = false;  break;  
                                      case 404: fe = false; break;
      

      Status 404 und 410 sagen eindeutig, dass die Ressource nicht vorhanden ist. Status 400 wird im Falle eines unverständlichen Requests ausgegeben. Dies bedeutet aber keines Falls, dass die Ressource nicht vorhanden sei. In wieweit man auch Status 30* zur Aussage "Ressource ist (nicht) vorhanden" subsumiert, ist Implementierungssache des JavaScripts.

      Gruß aus Berlin!
      eddi

      --
      Frei nach z1626: Was wir brauchen ist eine neue Aufklärung - eine "Aufklärung 2.0" wenn man so will.
      Wie sehe es bsw. mit Strafverfolgung der Bundesregierung nach § 154 StGB für jedes von Karlsruhe kassierte Gesetz aus? Wurden sie etwa nicht auf das Grundgesetz eingeschworen?
      1. Hi,

        die Begründung kannte ich bis jetzt noch gar nicht, sie scheint mir aber nicht zutreffend zu sein. Der Aufruf von alert(fe) zeigt klar und deutlich, das die Variable "fe" zum einen existiert und einen Wert hat, und zum anderen nach Deiner Darstellung entsprechend die Funktion Geschichte ist. Dennoch wird fe korrekt ausgegeben.

        Natürlich wird fe an der Stelle mittels alert korrekt ausgegeben.

        Aber wenn aus der Handlerfunktion mittels return ein Wert zurückgegeben wird, *wohin* sollte dieser denn deiner Meinung nach zurückgegeben werden?

        MfG ChrisB

        --
        Light travels faster than sound - that's why most people appear bright until you hear them speak.
        1. Danke für eure Hilfe.

          Wie muss ich also die Funktion ändern, dass ich einen Rückgabewert, den
          "return fe;" erhalte ? Oder ist das so direkt gar nicht möglich ?

          Chris hat mir ja einen Lösungsansatz gegeben, aber da blick ich leider nicht durch :

          [...] oder du verarbeitest das Ergebnis bereits in deiner Handlerfunktion wie
          gewünscht, bzw. übergibst ihr auch noch eine Referenz auf eine weitere
          Funktion, die nach dem Eintrudeln des Ergebnisses aufgerufen werden soll,
          und die dann mit dem Ergebnis etwas machen kann.

          @Edgar :

          Status 404 und 410 sagen eindeutig, dass die Ressource nicht vorhanden ist.
          Status 400 wird im Falle eines unverständlichen Requests ausgegeben. Dies
          bedeutet aber keines Falls, dass die Ressource nicht vorhanden sei. In
          wieweit man auch Status 30* zur Aussage "Ressource ist (nicht) vorhanden"
          subsumiert, ist Implementierungssache des JavaScripts.

          Werde ich berücksichtigen. Danke ! Ich erhalte komischerweise bei Bildern, die
          auf externen Servern liegen und nicht vorhanden sind immer den Status 400.
          (als alert ausgabe)

          1. Hi,

            Ich erhalte komischerweise bei Bildern, die auf externen Servern liegen und nicht vorhanden sind immer den Status 400.

            Da dürftest du eher eine Fehlermeldung in der JS-Konsole bekommen, weil ein solcher Request die Same Origin Policy verletzt, und somit unter normalen Umständen gar nicht möglich ist.

            MfG ChrisB

            --
            Light travels faster than sound - that's why most people appear bright until you hear them speak.
            1. Da dürftest du eher eine Fehlermeldung in der JS-Konsole bekommen, weil »» ein solcher Request die Same Origin Policy verletzt, und somit unter
              normalen Umständen gar nicht möglich ist.

              Das ich den Status 400 bekomme liegt daran, dass ich bei den URLs, die ich
              meiner Javascript Funktion übergebe ein modifiziertes (= so, dass auch
              externe URL's möglich sind) timthumb script mitlaufen habe.
              Meine URL's sehen beispielsweise so aus :

              http://localhost/wordpress/wp-content/themes/gazette/timthumb.php?src=http://c2.ac-images.myspacecdn.com/images02/42/l_b2bc676b05364fb1b61a41abf6e99c1d.jpg&h=270&w=595&zc=1&q=95

              Jedoch wäre es schon schön, wenn Du eben mit Beispielcode hilfreich zur »» Seite stündest, um aufzuklären, statt Offensichtlichkeiten abzufragen und
              somit den entsetzlichen Stil von Cheatah nachzuäffen.

              hmm ... mein Beispielcode ist aber endlos lang. Ich hätte nicht gedacht,
              dass jemand sich für meine Leidensgeschichte interessiert :o) Aber bitte:
              Ich arbeite an einem Wordpress Theme ähnlich dem WOO Gazette theme.

              Dies verwendet die Smooth Gallery von johndesign.net.
              Leider besitzt diese Gallerie meines Wissens keine Funktion ein "default"
              Bild anzugeben, sollte ein Bild nicht geladen werden können. Diese versuche
              ich nun nachträglich hinzuzufügen.

              Die Bilder liest die Gallerie aus folgendem html Code aus :

              <div id="myGallery">  
                  <div class="imageElement">  
              	<h3>Item 1 Title</h3>  
              	<p>Item 1 Description</p>  
              	<a href="gallery-images/item-1/" title="open image" class="open"></a>  
                      <img src="assets/images/samples/77196_6784-gallery.jpg" class="full" alt="Item 1 Title" />  
              	<img src="assets/images/samples/77196_6784-mini.jpg" class="thumbnail" alt="thumbnail of Item 1 Title" />  
                   </div>  
              </div>
              

              Anfangs hab ich eine Lösung des Problems mit php versucht. Zuerst indem ich
              die Existenz der Bilder mit "fopen" abgefragt habe, dann mit cURL und
              schlussendlich mit get_headers. Aber die ersten beiden sind recht langsame
              Funktionen die die Ladezeit der Seite stark erhöhen, letztere funktioniert
              nur mit php5.

              Also hab ich mich für eine Client-seitige Lösung entschieden. Javascript.
              Zuerst hab ich versucht die Bilder Url mit onerror zu modifizieren, so dass
              bei einem Fehler eine Funktion aufgerufen wird, die direkt auf die DOM der
              Smooth Gallery zugreift :

              <div id="myGallery">  
                  <div class="imageElement">  
              	<h3>Item 1 Title</h3>  
              	<p>Item 1 Description</p>  
              	<a href="gallery-images/item-1/" title="open image" class="open"></a>  
                      <img src="assets/images/samples/77196_6784-gallery.jpg" onerror="default_pic(this.src)" class="full" alt="Item 1 Title" />  
              	<img src="assets/images/samples/77196_6784-mini.jpg" onerror="default_pic(this.src)" class="thumbnail" alt="thumbnail of Item 1 Title" />  
                   </div>  
              </div>
              

              Dazugehörige Javascript Funktion :

              			function default_pic(src){  
              				var default_thumb	= "http://localhost/airbagpromo_testarea/wp-content/themes/gazette/images/default_100x75.png";  
              				var sft 			= src.search(/h=75/);  
              				var sfi 			= src.search(/h=270/);  
              				var thumb_src		= window.el.innerHTML;  
              				var searchfor   	= src.replace(/&/g, "&amp;");  
              				searchfor 			= searchfor.toRegExpString();  
              				searchfor 			= new RegExp(searchfor, "g");  
              				  
              				if(sft != -1){ //it's a thumbnail  
              					thumb_src = thumb_src.replace(searchfor, default_thumb);  
              					window.el.innerHTML = thumb_src;  
              				}  
                
              				if(sfi != -1){// it's a normal picture  
              					// todo  
              				}  
              			}  
                
              // changes any String to a RegExp compatible format replacing reserved chars ^$.*+?=!:|\/()[]{}  
              String.prototype.toRegExpString = function () { // does not work in netscape 4;  
              	return this.replace(/([\^\$\.\*\+\?\=\!\:\|\\\/\(\)\[\]\{\}])/g,"\\$1");  
              };
              

              Das Problem hierbei war, dass es mir zwar gelungen ist die DOM der
              smooth Gallery (window.el.innerHTML) zu verändern. Diese Veränderungen
              jedoch nicht übernommen wurden. Warum weiß ich nicht, dazu hätte ich
              den Code der smooth Gallery genauer studieren müssen. Mir ist aber
              aufgefallen, dass es wenn ich direkt das smooth Gallery script verändere
              funktioniert. Also habe ich abermals meinen Ansatz gewechselt:

              In Zeile 149 der jd.gallery.js Version 2.0 versuche ich nun
              direkt das Script so zu verändern, dass ein "default"-Bild angezeigt wird.
              Den ganzen Code kann ich aufgrund der Beschränkungen des Forums ("sie
              sind wohl geschwätzig") nicht posten. Deshalb hier der Auszug :

                
              populateGallery: function(element, startNumber) {  
              		var data = [];  
              		options = this.options;  
              		currentArrayPlace = startNumber;		  
              		element.getElements(options.elementSelector).each(function(el) {  
              			  
              			//	alert("src: "+ el.getElement(options.imageSelector).getProperty('src'));  
              			  
              			var img_exists = file_exist(el.getElement(options.imageSelector).getProperty('src'));  
              			alert(img_exists);  
              			elementDict = {  
              				image: el.getElement(options.imageSelector).getProperty('src'),  
              				number: currentArrayPlace,  
              				transition: this.options.defaultTransition  
              			};
              
              1. P.S.: So ich arbeite jetz dran. Wenn ich die Lösung hab poste ich den Code hier.

                lg
                mark

              2. Re:

                [Status 400]
                http://localhost/wordpress/wp-content/themes/gazette/timthumb.php?src=http://c2.ac-images.myspacecdn.com/images02/42/l_b2bc676b05364fb1b61a41abf6e99c1d.jpg&amp;h=270&amp;w=595&amp;zc=1&amp;q=95

                Wenn es für Dich mit 400 läuft, ist das natürlich kein Thema. Dennoch wundert es mich, das der Server, wie Du schriebst, nur bei nicht vorhandenen Ressourcen mit 400 antwortet. Das ist jedenfalls nicht standardkonform. (Ein Grund mehr sein CMS lieber selbst zu schreiben.)

                Gruß aus Berlin!
                eddi

                --
                Frei nach z1626: Was wir brauchen ist eine neue Aufklärung - eine "Aufklärung 2.0" wenn man so will.
                Wie sieht es bsw. mit Strafverfolgung der Bundesregierung nach § 154 StGB für jedes von Karlsruhe kassierte Gesetz aus? Wurde sie etwa nicht auf das Grundgesetz eingeschworen?
                1. Hi,

                  [Status 400]
                  http://localhost/wordpress/wp-content/themes/gazette/timthumb.php?src=http://c2.ac-images.myspacecdn.com/images02/42/l_b2bc676b05364fb1b61a41abf6e99c1d.jpg&amp;h=270&amp;w=595&amp;zc=1&amp;q=95

                  Wenn es für Dich mit 400 läuft, ist das natürlich kein Thema. Dennoch wundert es mich, das der Server, wie Du schriebst, nur bei nicht vorhandenen Ressourcen mit 400 antwortet. Das ist jedenfalls nicht standardkonform.

                  Wir wissen nicht, welche Gründe "er" dafür hat.

                  400 steht für Bad Request.
                  Und dieser Request kommt hier nicht von einem "normalen" Browser, sondern von einem PHP-Script - und ist damit, ohne weitere Maßnahmen, relativ deutlich von ersterem zu unterscheiden.
                  Und gerade "grosse" Seiten wie MySpqce haben oftmals ein starkes Interesse daran, das Auslesen ihrer Ressourcen mittels nicht genehmer Spider/Bots zu unterbinden. Dass man in so einem Falle mit einem 400 antwortet, ist also nicht so ungewöhnlich, und auch nicht unorthodox (403 Forbidden wäre natürlich eine ebenso denkbare Alternative).

                  Warum das im vorliegenden Falle nur bei nicht vorhandenen Bildern passiert, wäre noch zu untersuchen.

                  MfG ChrisB

                  --
                  Light travels faster than sound - that's why most people appear bright until you hear them speak.
                  1. Re:

                    Und dieser Request kommt hier nicht von einem "normalen" Browser, sondern von einem PHP-Script - und ist damit, ohne weitere Maßnahmen, relativ deutlich von ersterem zu unterscheiden.

                    Warum?

                    Und gerade "grosse" Seiten wie MySpqce haben oftmals ein starkes Interesse daran, das Auslesen ihrer Ressourcen mittels nicht genehmer Spider/Bots zu unterbinden.

                    Die Information kann ich mir dazu wo nachlesen?

                    Gruß aus Berlin!
                    eddi

                    --
                    Frei nach z1626: Was wir brauchen ist eine neue Aufklärung - eine "Aufklärung 2.0" wenn man so will.
                    Wie sieht es bsw. mit Strafverfolgung der Bundesregierung nach § 154 StGB für jedes von Karlsruhe kassierte Gesetz aus? Wurde sie etwa nicht auf das Grundgesetz eingeschworen?
          2. Re:

            Ich erhalte komischerweise bei Bildern, die auf externen Servern liegen und nicht vorhanden sind immer den Status 400.

            Das ist interessant. Kannst Du mir hier einen Link posten, bei dem dies so ist? Ich würde mir mal die Header ansehn. Danke.

            Gruß aus Berlin!
            eddi

            --
            Frei nach z1626: Was wir brauchen ist eine neue Aufklärung - eine "Aufklärung 2.0" wenn man so will.
            Wie sehe es bsw. mit Strafverfolgung der Bundesregierung nach § 154 StGB für jedes von Karlsruhe kassierte Gesetz aus? Wurde sie etwa nicht auf das Grundgesetz eingeschworen?
        2. Re:

          Aber wenn aus der Handlerfunktion mittels return ein Wert zurückgegeben wird, *wohin* sollte dieser denn deiner Meinung nach zurückgegeben werden?

          xmlHttp.onreadystatechange = function () {}
          Dass es nicht funktioniert, habe ich gerade eben auch nachvollziehen können, weil ich ein Test nicht local habe laufen lassen. Jedoch wäre es schon schön, wenn Du eben mit Beispielcode hilfreich zur Seite stündest, um aufzuklären, statt Offensichtlichkeiten abzufragen und somit den entsetzlichen Stil von Cheatah nachzuäffen.

          Gruß aus Berlin!
          eddi

          --
          Frei nach z1626: Was wir brauchen ist eine neue Aufklärung - eine "Aufklärung 2.0" wenn man so will.
          Wie sehe es bsw. mit Strafverfolgung der Bundesregierung nach § 154 StGB für jedes von Karlsruhe kassierte Gesetz aus? Wurde sie etwa nicht auf das Grundgesetz eingeschworen?
          1. Hi,

            Dass es nicht funktioniert, habe ich gerade eben auch nachvollziehen können, weil ich ein Test nicht local habe laufen lassen. Jedoch wäre es schon schön, wenn Du eben mit Beispielcode hilfreich zur Seite stündest,

            Beispielcode für was?

            um aufzuklären, statt Offensichtlichkeiten abzufragen

            Wenn Offensichtlichkeiten vom Frager nicht erkannt oder berücksichtigt werden, dann weise ich erst mal darauf hin.

            und somit den entsetzlichen Stil von Cheatah nachzuäffen.

            Den brauche ich nicht nachzuäffen, den kann ich selber :-)
            Und ich finde ihn nicht entsetzlich, sondern in solchen Fällen angebracht und hilfreich.

            Frager hat Offensichtlichkeit nicht bedacht, wird darauf hingewiesen - und damit dazu angeregt, selber noch mal darüber nachzudenken.

            Wenn mir sowas passiert, dann sind mir Antworten in diesem "Stil" noch mit die liebsten. Sie weisen die Richtung, in die ich meine eigenen Gedanken lenken muss, um dem Problem auf die Schliche zu kommen.
            Sie sind für mich i.a.R. hilfreicher, als gut gemeinter Beispielcode, der dann doch wieder irgendwie am Problem vorbeigeht, ggf. Fehler enthält oder viel Überflüssiges, weil der Antworter ihn per C&P aus einer eigenen Applikation bereitstellt.

            MfG ChrisB

            --
            Light travels faster than sound - that's why most people appear bright until you hear them speak.
            1. Re:

              Beispielcode für was?

              function file_exist(url){  
                      var xmlHttp = null;  
                      // Mozilla  
                      xmlHttp = new XMLHttpRequest();  
                      if (xmlHttp) {  
                              xmlHttp.open("HEAD",url, true);  
                              xmlHttp.send(null);  
                              xmlHttp.onreadystatechange = function () {  
                                      if(xmlHttp.readyState == 4) {  
              				alert("Aufruf 1");  
                                      }  
                              }  
                      }  
                      // local wird dies als Zweites aufgerufen  
              	alert("Aufruf 2");  
              }
              

              Beispielcode zur Demonstration Deiner Aussage

              Gruß aus Berlin!
              eddi

              --
              Frei nach z1626: Was wir brauchen ist eine neue Aufklärung - eine "Aufklärung 2.0" wenn man so will.
              Wie sieht es bsw. mit Strafverfolgung der Bundesregierung nach § 154 StGB für jedes von Karlsruhe kassierte Gesetz aus? Wurde sie etwa nicht auf das Grundgesetz eingeschworen?