Multi-Page mode
Multi-Page mode is the default mode of Sircl, and of the browser. Navigating to a new page is done by the browser, which also keeps track of the history stack. Sircl Ajax requests are used to update parts of the page.
Introduction
By default, when the Sircl libraries are added to a web project, Sircl operates in Multi-Page mode. This is the default mode that minimizes impact on an existing website. Yet, you can write SPA's (Single Page Applications) in the Multi-Page mode too.
The main advantages of this mode are:
- Almost all features of Sircl are available: page part loading, event-actions, change-actions, etc, etc.
- Because almost all Sircl features are "opt-in" (they are only active when you explicitely request them) this mode has minimal impact on an existing project.
Because of these advantages, Multi-Page mode (MPM) is the ideal option to apply on existing projects on which you want to benefit from the Sircl features with minimal impact to the existing code.
Starting with Multi-Page Mode
Multi-Page mode is what you get when you add the Sircl libraries to a project without taking further steps to switch to Single-Page mode. It's the default mode.
Running your project after adding the Sircl libraries should have no impact. If you are adding Sircl to an existing project, you should test and assert there is no impact.
Applying Event-Actions & Change-Actions
Once you have added the proper libraries (sircl.js, sircl-extended.js and/or sircl-changeactions.js), you can start applying event-actions and change-actions by simply adding their commanding classes and attributes.
For instance, if you had two checkboxes that you want to make dependent on one another, add ifchecked-enable
, ifchecked-check
, etc. event-action attributes to obtain the desired behavior.
Loading page parts
As soon as the core library (sircl.js) is added, you can start using page part loading. Page part loading relies on Ajax and is triggered by the use of inline targets.
Suppose you have following page containing a form with a list (two items with checkboxes), a field and button to add an item to the list, and a button to delete the checked items from the list:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<h1>To do's</h1>
<form method="post">
<div><input type="checkbox" name="Index" value="0" /> Book a hotel</div>
<div><input type="checkbox" name="Index" value="1" /> Look for activities</div>
<hr />
<input type="text" name="ToAdd" autofocus />
<button type="submit" name="Command" value="Add">Add</button>
<hr />
<button type="submit" name="Command" value="Del">Delete selected</button>
</form>
</body>
</html>
The form contains two submit buttons:
The Add button is supposed to add the text in the ToAdd input element to the list. When this button is pressed, the form is posted to the server, which performs the operation and returns a new full page where the list has been updated.
The Delete button is supposed to delete the items in the list that were checked. When the button is pressed, the form is posted to the server, which again performs the operation and returns a new full, updated page.
So for both submit buttons a full page is returned. This is how web pages work.
With Sircl, we can use page part loading to avoid reloading the full page on every mutation. First we have to design our solution. We have to take a few decisions:
- Which part of the page will we allow to be loaded separately ?
We could choose to separately load the full form, the content of the form, or only the items in the list.
In our example, we choose to load separately the content of the form. - How will the separately loaded part be loaded initially ?
We could choose to have the separatable part be loaded embedded when loading the full page, so no additional request is needed. Or we could choose the initial page load to trigger a second request to load the part in it.
In our example we choose the latter option which we can realize with theonload-load
Sircl attribute. The first option would have required server-side coding and the details would depend on the used server-side technology.
So we will now update our page to:
- Contain references to sircl.js and sircl.css. We also need to include jQuery.
- Remove the form content and have it loaded by means of the
onload-load
attribute.
We also add anaction
attribute to the form to post the form to the separate list handler.
We add atarget
attribute using a relative CSS selector to refer to the form itself as inline target, so that Sircl is triggered to use page part loading (using Ajax). - We can replace the content with a "Loading..." message that will automatically be replaced by the form content.
Our home page now is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="/lib/sircl2/sircl.css" rel="stylesheet" />
</head>
<body>
<h1>To do's</h1>
<form onload-load="/ToDos" action="/ToDos" target=":this" method="post">
Loading...
</form>
<script src="/lib/jQuery/jquery-3.5.1.slim.min.js"></script>
<script src="/lib/sircl2/sircl.js"></script>
</body>
</html>
A GET call to /ToDos will now return only the content of the form (a page part):
<div><input type="checkbox" name="Index" value="0" /> Book a hotel</div>
<div><input type="checkbox" name="Index" value="1" /> Look for activities</div>
<hr />
<input type="text" name="ToAdd" autofocus />
<button type="submit" name="Command" value="Add">Add</button>
<hr />
<button type="submit" name="Command" value="Del">Delete selected</button>
A POST call to /ToDos will, as before, process the Add or Delete button, then return the updated page part.
Notice how the /ToDos handler (GET and POST) has now become a "component", standing on it's own and pluggable in any page of your application.
When adding or deleting ToDo items, only the content of the form is updated. The rest of the page remains unchanged and is not reloaded.
The browsers URL has not changed either. And reloading the page after adding or deleting items will not induce a POST to be resubmitted. And navigating back will not go through the whole history of added and deleted todo's but will bring the user to the previous full page request.
We can further enhance out list component with spinners on the Add and Delete buttons, and if we also add a reference to sircl-extended.js, we can add a top checkbox that, when checked/unchecked, checks/unchecks all other checkboxes, and add the onsubmit-disable
class on the FORM
element to have the buttons disabled when a call is in progress.
About Javascript code
If you are upgrading an existing application, chances are your application already contains Javascript code.
Most of that code will still work fine. Sircl is not a Javascript framework that requires you to write code on a specific manner. But there are a few point to pay attention on:
On page load initialization code
Web applications containing Javascript often have code triggered by the window.onload or document.onload events. This code is often added to the onload event handler using following notation:
document.onload = function() { /* code here...*/ };
document.addEventListener("load", function() { /* code here... */ });
or added as attribute on an element, often the BODY
element:
<body onload="/* code here...*/">
When using jQuery, a popular alternative to write document.onload handlers is to use any of those notations:
$(document).ready(function() { /* code here... */ });
$(function() { /* code here... */ });
Any of these ways will still work. But you must be aware that this executes code typically only when the whole page is loaded, and not when a page part is loaded.
If your code processes (parts of) the page, performs transformations of the HTML code, adds event handlers to elements,... it will not do so on page parts loaded through Ajax by Sircl.
To have code execute both when the initial page loads, and when a page part is loaded, make sure the Sircl core library (sircl.js) is loaded first, then provide the code as parameter of the sircl.addContentReadyHandler function, as in:
sircl.addContentReadyHandler(function() { /* code here ... */ });
Alternatively, you can also choose for the jQuery inspired short-hand notation with double $$-sign:
$$(function() { /* code here ... */ });
Event handlers
Another point of attention are event handlers. The reason is again the same: if event handlers are attached, and then the content of a page part is modified, event handlers will not operate on the lates content part.
Sircl solves this issue by adding event handlers on the document object (or in some cases, the BODY
element), relying on event bubbling for the event to be captured and handled.
For instance, the following code adds an event handler on the document object, to handle "click" events on elements with the alert
class:
$(function() {
$(document).on("click", ".alert", function(e) {
alert($(this)[0].innerText);
});
});
An example of usage:
<p class="alert">
Click on this message to see this message in an alert box.
</p>
Not that the code uses the regular jQuery document onload shorthand notation with the single $-sign function and not the Sircl double $$-sign function as the handler only needs to be installed on the document object once, when the document is loaded, and not every time a document part is changed.
HTML event handler attributes (i.e. the onclick
attribute) do work, but be aware that they are executed before Sircl event handlers, and therefore cannot be cancelled by Sircl event-actions as onclick-propagate
or onclick-confirm
attributes, as the following example illustrates:
<button onclick="alert('Clicked!');" onclick-confirm="Sure?"> Click me </button>
The onclick
handler is executed before the onclick-confirm
question is shown. As a result, the onclick-confirm
cannot prevent the onclick
handler to be executed anymore.
Building Single Page Applicatons
As soon as you start using the page part loading capabilities of Sircl, you have a page that is changing it's content, it's appearance, and by that you have a single page that can host a whole application. The above example of a ToDo list is a SPA, a Single Page Application, as long as the application is limited to that single page...
Creating Single Page Applications with Sircl in Multi-Page Mode comes down to having a single page that hosts the whole application by changing its appearance and content by using page part loading and other Sircl features.
In Multi-Page Mode, when the page remains the same, the URL to the page remains the same too and deep linking is not supported (you can not have a hyperlink to a specific state or view of the application).
To support features as URL routing and deep linking, Sircl must be used in Single-Page Mode.
When to use
Sircl's Multi-Page mode is a good solution when:
- You want to upgrade an existing application to use Sircl features with minimal effort.
- You want to write a new, multi-page site or application.
- You want to write a new simple Single Page Application where routing and deep linking are not required.
If you are writing a new site or application and want it to operate as Single Page Application supporting routing and deep linking, then use the Single-Page Mode of Sircl.