HTML5, CSS3, jQuery, JSON, Responsive Design...

jQuery.getDominoViewJSON() function

Administrator   November 17 2012 11:34:51 PM
Following on from my post describing the horrendous Ajax bug in Domino 8.5.2/8.5.3, I thought I would I have a go at putting together a jQuery plugin that fetches data from a Domino view as JSON via Ajax, and that this function should incorporate the workaround for this bug that I described in my earlier post.

This function, which I've called getDominoViewJSON(), is really just a front-end to the jQuery.ajax() function.  But this is nothing new: there are number of such convenience functions within jQuery itself - i.e. jQuery.get(), jQuery().getJSON, jQuery().load and so on - and these are all just front-ends to jQuery.ajax() in the background.

The function takes at least one parameter, which is an object.  That object's attributes are as follows:
  • dbPath: web path to your Domino database.  Defaults to "/names.nsf" if not supplied.
  • view: the view from which you're pulling the data.  Must be supplied if no agent parameter is supplied.
  • agent: an agent which will be printing your data.  Must be supplied if view parameter is not supplied.  Ignored if view parameter is supplied.
  • start: the start parameter.  No default.
  • count: the count parameter. No default.
  • RestrictToCategory:  yes, the RestrictToCategory parameter!  I doubt you need me to tell you what it does.  Check the Designer Help if you don't.
  • cache: true or false.  Passed straight through to the jQuery.ajax() cache parameter.  Defaults to true (queries are cached).
  • forceNoCache: true or false.  Defaults to false.  Forces caching via the today's date and time parameter trick.  If true, all jQuery.ajax() calls will have a _jqdvsForceNoCache parameter appended, with its value set to the current date and time (down to the second).  This guarantees that all ajax calls are not cached.  (See Update 05/03/2013 section below for more info.)
  • forceNoCacheInterval: integer period of minutes after which Ajax calls are forced to get fresh data.   Should be set between 0 and 60.  Only used if forceNoCache is set to true.  The regular cache parameter should also be set to true in this case.  (See Update 06/03/2013 section below for more info.)
  • other: a generic parameter.  Anything you assign to this will be appended to the Ajax query.  You'll need to include any ampersands and so on.
  • success: a function that will be run if the data is retrieved successfully.  Must be supplied.  (Well, not much will happen if it isn't!)
  • error: a function that will be run if the data is not retrieved successfully.  If not supplied, an alert of the error will pop-up instead.

Here's an example of how you might call such a function with a single function:
$.getDominoViewJSON({
    dbPath: "/tools/fakenamess.nsf",
    start: 1,
    count: 100,
    view: "($VimPeople)" ,
    success: function(jsonObj) {
           console.log("mySuccessFunction(): " + JSON.stringify(jsonObj));                // Note: JSON object not available in older versions of IE
    },
    error: function(e) {
      console.log("Supplied error function was called: " + e);
    }
});


Update 22/11/2012 - Optional Map Array Parameter

If supplied with only the one configuration object parameter, described above, then what is returned is the default JSON object that is generated by Domino.  If you've seen these before, then you'll know that such a JSON object contains a lot of Domino view generated junk that you're probably not too interested in.  You'll likely want to strip that stuff out so you can more easily get to the actual data in the object.

Alternatively, you can supply a second parameter to getDominoViewJSON() and the function will do that for you.  This second parameter, if supplied, must be an array of objects, each one of which must have the following parameters:
  • colNo: the number of the column to be returned, with the first column being 0 (zero).
  • name: the name that you want to give the data being returned by the current column.  (The view's column title, if you like.)
  • dataType: the type of data that the column holds.  Possible types are "text", "date", "dateISO" (see below) or "number".  Defaults to "text" if not supplied.

Here's the function call example, updated to specify a second array parameter:
$.getDominoViewJSON({
dbPath: "/tools/fakenames.nsf",
start: 2,
count: 100,    view: "($VimPeople)",
success: function(jsonObj) {
  console.log("mySuccessFunction(): " + JSON.stringify(jsonObj));                // Note: JSON object not available in older versions of IE
},
error: function(e) {
  console.log("Supplied error function was called: " + e);
}
},
[{name: "fullName", colNo: 0},{name: "firstName", colNo: 1}, {name: "lastName", colNo: 3}, {name:"dataCreated", colNo: 4, dataType: date}]);



dateISO Column Type (Update 12/01/2013)

This data type assumes that your view column is a textual representation of a date, but in ISO 8601 format: e.g. 2013-01-12 for just a date or 2013-01-12T12:08:38 if there's a time component.  Note that ISO 8601 is fussy about leading zeroes:  you must use "01" for January, not just "1".  Likewise, it must be "01", "02" for the days.  You can set this up in your view column formula by using the @Right() function to add the leading zeroes, e.g:

@Text(@Year(Date1)) + "-" + @Right("0" + @Text(@Month(Date1));2) +  "-" + @Right("0" + @Text(@Day(Date1));2)
 


Update 05/02/2013 - forceNoCache parameter

When set to true, all jQuery.ajax() calls will have a _jqdvsForceNoCache parameter appended to their query string.  Its value set to the current date and time (down to the second).  This ensures that every ajax query string is unique, and therefore, cannot be cached.

I added this parameter when I saw that for some browsers the normal cache ajax cache parameter wasn't always being obeyed.  You'll no doubt be as shocked as I was to discover that older versions of Internet Explorer were the culprits here.


Update 06/02/2013  forceNoCacheInterval parameter

When the forceNoCache parameter is set to true, you can also specify time inteval, in minutes, for how often you want the ajax call to retrieve the new data.  Value must be a number between 0 and 60.  It works by rounding up the time component of the ajax call's _jqdvsForceNoCache parameter (see previous paragraph) to the nearest clock equivalent.  E.g. if the parameter is set to 15, then the _jqdvsForceNoCache parameter's time component is rounded up to 15, 30, 45 and 00.  After each clock period is passed, any subsequent Ajax calls will pull in fresh data.

Note, the "normal" Ajax cache parameter can (and really should) be set to true, when forceNoCache is set to true and a forceNoCacheInterval value is set.



Downloads

Version 0.7, 02/05/2013
  • Broke the mapArray functionality out into its own plugin, jQuery.mapDominoViewJSON.  The jQuery.getDominoViewJSON plugin now calls this new plugin rather than having its code embedded in itself.  This allows you to use the mapArray functionality on data that you've retrieved from a view, independently of jQuery.getDominoViewJSON.  (I'm using it in the backbone.js parse() function of a backbone.js Collection, for example.)
  • Fixed problem where test for no results didn't always work.
getDominoViewJSON.0.7.txt

Version 0.6, 06/02/2013
  • Added forceNoCacheInterval parameter.
getDominoViewJSON.0.6.txt

Version 0.5, 05/02/2013
  • Added forceNoCache parameter.
getDominoViewJSON.0.5.txt

Version 0.4, 15/01/2013
  • Fixed bug in new dateISO interpreter so that it now works on IE.
getDominoViewJSON.0.4.txt


Version 0.3, 12/01/2013
  • Some bug fixes, e.g. the map data function no longer triggers a JS error when no results are returned
  • Added dateISO data type for the Map Array functionality
  • Added RestrictToCategory parameter
getDominoViewJSON.0.3.txt


Version 0.2, 22/11/2012
  • Added the mapArray functionality as the second, optional parameter to the function
getDominoViewJSON.0.2.txt

First version, 0.1, 17/11/2012
getDominoViewJSON.0.1.txt
Comments

1Edward Lee  01/15/2013 7:39:19 AM  jQuery.getDominoViewJSON() function

Can I just say thanks for writing this blog post.

I was scratching my head trying to get JQuerys AutoComplete to work with Domino JSON and this post put me on the right track.

The only modification I need to do was remap values when I got that back to the autocomplete function (see below), but that's only because of AutoComplete's specific needs.

response($.map(jsonObj.dataArray, function(item) {

return {label: item.label,value: item.value}

}))

Thanks so much.

Ed

2Fran  04/23/2013 4:23:18 AM  jQuery.getDominoViewJSON() function

Awsome blog & awsome post!!!!

Is it possible to return json object?

In the success function I tried to "return jsonObj" and then do the "console.log" of the return value but I get "undefined"

What I'm doing wrong?

3Mike Brown  04/23/2013 6:20:58 AM  jQuery.getDominoViewJSON() function

@Fran,

Return it to where? Where are you putting your "return jsonObj" call?

4Fran  04/23/2013 3:50:15 PM  jQuery.getDominoViewJSON() function

Something like

var jsonObj = $.getDominoViewJSON(...)

I modify your function for adding a new "configOption" for return "readdesign", and it works great (your code is so clear and easy to adapt... great!!)

So, I need 2 objects: the "readdesign" (col titles, widths, ...) and the "readviewentries" (col values)

And finally, I should process that 2 objects with the same function.

And to do that, I need that json object...

5Michael Brown  04/23/2013 5:34:29 PM  jQuery.getDominoViewJSON() function

@Fran,

Re: var jsonObj = $.getDominoViewJSON(...)

Sorry, but Ajax doesn't work that linear way. Ajax data retrieval is a background process. You must use the success callback function to retrieve the JSON object; it's the first parameter that's passed to it, in fact.

If Ajax worked the way that you seem to be asking for, then your whole application would pause at your var jsonObj = $.getDominoViewJSON(...) line, while it waited for your data to return. And who knows how long that might take? The browser could do nothing else while it's waiting. It would appear to be frozen for the user, who would likely assume that it's crashed after a few seconds and would reach for Ctrl->Alt->Delete.

Note that you don't have to write the whole all of your object handling code inside the success function though. If you have an external function, they you can pass the jsonObj to that, e.g.:

function mySuccessFunction(jsonObj) {

// Do your stuff with jsonObj

}

$.getDominoViewJSON({

dbPath: "/myPath/myDB.nsf",

start: 2,

count: 100,

view: "myView",

success: function(jsonObj) {

mySuccessFunction(jsonObj);

}

}

6Fran  04/23/2013 9:08:53 PM  jQuery.getDominoViewJSON() function

Thank you Michael, I would try to chain 3 (or 4) levels my functions, because I need to get view data and column titles dynamically, so I need do 2 "getDominoViewJSON" and then, process the 2 json objects, so, it must be "synchronous" (at least "readvdesign").

But I think it's easier for me modify your code and, in the ajax success function, assign json object to a variable that I can return at the end of the function...

Clean and understandable code is amazing!!!!

7Mike Brown  04/24/2013 5:54:05 AM  jQuery.getDominoViewJSON() function

@Fran,

Keep in mind that when you're kicking off multiple Ajax call, there's no way to know when they'll finish or in what order. The first Ajax call that you make might actually finish after the second call you make!

If you must have the calls chained in order, then you could look at making your second Ajax call from within the success function of your first Ajax call. Then the order really is guaranteed. You can also pass the results of the first call - your first JSON object - as an extra parameter to the function that kicks off the second call. Then the success function for your second call can do whatever you need to do to put the two result objects together.

About