Tipps und Tricks zu den Themen: Software- und Webentwicklung

Donnerstag, 18. April 2013

Facebook Plugins dynamisch einbinden (XFBML)

Das Facebook SDK wird für eine Integration von sozialen Funktionen via Facebook benötigt. Ein unangenehmer Nachteil besteht darin, dass sobald das Script geladen ist, der Parser durch das Dokument geht und sowohl Facebook-Events als auch Content anbindet. Oft wird dieser Prozess zu früh, während dem Seitenaufbau gestartet. Falls beispielsweise gleich zu Beginn eine Startanimation ablaufen soll, dann kommt es dabei zu unangenehmen Aussetzern. Hinzu kommt, dass dieser Prozess unterschiedlich viel Zeit und Rechenkapazität in Anspruch nehmen kann, besonders wenn mehrere Facebook-Plugins (Like Button, Share Button, etc.) auf derselben Seite enthalten sind, kann der Browser gern mal mehrere Sekunden "einfrieren"!

Ein Blick in die Consolenumgebung (Netzwerkverkehr o. Laufzeitprofiler) verdeutlicht sehr schnell, dass eine überdimensional große Menge an Code und HTML-Elementen schon bei einem einzigen Facebook-Button-Plugin nachgeladen, initialisiert und ausgeführt werden. Im Prinzip sind solche Plugins ein Performance-Killer für jede Internetseite, gerade bei CPU-schwachen Systemen wie Tablets oder Smartphones.

Leider bietet das SDK selbst keine Steuerung die den Parser daran hindert nach dem Laden durch das ganze Dokument zu gehen. Eine alternative Lösung für dieses Problem ist, die <DIV>-Objekte, die der Parser umwandelt, zu entkapseln, indem die Attribute in den JavaScript-Teil und die Ziel-URL des Plugins (die sich bei mehreren Plugins desselben Typs lediglich ändert) in einen versteckten Container verschoben und erst bei Bedarf vom SDK-Parser dynamisch umgewandelt werden.

Hier ein Beispiel eines HTML-Ausschnitts, den Facebook beim Seitenstart nicht automatisch umwandeln wird:
<div id="content">

    <!-- 1. PART -->

    <div id="part_1">

        <!-- 

            CONTENT ...
 
        -->

        <div class="fb_plugin" style="display:none">

            www.my_domain.com/mysite.html?target=part_1

        </div>

    </div>

    <!-- 2. PART -->

    <div id="part_2">

        <!-- 

            CONTENT ...
 
        -->

        <div class="fb_plugin" style="display:none">

            www.my_domain.com/mysite.html?target=part_2

        </div>

    </div>

    <!-- 3. PART -->

    <div id="part_3">

        <!-- 

            CONTENT ...
 
        -->

        <div class="fb_plugin" style="display:none">

            www.my_domain.com/mysite.html?target=part_3

        </div>

    </div>

</div>
Auf diese Art können hintereinander beliebig viele Facebook-Buttons auf derselben Seite folgen. Damit die entkapselten <DIV>-Objekte als Facebook-Plugin wiederhergestellt werden können müssen die nachfolgenden Schritte vorgenommen werden. Zuerst ist ein DIV-Element mit der ID "fb-root" erforderlich. Optimalerweise wird dies direkt vor dem schließenden BODY-Tag platziert. Anschließend wird das Facebook SDK per Javascript geladen:
<div id="fb-root"></div>

<script>

    /* Import Facebook SDK */

    (function(){
    
        /* Starts after loaded */ 
    
        window.fbAsyncInit = function () {
    
            /* Init the FB JS SDK */
    
            FB.init({
    
                appId: 'YOUR_APP_ID',
                status: true,
                xfbml: true
            });
        };
        
        /* Load the SDK asynchronously */
    
        (function (d, s, id) {
    
            var js, fjs = d.getElementsByTagName(s)[0];
            if (d.getElementById(id)) return;
            js = d.createElement(s);
            js.id = id;
            js.src = "//connect.facebook.net/de_DE/all.js";
            fjs.parentNode.insertBefore(js, fjs);
    
        }(document, 'script', 'facebook-jssdk'));
    
    })();

</script>
Diese Funktion wandelt die versteckten DIV-Container in ein Facebook-Plugin um:
<script>

    /* Use this function to parse dynamically */

    function parseContent(id){

        var tmpRoot = document.getElementById(id);
        var tmpObj  = tmpRoot.getElementsByClassName('fb_plugin')[0];   

        /* Restore valid plugin notation */
                   
        tmpObj.innerHTML = 

            '<div data-send="true"
                  data-show-faces="false"
                  data-width="450"
                  data-href="' + tmpObj.innerHTML + '">
            </div>';

        tmpObj.style.display = 'block';       

        /* Parse a part of content dynamically */

        FB.XFBML.parse(tmpRoot);    
    }

</script>
Ein Beispiel wie diese Funktion aufgerufen wird:
<script>

    /* Example: */

    parseContent('part_1');

</script>
Durch einen Aufruf von "FB.XFBML.parse()" können beliebige Stellen an den Parser übermittelt werden, genau dann wenn sie benötigt werden (z.B. versteckter Inhalt einblenden, unmittelbar nach Startanimation, klappbare Boxen, usw.). Die Funktion "FB.XFBML.parse()" lässt sich übrigens auf dieselbe Weise auch auf AJAX-nachgeladenen Content anwenden.



Keine Kommentare:

Kommentar veröffentlichen