Show last authors
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
9 * a JavaScript code that makes an asynchronous HTTP request to get the UI element that is being lazy loaded
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"}}
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 });
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"}}
36 require(['jquery'], function($) {
37 var init = function(event, data) {
38 var container = $((data && data.elements) || document);
39 container.find('.some-selector').each(function() {
40 // Enhance the matched UI elements.
41 ...
42 });
43 };
44
45 // Initialize UI elements that are lazy loaded.
46 $(document).on('xwiki:dom:updated', init);
47 // Initialize UI elements that are already loaded (present on the page).
48 $(init);
49 });
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"}}
56 var documentReference = XWiki.Model.resolve('Path.To.Page', XWiki.EntityType.Document);
57 var serviceURL = new XWiki.Document(documentReference).getURL('get');
58 {{/code}}
59 )))
60 * or a Velocity template(((
61 {{code language="js"}}
62 var serviceURL = XWiki.currentDocument.getURL('get', 'xpage=templateName');
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"}}
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))
81 {{/code}}
82
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