Unobtrusive Javascript mit jQuery

Unobtrusive – unaufdringlich, zurückhaltend, dezent – meint hier den unauffälligen Einsatz von Javascript. Statt den HTML-Code mit Javascript zu spicken, wird der Code zum einen ausgelagert und zum anderen nicht explizit an HTML-Elemente gebunden, sondern implizit durch das Setzen entsprechender Attribute. Insgesamt führt dieser Ansatz zu einer besseren Trennung von UI Design (HTML) und Verhalten (Javascript) und einer besseren Wiederverwertbarkeit des geschriebenen Codes.

Gerade beim (ersten) Einsatz von jQuery neigt man u.U. dazu, für spezifische GUI-Elemente spezifisches Verhalten zu programmieren, statt allgemeingültigere Ansätze zu verfolgen. Oft wird der Code entsprechend mit diesem spezifischen Javascript durchsetzt.

Die beiden Beispiele finden sich online unter http://demo.jochenlinnemann.de/foundation/xp/unobtrusive

Beispiel: jQueryUI

<a href="#" id="DialogStarter">Zeige Dialog</a>
<div id="SampleDialog" title="Hinweis">
    <p>Hallo, Welt!</p>
</div>

Der obige HTML-Ausschnitt könnte durch das folgende Javascript mit Leben erfüllt werden:

<script type="text/javascript">
    $(function () {
        $("#SampleDialog").dialog({ autoOpen: false });
        $("#DialogStarter").button().click(function() {
            $("#SampleDialog").dialog("open");
        });
    });
</script>

Dieser Quelltext macht nichts Besonderes, ist aber spezifisch für den obigen HTML-Ausschnitt geschrieben. Es wäre wesentlich schöner, wenn man durch einfache Deklaration ein Verhalten an ein HTML-Element binden könnte. In meinem Beispiel verwende ich das Attribut „class“, um das grundlegende Verhalten zu steuern:

<a href="#" class="jsButton">Zeige Dialog</a>
<div id="SampleDialog" title="Hinweis" class="jsDialog">
    <p>Hallo, Welt!</p>
</div>

Ein passendes, allgemeingültiges Skript kann nun „jsButton“ und „jsDialog“ mit einem entsprechenden Verhalten belegen. Dieser Code kann bequem in eine *.js-Datei ausgelagert werden. Hier sei er der Einfachheit halber in einem <script>-Tag eingefasst:

<script type="text/javascript">
    $(function () {
        $(".jsDialog").dialog({ autoOpen: false });
        $(".jsButton").button();
    });
</script>

Für den Button fehlt jetzt noch eine Möglichkeit, das Verhalten genau zu spezifizieren. Dazu verwende ich in diesem Beispiel selbstdefinierte HTML5-„data-„-Attribute:

<a href="#" class="jsButton"
   data-js-target="#SampleDialog"
   data-js-action="dialog"
   data-js-param="open">Zeige Dialog</a>

Die Erweiterung des Javascripts bringt dann das gewünschte Verhalten:

<script type="text/javascript">
    $(function () {
        $(".jsButton").button().click(function () {
            var target = $(this).attr("data-js-target");
            var action = $(this).attr("data-js-action");
            var param = $(this).attr("data-js-param");

            if (target && action && param) $(target)[action](param);
            else if (target && action) $(target)[action]();
        });
    });
</script>

Beispiel: Ajax

Auf ähnliche Weise lässt sich auch das Verhalten von Links ändern, so dass zum Beispiel kein Seitenwechsel stattfindet, sondern Inhalte aus einer anderen Seite gezielt nachgeladen werden, um in der aktuellen Seite zu erscheinen.

<a href="unob-full.html" class="jsButton"
   onclick="$('#Content').load($(this).attr('href')
   + ' #ProductDetails > *');
   event.preventDefault();">Lade komplettes HTML</a>
<div id="Content" class="ui-widget">
</div>

In „Unobtrusive“-Schreibweise würde daraus:

<a href="unob-full.html" class="jsButton ajaxLink"
   data-ajax-target="#Content"
   data-ajax-source="#ProductDetails">Lade komplettes HTML</a>
<div id="Content" class="ui-widget">
</div>

Und das zugehörige Javascript sähe wie folgt aus (und könnte ebenfalls in eine *.js-Datei ausgelagert werden):

<script type="text/javascript">
    $(function () {
        $(".ajaxLink")
        .click(function (event) {
            var target = $(this).attr("data-ajax-target");
            var href = $(this).attr("href");

            if (target && href) {
                var source = $(this).attr("data-ajax-source");
                $(target).load(href + (source ? " " + source + " > *" : ""));
            }

            event.preventDefault();
        });
    });
</script>

jQuery Mobile

Sowohl das jQueryUI- als auch das Ajax-Beispiel lassen sich in der Umsetzung von jQuery Mobile in der einen oder anderen Form wiederfinden; dort wird grundlegendes Verhalten durch „data-role“ und das Nachladen von Inhalten durch „data-ajax“ gesteuert. Letzteres wird standardmäßig als „true“ angenommen, wodurch das Laden aller verlinkten Seiten per Ajax-Request erfolgt.