Wiki source code of Lazy Loading

Last modified by Marius Dumitru Florea on 2021/08/24

Hide last authors
Marius Dumitru Florea 1.1 1 One common and recurrent need when working on the front-end is to be able to load some UI elements after the page has been loaded. This technique is called lazy loading and it's very useful if you have UI elements that don't need to be visible right away, especially if they are heavy and thus would slow down the page load. We use this for instance to:
2
3 * load the content of a modal dialog box on demand, when the modal is first shown
4 * load the content of a tab when the tab is first activated
5 * load the content of a panel after the rest of the page has been loaded
6
7 In order to apply this technique you need to have:
8
Marius Dumitru Florea 1.2 9 * a JavaScript code that makes an asynchronous HTTP request to get the UI element that is being lazy loaded
Marius Dumitru Florea 1.1 10 * a server side script / service that generates and returns the HTML of the requested UI element
11
12 The JavaScript code usually looks like this:
13
14 {{code language="js"}}
Marius Dumitru Florea 3.1 15 require(['jquery'], function($) {
16 var lazyLoad = function(container) {
17 var serviceURL = ...
18 container.empty().addClass('loading');
19 return $.get(serviceURL).done(function(html) {
20 // Inject the HTML received from the server.
21 container.html(html);
22 // Let the others know that the DOM has been updated in order to enhance it.
23 $(document).trigger('xwiki:dom:updated', {'elements': container.toArray()});
24 }).always(function() {
25 container.removeClass('loading');
26 });
27 };
28 });
Marius Dumitru Florea 1.1 29 {{/code}}
30
31 Note that triggering the ##xwiki:dom:updated## event is very important because it allows the loaded UI element to be enhanced by other JavaScript modules (some of which may have been also lazy loaded along with the UI element). {{version since="13.7-rc-1"}}Note also that we don't have to care about loading / injecting the JavaScript or CSS required by the UI element. This is done automatically by the XWiki platform, with the help of the server side, as we'll see below.{{/version}}
32
33 A JavaScript module that enhances UI elements that are being lazy loaded looks like this:
34
35 {{code language="js"}}
Marius Dumitru Florea 2.1 36 require(['jquery'], function($) {
37 var init = function(event, data) {
38 var container = $((data && data.elements) || document);
39 container.find('.some-selector').each(function() {
Marius Dumitru Florea 3.1 40 // Enhance the matched UI elements.
Marius Dumitru Florea 2.1 41 ...
42 });
43 };
44
Marius Dumitru Florea 3.1 45 // Initialize UI elements that are lazy loaded.
Marius Dumitru Florea 2.1 46 $(document).on('xwiki:dom:updated', init);
Marius Dumitru Florea 3.1 47 // Initialize UI elements that are already loaded (present on the page).
Marius Dumitru Florea 2.1 48 $(init);
49 });
Marius Dumitru Florea 1.1 50 {{/code}}
51
52 For the server side we use most of the time:
53
54 * either a script rendering macro (e.g. [[Velocity Macro>>extensions:Extension.Velocity Macro]]) within a wiki page(((
55 {{code language="js"}}
Marius Dumitru Florea 3.1 56 var documentReference = XWiki.Model.resolve('Path.To.Page', XWiki.EntityType.Document);
57 var serviceURL = new XWiki.Document(documentReference).getURL('get');
Marius Dumitru Florea 1.1 58 {{/code}}
59 )))
60 * or a Velocity template(((
61 {{code language="js"}}
Marius Dumitru Florea 3.1 62 var serviceURL = XWiki.currentDocument.getURL('get', 'xpage=templateName');
Marius Dumitru Florea 1.1 63 {{/code}}
64 )))
65
66 If we chose to implement the server side in a wiki page using the Velocity macro then the code could look like this:
67
68 {{code language="none"}}
Marius Dumitru Florea 3.1 69 #template('display_macros.vm')
70 #initRequiredSkinExtensions()
71 ## Generate the HTML for the requested UI element.
72 ...
73 ## Use the skinx plugin to pull required skin extensions (JavaScript and CSS).
74 #set ($discard = $xwiki.ssx.use('Path.To.Style'))
75 #set ($discard = $xwiki.jsx.use('Path.To.JavaScript'))
76 ...
77 #getRequiredSkinExtensions($requiredSkinExtensions)
78 ## We use the X-XWIKI-HTML-HEAD custom HTTP header to return the required JavaScript and CSS resources. Note that the
79 ## HTML of the UI element is returned in the response body.
80 #set ($discard = $response.setHeader('X-XWIKI-HTML-HEAD', $requiredSkinExtensions))
Marius Dumitru Florea 1.1 81 {{/code}}
82
Marius Dumitru Florea 4.1 83 {{version since="13.7-rc-1"}}The resources we specify using the ##X-XWIKI-HTML-HEAD## custom HTTP header will be injected automatically in the page head.{{/version}}

Get Connected