Christoph: Nützliche JavaScript-Schnipsel

Moin.

Diejenigen von euch, die sich seit längerem mit JavaScript herumschlagen mussten, habe sich mit der Zeit eventuell eine eigene Bibliothek von Skripten zugelegt.

Ich würde gerne sehen, was sich bei anderen so angesammelt hat. Dabei sollten die Skripte

- nützlich
  - kurz
  - browserübergreifend funktionstüchtig

sein. Zwei von drei Punkten sollten mindestens erfüllt sein.

Ich mache mal den Anfang:

--- clone() ---

Echte prototypische Vererbung mit der von Mozilla bekannten \_\_proto\_\_ Eigenschaft. Anders als in Geckos ist diese browserübergreifend jedoch nur bei Objekterzeugung setzbar.

  
function clone(obj) {  
 if(obj.isPrototypeOf(this))  
  this.__proto__ = obj;  
 else return new arguments.callee(arguments.callee.prototype = obj);  
}  

--- hash() ---

Hashfunktion für beliebige Datentypen. Erlaubt es, Objekte als Maps mit beliebigen Schlüsseln zu verwenden - unterscheidet '5' und 5 und versieht Objekte mit eindeutiger Id.

  
function hash(value) {  
 return (typeof value) + ' ' + (value instanceof Object ?  
  (value.__hash || (value.__hash = ++arguments.callee.current)) :  
  value.toString());  
}  
  
hash.current = 0;  

--- each() ---

Iteration über die objekteigenen Eigenschaften.

  
function each(obj, func) {  
 for(var prop in obj) {  
  if(obj.hasOwnProperty(prop))  
   func.call(obj, prop, obj[prop]);  
 }  
}  

--- XMLHttpRequest() ---

Erlaubt es, Request-Objekte auch im IE über new XMLHttpRequest() zu erzeugen.

  
if(typeof window.XMLHttpRequest !== 'function' &&  
 typeof window.ActiveXObject === 'function') {  
 window.XMLHttpRequest = function() {  
  try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}  
  try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}  
  try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}  
  try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}  
  return null;  
 };  
}  

--- onready() ---

Browserübergreifender Ersatz für das DOMContentLoaded-Ereignis. Erwartet eine Liste von Funktionen als Argumente.

  
function onready() {  
 var args = arguments;  
 var timeout = arguments.callee.timeout;  
 (function() {  
  if(document.body && document.body.lastChild) {  
   for(var i = 0; i < args.length; ++i)  
    args[i]();  
  }  
  else setTimeout(arguments.callee, timeout);  
 })();  
}  
  
onready.timeout = 100;  

--- capture() ---

Nicht wirklich kurz, aber dafür äußerst nützlich: Vereinfacht die Ereignis-Behandlung enorm. Erwartet als Argmente:

1. den Ereignis-Typ (z.B. 'click')
  2. eine Auswahlregel, welche Elemente als Ereignis-Quellen in Frage kommen
  3. die Funktion, die das Ereignis verarbeitet

Erlaubte Werte für die Auswahlregel sind

- true:
Das Ereignis wird immer abgefangen

- eine Zeichenkette:
Beginnt diese mit '#', werden Elemente mit entsprechender Id behandelt. Beginnt sie mit '.', werden Elemente mit entsprechender Klasse behandelt. Ansonsten wird die Zeichenkette als Element-Name interpretiert.

- ein regulärer Ausdruck:
Der Ausdruck wird gegen die className-Eigenschaft eines Elements geprüft.

- eine beliebige Funktion:
Das zu überprüfende Element wird als this übergeben; die Funktion muss einen Wahrheitswert zurückgeben.

Sowohl in standardkonformen Browsern als auch im IE wird der Verarbeitungsfunktion die Ereignis-Quelle als this und das Ereignis-Objekt als erstes Argument übergeben. Liefert die Funktion false zurück, wird die Standard-Behandlung des Ereignisses (Formular absenden, Link verfolgen, ...) ausgesetzt.

  
var capture = (function() {  
 function noCapture() {  
  throw new Error('event capture unsupported');  
 }  
  
 function returnTrue() {  
  return true;  
 }  
  
 function createChecker(condition) {  
  if(condition === true)  
   return returnTrue;  
  
  if(typeof condition === 'string') {  
   switch(condition.charAt(0)) {  
    case '#': {  
     var id = condition.substring(1);  
     return function() {  
      return this.id === id;  
     }  
    }  
  
    case '.': {  
     return createChecker(eval('/(^|\s)' +  
      condition.substring(1) + '(\s|$)/'));  
    }  
  
    default: {  
     var tagName = condition.toLowerCase();  
     return function() {  
      return this.nodeName.toLowerCase() === tagName;  
     };  
    }  
   }  
  }  
  
  if(condition instanceof RegExp) {  
   return function() {  
    return condition.test(this.className);  
   };  
  }  
  
  if(typeof condition === 'function')  
   return condition;  
  
  throw new Error('unsupported capture condition: ' + condition);  
 }  
  
 function addCapture(type, condition, handler) {  
  var checker = createChecker(condition);  
  document.addEventListener(type, function(event) {  
   if(checker.apply(event.target) &&  
    handler.call(event.target, event) === false) {  
    event.preventDefault();  
   }  
  }, false);  
 }  
  
 function attachCapture(type, condition, handler) {  
  var checker = createChecker(condition);  
  document.attachEvent('on' + type, function() {  
   if(checker.apply(event.srcElement) &&  
    handler.call(event.srcElement, event) === false) {  
    event.returnValue = false;  
   }  
  });  
 }  
  
 return document.addEventListener ? addCapture :  
  document.attachEvent ? attachCapture :  
  noCapture;  
})();  

Und jetzt ihr ;)

Christoph

  1. PS: Der Name der Funktion capture() ist irreführend, da sie am Ende der 'bubbling'- Phase und nicht zu Beginn der 'capture'-Phase greift (vgl. w3c Spezifikation).

    Irgendwelche Namensvorschläge?

    Christoph

  2. Hi,

    keine Ahnung ob das Forum jetzt hier ein Scriptarchiv zulässt, ich fände es nicht verkehrt.

    Meinen Senf kann ich allerdings nicht dazugeben, weil meine JS-Schnipsel dir wohl zu trivial erscheinen würden, wenn ich deine proffesionellen Dinger sehe.

    Aber ich schreibe dennoch mal aus einem anderen Grund. Bei deinem Nick fällt mir auf, das ein schreibfreudiger Stammposter namens "Christoph Schnauß" seit einem halben Jahr nichts mehr schreibt, weiss Jemand warum?

    Paul

    1. Moin!

      keine Ahnung ob das Forum jetzt hier ein Scriptarchiv zulässt, ich fände es nicht verkehrt.

      Ich halte es für eine schlechte Idee. Das Archiv ist riesig und nicht so wahnsinnig gut durchsuchbar - jedenfalls im Vergleich zu viel besser geeigneteren Orten wie z.B. den Artikeln.

      Meinen Senf kann ich allerdings nicht dazugeben, weil meine JS-Schnipsel dir wohl zu trivial erscheinen würden, wenn ich deine proffesionellen Dinger sehe.

      Aber ich schreibe dennoch mal aus einem anderen Grund. Bei deinem Nick fällt mir auf, das ein schreibfreudiger Stammposter namens "Christoph Schnauß" seit einem halben Jahr nichts mehr schreibt, weiss Jemand warum?

      Nein, keiner weiß das. Denk dir einfach irgendeinen der vielen möglichen Gründe dafür: Keine Lust, keine Zeit, kein Internet, keine Möglichkeit mehr weil verstorben etc...

      - Sven Rautenberg

      1. Moin.

        keine Ahnung ob das Forum jetzt hier ein Scriptarchiv zulässt, ich fände es nicht verkehrt.

        Ich halte es für eine schlechte Idee. Das Archiv ist riesig und nicht so wahnsinnig gut durchsuchbar - jedenfalls im Vergleich zu viel besser geeigneteren Orten wie z.B. den Artikeln.

        Aber das Forum ist eine gute Anlaufstelle, um Ideen für einen eventuellen Artikel zu sammeln (das soll jetzt noch keine Zusage sein, aber wer weiß - ich spiele derzeit mit dem Gedanken, etwas über Maps in JavaScript zu schreiben - eine englische Version gibt es bereits).

        Christoph

        1. PS: Gibt es eigentlich Pläne, die SELFHTML-Artikel (eventuell zur Veröffentlichung von SELFHTML9) neu zu organisieren?

          Falls sich die Zahl der JavaScript-Artikel weiter erhöht, ist eine reine Auflistung nach Erscheinungsdatum nicht wirklich benutzerfreundlich...

          Christoph

          1. Moin!

            PS: Gibt es eigentlich Pläne, die SELFHTML-Artikel (eventuell zur Veröffentlichung von SELFHTML9) neu zu organisieren?

            Falls sich die Zahl der JavaScript-Artikel weiter erhöht, ist eine reine Auflistung nach Erscheinungsdatum nicht wirklich benutzerfreundlich...

            Vorschläge? Nicht, dass ich irgendwas versprechen würde ;) - aber konkrete Verbesserungsvorschläge helfen meist mehr, als nur "macht das doch mal 'anders'". :)

            - Sven Rautenberg

            1. Moin.

              Falls sich die Zahl der JavaScript-Artikel weiter erhöht, ist eine reine Auflistung nach Erscheinungsdatum nicht wirklich benutzerfreundlich...

              Vorschläge? Nicht, dass ich irgendwas versprechen würde ;) - aber konkrete Verbesserungsvorschläge helfen meist mehr, als nur "macht das doch mal 'anders'". :)

              Solange die Zahl der Artikel nicht überhand nimmt, würde ich alle auf einer Seite belassen, aber weitere Kategorien per Überschriften hinzufügen.

              Am Anfang des Dokuments sollte eine (ebenfalls in Kategorien unterteilte) Link-Liste zu den entsprechenden Detaileinträgen stehen.

              Eine konkrete Kategorisierung der JavaScript-Artikel erweist sich auf Grund der Diversität der Artikel als nicht einfach. Der folgende Vorschlag hat daher eher den Charakter eines 'proof-of-concept':

              • Sprache
                    Objekt-Handling in JavaScript
                    Objektabfragen und Fallunterscheidungen in JavaScript

              • Tabellen
                    Eigenes table-Objekt in JavaScript
                    Datensatzauswahl aus Tabelle mit Fullrowselect
                    Tabellen dynamisch sortieren
                    Übergroße Tabellen in koordiniert scrollenden Frames

              • Frames & Fenster
                    Datei dynamisch in Frameset laden
                    Fenster- und Frameszugriff
                    "Auflösungsweiche": Weiterleitung in Abhängigkeit der Fenstergröße

              • Formulare
                    Formulare: Text an Cursorposition einfügen
                    E-Mail-Syntax überprüfen
                    Formularauswertung

              • Algorithmen & Datenstrukturen
                    MD5-Hashing mit JavaScript
                    Datumsüberprüfung
                    Verkettete Auswahllisten
                    Gleichverteilte Zufallszahlen erzeugen

              • DHTML
                    Positionierung von Layern (DHTML)
                    Drag and Drop
                    Aufklappbare Menüs
                    Typographische Korrekturen
                    Text automatisch markieren

              • spezielle Anwendungen
                    Sitemap mit JavaScript und Layers
                    Auf Dateien mit JavaScript zugreifen
                    JavaScript Diagram Builder
                    Datenbanken mittels JavaScript nutzen
                    Javascript-Wertübergabe zwischen HTML-Dokumenten

              • Helferlein
                    HelferleinScript "Debug-Infos"
                    Bookmarklets
                    Komfortable Timer-Funktion

              • Bibliotheken
                    JavaScript Square Matrix Library

              • Lehrgänge
                    Fader-Framework - kleiner Lehrgang zum vernünftigen Schreiben eines JavaScripts
                    Organisation von JavaScripten

              Christoph

              1. Am Anfang des Dokuments sollte eine (ebenfalls in Kategorien unterteilte) Link-Liste zu den entsprechenden Detaileinträgen stehen.

                Wenn ich es mir recht überlege, sollte die Link-Liste eventuell doch nur Verweise zu den Kategorien enthalten - die Liste wird sonst zu lang, um wirklich nützlich zu sein...

                Christoph

              2. Moin!

                Falls sich die Zahl der JavaScript-Artikel weiter erhöht, ist eine reine Auflistung nach Erscheinungsdatum nicht wirklich benutzerfreundlich...

                Vorschläge? Nicht, dass ich irgendwas versprechen würde ;) - aber konkrete Verbesserungsvorschläge helfen meist mehr, als nur "macht das doch mal 'anders'". :)

                Solange die Zahl der Artikel nicht überhand nimmt, würde ich alle auf einer Seite belassen, aber weitere Kategorien per Überschriften hinzufügen.

                Tja, ein Gegenargument wäre halt: Das Erscheinungsdatum eines Artikels ist schon durchaus relevant zur Bewertung, wie sinnvoll der dargestellte Inhalt sich heutzutage noch anwenden läßt.

                Zweites Argument: Die Artikel lassen sich mit unserer Suchmaschine auch ganz rasch durchsuchen, wenn man das Feld links unter dem Logo ausfüllt. -- Das allerdings ist zurecht als absolut unintuitiv kritisierbar, und das Resultat auf der Ergebnisseite hat Probleme mit UTF-8 vs. ISO-8859-1 (jaja, so viele Dinge zu tun, so wenig Zeit...).

                Am Anfang des Dokuments sollte eine (ebenfalls in Kategorien unterteilte) Link-Liste zu den entsprechenden Detaileinträgen stehen.

                Eine konkrete Kategorisierung der JavaScript-Artikel erweist sich auf Grund der Diversität der Artikel als nicht einfach. Der folgende Vorschlag hat daher eher den Charakter eines 'proof-of-concept':

                Ganz ehrlich: Im Moment fühle ich nicht, dass sich jemand vom Redaktionsteam berufen fühlt und die Zeit aufbringen kann, in den Quelldateien und dem die Übersichten generierenden PHP-Skript derart einzugreifen, dass so eine alternative Übersicht entsteht.

                Allerdings heißt das ja nicht, dass deshalb niemand die Arbeit machen kann. Deshalb: Wer sich in das Problem reinfuchsen will, kriegt gerne die Quelldateien von mir als ZIP zum werkeln (PHP läuft als Kommandozeilenskript), kann seine Änderungen zurückschicken, und ich check' kurz durch, ob das auch alles auf dem Server funktioniert. Bei Interesse: Mail an svenr@selfhtml.org.

                - Sven Rautenberg

            2. Hi,

              Falls sich die Zahl der JavaScript-Artikel weiter erhöht, ist eine reine Auflistung nach Erscheinungsdatum nicht wirklich benutzerfreundlich...

              Vorschläge?

              Tagging :-)

              SELFHTML-9.0-ZweiPunktNull.

              MfG ChrisB

              --
              „This is the author's opinion, not necessarily that of Starbucks.“
            3. Hallo,

              Vorschläge?

              Die Einträge baumartig sortieren

              mfg, Flo

              --
              sh:) fo:| ch:? rl:( br:^ n4:| ie:{ mo:| va:} de:> zu:} fl:{ ss:) ls:< js:|
      2. Hi Sven,

        Aber ich schreibe dennoch mal aus einem anderen Grund. Bei deinem Nick fällt mir auf, das ein schreibfreudiger Stammposter namens "Christoph Schnauß" seit einem halben Jahr nichts mehr schreibt, weiss Jemand warum?

        Nein, keiner weiß das. Denk dir einfach irgendeinen der vielen möglichen Gründe dafür: Keine Lust, keine Zeit, kein Internet, keine Möglichkeit mehr weil verstorben etc...

        brrrrr, was ist das denn? Ich muss zugeben, das meine Frage nicht unbegründet kommt, ich hatte den Eindruck bei diversen Postings von Christoph einen leisen Hilferuf nach Aufmerksamkeit zu vernehmen, und dacht schon sowas kann leicht suizidgefärdet gelten. Falls ich micht irre und du liest das Christoph, nichts für ungut, ist ja nur Theorie.

        Aber das von euch keiner etwas weiss und auch offensichtlich nicht interessiert, verstehe ich nicht. Ihr unternehmt Sachen zusammen(Selftreffen) kennt euch schon jahrelang und dann interessiert euch sowas nicht besonders?

        Paul

        1. Moin,

          Aber das von euch keiner etwas weiss und auch offensichtlich nicht interessiert, verstehe ich nicht. Ihr unternehmt Sachen zusammen(Selftreffen) kennt euch schon jahrelang und dann interessiert euch sowas nicht besonders?

          Christophs hat eine sehr eigene Art, zu sein. Das macht es sicher nicht leicht, dauerhaft mit ihm "auf einer Welle" zu sein. Ich sage das ganz wertfrei; ich bin nie mit ihm "zusammengerasselt".

          Er hat übrigens einen Telefonbucheintrag.

          Grüße

          Swen

          1. Hi,

            Er hat übrigens einen Telefonbucheintrag.

            ja nur stand ich nie, im Gegensatz zu vielen anderen hier, im Kontakt zu Ihm. Aber wenn es kein anderer versucht, habe ich angerufen und es kam nur der AB. Ich habe drauf gesprochen er möchte doch mal bitte kurz etwas dazu schreiben. Bin gespannt.

            Paul

      3. Hi,

        Nein, keiner weiß das. Denk dir einfach irgendeinen der vielen möglichen Gründe dafür: Keine Lust, keine Zeit, kein Internet, keine Möglichkeit mehr weil verstorben etc...

        noch viel wahrscheinlicher: weil bei der Herstellung von Hollunderwein oder bei dessen artgerechter Vernichtung ;-)

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        O o ostern ...
        Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
        1. noch viel wahrscheinlicher: weil bei der Herstellung von Hollunderwein

          blausäurevergiftung? :p

  3. [latex]Mae  govannen![/latex]

    Diejenigen von euch, die sich seit längerem mit JavaScript herumschlagen mussten, habe sich mit der Zeit eventuell eine eigene Bibliothek von Skripten zugelegt.

    Ich würde gerne sehen, was sich bei anderen so angesammelt hat. Dabei sollten die Skripte

    Ich fange trivial an:

    Aufgrund der fehlerhaften Arbeitsweise von typeof nutze ich folgende Funktionen:

    function isObject(o) {  
      return (typeof o === 'object' && !(o instanceof Array) && o !== null);  
    }  
    function isArray(a) {  
      return (typeof a === 'object' && a instanceof Array);  
    }
    

    Dann eine Array-Mischfunktion hier aus dem Forum
    Array shuffle

    Funktionen, um events hinzuzufügen / entfernen (glaube von molily im forum gepostet, leicht angepasst; habe leider keinen Thread-Verweis gespeichert)

    function addEvent(obj, ev_type, fn) {  
      if (!obj || typeof ev_type !== "string" || typeof fn !== "function") {  
        return;  
      }  
      if (obj.addEventListener) {  
        obj.addEventListener(ev_type, fn, false);  
      }  
      else if (obj.attachEvent) {  
        obj.attachEvent('on' + ev_type, function() {  
          return fn.call(obj, window.event);  
        });  
      }  
    }  
    function removeEvent(obj, ev_type, fn) {  
      if (!obj || typeof ev_type !== "string" || typeof fn !== "function") {  
        return;  
      }  
      if (obj.removeEventListener) {  
        obj.removeEventListener(ev_type, fn, false);  
      }  
      else if (obj.detachEvent) {  
        obj.detachEvent('on' + ev_type, obj[ev_type + fn]);  
        obj[ev_type + fn] = null;  
      }  
    }
    

    Ladefunktion, die eine Funktion auszuführt, sobald das Dokument verfügbar ist oder auf window.onload zurückfällt

    function ondomcontent(func) {  
      /* Inspiriert von Dean Edwards/Matthias Miller/John Resig  
        http://dean.edwards.name/weblog/2006/06/again/#comment5338 */  
      var wol = window.onload;  
      /* Mozilla/Opera/... */  
      if (document.addEventListener) {  
        document.addEventListener("DOMContentLoaded", func, false);  
      }  
      /* Internet Explorer */  
      /*@cc_on @*/  
      if (/*@_win32 !== @*/false) {  
        document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");  
        var script = document.getElementById("__ie_onload");  
        script.onreadystatechange = function () {  
          if (this.readyState === "complete") {  
            func(); // call the onload handler  
          }  
        };  
      }  
      /* Safari */  
      if (/WebKit/i.test(navigator.userAgent)) { /* sniff WebKit */  
        wk_timer = setInterval(function () {  
          if (/loaded|complete/.test(document.readyState)) {  
            func(); /* call the onload handler */  
          }  
        }, 10);  
      }  
      /* for other browsers */  
      if (typeof wol == "function") {  
        window.onload = function() {  
          wol();  
          func();  
        }  
      }  
      else {  
        window.onload = func;  
      }  
    }
    

    Inhalt des Value-Attributes ermitteln

    /** getElementValue(el)  
    * Internet-Explorer gibt z.B. bei Buttons nicht den Wert des Value-Attributes zurück, wenn das  
    * Button-Element einen Inhalt hat. In diesem Fall wird versucht, über eine RegExp den Inhalt des  
    * Value-Attributes aus outerHTML zu ermitteln.  
    * @param  object  el  Referenz auf das Element, dessen Value-Wert ermittelt werden soll  
    * @return mixed       Wert des Value-Attributes oder bei Mißerfolg der ursprüngliche Wert  
    */  
    function getElementValue(el) {  
      if (el && el.value) {  
        if (el.value == el.innerHTML) {  
          var v = el.outerHTML.match(/value=\"(.+?)\"/i);  
          if (v && v[1]) return v[1];  
        }  
        return el.value;  
      }  
      return null;  
    }
    

    Kai

    --
    Ash nazg durbatulûk, ash nazg gimbatul,ash nazg thrakatulûk, agh burzum-ishi krimpatul
    selfcode sh:( fo:| ch:? rl:( br:< n4:# ie:{ mo:| va:) js:) de:> zu:) fl:( ss:| ls:?
    1. Aufgrund der fehlerhaften Arbeitsweise von typeof nutze ich folgende Funktionen:

      function isObject(o) {

      return (typeof o === 'object' && !(o instanceof Array) && o !== null);
      }
      function isArray(a) {
        return (typeof a === 'object' && a instanceof Array);
      }

        
      Warum ist das `typeof a` in `isArray()` notwendig? Meiner Meinung nach könnte man auch `typeof o === 'object' && o !== null` zu `o instanceof Object` zusammenfassen.  
        
      
      > Funktionen, um events hinzuzufügen / entfernen (glaube von molily im forum gepostet, leicht angepasst; habe leider keinen Thread-Verweis gespeichert)  
      > [...]  
        
      Habe ich auch (fast genauso) im Einsatz als Alternative zur `capture()`-Funktion. Diese ist vom Performance-Standpunkt aus ein Alptraum, aber einfach zu praktisch, um darauf zu verzichten. Statt auf das Laden des DOM-Baums zu warten, passende Elemente zu suchen und jedem einzeln Ereignis-Handler hinzuzufügen, erlaubt es `capture()`, eine kleine Testfunktion zu schreiben und den Handler einmalig global bekanntzumachen.  
        
      
      > Ladefunktion, die eine Funktion auszuführt, sobald das Dokument verfügbar ist oder auf window.onload zurückfällt  
      > [...]  
        
      Siehe `onready()`. Ich habe auch eine Version, die zunächst versucht, ein 'DOMContentLoaded' Ereignis zu setzen und im IE auf 'onreadystatechange' zurückgreift. Das garantiert, dass die Funktionen /vor/ allen 'onload'-Handlern ausgeführt werden. In der Praxis war das aber nicht wirklich nötig, daher die verkürzte Variante.  
        
      
      > Inhalt des Value-Attributes ermitteln  
      > [...]  
        
      Über diese Problematik bin ich bisher noch nicht gestolpert. Gut zu wissen!  
        
      Christoph
      
      1. [latex]Mae  govannen![/latex]

        function isObject(o) {

        return (typeof o === 'object' && !(o instanceof Array) && o !== null);
        }
        function isArray(a) {
          return (typeof a === 'object' && a instanceof Array);
        }

        
        >   
        > Warum ist das `typeof a` in `isArray()` notwendig?  
          
        Nicht. Kommt, weil ich die Objekt-Funktion "ge-c&p't" habe und nur den hinteren Bereich angepasst habe :(  
          
        
        > Meiner Meinung nach könnte man auch `typeof o === 'object' && o !== null` zu `o instanceof Object` zusammenfassen.  
          
        Prinzipiell schon, aber:  
          
        ~~~javascript
        var c = {  
         a: 2,  
         b: 3  
        }  
          
        function T1() {  
         this.a = 4;  
        }  
          
        b = new T1()  
          
        alert( c instanceof Object)  
        alert( b instanceof Object)  
        alert( window instanceof Object)  
        alert(isObject(c))  
        alert(isObject(b))  
        alert(isObject(window))
        ~~~ ergibt im IE6 true true false true true true , im FF/Opera 6 \* true  
          
          
        Cü,  
          
        Kai
        
        -- 
        Ash nazg durbatulûk, ash nazg gimbatul,ash nazg thrakatulûk, agh burzum-ishi krimpatul  
          
        selfcode sh:( fo:| ch:? rl:( br:< n4:# ie:{ mo:| va:) js:) de:> zu:) fl:( ss:| ls:?  
        
        
        1. Moin.

            
          
          > alert( c instanceof Object)  
          > alert( b instanceof Object)  
          > alert( window instanceof Object)  
          > alert(isObject(c))  
          > alert(isObject(b))  
          > alert(isObject(window))
          
          

          ergibt im IE6 true true false true true true , im FF/Opera 6 * true

          Sicher?

          javascript:void(alert((typeof window) + ' ' + (window instanceof Object)))

          in der Adresszeile gibt in meinem FF3.0.5 'object false'...

          Christoph

          PS: Was der typeof des Host-Objekts ist, ist übrigens 'implementation-dependent'

          1. [latex]Mae  govannen![/latex]

            Sicher?

            javascript:void(alert((typeof window) + ' ' + (window instanceof Object)))

            in der Adresszeile gibt in meinem FF3.0.5 'object false'...

            Im FF 2.0.0.20 'object true'

            Cü,

            Kai

            --
            Ash nazg durbatulûk, ash nazg gimbatul,ash nazg thrakatulûk, agh burzum-ishi krimpatul
            selfcode sh:( fo:| ch:? rl:( br:< n4:# ie:{ mo:| va:) js:) de:> zu:) fl:( ss:| ls:?
          2. Moin.

            Dass window instanceof Object === false scheint ein Bug zu sein, denn window.\_\_proto\_\_ instanceof Object === true.

            Genauer:

            alert(window.\_\_proto\_\_) ergibt '[xpconnect wrapped native prototype]'
            alert(window.\_\_proto\_\_.\_\_proto\_\_) ergibt '[object Global Scope Polluter]'
            alert(window.\_\_proto\_\_.\_\_proto\_\_.\_\_proto\_\_) ergibt '[object Object]'

            Und window.\_\_proto\_\_.\_\_proto\_\_.\_\_proto\_\_ === Object.prototype ist true. Also ist Object.prototype Teil der [[Prototype]]-Kette von window.

            Blöder Firefox ;)

            Christoph

    2. [latex]Mae  govannen![/latex]

      Dann eine Array-Mischfunktion hier aus dem Forum
      Array shuffle

      … die mich gerade _extrem_ geärgert hat, da sie keine Referenz auf das Array zurückgibt. Aber bis ich mal auf die Idee gekommen bin, daß es an shuffle liegt und nicht an meinem Code! Wenn man etwas voraussetzt, ist man manchmal blind.  *koppschüttel*

      function getRandoms(a, num) {  
         // hier ggf. Validitätsprüfung der Parameter  
         return a.shuffle().slice(0,num);  
      }
      

      funktioniert so natürlich nicht.

      ein einfaches return this; am Ende der shuffle-Funktion eingefügt und schon geht's

      Cü,

      Kai

      --
      Ash nazg durbatulûk, ash nazg gimbatul,ash nazg thrakatulûk, agh burzum-ishi krimpatul
      selfcode sh:( fo:| ch:? rl:( br:< n4:# ie:{ mo:| va:) js:) de:> zu:) fl:( ss:| ls:?
      1. Hallo Kai345,

        Dann eine Array-Mischfunktion hier aus dem Forum
        Array shuffle

        … die mich gerade _extrem_ geärgert hat, da sie keine Referenz auf das Array zurückgibt. ...

        so ist das, wenn man Codeschnipsel aus dem Internet benutzt, ohne sie zu verstehen. Ein Blick in den Quellcode hätte dir gezeigt, dass da nichts "returnt" wird. Warum auch, die Funktion wirkt auf das Array.

        Gruß, Jürgen

        1. Lieber JürgenB,

          Array shuffle

          dass da nichts "returnt" wird. Warum auch, die Funktion wirkt auf das Array.

          ist es nicht bei anderen (nativen) Array-Funktionen so, dass sie ein Array als Rückgabewert liefern? Insofern wäre es nur recht und billig, eine entsprechende Rückgabe zu erwarten. Von daher hätte ich auch ein return this erwartet oder dann selbst ergänzt.

          Wieso genügt es Dir in diesem Falle, gerade keinen Rückgabewert zu erhalten? Wie verwendest Du denn diese Funktion?

          Liebe Grüße,

          Felix Riesterer.

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

            Wieso genügt es Dir in diesem Falle, gerade keinen Rückgabewert zu erhalten? Wie verwendest Du denn diese Funktion?

            Die verlinkte shuffle-Funktion vertauscht die Elemente des als this zur Verfügung gestellten Arrays, erzeugt also keinerlei neue Objekte. Die Rückgabe irgendeinen Werts ist damit nicht erforderlich.

            Der einzige Grund, warum ein return this sinnvoll sein könnte, ist, die Verkettung von Methodenaufrufen zu ermöglichen...

            Christoph

          2. [latex]Mae  govannen![/latex]

            ist es nicht bei anderen (nativen) Array-Funktionen so, dass sie ein Array als Rückgabewert liefern? Insofern wäre es nur recht und billig, eine entsprechende Rückgabe zu erwarten. Von daher hätte ich auch ein return this erwartet oder dann selbst ergänzt.

            Leider nicht alle Funktionen. Am ähnlichsten zu shuffle() wäre wohl reverse(), dort gibt es auch keinen Rückgabewert. Man muß dort auch [1,2,3,4,5].reverse(); schreiben und nicht var newArray = [1,2,3,4,5].reverse(); Insofern ist es schon verständlich, die Funktion ohne Rückgabewert zu schreiben. Die Verwirrung kam durch etwas anderes, siehe anderer Beitrag meinerseits

            Cü,

            Kai

            --
            Ash nazg durbatulûk, ash nazg gimbatul,ash nazg thrakatulûk, agh burzum-ishi krimpatul
            selfcode sh:( fo:| ch:? rl:( br:< n4:# ie:{ mo:| va:) js:) de:> zu:) fl:( ss:| ls:?
          3. Hallo Felix,

            Wieso genügt es Dir in diesem Falle, gerade keinen Rückgabewert zu erhalten? Wie verwendest Du denn diese Funktion?

            ich mische die Arrays (in einem Spiel) sehr oft und spare mir so das Anlegen von immer neuen Arrays. Das Originalarray benötige ich nicht. Das "oberste" Entwicklungsziel war neben der Funktionalität die Geschwindigkeit.

            Gruß, Jürgen

        2. [latex]Mae  govannen![/latex]

          so ist das, wenn man Codeschnipsel aus dem Internet benutzt, ohne sie zu verstehen.

          Wie nett. Aber es wäre natürlich viel zu einfach gewesen, sich erst einmal über den konkreten Hintergrund zu informieren, bevor man Anderen etwas unterstellt.

          Ein Blick in den Quellcode hätte dir gezeigt, dass da nichts "returnt" wird.

          Und die shuffle-Funktion, die ich früher benutzt habe, tut genau dieses. Insofern bestand eine implizite, wenn auch falsche  Erwartungshaltung. Natürlich hätte ich nachsehen sollen, da ich aber aus dieser Gewohnheit fest davon überzeugt war, daß eine Rückgabe stattfinden wird, habe ich es nicht getan. Kein Grund, beleidigend zu werden.

          Warum auch, die Funktion wirkt auf das Array.

          Ach.

          Kai

          --
          Ash nazg durbatulûk, ash nazg gimbatul,ash nazg thrakatulûk, agh burzum-ishi krimpatul
          selfcode sh:( fo:| ch:? rl:( br:< n4:# ie:{ mo:| va:) js:) de:> zu:) fl:( ss:| ls:?
    3. Aufgrund der fehlerhaften Arbeitsweise von typeof nutze ich folgende Funktionen:

      function isObject(o) {

      return (typeof o === 'object' && !(o instanceof Array) && o !== null);
      }
      function isArray(a) {
        return (typeof a === 'object' && a instanceof Array);
      }

        
      Bei diesen Funktionen solltest du aber bedenken, dass sie nicht funktionieren, wenn die Arrays aus anderen Frames, Tabs oder Fenstern stammen, `a instanceof Array`{:.language-javascript} ist dann `false`{:.language-javascript}.
      
      -- 
      Reden ist Silber, Schweigen ist Gold, meine Ausführungen sind Platin.  
        
      Self-Code: sh:( ch:? rl:( br:> n4:( ie:{ mo:) va:) de:> zu:} fl:| ss:| ls:~ js:| 
      
  4. Moin.

    Die jeweils aktuelle Version der JavaScript-Schnipsel gibt es jetzt als Mercurial-Repository.

    Christoph

    1. Moin.

      Es gibt jetzt auch die Möglichkeit, sich aus den Schnipsels komfortabel eine eigene Bibliothek zusammenzustückeln.

      Der Link zeigt auf die derzeit aktuelle Version. Für neuere Versionen muss der Weg über die Portalseite genommen werden (files->libmaker.html->raw).

      Christoph

  5. gruss Christoph, hallo Kai,

    ... Und jetzt ihr ;)

    ich poste mal nur die fuer mich zur zeit immer noch praxisrelevanten eigenloesungen:

    unverzichtbar:

    * [jsApi.Array.mozExtensions.revisioned.dev-03.js]
      * [jsApi.Array.mozExtensions.revisioned.dev-04.js]

    • Array.prototype.indexOf            basierend auf der aelteren [jsApi.Array.mozExtensions.dev.js]

    • Array.prototype.lastIndexOf

    • Array.prototype.contains

    • Array.prototype.forEach

    • Array.prototype.every

    • Array.prototype.some

    • Array.prototype.map

    • Array.prototype.filter

    • Array.prototype.reduce

    • Array.prototype.reduceRight

    • Array.prototype.defragment

    • Array.prototype.getDefragmented

    • Array.prototype.normalize          basierend auf der aelteren [jsApi.Array.normalize.dev.js]

    • Array.prototype.getNormalized

    • Array.prototype.remove

    • Array.prototype.indexOfFilter

    • Array.prototype.lastIndexOfFilter

    • Array.indexOf                      basierend auf der aelteren [jsApi.Array.mozGenerics.dev.js]

    • Array.lastIndexOf

    • Array.contains

    • Array.forEach

    • Array.every

    • Array.some

    • Array.map

    • Array.filter

    • Array.reduce

    • Array.reduceRight

    • Array.getDefragmented

    • Array.getNormalized

    • Array.indexOfFilter

    • Array.lastIndexOfFilter

    ebenfalls unverzichtbar:

    * [jsApi.EventDispatcher.new.js]
      * extrahiert aus [jsApi.EventDispatcher.dev.new.js], der wiederum auf
      * dem aelteren [jsApi.EventDispatcher.dev.js] aufsetzt.

    • [[EventDispatcher]]-Singleton

    ... ein immer noch ganz passabler code-steinbruch:

    * [jsApi.Object.typeDetection.new.dev.js].

    • isUndefined

    • isNull

    • isValue

    • isObject

    • isNative

    • isAlien

    • isBoolean

    • isNumber

    • isString

    • isBooleanValue

    • isNumberValue

    • isStringValue

    • isBooleanObject

    • isNumberObject

    • isStringObject

    • isInteger

    • isFraction

    • isError

    • isEvalError ...

    • ...

    • isURIError

    • isDate

    • isRegExp

    • isFunction

    • isArray

    • isArrayLike

    • isObjectObject

    • isConstructedObject

    • isEmpty

    • ...

    • Object.prototype.isEmpty

    ... ein bischen spielkram:

    * [jsApi.Number.times.dev.js]

    • Number.prototype.times
    • Number.times
    • String.prototype.times

    * [jsApi.Boolean.ifTrue.ifFalse.dev.js]

    • Boolean.prototype.ifTrue
    • Boolean.prototype.ifFalse

    fuer alles andere (Node/Element, DOM, DOM-Events) greife ich mittlerweile auf
    richtig professionell entwickelte/getestete bibliotheken und frameworks zurueck.

    so long - peterS. - pseliger@gmx.net

    --
    »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
    Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
    ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
    1. * [jsApi.Boolean.ifTrue.ifFalse.dev.js]

      • Boolean.prototype.ifTrue
      • Boolean.prototype.ifFalse

      Zu diesen beiden Methoden hätte ich direkt einen Verbesserungsvorschlag: Füge ihnen einen weiteren optionalen Parameter hinzu, der ein Objekt beinhalten kann, in dessen Kontext die übergebene Funktion ausgeführt wird. Also so:

      (function (fct, obj){  
      /* ... */  
      fct.call(obj);  
      /* ... */}
      
      --
      Reden ist Silber, Schweigen ist Gold, meine Ausführungen sind Platin.
      Self-Code: sh:( ch:? rl:( br:> n4:( ie:{ mo:) va:) de:> zu:} fl:| ss:| ls:~ js:|
      1. gruss "God's Boss",

        • Boolean.prototype.ifTrue
        • Boolean.prototype.ifFalse

        hey, das war doch nur ein 5-minuten spass ...

        ...
        Zu diesen beiden Methoden hätte ich direkt einen Verbesserungsvorschlag:
        Füge ihnen einen weiteren optionalen Parameter hinzu, der ein Objekt
        beinhalten kann, in dessen Kontext die übergebene Funktion ausgeführt wird.
        ...

        na gut, Du hast ja recht. es liegt tatsaechlich auf der hand, dies zu tun.

        done:

        /*  
          [link:http://de.wikipedia.org/wiki/Smalltalk-80_(Programmiersprache)#IF-Anweisung]  
        */  
          
          
        [link:http://www.pseliger.de/jsExtendedApi/jsApi.Boolean.ifTrue.ifFalse.dev.js@title=Boolean.prototype.ifTrue] = (function (fct, target/*optional:[object|function]*/) { // [caseTrue], [ifTrue], [ifTrueDo]  
          
          var isTrue = this.valueOf();  
          if (isTrue && (typeof fct == "function")) {  
          
            fct.call(((typeof target == "undefined") || ((typeof target == "obj") && !target)) ? (null) : (target));  
          }  
          return isTrue;  
        });  
        Boolean.prototype.ifFalse = (function (fct, target/*optional:[object|function]*/) { // [caseFalse], [ifFalse], [ifFalseDo]  
          
          var isTrue = this.valueOf();  
          if (!isTrue && (typeof fct == "function")) {  
          
            fct.call(((typeof target == "undefined") || ((typeof target == "obj") && !target)) ? (null) : (target));  
          }  
          return isTrue;  
        });  
          
          
        /*  
          [link:http://jconsole.com]  
        */  
        (7 < 6).ifTrue(function () {  
          print(" ... is true.");  
        }).ifFalse(function () {  
          print(" ... is false.");  
        });  
          
        (7 > 6).ifTrue(function () {  
          print(" ... is true.");  
        }).ifFalse(function () {  
          print(" ... is false.");  
        });
        

        danke und so long - peterS. - pseliger@gmx.net

        --
        »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
        Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
        ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
        1. hallo again Timo,

          na gut, Du hast ja recht. es liegt tatsaechlich auf der hand, dies zu tun.

          ... wenn man dann aber schon so weit ist, faellt mir auf und ein, das der
          ganze kram konsequenterweise auch gleich mit einem vezicht auf benutzung
          von »if ( .. ) { ... } else { ... } « umgesetzt werden sollte.

          done:

          also nochmal:

          /*  
            [link:http://de.wikipedia.org/wiki/Smalltalk-80_(Programmiersprache)#IF-Anweisung]  
          */  
          [link:http://www.pseliger.de/jsExtendedApi/jsApi.Boolean.ifTrue.ifFalse.dev.js@title=Boolean.prototype.ifTrue] = (function (fct, target/*optional:[object|function]*/) { // [caseTrue], [ifTrue], [ifTrueDo]  
            
            return (((this.valueOf() && (typeof fct == "function")) ? (function () {fct.call(((typeof target == "undefined") || ((typeof target == "obj") && !target)) ? (null) : (target)); return true;}) : (function () {return false;}))());  
          });  
          Boolean.prototype.ifFalse = (function (fct, target/*optional:[object|function]*/) { // [caseFalse], [ifFalse], [ifFalseDo]  
            
            return (((!this.valueOf() && (typeof fct == "function")) ? (function () {fct.call(((typeof target == "undefined") || ((typeof target == "obj") && !target)) ? (null) : (target)); return true;}) : (function () {return false;}))());  
          });  
            
            
          /*  
            [link:http://jconsole.com]  
          */  
          (7 < 6).ifTrue(function () {  
            print(" ... is true.");  
          }).ifFalse(function () {  
            print(" ... is false.");  
          });  
            
          (7 > 6).ifTrue(function () {  
            print(" ... is true.");  
          }).ifFalse(function () {  
            print(" ... is false.");  
          });
          

          so long - peterS. - pseliger@gmx.net

          --
          »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
          Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
          ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
    2. Moin.

      ... ein immer noch ganz passabler code-steinbruch:

      * [jsApi.Object.typeDetection.new.dev.js].

      Ziemlich beeindruckend, deine Typerkennung. Nach Lesen dieses Artikels habe ich mir auch eine eigene Version einer typeOf-Funktion zusammengeschustert:

        
          function typeOf(value) {  
              var type = typeof value;  
              if(type === 'object') {  
                  return value === null ? 'null' : Object.prototype.toString.call(value).  
                      match(arguments.callee.regex)[1];  
              }  
              else return type;  
          }  
        
          typeOf.regex = /^\[(.*)\]$/;  
      
      

      Diese Funktion sollte es unter anderem ermöglichen, Arrays auch über Fenstergrenzen hinweg zu erkennen (der instanceof-Operator versagt hier).

      Der Rückgabewert ist bei nicht-Objekten identisch mit typeof, bei Objekten setzt er sich zusammen aus 'object ' gefolgt von der [[Class]]-Eigenschaft ('Array', 'String', 'Number', ...).

      null wird extra behandelt und liefert 'null'.

      Christoph

  6. Hi,

    try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
      try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
      try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}

    Alles überflüssig.

    try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}

    Das ist der einzig notwendige Aufruf.

    MS bleibt i.d.R. abwärtskompatibel, und neuere IEs brauche das ja eh nicht mehr (es wird sich also auch in Zukunft nicht mehr ändern).

    Gruß, Cybaer

    --
    Man muß viel gelernt haben, um über das, was man nicht weiß, fragen zu können.
    (Jean-Jacques Rousseau, Philosoph u. Schriftsteller)
    1. Moin.

      try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}

      Das ist der einzig notwendige Aufruf.

      Ist das sicher? Ich meine, dass mit dieser Version einige IE-Versionen Probleme (mit synchronen Anfragen, war es glaube ich?) hatten.

      Vielleicht trügt mich da aber auch mein Gedächtnis...

      Christoph

      1. Hi,

        Ist das sicher?

        Was ist beim IE schon "sicher"? >;->

        Ich meine, dass mit dieser Version einige IE-Versionen Probleme (mit synchronen Anfragen, war es glaube ich?) hatten.

        Ist mir nicht bekannt. Aber wenn Du das verifizieren könntest, dann schrei ruhig nochmal "Hallo!". ;-)

        Gruß, Cybaer

        --
        Man muß viel gelernt haben, um über das, was man nicht weiß, fragen zu können.
        (Jean-Jacques Rousseau, Philosoph u. Schriftsteller)