Pimcore Ajax Navigation

Lukas [php, Tricks und Tools, Pimcore]

Ajax wird gerne benutzt, um Teile der Seite neu zu laden. Das weil es schneller ist nur partiell Inhalte zu laden, aber auch weil es chic aussehen kann. Für eine Seite war ein animierter Seitenwechsel gewünscht. Damit das Suchmaschinentechnisch ebenfalls sinnvoll ist, war der Plan der folgende: Alle Seiten haben eine eigene URL und können darüber abgerufen werden. Das Stellt auch sicher, dass die Seite ohne Javascript funktioniert. Sobald Javascript greift, werden sämtliche Links so angepasst, dass der Inhalt jeweils per Ajax nachgeladen wird. Und das ohne dass der Bearbeiter der Seite im CMS davon etwas wissen muss.

Um das zu realisieren muss man an zwei Orten eingreifen. Dank dem MVC Modell einmal im Controller in Pimcore. Der zweite Teil ist ein Javascript welches die Links auswechselt und den Seitenwechsel animiert.

1. Teil: Pimcore Controller ajaxifizieren

Dank des MVC Ansatzes ist dieser Teil ein Kinderspiel. Im folgenden der Codeschnipsel unserer default Action. Da wir grösstenteils mit Areas bzw. Bricks arbeiten ist im Controller nichts weiter notwendig. Der View wird einfach mitgeteilt, dass das Layout nicht akiviert werden soll. Der gesamte HTML Code kann über die render methode der view anstatt direkt ausgegeben zu werden in ein String gepackt werden. Das ist in dem Fall notwendig, weil zusätzlich ein Hintergrundbild pro Seite in einer property angegeben werden kann. Dieses wird zusammen mit dem HTML Code der Seite in ein JSON Array umgewandelt und zurückgegeben.

public function default() {
    if ($this->getParam("layout") !== "false") {
        $this->enableLayout();
    } else {
        $htmlString = $this->view->render('default/default.php');
        $background = $this->document->getProperty('background_image');
        echo Zend_Json::encode(
            array("content" => $htmlString,
                  "background" => $background->getFullPath()
            )
        );
        exit();
    }
}

2. Teil: Das Javascript

Damit nun der layout Parameter mit false übergeben wird damit der Inhalt der Seite in einem json array verpackt zurückkommt braucht es den Javascript teil. Der übernimmt noch weitere Aufgaben. So gilt es zum Beispiel den Hintergrund zu wechseln sowie die URL, damit wenn jemand diese kopiert auch wirklich die aktuell angezeigt Seite als Link weitergegeben wird.

a) Ersetze die Click-Action in der Navigation:

Hier gibt es einige Teile zu erklären. Damit dies gleich an Ort und Stelle passiert sind im Source-Code Kommentare angebracht. Einige Funktionen sind ausgelagert und werden im Nachhinein noch weiter erläutert.

$(document).ready(function() {
    // Fange alle click Events der Links innerhalb der Navigation ab
    $('nav a').click(navClickFunc);
});

function navClickFunc(e) {
    // Default event stoppen. Sorgt dafür, dass der
    // Link nicht wie üblich aufgerufen wird.
    e.preventDefault();
    // Sammle die wichtigsten Variabeln für später
    var href = $(this).attr('href');
    var id = "content" + href.replace(///g, "-");
    var navclass = "nav" + href.replace(///g, "-");
    var backgroundId = "background" + href.replace(///g, "-");
    var currentContent = $('div#content div.active');
    var currentBackground = $('div#backstretch div.active');
    var width = currentContent.width();

    // Prüfe ob der aktuelle Link der momentan sichtbaren Seite
    // entspricht. Falls ja abbrechen.
    var currentId = currentContent.attr("id");
    if (id == currentId) {
        return;
    }

    var target = $('div#' + id);
    if (target.length > 0) {
        // Die Seite ist bereits im DOM vorhanden. Hier muss
        // nur die animation des Seitenwechsels erfolgen.
        target.css("left", "-" + width + "px");
        animate(currentContent, target);
        var newBackground = $('div#' + backgroundId);
        fadeBackground(currentBackground, newBackground);
        updateUrl(href);
    } else {
        // Seite ist nicht im DOM. Lade per Ajax nach.
        $.ajax({
            url : href,
            dataType : "json",
            data : {
                layout : "false"
            }
        }).done(function(data) {
            // Hintergrund div bereitstellen
            var newBackground = $('<div></div>');
            newBackground.attr("id", backgroundId);
            newBackground.css("display", "none");
            newBackground.css("background-image",
                              "url(" + data.background + ")");

            // Neues content div bereitstellen
            var parent = $("div#content");
            var newContent = $('<div></div>');
            newContent.attr("id", id);
            newContent.addClass("content-div");
            newContent.css("left", '-' + width + 'px');
            newContent.append(data.content);
            parent.append(newContent);
            var backgroundParent = $("div#backstretch");
            backgroundParent.append(newBackground);

            // Hintergrundbild laden und wenn geladen animation starten
            var preloadImage = $('<img src="' + data.background + '" />');
            preloadImage.load(function() {
                fadeBackground(currentBackground, newBackground);
            });

            // Seitenwechsel animieren
            animate(currentContent, newContent);
            // URL ändern
            updateUrl(href);
        });
    }

    // css class der aktiven Seite anpassen
    $('.navigation .active').removeClass("active");
    $("." + navclass).addClass("active");
}

b) Ersetze aktuelle URL in der Adresszeile:

Zum Script oben gehört die Funktion updateUrl(href). Sie sorgt dafür, dass in der Adresszeile des Browsers die URL der neuen per Ajax nachgeladenen Seite angezeigt wird. Das funktioniert in allen Browsern (Ausser natürlich dem Internet Explorer < 10).

function updateUrl(href) {
    if (supports_history_api()) {
        window.history.pushState({}, "", href);
    }
}

function supports_history_api() {
  return !!(window.history && history.pushState);
}

Fertig ist die nachgerüstete Ajax-Navigation mit Pimcore, die zugleich auch ohne Javascript funktioniert sowie auch den Anforderungen an SEO (Jede Seite hat eine eigene URL mit allem drum und dran) sowie an die Usability (Die URL kann jederzeit kopiert und weitergeleitet werden) gerecht wird.

zurück