Skip to content
This repository has been archived by the owner on May 16, 2019. It is now read-only.
/ pseudoimport-html Public archive

(abandoned). Use <link rel="import"> instead of pseudoimport-html

License

Notifications You must be signed in to change notification settings

m3co/pseudoimport-html

Repository files navigation

MDL/CE/WC-fragment

Here's a simple MDL/CE/WC component that allows you to import HTML code.

Check the tests MDL.

Check the tests CE.

Check the tests WC.

Feel free to import HTML content by using

<div class="mdl-fragment" src="an_URI.html"></div>

or

<x-fragment src="an_URI.html"></x-fragment>

Concept

A fragment is an HTMLElement like a container. It's defined as follows:

<x-fragment id="fragment-id" src="an_URL.html"></x-fragment>

The expected behavior here's to fetch the HTML code at an_URL.html then put this code inside the fragment. A fragment exposes a simple interface:

var fragment = document.querySelector('#fragment-id');
fragment.addEventListener('load', e => {
  // here you see that
  // e.detail.fragment === fragment
  // and this callback is reached once the HTML code
  // from fragment.src has been fetched and appended to fragment
});

fragment.loaded.then((fragment_) => {
  // here you see that
  // fragment_ === fragment
  // and this promise is ready once the HTML code
  // from fragment.src has been fetched and appended to fragment
});

Scripts that are inside a <x-fragment> see an special variable called document.currentFragment. This variable behaves as document.currentScript.

Also, due to lack of beforescriptexecute event, here the scripts that are shipped inside a <x-fragment> are treated in a special way. See below.

So, a fragment forces you to keep in mind an small set of features

  • load event
  • loaded promise
  • currentFragment
  • special threatment of scripts

Assumptions

Scripts' events

Because of replacement all fragment's scripts with executable scripts, we encourage not to rely on script's events. Check this demo

Scripts or Modules?

The rough idea is that the fragment behaves like <script>. If you import two or more times the same fragment, then it'll be fetched and executed as browser does with scripts. There's no complex mechanism that allows to import a fragment, and reuse its code in somewhere else.

document.currentFragment

A.k.a the cousing of document.currentScript. It works only once. So, while executing an script, the value of document.currentFragment is the fragment caller. Once the promise of all scripts is completed, then document.currentFragment = null.

Earlier content cannot be touched

Let's imagine an obvious case

<x-fragment src="URL.html">
  <script src="something-that-could-be-important.js"></script>
  <div class="loader-or-similar">
    ~
  </div>
</x-fragment>

If the fragment would reset the content, then there's no guarrante that something-that-could-be-important won't brake the page after putting the fetched content from URL.html, right? By this simple reason, the eariler content cannot be touched.

Contexts are important

Please, do not mix fragment-mdl.js with fragment-ce.js and fragment-wc.js. The last one is for old browsers. MDL is for Material Design Lite. CE is for Custom Elements and WC is for Web Components but instead of customElements.define it uses document.registerElement.

If this idea looks good to you and you want to implement it into your favorite framework, then feel free to send me a PR. I'll be glad to help you with testing and more.

Fetch an URI

This tool allows to import html code from a src = URI where that resource is fetched via fetch. This means that fetch will handle CORS and some other cases.

Load event dispatching order

While its expected that if a resource has been fetched and parsed successfully then a load event will be fire, this tool fetches and parses all the fragments and then will fire the load events in order of appearance. E.g in MDL:

<div class="mdl-fragment" src="fragmentA.html"> <!-- (1) -->
  <!-- for the sake of the example, the fragmentA.html's content is: -->
  <!-- <fragmentA.html> -->
  <div class="mdl-fragment" src="fragmentB.html"> <!-- (2) -->
  </div>
  <!-- </fragmentA.html> -->
</div>

As intended here, (1) will dispatch load event after all its content and fragments has been fetched and parsed successfully. After (1) has finished, (2) will dispatch load event having all its content and fragments fetched and parsed successfully, and so on...

All scripts that belong to a fragment will be executed as async.

The load event is exposed as a Promise through loaded property.

Relative URIs

The resolution of relative URI is implemented by using a baseURI attribute that is assigned while fetching. Once the content has been fetched and parsed successfully, then this attribute is deleted.

The above doesn't apply for <scripts src=relativeURI></scripts> inside a fragment. The reason is that the src's <script> must be changed in order to let the browser's parser do its job.

Fetch options

You can provide global options for fetch request through meta-tag. In ex., you have options object:

let options = {
  headers: {
    "cache-control": "no-cache"
  },
  method: "GET"
}

You would be transform it to:

<!-- In custom-element (ce) -->
<meta x-fragment headers-cache-control="no-cache" method="GET">
<!-- In material design light (mdl) -->
<meta mdl-fragment headers-cache-control="no-cache" method="GET">

Also, you can divide options to multiple meta-tags:

<meta x-fragment headers-cache-control="no-cache">
<meta x-fragment method="GET">

Contribute

Install

$ git submodule init

$ git submodule update

$ npm start