Dodavanje stilskih tablica (CSS) i JavaScript (JS) u Drupal 8 temu
Ova dokumentacija je za teme. Informacije o modulima pogledajte u odeljku Dodavanje stilskih tablica (CSS) i JavaScript (JS) u Drupal 8 modul.
U Drupalu 8, stilovi (CSS) i JavaScript (JS) se učitavaju kroz isti sistem za module (kod) i teme za sve: biblioteke resursa.
Za jasnoću, ove instrukcije su namenjene SAMO radu u temama i ne odnose se na module.
Drupal koristi princip visokog nivoa: resursi (CSS ili JS) se učitavaju samo ako vi kažete Drupalu da ih treba učitati. Drupal ne učitava sve resurse na svakoj stranici jer bi to umanjilo performanse interfejsa.
Razlike u odnosu na Drupal 7
Postoji šest važnih razlika u odnosu na Drupal 7 za entuzijaste:
- Fajl THEME.info.yml je zamenio THEME.info fajl (sa istim podacima).
- Properti stylesheets (za dodavanje CSS-a) u THEME.info je uklonjen i zamenjen fajlom *.libraries.yml, gde je `*` ime teme ili modula.
- Properti scripts (za dodavanje JS) u THEME.info je uklonjen i takođe zamenjen *.libraries.yml fajlom.
- Učitavaće se samo CSS i JS koji su potrebni na stranici. Na primer, jQuery više nije automatski učitan osim ako nije eksplicitno naveden u *.libraries.yml. Ako vašoj temi treba jQuery ili drugi resursi koji treba da se učitaju na svim stranicama, dodajte ih u *.libraries.yml, a zatim uključite biblioteku u THEME.info.yml.
- U Drupalu 7 biblioteke su se definisale preko hook_library_info(). To je zamenjeno fajlom *.libraries.yml.
- U Drupalu 8 drupal_add_css(), drupal_add_js() i drupal_add_library() su uklonjeni u korist #attached
Proces
Da biste učitali CSS ili JS resurse:
- Sačuvajte CSS ili JS u fajl, koristeći odgovarajuće konvencije imenovanja i strukturu fajlova.
- Definišite "biblioteku" koja registruje ove CSS/JS fajlove u vašoj temi.
- "Prikačite" biblioteku na sve stranice, na određene Twig šablone ili ciljajte određene stranice pomoću #attached u preprocess funkciji.
Definisanje biblioteke
Sve biblioteke resursa definišite u fajlu *.libraries.yml u folderu vaše teme. Ako se vaša tema zove fluffiness, fajl mora biti fluffiness.libraries.yml. Svaka "biblioteka" u fajlu detaljno navodi CSS i JS fajlove (resurse), na primer:
# fluffiness.libraries.yml cuddly-slider: version: 1.x css: theme: css/cuddly-slider.css: {} js: js/cuddly-slider.js: {}
U ovom primeru, JavaScript fajl cuddly-slider.js i CSS cuddly-slider.css se nalaze u odgovarajućim direktorijumima js i css unutar vaše teme.
Napomena: iako primer pokazuje jedan css i jedan js fajl + jquery, dostupno je mnogo više opcija za definisanje biblioteka. Više informacija potražite u sekciji "Definisanje biblioteka: opcije i detalji".
Uključivanje jQuery u vašu biblioteku
Zapamtite, Drupal 8 više ne učitava jQuery na sve stranice po defaultu, zato ako cuddly-slider zahteva jQuery, morate navesti zavisnost od osnovne biblioteke koja sadrži jQuery (drupal core pruža jQuery, a ne modul ili tema). Zavisnost se navodi kao naziv prostora imena, pa kosa crta, zatim ime biblioteke, ovde je to core/jquery. Ako neka druga biblioteka zavisi od cuddly-slider biblioteke, ona navodi fluffiness/cuddly-slider, ime teme plus ime biblioteke. Ne možete navesti pojedinačni fajl kao zavisnost, samo celu biblioteku.
Dakle, da bismo omogućili jQuery za cuddly-slider, ažuriraćemo primer gore:
# fluffiness.libraries.yml cuddly-slider: version: 1.x css: theme: css/cuddly-slider.css: {} js: js/cuddly-slider.js: {} dependencies: - core/jquery
Definisanje zavisnosti
Da biste naveli zavisnosti, potrebne biblioteke se navode kao resurs/biblioteka. Za osnovne biblioteke resurs je core, dok za druge zavisi od imena modula ili teme. Na primer, ako new_library zavisi od jQuery iz core, my_library definisane u my_theme i my_library definisane u my_module, onda ćete zavisnosti navesti ovako:
# fluffiness.libraries.yml new_library: js: js/new_libary.js: {} dependencies: - core/jquery - my_module/my_library - my_theme/my_library
Imena modula i tema služe kao imenski prostori za biblioteke istih naziva.
Prikačivanje biblioteke na sve stranice
U većini tema koristi se global-styling biblioteka resursa za CSS fajlove koje treba učitati na svakoj stranici gde je tema aktivna. Takođe je moguće isto uraditi za JS koristeći global-scripts biblioteku.
# fluffiness.libraries.yml (više biblioteka može biti definisano u istom fajlu, ovo bi se nalazilo ispod cuddly-slider biblioteke) global-styling: version: 1.x css: theme: css/layout.css: {} css/style.css: {} css/colors.css: {} global-scripts: version: 1.x js: js/navmenu.js: {}
Da bi ove biblioteke bile dostupne na svim stranama teme, global-styling/global-scripts moraju biti dodate u info.yml vaše teme (npr. fluffiness.info.yml)
#fluffiness.info.yml name: Fluffiness type: theme description: 'A cuddly theme that offers extra fluffiness.' core: 8.x libraries: - fluffiness/global-styling - fluffiness/global-scripts base theme: classy regions: header: Header content: Content sidebar_first: 'Sidebar first' footer: Footer
Prikačivanje biblioteke preko Twig šablona
Biblioteku resursa možete prikačiti Twig šablonu koristeći funkciju attach_library() u bilo kojem *.html.twig fajlu, na primer:
{{ attach_library('fluffiness/cuddly-slider') }} <div>Neki fluffy markup {{ message }}</div>
Prikačivanje biblioteke na podskup stranica
U nekim slučajevima ne želite da vaša biblioteka bude aktivna na svim stranicama, već samo na podskupu. Na primer, možda želite da se vaša biblioteka učitava samo kada se prikaže određeni blok ili određeni tip čvora.
Tema to može uraditi implementacijom funkcije THEME_preprocess_HOOK() u .theme fajlu, zamenjujući "THEME" mašinskim imenom vaše teme, a "HOOK" mašinskim imenom tematskog hook-a.
Na primer, ako želite da dodate JavaScript na stranicu za održavanje, deo "HOOK" je "maintenance_page", pa funkcija izgleda ovako:
function fluffiness_preprocess_maintenance_page(&$variables) { $variables['#attached']['library'][] = 'fluffiness/cuddly-slider'; }
Slično možete napraviti i za druge hookove, a funkcija može sadržati i logiku — npr. da proveri koji se blok procesira u hooku "block", koji je tip čvora u hooku "node", itd.
Važna napomena! U ovom slučaju morate navesti metapodatke za keširanje koji odgovaraju vašem stanju! Gornji primer radi bez dodatnih metapodataka za keširanje. Najčešći slučaj je kada dodajete biblioteku resursa na osnovu trenutne rute:
function fluffiness_preprocess_page(&$variables) { $variables['page']['#cache']['contexts'][] = 'route'; $route = "entity.node.preview"; if (\Drupal::routeMatch()->getRouteName() === $route) { $variables['#attached']['library'][] = 'fluffiness/node-preview'; } }
Definisanje biblioteka: opcije i detalji
Dodavanje atributa u prikačene css/js
Atributi se dodaju unutar vitičastih zagrada iza svakog fajla u THEMENAME.libraries.yml fajlu vaše teme.
CSS atributi
Sledeći atributi su opciono i primenjuju se za svaki CSS resurs.
attributes | Nepotrebni atributi. Poznat slučaj korišćenja Bootstrap CDN. |
{ attributes: { crossorigin: anonymous } } |
browsers | Učitaj resurs uslovno prema pretraživaču. Napomena: ovaj metod koristi uslovne komentare koji nisu podržani u IE10 i novijim verzijama. |
{ browsers: { IE: 'lte IE 9', '!IE': false } } |
group | Aktivi se agregiraju po grupama. Podrazumevano: SMACSS grupa kojoj pripada aktiv. | Retko se koristi |
media | Tip medijuma. |
{ media: print } |
minified | Da li je aktiv već minimiziran. Podrazumevano: false |
{ type: external, minified: true } |
preprocess | Da li treba da se agregira. Podrazumevano: true |
{ preprocess: false } |
type | Izvor aktivacije. Podrazumevano: file |
{ type: external, minified: true } |
weight | Podešava redosled u odnosu na druge aktive u istoj SMACSS grupi. Podrazumevano: 0. Koristite vrednost od -50 do +50. |
{ weight: 1 } |
JS atributi
Sledeći atributi su opciono i primenjuju se za svaki JS resurs.
attributes | Dodatni atributi skripti. |
{ type: external, attributes: { async: true } } |
browsers | Učitaj resurs uslovno prema pretraživaču. Napomena: ovaj metod koristi uslovne komentare koji nisu podržani u IE10 i novijim verzijama. |
{ browsers: { IE: 'lte IE 9', '!IE': false } } |
preprocess | Da li treba da se agregira. Podrazumevano: true |
{ preprocess: false } |
type | Izvor aktivacije. Podrazumevano: file |
{ type: external, minified: true } |
weight | Ne preporučuje se, umesto toga koristite zavisnosti. Podešava redosled u odnosu na druge aktive. Treba da bude negativan. |
{ weight: -1 } |
Perepisivanje i proširivanje biblioteka
Da biste promenili biblioteke definisane u *.libraries.yml, morate ići u *.info.yml. One se mogu zameniti ili proširiti pomoću libraries-override ili libraries-extend. Override definisan u *.info.yml će se naslediti u podtemama.
Properti stylesheets-remove koji se koristi u *.info.yml je zastareo i biće uklonjen u Drupal 9.0.x. stylesheets-override je već uklonjen.
libraries-override
Logika koju treba koristiti prilikom kreiranja override-a:
- Koristite originalni namespace modula (ili core) za ime biblioteke.
- Koristite putanju najnovijeg override-a kao ključ.
- Ta putanja treba da bude puna putanja do fajla.
Na primer:
libraries-override: contextual/drupal.contextual-links: css: component: /core/themes/stable/css/contextual/contextual.module.css: false
Ovde contextual/drupal.contextual-links je namespace osnovne biblioteke, a /core/themes/stable/css/contextual/contextual.module.css je puna putanja poslednjeg override-a. U ovom slučaju fajl je uklonjen (false).
Važno je napomenuti da je samo poslednji deo puna putanja, dok ostali predstavljaju namespace. Linije css: i component: odražavaju strukturu override-ovane biblioteke.
Ovo imajte na umu jer zavisnost od fajl sistema može da pukne ako se promeni struktura fajlova sajta. Zbog toga postoji problem uklanjanja zavisnosti od pune putanje korišćenjem stream wrapper-a.
Evo još nekoliko primera korišćenja libraries-override za uklanjanje ili zamenu CSS ili JS fajlova ili cele biblioteke koju nasleđuje vaša tema iz modula ili druge teme.
libraries-override: # Zamena cele biblioteke. core/drupal.collapse: mytheme/collapse # Zamena fajla drugim. subtheme/library: css: theme: css/layout.css: css/my-layout.css # Zamena fajla override-ovanog iz stable teme. contextual/drupal.contextual-toolbar: css: component: core/themes/stable/css/contextual/contextual.toolbar.css: css/contextual.toolbar.css # Zamena JS fajla iz core modula. toolbar/toolbar: js: js/views/BodyVisualView.js: js/views/BodyVisualView.js # Uklanjanje fajla. drupal/dialog: css: theme: dialog.theme.css: false # Uklanjanje cele biblioteke. core/modernizr: false # Zamena specifičnih fajlova iz biblioteke kontribut modula. # Napomena: Biblioteke koje modul može override-ovati su u njegovom *.libraries.yml fajlu. U ovom primeru, libraries.yml je u: /modules/contrib/webform/webform.libraries.yml webform/webform.element.location.places: css: component: css/webform.element.location.places.css: css/my-themes-replacement-file.css js: js/webform.element.location.places.js: js/my-themes-replacement-file.js
libraries-extend
libraries-extend omogućava temama da menjaju biblioteke dodavanjem dodatnih zavisnosti biblioteci pri svakom učitavanju biblioteke.
libraries-extend definiše proširenje biblioteke sa bilo kojim brojem drugih biblioteka.
Ovo je idealno za različito stilizovanje komponenti u temi, a da ne uključujete CSS globalno. Tako da prilagodite izgled komponente samo gde treba.
# Proširenje drupal.user: dodavanje asseta iz classy teme. libraries-extend: core/drupal.user: - classy/user1 - classy/user2
Dodatna podešavanja JavaScripta
Redosled učitavanja asseta
Redosled u kom su fajlovi navedeni je redosled u kom se učitavaju. Po defaultu, svi JS resursi se učitavaju u podnožju (footer). JS za kritične UI elemente, koje nije moguće prikazati bez pripadajućeg JS-a, može se učitati u zaglavlju, ako je potrebno, na sledeći način:
js-header: header: true js: header.js: {} js-footer: js: footer.js: {}
Postavite header na true da označite da se JS iz ove biblioteke nalazi na "kritičnom putu" i mora biti učitan iz zaglavlja. Sve direktne ili indirektne zavisnosti biblioteke će se automatski učitati iz zaglavlja, nije potrebno posebno ih navoditi. To znači da je resurs "kritičan" i treba ga učitati prvi.
Dodavanje prilagođenog JavaScripta
Ponekad želite dodati JavaScript na stranicu koji zavisi od nekih PHP vrednosti.
U tom slučaju, kreirajte JS fajl, definišite i prikačite biblioteku kao i do sada, ali takođe prikačite JS podešavanja i dozvolite JS fajlu da čita te podatke preko drupalSettings (naslednik Drupal 7 Drupal.settings). Da bi drupalSettings bio dostupan JS fajlu, morate navesti zavisnost od njega, kao što je slučaj sa jQuery.
Tako postaje:
cuddly-slider: version: 1.x js: js/cuddly-slider.js: {} dependencies: - core/jquery - core/drupalSettings
i
function fluffiness_page_attachments_alter(&$page) { $page['#attached']['library'][] = 'fluffiness/cuddly-slider'; $page['#attached']['drupalSettings']['fluffiness']['cuddlySlider']['foo'] = 'bar'; }
Gde je 'bar' neka izračunata vrednost. (Napomena: potrebno je navesti i keš metapodatke!)
Zatim cuddly-slider.js može pristupiti settings.fluffiness.cuddlySlider.foo (što će biti 'bar'):
(function ($, Drupal, drupalSettings) { 'use strict'; Drupal.behaviors.mybehavior = { attach: function (context, settings) { console.log(settings.fluffiness.cuddlySlider.foo); } }; })(jQuery, Drupal, drupalSettings);
Dodavanje atributa elementima skripte
Ako želite dodati atribute u script tag, dodajte key attributes u JSON nakon URL-a skripte. Unutar objekta iza key attributes, navedite ime atributa kao novi key. Vrednost tog key-a je vrednost atributa. Ako je vrednost true, atribut će biti prikazan sam, bez vrednosti.
Na primer:
https://maps.googleapis.com/maps/api/js?key=myownapikey&signed_in=true&libraries=drawing&callback=initMap: type: external attributes: defer: true async: true data-test: map-link
Ovo će proizvesti sledeću markup:
<script src="https://maps.googleapis.com/maps/api/js?key=myownapikey&signed_in=true&libraries=drawing&callback=initMap" async defer data-test="map-link"></script>
Inline JavaScript
Inline JavaScript se snažno ne preporučuje. Preporučuje se da se JavaScript stavi u fajl koji se učitava, jer to omogućava keširanje na strani klijenta. Takođe omogućava lakše pregledanje i uređivanje JavaScript koda.
Inline JavaScript koji generiše markup
To se ne preporučuje i obično nije potrebno. Stavite JavaScript u fajl. Primeri su reklame, dugmad za deljenje na društvenim mrežama, vidžeti društvenih mreža. Oni koriste inline JavaScript, ali su specifičan tip sadržaja/markupa, jer nisu namenjeni da ukrase sadržaj sajta ili interaktivnost, već da izvuku spoljašnji sadržaj preko JavaScripta.
Možete ih staviti u prilagođeni blok ili čak direktno u Twig šablon.
Na primer:
<script type="text/javascript"><!-- ad_client_id = "some identifier" ad_width = 160; ad_height = 90; //--></script> <script type="text/javascript" src="http://adserver.com/ad.js"></script> <a class="twitter-timeline" href="https://twitter.com/wimleers" data-widget-id="307116909013368833">Tweets by @wimleers</a> <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
Inline JavaScript koji utiče na celu stranicu
Korišćenje bilo kakvog inline JavaScripta se snažno ne preporučuje. Primeri inline JS koji utiču na celu stranicu su analitika (npr. Google Analytics) i servisi za hostovanje fontova. Inline JS koji utiče na celu stranicu može biti ili frontend/stilizacija ili logika.
Za frontend/stilizaciju (npr. hostovani fontovi) JS pripada temi. Stavite JS direktno u vaš html.html.twig fajl. Za fontove, ovo omogućava da se ispravno pozicionira za najbolji i najbrži prikaz krajnjem korisniku, jer sprečava FOUT (Flash Of Unstyled Text), dok se font učitava (fontovi preko JS treba da se nalaze u HTML <HEAD> pre CSS-a)!
(Više o tome pročitajte u odličnoj analizi "Async Typekit & Micro-FOUT".)
U drugom slučaju, JS pripada modulu; u tom slučaju pogledajte "Dodavanje CSS i JS u Drupal 8 modul".
Inline JavaScript u integracionom modulu
Korišćenje bilo kakvog inline JavaScripta se snažno ne preporučuje. Ako možete, koristite gore navedene primere pre nego što pokušate inline JS.
Dve stvari koje treba uzeti u obzir prilikom pružanja polja koje prihvata inline JS koje postavlja korisnik sajta:
1. Polje, forma ili stranica koja prihvata inline JS mora imati prikačeno odgovarajuće dozvole.
Primer: MODULE.routing.yml
MODULE.settings: path: /admin/config/services/MODULE defaults: _title: 'MODULE settings' _form: \Drupal\MODULE\Form\MODULESettings requirements: _permission: 'administer site configuration'
2. Vrednost, ako je uskladištena u konfiguracionom objektu, mora obavestiti sistem renderovanja o svojoj CacheableMetadata, tako da se keš renderovanja očisti/istekne kada se promeni.
Primer: MODULES.module
<?php /** * @file * Integracija MODULE u Drupal sajt. */ use Drupal\Core\Render\Markup; /** * Implementira hook_page_bottom(). */ function MODULE_page_bottom(array &$page_bottom) { $settings = \Drupal::config('MODULE.settings'); $user = \Drupal::currentUser(); $page_bottom['MODULE'] = [ '#markup' => Markup::create($settings->get('js_code')), '#cache' => [ 'contexts' => ['user'], 'tags' => ['user:' . $user->id()], ], ]; // Dodaj metapodatke keširanja konfiguracije. /** @var Drupal\Core\Render\Renderer $renderer */ $renderer = \Drupal::service('renderer'); $renderer->addCacheableDependency($page_bottom['MODULE'], $settings); }
CDN / Spoljašnje biblioteke
Možda želite da koristite JavaScript sa CDN-a (Content Delivery Network) — na primer, web fontovi su uglavnom dostupni samo preko eksternih URL-ova. To možete uraditi deklarisanjem biblioteke kao eksternu (type: external). Takođe je korisno uključiti neke informacije o spoljnim bibliotekama u definiciju.
(Napomena: Ovo uopšte nije dobra praksa za biblioteke sa CDN-a; izbegavajte ako je moguće jer uvodi dodatne tačke kvara i utiče na performanse i sigurnost, zahteva više TCP/IP konekcija i uglavnom nije keširano u browseru. Međutim, spoljne biblioteke ne treba da se hostuju na Drupal.org kao deo vašeg repozitorijuma — pogledajte Politiku o spoljnim bibliotekama na Drupal.org za detalje.)
angular.angularjs: remote: https://github.com/angular version: 1.4.4 license: name: MIT url: https://github.com/angular/angular.js/blob/master/LICENSE gpl-compatible: true js: https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js: { type: external, minified: true }
Ako želite da vaš eksterni fajl bude zatražen istim protokolom kao i stranica, koristite URL bez protokola:
js: //ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js: { type: external, minified: true }
Za dodavanje CSS-a, evo primera integracije Font Awesome:
font-awesome: remote: https://fortawesome.github.io/Font-Awesome/ version: 4.5.0 license: name: MIT url: https://fortawesome.github.io/Font-Awesome/license/ gpl-compatible: true css: theme: https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css: { type: external, minified: true }
Primer Bootstrap CDN CSS sa prilagođenim atributima.
bootstrap-cdn: remote: getbootstrap.com version: 4.0 license: name: MIT url: https://github.com/twbs/bootstrap/blob/master/LICENSE css: theme: 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css': type: external minified: true attributes: crossorigin: anonymous integrity: "sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
Više informacija
Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.