Ein Tutorial, das ein Basiswissen liefern soll, wie alles so funktioniert, ungefähr, oder doch nicht und warum eigentlich dann doch irgendwie... Es beschäftigt sich nicht mit CSS, HTML, Modulpositionen etc. eines Template im Detail. Es geht meist um den Template-<HEAD>-Bereich , in dem z.B. Skripte geladen werden. Aber wie kommen die da hin? Das hier ist ein "Mach-mal-und-probier-dann-selbst-Tutorial".

Anlass für dieses Tutorial, war eine der vielen Anfragen in einem Joomla-Portal, wo ein Anfänger mithilfe eines relativ untauglichen Video-Tutorials, das aber trotzdem ein paar Hundert Daumen hatte, versuchte, sich in die Joomla3-Templateentwicklung einzuarbeiten und das mit Bootstrap 3 (so sah das Tutorial das vor), während Joomla noch mit Bootstrap 2 unterwegs ist. Der Hinweis, sich mal mit dem joomlaeigenen Protostar-Template zu beschäftigen und erst mal BS 3 zu vergessen, wurde in etwa so beantwortet, dass das Protostar zu kompliziert sei.

Problem des Fragenden war schlicht, dass seine händisch eingefügten <SCRIPT>- und <LINK>-Tags nicht funktionierten wie erwartet, auch bei seinem vollkommen reduzierten Template nicht, weil Joomla zusätzlich Kram in den <HEAD>-Tag packt.

In diesem 1. Teil versuche ich klar zu machen, was in so einem Joomla3-Template-<HEAD> eigentlich passiert und warum so viel unerwartet. Wieso da Sachen drin stehen, die der Templateersteller gar nicht "angefordert" hat und die deshalb Konflikte machen könnten.

Wenn Sie das alles nicht die Bohne interessiert und Sie nur wissen wollen, wie man Joomla 3 z.B. Bootstrap 3 korrekt unterjubelt, gehen Sie auf diese Seite unter Überschrift "Jetzt aber mal richtig": Joomla 3 Templates verstehen - HEAD - Teil2: Bootstrap Override

Vorbereitungen

Installiere ein Joomla 3.4.1 auf XAMPP oder online

Selbstverständlich kannst du auch eine neuere Version versuchen, sowohl Joomla als auch XAMPP bzw. PHP. Eigentlich empfehle ich das sogar. Der schon alte Tutorial-Text geht aber von 3.4.1 aus, was z.B. den Override unten anbelangt. Joomla und auch das verwendete Protostar-Template ändern sich stetig. Du kannst auch fragen bei Problemen!

https://github.com/joomla/joomla-cms/releases ist eine verlässliche Quelle. Nimm das Paket Joomla_3.4.1_Stable-Full_Package.zip.

Seit Joomla 3.7 hat sich etwas bei der Verwendung der unten beschriebenen JHtml-Methoden script() und stylesheet() geändert. Beachte hierzu die jeweiligen Info-Einschübe. Beachte auch, dass die 3.7-Varianten nicht rückwärtskompatibel sind, also in Versionen kleiner 3.7 NICHT funktionieren.

Bei der Installation (!)
  • nur Pflichtfelder füllen, also die mit Sternchen,
  • keine Demodaten mitinstallieren.
Nach der Installation deutsche Sprache installieren und als Standard festlegen

Deutsche Sprache nach Joomla-Installation nachinstallieren und als Standardsprache festlegen

Templatekopie anlegen

Template-Editor im Backend finden

Du kannst die Dateien natürlich auch mit eigenen Werkzeugen bearbeiten, aber für dieses Tutorial ist der Editor im Joomla-Backend ganz praktisch.

Erweiterungen > Templates > Klicke in Spalte "Template", nicht Spalte "Stil", auf den Templatenamen "Protostartest"

Hinweis zu Pfaden

In den Code-Beispielen unten sieht man häufig ein /joomla34/, was bei dir wahrscheinlich anders lautet, wenn du wie ich eine lokale Joomla-Installation mit XAMPP verwendest oder gar nicht da ist. Denks dir weg...

Template-Grundgerüst

Jetzt machen wir unser neues Template "Protostartest" gleich kaputt. Wir reduzieren es auf ein minimales Grundgerüst.

Im Template-Editor findet man links die Dateien, die man durch Anklicken zur Bearbeitung öffnet.

Öffne die /templates/protostartest/index.php und reduziere sie wie folgt. Fast alles raus. Dann speichern.


<?php defined('_JEXEC') or die; ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->language; ?>" lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>"> <head> </head> <body> </body> </html>

Gehe ins Frontend und rufe deine gänzlich weiße Seite auf. Zeige dir den HTML-Quelltext der Seite an, z.B. durch Rechtsklick auf die Seite.

In vielen Browsern kann man sich den Seitenquelltext in einem neuen Tabulator anzeigen lassen. Meist geht das auch mit Tastenkombination STRG+U oder man findet was im Browsermenü.

Wir sehen im HTML-Quelltext, dass Joomla bereits einige Arbeit erledigt hat, beispielsweise die aktuelle Seitensprache eingesetzt hat, bei mir de-de für "Deutsch wie in Deutschland gesprochen". Und auch die passende Schreibrichtung ltr für "left to right".


<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de-de" lang="de-de" dir="ltr"> <head> </head> <body> </body> </html>

Stelle für weitere Erleuchtung im Joomla-Backend unter Erweiterungen > Sprachen > Installiert-Site die Standardsprache des Frontends auf Englisch um.

Natürlich ändern sich beim Ändern der "Installierten Sprache" nicht alle Texte der Seite, aber z.B. die Beschriftungen von Login-Feldern.

Lädt man die Seiten-Quelltext-Ansicht im Browser jetzt neu, beispielsweise mit Taste STRG+F5, um auch gleich den Browsercache zu löschen, sieht man die automatischen Veränderungen (en-gb) im <HTML>-Tag unserer Testseite.


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xml:lang="en-gb"
      lang="en-gb"
      dir="ltr">
<head>
</head>
<body>
</body>
</html>

<HEAD>-Daten von Joomla einsetzen lassen

Damit sind Zeilen zwischen den Tags <head> und </head> gemeint. Wir ergänzen unser Grundgerüst im Template-Editor um eine einzelne Zeile <jdoc:include type="head" />:


<?php
defined('_JEXEC') or die;
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xml:lang="<?php echo $this->language; ?>"
      lang="<?php echo $this->language; ?>"
      dir="<?php echo $this->direction; ?>">
<head>
  <jdoc:include type="head" />
</head>
<body>
</body>
</html>

Solche jdoc-Dinger <jdoc:include type="xyz" /> wie in Zeile 10 sind typisch für Joomla-Templates. Man findet so was in einem "normalen" Joomla-Template an diversen Stellen. Uns reicht im Moment das Ding mit dem type="head", der nebenbei erwähnt, in einem Template nur 1x vorkommen darf im Unterschied zu anderen jdoc-Typen. Sonst Katastrophe...

Wir werfen wieder einen Blick in unseren neuen Quelltext im Frontend:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xml:lang="de-de"
      lang="de-de"
      dir="ltr">
<head>
    <base href="http://localhost/joomla34/" />
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <meta name="generator" content="Joomla! - Open Source Content Management" />
  <title>Home</title>
  <link href="http://localhost/joomla34/index.php" rel="canonical" />


  <link href="/joomla34/index.php?format=feed&amp;type=rss" rel="alternate" type="application/rss+xml" title="RSS 2.0" />
  <link href="/joomla34/index.php?format=feed&amp;type=atom" rel="alternate" type="application/atom+xml" title="Atom 1.0" />
  <link href="/joomla34/templates/protostartest/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />
  <script src="/joomla34/media/jui/js/jquery.min.js" type="text/javascript"></script>
  <script src="/joomla34/media/jui/js/jquery-noconflict.js" type="text/javascript"></script>
  <script src="/joomla34/media/jui/js/jquery-migrate.min.js" type="text/javascript"></script>
  <script src="/joomla34/media/system/js/caption.js" type="text/javascript"></script>
  <script type="text/javascript">
jQuery(window).on('load',  function() {
 new JCaption('img.caption');
});
  </script>
</head>
<body>
</body>
</html>

Die ersten paar Zeilen im <HEAD> sind OK, sag ich mal (ich habe sie mit ein paar Leerzeilen darunter abgesetzt), ein <BASE>-Tag, ein paar <META>-Tags, ein <TITLE>-Tag, ein canonical-<LINK> (der in aktuelleren Joomla-Versionen nicht immer auftaucht), etwas weiter unten im Wust ein favicon.ico. So was gehört in eine Webseite, mal mehr davon, mal weniger.

Aber dann: Was soll das? Alles "zugemüllt" mit <link... und <script... - Kram, was diverse Javascript-Dateien und Feed-Schmarrn einbindet, manchmal auch noch CSS-Dateien, obwohl unsere Seite nach wie vor weiß ist, keine Inhalte hat, die das brauchen könnten.

Tja, und da sind wir beim Thema. Nicht unser Template hat dieses Zeugs angefordert (hätte es natürlich auch können, sehen wir später), sondern irgendeine Erweiterung oder mehrere, die diese Dateien benötigen, haben Zeilen in ihrem PHP-Code sonstwo, die den <HEAD> vorab befüllen, den Joomla im Template dann via <jdoc:include type="head" /> ausgibt. Magie, Magie...

Erweiterung? Wo denn? Wir haben doch extra eine Seite ohne Demodaten etc. installiert.

Wenn Du in der Joomla-Administration im Menü Menüs nachsiehst, stellst du fest, obwohl wir ein Joomla ohne Demodaten installiert haben, dass es dennoch 1 Startseiteneintrag gibt, vom Typ "Hauptbeiträge" und der wird von der Komponente, der Erweiterung com_content (Inhalte) "abgewickelt". Das ist also unser Übeltäter. Irgendwo (das Problem!) in ihrem Code gibt diese Komponente Befehle aus, den <HEAD> mit sonstwas zu befüllen, was diese Komponente im Normalfall braucht.

Im Backend entdeckt: Der "Übeltäter". Der Menüeintrag "Beiträge > Haupteinträge" der Erweiterung "com_content"

Dieser Menüeintrag "erwartet" quasi, dass er auf der Startseite zur Anzeige kommen wird und damit er gut aussieht und richtig funktioniert, befüllt er den <HEAD> mit JavaScript, gelegentlich auch CSS, mal per Dateien, die eingebunden werdem, mal mit so genannten Inline-Skripten (siehe oben jQuery(window).on('load', function()... ) oder Inline-Styles. Er, respektive die Erweiterung dahinter, verlässt sich dabei nicht auf das Template, das diesen Kram vielleicht oder vielleicht auch nicht lädt. Das Template hat keine Ahnung, mit was es später im Detail befüllt wird und die Erweiterungen haben keine Ahnung wie das Template aufgebaut ist und was es lädt oder nicht...

Inline-Styles? Damit meine ich, und akademisch nicht ganz richtig, CSS-Regeln und JavaScript-Schnipsel, die nicht aus einer CSS- oder JS-Datei bezogen werden, sondern irgendwo direkt lesbar im Quelltext zu sehen sind. In obigem Beispiel sieht man davon keine, aber Joomla-Erweiterungen können auch solche einsetzen.

Dass in deinem "kastrierten" Testtemplate eine entscheidende Zeile für die Anzeige des Komponenten-Contents fehlt (<jdoc:include type="component" />), also für die Ausgabe der Haupteinträge, weiß weder der Menüeintrag noch Joomla zum Zeitpunkt, wo der <HEAD>-Inhalt vorab zusammengestellt wird.

Ergo: Erweiterungen, Module, Komponenten, Plugins können am Template vorbei, <HEAD>-Daten für ihre Belange einfügen, egal, ob man das nun als Template-Ersteller will oder nicht oder braucht oder sonstwas. Sch... Joomla!

Also mal raus mit dem Kram (zumindest bei unserer rudimentären Seite schaffen wir das)

Gehe in den oben gezeigten Menüeintrag "Home" > Tabulator "Integration" > stelle "Feedlink" auf "Verbergen" > Speichern.

Im Frontend den Seitenquelltext neu laden. Schon sind 2 Zeilen weniger, die beiden <LINK> mit dem format=feed.

Gehe in den Template-Editor > Tabulator "Overrides erstellen" > Klicke "com_content" > dann auf "featured" (was "Haupteinträge" bedeutet und zu unserem Home-Menüeintrag gehört). Das Override wird automatisch erstellt, in deinem Template-Ordner /protostartest/html/com_content/. Siehe auf der linken Seite in der Dateiübersicht im Template-Editor.

Beachte, um Verwirrung zu vermeiden: Auch, wenn sich dieses Override jetzt im Templateordner befindet, ist das KEINE Templatedatei im eigentlichen Sinne. Sie gehört zur Erweiterung. Wenn wir die neuen Override-Dateien bearbeiten, bearbeiten wir die Komponente com_content. Aber so, dass die Bearbeitung auch das nächste Joomla-Update überlebt, ohne überschrieben zu werden. Oder pauschaler, da ja nicht nur Komponenten-Overrides erstellt werden können, sondern ebenso für Module, (derzeit wenige) Plugins: bearbeiten wir die betreffende Erweiterung update-sicher.

Kleiner Hinweis für neuere Joomla-3-Versionen: Wenn schon ein Override existiert und man noch mal einen erstellt, wird der zweite mit einem Datumsstempel im Dateinamen angelegt. Dieser zweite Override ist funktionslos, so lange du den ersten nicht löscht und den zweiten umbenennst (Datumsteil raus). Das ist zumindest für mich verwirrend. Ich hätte das anders gemacht ;-)

Weiter in den Tabulator "Editor" > klicke/öffne links den Ordner /html/ > dann /com_content/featured/ > öffne die Datei default.php. Im Editor-Bereich wird der Code nun angezeigt..

Deaktiviere wie im Bild zu sehen die  PHP-Zeile JHtml::_('behavior.caption'); durch ein vorangestelltes Gatterzeichen (oder heißt es Rautezeichen?).

caption-deaktivieren.jpg

Speichern und der übliche Blick im Frontend in den Seitenquelltext, den du neu geladen hast. Wow! Kleine Code-Aktion, große Wirkung:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xml:lang="de-de"
      lang="de-de"
      dir="ltr">
<head>
    <base href="http://localhost/joomla34/" />
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <meta name="generator" content="Joomla! - Open Source Content Management" />
  <title>Home</title>
  <link href="http://localhost/joomla34/index.php" rel="canonical" />
  <link href="/joomla34/templates/protostartest/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />

</head>
<body>
</body>
</html>

Dieses JHtml::_('behavior.caption'); ist nur eine mögliche Zeile von vielen ähnlichen in der Joomla-Programmierung, die sowohl JQuery als auch weitere Dateien und Skript-Schnipsel lädt. Mal mehr, mal weniger, um eine bestimmte Funktionalität auf der Seite verfügbar zu machen. Schicke (na ja, man kann streiten) MouseOver-Tooltips z.B.

Unseren Override lassen wir so wie er ist, also mit deaktivierter Zeile und können ihn verlassen.

Eine weitere Demo: Erweiterungen > Module > Knopf "Neu" > Modul vom Typ "Suchindex" > Position "Banner" > Tabulator "Menüzuweisung" > "Auf allen Seiten".

Wenn du im Frontend den Quelltext anschaust, ist da... schlichtweg mal gar nix Neues...

In der index.php unseres Template-Fragments fügen wir deshalb eine Modulposition banner ein, weil die haben wir zuoberst ja radikal entfernt. Setze die Zeile <jdoc:include type="modules" name="banner" style="xhtml" /> innerhalb des <BODY> ein:

...
<body>
  <jdoc:include type="modules" name="banner" style="xhtml" />
</body>
...

Seite im Frontend neu laden und gucke den Quelltext. Man sieht, dass dieses Modul auch Bootstrap-JavaScript geladen hat (bootstrap.min.js). Eben, weil es es braucht und sich nicht auf das Template verlassen will.

Deaktiviere das Modul im Backend, und alles "ist wieder gut" im Seitenquelltext. Kein "Kram" mehr.

Die magische JHtml-Klasse

Nachdem uns jetzt keine Erweiterung mehr dazwischenpfuscht und nur noch das Template regiert, setzen wir exakt die Zeile JHtml::_('behavior.caption'); die wir mit dem #-Zeichen im featured-Override derzeit deaktiviert haben im Template selbst ein; im PHP-Block vor der so genannten DOCTYPE-Deklaration der index.php.


<?php defined('_JEXEC') or die; JHtml::_('behavior.caption'); ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->language; ?>" lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>"> <head> <jdoc:include type="head" /> </head> <body> <jdoc:include type="modules" name="banner" style="xhtml" /> </body> </html>

Die Wirkung ist die selbe. Auch im Template eingesetzt, holt sich diese Zeile, die eine bestimmte Funktionalität bereit stellt, seine CSS-Dateien, Java-Scriptdateien, Inline-Script... in's gerenderte Template.

Und was ist, wenn wir die Zeile sowohl im Template haben, als auch in unserem featured-Override von oben? Lädt dann Joomla alles doppelt? Probiere es aus und aktiviere die Zeile im obigen Haupteinträge-Override wieder, indem du das Gatterzeichen # wieder entfernst und speicherst.

Im Override /html/com_content/featured/default.php die magische JHtml-Zeile wieder aktivieren

Blick in den Seitenquelltext sagt uns: Nein, Joomla lädt nichts doppelt.

Und das ist das "Geniale" an diesen Zeilen. Ich kann sie überall dort vorsorglich einsetzen, versehentlich sogar mehrfach, wo ich nicht sicher sein kann, dass Template oder irgendwelche anderen Erweiterungen sie bereits eingesetzt haben.

Setze nun das Gatterzeichen in den Haupteinträge-Override wieder ein, damit wir "im Template wieder unter uns sind".

Das geht sogar noch weiter. Wenn man sich den Seitenquelltext mal ansieht, lädt unsere Zeile JHtml::_('behavior.caption'); auch JQuery (jquery.min.js), eine in Joomla 3 nicht wegzudenkende JavaScript-Bibliothek. Sehr viele Erweiterungen geben Befehl JQuery zu laden.

Wenn man nur die JQuery-Bibliothek benötigt, also ohne dies caption.js-Gedöns, kann man das mit folgender, alleiniger Zeile erreichen


JHtml::_('jquery.framework');

Will man die Bootstrap-Bibliothek laden (ebenfalls in Joomla 3 kaum wegzudenken, wenn auch eine mittlerweile total veraltete Version 2), verwendet man diese Zeile, was ebenfalls viele Erweiterungen machen:


JHtml::_('bootstrap.framework');

Die lädt wiederum JQuery gleich mit, weil ohne macht Bootstrap-JavaScript kaum Sinn für BS-Versionen 2 bis 4.

Verwirrung? Geht ja nur um's Grundprinzip. Jeder und alles in Joomla darf sich je nach Bedürfnissen in den <HEAD> laden wasimmer gewünscht.

Spiel mal im Template-Editor mit folgendem Gerüst herum und deaktiviere JHtml-Zeilen wechselweise, indem du jeweils das Gatterzeichen # vor die Zeilen setzt oder nicht (und das Speichern der index.php nicht vergisst, wie ich eben). Du wirst feststellen, dass JQuery immer nur 1x geladen wird, obwohl mehrere der Zeilen für sich diese Bibliothek anfordern und eben ggf. weitere Dateien. Kannst auch die Zeilen mal verdoppeln, ob dann was doppelt geladen wird... Oder umsortieren.


<?php
defined('_JEXEC') or die;

JHtml::_('behavior.caption');
JHtml::_('jquery.framework');
JHtml::_('bootstrap.framework');
JHtml::_('bootstrap.loadCss');
JHtml::_('stylesheet', 'media/mediamanager.css', array(), true);
JHtml::_('behavior.framework', true);

?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xml:lang="<?php echo $this->language; ?>"
      lang="<?php echo $this->language; ?>"
      dir="<?php echo $this->direction; ?>">
<head>
  <jdoc:include type="head" />
</head>
<body>
  <jdoc:include type="modules" name="banner" style="xhtml" />
</body>
</html>

Seit Joomla 3.7. lautet die Zeile 8 so:

JHtml::_('stylesheet', 'media/mediamanager.css', array('relative' => true));

Kannst zusätzlich das Suchindex-Modul und/oder den Featured-Override wieder "scharf schalten". Vergiss danach für folgende Schritte das Deaktivieren nicht!

Es gibt keine Ladekonflikte. "Sch... Joomla"? Schlaues Joomla!

So, jetzt lass mal alle Zeilen auf einmal aktiv und wirf einen Blick in den Seitenquelltext:

...

<link rel="stylesheet" href="/joomla34/media/media/css/mediamanager.css" type="text/css" />
<link rel="stylesheet" href="/joomla34/media/jui/css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="/joomla34/media/jui/css/bootstrap-responsive.min.css" type="text/css" />
<link rel="stylesheet" href="/joomla34/media/jui/css/bootstrap-extended.css" type="text/css" />
<script src="/joomla34/media/jui/js/jquery.min.js" type="text/javascript"></script>
<script src="/joomla34/media/jui/js/jquery-noconflict.js" type="text/javascript"></script>
<script src="/joomla34/media/jui/js/jquery-migrate.min.js" type="text/javascript"></script>
<script src="/joomla34/media/system/js/caption.js" type="text/javascript"></script>
<script src="/joomla34/media/jui/js/bootstrap.min.js" type="text/javascript"></script>
<script src="/joomla34/media/system/js/mootools-core.js" type="text/javascript"></script>
<script src="/joomla34/media/system/js/core.js" type="text/javascript"></script>
<script src="/joomla34/media/system/js/mootools-more.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery(window).on('load',  function() {
 new JCaption('img.caption');
});
</script>

...

Du stellst fest, dass Joomla sich auch um die richtige Reihenfolge kümmert. Sowohl Trennung CSS-Block, dann JS-Dateien-Block, dann erst Inline-Kram als auch "kluge" Sortieung, in den Blöcken selbst. Besonders wichtig ist das bei den JavaScript Dateien. Wenn Bootstrap von JQuery abhängt, wenn ersteres also zweiteres "braucht", dann muss zweiteres vor ersterem geladen werden.

Du siehst, arbeitet man joomlakonform, wird einem viel Forscherei abgenommen. Selbstverständlich kann man auch <SCRIPT>- und <LINK>-Zeugs zusätzlich "händisch" in sein Template einsetzen, aber es muss eben an der richtigen Stelle sein.

Und wozu etwas einbinden, was Joomla eh schon dabei hat und simpel richtig im <HEAD> einsetzt. Der häufigste Fehler übrigens, nicht nur in Templates.

Also, JavaScript-Dateien müssen meist in der richtigen Reihenfolge geladen werden, damit sie alle nebeneinander funktionieren können. Macht man hier was falsch, kann die ganze Seite kollabieren, weil sich solche JavaScript-Fehler evtl. fortpflanzen. Slider und Captcha und Dingsbums funktionieren nicht mehr, obwohl die gar nichts dafür können, sondern irgendein kleines Scroll-To-Top-Skript, das unachtsam sonstwo eingesetzt wurde.

Ebenso gibt Joomla die drei CSS-Dateien von Bootstrap (Zeilen 4-6 im letzten Code) in richtiger Reihenfolge aus.

Aber, wenn du mal die beiden Zeilen, die lediglich CSS-Dateien laden umsortierst, da ändert sich die Reihenfolge dann doch.

JHtml::_('stylesheet', 'media/mediamanager.css', array(), true);
JHtml::_('bootstrap.loadCss');

Seit Joomla 3.7. lauten die 2 Zeilen so:

JHtml::_('stylesheet', 'media/mediamanager.css', array('relative' => true));
JHtml::_('bootstrap.loadCss');

Also im Kopf behalten: Es gibt auch Situationen, in denen man sich durchaus Gedanken über die Reihenfolge der JHtml-Zeilen machen sollte/muss.

Die JHtml-Methoden stylesheet (CSS) und script (JS)

In Joomla 4 wurde ein "Professoren-Monster" in den Core eingeführt, das in Teilen inkompatibel mit der für Normalsterbliche stinkeinfachen Verwendung dieser beiden Methoden ist. Es wäre besser gewesen, diese beiden Methoden in Joomla 4 komplett zu entfernen, anstatt sie neben dem Monster drinnen zu behalten. Kurz: Sie funktionieren noch, aber mit Unwägbarkeiten behaftet.

Zwei JHtml-Zeilen stelle ich noch vor und, was man damit machen kann. Deaktiviere dafür in der index.php die anderen Zeilen mit dem Gatterzeichen # und füge dann dies ein:

JHtml::_('stylesheet', 'com_finder/indexer.css', array(), true);

Das array() muss uns mal nicht jucken. Gehört halt da hin, wenn man danach noch dieses true eingeben muss, was in diesem Fall unbedingt nötig ist!

Seit Joomla 3.7. lautet die Zeile wie folgt. Der Zweck des true ist damit etwas offensichtlicher und das "blöde" leere array() kann weg bleiben.

JHtml::_('stylesheet', 'com_finder/indexer.css', array('relative' => true));

Da steht als 2. Parameter (Argument) ein Pfad com_finder/indexer.css . Jetzt kannst du gerne mal suchen gehen, ob du die Datei indexer.css in deinem Joomla irgendwo findest in einem Ordner /com_finder/. Is mal nich. Aber im Seitenquelltext steht wundersamerweise ein Pfad mit einem media/ und einem css/ dazwischen

media/com_finder/css/indexer.css

und tatsächlich, der existiert in meiner Joomla-Installation inklusive Datei. Das true macht also, dass Joomla im Ordner media/ sucht, und darin im Ordner com_finder/css . Wenn es darin die Datei gibt, alles gut, Datei einbinden. Wenn nicht, passiert nichts.

Probier ich also zum Vergleich mal diesen eigentlich richtigen Pfad, aber eben mit true, verwirre ich das System und es wird nichts im Seitenquelltext angezeigt.

JHtml::_('stylesheet', 'media/com_finder/css/indexer.css', array(), true);

Seit Joomla 3.7. lautet die Zeile wie folgt.

JHtml::_('stylesheet', 'media/com_finder/css/indexer.css', array('relative' => true));

Ändere jetzt das true in ein false und Juhuu, CSS-Datei-Einbindung ist wieder da, weil Joomla sich nicht einen Pfad zusammenbastelt wie zuvor, sondern direkt den eingegebenen Pfad prüft. Auch hier wäre es so, dass nichts angezeigt wird, wenn die eingeg. CSS-Datei nicht existiert. Kannst ja mal einen Tippfehler reinmachen (soll gar nicht selten vorkommen beim Programmieren ;-) ).

Hinweis: Statt der ausgeschriebenen Variante mit false, kann man auch kurz schreiben

JHtml::_('stylesheet', 'media/com_finder/css/indexer.css');

Natürlich ist so jeder Pfad erlaubt, bspw. JHtml::_('stylesheet', 'templates/protostartest/css/template.css');

So, und jetzt fügen wir beide Zeilen ein, von denen wir ja wissen, dass sie einzeln funktionieren und beide die selbe Datei einbinden.

JHtml::_('stylesheet', 'com_finder/indexer.css', array(), true);
JHtml::_('stylesheet', 'media/com_finder/css/indexer.css');

Seit Joomla 3.7. lauten die Zeilen wie folgt.

JHtml::_('stylesheet', 'com_finder/indexer.css', array('relative' => true));
JHtml::_('stylesheet', 'media/com_finder/css/indexer.css');

Ergebnis: Die CSS-Datei wird nur 1x eingebunden!

Das Analogon für JavaScript- Dateien ist übrigens JHtml::_('script', 'templates/protostartest/js/template.js'); mit einem Unterschied. Sollte das true nötig sein, ist das 3. Argument nicht array(), sondern true oder false.

Probier einfach diese Zeilen einzeln aus, mal mit true, mal mit false. Siehst dann schon:

Bis Joomla 3.6!

JHtml::_('script', 'templates/protostartest/js/template.js', true, false);
JHtml::_('script', 'templates/protostartest/js/template.js', false, false);
JHtml::_('script', 'com_finder/sliderfilter.js', false, true);
JHtml::_('script', 'com_finder/sliderfilter.js', true, true);
JHtml::_('script', 'media/com_finder/js/sliderfilter.js', true, false);
JHtml::_('script', 'media/com_finder/js/sliderfilter.js', false, false);

Seit Joomla 3.7. lauten diese Zeilen wie folgt.

JHtml::_('script', 'templates/protostartest/js/template.js', array('framework' => true, 'relative' => false));
JHtml::_('script', 'templates/protostartest/js/template.js', array('framework' => false, 'relative' => false));
JHtml::_('script', 'com_finder/sliderfilter.js', array('framework' => false, 'relative' => true));
JHtml::_('script', 'com_finder/sliderfilter.js', array('framework' => true, 'relative' => true));
JHtml::_('script', 'media/com_finder/js/sliderfilter.js', array('framework' => true, 'relative' => false));
JHtml::_('script', 'media/com_finder/js/sliderfilter.js', array('framework' => false, 'relative' => false));

Oder seit Joomla 3.7. in gekürzter Form, die exakt das Selbe macht, da sowohl die Option 'framework' als auch 'relative' per Voreinstellung auf false steht.

JHtml::_('script', 'templates/protostartest/js/template.js', array('framework' => true));
JHtml::_('script', 'templates/protostartest/js/template.js');
JHtml::_('script', 'com_finder/sliderfilter.js', array('relative' => true));
JHtml::_('script', 'com_finder/sliderfilter.js', array('framework' => true, 'relative' => true));
JHtml::_('script', 'media/com_finder/js/sliderfilter.js', array('framework' => true));
JHtml::_('script', 'media/com_finder/js/sliderfilter.js');

Überlegt man ein bisschen, wird einem klar, wird meine eingebundene Datei, sei es nun CSS oder JS, nicht in der Reihenfolge angezeigt, wie ich erwarte, ist mir vielleicht eine andere Stelle im Code, vielleicht in einer anderen Erweiterung, zuvorgekommen?

Die Methoden addScript (JS), addStyleSheet (CSS)

In Joomla 4 wurde ein "Professoren-Monster" in den Core eingeführt, das in Teilen inkompatibel mit der für Normalsterbliche stinkeinfachen Verwendung dieser beiden Methoden ist. Es wäre besser gewesen, diese beiden Methoden in Joomla 4 komplett zu entfernen, anstatt sie neben dem Monster drinnen zu behalten. Kurz: Sie funktionieren noch, aber mit Unwägbarkeiten behaftet.

Und zum Ende noch eine Variante einzelne CSS oder JS einzubinden. Eigentlich der direktere Weg zum Ziel... Man findet sie im Code vieler Erweiterungen. Geschmackssache.

JHtml::_('script', 'templates/protostartest/js/template.js');
JHtml::_('stylesheet', 'templates/protostartest/css/template.css');

$doc = JFactory::getDocument();
$doc->addScript('templates/protostartest/js/template.js');
$doc->addStyleSheet('templates/protostartest/css/template.css');

Die JHtml-Zeilen 1-2 kennen wir ja schon. Und die Zeilen 4-6 machen in diesem Fall das selbe. Und auch hier wird nicht doppelt geladen, wenn beide Varianten irgendwo in den Untiefen des Systems verwendet werden.

Selbst rumprobieren mit zeilenweise Gatterzeichen #... Eigene zusätzliche Zeilen ausdenken, prüfen... Zeilen umsortieren.