JavaScript-Mysterien: Teil 1: Warum haben manche (jQuery-)Libraries ein führendes Semikolon?

Dem ein oder anderen ist es vielleicht schon aufgefallen: Manche Libraries (nicht ausschließlich jQuery bezogen) haben ein führendes „;“, bevor der eigentliche Code losgeht. Das sieht dann so aus:

//Plugin Code WITH leading ;
;(function () {
console.log("plugin function called");
//source code
})();

Aber warum ist da ein führendes Semikolon? Oder wie mein Cousin letztens fragte:

ist dir eigentl aufgefallen das dein code mit einem traurigen smiley beginnt, ist dass n programmiererwitz?

Der gleiche Code würde auch ohne ; funktionieren und wäre einwandfrei. Das führende Semikolon hat den Sinn, um Code, der VORHER ausgeführt wird und möglicherweise kein abschließendes Semikolon hat, abzuschließen, damit der Plugin-Code selber ausgeführt wird. Gewöhnlich kennt man den Code nicht, den andere Entwickler schreiben :-).
Würde das Semikolon da nicht stehen und Code vorher kein abschließendes ; haben, so würde der Plugin-Code einen Fehler werfen.

Beispiel gefällig? Plugin-Code ohne führendes Semikolon

Dieser Code wirft einen Fehler, da der Code vor dem Plugin-Code kein abschließendes Semikolon hat:

//some source code WITHOUT trailing ;
console.log("test")
 
//Plugin Code WITHOUT leading ;
(function () {
console.log("plugin function called");
//source code
})();

Zum Überprüfen den Code einfach mit Copy&Paste in die Konsole packen und ausführen. Als Resultat folgt ein TypeError:

Plugin-Code mit führendem Semikolon

Führt man den gleichen Code nochmal aus, nur mit führendem Semikolon läuft der Code durch:

//some source code
console.log("test")
 
//Plugin Code WITH leading ;
;(function () {
console.log("plugin function called");
//source code
})();

Kein Wunder, der „fremde“ Code, der vorher ausgeführt wird, wird jetzt ordnungsgemäß mit einem Semikolon abgeschlossen.

Doppeltes Semikolon

Was passiert aber, wenn der vorherige Code bereits durch ein Semikolon abgeschlossen wird? Dann fügt der Plugin-Code ein weiteres Semikolon hinzu! Das ist doch unnötig! Ja, ist es – aber es führt zu keinem Fehler. Ein Semikolon schließt ein Statement in JavaScipt ab. Steht nichts davor, ist es ein leeres Statement:

//some source code WITH trailing ;
console.log("test");
 
//Plugin Code WITH leading ;
;(function () {
console.log("plugin function called");
//source code
})();

That’s it! JavaScript ermöglicht (leider) das Schreiben und Ausführen von Code ohne Semikolon – davon ist jedoch „strict“ abzuraten.

Weiterführende Literatur

Wer ein wenig mehr dazu lesen will, beispielsweise einen satirischen Artikel über Semikolon-Vermeidung, bitteschön: http://benalman.com/news/2013/01/advice-javascript-semicolon-haters/

Typo3 – Extensionmanager zeigt keine neuen Extensions mehr an – XAMPP – Teil II

Nachdem ich letztens schon das Problem hatte, dass der Extensionmanager keine Extensions mehr angezeigt hat und ich das auch erfolgreich lösen konnte kam nun das selbe Problem an anderer Stelle im Typo3 wieder auf mich zu. Ich wusste noch, dass irgendwo eine Liste aller Extensions filterbar war nach allen, die Updates haben und genau diese Liste habe ich gesucht:

Unter Extension Manager –> Extension Manager klickt man auf den Tab „Remote Repository“ und sollte meiner Meinung nach alle Extensions sehen, insbesondere nachdem ich ja wie im vorherigen Artikel beschrieben gerade alle Extensions aus dem Repository neu aktualisiert hatte.

Stattdessen erwartete mich eine leere Liste (im Screenshot bereits die aktualisierte Ansicht):

Der Fehler bzw. das Problem ist auch bekannt: http://lists.typo3.org/pipermail/typo3-english/2011-October/077511.html. Unter „Last Update“ (blau umrandet im nachfolgenden Bild) stand bei mir 30.05.2012, also mehr als ein Jahr alter Stand, daher waren auch nur ca. 4.500 Extensions im Repository. Die Liste aktualisiert man auf dem sehr kleinen unscheinbaren grün umrandeten Button:

Die Liste bleibt aber leer, auch nach der Aktualisierung. Gelb umrandet kommt die Info bei erfolgreichem Updaten und das Datum und die Anzahl der Extensions aktualisiert sicht (blau umrandet im Bild). Hier lassen sich noch Filter einstellen mit Klick auf den rot umrandeten Button: Alle Extensions (aktuelle Einstellung), alle installierten Extensions und alle Extensions, die Updates haben. Die letzten beiden Einstellungen funktionieren auch, nur die Liste mit allen Extensions bleibt leer.

Schaut man sich den Request genauer an:

Die Antwort sieht folgendermaßen aus:

[
    {
        "tid": 7,
        "action": "ExtDirect",
        "method": "getRemoteExtensionList",
        "type": "rpc",
        "result": {
            "length": 0,
            "data": []
        },
        "debug": ""
    }
]

Ich habe den Request in Postman, einer übrigens sehr zu empfehlenden Browsererweiterung für den Chrome, nachgebaut, um ein wenig an den Parametern zu spielen und dabei herausgefunden, dass der query-Parameter falsch befüllt wird bei der Auswahl „Alle Extensions“. Wie oben zu sehen ist query: „“, also leer, somit ist die Antwort auch richtig: Es gibt keine Extension mit den Namen „“. Wenn ich beim Filter „tt_“ eingebe, wird der Query-Parameter mit “ query: „tt_“ “ befüllt und die Liste aktualisiert sich korrekt. Ein * als Wildcard funktioniert bei der Anfrage perfekt, um alle Extensions anzuzeigen:

Voila! Alle Extensions wären dann auch da! 🙂

Typo3 – Extensionmanager zeigt keine neuen Extensions mehr an – XAMPP

Mal wieder Typo3, meist ein lokales Problem mit Installationen, die zum Testen auf XAMPP laufen. Ich sitze derzeit daran, eine Typo3-Installation von Version 5.4.16 auf die aktuelle Version 6.1.3 upzudaten und probiere dies erstmal lokal mit einer Spiegelung auf XAMPP.

Als ersten Schritt will ich alle vorhandenen Extensions aktualisieren. Dazu gehe ich in den Extensionmanager und suche (ich hab lang nichts mehr mit Typo3 gemacht) den Button, um die Extensionsliste aus dem TER zu aktualisieren.

Unter „Import extensions“ findet man dann auch diesen grauen, unscheinbaren Button „Retrieve/Update“, neben welchem steht von wann die derzeitige Liste ist, in meinem Fall habe ich schon aktualisiert, daher steht dort der 16.8.2013. Konkret handelt es sich dabei um die Datei „typo3temp/extensions.xml.gz“, welche aktualisiert wird. Diese kann man auch löschen oder umbenennen, um sicher zu gehen, dass wirklich eine aktuelle Datei heruntergeladen wird.

Bevor ich jedoch erfolgreich aktualisieren konnte, kam einfach nur ein grauer Screen oder weißer Bildschirm, nachdem ich auf „Retrieve/Update“ gedrückt hatte – sonst nichts. Über die Developer-Tools im Chrome sieht man unter „Network“ für diesen Request folgendes:

500 –> Internal Server Error, die Dauer des Requests findet man unter „Time“: 30,07 Sekunden. Verdächtig :). Die Standard-Ausführungszeit für Skripte ist auf 30 Sekunden begrenzt.

Abhilfe schafft hier das Hochsetzen der PHP-Einstellung „max_execution_time“ in der php.ini, welche man normalerweise unter „xampp/php/php.ini“ findet. Wer will kann diesen Wert jetzt solange hochsetzen, bis der Request nicht mehr fehlschlägt, ich hab ihn einfach auf 600 Sekunden gesetzt: „max_execution_time = 600“, 10 Minuten sollten ausreichend Zeit sein :). Der letzte Schritt ist der Wichtigste: Apache neu starten!

Feedback erwünscht!

Eigene Bildgrößen in der WordPress-Mediathek auswählbar machen

Dass man bei WordPress relativ leicht eigene Bildgrößen einstellen kann und in seinem Template einbinden kann ist meiner Meinung nach recht bekannt. Vor kurzem brauchte ich jedoch die Möglichkeit, dass der Anwender eben diese eigens angelegten Bildgrößen auch selber auswählen kann und sich nicht nur zwischen den vordefinierten Bildgrößen entscheiden muss:
WordPress-Mediathek Standard-Bildgrößen
Dazu bietet WordPress einen schönen Filter, welcher leicht zu implementieren ist. Vorerst jedoch muss man die Voraussetzung schaffen, um eigene Bildgrößen anlegen zu können. Der nachfolgende Code erklärt, wie man sowohl eigene Bildgrößen definiert und wie man diese in der Mediathek beim Bild einfügen – Dialog auswählbar macht. Er ist in die functions.php-Datei des Themes einzubauen:

/**
 * Enable support for Post Thumbnails 
 * (Support für eigene Bildgrößen einschalten)
 */
add_theme_support( 'post-thumbnails' );
 
/**
 * Add custom image sizes 
 * (Eigene Bildgrößen hinzufügen)
 */
add_action( 'after_setup_theme', 'af_add_custom_image_sizes' );
function af_add_custom_image_sizes() {
              //params: 'size-name', width, height, crop
    add_image_size( 'home-featured-image', 306, 152, false );
    add_image_size( 'imageslider-preview', 180, 240, false);
    add_image_size( 'imageslider-view', 99999, 600, false);
}
/**
 * Make custom image sizes available via media manager 
 * (Eigene Bildgrößen in der Mediathek verfügbar machen)
 */
add_filter( 'image_size_names_choose', 'custom_image_sizes_choose' );
function custom_image_sizes_choose( $sizes ) {
	$custom_sizes = array(
			'home-featured-image' => 'Startseitenbilder',
			'imageslider-preview' => 'Slider-Vorschau',
			'imageslider-view' => 'Slider-Bild'
	);
	return array_merge( $sizes, $custom_sizes );
}

Wichtig ist, dass man die Bezeichnung des ersten Parameters bei add_image_size gleich setzt zu den Keys im Array $custom_sizes. Am besten speichert man sich diese in einer eigenen Variable.
Im Template kann man dann über die Bezeichnungen die entsprechende Bildgröße einbinden:

/**
 * into the loop
 * (innerhalb des Loops)
 */
if(has_post_thumbnail()){
	the_post_thumbnail('home-featured-image');
}
/**
 * somewhere else i.e. outside the loop
 * woanders, z.B. außerhalb des Loops
 */
if(has_post_thumbnail($post->ID)){
	echo get_the_post_thumbnail($post->ID, 'home-featured-image');
}

Auch kann man die eigene Bildgröße in allen Bildfunktionen verwenden, die $size als Parameter empfangen können, beispielsweise wp_get_attachment_image(), wp_get_attachment_image_src() oder wp_get_attachment_link(). Die letzten 3 Funktionen benötigen jedoch eine Attachment-ID als Pflichtparameter (siehe Dokuverlinkungen).

Das Ergebnis in meinem Beispiel kann nun folgendermaßen aussehen:

Sieht man hinter den eigenen Bildgrößen keine Dateimaße und sind die Radio-Buttons ausgegraut und nicht anklickbar, so existiert diese Datei nicht in diesem Format. Gründe dafür können sein, dass sie zu klein ist für die eingestellte Bildgröße und somit nicht erstellt werden konnte oder dass die Datei hochgeladen wurde, bevor man die eigenen Bilddateigrößen festgelegt hat. Im Normalfall sollte jedoch folgende Ansicht danach vorhanden sein:
WordPress eigene Bilddateigrößen in der Mediathek auswählen

Viel Erfolg beim Umsetzen! Feedback und Verbesserungsvorschläge immer erwünscht! 🙂

Eigenen JavaScript-Code in das WordPress-Backend einbinden

Beim letzten Projekt benötigte ich JavaScript-Code, um das Backend ein wenig zu modifizieren. Hier will ich kurz anhand eines Beispiels festhalten, wie ich das realisiert habe.
Konkret ging es darum, dass ich im Backend ein Feld hatte, welches den Farbcode eines Elements im DOM bestimmen sollte. Der User sollte dazu aus einer vorgegebenen Liste mit Farbwerten einen auswählen und das DOM-Element sollte mittels Inline-CSS die entsprechende Hintergrundfarbe annehmen:

Normale Select-Option-HTML-Liste

Diese Liste wurde via Backend durch das (absolut empfehlenswerte!) Plugin Types eingepflegt und die Option-Values enthielten den CSS-kompatiblen Farbcode:

Da die Farbwerte jedoch teils recht nah beieinanderlagen, wollte ich die Select-Liste mit der entsprechenden Hintergrundfarbe unterlegen, so dass der User im Backend sieht, welchen Farbton er auswählt.
Das Plugin generiert folgenden HTML-Code für die Select-Liste:

<select id="wpcf-select-pagecolor-1178946369" name="wpcf[pagecolor]" class="wpcf-form-select form-select select">
	<option value="white" class="wpcf-form-option form-option option">Weiß</option>
	<option value="#cc3f14" class="wpcf-form-option form-option option">Rotorange</option>
	<option value="red" class="wpcf-form-option form-option option">Rot</option>
	<option value="#ffd900" class="wpcf-form-option form-option option">Dunkelgelb</option>
	<option value="#6f0" class="wpcf-form-option form-option option">Leuchtend Hellgrün</option>
	<option value="#24ff21" class="wpcf-form-option form-option option">Hellgrün</option>
	<option value="#0580ff" class="wpcf-form-option form-option option">Hellblau</option>
	<option value="#b2ffff" class="wpcf-form-option form-option option">Helltürkis</option>
	<option value="#ba87ff" class="wpcf-form-option form-option option">Hellviolett</option>
	<option value="#f200c2" class="wpcf-form-option form-option option">Pink</option>
</select>

 

Das Ergebnis sollte so aussehen:

Eingefärbte HTML-Select-Option-Liste

Dazu wollte ich mittels jQuery die value’s der option-Tags auslesen, also die Werte, die ich via Types CSS-kompatibel im Backend vorher eingepflegt hatte.

Folgender Code half hier aus:

<!--?php 
function custom_admin_js() {
	$script = '<script type="text/javascript"-->// &lt; ![CDATA['; 	$script .= ' 	jQuery(document).ready( function(){ 		var setBackground = function(){ 			jQuery("select[name=\"wpcf[pagecolor]\"]").css("background-color",  				jQuery("select[name=\"wpcf[pagecolor]\"]").find("option:selected").val() 			)}; 		setBackground(); 		jQuery("select[name=\"wpcf[pagecolor]\"]").find("option").each(function(){ 			jQuery(this).css("background-color", jQuery(this).val()); 		}); 		jQuery("select[name=\"wpcf[pagecolor]\"]").on("change",setBackground); 	}); 	'; 	$script .= ' // ]]&gt;';
	echo $script;
}
add_action('admin_head', 'custom_admin_js');
?&gt;

Wichtig hier ist der add_action – Aufruf, der als 2. Parameter den Namen der Funktion bekommt, die obenstehend deklariert ist und den JavaScript-Code enthält. Dort kann natürlich auch jeder andere Code stehen.

In meinem Fall benötigte ich den obenstehenden jQuery-Code, welcher hier nochmal genauer erläutert wird:

jQuery(document).ready( function(){
	//save background-color setting function for select-element into variable
	var setBackground = function(){
		jQuery("select[name=\"wpcf[pagecolor]\"]").css("background-color", 
			jQuery("select[name=\"wpcf[pagecolor]\"]").find("option:selected").val()
		)};
 
	//call the function to set the background color of the select-element
	setBackground();
 
	//set background-color for all option-tags
	jQuery("select[name=\"wpcf[pagecolor]\"]").find("option").each(function(){
		jQuery(this).css("background-color", jQuery(this).val());
	});
 
	//bind change-event to select-element
	jQuery("select[name=\"wpcf[pagecolor]\"]").on("change",setBackground);
});

Als jQuery-Selector konnte ich auf keine ID zugreifen, da die ID vom Types-Plugin generiert wurde und in jeder Installation anders wäre, daher nutzte ich folgenden Selektor:

select[name="wpcf[pagecolor]"]

Dieser war für meine Zwecke ausreichend, da er eindeutig war. In der Variable setBackground speichere ich mir eine Funktion, die das in der Select-Liste selektierte Option-Tag ausliest und den value-Wert als Hintergrundfarbe des Select-Elements setzt. Danach rufe ich die Funktion auch gleich auf, um den Wert zu setzen. Als rein anonyme Funktion kann ich sie jedoch nicht nutzen, da ich auch bei Farbwechsel den neu ausgewählten Wert setzen wollte. Dazu dient die letzte Zeile, in welcher der Event-Handler „onchange“ die Funktion „setBackground()“ bei Wechsel des Option-Elements aufruft. Wichtig hierbei ist, dass die Funktion ohne () übergeben wird, da hier nur die Referenz auf die Funktion notwendig ist. Würde man die Klammern mit übergeben, würde die Funktion direkt an dieser Stelle im Code ausgeführt werden und nicht erst bei Aufruf des Change-Events.

Das wars dann auch schon!
Anregungen, Kommentare und Verbesserungsvorschläge sind erwünscht! 🙂