Ich weiss (nicht mehr) ob Du im Facebook bist…

Update 27.01.2011: *übel_fluch*! Facebook hat ein Captcha eingebaut, dass diese Detection momentan nicht mehr funktionieren lässt. Das Prinzip bleibt ok, die Realisierung brauchte nun etwas mehr Zeit.

Big BrotherEigentlich hätte ich ja ganz Anderes zu tun, aber per Zufall bin ich über den genialen Blogartikel von Mike Cardwell gestolpert. Er hat eine Idee gehabt, wie es möglich wird herauszufinden, ob Benutzer auf Facebook und Konsorten eingeloggt sind oder nicht.

Umgesetzt in eine kleine Library läuft es als Proof-of-Concept auf Firefox und sieht folgendermassen aus:

Loggen Sie in Gmail, Facebook, Twitter oder Digg ein um Resultate zu sehen.
Sind Sie nicht abgelenkt?

Neuer Check

Grundsätzlich wäre es ja ganz einfach: Man schaut vom Client-Browser aus, ob man Zugriff auf Bilder oder Seiten hat, die nur für Eingeloggte zur Verfügung stehen. Leider gestaltet sich dieser simple Ansatz nicht so einfach, weil mit Ajax nur zur Domain der Website verbunden werden darf und nicht an einen x-beliebigen Ort. Ein Proxy hilft auch nicht weiter, da es die Cookies des Browsers braucht, und die werden nur an Facebook, etc direkt abgeliefert.

Wie kann man also diese Restriktion umgehen?

Weiterlesen

UWA Widgets coden

Web 2.0, Just Do It…

Je besser man etwas kennt, desto besser kann man darüber lästern… Ich habe beschlossen, mich ganz praktisch durch das Tal der Tränen zu kämpfen und mich auf dieser Wanderung mit den technischen Teilen von Web 2.0 herumzuschlagen. Wie fühlt sich Ajax an? Wieviel Schatten spendet der DOM-Tree? XML oder JSON, JavaScript und APIs sollten die Dämonen auf meinem Weg sein.

Das Resultat

Das Resultat kann im Ecosystem angesehen und installiert werden. Es ist ein Widget, das Adressen über tel.search.ch sucht.
Tel.search.ch bietet ein geniales, gut dokumentiertes REST API an.

Ein paar Screenies?
So siehts in Netvibes aus:
Das tel.search.ch Widget in Netvibes

So in iGoogle:
Das tel.search.ch Widget in iGoogle

Und so in der Sidebar von Windows Vista:
tel.search.ch UWA Widget in Windows Vista Sidebar

Weiterlesen

Ein Ajax Baum der sich sein Zustand merkt

Man gönnt sich ja sonst nichts… Ich wollte für eine mit dem Symfony Framework erstellte Webanwendung eine Baumansicht. Da leichtes implemenieren langweilig ist, musste es schon ein Ajaxbaum mit Kontextmenü und allem Schnickschnack sein. Nach längerem Suchen fiel die Wahl auf Dojo, einem Toolkit mit vielen Widgets und sonstigen Spassmachern. Der Baum besitz viele Nodes, darum sollten diese dynamisch nachgeladen werden (ok, etwas Masochismus war auch dabei). Die Anwendung besteht eigentlich aus herkömmlichen Seitenwechseln, und so musste der Baum auch seinen Zustand halten können. Nundenn, nach laaaaaanger Probierephase (die Dokumentation ist nicht gerade erschlagend) und der Hilfe vom Web wurde es dennoch Realität *freu*.

Hilfreiche Websites:

Tipps generell:

  • var djConfig = {isDebug: true }; aktiviert die Debugeingaben, dojo.debug(‚Blah‘); kann für Debugausgaben benutzt werden.
  • saveExpandedIndices und restoreExpandedIndices sind methoden des erweiterten tree-Controllers! Er muss also require’d und gemixint werden (siehe unten)
  • Der Baumzustand wird in einem Cookie gespeichert, damit hat man in der Applikation nichts mehr damit zu tun.

Wie das Ganze in Symfony integriert wurde kann gerne nachgefragt werden.

Nundenn, gimme Code:

<script type="text/javascript" src="/js/dojo.js"></script>
<script type="text/javascript">
var djConfig = {isDebug: true }; // Comment if debugguing
dojo.require("dojo.widget.Tree");
dojo.require("dojo.widget.TreeSelector");
dojo.require("dojo.widget.TreeNode");
dojo.require("dojo.widget.TreeContextMenu");
dojo.require("dojo.widget.TreeLoadingController");
dojo.require("dojo.widget.TreeControllerExtension");
// Do something if a node is clicked
function modulTreeSelectFired() {
    var treeSelector = dojo.widget.manager.getWidgetById('modulTreeSelector');
    var treeNode = treeSelector.selectedNode;

    < !get a reference to the songDisplay div –>
    //var hostDiv = document.getElementById("songDisplay");

    var isFolder = treeNode['isFolder'];
    if ( !isFolder) {
       //var song = treeNode['title']
       //hostDiv.innerHTML = "You clicked on "+song;
    } else {
       //hostDiv.innerHTHML = "";
    }
    //hostDiv.style.display = "";
}

// Set up Dojo and the tree
function init() {
    var treeSelector = dojo.widget.manager.getWidgetById('modulTreeSelector');
    dojo.event.connect(treeSelector,'select','modulTreeSelectFired');

    var modulTree = dojo.widget.manager.getWidgetById('modulTree');
    dojo.event.topic.subscribe(modulTree.eventNames.collapse, "saveExpandedIndices");
    dojo.event.topic.subscribe(modulTree.eventNames.expand, "saveExpandedIndices");

    // add extensions to controller
    dojo.lang.mixin(dojo.widget.byId('modulTreeController'), dojo.widget.TreeControllerExtension.prototype);

    // Restore old state
    restoreExpandedIndices();
 }

// Save the tree state
function saveExpandedIndices() {
        // You can save this object as tree persistent state
        indices = dojo.widget.byId('modulTreeController').saveExpandedIndices(
            dojo.widget.byId('modulTree')
        );
        var flatIndices = dojo.json.serialize(indices);
        //dojo.debug(flatIndices);
        dojo.io.cookie.setCookie('modulTree/saveindices',flatIndices, 365, null, null, null);
    }

// Restore the tree state
function restoreExpandedIndices() {
        flatIndices = dojo.io.cookie.getCookie('modulTree/saveindices');
        indices = dojo.json.evalJson(flatIndices);
        //dojo.debug(flatIndices)
        if(indices) {
            dojo.widget.byId('modulTreeController').restoreExpandedIndices(dojo.widget.byId('modulTree'), indices
            );
        }
    }

// Initialize
dojo.addOnLoad(init);</script>

Der HTML-Code sollte eigentlich klar sein: Controller, Kontextmenü und Tree aufbauen (nur die erste Hierarchiestufe) und der PHP-Teil ist nach Vorgabe. Sind mehr Details gewünscht, liefere ich diese gerne nach.

Stichworte: persistent tree state, remembering tree state

Ergänzung, Juli 2008: Oky, Ihr habt recht: Gimme Code! Schwatzen kann jeder!

Hier mal den Quellcode (eher das Gerüst, bzw proof-of-concept 🙂 ) des Moduls und den Inhalt des web/js Verzeichnisses. Hilft das was? Braucht es mehr, damit es sinnvoll ist?

Geschrieben wurde es mit Symfony 1.0 und Dojo 0.4 Rev: 6258.

In der Zwischenzeit bin ich aber von dem Dojo-Ajax Zeux wieder etwas weggekommen. Ich progge für Intra- und Extranetapplikationen, und da sind zu viele Browser mit zu vielen Konfigurationen im Einsatz. Für „öffentliche“ Websites ist es sicher schön, auch wenn es (wie bei Symfony üblich) nicht voll Ajax ist, sondern halt nur Komponentenweise, was ich nicht als schön empfinde…

Ich bin zurück zum guten alten PHP-Layersmenü (Beitrag dazu folgt noch). Das fallbackt sehr schön ohne Java Script.