PDA

View Full Version : Extending Ext.nd Alpha 2 to support categorized views


GavinL
07-18-2007, 05:10 AM
I spent half an hour seeing how easy it would be to extend Ext.nd Alpha 2 to support categorized views. As it turns out, it was fairly trivial.

See: http://extjs.com/forum/attachment.php?attachmentid=1015&d=1184747490

Rather than alter the Ext.nd scripts directly, I created an extension script that extends and overrides some of the classes and methods. This way, all you need to do is add one new script tag and one new stylesheet tag to the Ext.nd.$$ViewTemplateDefault, update the JS Header and HTML Head Content, and add the JS file and CSS file as file resources to the Ext.nd database.

In the process I also fixed the display of Domino icons in the outline, and put a partial fix in place for the action bar icons.

(Reminder: if you've already copied the Ext.nd.$$ViewTemplateDefault form to your database, you'll need to re-copy it over once you've updated it in the Ext.nd database).

To use the script, you need to update Ext.nd.$$ViewTemplateDefault as follows:

Ext.nd.$$ViewTemplateDefault
----------------------------

JS Header
---------

// ViewTemplateDefault is declared in HTML Head section
ViewTemplateDefault.init = function() {
var ui = new Ext.nd.ux.DominoUI({
uiView : {viewName : this.viewName},
uiOutline : {
outlineName : 'AllViews',
useOutlineIcons : true
}
});
}
Ext.onReady(ViewTemplateDefault.init, ViewTemplateDefault , true);

HTML Head
---------

viewName := @Subset(@ViewTitle;-1);
dbPath := "/" + @WebDbName + "/";
ServerName := @If(@TextToNumber(@Version) < 190; @Subset(@DbName;1); @ServerName);
unid := @Text(@DocumentUniqueID);
extndUrl := @GetProfileField("Ext.nd.Profile"; "ExtNDDb"; ServerName);
mode := @If(@UrlQueryString("debug") = "true"; "-debug"; "");
"<!-- Ext JS library -->" + @NewLine +
"<script type='text/javascript' src='" + extndUrl + "ext/adapter/ext/ext-base.js'></script>" + @NewLine +
"<script type='text/javascript' src='" + extndUrl + "ext/ext-all" + mode + ".js'></script>" + @NewLine +
"<!-- Ext.nd JS library -->" + @NewLine +
"<script type='text/javascript' src='" + extndUrl + "extnd/extnd-all" + mode + ".js'></script>" + @NewLine +
"<script type='text/javascript' src='" + extndUrl + "extnd/ux/source/extnded.js?Open&nocache=" + @URLEncode("UTF-8";@Text(@Now)) + "'></script>" + @NewLine +
"<script type='text/javascript' src='" + dbPath + "Ext.nd.Session.js?ReadForm'></script>" + @NewLine +
"<script type='text/javascript'>" + @NewLine +
" Ext.nd.init({extndUrl : '" + extndUrl + "'});" + @NewLine +
" var ViewTemplateDefault = {};" + @NewLine +
" ViewTemplateDefault.viewName = '" + viewName + "';" + @NewLine +
"</script>" + @NewLine +
"<link rel='stylesheet' type='text/css' href='" + extndUrl + "ext/resources/css/ext-all.css' />" + @NewLine +
"<link rel='stylesheet' type='text/css' href='" + extndUrl + "ext/resources/css/xtheme-aero.css' />" + @NewLine +
"<link rel='stylesheet' type='text/css' href='" + extndUrl + "extnd/resources/css/domino.css' />" + @NewLine +
"<link rel='stylesheet' type='text/css' href='" + extndUrl + "extnd/resources/css/Ext.nd.ed.Domino.css' />"

You should then add the the .js file from the attached zip below to the Ext.nd database as a file resource called extnd/ux/source/extnded.js, and add the .css file from the attached zip below as a stylesheet called extnd/resources/css/Ext.nd.ed.Domino.css

I've done very little testing of the code so far, so like Ext.nd please consider this alpha code and use at your own risk. It's not as feature rich at the moment as the standalone database I posted a couple of weeks ago, but it shouldn't take too much longer to get it to that stage.

bhaidaya
07-18-2007, 02:09 PM
Nice addition.

I incorporated your changes similar to your recommendations although instead i used an ext.nd.overrides.js which i placed in the head after the extnd inclusion.
what happens next is each view works but displays '[object Object]' in every cell. I haven't tracked down where this is happening. I've attached a screenshot and a copy of my overides file... perhaps you can take a look?

bhaidaya
07-18-2007, 02:25 PM
Just to clarify, my file does not include all of your changes...
and the difference in refrence is i am doing

Ext.nd.data.DominoViewXmlReader.readRecords = function(doc) {

this.xmlData = doc;



instead of what you are doing


Ext.extend(Ext.nd.ux.data.DominoViewXmlReader, Ext.nd.data.DominoViewXmlReader, {

readRecords : function(doc) {

this.xmlData = doc;


The only reason i did this was because i'm already doing a significant amount of overrides in order for it to work in my application and this allows me to compare and update where i've made changes...

bhaidaya
07-18-2007, 03:41 PM
Fixed...
Ext.nd.data.DominoViewXmlReader.readRecords = function...
should be
Ext.nd.data.DominoViewXmlReader.prototype.readRecords = function...

and there is one more like that as well... silly me.

I've attached my current overrides file, which includes some fixes for bugs and behaviours.. i don't htink all of these are usable by everyone especially my opendocument and outline double click..

GavinL
07-18-2007, 03:51 PM
It looks like you've discovered what's causing the problem for you - I used my own class as a replacement for DominoViewXMLReader which you are not implementing.

The reason the code doesn't work if you exclude this override is that I've changed the record config to use the column name rather than the column number. Past experience has shown me you run into a lot less problems by doing this.

Therefore, you'll need to change the dominoRenderer function so that it uses val.data rather than val, and you'll also need to change the recordConfig variable so that the mapping points to columnnumber.

However, you'll now find that any views that have categories in the format category\subcategory (e.g. pseudo categories) will now fail to render any value (For example - take a look at the certificates view in the Notes Address Book). You might be able to fix that in the doRender function of Ext.nd.ux.grid.DominoGridView but I don't know a quick fix.

GavinL
07-18-2007, 04:03 PM
Fixed...
Ext.nd.data.DominoViewXmlReader.readRecords = function...
should be
Ext.nd.data.DominoViewXmlReader.prototype.readRecords = function...

and there is one more like that as well... silly me.

I've attached my current overrides file, which includes some fixes for bugs and behaviours.. i don't htink all of these are usable by everyone especially my opendocument and outline double click..

Ah - I see what you've done. You are still using my parseEntryData function, so you shouldn't need to modify recordConfig or the dominoRenderer function. That's probably a better approach as it means you're still using the column names rather than numbers.

I'm glad it's working for you. I need to take a more thorough look through your other changes but it looks like there's some useful fixes in there I could use myself - thanks.

bhaidaya
07-18-2007, 05:06 PM
Yeah good stuff.

Once I implemented your code I broke my grid filters in my search fields so i'll post a fix to that when i get to fixing that. ( i'm sure it's a val.data instead of val like you said)

bhaidaya
07-18-2007, 05:23 PM
Here it is...

replace this line in Ext.nd.UIView.prototype.handleViewSearch
if ( r.data[aux1[j]].data[0].toLowerCase().indexOf(value.toLowerCase()) < 0 ){

with this...
if ( r.data[aux1[j]].toLowerCase().indexOf(value.toLowerCase()) < 0 ){

this filter doesn't handle paging well but works great for a client side filtering approach

Zakaroonikov
07-18-2007, 06:00 PM
I spent half an hour seeing how easy it would be to extend Ext.nd Alpha 2 to support categorized views. As it turns out, it was fairly trivial.

See: http://extjs.com/forum/attachment.php?attachmentid=1015&d=1184747490



Brilliant work Gavin. It works a treat.

Dominoble
07-31-2007, 01:17 PM
It works pretty well but if you remove a column in the view the data doesn't realign properly. It would also be great to have CollapseAll and ExpandAll functions. Thanks again!

Zakaroonikov
08-20-2007, 10:37 PM
I noticed that you are using the record.mapping as

'entrydata[@name="' + name + '"]'


instead of
columnnumber

This appears to break the remote sorting of extnd as it is using the columnnumber to determine what to sort on. Is there any way that we can get both functions working together?

GavinL
08-21-2007, 07:01 AM
I noticed that you are using the record.mapping as

'entrydata[@name="' + name + '"]'


instead of
columnnumber

This appears to break the remote sorting of extnd as it is using the columnnumber to determine what to sort on. Is there any way that we can get both functions working together?

Yes, past experience has shown me that you run into a lot less problems using the name rather than the columnnumber (especially with RestrictToCategory where the column numbers shift, and working with pseudo category columns).

I actually have column sorting working properly in my application, but didn't include it in the patch to Ext.nd as I seemed to be overriding a lot of code and it was becoming more complicated than it needed to be. If you're interested, you should be able to create an override from the column sorting code I have in this application: http://www.openntf.org/Projects/codebin/codebin.nsf/CodeByDate/67BCFE4494F3639E862573080037FD81?OpenDocument

I haven't got a lot of spare time at the moment to update the extension, but I'll have a look an see much effort it would take to pull out the revised column sorting code and add it in.

s_redko
10-09-2007, 04:24 AM
Dear all,

We faced with the same problems as described here:
http://extjs.com/forum/showthread.php?p=70478#post70478

We have modified the ext-nd-overrides-v2 to support the following:
1. Multi-level categories or response hierarchy
2. Subtotal in categories and column totals
3. FTSearch in view

So views look good enough in Ext.ND now !:D

Please find the code in the attachment.

tarikonen
10-09-2007, 04:46 AM
I have inserted your js and css in my database but categorized view don't appear correctly. I have modified Ext.nd $$ViewTemplateDefault to include extended.js...
On Internet explorer i don't see category and relative spin, in Firefox i can see category and spin but i can't expand or collapse

what is wrong?

Thanks a lot for your work

s_redko
10-09-2007, 05:04 AM
I think you need to change JS Header code to the following:

ViewTemplateDefault.init = function() {
var ui = new Ext.nd.ux.DominoUI({
uiView : {viewName : this.viewName},
uiOutline : {outlineName : 'YourOutlineName'}
});
}

Ext.onReady(ViewTemplateDefault.init, ViewTemplateDefault , true);

tarikonen
10-09-2007, 05:11 AM
I have already modified the JS Header of Ext.nd $$ViewTemplateDefault with "ux" reference... but not work... :((
Any idea?

Thank's for your support...

GavinL
10-09-2007, 06:07 AM
I'm not sure what you're problem may be just from your description. Do you have an online demonstration of the problem you can share?

The code didn't go through a great deal of testing, but it worked for all the views in the address book I tried. Maybe start with a simpler example, such as trying it against a copy of the address book? See if you can get that working first.

GavinL
10-09-2007, 06:09 AM
Nice work! I'll take a look and see if I can update the main post with your changes. I still need to look at fixing the column sorting that I broke with my original change - should get around to that soon.

Dear all,

We faced with the same problems as described here:
http://extjs.com/forum/showthread.php?p=70478#post70478

We have modified the ext-nd-overrides-v2 to support the following:
1. Multi-level categories or response hierarchy
2. Subtotal in categories and column totals
3. FTSearch in view

So views look good enough in Ext.ND now !:D

Please find the code in the attachment.

s_redko
10-09-2007, 07:02 AM
I am glad that you find our changes usefull.

Yes you are right, column (category) sorting is very important feature of Domino views.
But I think we need to have also other base view features like:
1. Collapse All/Expand All
2. Export (CSV, Excel)

Do you have any plans for implementing such features ?

Do you think we can expect something similar for categorized views in the next release of Ext.ND ?

tarikonen
10-09-2007, 07:02 AM
It's possible that my database don't use $$ViewTamplateDefault?
Sorry for my silly question but i have deleted the form Ext.nd.$$ViewTamplateDefault and nothing is changed...

GavinL
10-09-2007, 09:13 AM
I agree - expand all/collapse all would be useful, but my previous attempts to provide this have suffered severe performance problems when the view contains many levels of categorisation, and many documents in those categories. I'd love to see someone come up with a good solution for that. The way that the category code works at the moment would mean multiple asynchronous requests to retrieve the sub category data for each node. Export to CSV should be less of an issue - you could do that fairly easily with an agent.

As this was an independent effort, I'm not sure what plans Rich and Jack have for category and parent/child hierarchy support for Ext.nd based on 2.0. The new grouping options in the 2.0 grid look useful, but they only get you part of the way.

I am glad that you find our changes usefull.

Yes you are right, column (category) sorting is very important feature of Domino views.
But I think we need to have also other base view features like:
1. Collapse All/Expand All
2. Export (CSV, Excel)

Do you have any plans for implementing such features ?

Do you think we can expect something similar for categorized views in the next release of Ext.ND ?

s_redko
10-09-2007, 09:35 AM
Collapse All/Expand All

Why don't just reload UIView component with "?ReadViewEntries&CollapseAll" or "?ReadViewEntries&ExpandAll" datasource instead of multiple asynchronous requests ?

Export to CSV

Yeah, task is simple with exporting all entries. But what about selected entries only ? We need client-side (grid-side) export for such case.


I agree - expand all/collapse all would be useful, but my previous attempts to provide this have suffered severe performance problems when the view contains many levels of categorisation, and many documents in those categories. I'd love to see someone come up with a good solution for that. The way that the category code works at the moment would mean multiple asynchronous requests to retrieve the sub category data for each node. Export to CSV should be less of an issue - you could do that fairly easily with an agent.

As this was an independent effort, I'm not sure what plans Rich and Jack have for category and parent/child hierarchy support for Ext.nd based on 2.0. The new grouping options in the 2.0 grid look useful, but they only get you part of the way.

tarikonen
10-09-2007, 09:58 AM
I have already modified the JS Header of Ext.nd $$ViewTemplateDefault with "ux" reference... but not work... :((


Ok, now it work. The problem was due to the fact that I modified the form Ext.nd.$$ViewTemplateDefault instead of modifying the main form (start form) of the application.

Thank's to all

captainm1uk
10-09-2007, 05:48 PM
Hi- i am being a bit silly here but i added the files to the db the js and css - edited the js header to include the ux and now get error ex.nd.ux.dominoui is null or not an object. I just imported the extended.js into the file structure right ? or am i missing something

captainm1uk
10-09-2007, 06:28 PM
Sorry was being silly - didn't read the first post correctly - works a treat

Thanks

tarikonen
10-10-2007, 03:48 AM
Hi, i have installed the s_redko ext-nd-overrides-v2 and now i see categorized view correct, but i have realized that full-text search doesn't work anymore. I have created the index and when from footer bar of the grid i make the search it doesn't return me any result.
It's only a mine problem?

Thanks in advance

zeus
10-10-2007, 09:30 AM
Dear all,

We faced with the same problems as described here:
http://extjs.com/forum/showthread.php?p=70478#post70478

We have modified the ext-nd-overrides-v2 to support the following:
1. Multi-level categories or response hierarchy
2. Subtotal in categories and column totals
3. FTSearch in view

So views look good enough in Ext.ND now !:D

Please find the code in the attachment.

Hi,

thank you for the new extended.js , but seems not to work properly :

all the columns with numbers, (categorized and not) hace a "NaN" and not the number. Opeing the form the fields are ok, with number.

???

s_redko
10-10-2007, 09:37 AM
It was tested in IE6.0 and IE7.0 only.
Probably you use another browser.:-?

Please let me know if so.

zeus
10-10-2007, 09:52 AM
It was tested in IE6.0 and IE7.0 only.
Probably you use another browser.:-?

Please let me know if so.

yes, you are right. With ie7 it's ok. With firefox no.

In the view in some columns I have some lotus icons, and with IE7 I can't see them. With firefox I can.

The search bar ft in the view don'twork.

But in any case great job, thank you ;)

Dominoble
10-10-2007, 02:31 PM
It's possible that my database don't use $$ViewTamplateDefault?
Sorry for my silly question but i have deleted the form Ext.nd.$$ViewTamplateDefault and nothing is changed...

I have found that the categories don't show if you access the view through a page. If you skip the page and use "http://server/db.nsf/view?OpenView" the categories show but then you have all kinds of other problems.

GavinL
10-10-2007, 03:43 PM
I have found that the categories don't show if you access the view through a page. If you skip the page and use "http://server/db.nsf/view?OpenView" the categories show but then you have all kinds of other problems.

Can you describe some of the problems you're experiencing? Is this with the original version I posted, or with the revision 3 that s_redko posted? I've just tried the new revision and ran into the broken image problem myself. I like the way that views with total columns now display correctly, but it seems in the process views with 'extend last column' set broke.

I'll try and merge the best pieces from the two, and see if that fixes some of the issues. I'll also look at applying those fixes to the Gecko fork in the code too.

Dominoble
10-10-2007, 04:24 PM
I finally figured out the problem I was having with the page. I had Ext.nd.ux.DominoUI defined in the $$ViewTemplateDefault form but Ext.nd.DominoUI in the page. I just installed s_redko's file and saw the extendlast column problem. Unfortunately if your column totals are in the first column the twisties won't display. Or to the left of any twistie for that matter. And I don't get sub-totals. Don't know if that's supported or not.

zeus
10-11-2007, 07:36 AM
I have a little problem too..

Also in ie7 , the date numbers are with decimal ex. 2007,00 (I have a category in the first column that is a lotus formula @year(date_field)

???

Zakaroonikov
10-15-2007, 01:26 AM
I have made some modifications to the code to show a load mask when data is being loaded on a category expansion:

Add to the end of the 'renderChildNodeData' function:

renderChildNodeData : function(o, success, resp) {
...
var gridEl = this.grid.getGridEl();
gridEl.unmask();
},


And add the following code:

var gridEl = this.grid.getGridEl();
gridEl.mask('Loading...','x-mask-loading');


before the following code in 'retreiveChildNodes':

childNodeData.request({
url: this.dbPath + this.viewName + "?ReadViewEntries&Start=" + position + ".1&Count=" + children + "&Collapse=" + position + sRestrictUrl + "&nocache=" + encodeURIComponent(new Date()),
method: "GET",
callback: this.renderChildNodeData,
scope: this
});


You should now get the '@ Loading...' message appearing while the data is being retrieved.

Renaud
10-22-2007, 10:49 AM
Hello everyone & first sorry for my poor english skill

I try to make work alone this function : "Ext.nd.ux.data.DominoViewXmlReader" but i've got errors.
So my question is :
Is anybody have a standalone version of this domino's view parser ?

i just need a "readviewentries" parser to work with an application which currently use ExtJS but not Ext.nd.

Any help will be appreciated, thanks in advance :)

RWaters
10-22-2007, 11:43 AM
i just need a "readviewentries" parser to work with an application which currently use ExtJS but not Ext.nd.


I would take a look at the DominoViewXmlReader provided with the default Ext.nd install. There really isn't much in there that is dependent on other Ext.nd components. (Except perhaps the renderer for the grid)

bhaidaya
10-29-2007, 04:42 PM
In the view in some columns I have some lotus icons, and with IE7 I can't see them. With firefox I can.

Just FYI this breaks view icons


case "number":
if (dataItem.lastChild.lastChild.nodeValue) {
return parseFloat(dataItem.text).toFixed(2);
}

captainm1uk
11-19-2007, 09:15 AM
Hi - I have v3 overrides and works well apart from the search functionality. Below is the js file but whenever I search the view it doesn't return any results - just blank
Can anyone help ?

/*
* Ext.nd.ed
* Copyright(c) 2007, Gavin Luscombe.
*
* The JavaScript code is licensed under the
* Lesser GNU (LGPL) open source license version 2.1.
*
* http://www.gnu.org/licenses/lgpl.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
// Set up namespace
Ext.namespace('Ext.nd.ux.grid');
Ext.namespace('Ext.nd.ux.data');
Ext.namespace('Ext.nd.ux.util');
/* ==== Ext.nd.UIOutline ==== */
Ext.nd.ux.UIOutline = function(config){
Ext.nd.ux.UIOutline.superclass.constructor.call(this, config);
};
Ext.extend(Ext.nd.ux.UIOutline, Ext.nd.UIOutline, {
init: function() {
var cb = {
success : this.init2.createDelegate(this),
failure : this.init2.createDelegate(this),
scope: this
};
Ext.lib.Ajax.request('GET', this.outlineUrl + '?ReadEntries&nocache=' + encodeURIComponent(new Date()), cb);
},

openEntry: function(node, e) {

var attributes, extndType, extndHref, extndPosition, entryId, title;
attributes = node.attributes;
extndHref = attributes.extndHref;
extndType = attributes.extndType;
extndPosition = attributes.extndPosition;
entryId = "id-" + extndPosition;
title = node.text;

if (extndType == "2" || extndType == "20") {
if (this.uiView.grid) {
this.viewPanel.setContent("");
try {
this.uiView.grid.destroy();
} catch(e) {}
}
var viewUrl = (extndHref.indexOf('?') > 0) ? extndHref.split('?')[0] : extndHref.split('!')[0];

this.uiView = new Ext.nd.ux.UIView({
layout : this.layout,
viewUrl : viewUrl,
viewParams : "",
container : this.viewPanel,
statusPanel : this.statusPanel
});

this.viewPanel.setTitle(title);
this.layout.showPanel(this.viewPanel);
} else if (extndHref != "") {
var entry = this.layout.getRegion('center').getPanel(entryId);
if(!entry){
var iframe = Ext.DomHelper.append(document.body, {
tag: 'iframe',
frameBorder: 0,
src: extndHref,
id : entryId
});
var panel = new Ext.ContentPanel(iframe, {
title: Ext.util.Format.ellipsis(title,16),
fitToFrame:true,
closable:true
});
this.layout.add('center', panel);
} else { // we've already opened this entry
this.layout.showPanel(entry);
}
}
}
});
/* ==== Ext.nd.ux.data.DominoViewStore ==== */
Ext.nd.ux.data.DominoViewStore = function(config){
Ext.nd.ux.data.DominoViewStore.superclass.constructor.call(this, config);
};
Ext.extend(Ext.nd.ux.data.DominoViewStore, Ext.nd.data.DominoViewStore, {

});
/* ==== Ext.nd.ux.data.DominoViewXmlReader ==== */
Ext.nd.ux.data.DominoViewXmlReader = function(meta, recordType){
Ext.nd.ux.data.DominoViewXmlReader.superclass.constructor.call(this, meta, recordType);
};
Ext.extend(Ext.nd.ux.data.DominoViewXmlReader, Ext.nd.data.DominoViewXmlReader, {
readRecords : function(doc) {
this.xmlData = doc;
var root = doc.documentElement || doc;
var q = Ext.DomQuery;
var recordType = this.recordType, fields = recordType.prototype.fields;
var sid = this.meta.id;
var totalRecords = 0, success = true;
if(this.meta.totalRecords){
totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
}

if(this.meta.success){
var sv = q.selectValue(this.meta.success, root, true);
success = sv !== false && sv !== 'false';
}
var records = [];
var ns = q.select(this.meta.record, root);
for(var i = 0, len = ns.length; i < len; i++) {
var n = ns[i];
var values = {};
var id = sid ? q.selectValue(sid, n) : undefined;
for(var j = 0, jlen = fields.length; j < jlen; j++){
var f = fields.items[j];
var v = this.parseEntryData(f.mapping || f.name, n, f.defaultValue);
v = f.convert(v);
values[f.name] = v;
}
var record = new recordType(values, id);
record.node = n;
records[records.length] = record;
}
return {
success : success,
records : records,
totalRecords : totalRecords || records.length
};
},

parseEntryData : function(path, root, defaultValue) {
var valueCache = {};
var trimRe = /^\s+|\s+$/g;

path = path.replace(trimRe, "");
if(!valueCache[path]){
valueCache[path] = Ext.DomQuery.compile(path, "select");
}
var n = valueCache[path](root);
n = n[0] ? n[0] : n;
return this.getItemText(n && n.lastChild ? n : null);
},
getItemText : function(dataItem, nListOffset){

if (!dataItem) { return null; }

var oRetVal = null;
var nItems = null;
var i;
var sDate = "";

switch (dataItem.lastChild.nodeName) {

case "date":
if (dataItem.lastChild.lastChild.nodeValue) {
sDate = dataItem.lastChild.lastChild.nodeValue;
if (sDate.length == 8) {
sDate += "T000000,00+00";
}
return Ext.nd.ux.util.Format.date(sDate, 'd-M-Y');
}
break;

case "number":
if (dataItem.lastChild.lastChild.nodeValue) {
return parseFloat(dataItem.text).toFixed(2);
}
break;

case "time":
if (dataItem.lastChild.lastChild.nodeValue) {
return Ext.nd.ux.util.Format.date(dataItem.lastChild.lastChild.nodeValue, 'g:i a');
}
break;

case "datetime":
if (dataItem.lastChild.lastChild.nodeValue) {
sDate = dataItem.lastChild.lastChild.nodeValue;
if (sDate.length == 8) {
sDate += "T000000,00+00";
return Ext.nd.ux.util.Format.date(sDate, 'd-M-Y');
} else {
return Ext.nd.ux.util.Format.date(sDate, 'd-M-Y g:i a');
}
}
break;

case "textlist":
var textItems = dataItem.lastChild.getElementsByTagName("text");
if (!textItems) { return ""; }
nItems = textItems.length;
if( nListOffset ) {
if( nListOffset > nItems-1 ) { return ""; }
return textItems[nListOffset].nodeValue;
}
var aTextList = new Array();
for( i=0; i< nItems; i++ ) {
aTextList[i] = textItems[i].firstChild.nodeValue.replace(new RegExp("\u000A","g"), "");
}
oRetVal = aTextList.join("\u000A");
break;

case "datetimelist":
var dateTimeItems = dataItem.lastChild.getElementsByTagName("datetime");
if (!dateTimeItems) { return ""; }
nItems = dateTimeItems.length;
if( nListOffset ) {
if( nListOffset > nItems-1 ) { return ""; }
return dateTimeItems[nListOffset].nodeValue;
}
var aDateTimeList = new Array();
for( i=0; i< nItems; i++ ) {
aDateTimeList[i] = dateTimeItems[i].firstChild.nodeValue.replace(new RegExp("\u000A","g"), "");
}
oRetVal = aDateTimeList.join("\u000A");
break;
}

if (oRetVal) {
return oRetVal;
} else {
return (dataItem.lastChild.firstChild ? dataItem.lastChild.firstChild.nodeValue.replace(new RegExp("\u000A","g"), "") : "");
}

}
});
/* ==== Ext.nd.ux.grid.DominoGrid ==== */
Ext.nd.ux.grid.DominoGrid = function(container, config){
Ext.nd.ux.grid.DominoGrid.superclass.constructor.call(this, container, config);
};
Ext.extend(Ext.nd.ux.grid.DominoGrid, Ext.nd.grid.DominoGrid, {
getView : function(){
if(!this.view){
this.view = new Ext.nd.ux.grid.DominoGridView();
}
return this.view;
}

});
/* ==== Ext.nd.ux.grid.DominoGridView ==== */
Ext.nd.ux.grid.DominoGridView = function(config){
Ext.nd.ux.grid.DominoGridView.superclass.constructor.call(this, config);
};
Ext.extend(Ext.nd.ux.grid.DominoGridView, Ext.nd.grid.DominoGridView, {
init: function(grid){

Ext.grid.GridView.superclass.init.call(this, grid);
this.bind(grid.dataSource, grid.colModel);
grid.on("headerclick", this.handleHeaderClick, this);
if(grid.trackMouseOver){
grid.on("mouseover", this.onRowOver, this);
grid.on("mouseout", this.onRowOut, this);
}
grid.cancelTextSelection = function(){};
this.gridId = grid.id;
var tpls = this.templates || {};
if(!tpls.master){
tpls.master = new Ext.Template(
'<div class="x-grid" hidefocus="true">',
'<div class="x-grid-topbar"></div>',
'<div class="x-grid-scroller"><div></div></div>',
'<div class="x-grid-locked">',
'<div class="x-grid-header">{lockedHeader}</div>',
'<div class="x-grid-body">{lockedBody}</div>',
"</div>",
'<div class="x-grid-viewport">',
'<div class="x-grid-header">{header}</div>',
'<div class="x-grid-body">{body}</div>',
"</div>",
'<div class="x-grid-bottombar"></div>',
'<a href="#" class="x-grid-focus" tabIndex="-1"></a>',
'<div class="x-grid-resize-proxy"> </div>',
"</div>"
);
tpls.master.disableformats = true;
}
if(!tpls.header){
tpls.header = new Ext.Template(
'<table border="0" cellspacing="0" cellpadding="0">',
'<tbody><tr class="x-grid-hd-row">{cells}</tr></tbody>',
"</table>{splits}"
);
tpls.header.disableformats = true;
}
tpls.header.compile();
if(!tpls.hcell){
tpls.hcell = new Ext.Template(
'<td class="x-grid-hd x-grid-td-{id} {cellId}"><div title="{title}" class="x-grid-hd-inner x-grid-hd-{id}">',
'<div class="x-grid-hd-text" unselectable="on">{value}<img class="x-grid-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" /></div>',
"</div></td>"
);
tpls.hcell.disableFormats = true;
}
tpls.hcell.compile();
if(!tpls.hsplit){
tpls.hsplit = new Ext.Template('<div class="x-grid-split {splitId} x-grid-split-{id}" style="{style}" unselectable="on"> </div>');
tpls.hsplit.disableFormats = true;
}
tpls.hsplit.compile();
if(!tpls.body){
tpls.body = new Ext.Template(
'<table border="0" cellspacing="0" cellpadding="0">',
"<tbody>{rows}</tbody>",
"</table>"
);
tpls.body.disableFormats = true;
}
tpls.body.compile();
if(!tpls.row){
tpls.row = new Ext.Template('<tr class="x-grid-row {alt}">{cells}</tr>');
tpls.row.disableFormats = true;
}
tpls.row.compile();
if(!tpls.cell){
tpls.cell = new Ext.Template(
'<td class="x-grid-col x-grid-td-{id} {cellId} {css}" tabIndex="0">',
'<div class="x-grid-col-{id} x-grid-cell-inner" style="{style}"><div class="ext-nd-ed-grid-cell" unselectable="on" {attr}>{value}</div></div>',
"</td>"
);
tpls.cell.disableFormats = true;
}
tpls.cell.compile();

if(!tpls.categoryCell){
tpls.categoryCell = new Ext.Template(
'<td class="x-grid-col x-grid-td-{id} {cellId} {css}" tabIndex="0">',
'<div class="x-grid-col-{id} x-grid-cell-inner" style="{style}"><div class="ext-nd-ed-grid-categorycell" unselectable="on" {attr}>{value}</div></div>',
"</td>"
);
tpls.categoryCell.disableFormats = true;
}
tpls.categoryCell.compile();

if(!tpls.responseCell){
tpls.responseCell = new Ext.Template(
'<td colspan="{cols}" class="x-grid-col x-grid-td-{id} {cellId} {css}" style="width: {colWidth}" tabIndex="0">',
'<div class="ext-nd-ed-grid-col-response x-grid-cell-inner" style="{style}"><div class="ext-nd-ed-grid-cell" unselectable="on" {attr}>{value}</div></div>',
"</td>"
);
tpls.responseCell.disableFormats = true;
}
tpls.responseCell.compile();
this.templates = tpls;
},

doRender : Ext.isGecko ?
function(cs, rs, ds, startRow, colCount, stripe){
var ts = this.templates, ct = ts.cell, rt = ts.row;
// buffers
var buf = "", lbuf = "", cb, lcb, c, p = {}, rp = {}, r;
var child, category, q, indent, config, categoryTotal;

for(var j = 0, len = rs.length; j < len; j++){
r = rs[j], cb = "", lcb = "", rowIndex = (j+startRow);

child = r.node.getAttribute("response");
category = !r.node.getAttribute("unid");
categoryTotal = r.node.getAttribute("categorytotal");

for(var i = 0; i < colCount; i++){
c = cs[i];
config = this.cm.config[i];

p.style = "font-weight: " + config.fontWeight + ";";
p.style += " color: " + config.colour + ";";

if ((config.response && child) || category) {

ct = ts.responseCell;
if (!categoryTotal) {
p.cols = colCount - i;
}
q = Ext.DomQuery;

if (category && !categoryTotal) {
indent = this.getNodeDepth(r.node.getAttribute("position"));
p.style += " margin-left: " + parseInt(indent * 16) + "px;";

// Remap column to one containing the category data
// Due to pseudo-categories (myCat\pseudoCat etc.), this may not be the current column
if (!r.data[c.name] || "" == r.data[c.name]) {
var found = false;

for(var entry in r.data) {
if (r.data[entry] && "" != r.data[entry]) {
for(var k=0; k < cs.length; k++) {
if (cs[k].name == entry) {
i = k;
c = cs[k];
found = true;
}
}
}
}

if (!found) {
r.data[c.name] = "(Not Categorized)";
}
}

}
if (categoryTotal) {
ct = (!r.data[c.name] || r.data[c.name] == "") ? ts.cell : ts.categoryCell;
}

if (!category) {
indent = q.selectNode("entrydata[name='" + c.name + "']", r.node).getAttribute("indent");
p.style = "margin-left: " + parseInt(this.cm.getColumnWidth(i) + parseInt(indent * 16)) + "px";
}
p.cellId = "x-grid-cell-" + rowIndex + "-" + i;
p.id = c.id;
p.css = p.attr = "";
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);

if (!categoryTotal) {
i = colCount - 1;

//Set the width of the column cell, so that table fills its container - important if only categories are loaded
if (j == 0) {
var totalWidth = 0;
for(var z = 0, colLen = this.cm.getColumnCount(); z < colLen; z++){
var w = this.cm.getColumnWidth(z);
totalWidth += w;
}

p.colWidth = parseInt(totalWidth) + "px";
}
}
} else {
p.cellId = "x-grid-cell-" + rowIndex + "-" + i;
p.id = c.id;
p.css = p.attr = "";
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
}

if(p.value == undefined || p.value === "") p.value = " ";
if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
p.css += p.css ? ' x-grid-dirty-cell' : 'x-grid-dirty-cell';
}
var markup = ct.apply(p);
if(!c.locked){
cb+= markup;
}else{
lcb+= markup;
}
}
var alt = [];
if(stripe && ((rowIndex+1) % 2 == 0)){
alt[0] = "x-grid-row-alt";
}
if(r.dirty){
alt[1] = " x-grid-dirty-row";
}
rp.cells = lcb;
if(this.getRowClass){
alt[2] = this.getRowClass(r, rowIndex);
}
rp.alt = alt.join(" ");
lbuf+= rt.apply(rp);
rp.cells = cb;
buf+= rt.apply(rp);
}
return [lbuf, buf];
} :
function(cs, rs, ds, startRow, colCount, stripe){
var ts = this.templates, ct = ts.cell, rt = ts.row;
// buffers
var buf = [], lbuf = [], cb, lcb, c, p = {}, rp = {}, r;
var child, category, q, indent, config, categoryTotal, sortCat;

for(var j = 0, len = rs.length; j < len; j++){

r = rs[j], cb = [], lcb = [], rowIndex = (j+startRow);
child = r.node.getAttribute("response");
sortCat = r.node.getAttribute("sortcategorize");
category = !r.node.getAttribute("unid");
categoryTotal = r.node.getAttribute("categorytotal");
var ctgDone = false;

for(var i = 0; i < colCount; i++){

c = cs[i];

config = this.cm.config[i];
p.style = "font-weight: " + config.fontWeight + ";";
p.style += " color: " + config.colour + ";";

if (!ctgDone && ((config.response && child) || category)) {
p.cols = 0;
ct = ts.responseCell;
if (!categoryTotal) {
for(var ii = 0; ii < colCount; ii++)
{
if(!r.data[cs[ii].name])
p.cols += 1;
}
}

q = Ext.DomQuery;

if (category && !categoryTotal) {
indent = this.getNodeDepth(r.node.getAttribute("position"));
p.style += " margin-left: " + parseInt(indent * 16) + "px;";

var found = true;

// Remap column to one containing the category data
// Due to pseudo-categories (myCat\pseudoCat etc.), this may not be the current column
if (!r.data[c.name] || r.data[c.name] == "") {
found = false;

for(var entry in r.data) {
if (null != r.data[entry] /*&& "" != r.data[entry]*/) {
for(var k=0; k < cs.length; k++) {
if (cs[k].name == entry) {
i = k;
c = cs[k];
found = true;
ctgDone = true;
break;
}
}
}

if(found)
break;
}
}
else
ctgDone = true;

if ("" == r.data[c.name]) {
r.data[c.name] = "(Not Categorized)";
ctgDone = true;
}
}

if (categoryTotal) {
ct = (!r.data[c.name] || r.data[c.name] == "") ? ts.cell : ts.categoryCell;
}

if (!category && !categoryTotal) {
indent = q.selectNode("entrydata[name='" + c.name + "']", r.node).getAttribute("indent");
p.style = "margin-left: " + parseInt(this.cm.getColumnWidth(i) + parseInt(indent * 16)) + "px";
}
p.cellId = "x-grid-cell-" + rowIndex + "-" + i;
p.id = c.id;
p.css = p.attr = "";
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
if (!categoryTotal) {
//i = colCount - 1;

//Set the width of the column cell, so that table fills its container - important if only categories are loaded
if (!ctgDone) {
var totalWidth = 0;
for(var z = 0, colLen = this.cm.getColumnCount(); z < p.cols; z++){
var w = this.cm.getColumnWidth(z);
totalWidth += w;
}

p.colWidth = parseInt(totalWidth) + "px";
}
}

} else {
p.cols = 0;
p.cellId = "x-grid-cell-" + rowIndex + "-" + i;
p.id = c.id;
p.style += "text-align:" + config.align;
p.css = p.attr = "";

p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
}
if(0 < p.cols)
i = p.cols - 1;

if(p.value == undefined || p.value === "") p.value = " ";
if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
p.css += p.css ? ' x-grid-dirty-cell' : 'x-grid-dirty-cell';
}
var markup = ct.apply(p);
if(!c.locked){
cb[cb.length] = markup;
}else{
lcb[lcb.length] = markup;
}
}
var alt = [];
if(stripe && ((rowIndex+1) % 2 == 0)){
alt[0] = "x-grid-row-alt";
}
if(r.dirty){
alt[1] = " x-grid-dirty-row";
}
rp.cells = lcb;
if(this.getRowClass){
alt[2] = this.getRowClass(r, rowIndex);
}
rp.alt = alt.join(" ");
rp.cells = lcb.join("");
lbuf[lbuf.length] = rt.apply(rp);
rp.cells = cb.join("");
buf[buf.length] = rt.apply(rp);
}
return [lbuf.join(""), buf.join("")];
},

updateHeaderSortState : function(){
var state = this.ds.getSortState();
if(!state){
return;
}

this.sortState = state;
var sortColumn = this.cm.findColumnIndex(state.field);
if(sortColumn != -1){
var sortDir = state.direction;
var sc = this.sortClasses;
var hds = this.el.select(this.headerSelector).removeClass(sc);
if (sortDir != "") { hds.item(sortColumn).addClass(sc[sortDir == "DESC" ? 1 : 0]); }
}
},

updateSplitters : function(){
var cm = this.cm, s = this.getSplitters();
if(s){ // splitters not created yet
var pos = 0, locked = true;
for(var i = 0, len = cm.getColumnCount(); i < len; i++){
if(cm.isHidden(i)) continue;
var w = cm.getColumnWidth(i);
if(!cm.isLocked(i) && locked){
pos = 0;
locked = false;
}
pos += w;
if (typeof s[i] != "undefined") {
s[i].style.left = (pos-this.splitOffset) + "px";
}
}
}
},

getNodeDepth : function(sPos) {

var iDepth = 0;

if (sPos) {
var aDepth = sPos.split(".");
iDepth = aDepth.length - 1;
} else {
iDepth = 0;
}
return iDepth;
}
});
/* ==== Ext.nd.ux.grid.DominoUI ==== */
Ext.nd.ux.DominoUI = function(config){
Ext.nd.ux.DominoUI.superclass.constructor.call(this, config);
};
Ext.extend(Ext.nd.ux.DominoUI, Ext.nd.DominoUI, {

init : function() {

this.createDominoUI();
if (this.uiView.viewName != '' || this.uiView.viewUrl != '') {
this.uiView = new Ext.nd.ux.UIView(Ext.apply({
container : this.viewPanel,
layout : this.layout,
statusPanel : this.statusPanel
}, this.uiView));

this.viewTitle = (this.viewTitle) ? this.viewTitle : (this.uiView.viewName) ? this.uiView.viewName : this.uiView.viewUrl;
this.viewPanel.setTitle(this.viewTitle);
}

if (this.uiOutline.outlineName != '' || this.uiOutline.outlineUrl != '') {
this.uiOutline = new Ext.nd.ux.UIOutline(Ext.apply({
layout : this.layout,
container : this.outlinePanel,
viewPanel : this.viewPanel,
uiView : this.uiView
},this.uiOutline));
}

}
});
/* ==== Ext.nd.ux.grid.UIView ==== */
Ext.nd.ux.UIView = function(config){
Ext.nd.ux.UIView.superclass.constructor.call(this, config);
};
Ext.extend(Ext.nd.ux.UIView, Ext.nd.UIView, {
init: function() {

// need an actionbar?
if (this.showActionbar || this.toolbar) {
if (!this.toolbar) {
var tb = Ext.DomHelper.append(document.body,{tag: 'div'});
this.toolbar = new Ext.nd.Actionbar({
container:tb,
noteType:'view',
noteName:this.viewName,
useDxl: true
});
// TODO: this hack is just to make sure the toolbar has a height before the grid loads
this.toolbar.addSeparator();
if (this.showSingleCategory && this.showCategoryComboBox) {
var store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
method:'GET',
url: this.viewUrl + '?ReadViewEntries&CollapseView&count=' + this.categoryComboBoxCount + '&randomizer='+new Date().getTime()
}),
reader: new Ext.data.XmlReader({
record: 'viewentry',
totalRecords: '@toplevelentries',
id: '@position'
},[{name:'text'}]
)
});
store.load();

var combo = new Ext.form.ComboBox({
store: store,
displayField:'text',
typeAhead: true,
mode: 'local',
triggerAction: 'all',
emptyText: this.emptyText,
value: this.showSingleCategory,
selectOnFocus:true,
grow: true,
resizable: true
});
this.toolbar.addField(combo);
this.toolbar.addSeparator();
combo.on('beforeselect',function() {
if(this.isSearching) {
Ext.MessageBox.alert("Error","You must clear the search results before changing categories");
return false; // Cancel the select
}
},this);
combo.on('select',this.handleCategoryChange,this);
}
if (this.showSearch && !this.searchInPagingToolbar) {
this.createSearch(this.toolbar);
}
}
}
// now get the rest of the view design
this.getViewDesign();
},

createSearch: function(toolbar) {
this.searchField = new Ext.form.TextField({
blankText: "Search view...",
name: "extnd-vw-search",
width: 100
});
toolbar.addSeparator();
toolbar.addField(this.searchField);
toolbar.addButton({text: "Search", scope: this, handler: this.handleViewSearch});
toolbar.addSeparator();
},

getViewDesign: function() {
var cb = {
success : this.getViewDesignCB,
failure : this.getViewDesignFailure,
scope: this
};
Ext.lib.Ajax.request('GET', this.viewUrl + '?ReadDesign&nocache=' + encodeURIComponent(new Date()), cb);
},

getViewDesignCB: function(o) {

var q = Ext.DomQuery;

var arColumns = q.select('column',o.responseXML);

this.designAttrs = q.selectNode("viewdesign", o.responseXML);
this.lastColumn = arColumns.length - 1;

var arColumnConfig = [];
var arRecordConfig = [];

for (var i=0; i<arColumns.length; i++) {
if (i==0 && this.showSingleCategory) {
continue;
}

var col = arColumns[i];
var columnnumber = q.selectNumber('@columnnumber',col);
columnnumber = (this.showSingleCategory) ? columnnumber - 1 : columnnumber;

var tmpName = q.selectValue('@name',col,'');
var name = (tmpName == undefined) ? 'columnnumber_' + columnnumber : tmpName;

var tmpTitle = q.selectValue('@title',col,"&nbsp;");
var title = (tmpTitle == undefined) ? "&nbsp;" : tmpTitle;
var width = q.selectNumber('@width',col) * 1.41;

var response = q.selectValue('@response',col,false);
var responseValue = (response) ? true : false;

var twistie = q.selectValue('@twistie',col,false);
var twistieValue = (twistie) ? true : false;

var listseparatorValue = q.selectValue('@listseparator',col,'none');

var resize = q.selectValue('@resize',col,false);
var resizeValue = (resize) ? true : false;

var sortcategorize = q.selectValue('@sortcategorize',col,false)
var sortcategorizeValue = (sortcategorize) ? true : false;

var resortascending = q.selectValue('@resortascending',col,false);
var resortascendingValue = (resortascending) ? true : false;

var resortdescending = q.selectValue('@resortdescending',col,false);
var resortdescendingValue = (resortdescending) ? true : false;

var resorttoview = q.selectValue('@resorttoview',col,false);
var resorttoviewValue = (resorttoview) ? true : false;
var resortviewunidValue = (resorttoview) ? q.selectValue('@resortviewunid',col,"") : "";

var isSortable = (resortascendingValue || resortdescendingValue || resorttoviewValue) ? true : false;

var icon = q.selectValue('@icon',col,false);
var iconValue = (icon) ? true : false;

var align = q.selectValue('@align',col,false);
var alignValue = (align) ? ((align == "2") ? 'center' : 'right') : 'left';
var headerAlign = q.selectValue('@headeralign',col,false);
var headerAlignValue = (headerAlign) ? ((headerAlign == "2") ? 'center' : 'right') : 'left';
var tmpDateTimeFormat = q.select('datetimeformat',col)[0];
var datetimeformat = {};
datetimeformat.show = q.selectValue('@show',tmpDateTimeFormat);
datetimeformat.date = q.selectValue('@date',tmpDateTimeFormat);
datetimeformat.time = q.selectValue('@time',tmpDateTimeFormat);
datetimeformat.zone = q.selectValue('@zone',tmpDateTimeFormat);

var columnConfig = {
header: title,
align: alignValue,
dataIndex: name,
width: width,
renderer: this.dominoRenderer.createDelegate(this),
sortable: isSortable,
resortascending: resortascendingValue,
resortdescending: resortdescendingValue,
resortviewunid: resortviewunidValue,
sortcategorize: sortcategorizeValue,
resize: resizeValue,
listseparator: listseparatorValue,
response: responseValue,
twistie: twistieValue,
icon: iconValue,
datetimeformat: datetimeformat
};

var recordConfig = {
name: name,
mapping: 'entrydata[@name="' + name + '"]'
};

arColumnConfig.push(columnConfig);
arRecordConfig.push(recordConfig);

}

this.dominoView = {
meta : {
root : 'viewentries',
record : 'viewentry',
totalRecords : '@toplevelentries',
id : '@position',
columnConfig : arColumnConfig
},
recordConfig : arRecordConfig
};
this.createGrid();
},
createGrid: function() {
var sViewParams = (this.viewParams == undefined) ? "" : this.viewParams;

this.reader = new Ext.nd.ux.data.DominoViewXmlReader( this.dominoView.meta, this.dominoView.recordConfig);
this.cm = new Ext.grid.DefaultColumnModel(this.dominoView.meta.columnConfig);

this.ds = new Ext.nd.ux.data.DominoViewStore({
proxy: new Ext.data.HttpProxy({
url: this.viewUrl + '?ReadViewEntries&CollapseView&nocache=' + encodeURIComponent(new Date()),
method: "GET"
}),
baseParams: this.baseParams,
reader: this.reader,
remoteSort: false
});
if (this.grid) {
try {
this.grid.destroy();
} catch (e) {}
}
var dh = Ext.DomHelper;
this.grid = new Ext.nd.ux.grid.DominoGrid(dh.append(document.body,{tag: 'div'}), {
ds: this.ds,
cm: this.cm,
loadMask: true,
selModel: new Ext.grid.RowSelectionModel({singleSelect : this.singleSelect}),
enableDragDrop: true,
ddGroup: 'TreeDD',
autoExpandColumn: (this.designAttrs.getAttribute("extendlastcolumn")) ? false : this.lastColumn,
enableColLock: false
});
var container = (this.container.getEl) ? this.container.getEl() : this.container;
var layout = Ext.BorderLayout.create({
center: {
panels: [new Ext.GridPanel(this.grid, {toolbar: this.toolbar, fitToFrame : true})]
}
}, container);

this.grid.on('rowclick', this.gridHandleRowClick, this);
this.grid.addListener('rowdblclick',this.gridHandleRowDblClick, this, true);
this.grid.addListener('keydown',this.gridHandleKeyDown, this, true);
this.grid.addListener('rowcontextmenu',this.gridHandleRowContextMenu, this, true);
this.grid.addListener('headerclick',this.gridHandleHeaderClick, this, true);

/*this.loadMask = new Ext.LoadMask(container,
Ext.apply({store:this.ds}, this.loadMask));*/

this.grid.render();

var gridFoot = this.grid.getView().getFooterPanel(true);
this.paging = new Ext.nd.DominoPagingToolbar(gridFoot, this.ds, {pageSize: this.count});

if (this.showSearch && this.searchInPagingToolbar)
{
this.createSearch(this.paging);
}

this.ds.load({params:{count : this.count}});
},

handleViewSearch: function() {
var qry = this.searchField.getValue();
var tb = (this.searchInPagingToolbar)?this.paging:this.toolbar;

if (!this.isSearching) {
this.oldDataSource = this.grid.getDataSource(); // Save the current DS so we can restore it when search is cleared

// define the Domino viewEntry record
//var viewEntry = Ext.data.Record.create(this.dominoView.recordConfig);
// create reader that reads viewEntry records
//var viewEntryReader = new Ext.nd.data.DominoViewXmlReader(this.dominoView.meta, viewEntry);

this.ds = new Ext.nd.ux.data.DominoViewStore({
proxy: new Ext.data.HttpProxy({
url: Ext.nd.extndUrl+'($Ext.nd.SearchView)?OpenAgent',
method: "GET"
}),
baseParams: {db: this.dbPath, vw: this.viewName },
reader: this.reader,
remoteSort: false
});

this.grid.reconfigure(this.ds, this.grid.getColumnModel());
this.paging.unbind(this.oldDataSource);
this.paging.bind(this.ds);
this.isSearching = true; // Set this so we don't create the search datastore multiple times
this.clearSearchButton = tb.addButton({text: "Clear Results", scope: this, handler: this.handleClearSearch});
}
this.grid.getDataSource().load({params:{query: qry, count: this.searchCount, start: 1}});
},

dominoRenderer: function(val, cell, row, rowIdx, colIdx, ds) {

if (typeof val == "undefined" || val == null) { return ""; }

var config = this.dominoView.meta.columnConfig[colIdx];
var output = "";
var isResponse = false;

//Check whether we have a category or a document with responses
if (config.twistie && val != "" && !config.icon) {
if (row.node) {
output += (row.node.getAttribute("children")) ? "<img id='" + Ext.id() + "' class='ext-nd-ed-twistie' src='/icons/expand.gif' />" : "<img class='ext-nd-ed-blank' src='/icons/ecblank.gif' />";
}
}

if (config.icon) {

if (val == "" || val == 0 || val == null) {
output += "<img id='" + Ext.id() + "' class='ext-nd-ed-icon' src='/icons/ecblank.gif' />";
} else {
if (!isNaN(val)) {
var sIcon = "00" + val;
sIcon = sIcon.substr(sIcon.length - 3, 3);
var url = "/icons/vwicn" + sIcon + ".gif" ;

output += "<img id='" + Ext.id() + "' class='ext-nd-ed-icon' src='" + url + "' />";
}
}

} else {
output += val;
}

return output;

},

gridHandleRowClick: function(grid, rowIndex, e) {
var el = e.getTarget();
var row = grid.selModel.getSelected();
var node = row.node;

if (node) {

var unid = (node.getAttribute("unid")) ? node.getAttribute("unid") : node.getAttribute("noteid");
var position = node.getAttribute("position");
var children = node.getAttribute("children");

if (el.className == "ext-nd-ed-twistie") {
this.retrieveChildNodes(row, el.id, unid, position, children);
}

}
},
renderChildNodeData : function(o, success, resp) {

var row = this.grid.selModel.getSelected();
var node = row.node;
row.childRowsLoaded = true;

var unid = (node.getAttribute("unid")) ? node.getAttribute("unid") : node.getAttribute("noteid");

var doc = resp.responseXML;
var root = doc.documentElement || doc;

var ds = this.grid.getDataSource();
var index = ds.indexOf(row);
//Read in the child records
var childRecords = this.reader.readRecords(root);

for (var i = 0; i < childRecords.records.length; i++) {
//Handle hidden documents that contain readers fields
if (this.getNodeDepth(childRecords.records[i].id) <= this.getNodeDepth(row.id)) { break; }
ds.insert(++index, childRecords.records[i]);
}
var gridEl = this.grid.getGridEl();
gridEl.unmask();
},

retrieveChildNodes : function(row, elementId, unid, position, children) {
var oTwistie = Ext.getDom(elementId);
var view = this.grid.getView();
var selModel = this.grid.selModel;
var rowIdx = this.ds.indexOf(row);
var parentRowId = row.id;
var currentRowId = null;
var q = Ext.DomQuery;
var tr = null;
if (oTwistie) {
var bIsCollapsed = (oTwistie.src.indexOf("expand") >= 0) ? true : false;
if (bIsCollapsed) {
oTwistie.src = oTwistie.src.replace(/expand/g, "collapse");

if (!row.childRowsLoaded) {
var childNodeData = new Ext.data.Connection();

var sRestrictUrl = (this.showSingleCategory) ? "&RestrictToCategory=" + this.showSingleCategory : ""
var gridEl = this.grid.getGridEl();
gridEl.mask('Loading...','x-mask-loading');
childNodeData.request({
url: this.dbPath + this.viewName + "?ReadViewEntries&Start=" + position + ".1&Count=" + children + "&Collapse=" + position + sRestrictUrl + "&nocache=" + encodeURIComponent(new Date()),
method: "GET",
callback: this.renderChildNodeData,
scope: this
});
} else {
//Display existing child rows
this.grid.selModel.selectNext();
row = selModel.getSelected();
while(row) {
currentRowId = row.id;

//Ensure we only act on child rows
if(this.getNodeDepth(currentRowId) <= this.getNodeDepth(parentRowId)) { break; }

//Make sure we only act on immediate descendants
if(this.getNodeDepth(currentRowId) == parseInt(this.getNodeDepth(parentRowId) + 1)) {
tr = view.getRow(this.ds.indexOf(row));
if (tr) {

tr.style.display = "";
//Now find the twistie, and reset its state to collapsed
oTwistie = q.selectNode("IMG[class='ext-nd-ed-twistie']", tr);
if (oTwistie) {
oTwistie.src = oTwistie.src.replace(/collapse/g, "expand");
}
}
}

selModel.selectNext();
row = selModel.getSelected();
if (row.id == currentRowId) { row = null };
}

selModel.selectRow(rowIdx, false);
}

} else {
oTwistie.src = oTwistie.src.replace(/collapse/g, "expand");

//Hide child rows
this.grid.selModel.selectNext();
row = selModel.getSelected();
while(row) {
currentRowId = row.id;

if(this.getNodeDepth(currentRowId) <= this.getNodeDepth(parentRowId)) { break; }
tr = view.getRow(this.ds.indexOf(row));
if (tr) {
tr.style.display = "none";
}

selModel.selectNext();
row = selModel.getSelected();
if (row.id == currentRowId) { row = null };
}

selModel.selectRow(rowIdx, false);

}
}

},

getNodeDepth : function(sPos) {

var iDepth = 0;

if (sPos) {
var aDepth = sPos.split(".");
iDepth = aDepth.length - 1;
} else {
iDepth = 0;
}
return iDepth;
}

});
Ext.nd.ux.util.Format = function(){
return {

fromIso8601String : function(sDate) {

var regexp = '^([0-9]{4})[-/.]?([0-9]{1,2})[-/.]?' +
'([0-9]{1,2})(T?([0-9]{1,2})([-:.]?' +
'([0-9]{1,2})([-:.]?([0-9]{1,2})' +
'(,([0-9]{1,3}))?)?)?)?((Z)' +
'|([+-])([0-9]{1,2})([-:.]?' +
'([0-9]{1,2})([-:.]?([0-9]{1,2}))?)?)?$';
var r = sDate.match(new RegExp(regexp));

if (r == null) { return null; }

var y = r[1];
var mo = r[2];
var d = r[3];

if (r.length > 5) {
var h = ("" != r[5]) ? h = r[5] : 0;
if (r.length > 7) {
var mi = ("" != r[7]) ? r[7] : 0;
if (r.length > 9) {
var s = ("" != r[9]) ? r[9] : 0;
var ms = (r.length > 11 && "" != r[11] && r[11]) ? r[11] * Math.pow(10, 3 - r[11].length) : 0;
}
}
}
var oDate = new Date(Date.UTC(y, mo - 1, d, h, mi, s, ms));
var o = -1 * oDate.getTimezoneOffset() * 60;
if (r.length > 14 && "" != r[14] && "" != r[15]) {
o = (('+' == r[14]) ? 1 : -1) * r[15] * 60 * 60;
o += (("" != r[17]) && r[17]) ? r[17] * 60 : 0;
o += (("" != r[19]) && r[19]) ? r[19] : 0;
}
oDate.setTime(parseInt(oDate.getTime()) - (o * 1000));

return oDate;
},
date : function(v, format){
if(!v){
return "";
}
if(!(v instanceof Date)){
if (this.fromIso8601String(v)) {
v= this.fromIso8601String(v);
return v.format(format || "m/d/Y");
} else {
return v;
}
}
}
};
}();

J
12-03-2007, 07:49 AM
Hi I am using Beta2 R1 and when I try to search in view (categorized one) I have a web error (this.paging is null or not an object). Any idea?

derricktsai
05-13-2009, 09:56 PM
May i use the database ?
Maybe i can support same answer...

jratcliff
05-14-2009, 12:08 AM
May i use the database ?
Maybe i can support same answer...

You want to be a pre-beta tester for Beta 2 of Ext.nd? Just PM me with your email address and I'll send it to you. Or you can email me at jack.ratcliff at gmail dot com