Resource optimization for Anonymous users

The ‘Use runtime optimized … resources’ is a great XSP Properties property to downsize the amount of calls to the Domino server for downloading stylesheet and javascript resources.

In order to reduce the size of the download(s) the rendered property in a Theme design element can be handy.

For example resources that are used in Xpages that are not accessible by Anonymous users you can initially restrict via:

Screen Shot 2016-03-08 at 12.15.01

When they later logon and access XPages that use the resource, it will be available.

Just a simple tip. Happy development =)

Styling the Pager control for Bootstrap UI

Many of us are acquainted with  Bootstrap in our XPages application. However if you place a Pager control on your XPage it does not render according bootstrap style.

So what can you do?

If you have the option to install the Extension Library with Bootstrap in it: DO IT.

If you don’t have that option you can place the Bootstrap resources in your NSF or use a CDN.

If you are using these last two options you will notice the Pager control is still non-Bootstrap styled. You can either:

  • Apply CSS yourself (link, link)
  • Apply your renderer (link)

I noticed in the first approach the … display for page numbering will not be proper styled:

Screen Shot 2016-03-01 at 10.46.13.png

If you are a CSS-wizard you probably can fix this (I can’t).

The second approach renders the Pager perfectly with Bootstrap style applied and hopefully the strange behaviours Frank van der Linden refers to do not appear.

Happy development =)

 

 

Bootstrap Pills navigation for Dynamic Content control

Introduction

Besides parameters you can include a hash (#) property in the URL in your XPages application. This “fragment identifier” is a short string of characters that refers to a resource that is subordinate to another, primary resource.

So it is mainly used to set a location anchor to a part in a page.

In this post I will show how to get value of Hash property in XPages and make a nice Bootstrap Pills navigation control for the Dynamic Content Control

XPages

In XPages you can use it within the xp:link control but the dynamic content control also makes use of it.

XSnippet Dynamic Content Control

The following XSnippet demonstrates how to set up a dynamic content control:

<?xml version="1.0" encoding="UTF-8"?>
  <xp:link escape="true" text="Load Dynamic Content Server side" id="link1">
    <xp:eventHandler event="onclick" submit="true" refreshMode="partial">
      <xp:this.action>
        <![CDATA[#{javascript:getComponent("dynC").show("key1")}]]>
      </xp:this.action>
    </xp:eventHandler>
  </xp:link>
  <xp:link escape="true" text="Load Dynamic Content Client side" id="link2">
    <xp:eventHandler event="onclick" submit="false">
      <xp:this.script><![CDATA[XSP.showContent("#{id:dynC}","key2")]]></xp:this.script>
    </xp:eventHandler>
  </xp:link>
  <xe:dynamicContent id="dynC" useHash="true">
    <xp:this.facets>
      <xp:panel xp:key="key1">Content1</xp:panel>
      <xp:panel xp:key="key2">Content2</xp:panel>
    </xp:this.facets>
  </xe:dynamicContent>
</xp:view>
With this snippet you get the following Hash set in the URL of your XPage: #content=…

Getting value of Hash property

I suggest to use one of the following 2 options to collect the value of the hash property:

  1. Use a custom function
  2. Use Dojo

The first option is another XSnippet by Thomas Adrian. The second is a suggestion by Mark Leusink to (re)use Dojo.

getHashUrlVars

Include the function in a shared CSJS library and call it via the function getHashUrlVars()["content"].

dojo.queryToObject

The dojo approach is also straightforward. Call the function dojo.queryToObject( dojo.hash() ); and then abstract the content property var active = hash[“content”];.

Pills navigation for Dynamic Content Control

Since there is no list item control in XPages it is a bit hard to set the properties via computation. However via CSJS you can manipulate the DOM a lot and add some responsiveness yourself.

The following script builds an unorderlist containing links to set a part of the Dynamic Content control as visible:

<xp:div id=”nav-pills-container”>
<ul class=”nav nav-pills”>
<li id=”Pictures” class=”dclist”>
<xp:link escape=”true” text=”Pictures” id=”link4″>
<xp:eventHandler event=”onclick” submit=”true”
refreshMode=”partial”>
<xp:this.action>
<![CDATA[#{javascript:getComponent(“dynC”).show(“Pictures”)}]]>
</xp:this.action>
</xp:eventHandler>
</xp:link>
</li>

<li id=”Albums” class=”dclist”>
<xp:link escape=”true” text=”Albums” id=”link1″>
<xp:eventHandler event=”onclick” submit=”true”
refreshMode=”partial”>
<xp:this.action>
<![CDATA[#{javascript:getComponent(“dynC”).show(“Albums”)}]]>
</xp:this.action>
</xp:eventHandler>
</xp:link>
</li>
<li id=”Profiles” class=”dclist”>
<xp:link escape=”true” text=”Profiles” id=”link2″>
<xp:eventHandler event=”onclick” submit=”true”
refreshMode=”partial”>
<xp:this.action>
<![CDATA[#{javascript:getComponent(“dynC”).show(“Profiles”)}]]>
</xp:this.action>
</xp:eventHandler>
</xp:link>
</li>

</ul>

The second script checks which content section is set “visible” for the Dynamic Content control via the hash property in the URL. The corresponding list item in the Pills navigation is set as active.

<xp:eventHandler event=”onClientLoad” submit=”false”>
<xp:this.script><![CDATA[function setActive(id){
$( “li.dclist” ).removeClass( “active” );
var id = “#” + id;
$(id).addClass( “active” );
}

var hash = dojo.queryToObject( dojo.hash() );
var active = hash[“content”];
setActive(active);
]]></xp:this.script>
</xp:eventHandler>

As a result I get the correct list item displayed as active for my Pills navigation:

navpills

Code

In case you want to see the code working in an example download the Bildr application on OpenNTF. There I have applied this technique for the search function.

 

Re-Unite Gallery & FIX AMD loading for XPages

Introduction

In my previous post “Another draw (unite gallery) in the waste-basket” I wrote the complication I had with getting the Unite Gallery to work properly within XPages.

It turns out that this is related to Asynchronous module definition complications within XPages., although you do not get error messages in your web browser console.

Fixing the XPages R9 dojo define.amd problem once and for all

Marky Roden wrote a post about a solution a while ago which was inspired by a x-code snippet Ferry Kranenburg posted.

The principle is quiet simple but saves you a lot of headaches:

  • duplicates define.amd to define._amd
  • deletes define.amd
  • loads the AMD enabled jquery plugin (successfully)
  • duplicates define._amd back to define.amd
  • deletes define._amd

Using a Theme

In stead of setting the fix for individual pages I am using a Theme to fix it (since I am using a Select2 combobox in my navbar header).

amd fix

Step 1 – Adding two JS libraries to your WebContent

These files contain the same code as in the XSnippet.

Step 2 – Load your resources via a Theme design element

amd_theme

As you can see I load my JavaScript libraries who use AMD within the two previous set up libraries.

Result

As a result the buttons on the XPage containing the Unite Gallery work fine again !

Happy development =)

 

Another draw (unite gallery) in the waste-basket

Gallery galore

For an application I want to provide an image slider, in stead of the default Bootstrap carousel. I remembered a blog post of Johnny Oldenburger about Unite Gallery a while ago so I gave that a try.

Repeat and xp:image

Where Johnny demonstrated some static images I want to populate the image collection so I set up a repeat control with an xp:image control inside and calculate it’s properties.

Here is what the code looks like:

Code

The code of the XPage you can download here.

 

Code walk-through

After loading the JS resources I have a script block that build the gallery when the document is ready. The div gallery functions as container for the gallery.

Then I have a repeat control. An album object is just a Notes document that contains references to other Notes documents containing the picture files. So my Album.getPictures method returns a vector of references for which I have to make a lookup (via a Picture object) and collect some values (which size picture to use (thumbnail or original).

I separate the design from the data, so I also have to collect the location of the data db.

In the example I have two ways to define the image, one is via a xp:text control and the other is via the xp:image control. I rather prefer this last option.

Result

 

Below you can see a snippet of how the result. At first it looks nice, does’t it?unitegallery

Complications with XPages

So after I got the gallery on my XPage with dynamic content I started to notice undesired behaviour. My Bootstrap navbar links (xp:link) didn’t work anymore. Buttons on the same page stopped behaving and more.

A quick search after “Unite Gallery and XPages” lead me to some stackoverflow questions where people described similar problems.

Untill now I have not found a solution to get it working.

Lesson learned

Before implementing a plugin in XPages, do some research on possible complications.

 

 

Quick way to get dynamic (BS) list groups from Notes views

Introduction

For an app I needed lists to let users quickly to have access to a subset of documents. Bootstrap has a nice feature called List Groups which gives you a nice basic UI for unordered lists with list-items.

A list group can contain badges which I find a nice alternative for a tag cloud which to me are not very mobile friendly.

Before we get started let’s show how the end-result could look like:

list-group computed

So how do we do this in XPages & Java?

First I want to point to a snippet Oliver Busse posted about Iterating through a HashMap in a repeat control. If you use that basic principle of binding a HashMap to a Repeat Control  and use a categorized view for filling the Hashmap you are there!

Java class snippet

Below is the snippet from my Java class:

public Set<Entry<String, Integer>> categoriesMap(String viewName) throws NotesException{
HashMap<String, Integer> categories = new HashMap<String, Integer>();
Database dataDB = dao.getDatabase();
String ViewName = viewName;
ViewNavigator nav = dataDB.getView(viewName).createViewNav();
ViewEntry entry = nav.getFirst();
while (entry != null && !entry.isTotal()){
categories.put(entry.getColumnValues().firstElement().toString(), entry.getChildCount());
ViewEntry tmpentry = nav.getNextSibling(entry);
entry.recycle();
entry = tmpentry;
}
nav.recycle();
return categories.entrySet();
}

The code will run through the provided Notes view and go through the categories and places the name/label and value/totals in a Map and returns a set view of the mappings contained in this map.

Custom Control

Next step is to place the list-group code from Bootstrap in a custom control and make it dynamic by generating the list-items via a Repeat control and bind that control to my Java code:

<?xml version=”1.0″ encoding=”UTF-8″?>
<xp:view xmlns:xp=”http://www.ibm.com/xsp/core”&gt;
<h2>
<xp:text
escape=”true”
id=”computedField1″
value=”#{javascript:compositeData.header}”>
</xp:text></h2>
<ul class=”list-group”>
<xp:repeat
id=”repeat1″
rows=”30″
var=”obj”
indexVar=”idx”>
<xp:this.value><![CDATA[#{javascript:var viewName = compositeData.viewName;
Picture.categoriesMap(viewName);}]]></xp:this.value>
<li class=”list-group-item”>
<span class=”badge”>
<xp:text
escape=”true”
id=”computedField2″
value=”#{javascript:obj.getValue()}”>
</xp:text>
</span>
<xp:link
escape=”true”
text=”#{javascript:obj.getKey()}”
id=”link1″>
<xp:eventHandler
event=”onclick”
submit=”true”
refreshMode=”complete”>
<xp:this.action>
<xp:openPage>
<xp:this.name><![CDATA[#{javascript:var target = compositeData.targetPage;
return target + “?filter=” + obj.getKey();}]]></xp:this.name>
</xp:openPage>
</xp:this.action></xp:eventHandler>
</xp:link>
</li>
</xp:repeat>
</ul>
</xp:view>

Properties

The custom controls takes in some properties set in the Property Definition section. Via this way I can re-use the Custom control for multiple dynamic list groups:

Conclusion

As you see, with a minimal amount of code you can create dynamic lists for your apps. In the sample above I do not handle views with more than 30 categories but I am sure you fix this yourself. Also the active class property is not implemented.

Happy development =)

 

Using HTML Entities in XPages

Introduction

Often when you’re designing a web page or application you want to use HTML entities or special characters. This happens quiet often when you are using Bootstrap in your design.

Problem

For example the header in the Bootstrap modal has a close button which is defined as followed:

<div class=“modal-header”>
<button type=“button” class=“close” data-dismiss=“modal”>&times;</button>
<h4 style=“color:red;”><span class=“glyphicon glyphicon-lock”></span> Login</h4>
</div>

When you past this code in your XPage you get the following error:

The entity “times” was referenced, but not declared.

So you cannot use this in your XPage source because it is not valid XML.

Answer

The short and quick answer is to use the numerical equivalents. In our case for &times; you will want to use & #215; (mind the space since WordPress is formatting it otherwise).

In the table on this linked page you will find on overview and description of (all) HTML Entities  and their corresponding Unicode decimals.

Below is a summary of HTML Entities I use often:

&nbsp; … & #160;

&times; … & #215;

&amp; … & #38;

&euro; … & #8364;

&quot; … & #34;

&reg; … & #174;

A simple tip, but useful none the less. Happy development =)

Responsive StandbyDialog & Cancel that operation

Introduction

Fredrik Norling has posted a new XSnippet on OpenNTF for a responsive standby  widget.  Great because in my current project a) I use Bootstrap for responsive behavior b) some operations take way more time that others.

Below is a sample how the dialog looks like:

standby_widget

When investigating the code I noticed 2 things:

  • A typo for the bootstrap model
  • The close button does not actually cancel the operation. It just closes the dialog.

Small dialog

The typo is a quickfix. Change

 '<div class="modal-dialog modal-m"><div class="modal-content">' +

into

‘<div class=”modal-dialog modal-sm”><div class=”modal-content modal-content-sm”>’ +

so you use Bootstrap’s small modal and not the default large one.

Cancel the partial refresh

For the partial refresh I found the solution in a post on Sven Hasselbach’s (holy) blog. Sven also posted the solution as an XSnippet on OpenNTF.

Scriptblock

First add a new scriptblock on the custom control that contains the Standby Dialog widget:

<xp:scriptBlock id=”scriptBlockXHRHandler”>
<xp:this.value><![CDATA[

var xhrCall = null;

dojo.addOnLoad( function(){

/*** hijack dojo’s xhrRequest ***/
dojo._xhrPost = dojo.xhrPost;
dojo._xhrGet = dojo.xhrGet;

dojo.xhrPost = function( args ){
xhrCall = dojo._xhrPost( args );
}

dojo.xhrGet = function( args ){
xhrCall = dojo._xhrGet( args );
}
});
]]>
</xp:this.value>
</xp:scriptBlock>

Then I included the call to the cancel function of the xhrCall object just before the allowSubmit function of the XSP object.

xhrCall.cancel();
XSP.allowSubmit();

Now if you click the close button in the Bootstrap modal the partial refresh is aborted.standby_widget abort

 

Carousel with dynamic content

Introduction

For an application I needed a carousel to display images on the frontpage. Since we go “all-in” Bootstrap the “natural choice” would be the Carousel component from the Extension Library. Unfortunately that control currently only accepts “static” slideNodes so I had to come up with something similar.

In the beginning…

First I just took the sample code from W3schools how to setup a basic Bootstrap Carousel component.

car_code01

Second I set up a Notes view that contains the data I need for my carousel. This view will be the source for an XPages Rest Service control (PDF alert) which I call after page load with an Ajax call using jQuery’s getJSON.

car_code02

car_code03

As you can see I update the Bootstrap sample code with the received result(s).

As a result I get the Carousel component from Bootstrap but now with ‘dynamic content’.

carousel

(for those who have never seen a Carousel)

The only complication I experienced was due to the fact that I separate the design from the data and accessing the data is easier in SSJS/Java then CSJS.

Here is the code: Link Dropbox

Happy development =)