Select2 v4 needs AMD fixing in Domino R9 XPages

As we have seen in the past AMD (Asynchronous Module Definition) in Dojo causes issues with jQuery plugins and other JavaScript libraries, in that it prevents them from loading correctly.

The select2 version4 – new release contains AMD checking code

https://github.com/select2/select2/blob/master/dist/js/select2.js

As you can see from the start

(function (factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['jquery'], factory);
  } else if (typeof exports === 'object') {
    // Node/CommonJS
    factory(require('jquery'));
  } else {
    // Browser globals
    factory(jQuery);
  }
}

So we have two choices – edit the select2.js code which you download and add it to your database – change the code to look like this

(function (factory) {
  if (typeof define === 'function' && false) { // removed define.amd and returned false
    // AMD. Register as an anonymous module.
    define(['jquery'], factory);
  } else if (typeof exports === 'object') {
    // Node/CommonJS
    factory(require('jquery'));
  } else {
    // Browser globals
    factory(jQuery);
  }
}

Or we have to ensure the database properties are set to do resource aggregation and use the following code to insert jQuery and select2 into the header

<xp:this.resources>

  <xp:headTag tagName="script">
   <xp:this.attributes>
    <xp:parameter name="type" value="text/javascript" />
    <xp:parameter name="src" value="js/jquery-1.9.1.min.js" />
   </xp:this.attributes>
  </xp:headTag>

  <xp:headTag tagName="script">
   <xp:this.attributes>
    <xp:parameter name="type" value="text/javascript" />
    <xp:parameter name="src" value="select2.js" />
   </xp:this.attributes>
  </xp:headTag>
 </xp:this.resources>

Check out Sven’s other blog post on the subject – http://hasselba.ch/blog/?p=1181

Binding jQuery code to an XPages partialRefresh using DOM Mutation events

Introduction

In this article I will demonstrate how to bind to the event which triggers on the completion of an XPages partialRefresh. Using that binding we will then be able to action to contents of the newly added partialRefresh DOM elements.

Background

In multiple articles I have discussed the use of the onComplete event of a programmatically triggered partialRefresh to be able to re-apply a jQuery plugin’s bindings to an area of an XPage. This works very nicely and integrates with the Dojo events controlling the xhr request to the Domino server.

A problem arises when you do not have a programmatically controlled partialRefresh, say for example in a pager. XPages uses the same technology to execute a partial refresh on a viewPanel – but you and I do not have programmatic access to the onComplete event without hijacking it.

This was brought back to my attention when reading Brad Balassaitis’ excellent article on adding font awesome to his data view. In that case he does not have an event available to him through the XPages designer so he has to hijack the Dojo calls. A practical solution given the tools available.

In general though I have always found using the XPage events a non-elegant way of controlling the page and there has to be a better way – I think upon reflection this is a nice learning experience and “good to know” article but not practical in production.

DOM Mutation events

These events have been around for a while but are now “deprecated” in favor of the new MutationObserver() constructor which is unfortunately not implemented in Internet Explorer until IE11

  • DOMAttrModified
  • DOMAttributeNameChanged
  • DOMCharacterDataModified
  • DOMElementNameChanged
  • DOMNodeInserted
  • DOMNodeInsertedIntoDocument
  • DOMNodeRemoved
  • DOMNodeRemovedFromDocument
  • DOMSubtreeModified

As the mozilla article states – “The practical reasons to avoid the mutation events are performance issues…...” – watching the DOM for changes every time a change happen has very processor intensive – believe me in my experiments if you latch onto DOMSubTreeModified and you are using jQuery which is constantly changing the DOM – you can easily drag your browser to its knees.

So in this article I am going to demonstrate how to use the “old” method for IE<11 and the preferred new method. You can then decide for yourself on the right way to do things – Dojo hijacking, degrading DOM performance or if you are lucky enough to not have to support IE – the way of the future 🙂

An example of the general problem

If I have a simple view panel on a page and I use some jQuery to stripe the rows it looks pretty…..(yes there are other ways to stripe the rows this is just to demonstrate the point).

jq1

But as soon as I hit the pager – the striping is lost. The DOM elements are removed and the new elements do not have the striping applied

jq2

The partialRefresh

As I am sure most of you know the partialRefresh as genius as it is, works by POST-ing the field values on the form back to the server where the JSF licecycle processes these POST-ed values and then returns a new set of HTML to the browser. That new HTML is inserted as a direct replacement of the DOM element which was being refreshed. Looking at the response from the server you can see below that when paging through a viewPanel the viewPanel1_OUTER_TABLE is re-downloded from the server and replaces the existing Table element in the DOM.

jw3

So my striped table is deleted from the DOM and replaced – ergo no more striping.

DOM Node insertion

Using the DOM Mutation event DomNodeInserted it is actually relatively easy to re-stripe the table.

I first surrounded the viewPanel with a div wrapper “viewPanelWrapper”. This is what I will use to listen to changes for. Because the whole outer table is replaced I cannot listen to events on it – it is removed along with my binding.

The first piece of code will demonstrate the event listener

$('.viewPanelWrapper').on("DOMNodeInserted", function(){
    console.log('a node was inserted')
})

When I run the above code snippet through firebug you will see that nothing changes (1). But when I click Next the partialRefresh is triggered and “a node was inserted”
jq5

If we then take this a step further we can add in our striping code again

$('.viewPanelWrapper').on("DOMNodeInserted", function(){
    console.log('a node was inserted')
    $('.viewPanel TR:even').css({background: '#FFCCCC'})
})

And that’s pretty much it – pretty simple really.

jq6

So then extending this simple example you can see how a jQuery plugin could be reapplied to any page after a partialRefresh has been triggered – JUST BE AWARE THAT THERE IS A PRICE TO PAY IN PERFORMANCE. If you are going to do this then make sure that you pick the smallest area to check possible and that it does not change every second – your browsers and more importantly users will not thank you. On and applying a jQuery plugin almost certainly also modifies your DOM – be careful not to create an endless loop of pluging in your plugin.

So the “better way”

This article explains the reasoning behind the new MutationObserver and more importantly why it makes more sense than what I just showed you.

DOM MutationObserver – reacting to DOM changes without killing browser performance.

Check out the “So what are these good for” section at the end – obviously they were talking about XPages 😉

Using a slightly modified version of their example we get this

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
  var list = document.querySelector('.viewPanelWrapper');

  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {

        console.log(mutation.type);
        $('.viewPanel TR:even').css({background: '#FFCCCC'})
    });
  });

  observer.observe(list, {
  	attributes: true,
  	childList: true,
  	characterData: true
   });

jq7

Which works the same but as the article explains – WAY more efficient and also gives you the control to not screw up your plugins.

Remember though the caveat is modern browsers and that it is IE11 only

Conclusion

Overall this has been a fascinating learning experience for me. I can’t recommend using the DOMNodeInserted event listener because it definitely caused me pain and anguish in browser performance. The MutationObserver is a very interesting concept but I am not convinced I would use it in an application until I better understand it.

jQuery Promises – Taking action .when() multiple ajax calls are complete

jQuery.when() – “Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events”

https://api.jquery.com/jQuery.when/

Wouldn’t it be nice to be able to know when two ajax calls are both complete – and then process the data returned from both, at the same time ?

Callbacks

Off the top of my head I would normally achieve this using a callback – and I have done so in some of my ExtJS in XPages articles. The following code snippet creates a callback that once the $.ajax call the url is complete take the data and pass it to the createGrid function. In there I could make another ajax call and then when that is complete I could process both data sets.

function getGridData(url, callback){

	var dataURL = url
	$.ajax({
		  url: dataURL+"&rand="+aRandomNumber()+"&"
		}).done(function ( data ) {
			//one the data is loaded then pass it to the callback function
			//passed in as one of the function arguments
			if(callback){
				callback(data)
			}
		});
}

var url = location.href
url = (url.indexOf('5Col')>-1) ? '5Col' : ""

url = 'xRestService.xsp/byFirstNameFlat'+url+'?count=100000'
var theData
var theCallBack = function(theData){
		createGrid(theData)
		}
getGridData(url, theCallBack)

This kinda makes an synchronous linear usage of asynchronous calls – do this then do that

As inelegant as that it, it works. The problems really start when you have 3, 4 or more callbacks and you get a callback hell of what if something fails in the middle and you have to run back up the tree looking for a fail – not pretty.

Using jQuery.when()

Modern browsers support the Promises concept which natively allows us to do the same thing but we know what that means and not the browsers we code for today.

.when() gives us the ability to pass as many ajax calls as we like, and then create one line of code which processes all the answers together.

Example

Here is a simple REST service feed from an XPages URL (fakenames data)

http://copper.xomino.com/xomino/extjs.nsf/xRestService.xsp/byFirstNameFlat?count=5

[
  {
      "@entryid":"1-AE3FB4C32057B87C85257C22000A83DD",
      "@unid":"AE3FB4C32057B87C85257C22000A83DD",
      "@noteid":"F5CA",
      "@position":"1",
      "@siblings":1304,
      "@form":"fUserName",
      "noteid":"NT0000F5CA",
      "firstname":"Alfred",
      "lastname":"Hall",
      "address":"2139 Jail Drivedd",
      "city":"Tremont",
      "state":"FL",
      "zip":615680,
      .........
  }
]

Which is nice ‘n all, but if we then wanted to know what State FL was (remember this is an example)

At the same time as pulling in the person you could also pull a list of US states

http://copper.xomino.com/xomino/extjs.nsf/states.json

{
    "AL": "Alabama",
    "AK": "Alaska",
    "AS": "American Samoa",
    "AZ": "Arizona",
    "AR": "Arkansas",
    "CA": "California",
    "CO": "Colorado",
    "CT": "Connecticut",
    "DE": "Delaware",
    "DC": "District Of Columbia",
    "FM": "Federated States Of Micronesia",
    "FL": "Florida",
    "GA": "Georgia",
    ......

From that we can then do a cross reference and display something useful.

The $.when returns each element as an Array of data so we have to get the zeroth value of each object returned to access it’s key/pairs

$.when(
    $.ajax({
        url: "xRestService.xsp/byFirstNameFlat?count=5",
        dataType: "json"
    }),
    $.ajax({
        url: "states.json",
        dataType: "json"
    })
).done(function( people, states ) {
    for (var i=0; i < people[0].length; i++){
        var person = people[0][i]
        var temp = ""
        temp=temp+person.firstname+" "
        temp=temp+person.lastname+" lives in "
        temp=temp+states[0][person.state]
        console.log(temp)
    }

});

As you can see from the screenshots below – the ajax calls can be executed in either order and still the result stands because the .done() function is not run until both are complete

d2

d1

d3

 

 

Conclusion

This is a very interesting capability which has apparently been around for ages and I wish I had known about it earlier (added jQuery v1.5)

 

jQuery in XPages #20 – NProgress – YouTube-like slim progress bar

In this article I will describe how to implement and use the jQuery NProgress nano scrollbar plugin

Demonstration

The XPages integration of NProgress is demonstrated here

Download

The demonstration database can be downloaded from the link above or from here

NProgress

Introduction

Since Youtube.com added their nano scroll bar at the top of the page there have been a flurry of different jQuery plugins which mimic the nano progress bar at the top of the screen.

np1

The silly thing is that the progress bar itself does nothing useful.

  • It does not
    • Indicate any meaningful progress on the download of the AJAX or page
    • Give any indication of the likelyhood of page download completion
  • It does
    • Give the user a false sense of something happening on the page
    • Provide a nice User Experience for very little overhead and effort on the part of the developer

Using NProgress you can very quickly and easily add this capability to your website for only a very small overhead to the size of your application.

Adding NProgress to your XPages

  • Go to the NProgress site and download the file from the github site linked on the page
  • Drag and drop the contents of the zip file into your WebContents folder
  • Create a sample page with the following
 <link href='nprogress/support/style.css' rel='stylesheet' />
  <link href='nprogress/nprogress.css' rel='stylesheet' />

<xp:this.resources>
	<xp:headTag tagName="script">
		<xp:this.attributes>
			<xp:parameter name="type" value="text/javascript" />
			<xp:parameter name="src" value="js/jquery.js" />
		</xp:this.attributes>
	</xp:headTag>
</xp:this.resources>

<xp:this.resources>
	<xp:headTag tagName="script">
		<xp:this.attributes>
			<xp:parameter name="type" value="text/javascript" />
			<xp:parameter name="src" value="nprogress/nprogress.js" />
		</xp:this.attributes>
	</xp:headTag>
</xp:this.resources>

The reason we add this to our XPage in the manner above is because nprogress uses AMD as a possible loader (to integrate with require.js) and because of that Dojo 1.8 (on an R9 server) breaks it.

On my demo page I have loaded a viewPanel with 1300 documents in it – I cannot show you more because I do not want a large database on my host’s site but rest assured if you run this up to a 5000 row viewPanel the effect is better because the refresh is slower.

np2

On the demo I have included the main example from the NProgress site and you can see that there are a number of methods for starting and manipulating the progress bar. I use start because it very nicely randomly increments itself to give that illusion of progress.

On the XPage I have a button which refreshes the view Panel – and in the client script as the button is pushed I start the NProgress. In the onComplete of the refresh I end NProgress and really it is as simple as that

<xp:button value="Reload  viewPanel" id="button1" styleClass="clickMe btn btn-warning">
	<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="viewwrapper"
		onComplete="NProgress.done()">
		<xp:this.script><![CDATA[
			NProgress.start()
		]]></xp:this.script>
	</xp:eventHandler>
</xp:button>

I would suggest that if you are able to integrate with Tony McGuckin’s excellent XSnippet for intercepting dojo io events you could create an automated NProgress bar should you so chose.

Conclusion

As web developers we have used spinners in our application for quite a number of years – this is a new twist on that concept and seems to be getting very good reviews from users. Consider integrating it into your applications.

jQuery in XPages #19 – Shadow (Add eye catching drop shadows to your page elements)

In this article I will describe how to implement and use the jQuery shadow plugin to create great looking shadowed panels within your XPages application.

Demonstration

The XPages integration of shadow is demonstrated here

Download

The demonstration database can be downloaded from the link above or from here

Shadow

Introduction

“Adapted from Nicholas Gallagher’s CSS drop shadows without images demo

Adding “depth” to the visual aspect of your website is one of those things which can make them “pop” (pun intended). Using the shadow plugin, one line of code can be the difference between “meh” and “wow”.

Browser support?

Here’s the nice bit IE9, Firefox 3.5 Chrome, Safari – which means it works in XPiNC as well, and that’s sweet!

shad4

How does it work?

The main driver behind this plugin is really Nicholas Gallagher’s CSS drop shadows without images demo. The plug author just wrapped it as a jQuery plugin to make his and everyone else’s life easier.

Using the plugin could not be easier. Using the normal jQuery selector you identify the design element(s) you want to add a shadow to and then determine which type of shadow to add.

We add the plugin to the WebContent folder within our database and reference it in our source code

<script src="jquery-shadow/jquery.shadow.js"></script>
<link rel="stylesheet" href="jquery-shadow/jquery.shadow.css" />

And then add the code to call the plugin updating the elements with the vpDemo class

   $('.vpDemo').shadow('raised')

Examples
The first example you can see on the website is just a simple view panel. You click the but to. And you can see the effect.

shad1

The second example is an xe:widgetContainer widget from the extension library – this has a dojo stylesheet already applied but the shadow works nicely

shad2

The final example allows you appling it to the xp:panel.

shad3

Other styles

There are other styles  available other than ‘raised’ check out the website demo examples to see the others but be aware that they do not all work in all browsers.

Conclusion

As with most of the plugins in this series – for next to no effort, you get a big payoff in user interface enhancements. In this case even more so because this is all CSS3 and no images necessary.

Just a note

Many people ask me how long it really takes to create the demos and get the functionality into the database.

Well figured this out at 3pm this afternoon, finished work (at 5pm), cooked dinner for the kids, went to a school PTA meeting, put the kids to bed, started writing the blog and finished the demo by 11pm – so not long really 🙂

Caveat from the author

These are his words on the git hub repo – heed them, or not 🙂

“The purpose of this is to make it easier, as you don’t need to remember the specific css class names.

However, this is extremely bad practice… and should not be used for a production site, but feel free to use it for prototyping…”

Webcast: jQuery The World’s Most Popular JavaScript Library Comes to XPages – now on YouTube

It was an absolute pleasure to do my jQuery in XPages presentation for the 3rd time (publicly) earlier this week and it was as part of the TLCC and Teamstudio webcast series highlighting some of the people and presentations from the community.

There were 430 people registered for the webcast and at its peak there were over 300 people watching.

As with each presentation, podcast and screencast I have had the privilege of being a part of, I am humbled by knowing that I am able to help other developers and users in the community.

For those people who missed the presentation it was recorded and posted for posterity on youtube

Thank you to everyone who attended and let me know what you want to find out about in the future.

Marky

Webinar – jQuery: The World’s Most Popular JavaScript Library Comes to XPages – April 23rd

I am very pleased to announce that as part of the TLCC 2013 XPages Webinar Series with Teamstudio I have been invited to give a webinar presentation of my IBM Connect 2013 presentation on jQuery. In this webinar I will be going through the slides and showing some demonstrations of how to use jQuery in XPages. There will also be a question and answer session at the end of the presentation for all those who are interested.

 

Tuesday,April 23rd – 10:30 A.M. to noon, Eastern U.S. time

Whether you want to add some serious eye candy to your XPages Applications or just want to do more with less code, jQuery, the world’s most popular JavaScript framework can help you. Come to this webinar and find out how you can use some of the thousands of jQuery plugins, in harmony with Dojo, within your XPages applications to create a better experience not only for your users, but for you as a developer. In this webinar, we’ll look at how jQuery works, how to add it to your XPages, and how a complete JavaScript beginner can take advantage of its power. We’ll demonstrate many working examples —  and a sample database will be provided.

 

For more information please look at the TLCC website link below and sign up

http://www.tlcc.com/admin/tlccsite.nsf/pages/xpages-webinar?opendocument

jQuery in XPages #18 Galleria (Easy to use Picture Carousel)

In this article I will describe how to implement and use the Galleria jQuery plugin to create a powerful picture carousel within your XPages application

Demonstration

The XPages integration of Galleria is demonstrated here

Download

The demonstration database can be downloaded from the link above or from here

Galleria

Introduction

“Galleria is a JavaScript image gallery framework that simplifies the process of creating beautiful image galleries for the web and mobile devices.”

I came across this carousel while I was researching my talk for IBMConnect 2013 and I was amazed by the simplicity, how powerful it was and how in depth and easy to understand the help documentation was. This article may be short and sweet because the plugin is that easy to implement!

Take a look at the example page http://galleria.io/

How does it work?

Looking at the documentation page there is a myriad of information on how to make the carousel you really want. The Beginner’s Guide is one of the best I have seen for any plugin. It is a step by step instruction on how to create the carousel in your web page including how to add jQuery.

We have to change that slightly to make the carousel work in our XPage – but only a little….

Download the plugin files from here http://galleria.io/download/

We add the jQuery library and the Galleria library file(s) to the database by adding them to the Web-Contents folder accessible via the package explorer.  (Window–>Show Eclipse Views–>Package Explorer) and drag and drop the two libraries from your computer into the “js” folder. We also add the themes and css files to the WebContent folder in the galleria folder.

gal1

We add the libraries to our XPages like this in the source panel

<script src="js/galleria-1.2.8.min.js"></script>

Using the information on the Beginner’s guide we also add the style

<style>
	#galleria{ width: 700px; height: 400px; background: #000 }
</style>

as well as the code to load the carousel once the page is loaded

Galleria.loadTheme('galleria/themes/classic/galleria.classic.min.js');
Galleria.configure({
   transition: 'fade',
   lightbox: true,
   imageCrop: true
});
Galleria.run('#galleria');

Once this is added to the page we just need to add some images…..In the beginners guide it staes that we have to just add some images into the galleria DIV

<div id="galleria">
    <img src="photo1.jpg">
    <img src="photo2.jpg">
    <img src="photo3.jpg">
</div>

but in our case we going to pull the pictures from notes documents in a view. In the same way as we did for the prettyphoto lightbox example we are going to add a view as a data source and use a repeat control to add the images to the page itself.

The data source

<xp:this.data>
	<xp:dominoDocument var="imageDoc" formName="imageHolder"></xp:dominoDocument>
	<xp:dominoView var="imagesView" viewName="images"></xp:dominoView>
</xp:this.data>

and the repeat control placing the images inside the galleria DIV

<div id="galleria">
	<xp:repeat id="repeat1" rows="30" value="#{imagesView}" var="imageRepeat">
		<xp:image id="Image1">
			<xp:this.url><![CDATA[#{javascript:"#{imageRepeat.imagePath}"}]]></xp:this.url>
		</xp:image>
	</xp:repeat>
</div>

And that is the absolute basic carousel (not that much different from the prettyphoto lightbox really at this point”

So what’s the difference with this one then?

Well it looks different, that is often a deciding factor when trying to impress your customer – which do they prefer the look of?

There are significantly more options to this carousel than the prettyphoto lightbox and this carousel has been optimized for mobile which the prettyPhoto has not (as far as I can tell). Let’s take a look at some of them…

Galleria comes with the following options:

  • Theming (allowing the developer to use pre-build settings to change the colors surrounding the carousel and the speed of the show)
  • Fullscreen capability
  • Responsive mobile view with swipe actions
  • An extensive API

In real words what does this mean? It means that you have almost absolute control over everything which happens within the slideshow or within the picture popups. Look at the optional themes as well. There are different themes you can buy which would serve you well if you were trying to implement this in a commercial site or if you just wanted to pump up an internal site.

In my example I have added a number of options to the carousel which give it some features. You should look seriously into the API to see what is possible.

Galleria.loadTheme('galleria/themes/classic/galleria.classic.min.js');
	Galleria.configure({
		transition: 'fade',
		lightbox: true,
		showCounter: true,
		showInfo: true,
		showImageNav: true,
		imagePan: true,
		imageCrop: true
	});
Galleria.run('#galleria');

Demonstration

Check out the demo(s)

The XPages integration of Galleria is demonstrated here

XPiNC browser url format – and why my demo failed at IBMConnect (part 2)

So this is article is to expand a little on the post I shared on Friday about my demo failure at IBMConnect. I will demonstrate why the problem occurred and what you can do about it. ALL thanks go to Simon Reid who pointed me at the reason once I had found the fix.

The Problem

I had a demonstration http://demo.xomino.com database which shows how some jQuery plugins can be used in XPages. The links within the menu “were” constructed as follows:

isExternal:=@If(@Right(Link; "http")!=""; @True; @False);

theLink:="<a href=\""+@If(isExternal; Link; "/"+@WebDbName+Link)+"\">"+LinkTitle+"</a>";

"<p>" + theLink+"</p>"+@NewLine

The point of this was to open up a link to an external site correctly and point a link to this database appropriately. The use of “/”+@WebDbName is to ensure that the database would still work when it was download and put on someone else’s server.

Works like a charm in the web
FAILED in XPinc

The Reason

As Simon Stated in his reply to my previous post – the XPiNC browser adds a /xsp/ to the front of the url.

To prove this I created a very simple link in an XPage:

<a href="javascript: alert(location.href)>Click Me</a>

And when I clicked the link in the XPiNC browser I got this…

XSPnooooo

And look at that “/xsp/xomino/jQinX.nsf” – there it is the xsp added to the URL

that is NOT what @WebDBName returns (/xomino/jQinX.nsf) and that is the root cause of the fail.

The Solution

There are a number of solutions and it really depends on what works for you – the fact that you are reading this you know about the issue and you need to work out which solution is best for you – here are some options if you need XPiNC support:

  1. Don’t user @WebDbName to get the database path – plain and simple.
  2. If you are able to – compute the links to the other XPages using the link control. I personally despise the link control because it is limiting and does not slot well into jQuery plugins – but it is an option.

The following code creates a link to the LongPress demo page – this works in XPiNC and on the Web

	<xp:link escape="true" text="Long Press Link" id="link2" value="/xLongPress.xsp" title="Long Press Link"></xp:link>

The link created looks like this in XPiNC

	<a id="view:_id1:_id2:_id52:link2" href="/xsp/xomino%5CjQinX.nsf/xLongPress.xsp" class="xspLink" title="Long Press Link">Long Press Link</a>

And looks like this in a browser

	<a id="view:_id1:_id2:_id52:link2" href="/xomino/jQinX.nsf/xLongPress.xsp" class="xspLink" title="Long Press Link">Long Press Link</a><br>

Unfortunately I want my links in documents in a view so that I can look them up – so I can’t use the xp:link

Here are some other options

  1. Use links which are not relative to the databasePath on the server. In my case I changed the menu links to be relative to each other “xPageSlide.xsp” rather than /xomino/jQinX.nsf/xPageSlide.xsp
  2. Use jQuery or dojo to do some form of XPiNC detection and manipulate the links after they have been sent to the page. You could do this by detecting if /xsp/ was the start of your location.path variable and adding it to all the link you cared about – this is dangerous and risky – not favorite which is also why I have no example.

 

Conclusion

The XPiNC browser adds /xsp/ to the front of all URLs – be aware of it

The solution depends on your needs – but for normal links to other XPages use the xp:link control which will do the link figuring out on it’s own

If I had not presented this and FAILED at IBMConnect I would not have had the conversation about it – and would not have learned something very important like this – AWESOME!

 

General Comment

How you deal with failure says a lot about your personality – if it drives you to be better then good for you.

This failure is a learning experience which was handled on stage by laughter, and I hope by this blog post as a learning experience for all 🙂

 

jQuery in XPages @IBMConnect demo fixed – and the problem explained

So I am in the middle of doing my presentation @ IBMConnect 2013 and everything is going relatively well…..and someone asks a question

Question: “Hey Marky – does jQuery work in XPiNC?”

Marky: “sure it does watch this”

#SmugWithConfidence
Click Click
#FailWhale
404 – proxyServer Error

WTF ????

#PresenterPanic??!!
#CrowdLaughter (mostly from my loyal friends)….
#OhTheShame

WTF??? 😦

I told the audience it was because I had obviously broken it and I thought I knew the problem – i apologized profusely and said that I would fix it ASAP. Well today is ASAP 😛

It now works – you can download the sample database from http://demo.xomino.com and run it in XPiNC

The Problem

Some genius…..had messed with the menu for IBMConnect and changed the menu links so they looked like this

	<a href="/xomino/jQinX.nsf/xPageSlide.xsp">PageSlide</a>

And that works perfectly fine in a web browser – but locally on the XPiNC webserver causes the ProxyServer error above!! The fix is simple – change it so that it is not relative to the server.

The issue is the /xomino link which is interpreted by the browser as http://demo.xomino.com, SLASH xomino. This is good technique because it doesn’t name the server and is therefore portable to other servers. But apparently fails in the local XPiNC server.

Why? I have no idea unfortunately but I am more concerned with the solution than the cause. Changing the links as follows and we have a working demo database again

	<a href="xPageSlide.xsp">PageSlide</a>

as all the demo pages are at the same level in the URL this is not a problem. Weird eh!

I will talk to some people smarter than I and see if I can find out why this problem is caused by the  XPiNC server – but be aware that you should not use links relative to the XPiNC server….weird!

I am very sorry this screwed up in the demo but hopefully enough people will forgive me and we can all carry on 🙂 🙂