HowTo: Erster Schritt zur jQuery Plugin-Entwicklung

image

Wer mit Javascript irgendwelche tollen Sachen machen möchte, kann dies natürlich alles selbst schreiben oder er nimmt sich ein vorgefertiges Framework und fügt ein paar Features hinzu. In diesem Blogpost will ich nur sehr kurz mal den Einstieg in die jQuery Plugin Entwicklung zeigen.

Weiterlesen »

HowTo: Eingabenvalidierung in ASP.NET MVC

image Eingabenvalidierung ist ein sehr wichtiger Punkt in der Anwendungsentwicklung. Man sollte niemals blind User-Eingaben vertrauen. Neben “fehlerhaften” Eingaben, gibt es auch noch die böswilligen Eingaben. In diesem Blogposts geht es um dieses Thema und wie man das in ASP.NET MVC machen kann.

Weiterlesen »

jQuery… ein paar Links

Da ASP.NET AJAX und ASP.NET MVC (noch?) nicht so richtig gut zusammenpassen muss ganz klar eine andere Javascript Bibliothek und AJAX Framework her – jQuery hat es mir angetan.

Der Blogpost ist eher eine Zusammenfassung von den Links die ich in den letzten Rundablagen bereits nebenbei gebloggt hab.

Was gibt es denn sonst noch für Javascript-Bibliotheken?

Danny Douglass hat einen netten Vergleich zwischen jQuery, YUI, Prototype, Dojo, MooTools, Ext JS, und Script.aculo.us gemacht. Eine nette Auflistung der Merkmale findet man hier.

jQuery Beispiele und Tutorials?

Auf noupe.com gefunden:

Drag`n`Drop gibts auch:

Es gibt noch mehr tolle Beispiele (siehe links oben), eine aktuelle offline Dokumentation hab ich zwar noch nicht gefunden, aber für die Version 1.1.4 gibt es hier eine.

Jeder braucht Plugins… jQuery hat einige:

Auf noupe.com gefunden:

VS 2008 / ASP.NET Integration:

Wer noch mehr brauchbare Links kennt, einfach kurz melden :)

Noch mehr beeindruckende Javascript Spielerein

Nachdem Robert schon mal diesen Link gebloggt hat habe ich noch diese coolen Scripts gefunden:

60 More AJAX- and Javascript Solutions For Professional Coding

80+ AJAX-Solutions For Professional Coding

und noch eine Liste vieler nützliche Javascriptbibliotheken:

AJAX, DHTML and JavaScript Libraries

Beeindruckende Javascript Spielerein mit jQuery

Ich hab mich bisher von jQuery oder anderen Javascript Librarys weniger beeindrucken lassen. Script.aculo.us war mir ein Begriff, aber ich hab jetzt einen interessanten Post gefunden: 37 More Shocking jQuery Plugins

Zum Teil ziemlich schicke Sachen dabei – ich glaub diese Seite sollte ich mir mal näher anschauen: Learning jQuery

HowTo: Excel-Export via AJAX

Wir (d.h. Oliver und ich) haben bei einem Projekt die Anforderung gehabt, in einer sehr AJAX und Javascriptlastigen Anwendung ein Excel Export mit einzubauen.

Durch ein Postback oder durch Aufruf einer Webmethode etc. ist dies sehr einfach zu lösen, allerdings gab es ein Problem:

Die letztendliche Ergebnisliste wird über verschiedene Javascript Methoden befüllt, d.h. das momentan angezeigte (und in einem JSON Objekt befindliche) Ergebnis muss am besten direkt irgendwie übergeben werden.

Da die Lösung etwas "geschickt" ist (der Erfinder ist Oliver) Schritt für Schritt erklärt:

1. Grundsätzlicher Aufbau

image

2. Default.aspx vorbereiten

Die ASPX Seite (abgesehen von dem Javascript – welches gleich näher beschrieben wird) ist simpel:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript">
    // wird gleich gezeigt
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <button type="button" onclick="createXlsData()">Create XLS</button>
    </div>
    </form>
</body>
</html>

Zwischenbemerkung: Wie erstellt man eigentlich eine Excel List?

Excel kann auch HTML Tabellen "interpretieren" und entsprechend darstellen.

Das HTML drumherum muss man weg lassen, um eine einfache Tabelle zu erzeugen muss man Excel sowas übergeben:

<table>
  <tr>
     <td>Sample</td>
  </tr>
</table>

3. Im Javascript Tabelle vorbereiten: "createXlsData()"

In diesem Teil können wir nun auf unsere JSON Objekte zugreifen – ohne nochmal einen Webservice etc. zu befragen.

function createXlsData()
    {
    var data = "<table>";
            data += "<tr>";
                data += "<td>Test 1</td>";
                data += "<td>Test 2</td>";
             data += "</tr>"

    for(i=0; i < 10; i++)
    {
        var singleLine = "<tr>";
                singleLine += "<td> Test Data1: " + i + "</td>";
                singleLine += "<td> Test Data2: "  + i + "</td>";
        singleLine += "</tr>";
        data += singleLine;
    }
        data += "</table>";
    sendXlsData(data);
    }

4. Daten an Handler übermitteln und Handler aufrufen

Da der String für einen "GET" Request zu lang ist, muss er per "POST" an den Handler übermittelt werden . natürlich mit AJAX.

Problem: Wenn man dies per AJAX macht, sieht man nie dieses Fenster:

image

Lösung: Der Handler speichert die übergebenen Werte in der Session und das Javascript ruft expliziert nochmal den Handler aus, welcher die Daten aus der Session holt.

Hier der komplette Source-Code der Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript">
    var DataExchangeHttpRequest;

    function createXlsData()
    {
    var data = "<table>";
            data += "<tr>";
                data += "<td>Test 1</td>";
                data += "<td>Test 2</td>";
             data += "</tr>"

    for(i=0; i < 10; i++)
    {
        var singleLine = "<tr>";
                singleLine += "<td> Test Data1: " + i + "</td>";
                singleLine += "<td> Test Data2: "  + i + "</td>";
        singleLine += "</tr>";
        data += singleLine;
    }
        data += "</table>";
    sendXlsData(data);
    }

    function sendXlsData(data)
    {
    if (window.XMLHttpRequest) // Mozilla, Safari, Opera, IE7
        {
        DataExchangeHttpRequest = new XMLHttpRequest();
        }
    else if (window.ActiveXObject) // IE6, IE5
        {
        DataExchangeHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        }

    DataExchangeHttpRequest.onreadystatechange = openXlsPage;
    DataExchangeHttpRequest.open('POST', 'ExcelHandler.ashx', true);
    DataExchangeHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    DataExchangeHttpRequest.setRequestHeader('Content-Length',data.length);

    DataExchangeHttpRequest.send(data);
    }
    function openXlsPage()
    {
        if (DataExchangeHttpRequest.readyState == 4 && DataExchangeHttpRequest.status == 200)
        {
        window.open("ExcelHandler.ashx?openXls=true","xls");
        }
    }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <button type="button" onclick="createXlsData()">Create XLS</button>
    </div>
    </form>
</body>
</html>

5. Der ASHX Handler

<%@ WebHandler Language="C#" Class="ExcelHandler" %>

using System;
using System.Web;

public class ExcelHandler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{

    public void ProcessRequest(HttpContext context)
    {

        if (context.Request.Params["openXls"] == "true")
        {
            // display data
            if (context.Session["ExcelData"] != null)
            {
                context.Response.ContentType = "application/vnd.ms-excel";
                context.Response.ContentEncoding = System.Text.Encoding.Default;
                context.Response.Write(context.Session["ExcelData"]);
            }
            else
            {
                context.Response.Write("session empty");
            }
        }
        else
        {
            // save data in session
            context.Response.ContentType = "application/vnd.ms-excel";
            string data = "";
            using (System.IO.StreamReader reader = new System.IO.StreamReader(context.Request.InputStream))
            {
                data = reader.ReadToEnd();
            }

            context.Session.Add("ExcelData", data);
        }
    }
    public bool IsReusable {
        get {
            return true;
        }
    }

}

Durch den Content Type "application/vnd.ms-excel" wird diese Javascript-generierte Tabelle von Excel erkannt.

Schematische Darstellung

image

Als Nutzer sieht das dann so aus

Klicken:

image

Fenster öffnet sich:

image

Im Excel sieht das dann so aus:

image

Bei der momentanen Lösung kommt da allerdings am Anfang noch eine Warnung, dass eine ASHX versucht was an Excel zu schicken – das bekommt man sicherlich auch noch irgendwie raus.

Wo macht das Sinn?

Das ganze macht da Sinn, wo man mit viel Javascript und AJAX sich Daten z.B. in einem JSON Objekt gesammelt hat und diese nun auch an Excel exportieren möchte – was bei uns der Fall war. Wenn man natürlich die Daten aus einer DB holen kann, ist sowas natürlich über ein Postback oder wie auch immer "sauberer".

Das ganze gehört eindeutig in die Kategorie: Freakige Sachen ;)

[ Download Source ]

HowTo: Microsoft AJAX Client API nutzen

Bereits einmal in einer Wöchentlichen Rundablage erwähnt, möchte ich mich heute mal der AJAX Client API widmen. Die Client API wird oft kaum genutzt, obwohl manche kleinen Helferlein praktisch sind. Infos zu den ASP.NET AJAX Extensions (also der serverseitigen API gibt es z.B. hier in einem HowTo).

Was ist die ASP.NET AJAX Client API?

Die AJAX Client API ist entweder für ASP.NET Entwickler direkt in dem Download der ASP.NET AJAX Extensions (oder ASP.NET 3.5) enthalten oder auch als seperater Download zu bekommen. Die Client API kann auch in PHP, JSP, Ruby usw. eingesetzt werden, da es nur eine Javascript Bibliothek ist.

Ich werde mit den ASP.NET AJAX Extensions arbeiten, allerdings sind die clientseitigen Sachen später auch bei PHP und co. gültig.

Wie wird diese eingebunden?

Sobald man in ASP.NET den Scriptmanager mit einfügt, ist die Client API sofort mit eingebunden und wird mitgeladen:

image

(in PHP und co. muss die Installationsanleitung bei dem seperaten Download angesehen werden)

Ein Blick in die DOM verrät uns, was alles mit geladen wurde (und das ist nur ein Ausschnitt):

image

Was hat man nun davon?

Die Microsoft AJAX API bietet einige kleine Helferlein, welche einem das Javascript-Leben erleichtern können – das dabei aber natürlich immer ein gewisser “Respekt” dabei sein sollte, sollte für alle klar sein: Nur weil eine Bibliothek “verrückte” Sachen erlaubt, heisst das noch lange nicht, dass man diese nutzen muss.

Die kleinen Helferlein zeige ich mal kurz an 5 Beispielen:

1. Zugriff auf ein DOM Element

Der Zugriff erfolgt immer über “document.getElementById(…)” oder ähnlichem – die Microsoft AJAX API stellt dafür ein kleine Abkürzung bereit – den “$get Shortcut“. Das erleichtert immerhin die Tipparbeit ;)

2. Eventhandler dynamisch anhängen

Ein Element dynamisch per Javascript mit einem Event versehen ist etwas haarig, da der ID nicht alles mit macht und mir spontan allein 3 Wege einfallen wie man das “klassisch” lösen kann:

  • über innerHTML die Events “reinschreiben” (das versteht wenigstens auch der IE)
  • über setAttribute (geht beim IE manchmal nicht)
  • über die jeweiligen Eventeigenschaften direkt (wenn man den Syntax nicht direkt im Kopf hat, ist es etwas nervig)

Die Microsoft AJAX API erlaubt über den “$addHandler Shortcut” genau das. Leider kann man wohl leider keinen Parameter oder weiteren Kontext mitgeben.

Für dieses Thema empfehle ich diesen Blogbeitrag, da er auch einige andere Features zeigt, z.B. kann man über den “event” Parameter rausbekommen, welcher Knopf gedrückt wurde (Enter z.B.) oder wo die Mausposition etc. ist (Wie sowas mit normalen JS geht, wird hier erklärt.)

3. Strings verknüpfen

Einen String mit JS über das “+” zu erzeugen, wird dann schwierig, sobald Zahlen dirn vorkommen. Zahlen werden dann sofort addiert und erst danach an die nachfolgende Zeichenfolge drangeklebt. Das ist nicht immer den Effekt, den man sich wünscht.

Microsoft stellt hier eine “StringBuilder” Klasse zur Verfügung.

4. Umgang mit Arrays

In Zeiten von JSON etc. arbeitet man wieder viel auf der Clientseite und möchte angenommen jedes Element eines Arrays an eine spezielle Methode übergeben, damit dieser weiter verarbeitet werden kann. Im normalen JS muss man nun hier erst eine Schleife durchlaufen lassen etc.

Microsoft stellt hier eine “Array.forEach” Methode bereit, die genau dies macht. Die Methode gehört zu den Array Type Extensions, welcher noch andere Extensions angehören.
Dazu ist wahrscheinlich auch dieser Blogeintrag sehr interessant und empfehlenswert.

5. Datumsanzeige

Wie gerade erwähnt, hat Microsoft einige “Extensions” für normale JS “Typen” bereitgestellt, darunter auch einer für den “Date” Typ. Dieser hilft, Datumsformatierungen wesentlich einfacher vor zu nehmen, als in der klassischen Variante. Die “Microsoft” Variante ist aus den bekannten Java oder .NET entnommen und daher eigentlich nichts unbekanntes. Siehe dazu am besten den unteren Abschnitt von diesem Blogeintrag.

Mein Demoprojekt und den Source Code:

Die 5 Beispiele können live auch hier angesehen werden und habe ich im IE7 und Firefox 2 getestet. Da dies alles nur Javascript Code ist, findet ihr auch dort den Source Code.

Fazit:

Die Client API ist sehr interessant wenn man sich einmal eingearbeitet hat und stellt einige Erleichterungen bereit. Einen Blick ist sie auf alle Fälle wert und wenn man ohnehin die ASP.NET AJAX Server Funktionalitäten nutzt, kann man die vom Client doch auch mal mit einbauen.

Die komplette Client Reference findet ihr hier.

[ Demoanwendung + Sourcecode ]

HowTo: Javascript Mouse Over – Mousepositionen für Details

Der Effekt ist eigentlich wohl bekannt und wir bei vielen Javascript Bibliotheken angeboten: Mouse Over Effekte. So werden z.B. Details oder weitere Informationen nachgeladen, sobald man mit dem Mousecursor über dem Element ist.

Doch bei einer solch einfachen Funktion ist ein komplettes Javascript Framework wie mit Kanonen auf Spatzen zu schießen, daher nun ein kleines HowTo wie man das selber in 5 Minuten implementieren kann:

Schritt 1: Grundgerüst erstellen

<body> 

    <h1>Javascript Mouse Over</h1> 

    <div id="MouseOver" style="display: none;"></div> 

<p onmousemove="showMouseOver('Mouse Over Text... Test...', event)"
onmouseout="hideMouseOver()">[Mouse Over]</p> 

    <p>...</p> 

</body>

In unserem Body Element ist ein Div namens “MouseOver” definiert, in welchen später unsere Mouseover Text drin ist. Danach folgt etwas Beispieltext, in welchen ich bestimmte Wörter über Javascript mit unserem kleinen Javascript verknüpft hab (onmousemove = anzeigen des Textes, onmouseout = verstecken des MouseOver Divs).

Schritt 2: Style hinzufügen

Als Style haben wir nur unser MouseOver etwas gestaltet:

    <style type="text/css"> 

        #MouseOver 

        { 

        border: solid 1px black; 

        position: absolute; 

        background-color: #FFF; 

        } 

    </style>

Dabei ist eigentlich nur das “position: absolute” wichtig.

Schritt 3: Javascript hinzufügen

Jedes Tag kann über “showMouseOver” einen Text übergeben und das Schlüsselwort event um auf die Mausposition zuzugreifen (dies hatte ich bei diesem HowTo nicht berücksichtig – dort wird der Eventhandler programmatisch zugeordnet, was aber nicht notwenig ist). Bei onmouseout muss dieser Detailtext wieder ausgeblendet werden – über “hideMouseOver”.

  • Javascript Funktionen:
    • onmousemove=showMouseOver(”text”, event)
    • onmouseout=hideMouseOver()

Javascript Code:

function showMouseOver(text, event) 

    { 

     document.getElementById('MouseOver').innerHTML = text; 

     var topPixel = event.clientY + 10; 

     var leftPixel = event.clientX + 10; 

     document.getElementById('MouseOver').style.top = topPixel + "px"; 

     document.getElementById('MouseOver').style.left = leftPixel + "px"; 

     document.getElementById('MouseOver').style.display = "block"; 

    }
function hideMouseOver() 

    { 

     document.getElementById('MouseOver').innerHTML = ""; 

     document.getElementById('MouseOver').style.top = "0px"; 

     document.getElementById('MouseOver').style.left = "0px"; 

    document.getElementById('MouseOver').style.display = "none"; 

    }

Über das Schlüsselwort “event” kann auf die Mauspositionsdaten zugegriffen werden – über clientX und clientY wird dann unser MouseOver Div positioniert und über innerHTML mit dem jeweiligen Text befüllt. Dabei werden bei der Positionierung nochmal 10 Pixel zugerechnet, da es a) designtechnisch besser ist und b) sonst die “mouseout” Funktion aufgerufen wird.

Bei hideMouseOver wird das MouseOver Div “geleert” und wieder versteckt.

image

Diese Technik funktioniert im IE7 und Firefox2 ohne Probleme – andere Browser müssten auch keine Probleme bringen. Hoff ich ;)

Viel Spaß…

[ Download Source Code & Demoanwendung ]

HowTo: Javascript Event "onscroll" nutzen

Der Javascript Eventhandler “onscroll” wird oftmals vergessen, z.B. wird er auch bei Selfhtml nicht gelistet, allerdings ist dieses Event doch sehr nützlich.

So hat Microsoft bei seiner Live Bildersuche das onscroll Event genutzt um die Suchergebnisse dynamisch mit AJAX hinzuzufügen um so das typische “Seite 1, 2, 3, 4, 5, 6… 100″ (siehe Google Suche) Layout zu umgehen. Der Vorteil daran ist, dass der Nutzer einfach wieder nach oben scrollen kann ohne das sich die Seite wieder lädt. Eingesetzt habe ich es selber z.B. bei der Shoppingmap Demoanwendung welche über AJAX dynamisch Amazon nach Suchtreffern abfragt und die Covers anzeigt.

Browserunterstützung

Das onscroll Event wird von allen gängigen Browsern unterstützt: IE6/7, Firefox, Opera und ich denke auch das Apple dieses Event unterstützt. In der MSDN und bei Mozilla Developer ist sogar ein Eintrag vorhanden. Daher kann man es eigentlich ohne Probleme einsetzen.

 

Simples Demoprojekt – der Aufbau

Wir haben im Prinzip nur ein Element, welches eine bestimmte Höhe hat und durch “overflow: auto” dazu genötigt wird, bei einem Übergroßen Content die Scrollbars einzublenden. Darüber haben wir noch eine kleine Debug (bzw. zum Verständnis brauchbare) Meldung.

In dem Element, in unserem Fall eine Liste (ul) sind bereits einige Standardeinträge vorhaden. Wenn man nun scrollt sollen neuen Elemente hinzugefügt werden.

image

HTML:

    <ul id="ScrollElement" onscroll="nextElements()" style="height: 100px; width: 300px; overflow: auto; border: solid 1px black;">
       <li>Item</li>
       <li>Item</li>
       <li>Item</li>
       <li>Item</li>
       <li>Item</li>
       <li>Item</li>
       <li>Item</li>
       <li>Item</li>
       <li>Item</li>
       <li>Item</li>
    </ul>

Diesem “ScrollElement” haben wir nun, ähnlich wie onclick, einfach das onscroll Event hinzugefügt.

 

Simples Demoprojekt – die “Scroll Logik” implementieren

Dies ist der Javascript Code welcher beim Scrollen immer aufgerufen wird.

    var global_block = false;
    var global_counter = 0;

    function nextElements()
    {
     var element = document.getElementById('ScrollElement');
     var height = element.scrollHeight;
     var scroll = element.scrollTop;

     var diff = height - scroll;

     document.getElementById('Debug').innerHTML = diff;

     if(diff <= 200 && global_block == false)
     {
     global_block = true;

     appendNewElements();
     }
    }

Es wurde eine globale Variable “global_block” definiert, welche verhindert, dass sobald nach unten gescrollt wird sofort neue Elemente an das Zielelement drangehangen werden. Insbesondere wenn man (sinnvollerweise) AJAX Requests macht, wie bei dem Shoppingmap Projekt, würde man dadurch den Client belasten, weil er viele Requests losschicken muss. Diese Variable verhindert dies, indem sobald ein Request aktiv ist, die Variable auf “true” gesetzt wird. Dadurch werden weitere Requests solange unterbunden, bis die Aktion ausgeführt wurde. Dannach kann man weiterscrollen.

Die Eigenschaft “scrollHeight” gibt die gesamte Höhe des Elementes wieder (auch das was man nicht sieht).
Die Eigenschaft “scrollTop” gibt den Abstand nach oben an. Die verlinkten Mozilla Seiten geben dies auch gut anhand von Screenshots wieder.

Wenn nun zu weit nach unten gescrollt wird und die Differenz unter einem bestimmten Wert fällt und noch kein Request losgeschickt wurde, dann werden neuen Elemente angehangen.

Simples Demoprojekt – das Anhängen neuer Elemente

Das Anhängen neuer Elemente läuft ganz einfach über createElement und appendChild ab. Bei jedem “Request” werden 10 Einträge hinzugefügt. 

    function appendNewElements()
    {
     for(var i=0; i<10; i++)
     {
      global_counter++;
      var newListElement = document.createElement('li');
      newListElement.innerHTML = 'AppendedItem: ' + global_counter;

      var parentElement = document.getElementById('ScrollElement');
      parentElement.appendChild(newListElement);
     }
     global_block = false;
    }

Am Ende wird die “blockierende” Variable wieder auf “false” gesetzt.

Resultat – das unendliche Scrollen

image

Man kann nun theoretisch unendlich lang nach unten scrollen. Nette Spielerei.

Wo ist das sinnvoll?

Sinnvoll ist so eine Funktionalität vor allem dort, wo viele Bilder oder Videos (oder Silverlight Content) nachgeladen werden. Da der Browser schlecht 300 Bilder auf einmal ziehen kann, sondern vielleicht nur immer 20, aber man selbst trotzdem dieses “Seite 1, 2, 3, 4″ leid ist, kann man diese Technik sehr gut mit AJAX kombinieren.

Dadurch erleichert man auch dem Nutzer das “zurückscrollen”, indem man zuvor geladen Sachen gleich ansehen kann und nicht erst warten muss bis der Browser zur vorherigen Seite zurück gegangen ist.
In dem ShoppingMap Demoprojekt ist die Funktionalität z.B. sehr nützlich und bietet einen interessanten Ansatz.

Democode Live:

[ Source Code +  Demoanwendung ]

Links:

ShoppingMap Demoprojekt
Selfhtml Javascript Eventhandler
Mozilla Developer – onscroll
MSDN – onscroll
Mozilla Developer – scrollHeight
Mozilla Developer – scrollTop
Microsoft Live Bildersuche

HowTo: Objektorientierte Programmierung / OOP in Javascript (Eine einfache Klasse erstellen)

Durch den (berechtigten) Hype um AJAX und das “Daten-Format” JSON wird eine Sache in der Webentwicklung immer interessanter: Die Javascriptentwicklung.

Insgesamt vollzieht sich meiner Meinung nach ein kleiner Wandel in der Webentwicklung – man versucht sehr viele Sachen auf den Client auszuführen. Diese Entwicklung kann ich nur begrüßen, denn warum muss ich bei einer Sortierung von einer Tabelle wieder mit den Server kommunizieren, obwohl die Daten bereits auf dem Client sind?

Genau solche Aufgaben können heute bereits Javascript-Frameworks erledigen. Auch bei Microsofts ASP.NET AJAX Extensions ist eine Clientbibliothek enthalten, doch nun kommen wir zur generellen Frage: Wie kann ich Daten in so einem Framework kapseln? Wie kann ich eigene Javascript Klassen mit Methoden definieren?

Klassen und Methoden in Javascript definieren – Schlagwort “prototype”

Prototype ist nicht nur ein Javascript Framework, sondern auch allgemein in der JS Welt ein Schlüsselwort für das definieren von Methoden. Aber erstmal Schritt für Schritt.
Wir machen ein ganz einfaches Beispiel – ein Rechteck. Das als Eigenschaft eine Höhe und Breite und wir möchten nun den Flächeninhalt berechnen.

 

Schritt 1: Konstruktor samt Member definieren

    function Rectangle()
    {
        this.height;
        this.width;
    }

Der Konstruktor ist eigentlich eine ganz normale JS Funktion, denn es gibt kein Schlüsselwort “class” in JS. Dannach sagen wir noch, dass wir zwei Eigenschaften height und width haben und schreiben noch (wie in der OOP üblich) ein “this” davor.

Schritt 2: Getter / Setter definieren

Wir können natürlich die Werte auch direkt dem Konstruktor übergeben (”Rectangle(10, 5)”), aber wir machen das direkt mit Getter/Setter-Methoden, wo auch das “prototype” zum Tragen kommt:

    Rectangle.prototype.setHeight = function(value)
    {
            this.height = value;
    }
    Rectangle.prototype.getHeight = function()
    {
            return this.height;
    } 

Wir “prototypen” das Rectangle und sagen, ass es eine “setHeight” und “getHeight” Funktion gibt, welche über das Schlüsselwort “this” Zugang zu den Eigenschaften der Klasse haben.
Das ganze natürlich auch noch für die andere Eigenschaft. 

Schritt 3: Calc Methode erstellen

Die Methode wo wir die Fläche errechnen wollen ist genauso einfach geschrieben wie bereits vermutet. “prototype” und über “this” auf die Werte zugreifen:

    Rectangle.prototype.calc = function()
    {
            var result = this.getWidth() * this.getHeight();
            return result;
    }    

Schritt 4: Objekte erstellen und testen

In der ganz einfachen Demoanwendung (siehe Link unten) erstellen wir unsere Obejekte in einer JS Funktion welche im onload aufgerufen wird.

    function initApp()
    {
        var objectA = new Rectangle();
        objectA.setHeight(10);
        objectA.setWidth(2);

        var objectB = new Rectangle();
        objectB.setHeight(15);
        objectB.setWidth(3);

        alert(objectA.calc());
        alert(objectB.calc());
    }

Schritt 5: Ergebnis

Funktioniert wunderbar (getestet IE7 und FF2):

image

image

Ein Blick in den Firebug zeigt uns auch die Hierarchie:

image

 

Weiterführende Links

 

Ich wollte dieses Beispiel ganz bewusst simple halten, da ich ansonsten immer nur sehr komplexe Beispiele gesehen hab. Wer sich tiefergehender darüber informieren möchte, der sollte sich diese Seite mal anschauen.

[ Source Code + Demoanwendung ]

HowTo: Xml mit Javascript Parsen (Zugriff auf Nodes & Attribute)

JSON ist eigentlich eine feine Sache – allerdings hat man manchmal keine Wahl und muss in Javascript ein XML parsen.

Das dies eigentlich fast genauso einfach ist, wie JSON, sieht man allerdings erst hinterher. Da der Zugriff manchmal allerdings etwas blöder ist als unter .NET selbst, schreibe ich kurz dieses HowTo. Die Demoanwendung samt kompletten Sourcecode gibts am Ende.

Vorbereitung: ASP.NET AJAX Projekt, XML Datein samt Webservice mit “ScriptService” versehen und einbinden

Unsere Demoappliaktion ist sehr einfach – das Hauptaugenmerk liegt sowieso später auf dem Javascript:

image

Die 3 XML Datein werden wir mit Javascript auswerten:

“Example_1.xml”

<?xml version="1.0" encoding="utf-8" ?>
<root>FooBar</root>

“Example_2.xml”

<?xml version="1.0" encoding="utf-8" ?>
<root>
   <itemCollection>
      <item>FooBar1</item>
      <item>FooBar2</item>
      <item>FooBar3</item>
   </itemCollection>
</root>

“Example_3.xml”

<?xml version="1.0" encoding="utf-8" ?>
<root>
   <itemCollection category="Products">
      <item id="1234523">
         <title>Foo1</title>
         <subtitle>Bar1</subtitle>
      </item>
      <item id="123797590">
         <title>Foo2</title>
         <subtitle>Bar2</subtitle>
      </item>
      <item id="889774395">
         <title>Foo3</title>
         <subtitle>Bar3</subtitle>
      </item>
   </itemCollection>
</root>

Wie man sieht – am Ende ist quasi die Königsdisziplin dran – verschachtelte Elemente und Attribute.

Der Webservice hat folgende Methode:

        [WebMethod]
        [ScriptMethod(ResponseFormat=ResponseFormat.Xml)]
        public XmlDocument LoadExample(int id)
        {
            string filename = "Example_" + id.ToString() + ".xml";
            string path = Path.Combine(this.Context.Request.PhysicalApplicationPath, filename); 

            XmlDocument ExampleDocument = new XmlDocument();
            ExampleDocument.Load(path); 

            return ExampleDocument;
        }

Achtung: Da die AJAX Extensions (siehe auch dazu hier die Grundlagen) immer ein Json zurückgeben, muss man erst das “ResponseFormat” auf “ResponseFormat.Xml” stellen.
Ansonsten einfaches einlesen der einzelnen XML “Example_X.xml” Datein und über den Webservice zurückgeben.
Diesen Webservice jetzt noch als Scriptservice im Scriptmanager bekannt machen und gut ist (das dazugehörige HowTo).

Einfaches Interface basteln

image

Das sehr einfache Interface besteht aus einer Überschrift und 3 Buttons welche die AJAX Requests starten, damit wir im Anschluss das XML auswerten können.
Unter den Buttons erfolgt dabei die Ausgabe und eine kurze Erklärung was da passiert.

Javascript: Example_1.xml parsen (einfacher Javascript Zugriff auf ein Element)

var myResult = result.getElementsByTagName("root")[0].firstChild.nodeValue;

Das ist der Zugriff auf unser “nodeValue” “FooBar”. In dem Screenshot kann man den Verlauf auch folgen: 

image 
(Ausschnitt aus dem Firebug – siehe dazu HowTo JS debuggen)

Erklärung:

getElementsByTagName: Liefert alle Nodes mit den übergebenen Namen zurück
getElementsByTagName(”root”)[0]: Liefert das erste vorkommen dieses Nodes zurück
firstChild: Liefert auch das erste Vorkommen eines Nodes zurück – wenn man aber auf den Value des Nodes Zugreifen will, muss man vorher ebenfalls über firstChild und dann erst nodeValue rein (siehe Screenshot)

Javascript: Example_2.xml parsen (Javascript Zugriff auf mehrere Element)

                var myResult = "";
                for(i = 0; i < result.getElementsByTagName("item").length; i++)
                    {
                    myResult += result.getElementsByTagName("item")[i].firstChild.nodeValue + "<br/>";
                    }

Erklärung:

Hier macht man sich den selben Mechanismus zunutze, diesmal fragt man allerdings vorher die Anzahl der gefunden Nodes über “getElementsByTagName(’xxx’).length” ab.
Dannach wieder jede Node durchgehen und auf unseren Inhalt über “firstChild.nodeValue” zugreifen.

Javascript: Example_3.xml parsen (Javascript Zugriff auf Xml Attribute)

Da es ja auch vorkommt, dass Attribute mit in den Nodes vorhanden sind, können diese natürlich ebenfalls über Javascript abgerufen werden:

result.getElementsByTagName("itemCollection")[0].getAttribute("category")

Über die Methode “getAttribute” wird direkt der gefundene Value des Attributes zurückgegeben. Eine andere (aber nicht so schöne) Möglichkeit ist über “element.attributes[0].value” – alledings geht “element.attributes["category"].value” nicht (jedenfalls bei mir gerade nicht).

Getestet alles mit IE 7 und Firefox 2 – sollte aber generell bei allen Browsern so funktionieren.

[ Source Code | Demoapplikation* ]

* auf dem Webspace funktioniert es momentan noch nicht so wie lokal – hängt mit dem Hoster zusammen – einfach die Demoapp runterladen und freuen ;)

Links:

HowTo – ASP.NET AJAX Grundlagen
HowTo – Clientseitiger Aufruf von Webmethoden
HowTo – JS debuggen

HowTo: Microsoft Silverlight 1.0 (Webanwendungen mit dynamischen SilverlightHosts verschönern)

Eine bestehende Webapplikation mit einem kleinen Silverlight Host die “Video” Fähigkeit beibringen ist nicht unbedingt schwierig, dass Problem was allerdings besteht ist, dass es bereits viele HTML Suchmasken oder Datenforumlare gibt.

Wenn man nun nur kleine Silverlight Teile benötigt, wollen wir keine große Silverlight Anwendung haben, sondern mehrere kleine, da wir diese mit den bereits bestehenden Forumlaren verschmelzen wollen:

image

 

Schritt 1: Template.xaml erstellen

Mit Microsofts Expression Blend 2 (August Preview) erstellen wir ein kleines Template, welches wir später befüllen wollen. Das Template ist ähnlich geartet wie das, welches ich bereits in diesem HowTo beschrieben habe.

image

Es enthält ein gespiegeltes Textelement, welches wir dynamisch unseren Divs hinzufügen wollen.

In diesem Template wurde die beiden Textelemente jeweils mit einem “x:Name=’TitleText’” & einem “x:Name=’TitleShadow’” versehen damit wir es in Javascript ansprechen können.

Schritt 2: Silverlight Projekt anlegen / Silverlight.js dem Projekt hinzufügen & Template einfügen

Ich hab in meinem Beispiel das Silverlight 1.0 Template des SDKs abgewandelt, aber ansonsten braucht man nur die Silverlight.js (aus dem Template z.B.) sowie unser Template aus dem Expression Blend Ordner (oder man hat die XAML Datei per Hand erstellt – ist am Ende egal) importieren.

image

Die Default.html enthält (neben dem Style und den JS Links):

<input type="text" name="Count" id="Count" />
<button type="button" onclick="createElements()">Click</button>
<div id="AppHost">
</div>

In dem “AppHost” Div werden wir unsere Divs hinzufügen, welche dann wiederrum unsere SilverlightHosts darstellen. 
In dem Inputfeld wird die Anzahl der Divs zum Erstellen angegeben welche bei “createElements()” erstellt werden.

Schritt 3: Javascript zum dynamischen Erstellen implementieren

In der Defaut.html.js liegt unsere “Logik”:

createElements():

function createElements()
{
    var count = document.getElementById('Count').value;
    for(var i = 0; i < count; i++)
        {
        var itemDiv = document.createElement('div');
        itemDiv.id = 'element_' + i;
        itemDiv.className = 'Elements';

        var silverlightDiv = document.createElement('div');
        silverlightDiv.id = 'element_silverlight_' + i;
        silverlightDiv.className = 'Silverlights';
        itemDiv.appendChild(silverlightDiv);
        createSilverlight(silverlightDiv, i);
        document.getElementById('AppHost').appendChild(itemDiv);
        }
}

Die “createSilverlight(silverlightDiv, i)” Methode erstellt unsere SilverlightHosts – das “silverlightDiv” gibt dabei an, in welchen Div es erstellt werden soll und das “i” ist in diesen einfachen Fall meine Javascript-ID, welches unser Div repräsentiert. Im praktischen Umfeld könnte es aber z.B. ein JSON Objekt sein.

createSilverlight(parentDiv, id):

function createSilverlight(parentElement, id)
{
    var slPluginId = 'SilverlightPlugIn_' + id;
   Silverlight.createObjectEx({
      source: 'Template.xaml',
      parentElement: parentElement,
      id: slPluginId,
      properties: {
         width: '295',
         height: '189',
         background:'#ffffffff',
            isWindowless: 'false',
         version: '1.0'
      },
      events: {
         onError: null,
         onLoad: onComplete
      },
      context: id
   });
}

 

Diese Methode erstellt den Silverlight Host mit der “createObjectEx” Methode. Allerdings können wir im Anschluss nicht direkt auf den SilverlightHost zugreifen und unsere beiden Textelemente je nachdem anpassen – daher definieren wir eine Javascript “onload” Methode namens “onComplete“.
Der Aufruf dieser Methode geschiet nachdem das Silverlight Objekt angelegt wurde – allerdings benötigen wir noch eine ID, damit wir in der onComplete Methode auch wissen, bei welcher ID wir gerade sind.
Für das weitergeben des ID Parameters an das “onload” Event gibt es das context Objekt: In unserem Fall geben wir hier unsere ID weiter, damit wir dann in der “onComplete” Methode darauf zugreifen können.

Wie auch im vorherigen Abschnitt: Ein JSON Objekt könnte genauso gut weitergegeben werden.

onComplete(sender, userContext, eventArgs):

function onComplete(sender, usercontext, eventArgs)
{
   sender.content.FindName("TitleText").Text = "My Item: " + usercontext;
   sender.content.FindName("TitleShadow").Text = "My Item: " + usercontext;
}

Mit den Informationen können wir nun unsere dynamischen Silverlight Hosts erstellen. Über den “sender” können wir auf den XAML Content zugreifen und über die “FindName” Methode unseren Text ändern.

Ergebnis:

Die Anwendung ist natürlich sehr zweifelhaft, allerdings soll es nur das Prinzip zeigen, wie man mehrere Silverlight Hosts nehmen kann, um einzelne Abschnitte der Website zu erweitern.

image

 

Downloads / Demos:

 

[ Hier gehts zur Demoapplikation | Hier gibts den SourceCode ]

 

Links:

HowTo: Microsoft Silverlight 1.0 (dynamische Spiegeleffekte erzeugen)
Microsoft Expression Blend 2 August Preview
Silverlight SDK
Silverlight Plugin erstellen
Silverlight onLoad
Silverlight Events
Silverlight FindName

HowTo: Mauseingaben & Javascript (Wie bastelt man ein Paint mit Javascript?)

In diesem HowTo schauen wir uns mal an, wie man auf Mauseingaben mit Javascript reagiert. Es ist etwas schwammig formuliert, allerdings fiel mir nichts besseres ein.
Auf einfache “onclick” Events oder “onhover” etc. zu reagieren, ist nicht besonders schwer. Allerdings ist es manchmal wichtig zu wissen, wo der Nutzer hingeklickt hat – direkt dort wo der Nutzer hinklickt muss irgendwas passieren. In Zeiten von Drag`n`Drop wird es auch immer wichtiger, die Maus intuitiv mit in die Weboberfläche zu integrieren – also mehr als nur simples klicken.

Hier setzt dieses HowTo an. Die Fragestellung in dem Titel ist zwar etwas überspitzt, allerdings wollen wir ein ganz einfaches Paint mit Javascript nachbasteln.

So sieht die Anwendung hinterher aus:

image

Schritt 1: Grundsätzlicher Aufbau

Der Hauptteil der Anwendung ist eigentlich nur ein “Div” in dem wir malen wollen:

    <div id="PaintingArea">
    </div>

Hier die Styleangaben:

    #PaintingArea
    {
    cursor: pointer;
    margin-top: 10px;
    border: solid 1px #000;
    height: 270px;
    width: 420px;
    z-index: 10;
    }

Schritt 2: Eventhandler setzen

Wie in den oberen Angabe zu sehen ist, werden keine Javascript Eventhandler hinzugefügt. Damit es auf allen Browsern läuft, muss man die Eventhandler per Code setzen (und am besten im Body onload aufrufen) :

    function init()
    {
    document.getElementById("PaintingArea").onmousedown = startPainting;
    document.getElementById("PaintingArea").onmousemove = performPainting;
    document.getElementById("PaintingArea").onmouseup = endPainting;
    }

onmousedown:

Bei einem einfachen “onmousedown” (also sobald die Maustaste gedrückt wird) wird ein Flag “Global_Painting” gesetzt, dass momentan gezeichnet wird und im Anschluss wird einfach unser Punkt (also ein Div gezeichnet).

onmousemove:
Wenn die Mause über den Div bewegt wird UND das Flag gesetzt ist, wird weiterhin gezeichnet. Falls vorher kein Klick (und kein Flag gesetzt wurde), wird nicht gemalt. So ist es möglich, dass man mit der Maus über das Div bewegt, ohne das was passiert.

onmouseup:
Wenn die Maustaste losgelassen wird, wird das Flag auf false gesetzt – also wird nicht mehr gemalt und die Maus kann wieder über das Div bewegt werden, ohne das was passiert.

Schritt 3: Mausposition auslesen

Hier kommt eigentlich der wichtigste Schritt – das auslesen der aktuellen Mausposition.

Im IE / Opera kann man über diese Eigenschaft darauf zurückgreifen:

        Global_Painting_offsetLeft = window.event.clientX;
        Global_Painting_offsetTop = window.event.clientY;

Im Firefox über diese hier (daher einfach eine kleine JS Browserweiche mit “if(document.all)“ einbauen) :

            Global_Painting_offsetLeft = clickEvent.clientX;
            Global_Painting_offsetTop = clickEvent.clientY;

Dabei ist “clickEvent” als Parameter der Funktion übergeben (obwohl in der init nichts angegeben wird – es funktioniert ;) ).
Die “Global_Painting_offsetXXX” Variablen speichern die momentane Mausposition.

Hier mal die komplette startPainting Funktion:

    function startPainting(clickEvent)
    {
    Global_Painting = true;    

    if(!clickEvent) clickEvent = window.event;
    if(document.all)
        {
        Global_Painting_offsetLeft = window.event.clientX;
        Global_Painting_offsetTop = window.event.clientY;
        }
    else
        {
        Global_Painting_offsetLeft = clickEvent.clientX;
        Global_Painting_offsetTop = clickEvent.clientY;
        }    

    paint();
    }

Die “perfomPainting” ist eigentlich ebenso.

Schritt 4: Das Malen implementieren

Die gemalten “Pixel” sind in wahrheit Divs mit einer Hintergrundfarbe. Den Div wird einfach als “style.top” und “style.left” Attribut die Werte aus unseren “Global_Painting_offsetXXX” gegeben.

Schritt 5: Fertig

Der Rest ist eigentlich nur noch simples Javascript – z.B. Farbe setzen oder “Pinselgröße”. Das kann ja jeder sich im Code anschauen.

Nachtrag:

Bei dem Malen verwende ich einfache Divs – das sieht für den Nutzer schön aus und ist auch recht easy. Man hätte auch eine Tabelle nehmen können, da wäre das programmatische Auswerten wesentlich einfacher, hätte aber das Raster begrenzt. Auch das es im FF etwas buggy ist, stimmt – allerdings soll dies nur eine Anregung sein und mal zeigen, wie man auf die Mauspositionsdaten zugreifen kann.

Viel Spaß beim Benutzen und Weiterverwenden :)  

Links:

[ Zur Javascript Paint Anwendung + Source Code ]

Neues HowTo: Javascript debuggen ist anstrengend…

… muss es aber nicht. Jedenfalls gibt es kleine Helferlein.

In dem neuen HowTo geht es genau daraum: Was sind die “wichtigesten” Tools und was können sie ganz grob.

[Hier gehts zum HowTo]

HowTo: Webanwendung debuggen (Javascript & HTML debuggen mit den entsprechenden Tools)

Eine normale Webseite zu erstellen geht sehr schnell. Doch heutige Webanwendungen sind seit AJAX und dem ganzen Web 2.0 Spielerein doch immer komplexer geworden. Dazu kommt die Anforderung, dass alle Seiten am Besten in jedem Browser gleich aussehen und ebenfalls auch gleich funktionieren soll.

Da Javascript generell eine eher unschöne Sprache ist, da es nur sehr wenig gute Tools gibt, die einem das Debuggen erleichtern und auch in jedem Browser anders interpretiert wird, braucht man wenigstens gewisse Anhaltspunkte zum Lösen des Problems.
In dem HowTo sollen ein paar Tipps vorgestellt werden, die mir bisher bei den meisten Problemen geholfen haben.

Tools die man als guter Webdesigner braucht:

Als Browser sollte man (je nach Anforderung) diese installiert haben:

- Internet Explorer 7 / Internet Explorer 6

  Tipp für den IE6: Wer bereits den IE7 installiert hat, kann sich den IE6 zum Beispiel als Virtual Maschine nochmal installieren.
  Das IE Team bietet dazu eine bis zum Dezember gültige Version an (Voraussetzung Virtual PC)
- Firefox 2
- Opera 9

Wer einen Mac hat (die PC Version nehm ich bis jetzt noch nicht wirklich ernst) sollte auch unter dem Safari schauen.

Folgende AddOns sollte man ebenfalls dazu installieren:

image 

Internet Explorer

Die IE Developer Toolbar gibt einen Einblick in die DOM und man kann so untersuchen, wie der IE es interpretiert.

Wer die Toolbar nicht findet, obwohl er sie installiert hat, einfach unter Ansicht / Explorer-Leiste nachschauen:

image

Die IE Developer Toolbar in Aktion:

image

Im unteren Bereich sieht man die DOM wie der IE sieht sieht – und umrahmt z.B. das gerade angeklickte Element und zeigt dessen Attribtute & Styles.

Das wäre es erstmal für den IE an den wichtigen Addons.

 

image

Firefox

Für den Firefox gibts wohl die meisten praktischen Entwicklertools – welche einem sehr viele Sachen abnehmen.
Fangen wir mit einem kleinen Plugin an, welches wahrscheinlich für die am nützlichsten ist, welche den IE garnicht mögen: IE Tab. Es zeigt Websites mit der IE Render Engine an.

image  (Momentan ist Firefox/Gecko Rendering aktiviert)

Und nun umschalten auf IE Rendering:

image

Als Beweis das es funktioniert ein Screenshot von Microsofts Outlook Web Access (mit Firefox Rendering sieht es für gewöhnlich um Längen schlechter aus) :

image

Das nächste Tool lässt schonmal das Herz des Webdesigners höher schlagen.

Die Toolbar bietet sehr viele Möglichkeiten um zu sehen, wie die Seite generell aufgebaut ist. So kann man (ähnlich wie die IE Development Toolbar) Tabellen oder Divs umrahmen lassen oder über ein Mouse-Over-Effekt sehen, welchen Style ein Element hat. Man kann über die Toolbar auch den Cache oder Javascript ausschalten, den Style ausschalten, sich ein Lineal einblenden lassen, Link-/Bildpfade anzeigen, Details zu den Formularen auf der Seite und und und…

image 
Beachte: Das Bild Element ist umrahmt und es wird angezeigt wo der Link verweißt (das Gelbe).

Das Tool fest schonmal mehr als die IE Development Toolbar, aber es geht noch netter:

 

Mittels Firebug kann man, ähnlich wie mit der Toolbar, auch direkt mit einem Mouse-Over die Seite untersuchen und die jeweiligen Elemente werden dann umrahmt und auch die komplette DOM kann eingesehen werden.
Was an Firebug noch besonders ist: Änderungen im Code können direkt eingefügt werden, sodass ein F5 oder ähnliches entfällt. Sehr elegant, wenn man mal wieder ein Style Attribute ändern/suchen muss, damit es überall gleich aussieht.

image 
Im unteren Teil sieht man gut, wie Firebug aufgebaut ist – es gibt mehrere Reiter.

Ein paar Bestandteile mal kurz erklärt:

    • HTML:
      • image
      • Einsicht in die CSS Eigenschaften des jeweiligen Elements (Rechts daneben)
      • Editieren des Styles etc.
    • CSS:
      • Einsicht in die CSS Datein
      • Ebenfalls editierbar
    • Script:
      • Kompletter Javascript Debugger (!!!)
      • image
      • Wie in Visual Studio kann man Breakpoints setzen (Beispiel ist von der Virtual Earth Demopage) und sofort die Ergebnisseund die DOM sehen
    • DOM:
      • Wie der Name schon verrät: Einsicht in die DOM (siehe Script – Rechter Teil)
    • NET:
      • Um mal zu sehen, wie lange ein Request dauert oder was als Request und Response Parameter gesendet wird ist dieser Reiter Ideal
      • image

Als letztes sei noch Yahoos YSlow Erweiterung für Firebug zu erwähnen.
Diese gibt Performancetipps welche auf der Yahoo Seite einsehbar sind oder einen Status darüber, wieviel Daten beim Aufruf gesendet werden etc.

image

 

Es gibt vermutlich noch mehr Tools, allerdings sind das die Tools die ich selber nutze.

Viel Spaß damit.

Links:

Internet-Explorer

Firefox

Opera