Computer Keyboard - Głównie JavaScript

Głównie JavaScript

by Jakub T. Jankiewicz

Importy HTML

Importy HTML (ang. HTML Imports) to nowa funkcjonalność w HTML, która jest częścią web komponentów. Daje możliwość importowania skryptów JavaScript, szablonów CSS czy stron HTML oraz daje dostęp do ich zawartości. Tak jak w przypadku AJAX-a, ale następuje to zanim strona się załaduje, w momencie gdy parser napotka tag importu w HTML.

W HTML istniało do tej pory kilka sposobów na ładowanie zewnętrznej treści:

  • iframe - służą do dodawania zagnieżdżonych stron HTML.
  • link - z jego pomocą można dodawać do strony arkusze CSS, fav-ikonki lub zlinkować Kanał RSS itp.
  • script - służy do załadowania plików JavaScript jeśli użyto atrybutu src.
  • audio - można za jego pomocą załadować pliki muzyczne.
  • video - służy do dołączania plików wideo.
  • object - stary sposób dołączania zewnętrznych treści.

Teraz do tego dochodzą jeszcze importy HTML. Aby dołączyć za ich pomocą zewnętrzny plik, używamy tagu link z atrybutem rel="import":

<link rel="import" href="import.html"/>

podana strona może zawierać pliki JavaScript i CSS np.:

<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
</html>

Jeśli dołączymy w naszym skrypcie taki import, załaduje on nam do strony bibliotekę jQuery. Importy są singletonami więc jeśli dołączymy kilka razy dany import będzie on pobrany tylko raz.

Dzięki importom HTML mamy możliwość definiowania komponentów, które dołączają wszystkie potrzebne pliki np. poniżej import który dołączy moją bibliotekę jQuery Terminal i utworzy globalną funkcje terminal:

<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery.terminal@1.7.0/css/jquery.terminal.min.css"/>
<script src="https://cdn.jsdelivr.net/npm/jquery.terminal@1.7.0/js/jquery.terminal.min.js"></script>
<style>
body {
    min-height: 100vh;
    margin: 0;
}
</style>
<script>
(function() {
    var $ = jQuery.noConflict();
    window.terminal = function(selector) {
        var args = [].slice.call(arguments, 1);
        return $.fn.terminal.apply($(selector), args);
    };
})();
</script>
</head>
<body>
</body>

Użytkownik nie musi wiedzieć że używamy biblioteki jQuery, wystarczy że wie że ma funkcje terminal, która przyjmuje selektor CSS jako pierwszy argument. Scope wewnątrz importu jest taki sam jak w dokumencie, który importuje plik, czyli window jest ten sam. Można tego importu użyć w ten sposób:

<!DOCTYPE html>
<html>
<link rel="import" href="terminal.html"/>
<body onload="terminal('body')"></body>
</html>

Niestety jeśli chodzi o style CSS w imporcie, Google Chrome oraz Chromium w wersji 61 wyświetlają ostrzeżenie, że zostaną usunięte w wersji M65, aby rozwiązać ten problem możemy dołączyć style do głównego dokumentu.

<script>
(function() {
    var url = 'https://cdn.jsdelivr.net/npm/jquery.terminal@1.7.0/css/jquery.terminal.min.css';
    var $ = jQuery.noConflict();
    $('<link href="' + url + '" rel="stylesheet"/>').appendTo('head');
    var importDoc = document.currentScript.ownerDocument;
    var style = importDoc.querySelector('style');
    document.head.appendChild(style);
    window.terminal = function(selector) {
        var args = [].slice.call(arguments, 1);
        return $.fn.terminal.apply($(selector), args);
    };
})();
</script>

NOTE: Podany plik można znaleźć w repo biblioteki.

Dostęp do zawartości

Za pomocą importów mamy także dostęp do zawartości danych plików, tak jak w przypadku AJAX-a, za pomocą właściwości import elementu link:

<link rel="import" href="https://cdn.jsdelivr.net/npm/jquery.terminal@1.7.0/js/jquery.terminal.min.js"
      onload="console.log(event.target.import.body.innerHTML)"/>

Tak jak w przypadku obrazków mamy dostęp do zdarzeń onload i onerror.

CORS

Tak jak w przypadku AJAX-a, a w odróżnieniu od stylów CSS, aby użyć importu strona musi mieć włączony CORS, przeciwnym wypadku nie tylko nie będziemy mieli dostępu do zawartości ale import nie załaduje się wcale,

Web komponenty

Dzięki importom HTML możemy w łatwy sposób dołączać web komponenty

<script>
  // Definicja komponentu <czesc>.
  var proto = Object.create(HTMLElement.prototype);

  proto.createdCallback = function() {
    this.innerHTML = 'Cześć, <b>' +
                     (this.getAttribute('name') || '?') + '</b>';
  };

  document.registerElement('hello-user', {prototype: proto});
</script>

Dołączając taki import mamy możliwość skorzystania z nowego taga czesc

<head>
<link ref="import" href="komponent.html"/>
</head>
<body>
  <hello-user name="Jan"><hello-user>
</body>

Wsparcie przeglądarek

Wszystko Fajnie, ale jakie jest wsparcie dla importów HTML w przeglądarkach? Niestety nie jest dobrze, z chwilą pisania tego artykułu tylko Chrome we wszystkich wersjach oraz Opera mają tą funkcjonalność. Wsparcie można zobaczyć na stronie Can I Use. Miejmy nadzieje, że wkrótce się to zmieni i wszystkie przeglądarki zaimplementują importy HTML, do tego czasu można użyć polyfill.

źródło strony (aby zobaczyć kod na GitHubie, musisz kliknąć przycisk raw)
Komentarze

Hasło, które podasz umożliwi ponowne zalogowanie się i np. usunięcie komentarza, jest dobrowolne. Email jest szyfrowany i używany do wysyłania powiadomień o odpowiedziach do komentarzy oraz do pobierania awatara dzięki usłudze Gravatar.com.

Wyślij komentarz na "Importy HTML"

Akceptowany HTML

<b>, <strong>, <u>, <i>, <em>, <s>, <big>, <small>, <sup>, <sub>, <pre>, <ul>, <ol>, <li>, <blockquote>, <code> escapes HTML, URLe automatycznie zamieniają się w linki, a [img]URL tutaj[/img] wyświetli zewnętrzny obrazek.

Akceptowany Markdown

**Pogrubienie**, _podkreślenie_, *kursywa*, ~~przekreślenie~~, `zaznacz`, ```kod``` ucieka HTML. HTML i Markdown mogą być stosowane razem w swoim komentarzu.

Wyświetlanie 2 Komentarzy (7 liczenie odpowiedzi)
lukaszpolowczyk

Zapomniałeś o ładowaniu obrazków na pomocą img. I z atrybutów właściwości CSS z url();
Oraz z wnętrza script można za pomocą XHR i modules ładować.

Usunięty...
Komentarz został usunięty.

Próba implementacji ładowania CSS-a poza link jest IMO sztuką dla sztuki – zwłaszcza jeśli weźmiemy pod uwagę ostatnie zmiany → https://jakearchibald.com/2...

Nie widzę sensu w próbie naprawiania czegoś, co nie jest zepsute.

I tak, ładuje się inne rzeczy, np. Service Worker czy manifest aplikacji. Do tego dochodzi prefetching i preloading.

lukaszpolowczyk W odpowiedzi na Comandeer

Ja wiem że to niepotrzebne, ale jak im tak zależy żeby nie dodać link import?

No bo pod spodem IMO nie jest to aż tak przemyślane, jak być powinno, co niestety widać. Np. nie są wyraźnie zarysowane granice między dokumentem importowanym a importującym.

Nie chcę Cię martwić, ale nikt nie zaimplementuje HTML Imports, bo Apple i Safari powiedziały "nie" wprost. Motywację Mozilli można poznać na ich blogu: https://hacks.mozilla.org/2...(TL;DR HTML Imports tworzą całkowicie osobny mechanizm obok ES Modules, co może wprowadzać niepotrzebną kompleksowość do kodu). Z tego też powodu Chrome ostatecznie również usunie HTML Imports, a ten powolny proces już się zaczął: https://groups.google.com/a...

Trwają obecnie prace nad nowym rozwiązaniem, HTML Modules, czyli wczytywaniem HTML-a przy pomocy mechanizmu ES Modules → https://github.com/w3c/webc...Choć wygląda to obiecująco, to do implementacji jest bardzo, bardzo daleko.

Wychodzi więc na to, że najlepszym sposobem na importowanie HTML-a na chwilę obecną jest… zrobienie odpowiedniego custom elementu pod to ;)

PS widzę dodatkowo, że w artykule używasz składni CE w wersji v0. W v1 CE deklaruje się poprzez customElements.define. Poza tym nazwa takiego komponentu musi zawierać w sobie - (ale nie jako pierwszy znak), więc czesc- jak już (inaczej przeglądarka zgłosi błąd).

Dzięki za info, szkoda bo wyglądało na fajną funkcjonalność.