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.

Advertisements

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.

EXTJS in XPages #12 – Counting categories with Grouped columns

In this article I will demonstrate how grouping can be added to the EXTJS grid within your XPage and how the number of rows within that group can be totaled and displayed to the user.

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/xGridGrouped.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

“Categorization” is something we are used to in the world of Domino Views and we can also create a pseudo total of the categorized columns by totaling an adjacent column. This is functional but is hardly aesthetically pleasing.

Grouping is easily achieved with an EXTJS grid and as we will see it is also dynamic and will re-total on filtering as well

Using the ‘Ext.grid.feature.Grouping’ feature we are easily able to create and manipulate a grid which looks like this (grouped by state)

tot1

How does it work?

We do not have to add much to our code to include the grouping feature. We first create a new variable inside of the createGrid() function representing the new feature.

var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
	ftype: 'groupingsummary',
	id: 'groupingFeature',
	groupHeaderTpl: [
		'{name:this.formatName} ({rows.length})', 
		{
		//This is used to display "None" if there is a blank category
		formatName: function(name) {
			var sName = (name == "") ? "None ": name;
			return sName;
		}
	}],
	startCollapsed: false
});

There are a few parameters to discuss in this code block but for the most part I think the code is self explanatory.

The groupHeaderTpl is the paramater to determine how the actual grouping
group line is displayed. In this case we are using the EXT templating technique.

  • {name: this.formatName} is the name of the column Header – it uses the formatName function to conditionally display the name of the column
  • {rows.length} is the number of rows within the group (the total)
  • formatName (referenced in the previous this.formatName) is a conditional function which determines if there is a value to even display as the group header. In this case if there are blank fields in the grouped column it will display “None” instead of just displaying nothing and a number.

After adding this new variable we have to add the feature to the grid in the features parameter:

var grid = Ext.create('Ext.grid.Panel', {
	renderTo: 'gridHere',
	frame: true,
	height: 400,
	title: 'Users',
	plugins: buffRend,
	features: [groupingFeature, filters],
	etc

Finally we need to tell the store which field to initially group using the groupField and groupDir parameters:

store = new Ext.data.Store({
	groupField: "state",
	groupDir: 'ASC',
	model : 'Person',
	autoLoad: true,
	sorters: {
				property : 'firstName',
				direction: 'ASC'
			},
	id: 'store',
	data: data,
	remoteFilter: false,
	buffered: false,
	proxy: {
		type: 'memory'
	}
});

That’s it – once again a big increase in functionality with a relatively simple incremental code addition to the grids we already had.

Some other neat things grouping does for us
When we have a grouped grid and we go to filter it the group header is dynamically re-calculated based on the filtered results

tot2

Adding the grouping feature to the grid allows us to group any of the columns by selecting the “group by this column” option which now appears in the column dropdown

tot3

tot4

As you can also see from the images above – the user has the option to remove grouping as well “Show in groups”

Conclusion
In this article I have only scratched the surface of the possibilities with the grouped grid. Good looking categories with counts are something we have strived for in Notes for a long time and I think this is a very neat solution.

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

Adding a new browser to the XPages “Preview in web browser” menu

I wanted to add Chrome to my list of browsers which I could preview my XPages in and I went digging in the preferences and found out how

From within DDE (not the client) in File > Preferences under the general section there is a “Web Browser” option where you can add a new one

browser2

Then I had to find where Chrome was installed (obviously change UserName to your own path)

C:\Users\UserName\AppData\Local\Google\Chrome\Application\chrome.exe

Added it and there you have it – now in my menu 🙂

browser1

EXTJS in XPages #11 – Grids with Locked Column(s)

In this article I will highlight a grid column property which allows the developer to lock the columns on an EXTJS grid in a similar fashion to freezing a frame in excel.

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/xGridLocked.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

Locking a column (or two or three) is a very useful way of retaining reference information on the left and being able to scroll across multiple pieces of information to the right.

Doing so in an EXTJS grid creates the effect show below whereby a horizontal scrollbar is added to the grid to the right of the locked column.

lock1

How does it work?

It is a column property ‘locked = true’. The example code below uses the REST example as demonstrated before and I added the locked property to the first column. You do not have to use the REST service example, that was the just the one I chose.

    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,         //this is the new property
            field: {
                xtype: 'textfield'
            },
            filterable: true
        }, {.....

That’s all you need to do. the caveat is that you must have at least one scrolling column on the right – which makes sense because if they were all locked – then there would not be a need to have any locked 🙂

Interesting side note – you will notice that I locked the Last Name column which is not the first column listed in the view – but it moved to the left. You cannot lock columns 1, 3, 5 and have everything scroll around them, locked columns move to the left. I would guess there could be a performance issue in not putting them into the grid in the right order so I would suggest you always list your locked columns first 🙂