Wiki source code of XWiki JavaScript API

Last modified by Simon Urli on 2022/09/14

Hide last authors
Manuel Smeria 17.3 1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
Sergiu Dumitriu 9.1 4
Manuel Smeria 17.3 5 = Observable XWiki Events =
Jerome 1.1 6
7 Stay in touch with what happens in the wiki! XWiki will fire custom javascript events on certain moment and upon certain actions that occur in the navigation flow.
8
Sergiu Dumitriu 9.1 9 Event names are build on the following model: ##xwiki:modulename:eventname##. Your JavaScript script or extension can get notified of such an event the following way:
Jerome 1.1 10
Sergiu Dumitriu 10.1 11 {{code language="javascript"}}
12 document.observe("xwiki:modulename:eventname", function(event) {
13 // Here, do something that will be executed at the moment the event is fired
14 doSomething();
Jerome 1.1 15
Sergiu Dumitriu 10.1 16 // The event can have an option memo object to pass to its observers some information:
17 console.log(event.memo.somethingINeedToKnow);
Sergiu Dumitriu 9.1 18 });
19 {{/code}}
Jerome 1.1 20
Manuel Smeria 17.3 21 Check out the real examples below or read more about [[Prototype.js's event system>>http://prototypejs.org/doc/latest/dom/Element/fire/]].
Jerome 1.1 22
Manuel Smeria 17.3 23 == DOM Events (xwiki.js) ==
Jerome 1.1 24
Simon Urli 45.1 25 * (((
26 **##xwiki:dom:loaded##**
Michael Hamann 46.1 27 This event is similar to [[prototype's dom:loaded event>>http://prototypejs.org/doc/latest/dom/document/observe/]], with the difference that in the time-lapse between ##dom:loaded## and ##xwiki:dom:loaded##, XWiki may have transformed the DOM. Example of DOM transformations operated by XWiki is setting the right target of links that have rel="external" attribute so that the document can be XHTML valid and still have the desired effect, making internal rendering error messages expandable, insert document template handlers for links to non-existent documents, and so on. In the future there might be more transformations operated by XWiki upon DOM initialization. This event is meant for code to be notified of loading of the XWiki-transformed version of the initial DOM. As ##dom:loaded##, it can be used as follows:
28
29 (((
Sergiu Dumitriu 17.2 30 {{code language="javascript"}}
Jerome 1.1 31 document.observe("xwiki:dom:loaded", function(){
Sergiu Dumitriu 10.1 32 // Initialization that can rely on the fact the DOM is XWiki-tranformed goes here.
Jerome 1.1 33 });
Vincent Massol 38.1 34 {{/code}}
Simon Urli 45.1 35 )))
36
37 (((
Manuel Smeria 17.3 38 {{info}}
39 It is recommended to bind startup scripts to this event instead of ##window.load## or ##document.dom:loaded##.
40 {{/info}}
41 )))
Simon Urli 45.1 42 )))
Manuel Smeria 17.3 43
Sergiu Dumitriu 11.1 44 * **##xwiki:dom:loading##**
Sergiu Dumitriu 9.1 45 ##xwiki:dom:loading## is sent between ##dom:loaded## and ##xwiki:dom:loaded##, before XWiki changes the DOM. This is the event that should start all scripts making important DOM changes that other scripts should see.
Sergiu Dumitriu 16.1 46 * **##xwiki:dom:updated##**
Sergiu Dumitriu 17.1 47 This event is sent whenever an important change in the DOM occurs, such as loading new content in a dialog box or tab, or refreshing the document content. Scripts that add behavior to certain elements, or which enhance the DOM, should listen to this event as well and re-apply their initialization process on the updated content, the same way that the whole DOM is enhanced on ##xwiki:dom:loaded##. The list of new or updated elements is sent in the ##event.memo.elements## property. For example:(((
48 {{code language="javascript"}}
49 var init = function(elements) {
50 // Search for special content to enhance in each DOM element in the "elements" list and enhance it
51 elements.each(function(element) {
52 element.select('.someBehavioralClass').each(function(item) {
53 enhance(item);
Sergiu Dumitriu 17.2 54 });
55 });
Sergiu Dumitriu 17.1 56 }
57 ['xwiki:dom:loaded', 'xwiki:dom:updated'].each(function(eventName) {
58 document.observe(eventName, function(event) {
59 init(event.memo && event.memo.elements || [document.documentElement]);
Sergiu Dumitriu 17.2 60 });
Sergiu Dumitriu 17.1 61 });
62 {{/code}}
Sergiu Dumitriu 1.5 63
Denis Gervalle 15.1 64 {{warning}}
65 If your script is loaded **deferred**, all these events may be triggered **before your script is executed** and therefore **before it has the ablity to observe these events**. Since 3.1.1, to prevent your handler to never being called, never use ##dom:loaded## anymore, and check ##XWiki.isInitialized## before waiting for ##xwiki:dom:loading##, and ##XWiki.domIsLoaded## before waiting for ##xwiki:dom:loaded##. If the flag is true, you should proceed immediately with your handler. Here is a simple construct to properly handle this:(((
66 {{code}}
67 function init() {
68 // This is your initialization handler, that you generally hook to xwiki:dom:loaded
69 }
70 (XWiki && XWiki.domIsLoaded && init()) || document.observe("xwiki:dom:loaded", init);
71 {{/code}})))
72 {{/warning}}
73
Manuel Smeria 17.3 74 == Document content events (actionButtons.js) ==
Sergiu Dumitriu 3.1 75
Sergiu Dumitriu 10.1 76 * **##xwiki:document:saved##**
77 This event is sent after the document has been successfully saved in an asynchronous request (i.e. after clicking the //Save and Continue// button).
78 * **##xwiki:document:saveFailed##**
79 This event is sent when a save and continue attempt failed for some reason. The XMLHttpRequest response object is sent in the memo, as ##event.memo.response##.
Sergiu Dumitriu 3.1 80
Manuel Smeria 17.3 81 == Action events (actionButtons.js) ==
Jerome 1.1 82
Simon Urli 45.1 83 * **##xwiki:actions:cancel##**
Sergiu Dumitriu 3.2 84 This event is sent after the user clicks the "Cancel" button of an editor (Wiki, WYSIWYG, object, rights, etc.), but before actually cancelling the edit.
Marius Dumitru Florea 36.1 85 * **##xwiki:actions:beforePreview##** (7.4.1+, 8.0M1+)
86 This event is sent after the user clicks the "Preview" button from an edit mode, but before the edit form is validated. You can use this event to update the form fields before they are submitted to the preview action.
87 * **##xwiki:actions:preview##**
88 This event is sent after the edit form has been validated, as a result of the user clicking the "Preview" button from an edit mode, but before the form is submitted. The event is fired only if the edit form is valid.
Marius Dumitru Florea 36.2 89 * **##xwiki:actions:beforeSave##** (7.4.1+, 8.0M1+)
Marius Dumitru Florea 36.1 90 This event is sent after the user clicks the "Save" or "Save & Continue" button from an edit mode, but before the edit form is validated. You can use this event to update the form fields before they are submitted to the save action.
Simon Urli 45.1 91 * (((
92 **##xwiki:actions:save##**
Michael Hamann 46.1 93 This event is sent after the edit form has been validated, as a result of the user clicking the "Save" or "Save & Continue" button from an edit mode, but before the form is submitted. The event is fired only if the edit form is valid. A memo is available if you need to know if the intend is to continue after the save, in ##event.memo['continue']##. You can use it as follows:
94
95 (((
Sergiu Dumitriu 10.1 96 {{code language="javascript"}}
Sergiu Dumitriu 12.1 97 document.observe("xwiki:actions:save", function(event){
98 var doContinue = event.memo['continue'];
Sergiu Dumitriu 10.1 99 if (doContinue) {
100 // do something specific
101 }
Jerome 1.1 102 });
Vincent Massol 38.1 103 {{/code}}
Simon Urli 45.1 104 )))
105
106 (((
Manuel Smeria 17.3 107 {{warning}}
108 While most properties can be accessed as ##event.memo.property##, this doesn't work with ##event.memo.continue## since ##continue## is a reserved keyword.
109 {{/warning}}
Simon Urli 45.1 110 )))
111
112 (((
Sergiu Dumitriu 10.1 113 All these events contain as extra information, in the second parameter sent to event listeners (the memo), the original click event (if any, and which can be stopped to prevent the action from completing), and the form being submitted, as ##event.memo.originalEvent##, and ##event.memo.form## respectively.
Manuel Smeria 17.3 114 )))
Simon Urli 45.1 115 )))
Sergiu Dumitriu 1.5 116
Manuel Smeria 17.3 117 == Document extra events (xwiki.js) ==
Jerome 1.1 118
Sergiu Dumitriu 11.1 119 * **##xwiki:docextra:loaded##**
120 This event is fired upon reception of the content of a document footer tab by AJAX. This event is useful if you need to operate transformations of the received content. You can filter on which tab content to operate (comments or attachment or information or ...) using the event memo. The DOM element in which the retrieved content has been injected is also passed to facilitate transformations.(((
Sergiu Dumitriu 10.1 121 {{code language="javascript"}}
Jerome 1.1 122 document.observe("xwiki:docextra:loaded", function(event){
123 var tabID = event.memo.id;
124 if (tabID == "attachments") {
125 // do something with the attachments tab retrieved content.
126 doSomething(event.memo.element);
127 }
128 });
Sergiu Dumitriu 9.1 129 {{/code}}
Sergiu Dumitriu 10.1 130 )))
Sergiu Dumitriu 9.1 131 * **##xwiki:docextra:activated##**
132 This event is fired upon activation of a tab. It differs from the loaded event since tabs are loaded only once if the user clicks going back and forth between tabs. This event will notify of each tab activation, just after the tab content is actually made visible. The tab ID is passed in the memo as for ##xwiki:docextra:loaded##
Oana Florea 4.1 133
Manuel Smeria 17.3 134 == Suggest events (ajaxSuggest.js) ==
Ecaterina Moraru (Valica) 8.1 135
Sergiu Dumitriu 9.1 136 * **##xwiki:suggest:selected##** (since 2.3)
Sergiu Dumitriu 11.1 137 This event is fired on the target input when a value was selected.
Ecaterina Moraru (Valica) 8.1 138
Manuel Smeria 17.3 139 == Fullscreen events (fullScreenEdit.js) ==
Oana Florea 4.1 140
Marius Dumitru Florea 14.1 141 * **##xwiki:fullscreen:enter##** (since 3.0 M3) (fired before entering full screen editing)
142 * **##xwiki:fullscreen:entered##** (since 2.5.1) (fired after entering full screen editing)
143 * **##xwiki:fullscreen:exit##** (since 3.0 M3) (fired before exiting full screen editing)
144 * **##xwiki:fullscreen:exited##** (since 2.5.1) (fired after exiting full screen editing)
145 * **##xwiki:fullscreen:resized##** (since 2.5.1)
Ecaterina Moraru (Valica) 6.1 146
Sergiu Dumitriu 11.1 147 All events have the target DOM element in ##event.memo.target##.
148
Manuel Smeria 17.3 149 == Annotations events (AnnotationCode/Settings jsx) ==
Ecaterina Moraru (Valica) 6.1 150
Sergiu Dumitriu 9.1 151 * **##xwiki:annotations:filter:changed##**
152 * **##xwiki:annotations:settings:loaded##**
Ecaterina Moraru (Valica) 6.1 153
Manuel Smeria 17.3 154 == Livetable events (livetable.js) ==
Ecaterina Moraru (Valica) 6.1 155
Sergiu Dumitriu 11.1 156 * **##xwiki:livetable:newrow##** (##event.memo.row## holds the new row)
Sergiu Dumitriu 9.1 157 * **##xwiki:livetable:loadingEntries##** (since 2.3 RC1)
Sergiu Dumitriu 11.1 158 * **##xwiki:livetable:receivedEntries##** (since 2.3 RC1) (##event.memo.data## contains the received JSON data)
159 * **##xwiki:livetable:loadingComplete##** (since 2.4 M1) (##event.memo.status## contains the response status code)
Sergiu Dumitriu 9.1 160 * **##xwiki:livetable:displayComplete##** (since 2.4 M1)
161 * **##xwiki:livetable:ready##** (since 2.4.4)
Denis Gervalle 15.1 162 * **##xwiki:livetable:loading##** (since 3.1.1) (should be used in place of ##xwiki:dom:loading## to startup livetables)
Sergiu Dumitriu 11.1 163
164 The livetable sends both generic events, named as above, and events specific to each livetable, containing the table name on the third position, such as ##xwiki:livetable:alldocs:loadingEntries##. The generic event has the table name in the memo, as ##event.memo.tableId##.
Caleb James DeLisle 18.1 165
Michael Hamann 46.1 166 == Live Data events (Logic.js) ==
167
168 * **##xwiki:livedata:instanceCreated##** (since 14.4 RC1) triggered when the DOM elements have been created and the instance initialized but potentially before entries are loaded
169 * ##**xwiki:livedata:beforeEntryFetch**## (since 13.4 RC1)
170 * ##**xwiki:livedata:afterEntryFetch**## (since 13.4 RC1)
171 * ##**xwiki:livedata:layoutChange**## (since 12.10)
172 * ##**xwiki:livedata:layoutLoaded**## (since 13.4 RC1)
173 * ##**xwiki:livedata:pageChange**## (since 12.10) with ##pageIndex## and ##previousPageIndex##
174 * ##**xwiki:livedata:pageSizeChange**## (since 12.10) with ##pageSize## and ##previousPageSize##
175 * ##**xwiki:livedata:select**## (since 12.10) with ##entry##
176 * ##**xwiki:livedata:deselect**## (since 12.10) with ##entry##
177 * ##**xwiki:livedata:selectGlobal**## (since 12.10)
Simon Urli 47.1 178 * ##**xwiki:livedata:sort**## (since 12.10) with ##property##, ##level## or ##type, and ##descending
Michael Hamann 46.1 179 * ##**xwiki:livedata:filter**## (since 12.10) with ##type##, ##property## and ##removedFilters## or ##oldEntry##/##newEntry##
Simon Urli 47.1 180 * ##**xwiki:livedata:entriesUpdated**## (since 14.8RC1)
Michael Hamann 46.1 181
182 All events are dispatched on the container that is wrapping the Live Data as native custom events. All events have the Live Data instance set as ##detail.livedata##. Additional properties are available depending on the event and the situation in which the event is triggered, some of them are listed above. Before 14.4RC1 and 13.10.6, the events were triggered on a detached DOM element and thus it was not really possible to register event listeners for them.
183
Caleb James DeLisle 19.1 184 = RequireJS and jQuery APIs =
Caleb James DeLisle 18.1 185
186 By default XWiki uses PrototypeJS which is bound to the $ symbol. Starting in XWiki 5.2, you may use jQuery by //requiring// it using the [[RequireJS>>http://requirejs.org/]] AMD standard. To do this you would write your code as follows:
187
188 {{code language="javascript"}}
189 require(['jquery'], function ($) {
190 $('#xwikicontent').append('<p>Inside of this function, $ becomes jquery!</p>');
191 });
192 {{/code}}
193
194 The best part is, any scripts which are loaded using require are loaded //asynchronously// (all at the same time) and if they are not required, they are never loaded at all.
Guillaume Delhumeau 20.1 195
Marius Dumitru Florea 37.1 196 == Deferred Dependency Loading ==
197
198 Loading (transitive) dependencies through RequireJS works if those modules are known by RequireJS. In order to make a module known you need to tell RequireJS where to load that module from. A module can be located in various places: in a WebJar, in the skin, in a JSX object or even in a file attached to a wiki page. If the module you need is common enough that is loaded on every page (like the 'jquery' module) then chances are it is already known (configured in javascript.vm). Otherwise you need to configure the dependency by using require.config().
199
200 {{code language="js"}}
201 require.config({
202 paths: {
203 module: "path/to/module"
204 },
205 shim: {
206 module: {
207 exports: 'someGlobalVariable',
208 deps: ['anotherModule']
209 }
210 }
211 });
212 {{/code}}
213
214 If two scripts need the same dependency then they will have to duplicate the require configuration. In order to avoid this you could move the configuration in a separate file and write something like this:
215
216 {{code language="js"}}
217 require(['path/to/config'], function() {
218 require(['module'], function(module) {
219 // Do something with the module.
220 });
221 });
222 {{/code}}
223
224 but you would still duplicate the configuration path in both scripts. Now, suppose that one of the scripts is only extending a feature provided by the dependency module. This means that it doesn't necessarily need to bring the dependency. It only needs to extend the module if it's present. This can be achieved starting with XWiki 8.1M1 like this:
225
226 {{code language="js"}}
227 require(['deferred!module'], function(modulePromise) {
228 modulePromise.done(function(module) {
229 // Do something with the module, if the module is loaded by someone else.
230 });
231 });
232 {{/code}}
233
234 In other words, the script says to RequireJS "let me know when this module is loaded by someone else" (someone else being an other script on the same page). This looks similar with the solution where the require configuration is in a separate file, but the advantage is that the path is not duplicated (i.e. we can move the module to a different path without affecting the scripts that use it).
235
236 Examples where this could be useful:
237
238 * extend the tree widget (if it's available on the current page)
239 * extend the WYSIWYG editor (if it's loaded on the current page)
240
241 An alternative is for each module that wants to support extensions to fire some custom events when they are loaded.
242
Marius Dumitru Florea 24.1 243 == Bridging custom XWiki events between Prototype and jQuery ==
Marius Dumitru Florea 23.1 244
245 Starting with XWiki 6.4 you can catch from jQuery the custom XWiki events that are fired from Prototype.
246
247 {{code language="js"}}
248 require(['jquery', 'xwiki-events-bridge'], function($) {
249 $('.some-element').on('xwiki:moduleName:eventName', function(event, data) {
250 // Here, do something that will be executed at the moment the event is fired.
251 doSomething();
252
253 // The passed data is a reference to the event.memo from Prototype.
254 console.log(data.somethingINeedToKnow);
255 });
256 });
257 {{/code}}
258
Marius Dumitru Florea 24.1 259 Starting with XWiki 7.1M1 the event listeners registered from Prototype are notified when a custom XWiki event is fired using the jQuery API. This doesn't mean you should write new event listeners using Prototype but that you can rely on existing event listeners until they are rewritten using jQuery.
260
261 {{code language="js"}}
262 // Prototype (old code that you don't have time to rewrite)
263 document.observe('xwiki:dom:updated', function(event) {
264 event.memo.elements.each(function(element) {
265 // Do something.
266 });
267 });
268 ...
Marius Dumitru Florea 24.2 269 // jQuery (new code, in a different file/page)
Marius Dumitru Florea 24.1 270 require(['jquery', 'xwiki-events-bridge'], function($) {
271 $(document).trigger('xwiki:dom:updated', {'elements': $('.some-container').toArray()});
272 });
273 {{/code}}
274
Guillaume Delhumeau 26.1 275 = Get some information about the current document {{info}}(Since 6.3M2){{/info}} =
Guillaume Delhumeau 20.1 276
Vincent Massol 33.2 277 In your javascript's applications, you can get (meta) information about the current document, though an AMD module.
Guillaume Delhumeau 21.1 278
Guillaume Delhumeau 20.1 279 {{code language="javascript"}}
280 require(['xwiki-meta'], function (xm) {
Guillaume Delhumeau 35.1 281 xm.documentReference // since 7.3M2, get the reference of the current document (as a DocumentReference object).
282 xm.document // get the current document (eg: Main.WebHome) -- deprecated since 7.3M2, use documentReference instead
283 xm.wiki // get the current wiki (eg: xwiki) -- deprecated since 7.3M2, use documentReference instead
284 xm.space // get the current space (eg: Main) -- deprecated since 7.3M2, use documentReference instead
285 xm.page // get the current page name (eg: WebHome) -- deprecated since 7.3M2, use documentReference instead
286 xm.version // get the current document version (eg: 1.1)
287 xm.restURL // get the REST url of the current doc (eg: /xwiki/rest/wikis/xwiki/spaces/Main/pages/WebHome)
288 xm.form_token // get the current CSRF token that you should pass to your scripts to avoid CSRF attacks.
Guillaume Delhumeau 43.1 289 xm.userReference // since 10.4RC1 and 9.11.5, get the reference of the current user
Simon Urli 45.1 290 xm.isNew // since 11.2RC1, define if the current document is new or not
291 xm.locale // since 12.3RC1, get the locale of the current document
Guillaume Delhumeau 20.1 292 });
293 {{/code}}
Guillaume Delhumeau 22.1 294
295 {{warning}}
296 It is actually the only clean way. In the past, we used to add some <meta> tags in the <head> section of the page, but is not even valid in HTML5. So now we have introduced this API that we will maintain, meanwhile relying on any other element in the page could be broken in the future!
297 {{/warning}}
Guillaume Delhumeau 28.1 298
299 == Be retro-compatible with versions older than 6.3 ==
300
301 If you want to be compatible with older version, you can use this trick:
302
303 {{code language="javascript"}}
304 require(['xwiki-meta'], function (xm) {
305 // Note that the require['xwiki-meta'] (meta information about the current document) is not available on
306 // XWiki versions < 6.3, then we get these meta information directly from the DOM.
307 var document = xm ? xm.document : $('meta[name="document"]').attr('content');
308 var wiki = xm ? xm.wiki : $('meta[name="wiki"]').attr('content');
309 var space = xm ? xm.space : $('meta[name="space"]').attr('content');
310 var page = xm ? xm.wiki : $('meta[name="page"]').attr('content');
311 var version = xm ? xm.version : $('meta[name="version"]').attr('content');
312 var restURL = xm ? xm.restURL : $('meta[name="restURL"]').attr('content');
313 var form_token = xm ? xm.form_token : $('meta[name="form_token"]').attr('content');
Guillaume Delhumeau 30.1 314 });
Guillaume Delhumeau 28.1 315 {{/code}}
Marius Dumitru Florea 31.1 316
Marius Dumitru Florea 32.3 317 = Work with Entity References {{info}}(Since 4.2M1){{/info}} =
Marius Dumitru Florea 31.1 318
Marius Dumitru Florea 32.3 319 You can resolve and serialize Entity References on the client side easily:
Marius Dumitru Florea 31.1 320
321 {{code language="js"}}
322 var documentReference = XWiki.Model.resolve('wiki:Space.Page', XWiki.EntityType.DOCUMENT);
323 var attachmentReference = new XWiki.AttachmentReference('logo.png', documentReference);
324 XWiki.Model.serialize(attachmentReference);
325 {{/code}}
326
327 You can check the full API [[here>>https://github.com/xwiki/xwiki-platform/blob/master/xwiki-platform-core/xwiki-platform-web/src/main/webapp/resources/uicomponents/model/entityReference.js]].
328
Marius Dumitru Florea 32.2 329 Starting with XWiki 7.2M1 the ##XWiki.Model## JavaScript API is supporting nested spaces:
Marius Dumitru Florea 31.1 330
331 {{code language="js"}}
332 var documentReference = XWiki.Model.resolve('wiki:Path.To.My.Page', XWiki.EntityType.DOCUMENT);
333 documentReference.getReversedReferenceChain().map(function(entityReference) {
334 return entityReference.type + ': ' + entityReference.name
335 }).join()
336 // Will produce:
337 // 0: wiki,1: Path,1: To,1: My,2: Page
338 {{/code}}
339
Marius Dumitru Florea 32.1 340 Starting with 7.2M1 you can also pass a 'provider' as the third argument to ##XWiki.Model.resolve()##. The provider is used to fill missing references, and it is either a function that gets the entity type, an array of entity names or an entity reference.
Marius Dumitru Florea 31.1 341
342 {{code language="js"}}
343 var documentReference = XWiki.Model.resolve('Page', XWiki.EntityType.DOCUMENT, function(type) {
344 switch(type) {
345 case: XWiki.EntityType.WIKI:
346 return 'wiki';
347 case: XWiki.EntityType.SPACE:
348 return 'Space';
349 default:
350 return null;
351 }
352 });
353 // Produces wiki:Space.Page
354
355 var documentReference = XWiki.Model.resolve('Page', XWiki.EntityType.DOCUMENT, ['wiki', 'Space']);
356 // Same output
357
358 var spaceReference = new XWiki.SpaceReference('wiki', 'Space');
359 var documentReference = XWiki.Model.resolve('Page', XWiki.EntityType.DOCUMENT, spaceReference);
360 // Same output
361 {{/code}}
Vincent Massol 33.1 362
363 Starting with 7.2M2 you can construct Reference to Nested Spaces and a new ##equals()## method has been added. Examples using Jasmine:
364
365 {{code language="js"}}
366 // Construct a Nested Space reference
367 var reference = new XWiki.SpaceReference('wiki', ['space1', 'space2']);
368 expect(XWiki.Model.serialize(reference)).toEqual('wiki:space1.space2');
369 reference = new XWiki.DocumentReference('wiki', ['space1', 'space2'], 'page');
370 expect(XWiki.Model.serialize(reference)).toEqual('wiki:space1.space2.page');
371 // Construct a non-Nested Space reference
372 reference = new XWiki.SpaceReference('wiki', 'space');
373 expect(XWiki.Model.serialize(reference)).toEqual('wiki:space');
374 // Try passing non-valid space parameters
375 expect(function() {new XWiki.SpaceReference('wiki', [])}).toThrow('Missing mandatory space name or invalid type for: []');
376 expect(function() {new XWiki.SpaceReference('wiki', 12)}).toThrow('Missing mandatory space name or invalid type for: [12]');
377
378 // Equals() examples
379 var reference1 = new XWiki.DocumentReference('wiki', ['space1', 'space2'], 'page');
380 var reference2 = new XWiki.DocumentReference('wiki', ['space1', 'space2'], 'page');
381 var reference3 = new XWiki.DocumentReference('wiki2', ['space1', 'space2'], 'page');
382 expect(reference1.equals(reference2)).toBe(true);
383 expect(reference1.equals(reference3)).toBe(false);
384 {{/code}}
385
Thomas Mortagne 34.1 386 In 7.2M2 a new XWiki.EntityReferenceTree class which partially mimic Java EntityReferenceTree on Javascript side. There is not much yet, it was mostly introduced to make easier to manipulate a serialized Java EntityReferenceTree.
387
388 {{code}}
389 this.entities = XWiki.EntityReferenceTree.fromJSONObject(transport.responseText.evalJSON());
390 {{/code}}
Vincent Massol 38.1 391 )))
Oana Florea 43.2 392
Oana Florea 43.3 393 = Related =
Simon Urli 45.1 394
Oana Florea 43.2 395 {{velocity}}
396 #set($tag = 'javascript')
397 #set ($list = $xwiki.tag.getDocumentsWithTag($tag))
398 (((
399 (% class="xapp" %)
Oana Florea 43.4 400 == $services.localization.render('xe.tag.alldocs', ["//${tag}//"]) ==
Oana Florea 43.2 401
402 #if ($list.size()> 0)
403 {{html}}#displayDocumentList($list false $blacklistedSpaces){{/html}}
404 #else
405 (% class='noitems' %)$services.localization.render('xe.tag.notags')
406 #end
407 )))
408 {{/velocity}}
Vincent Massol 44.1 409
410 = Example of understanding initialization =
411
Vincent Massol 44.2 412 {{warning}}
413 Please note that the following example is very specific:
Simon Urli 45.1 414
Vincent Massol 44.2 415 * It applies to old JavaScript code written using Prototype.js. The more recent recommendation is to use RequireJS and JQuery.
416 * It doesn't apply fully to any page having a LiveTable because the Rights UI has custom code to load the LiveTable.
417 {{/warning}}
418
Vincent Massol 44.1 419 Let's take the example of the Rights page of the Admin UI and understand how its LiveTable is initialized.
420
421 The browser will read the HTML from top to bottom. We have the following HTML content:
422
Simon Urli 45.1 423 {{code language="html"}}
Vincent Massol 44.1 424 ...
425 <head>
426 ...
427 <script type='text/javascript' src='/xwiki/resources/js/prototype/prototype.js?cache-version=1584467090000'></script>
428 ...
429 <script type='text/javascript' src='/xwiki/bin/skin/resources/js/xwiki/xwiki.js?cache-version=1584467090000&defer=false&amp;minify=false'></script>
430 ...
431 <script type='text/javascript' src='/xwiki/bin/skin/resources/js/xwiki/table/livetable.js?cache-version=1584467090000&minify=false' defer='defer'></script>
432 ...
433 </head>
434 <body>
435 ...
436 function startup() {
437 ... Rights LT init...
438 }
439 ...
440 (XWiki && XWiki.isInitialized && startup()) || document.observe('xwiki:livetable:loading', startup);
441 ...
442 {{/code}}
443
444 So here are the steps performed:
Simon Urli 45.1 445
446 1. ##prototype.js## is executed first and registers a function (~{~{code}document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);~{~{/code}}) to execute when the ##DOMContentLoaded## event is sent. This event is sent after the DOM has been parsed, thus after the scripts of the page have been executed. The ##fireContentLoadedEvent## function will fire the [[##dom:loaded## event>>http://api.prototypejs.org/dom/document/observe/]] when called.
Vincent Massol 44.1 447 1. ##xwiki.js## is executed and registers a function ({{code}}document.observe("dom:loaded", XWiki.initialize.bind(XWiki)){{/code}}) to execute when the ##dom:loaded## event is sent. In turn it'll fire 2 events ##xwiki:dom:loading## and ##xwiki:dom:loaded## when called.
448 1. ##livetable.js## is not executed at this stage since it's marked as ##defer##.
449 1. The Rights UI is executed and {{code}}XWiki && XWiki.isInitialized && startup(){{/code}} evaluates to false since the XWiki object has not been initialized yet at this stage. However it registers a function for the ##xwiki:livetable:loading## event.
450 1. The browser gets to the end of the HTML, and [[reads the ##livetable.js## script that was marked as deferred>>https://javascript.info/onload-ondomcontentloaded#domcontentloaded]]. The following executes: {{code}}(XWiki.isInitialized && init()) || document.observe('xwiki:dom:loading', init);{{/code}}. The {{code}}XWiki && XWiki.isInitialized && startup(){{/code}} part evaluates to false since the XWiki object has not been initialized yet. The ##init## function is registered for the ##xwiki:dom:loading## event. When fired, it will trigger the ##xwiki:livetable:loading## event.
451 1. Now that the DOM has been read, the browser sends the ##DOMContentLoaded## event.
452 1. Thus the prototype function is called and the ##dom:loaded## event is triggered.
453 1. Thus the ##xwiki.js##'s ##initialize## function is called and the ##xwiki:dom:loading## event is fired.
454 1. Thus the ##livetable.js##'s ##init## function is called and the ##xwiki:livetable:loading## event is fired.
455 1. Thus the Rights UI's ##startup## function is called and its LiveTable is initialized.

Get Connected