Xomino

Domino with the new improved X

x$ – now a part of XPages Extension Library

Posted by MarkyRoden on November 18, 2014

I am very flattered to find out that not only is my x$ OpenNTF xSnippet being used more widely than I realized (over 600 downloads). It now being used in the latest release of the OpenNTF Extension library.

If you look here – http://bootstrap4xpages.com/xsp/.ibmxspres/.extlib/responsive/xpages/js/xsp-mixin.js and search for it you will find


//jQuery selector that works with XPages IDs
//See - http://openntf.org/XSnippets.nsf/snippet.xsp?id=x-jquery-selector-for-xpages
function x$(idTag, param){
	idTag = idTag.replace(/:/gi, "\\:") + (param ? param : "");
	return($("#" + idTag));
}

Who knew my first foray into the XPages community would have such an impact.

The lesson here boys and girls should be that you should *share* your work however small and insignificant you think it is. Like all scientific research, very little code is “a completely new way of doing things”. Generally everything grows incrementally and just because you don’t think something is significant, someone else might.

You are reading this - what have you shared recently?

:)

 

Posted in Extension Library, jQuery, x$, XPages | Tagged: , , , | 4 Comments »

Got non-XPages design elements? You really should use WebContent.

Posted by MarkyRoden on November 17, 2014

Recently I was able to help explain an issue Russ Maher was having with his application png files - http://xpagetips.blogspot.com/2014/11/got-png-you-may-get-problems.html. It got me thinking that as modern web developers (which is what XPage developers need to be), we should not be using Domino database elements for “web elements”.

Back before R8 we all used the Database Files, Style sheets and Database Images as a way to reference files as part of the database. I now believe we need to stop using these altogether for “web development”.

w1

WebContent is better

A modern (non-XPages) web based application typically looks like this

w2

As you can see from the image above within a well structured web application css, images and js are all neatly separated out into separate folders. This makes it easy to drag and drop them from web server to web server because all the links are relative and easy to find.

Within our WebContent folder (Accessible within the package manager Window – Open Perspective – XPages) we are able to drag and drop a web project,  jQuery plugin, angular.js directive, extjs and many items and have them continue to function without any issue.

Bootstrap is another great example, well structured and easy to add to our applications.

w3

Source control

When we build out our applications and use source control the “database structure” is stored locally and then committed to our Git or Mercurial repository. Not using the WebContent folder causes us problems when we are searching for files in this environment. Having all our files as it they were in our database makes our lives harder and certainly harder for non-XPages developer to find our code. Some is in “Code” and the rest is in “Resources”, that doesn’t make sense.

w4

 

Conclusion

We as XPages developers need to stop using the “database” for files etc and start to use the WebContent like proper web developers.

 

PS

Yes - I know we all have old applications which get modernized and we cannot always do anything about it, but at the same time for new development moving forward this is where I am at.

 

 

 

Posted in Just Marky, XPages | 16 Comments »

XPages and Bluemix: How to create a Websockets message without being connected to the application

Posted by MarkyRoden on November 16, 2014

In this article I demonstrate how to create a Websocket message to be broadcast, from a website which is not connected to the Websocket directly. This will be achieved by using a http POST request of the message to a node.js server hosted on Bluemix and having that server then emit a Websocket message out to the application.

Introduction

In the previous article I demonstrated how to create an XPages chat client using a Bluemix hosted node.js server. I was able to do this by porting the node.js example to an XPage (xSocket.xsp). What I wanted to figure out (thank you Stack Overflow) was how to trigger a Websocket message to be sent out without using the Websocket socket.io JavaScript client.

Reference articles

This article is based on information already published on the following blog posts:

POSTing to a node route

In the Watson translation service example article I discussed how to create a new POST route within your node application using the simple express construct “app.post”.


var cors = require('cors');
app.use(cors());

var corsOptions = {
  origin: 'http://copper.xomino.com'
};

app.post('/xpages', cors(corsOptions), function(req, res){
  .....
});

In a similar fashion in this example I am going to POST data from the copper.xomino.com website and therefore I need to add the cors code to the application to allow this.

Looking at the message payload

If we look at the client.js file from the original node.js Bluemix example blog post we can see that the message which is sent to the websocket looks like this

    var msgField = $('#msg'),
    data = { msg: msgField.val(), nickname: nickname, when: new Date() };

So our target is to recreate that same data Object and send it through to the server socket emitter in the same format.

Creating the POST data

Once again learning from the previous Watson example the code for this is relatively simple. We create the data Object with a nickname and text value and then POST them to the xominosocket.mybluemix.net site. Logging the response from the server

var data = {
	nickname: 'marky ajax',
	text: 'Sample POST from AJAX'
}
console.log(data)
$.ajax({ url:
	"http://xominosocket.mybluemix.net/xpages",
	type: "POST",
	data: data
}).done(function( msg ) {
	console.log( msg);
});

Modifying the node.js code

The node.js code from the previous article needs to be updated in a number of ways.

The Watson Translation example used a version of express 3.x. Version 4 is more streamlined and does not contain a lot of middleware. When we attempt to POST data to the node server it cannot be understood because it is encoded by the web browser (by default). For his we need to add the npm module body-parser (not forgetting to include it in the package.json).

The new package.json looks like this

{
  "name": "xominosocket",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.10.1",
    "jade": "^1.7.0",
    "redis": "^0.10.3",
    "socket.io": "^1.2.0",
    "cors": "2.4.2",
    "body-parser": "1.9.2"
  }
}

The app.post also needs to be able to parse the incoming POST and then re-purpose this into a socket emit event. We do this as follows. I also added a check to make sure the req.body was coming through. This was failing before I realized I needed body-parser.

// Handle the form POST containing the text and nickname
app.post('/xpages', cors(corsOptions), function(req, res){
  var request_data = {};

  console.log(req.body)

  if (req.body){
    request_data = {
      'txt': req.body.text,
      'nickname': req.body.nickname
    };
  } else {
    request_data = {
      'txt': 'this failed',
      'nickname': 'Not this guy'
    };
  }

  var data = { msg: request_data.txt, nickname: request_data.nickname, when: new Date() };
  io.sockets.emit("msg", data);
  res.send(data);
});

Testing the new capability

For the purposes of this article I am only going to show the example in Firebug console. As you can see from the code on the right we are posting to the xominosocket site. On the left you can see the communication was successfully sent to the site, the response and the headers:

ws1

From the next screenshot you can see that the message is them broadcast out to the other client currently connected to the socket, in this case in Chrome.

ws2

Cors security

The cors security only allows POSTing from the copper.xomino.com site. This is a good thing :)

ws3

Conclusion

In this article we have seen how we can “create” a websockets emission event on the server by POSTing a message to a separate page within the application.

While this may seem pointless (“because why couldn’t I just create a normal websockets message from the page”), what we will see in a future article is the need to emit an event from the server which is not connected to the Websocket and doesn’t need to be.

 

Posted in Bluemix, node.js, npm, WebSockets | 2 Comments »

One way to make a responsive XPages viewPanel

Posted by MarkyRoden on November 11, 2014

In this article I will demonstrate a method for hiding columns using CSS and making an XPages view Panel pseudo-responsive.

What is Responsive Design?

  1. Responsive design is an approach to web page creation that makes use of flexible layouts, flexible images and cascading style sheet media queries. The goal of responsive design is to build web pages that detect the visitor’s screen size and orientation and change the layout accordingly.

    http://whatis.techtarget.com/definition/responsive-design

Introduction

XPages view panels out of the box are not “responsive”, in that they make no attempt to, and do not work well on a mobile device.

One solution demonstrated by Stewart Curry is to hide columns as the width of the browser decreases. Hiding the least significant, down to the most when the view space is smallest. This makes sense because you would not want to display 9 columns worth of data on a mobile device anyway.

Using the following CSS I was easily able to make an XPages view panel “work” at different resolutions by reducing the number of displayed columns. (IE9 and above http://caniuse.com/#search=nth-child)

<style>
	.xspDataTable {width: 75%}

	@media only screen and (max-width: 1000px) {
		.xspDataTable tr td:nth-child(2), .xspDataTable tr th:nth-child(2) { display:none; visibility:hidden; }
	}

	@media only screen and (max-width: 768px) {
		.xspDataTable tr td:nth-child(3), .xspDataTable tr th:nth-child(3) { display:none; visibility:hidden; }
	}

	@media only screen and (max-width: 480px) {
		.xspDataTable tr td:nth-child(1), .xspDataTable tr th:nth-child(1) { display:none; visibility:hidden; }
	}
</style>

How does it work?
The CSS media queries (IE9 and above) determine the CSS displayed depending on the width of the page (1000px, 768px and 480px in this case). At each stage I remove one column until I am left with just the detail as you can see below.


At > 1000px

a1

At > 768px

a2

At > 480px

a3

and below 480px

a4

Conclusion

This is not the only “method” for trying to achieve responsiveness out of tables, but definitely my favorite :)

 

 

 

Posted in CSS, XPages | Tagged: , | 3 Comments »

Creating an XPages Websockets chat client using Bluemix

Posted by MarkyRoden on November 9, 2014

In this article I will demonstrate how I was able to take an example Bluemix, node.js based, websocket chat program and re-purpose it to be used in XPages.

Introduction

Earlier this year I was very excited to find the Websockets in XPages project on OpenNTF published by Mark Ambler. The concept behind that project is to be able to create a notes document in a queue which is processed and then send out to all users. As much as I promised to help out and use the project, life and a business need to learn and use Angular.js got in the way. My abject apologies to Mark for not following through on my promise to help move the project along.

With this article though, I want to start my exploration of using an external Websockets server to transmit messages to my XPages applications. One of the *nice* things about Websockets is that unlike JavaScript AJAX they are *not* restricted by CORS. This means that I can host my Websockets server anywhere. In this case it is a win win for me as I get to learn more about Bluemix, node.js, websockets and other NoSQL databases like Redis in this case.

Creating a Websockets chat example in Bluemix

I found this article on Create an HTML5 chat app on Bluemix with Node.js, Redis, and Socket.io and following it through I was able to get my own chat program up and running within an hour or so.

ws1

It is not an especially difficult example to follow but I did find that it helped to understand a little about Bluemix and how a node.js application is put together. You should be able to figure it out though just following through the example.

The code for the original example can be found here https://hub.jazz.net/project/joelennon/bluemixchat/overview?welcome= if you want to take a look at it.

Porting the “client” to an XPage

Within the original example, the interface makes a connection to a Redis database to store the last 99 entries of the chat. Within the XPages example I could do that but I am not going to at this time. So the XPages interface will lose chat history when you refresh the page. I am not really concerned about that in the big picture.

Because I had all the files locally I was able to create a new IBM Domino database and drag the files into the WebContent directory. Within node.js the “Public” directory is assigned to the root of the server, but in this case I removed the public folder as it is unnecessary.

w2s2

 

The original example uses the jade templating engine to create the web page. But in this case I felt lazy and just viewed the source of the example once it was working and then extracted all the HTML I needed.

Moving socket.io to the HEAD

Because this is XPages and because we have dojo and I am sure I have pointed out before – we have to move the files to the HTML HEAD in such a manner as they come before Dojo within the application. Socket.io is apparently one such JavaScript library.

The HTML of the XPage is relatively simple. As you can see below we a using the xp:resources tag to insert the same HTML references to the local files as they were in the original example.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

	<link rel="stylesheet" href="//cdn.jsdelivr.net/normalize/3.0.1/normalize.min.css"/>
	<link rel="stylesheet" href="stylesheets/style.css"/>

	<xp:this.resources>
		<xp:headTag tagName="script">
			<xp:this.attributes>
				<xp:parameter name="type" value="text/javascript" />
				<xp:parameter name="src" value="//cdn.jsdelivr.net/jquery/2.1.1/jquery.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="socket.io/socket.io.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="javascripts/client.js" />
			</xp:this.attributes>
		</xp:headTag>
	</xp:this.resources>

	<h1>XPages Websocket Chat using Bluemix</h1>

	<input id="msg" autocomplete="off" autofocus="autofocus"/>
	<button type="submit">Send</button>

	<ul id="messages">
	</ul>

</xp:view>

 The critical difference – the server connection

Within the original example the socket code was on the same server as the client creating the messages. In this case they are not as my XPages server is wholly independent of Bluemix.

So I had to change the initial connection to the websocket server. Within the client.js file I changed the first line from

$(document).ready(function() {
  var socket = io(), nickname, msgList = $('#messages');
  ...

to the following

$(document).ready(function() {
  var socket = io.connect('http://xominosocket.mybluemix.net') //connect to the Bluemix server
  var nickname, msgList = $('#messages');
  ...

With these changes and a couple of stupid spelling mistake corrections I was able to bring my application up within my xSocket XPage.

ws3

You can see from the Firebug console that the copper.xomino.com application is talking to the xominosocket.bluemix.net application

Mobile Compatible

Yes you have to be connected to the website (rather than OS Push notification) but websockets works on iOS7+ and Android 4.4+

(http://caniuse.com/#feat=websockets)

Screenshot_2014-11-08-11-47-45

Conclusion

There is a lot more detail which we can go into as to how this example works but in the mean time if you want to play with it.

Here is the Bluemix Page: http://xominosocket.mybluemix.net/ (with chat history)

Here is an XPage: http://demo.xomino.com/xomino/WSinX.nsf/xSocket.xsp (no history)

For the full effect – open each link in a different browser and you can talk to yourself ;)

You can find my Bluemix code on Jazz Hub - https://hub.jazz.net/project/mdroden/xominosocket/overview.

Posted in Bluemix, node.js, WebSockets, WebSockets in XPages, XPages | 1 Comment »

Finding your localStorage values – Chrome Developer Tools

Posted by MarkyRoden on November 6, 2014

Just a quick tip – if you use localStorage and you need to find out what values you have in localStorage you can see them through developer tools easily.

  • F12 to pull up developer tools
  • Resources
  • Local Storage is right there

a1

 

PS

A similar feature will be release in the next Firefox (34) developer tools - https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector

Posted in Chrome Dev Tools | Leave a Comment »

Because developers make mistakes – Webstorm Local History

Posted by MarkyRoden on November 6, 2014

Similar to Eclipse, Webstorm has a local history capability, allowing the developer who realizes they made an idiot mistake an hour ago, to go back to it and save their day.

We’ve all been there and while committing to source control is a must for modern development, there are those times in between commits and then those when you are just too lazy to go through the repo looking for it.

Local History

Local History is always enabled in Webstorm – for the official help check here.

Under the VCS Menu you will find Local History. Open the file you want to view the history form and then

a1

This will then show you not only the local history between saves – but also the Source Control Commits – sweeeet !

 

a2

You can then copy back the changes, revert and or play with the changes you have made as they are highlighted between the current version and the selected old one

a3

a4

Posted in Webstorm | Tagged: | Leave a Comment »

Conditional style loading in IE10+

Posted by MarkyRoden on November 2, 2014

I learned this recently when trying to load a conditional stylesheet into an XPage. IE9 worked but IE11 failed on me and I couldn’t see why. It was only a small change so I ended up putting it in the main stylesheet as a media query.

 

Apparently IE10 and above does not understand conditional HTML code like this

  <!--[if IE]>
    This content is ignored in IE10 and other browsers.
    In older versions of IE it renders as part of the page.
  <![endif]-->

http://msdn.microsoft.com/en-us/library/ie/hh801214(v=vs.85).aspx

So to load a style conditionally in IE11 you can do it like this

@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
  Add your IE10+ specific styles here
}

thanks to http://www.adaodesign.com/css-styles-for-ie10-and-ie11-only

Posted in CSS, XPages | Leave a Comment »

Simple examples of how Google Developer Tools can aid Mobile Development

Posted by MarkyRoden on October 30, 2014

In this article I will show some simple examples of how Google Developer Tools can be used to help in mobile (responsive) development.

Introduction

Google Developer Tools (F12) within Chrome is one of those things which you *know* is way more powerful that you have ever cared to look at but this week I was introduced to a very cool new feature – thanks to @simonreid123. The ability to control the veiwport and size of the viewing window, as well as being able to throttle the speed of page load has helped me better design a site for mobile. This does not obviously replace real testing on aa real device, but definitely helps !!

The Mobile button in Developer Tools

In this example we are going to look at the BBC website from today. In a normal browser it looks like this.

a1

Bringing up developer Tools (F12) we can see a mobile button on the toolbar

a2

Clicking on that brings up a new view of the page.

a3

Once I do that I can select a “Device” from the menu

a5

 

After then refreshing the page (as it tells me to) I can see the page as if it were an iPad.a4

I then chose iPhone 4 and got a smaller screen

Across the top you can see the screen width and markers – and in orange the media queries (as specified by the style sheet) where there are going to be changes

a6

 

Dragging the tab to resize the browser you can see the changes on the orange lines

a7

Throttling

Another nice feature is the ability to arbitrarily slow the page load down as if we were on a slow network (more like a phone)

a8

 

Conclusion

This is a very useful and cool feature I was not aware of. I *know* there are many many many other things I do not know about developer tools….it’s all a great learning experience :)

 

Posted in Chrome Dev Tools | 1 Comment »

Binding jQuery code to an XPages partialRefresh using DOM Mutation events

Posted by MarkyRoden on October 29, 2014

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.

Posted in jQuery, jQuery in XPages, XPages | Tagged: , , | 1 Comment »