SSJS JSON parsing part deux

Yesterday’s blog post about adding json2.js created a discussion on it’s use and Johann pointed out that there were already JSON parsing functions baked into XPages SSJS. Phil Riand added them back in 8.5.1 and it has actually been mentioned a number of times on various Blogs. So apologies to all for me not knowing about it. I guess I never bothered to look as I knew how to do it with the json2.js 🙂

Julian Buss added a wiki post about it years ago – http://xpageswiki.com/web/youatnotes/wiki-xpages.nsf/dx/Work_with_ServerSide_JavaScript

	var json = toJson( {a:[1,2,3]} ) //-> '{"a":[1,2,3]}'
	var jsObj = fromJson( '{"a":[1,2,3]}' ) //-> {a:[1,2,3]}
	isJson( '{"a":[1,2,3]}' ) //-> true

So ok I learned something new – happens a lot – but then I also got to thinking – as I mentioned yesterday JSON.parse and JSON.stringify are so ubiquitous I decided to write some code to minic the coding standard in SSJS. This code serves zero purpose other than to make the usage of JSON consistent between SSJS and CSJS. It is a short version of what I wrote about yesterday and does not require the addition of the json2.js to the database.

	if (typeof JSON !== 'object') {
		JSON = {};
	}
	JSON = {
		parse: function(str){
			return fromJson(str)
		},
		stringify: function(obj){
			return toJson(obj)
		}
	}

Safe JSON parsing in XPages SSJS

JSON is now ubiquitous in the world of JavaScript and the origins can be found a http://www.json.org/.

Douglas Crockford was very concerned about using eval() to convert strings to objects and so he created  json2.js which can be found here https://github.com/douglascrockford/JSON-js/blob/master/json2.js. If you look at the code there is a huge RegEx in the middle of it which purposefully ensures that there is no dangerous code which the eval statement is run on. You should read the comments in the code – very insightful !

All browsers (IE8+) now support JSON.stringify or JSON.parse by default and we no longer need these functions to be added as an external library.

I found however that XPages SSJS does not seem to recognize the JSON object. So I added the json2.js code to an SSJS library and then added it as a resource within my XPage.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
	<xp:this.resources>
		<xp:script src="/json2.jss" clientSide="false"></xp:script>
	</xp:this.resources>
	<xp:repeat id="repeat1" rows="30" var="rep1">
		<xp:this.value><![CDATA[#{javascript:
			var temp ='[{"name": "marky"},{"name": "Billy"},{"name": "John"}]'
			return JSON.parse(temp)
		}]]>
	</xp:this.value>
		<xp:text escape="true" id="computedField1" value="#{javascript:rep1.name}"></xp:text>
		<hr />
	</xp:repeat>
</xp:view>

And with this I am now able to take a string of text – convert it safely to a JSON object and then use as the source for my repeat control.

json1

This message was inspired by Tim’s Tripcony’s blog post.

I love the idea of storing data as a JSON string inside of a single notes document field. This would move using Lotus Notes closer and closer to a modern NoSQL system, making applications more and more portable – love that idea.

However – this renders searching by field useless – which is usually one of the  requirements of an application.

jQuery event delegation

So it turns out that I may have blogged a moment too soon over the weekend….

While the following code works

	$('.modal').on('shown.bs.modal', function () {
		$('FORM')
			.append($('.modal-backdrop, .modal-scrollable'));
	})

It only works the FIRST time – and if you had tested your code properly Mark you would have found this out to be the case. Too eager to blog weren’t we Marky……*pouts*

So anyway like all mistakes a good excuse for more learning – and in this case it wasn’t so much learning it was more muscle memory and more (oh duh Marky – which happens a lot)

The problem
What is happening is that the original code above is only binding to the modal once – and once the modal is being shown on the page and then hidden again apparently that event binding is being lost. I have no proof of this but I suspect that the DOM objects are being destroyed and recreated which is what is causing the loss 😦

The solution
Event delegation – oh it is a wonderful thing once you get your head around it and extremely powerful – go read up about it here and check out the last example specifically

What I was doing is binding to the exact element and once that element is gone – no more binding.

What is Event Delegation?
Event delegation is basically the same thing as event binding, but it works on any matching element whether it exists yet or not.
Que?
What I mean to say is that this piece of code REALLY WORKS and I will explain

$('body').on('shown.bs.modal', '.modal', function () {
    $('FORM')
        .append($('.modal-backdrop, .modal-scrollable'));
})

In this example we are:

  • Selecting the Body
  • And then in the shown.bs.modal event of anything matching the .modal selector
  • do stuff as before.

So if you imagine a simple analogy of feeding a dog.

If you have a child – let’s say your son and you tell him that on the “breakfast event” put food in that exact blue dog bowl – he will do that

Being the obedient child that he is he will fill that bowl every day when it appears.

But being the obstinate child he is, when you replace *that* blue bowl with a new one he will not fill it because you told him to fill the old one

A fight ensues and he loses minecraft privileges!

You then change your instructions:  On the “breakfast event” put food in any dog bowl which appears in the Kitchen. So even if you replace it every day he will have to still do as he is told and fill the bowl.

That is what Event Delegation is – telling the DOM to do things to anything which exists now and anything which appears in the future.

The way it works is because of the second selector – you are telling the DOM body to look for anything with a shown.bs.modal and bind to it. So even though my original dialog apparently lost the binding, in the new case it is automatically re-applied because of the delegated event on the Body

If only I had remembered that before blogging earlier…….

Ah well – we all learned something new

I wonder what I missed today………..

Making XPages partialRefresh work in a bootstrap 3 dialog box.

In this article I will improve on the solution I posted last week to my form submittal problem and actually provide a more elegant and robust solution.

The problem

Dave Leedy

I mean to say that Dave Leedy posed a problem to me last Friday which gave me pause for thought. Obviously he had come across this issue before. “Marky have you tried to do a partialRefresh inside of the bootstrap modal dialog?”. I had not and I knew that I had plans to…..

Then it struck me – of course the partialRefresh can’t work in the dialog because the dialog is outside of the form. The partialRefresh relies on the ability to post data back to the server (via the form) and the collect the response and re-draw. Of course it isn’t going to work.

The solution

As I said the other day – the bootstrap dialog is not purposefully removing itself from the form, it is moving itself to the end of the DOM tree. Why? I couldn’t say but it seems to be pretty consistent. So on the assumption it is nothing to do with the “form” I figured the easiest solution would be to put it back *into* the form once it was visible.

As we saw before when the modal is created there are two elements moved to the end – the dialog itself and the faded out background

b3

Using a bit of jQuery magic we select those two DIVs and “append()” them back into the form. Using the append() method they are always added to the end of the target DOM element container. You should add this code to every page where you have a dialog. Add this code to a CSJS library and include it on every page where you have a bootstrap modal.

$(document).ready( function(){
	$('.modal').on('shown.bs.modal', function () {
		$('FORM').append($('.modal-backdrop, .modal-scrollable'));
	})
})

  What does that mean exactly?

  • In the ‘shown.bs.modal’ event of the selected $(‘.modal’)
  • Get the $(‘FORM’) and .append() into it the two selected $(‘.modal-backdrop, .modal-scrollable’) DIVs

and then you get this

b4

Once the modal is then inside the dialog we can post it to our hearts content.

We can prove that with a simple @Random within the dialog box and a quick code snippet in firebug

We add a “random” class to the computed text so that we can select it

b5

We then load up the dialog

b6

Run the JavaScript to cause a partialRefresh

b7

Et voila a partialRefresh with a dialog. It also works of course with XPage controls and buttons and the like but this was just a simple way to demonstrate how to do it

Conclusion

Once we understand the DOM changes which are being made for a bootstrap dialog we are able to use jQuery to easily manipulate the  resulting DOM to be able to make our application work.

 

ADDENDUM – updated

Please see the jQuery Event Delegation blog post to understand why this approach is limited and needed to be updated….new solution provided

Decoupling your CSS from your JavaScript, a “well no duh” moment

This weekend I had one of those “oh DUH” moments which I have been struggling with for quite some time. How can I better structure my jQuery selectors and make the code more maintainable? I came across this excellent article – Decoupling your HTML CSS and JavaScript and it all came into focus.

The problem

Using JavaScript selectors (dojo or jQuery) in XPages can be a problem because of the id naming scheme used by the JSP generator “id=”view:_id1:_id2:link5” and how this falls over in a selector. So an alternate to not having to mess with is attributes is to use class selectors $(‘.class’) which is actually much simpler and less troubling to get your head around.

When you are using class selectors for a DOM element which already has a class then awesome I don’t have to add any more classes. Using this bootstrap example there are multiple classes I can get a hold of to manipulate the dialog contents.

 <div class="modal fade myModal" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
			<button type="button" class="close modal-maxmin" aria-hidden="true">
				<i class="icon-external-link"> </i>
			</button>
			<button type="button" data-dismiss="modal" class="close" aria-hidden="true">
				<i class="icon-remove"> </i>
			</button>
          <h4 class="modal-title">modal-title</h4>
        </div>
        <div class="modal-body">
         modal-body : HERE GOES THE MESSAGE
        </div>
        <div class="modal-footer">
	        <div class="btn-group">
	          <button type="button" class="btn btn-default modal-cancel" data-dismiss="modal">CANCEL</button>
	          <button type="button" class="btn btn-primary modal-ok">OK</button>
	        </div>
        </div>
      </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
  </div><!-- /.modal -->

To add something to the body of the dialog I would do something like this

  $(".modal-body").html('Hi Marky')

The other problem

This example is very “coupled” code whereby my JavaScript selector is coupled to the real class file used by the HTML code. In reality what it means is that if I have to change the classname for some reason (hmm an example – oh I don’t know – going from Bootstrap2 to Bootstrap3 for example) then my JavaScript breaks down. While tightly coupled code is easy to follow, easy to create initially, it can be an absolute nightmare in the long run.

The epiphany moment

As I am reading Philip Walton’s article  I am struck by the “oh well no duh” moment when he talks about using js-* as a naming convention for classes which only exist for JavaScript selection.

  • My personal recommendation is to use a prefix for all JavaScript hooks. I use js-*. That way, when a developer sees such a class in the HTML source, she’ll know exactly where to look to discover its purpose.

Well no duh – brilliant idea!

In all senses this makes perfect sense:

  • The developer does not have to search through CSS files looking to see if you used the class as a selector as a real CSS marker
    • (well ok they changed something and the CSS broke, then they started to look for it)
  • It is immediately apparent from looking at the HTML that there is some dojo or jQuery selection/manipulation going to go on in this area because of the js-* class naming scheme
  • Within eclipse you can do a quick search and find out what is trying to manipulate this area before you go and ruin it

The new code

A very simple change to the modal-body but this then decouples my code form the bootstrap code – allowing me to make changes to the bootstrap classes int he future without breaking my JavaScript

 <div class="modal fade myModal" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
			<button type="button" class="close modal-maxmin" aria-hidden="true">
				<i class="icon-external-link"> </i>
			</button>
			<button type="button" data-dismiss="modal" class="close" aria-hidden="true">
				<i class="icon-remove"> </i>
			</button>
          <h4 class="modal-title">modal-title</h4>
        </div>
        <div class="modal-body js-modal-body"> <!-- js-modal-body change here -->
         modal-body : HERE GOES THE MESSAGE
        </div>
        <div class="modal-footer">
	        <div class="btn-group">
	          <button type="button" class="btn btn-default modal-cancel" data-dismiss="modal">CANCEL</button>
	          <button type="button" class="btn btn-primary modal-ok">OK</button>
	        </div>
        </div>
      </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
  </div><!-- /.modal -->

To add something to the body of the dialog I would now select the js-* class not the modal-body itself

  $(".js-modal-body").html('Hi Marky')

Comment

One of the things I love about my career is that it is an “always learning” experience for me. There are times like this where you think to yourself that is an awesome idea and you are very happy to learn it – and at the same time feel so stupid that you didn’t think of it yourself before 🙂

EXTJS in XPages #15 – Multi-select of documents

In this article I will discuss and highlight “multiselect” within the extjs grid. With a two line addition to the grid code we are able to select multiple documents and then action them.

EXTJS in XPages series
Here are links to all of the previous articles in this series

Demonstration
The EXTJS in XPages demonstration database can be found at http://demo.xomino.com/xomino/Extjs.nsf/xBufferedRendererCheckBox.xsp

Download
The sample database that will accompany this series is available from the menu in the live demo database from this link – http://demo.xomino.com/xomino/Extjs.nsf

Introduction

To be able to action more than one document we want to be able to select more than one in the grid. There are two ways we can do this and we are going to look at both. In the next article we will look at how to affect change to multiple documents.

mul1

How does that work?

Within the grid configurations we are able to add a multiSelect  parameter which allows us to select multiple documents. This can be achieved in the same way as you would multiselect in excel:

  • Hold down the SHIFT key and click two documents, Everything inbetween will be selected as well as the two documents clicked
  • Hold down the CTRL key and the documents clicked will be selected in addition to each other
  • Single clicking any other document without either key held down will only select the document clicked

mul2

  var grid = Ext.create('Ext.grid.Panel', {
        renderTo: 'gridHere',
        frame: true,
        multiSelect: true,     // <-----------
        height: 400,
        title: 'Users',
	    plugins: buffRend,

As you can see from the above picture the multiple selected documents are all highlighted.

Going one step further (if the users prefer it) you can add a “checkboxmodel” parameter to add “checkboxes” to the grid

  var grid = Ext.create('Ext.grid.Panel', {
        renderTo: 'gridHere',
        frame: true,
        multiSelect: true,     // <-----------
        selType: 'checkboxmodel',  //<----------------
        height: 400,
        title: 'Users',
	    plugins: buffRend,

Not only does this give a new interface it also allows users to select and deselect all by clicking on the checkbox at the top of the grid

mul3

Conclusion

Adding multi-select support to the grid is very simple and in the next article we will look at how to take action on that

EXTJS in XPages #13: Totaling your columns with a groupingSummary

In this article I will highlight a feature of the grouping capability – the “summary grouping”. This feature can be easily used to provide column totals on your grouped grid. We are also going to look at collapsing and expanding all the groups easily and further enhancing your grid features.

EXTJS in XPages series

Here are links to all of the previous articles in this series

Demonstration

The EXTJS in XPages demonstration database can be found at http://demo.xomino.com/xomino/Extjs.nsf/xGridGroupedSummary.xsp

Download

The sample database that will accompany this series is  available from the menu in the live demo database from this link – http://demo.xomino.com/xomino/Extjs.nsf

Introduction
As we saw in the previous article, adding “grouping” to a grid is relatively simple and with only a couple of changes we are also able to provide column totals. The example below shows the “sum” of the column for each group with a customizable label.

sum1

How does it work?

We are going to change two things from our grouping example. We are first going to change the Grouping feature to a GroupingSummary Feature. Other than that it is pretty much the same as before – I have added a couple of other optional parameters at the end so that the user cannot group the view by other columns.

	var groupingFeature = Ext.create('Ext.grid.feature.GroupingSummary',{
		id: 'group',
		ftype: 'groupingsummary',
		groupHeaderTpl: [
		  '{name:this.formatName} ({rows.length})', //Display "None" if there is a blank category
		  {
			  formatName: function(name) {
			  var sName = (name == "") ? "None ": name;
			  return sName;
		  }
        }],
        hideGroupedHeader: true,
        enableGroupingMenu: false,
        startCollapsed: false
	});

The second thing to change is adding parameters to the columns to show what kind of summary we want and what format we want it in.

In this case I have added the CVV2 column to the previous grid (cos it has numbers in it) and here is the column.

{
	text: 'C V V 2',
	width: 120,
	sortable: true,
	dataIndex: 'cvv2',
	field: {
		xtype: 'numberfield'
	},
	summaryType: 'sum',
	summaryRenderer: function(value, summaryData, dataIndex) {
		return value + ' widgets';
	},
	filterable: true
}

We have added the summaryType and summaryRenderer parameters to the columns object and as you can see it is fairly self explanatory what each option does. The summaryType field can be one of 5 options:

  • count
  • sum
  • min
  • max
  • average

The example below shows the “average” of the column for each group.

sum3

The summaryRenderer allows me to insert ” widgets” onto the end of the summary – but it could be hours, minutes years or any other label. You could even insert an icon or color the value based on status should you so chose.

Expand and Collapse
This code is equally applicable to the grouping feature in the last article. It is a simple peice of code which gets a handle on the feature (grouping or groupingSummary) and uses the 4.1 methods collapseAll() and expandAll() to do just that. The code below shows the updated gridDock object. Within that a “-” is a separator for the buttons.

var gridFunc = gridFunc || {}
gridFunc = {
	grid: function(){
	  return Ext.getCmp('myPanel')
	}
}

gridDock = [{
	id: 'activeStorePaging',
     xtype: 'toolbar',
     dock: 'bottom',
	 items: [
	   {
	       text: 'Clear Filter Data',
	       handler: function () {
	           grid.filters.clearFilters();
	       }
	   }
    ]
 },
'-',
   {
       text: 'Expand All',
       handler: function () {
           gridFunc.grid().features[0].expandAll();
       }
   },
'-',
  {
       text: 'Collapse All',
       handler: function () {
           gridFunc.grid().features[0].collapseAll();
       }
}]

In this example the gridFunc.grid() call is my way of getting a handle on the grid as discussed in this article. features[0] is the groupingFeature and that is it

sum4

Conclusion

The groupingSummary allows for a very simple and once again effective way of displaying data to your users using the EXTJS grid library.

Using Object literal notation to write better JavaScript in your XPages

In this article I will discuss one of the development pattern for creating JavaScript functions, Object Literal notation. We will look at the advantages to doing so and look at some of the neat things we can get from eclipse using this development pattern.

Introduction

As I have discussed on multiple occasions in blog posts and webinars, you should always try and separate your client side JavaScript from your XPages as much as possible. Using JavaScript libraries has many advantages:

  • Changes can be made without building your XPages
  • Separation of and therefore increased maintainability of functional design elements
  • Debugging using browser development tools
  • Syntax highlighting in the eclipse JavaScript editor

Creating JavaScript functions

There are many way in which you can create functions in JavaScript. You should definitely read this article Essential JavaScript Namespacing Patterns. Generally though the most common pattern I have come across in Domino development is the basic:

function foo(){
	// Do some stuff
}

As Domino developers, historically, JavaScript has been one of the languages we use to develop the application but “we” have never thought of ourselves as “JavaScript developers”, so why should we worry about doing it right, as long as it works….. But times changed quite some time ago and being a web developer is no longer about creating an application which works on the web, it is about using the web based tools and languages to the fullest of their potential. Domino Designer in Eclipse is not just our server side development environment, it is a powerful web based application development environment…..

Namespacing
In the browser the global (unspoken) namespace is “window” and any function created in this basic manner is created at that level. Any global variables declared at this level are pervasive across your application web page instance. For Example:

bar = [1]
function foo(bar){
	//Do something to bar
}

foo(bar);

is the same as writing

window.bar = [1]
window.foo = function(bar){
	//Do something to bar
}

window.foo(bar);

Polluting the namespace

What does that mean? If you have two variables or functions called the same thing then you can have conflict, pain and suffering. This can be caused by having multiple developers working on the same application and two of them using the same name for a function in a separate library they are working on, and then when the project is put together we have a problem.

Object Literal Notation

Creating a object from a literal array is simple in Javascript. “Object literal notation can be thought of as an object containing a collection of key:value pairs with a colon separating each pair of keys and values.”

This code creates a global person object with a firstname and lastname string property, and the age number property. The person object in in the global namespace but everything within the object is not. In this way we have taken up one global variable and not 4 (potentially):

	var person = {
		firstname: 'marky',
		lastname: 'roden',
		age: 21
	}

The typeof each property is not restricted to string and numbers – you can also have functions. In this example the fullname is returned from a function:

	var person = {
		firstname: 'marky',
		lastname: 'roden',
		age: 21,
		fullname: function(){
			return this.firstname + " "+this.lastname
		}
	}

	console.log(person.fullname())

Notice the use of “this” within the function. You have to be very careful when using “this” as a reference because of the JavaScript scoping but in this case it is straight forward. “this” is the person object.

So how does this help us write better JavaScript?

On occasions I have seen over 100 Javascript functions created within a single library, function after function after function. This makes for some tedious reading and maintainability is harder than it should be. When you see a function call on a web page which is causing you problems, you have no idea (without hunting for it) where the function is that you need to debug.

In addition as we have discussed if all the functions are at the top level within the namespace you have the risk of pollution and there is nothing more frustrating than staring at your correct looking function and wondering why it isn’t working, when in fact there is another function with the exact same name in the code you don’t know about. I expect many of you have been there, as have I.

Using the syntax as I demonstrated for person above we are able to create an object with a meaningful name and within that create functions.

So let’s plan to create our codebase with that premise….

For example I am now writing my grid functions to look like this:

var gridFunc = gridFunc || {} //if the object does not already exist declare it as an empty array

gridFunc = {
    self: this,
	grid: function(){
	  return Ext.getCmp('myPanel')
	},
	addLoading: function(){
		//add a loading mask
	},
	loadGrid: function(restService, titletag, query){
		//load the grid
	}
}

//if I ever need to get a handle to the grid on the screen I would call
var grid = gridFunc.grid()
//and because it is returned as an EXTJS object I can then use it as I normally would a grid variable
grid.doLayout(...)

Then we could create some chart functions like this

var chartFunc = chartFunc || {}

chartFunc = {
	loadPieChart: function(someJSON){
		//load a Pie Chart
	},
	grid: function(name, color1, color2){
		//load a grid Chart
	},
	loadBarChart: function(xAxis, yAxis, someJSON){
		//load a BarChart
	}
}

As you can see both of these objects contain a “grid” function but they do not clash because they are referenced as two completely different items:

  • chartFunc.grid()
  • gridFunc.grid()

Some nice features of Domino Designer in Eclipse

DDE helps us with code assist when you start you write JavaScript using Object Literals. I first created a JavaScript library within my database. That automatically opens up in an eclipse “JavaScript” editor. You do not get this functionality through an XPage source as that is an XML editor.

When you write a function the “old way” there is no help when you start to write out your code:

j1

But with object literal notation you get code assist. First of all it lists all the possible options for the demo object. If you have a list of functions within the object they will start to appear with the code assist. You’ve seen that before in DDE with other languages, now you’ve seen it in JavaScript as well !

j2

The code assist shows us that person is typeOf array and accepts up to three parameters. We can think of this as a method of the Person object.

j3

If we add a string to our object the code assist tells us so. We can think of this as a property of the Person object.

j4

That makes for a much easier life when coding!

Maintainability

Although you can separate your code into separate .js files for each functional capability (e.g. graphs.js, charts.js) I believe that using the object literal notation can take that abstraction another step, making code easier to find.

When we start to abstract our JavaScript code like this we take the first steps towards adding “JavaScript” developer to our toolset as a Domino developer.

There are other tool which can be used to develop JavaScript code libraries (sublimeText for example) and these tools provide even greater control over well written code. Writing the code “right” the first time will have its advantages down the line.

Conclusion

There is much to talk about – go read this article 5 times – it will take that long to take in the first couple of patterns, then bookmark it and come back to learn more. There are better ways to program – learn them 🙂

Arguably the most dangerous thing you could ever do in XPages – let other people use your eval() in their SSJS

In this article I will discuss the power of the JavaScript method eval() and demonstrate how your inappropriate usage of such could bring down your entire organization – yeah it is THAT dangerous….

Introduction

In JavaScript the eval() method has long been known as extremely powerful and also extremely dangerous. It turns a string into an executable piece of JavaScript code.

It can turn string  into JSON arrays:

var str = '[{marky: "genius"}, {brad: "blog monster"}]'
eval(str)

But it can also lead to more sinister things like XSS cross scripting attacks and other nasties – http://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea

Well guess what – you can also use eval() in SSJS – yaaaaaaaaay

No – Boo ! Big fat Boo and it should only be allowed in specially controlled circumstances – it can only hurt innocent developers who didn’t realize the risks or hurt innocent users who do not understand the responsibility which comes with the power.

But this would be a really cool capability

If you were able to give your users the ability to pass through some SSJS through the XPages web interface so that they could create some custom reports without having to add code to the database – that would be really nice of you, very flexible and kinda cool.

Let the user type in their own SSJS through a field on the form and then eval() the code executing it on the back end….NICE

And now you can see where this is going – suppose you either have:

  • A complete dufus working at your company 
  • An extremely smart and well trained disgruntled employee

You are in for a whole world of hurt.

Who does eval() run as?

The Signer of the XPage – which means in many corporate environments that is the signer id which has the ability to run unrestricted agents on the server – so in no time at all anyone could…and it would take most of us less than an hour to write this code….

  • Go to the catalog
  • Get every database
  • Get every document in every database and download the contents
  • Delete every document in every database
  • Delete NAB users
  • Replicate these changes out to every server in the environment
  • Mess with the server settings

Yeah but Marky we can all do that anyway so why the big deal

Yes I know you have the signer id or access to insert malicious code into your own environment – but your users don’t. Let me rephrase that – they had better not otherwise your administrators need beating with sharp sticks.

The risk in reality is people hurting themselves – writing code in the browser and then evaluating it on the server – is not:

  • Developing in in a dev environment
  • Thoroughly testing it in a secure test environment
  • Rolling it out to production in a controlled and pre-planned manner

No – it is giving the power of god to your users – and frankly, some of them are idiots…

Because the code would run as the signer it also gives users the potential to access areas of the server they would not otherwise have access to – databases, readers fields etc – that is also not good. And with this they have the power to cover their tracks as well – cos well it was clearly the signer who made the changes not them.

Can we do anything to protect ourselves?

Probably……

First – don’t let un-trusted, untested code into your environment – you wouldn’t let a developer do it, why let a non-developer do it ?!

Then maybe, do code reviews and do not allow code to be run unless reviewed, locked and approved.

Conclusion

This article is intentionally alarmist because I do not want to underestimate the potential risks involved. As I said in reality you are unlikely to cause any more trouble to stupid users than them hurting themselves.

eval() is used judiciously and in a well controlled manner is extremely powerful and allows developers the ability to do things otherwise impossible.

With using eval() comes the need for a complete understanding of the risks evolved. Used incorrectly it could be used to destroy your environment in a manner very few other code snippets are able to.

Editing and testing your XPages CSJS “in real time” using Chrome Developer Tools

In this article I will demonstrate how you can make live changes to your CSJS using firebug and chrome deveveloper tools and figure out where your bugs are happening before committing them to your XPages database.

Introduction 

First rule of thumb – put as much of your XPages Client Side JavaScript (CSJS) in a JavaScript script library as possible. The reasons are compelling and simple:

  • Separation of code makes for much easier maintenance
  • Changing CSJS libraries required a CTRL-F5 to view the changes and no BUILDING of the database code

The demonstration

I have created a very simple XPage and my code is not working – I want to find out why not. I could use the console to test my code and just run it before updating the CSJS library – but I wanted to show this method of debugging because it is probably more applicable to a more complex function than this simple one. The XPage source looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
	<xp:this.resources>
		<xp:script src="/csjsFirebugChromeDemo.js" clientSide="true"></xp:script>
	</xp:this.resources>

	<xp:br></xp:br>
	<xp:button value="Click me" id="button1">
		<xp:eventHandler event="onclick" submit="false">
			<xp:this.script><![CDATA[changeMe();]]></xp:this.script>
		</xp:eventHandler></xp:button>
	<xp:br></xp:br>
	<xp:br></xp:br>
	<xp:br></xp:br>
	<div class="change"></div>
</xp:view>

As you can see I have a button, a div and an included CSJSFireBugChrome resource This is the library

function changeMe(){
	$('change').html('this changed')
}

When I load the XPage and click the button nothing happens – why not? Well it is because the jQuery selector is wrong.

$(‘change’) will select all the elements with a Tagname CHANGE rather than selecting the class change which is really what I was looking to do. Let’s see how we can play with this in two dev environments.

Firebug console

As I have mentioned in other articles – a JavaScript function is easy to over-ride in the console. The global namespace for web browser Javascript is “window” and all functions live there by default. To over ride them we just use window.functionname in the console and create our own function. This demonstration is also applicable to Chrome Dev Tools console.

The example below shows what happens when I over-ride the function through the console. Not that I have added the .changeMe in the jQuery selector.

fire1

Then when I run the script and click the button again – success

fire2

Chrome live editing

Opening Chrome Developer tools allows you to view the “Source” of the files used in your XPage and edit them. This technique only works on the scripts which are loaded through a library – you cannot edit the code if it is inline within your HTML code. When we look in the chrome source we can see the CSJS function already there – hit F12 to make it come up and select the source option. Click on the arrow top left

ch1

Which then gives us the function

h2

This is editable !! All you need to do is make the change and then do a CTRL-S the save the change. (This is of course only changing the cached version of the function in the browser and not saving it back in your XPage). When we click the button again it now works 🙂

ch3

Advanced changes using breakpoints

This is where it can get really cool 🙂 As I mentioned before you cannot make changes to code which has already executed and code which in inline – but what you can do is set a breakpoint in the code and edit it before it is executed…..

In my EXTJS locking grid article I demonstrated that you can lock a certain column. Once the EXTJS code is run I cannot edit it through the Chrome source but I can make changes the code pre-execution using a break point. This way I do not have to keep saving  the XPage I can just reload the page and make changes as I see fit until I am happy with the code. This is the code and you can see the locked column is the lastname one.


    var grid = Ext.create('Ext.grid.Panel', {
        renderTo: 'gridHere',
        frame: true,
        features: [filters],
        height: 400,
        title: 'Users',
        store: store,
        iconCls: 'icon-user',
        columns: [{
            header: 'First123',
            sortable: true,
            dataIndex: 'firstname',
            filterable: true
        }, {
            text: 'Last',
            sortable: true,
            dataIndex: 'lastname',
            locked: true,                //here is the locked on lastname
            field: {
                xtype: 'textfield'
            },
            filterable: true
        }, {
            text: 'Address',
            sortable: true,
            dataIndex: 'address',
            field: {

I add a breakpoint in the code by clicking on the line number in the source code

br1

I then reload the page and the breakpoint stops where I told it to in the code execution

br2

I then change the code to lock the First123 column and not the lastname column by editing the JavaScript in the source

br3

et voila 🙂

Conclusion

In this article we have seen how using the Chrome Developer tools we can effect change to our CSJS without having to resort to re-saving anything in out XPage application. I especially like the breakpoint editing which *really* helps me to pinpoint my code errors and make sure they work before I change my XPage.

This is extremely productive