• Stars
    star
    232
  • Rank 172,847 (Top 4 %)
  • Language
    PHP
  • License
    MIT License
  • Created over 2 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Swap.js is a "HTML-over-the-wire" AJAX-navigation micro-library

Swap.js

logo_new300px

Swap.js is a JavaScript micro-library which facilitates AJAX-style navigation in web pages, in less than ~ 100 lines of code. (See "Why?" paragraph below)

This is inspired by the recent libraries that make server-side-rendering and "HTML-over-the-wire" techniques popular again (HTMX, Unpoly, Hotwire...).
In short, portions of a web page can be replaced by new content sent directly from the server as HTML fragments, in a very simple way.

Demo here using this library: Demo

Features:

  • AJAX-style navigation and replacement of HTML elements of the page
  • handling of the browser history (history back button, etc.)
  • automatic code launcher when HTML elements are created/removed in the DOM
  • adapted for single page applications (or not)

Important aspects:

  • vanilla JS (no external tool needed: no bundler, no webpack, no TypeScript compiler, no minification needed...)
  • the good old <a href="..." navigation still works if JavaScript is disabled in the browser (progressive enhancement)
  • you can keep your current server-side rendering solution (PHP, Python...)

Key idea:

<a href="newpage.html" swap-target="#container" swap-history="true">Click me</a>
<div id="container">Container</div>`

When you click on "Click me", the element #container is replaced by newpage.html's #container. Simple isn't it?

Simple example

See demo1/ folder.

index.html

<body>
<a href="index.html" swap-target="#container" swap-history="true">Home</a>
<a href="screen2.html" swap-target="#container" swap-history="true">Go to screen 2</a>
<div id="container">Container</div>
<script src="../swap.js"></script>
</body>

screen2.html

<body>
<a href="index.html" swap-target="#container" swap-history="true">Home</a>
<a href="screen2.html" swap-target="#container" swap-history="true">Go to screen 2</a>
<div id="container">You are on screen 2!</div>
<script src="../swap.js"></script>
</body>

Of course, in real life, you don't want to duplicate the same header and footer in multiple HTML files, and you will want to use server-side rendering: for a more complete example, see demo2/ folder with PHP code, multiple screens, multiple containers to be replaced, and also with some JS code that is run automatically when elements are inserted/destroyed in the DOM.

More advanced example

The folder demo3-email/ is another example of usage of the library. Nearly no JS is written, but mostly HTML attributes.

Live demo

Documentation

You can use these 3 features:

  • swap-target (HTML attribute)

    If present on a <a href="..." link, then, when clicked, a HTTP request is done with fetch() and the HTML fragment of the response matched by the CSS selector swap-target will replace the part of the current page matched by this same selector.

    This little detail is quite powerful because it allows you to continue to always render the full page server-side, no matter if only a HTML fragment will be used client-side (because AJAX navigation) or if the full page is required (for example, because the user did a refresh on the navigator). If you find in certain cases that it's a waste of bytes to send the full page in every case you can also render only a fragment server-side, based on the presence of HTTP request header swap-target ($_SERVER['HTTP_SWAP_TARGET'] in PHP), but this is purely optional.

  • swap-history (HTML attribute)

    If true, a new browser history element will be pushed when the link is clicked.

    When going back in history, an AJAX-call is made to update <body> based on the history URL.
    If you want to update something else than <body> when going back in history, you can set the HTML attribute swap-history-restore on the element which will be restored.

  • Loader/unloader JS functions when DOM elements are added/removed

    Sometimes, you want to execute JS code when a new HTML fragment is inserted, or when it is removed. Here is how it works:

    Swap.loaders['.screen2'] = () => {
        console.log("An element with class screen2 has just been inserted in the DOM.")
        var task = setInterval(() => { console.log("On repeat!"); }, 1000);
        return () => { clearInterval(task); };                // in a loader function, you return an unloader function which will be executed when the element is removed from DOM
    }
    

Why a 100 line-of-code limit?

When you start a new web project and decide to use a rather new library xyz.js, you always take the risk that:

  • eventually xyz.js will not be maintained anymore
  • a feature is missing but you don't know where to add it in the 50 different source code files with a total of 10'000 lines of code
  • there is a strange bug but you can't find where it is in these 10k lines of code
  • the library has hundreds of features you don't need

For this reason, this micro-library will always stay single-file and not have more than ~ 100 lines of code. No complex feature will be added, it will stay very basic. The benefit of all this is that you can read, understand, and improve the full code of the micro-library in less than 1 hour of your time.

This project's source code was initially much larger than its current state, with more complex mechanisms (for the same result), and I spent good time simplifying it and keep (what I find) the most elegant solution. It looks simple now, but it wasn't initially ;) (the use of MutationObserver API was helpful).

Contributions

Issues, ideas, discussions are welcome - please open an issue before doing a pull request to be sure it is necessary.

Which simple feature would you want to to see included? After all the current code is < 50 lines of code, so there is plenty of room until reaching the 100 lines of code limit :)

Author

Joseph Ernest

For R&D, Python, data science, automation consulting/freelancing requests, please contact me on https://afewthingz.com.

Sponsors are welcome to support the development of my open-source projects.

I am currently sponsored by CodeSigningStore.com. Thank you to them for providing a DigiCert Code Signing Certificate and supporting open source software.

License

MIT

More Repositories

1

writing

Writing is a lightweight distraction-free text editor, in the browser (Markdown and LaTeX supported).
JavaScript
1,031
star
2

bigpicture.js

bigpicture.js is a Javascript library that allows infinite panning and infinite zooming in HTML pages.
JavaScript
809
star
3

SamplerBox

SamplerBox is a sampler musical instrument based on RaspberryPi.
Python
416
star
4

Yopp

A very fast way to transfer a file from phone to computer and vice versa.
PHP
400
star
5

nfreezer

nFreezer is an encrypted-at-rest backup tool.
Python
301
star
6

talktalktalk

TalkTalkTalk is an easy-installable small chat room, with chat history.
HTML
251
star
7

void

Void is a blogging platform.
PHP
193
star
8

TinyAnalytics

TinyAnalytics is a lightweight analytics tool (unique visitors count, etc.)
PHP
148
star
9

AReallyBigPage

Collaborative whiteboard based on bigpicture.js
HTML
42
star
10

EasyVolcaSample

Easy upload .wav files to Korg Volca Sample!
C
25
star
11

impulseresponse.py

Get a reverb impulse response (IR) from a frequency sweep
Python
21
star
12

bloggggg

bloggggg is a blogging platform.
PHP
13
star
13

sdfgh

"sdfgh", an encrypted notepad in ~65 lines of Python. Read the code, trust it (or not), and use it (or not)!
Python
11
star
14

RaspFIP

Ecouter la radio FIP avec un Raspberry Pi (sans Γ©cran ni clavier). Une seule action Γ  faire : Power On !
9
star
15

0Doc

Documentation made simple.
JavaScript
6
star
16

rebootnow

Reboot to a specific device easily (HDD2, USB, CDROM, BIOS Setup, etc.)
Python
4
star
17

NeverForget

Easiest sticky notes app possible. Always there on Windows' deskop.
C++
3
star
18

wavfile.py

Python
2
star
19

aayi

The tiniest website analytics tool
PHP
1
star
20

ShareLinkAndPixelIt

Share external links on Facebook, but have them caught by your Facebook Pixel (useful to build retargeting audience)
PHP
1
star
21

0Doc-chip

Example of use of 0Doc for C.H.I.P.'s documentation
CSS
1
star
22

copycopypastepaste

CTRL+C some text, CTRL+C another text, then CTRL+V and CTRL+< to paste two buffers!
Visual Basic
1
star
23

textarea

https://josephernest.github.io/textarea/htmleditor.html
HTML
1
star
24

bigpicture-editor

Standalone editor based on bigpicture.js
JavaScript
1
star