Javascript questions for skins

Hello,

We want to make som significant changes in the UI and have been experimenting with the several ways to do this. Because of the way we have our build cycle set up at the moment we would like to work with a SkinPage and add Javascript libraries there as an object (JavaScriptExtension).

We made some PoC to get this working. Resulting in copy and pasting a JQuiry library in a JavaScriptExtension and surround it with require([‘jquery’, function($ …

I wonder if it is possible to add the original library as an attachment to the skin and read this attachment in the JavaScriptExtension.

In this way, updates to the library we can manage by updating the attachment,

With a webjar you can use $services.webjars.url() is there something similar?

Regards
Jurjen

Also note that we have a maven plugin to change wiki pages during the build:

AFAICS we don’t have any doc for it but you could check the source code and the tests.

Note sure if this helps but mentioning it just in case…

See https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/FrontendResources/IntegratingJavaScriptLibraries/ .

Hi,

thank you for the replies. I already read the documentation. In general I have some difficulties reading the documentation.

Because there aren’t many tutorials available in the community, in comparison to for example the PHP Laravel Framework, it is difficult to quickly understand and learn xwiki development. In the documentation a certain level of understanding of all components is expected.

For me as a novice Java/Velocity the gap to the documentation is to big. Several questions asked here come forth from that gap.

Right now we have build several packages that we can install true the extensions. Changes to the skin are made by updating the corresponding skin and create additions and overrides. In this way I would like to add external (JQUERY) JavaScripts. Reading the documentation I see the best way is to build this based upon a file based source, we apply to every installation on the farm. This would result in setting up a separate buildproces for the skin and a second way of deploying changes. (Packages/extensions and file based changes). The best way to manage this, is to include the skin in a docker image when updating the farm. This becomes complex fast. Making building apps on the XWIKI platform not cost effectively.

So is there a way we can include the javascript in the skinpage? Because I don’t understand the documentation enough. Either because I do not have the right level of java skills or how the JSSX en CSSX works. Is it possible to include a jquery JS, without copy ad pasting it as an object in the skin?

Regards
Jurjen

Where did you get that from? The documentation I linked talks about WebJars that you can declare as dependencies to your extension (Maven POM file) and that the Extension Manager can install automatically. The documentation also explains how to load the JavaScript from the WebJar using RequrieJS.

I said that based upon my understanding of the available tutorials and documentation.

Apparently I don’t understand the documentation or I do not have the appropriate skills, knowledge, etc to understand the documentation and make the right conclusions.

That is exactly why I would like to see more in depth tutorials. It will make the platform more accessible for developers/enthousiasts not having an in-depth experience in the development of java, maven, webjars, etc.

@JurjenRoels what part of Integrating JavaScript Libraries in XWiki (XWiki.org) is unclear? Maybe I can improve it. Note that it links to two examples How to integrate React and XWiki? (XWiki.org) and How to integrate d3js and XWiki? (XWiki.org) which indicate the steps you need to do:

  • install the WebJars (or declare them as dependencies of your extension)
  • create a wiki page with a JSX object to hold your JavaScript code, using RequireJS to load your JavaScript dependnecies
  • load this JSX on demand where you need it

Hi,

for the documentation this might be an interesting tutorial.

I have added the following webjar: GitHub - lou/multi-select: A user-friendlier drop-in replacement for the standard select with multiple attribute activated. by installing it through the extension manager: -search for: org.webjars.bower:multiselect en version 0.9.12

After that I went to the defaultSkin and created a new object of the XWiki.JavaScriptExtension class and put the following code in the object:

   require(['jquery', "$!services.webjars.url('org.webjars.bower:multiselect', 'js/jquery.multi-select.js', {'evaluate': false})"], function($) {
   jQuery('select[multiple]').multiSelect({
          selectableHeader: "<div class='custom-header'>All Items</div>",
          selectionHeader: "<div class='custom-header'>Selected Items</div>",
      });
 });

This initializes the javascript. To figure out what file to include I had to check on the server what the right path was, based upon the git source: /webjars//multiselect/0.9.12/js/jquery.multi-select.js

after that I made the init function on JQuery and added that to the require statement.

Now I am figuring out how to include de CSS. At the moment I have copied the CSS to an XWiki.StyleSheetExtension class.

This Webjar transforms a multiselect to a two column left-right multiselect

The whole example with CSS I will post here as well. It shows you how to extend JQUERY.

To make the CSS working I made an override Class: XWikiSkinFileOverrideClass for htmlheader.vm

Copied the content of htmlheader.vm and made a change at:

    ## Hook for inserting Link extensions. This will be replaced with the pulled link references.
    ## ---------------------------------------------------------------------------------------------------------------
    <!-- com.xpn.xwiki.plugin.skinx.LinkExtensionPlugin -->
    <link href="$services.webjars.url('drawer', 'css/drawer.min.css')" rel="stylesheet" type="text/css" />
    <link href="$services.webjars.url('org.webjars.bower:multiselect', 'css/multi-select.css')" rel="stylesheet" type="text/css" />

Since I do not like the width of the multiselect in the css I also made a

XWiki.StyleSheetExtension and added:

.ms-container{
  width: inherit;
}

@mflorea Is it possible to load the CSS file in the StyleSheetExtension, so you do not have to override htmlheader.vm?

I was not able to get that working, also I found no documentation on that part.

@mflorea when reading : https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/Tutorials/Skins/

creating a new skin is done on the server by creating a new directory in the skins.

Is it possible to create an extension that saves updates the flamingo srcs (xwiki-platform/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo at master · xwiki/xwiki-platform · GitHub) to that directory instead of copying it and editing it?

You use $xwiki.linkx as per Skin Extension Plugin (XWiki.org) . See xwiki-platform/macros.vm at master · xwiki/xwiki-platform · GitHub for an example. This needs to be put in a Velocity code that is executed when the wiki page is loaded.

This is for completely new skins. If you want a skin based on the existing one, i.e. Flamingo, then you follow https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/Tutorials/Skins/#HHowtooverrideaSkin by creating a skin override using wiki pages (no need to have access to the file system). You can then select this as the current skin, and more importantly you can package it as an extension.

Maybe I made a typo. But you cannot put $xwiki.linkx($services.webjars.url() in an StylesheetExtention. Right? it has to be in a vm file

Correct. I wonder if we van make a complete new skin and put it in a extension. I have tried several skins, from the extensions, but none creates new files in the skin directories.

It has to be executed when the page HTML is served, not when the resources (JS/CSS) needed by the page HTML are served. The later are served in separate HTTP requests, after the page HTML is loaded anyway. So this code needs to be executed when the initial request (to get the page HTML) is made. It doesn’t matter if the code is in a Velocity template, the page content, a sheet, a UI extension, whatever. What matters is that the code is executed when the page HTML is served so that it injects the link tag in the page HTML head.

Extensions cannot add files or folders to the XWiki WAR (where the file-system skins are located). So you have to do it from the wiki (i.e. as a XAR extension). You may be able to create a completely new skin by leaving the skin parent field empty (instead of inheriting from Flamingo) and providing all the required templates and styles.

@mflorea thanks for the responses.

Hopefully you can extract some extra information from this item for the documentation.

Regards
Jurjen

@mflorea is it possible by overriding to remove the Bootstrap 3.4 css from the skin?

So we can upgrade to another version with a webjar or a complete different framework?

Or is that only possible by creating your own skin?

You should be able to overwrite anything. The styles are loaded from stylesheets.vm. If you check the code it loads something like $xwiki.getSkinFile('style.css', true)), so you need to overwrite style.css from your skin.