PDA

View Full Version : How-To : Async treeview



becomcs
7 Jun 2007, 7:59 AM
Hello

I'm trying to add an async treeview dialogbox into a form.

I started to look into Treeloader source and I found two function to be modified:
RequestData : to modifiy dataUrl setting corresponding to domino url options. Perhaps by adding a getUrl (node) function?
ProcessResponse : To create node with readviewentries XML data domino format. I start to look into dominoviewxmlreader, but I'm litte bit confuse on how to use this class.

Any help is wellcome

jratcliff
9 Jun 2007, 6:02 PM
Hello

I'm trying to add an async treeview dialogbox into a form.

I started to look into Treeloader source and I found two function to be modified:
RequestData : to modifiy dataUrl setting corresponding to domino url options. Perhaps by adding a getUrl (node) function?
ProcessResponse : To create node with readviewentries XML data domino format. I start to look into dominoviewxmlreader, but I'm litte bit confuse on how to use this class.

Any help is wellcome

Not sure what you mean by "async treeview dialogbox". Is this like a categorized view?

becomcs
10 Jun 2007, 12:04 PM
No just a tree

jratcliff
10 Jun 2007, 12:09 PM
No just a tree

So you are wanting to put an 'outline' in a dialog? If so, I think the next Alpha version will help with this. The code was tweaked to allow you to pass in what the container is and and the outline will be rendered in your container. It may still be a week before the next alpha version but if you need it sooner, here's the code for Ext.nd.UIOutline



/**
* @class Ext.nd.DominoUI
* Makes an AJAX call to the outline's readentries and translates it into an {@link Ext.Tree}
* @constructor
* Create a new UIOutline component
* @param {Object} config Configuration options
*/
Ext.nd.UIOutline = function(config) {

var sess = Ext.nd.Session; // should we assume that there will always be a session?
var db = sess.CurrentDatabase;

// defaults
this.dbPath = db.WebFilePath;
this.outlineName = '';
this.useOutlineIcons = false;

// Set any config params passed in to override defaults
Ext.apply(this,config);

// outlineUrl is either passed in or built from dbPath and outlineName
this.outlineUrl = (this.outlineUrl) ? this.outlineUrl : this.dbPath + this.outlineName;

// init the outline, which creates it in the container passed in the config object
this.init();
};

Ext.nd.UIOutline.prototype = {
init: function() {
var cb = {
success : this.init2.createDelegate(this),
failure : this.init2.createDelegate(this),
scope: this
};
Ext.lib.Ajax.request('POST', this.outlineUrl + '?ReadEntries', cb);
},

// Private
init2: function(o) {
var response = o.responseXML;
var arEntries = response.getElementsByTagName('outlineentry');

// container can be a string id reference or a dom object, or even an Ext panel
var dh = Ext.DomHelper;
var container = (this.container.getEl) ? this.container.getEl() : this.container;

var Tree = Ext.tree;
var tree = new Tree.TreePanel(container, {
animate : true,
enableDD : true,
ddGroup: 'TreeDD',
containerScroll : true,
dropConfig : {appendOnly : true},
rootVisible : false
});

// add a tree sorter in folder mode
//new Tree.TreeSorter(tree, {folderSort : true}); // leave the sort order alone for domino outlines

// set the root node
// var root = new Tree.AsyncTreeNode({
var root = new Tree.TreeNode({
text : 'domino-folders',
draggable : false, // disable root node dragging
id : 'domino-folders'
});
tree.setRootNode(root);
var curNode = null;
var arNodes = [];
for (var i=0; i<arEntries.length; i++) {
var entry = arEntries.item(i);
var extndType = entry.attributes.getNamedItem('type').value;
var extndTitle = entry.attributes.getNamedItem('title').value;
var tmpextndHref = entry.attributes.getNamedItem('url');
var extndHref = (tmpextndHref) ? tmpextndHref.value : "";

// is expandable?
// if the attribute 'expandable' exists, then it is expandable
// don't be execused by expandable='true' or expandable='false'
// the true and false just tells you their initial state (either already expanded or already collapsed)
var expandable = entry.attributes.getNamedItem('expandable');
var isExpandable = (expandable) ? true : false;

var tmpextndIcon = entry.attributes.getNamedItem('icon');
var extndIcon = (tmpextndIcon) ? tmpextndIcon.value : "";
var curPosition = entry.attributes.getNamedItem('position').value;

var cls;
switch (extndType) {
// section
case "0" :
cls = (isExpandable) ? "folder" : "file";
break;
// view
case "2" :
cls = "file";
break;
// folder
case "20" :
cls = "folder";
break;
default :
cls = "file";
};

var curNode = new Tree.TreeNode({
text : extndTitle,
cls : cls,
allowDrag : true,
allowDrop : (extndType == "20" || extndType == "0") ? true : false,
isTarget : true,
leaf : false,
extndHref : extndHref,
extndType : extndType,
extndExpandable: isExpandable,
extndPosition : curPosition,
icon : (this.useOutlineIcons) ? extndIcon : null
});

curNode.on('click', this.openEntry.createDelegate(this), this, true);
//curNode.leaf = false;

arNodes[curPosition] = curNode;

if (curPosition.indexOf('.') > 0) {
var parentPosition = curPosition.substring(0,curPosition.lastIndexOf('.'));
arNodes[parentPosition].appendChild(curNode);
} else {
root.appendChild(curNode);
}
}

// handle the drop of the doc on the folder
tree.on('beforenodedrop', this.addToFolder);

// render the tree
tree.render();

//root.expand(false, /*no anim*/ false);
root.expand();
},

// Private
addToFolder: function(e) {
console.log('nodedragover - start');
console.log('addToFolder - start');

var type = e.target.attributes.extndType;
console.log('type='+type);

if (type == "20" || type == "0") {
console.log('expanding');
e.target.expand();
} else {
console.log('no, this is not a folder you can drop docs onto');
}

var unid, sFormula;
sFormula = '@username';
var selections = e.data.selections;
if (selections) {
console.log('we have some docs selected!');
for (var i=0; i<selections.length; i++) {
var oUNID = selections[i].node.attributes.getNamedItem('unid')
var unid = (oUNID) ? oUNID.value : null;
if (unid != null) {
console.log('unid='+unid);
var formula = new Ext.nd.Formula(sFormula,{
"ExecuteInDocumentContext": true,
"unid" : unid
});
// eval/execute formula
console.log('evaling formula');
formula.eval();
}
}
}

console.log('addToFolder - end');
console.log('nodedragover - end');
},

// Private
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") {
// delete the current grid
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];
// now create our new view/folder
//this.UIView(this.viewPanel.getEl(), url);
this.uiView = new Ext.nd.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);
}
}
}
};

// TODO: need to create custom DominoNode class that extends Node so that we don't need to override hadChildNodes method of Node
Ext.data.Node.prototype.hasChildNodes = function() {
// for the domino folders and categories we want to always return true;
var attr = this.attributes;
if (attr.extndType == "20" || ((attr.extndType == "0" || attr.extndType == "2") && (this.attributes.extndExpandable))) {
return true;
} else {
return false;
}
};

jratcliff
10 Jun 2007, 12:20 PM
To create an outline in your own 'container' the code would look like this:




var outline = new Ext.nd.UIOutline({
outlineName : 'myOutline',
container : 'outline'
});


Where 'myOutline' is the name of an outline and 'outline' is the id of a div on the page.

Note: this still needs some work but hopefully will give you a start to what you need.

~JR

becomcs
11 Jun 2007, 5:34 AM
Sorry.

I just wan a dialog box to select value(s) from a tree where data are provided by parent/child documents. Child data beeing retrived in an async process. Async because tree could contain many many data. So I need to retrieve only first level of the tree, then retrieve next level only by clicking on the corresponding node.

I don't look for a complexe dialog layout.

B2T

Zakaroonikov
11 Jun 2007, 2:02 PM
Sorry.

I just wan a dialog box to select value(s) from a tree where data are provided by parent/child documents. Child data beeing retrived in an async process. Async because tree could contain many many data. So I need to retrieve only first level of the tree, then retrieve next level only by clicking on the corresponding node.

I don't look for a complexe dialog layout.

B2T

Try the code below. I have modified the outline class for similar reasons where I need to produce a tree listing from a categorised view. The main changes is the addition of a isView variable which when true causes this class to set defaults for a view (ie use ?ReadViewEntries&Count=-1 instead of ?ReadEntries, use viewentry nodes instead of outlineentry nodes). You will need to set this parameter to true on object initialisation if you want this to work with views otherwise it will look for an outline.

Perhaps the Ext.nd team could make like changes to their code? :D


/*
* Ext.nd - Ext for Notes / Domino Alpha 1
* Copyright(c) 2006, Ext.nd Team.
*
* http://www.extjs.com/license
*/

/**
* @class Ext.nd.DominoUI
* Makes an AJAX call to the outline's readentries and translates it into an {@link Ext.Tree}
* @constructor
* Create a new UIOutline component
* @param {Object} config Configuration options
*/
Ext.nd.UIOutline = function(config) {

var sess = Ext.nd.Session; // should we assume that there will always be a session?
var db = sess.CurrentDatabase;

// defaults
this.dbPath = db.WebFilePath;
this.outlineName = '';
this.useOutlineIcons = false;

// Set any config params passed in to override defaults
Ext.apply(this,config);

// outlineUrl is either passed in or built from dbPath and outlineName
this.outlineUrl = (this.outlineUrl) ? this.outlineUrl : this.dbPath + this.outlineName;

// Setup request type depending on wether or no this is sources from a categorised view or outline
this.urlReq = this.isView ? '?ReadViewEntries&ExpandView&Count=-1' : '?ReadEntries';
// XML node name dependent on source type (viewentry->view outlineentry->outline)
this.entryTagName = this.isView ? 'viewentry' : 'outlineentry';

// init the outline, which creates it in the container passed in the config object
this.init();
};

Ext.nd.UIOutline.prototype = {
init: function() {
var cb = {
success : this.init2.createDelegate(this),
failure : this.init2.createDelegate(this),
scope: this
};
Ext.lib.Ajax.request('POST', this.outlineUrl + this.urlReq, cb); // Use correct request type
},

// Private
init2: function(o) {
var response = o.responseXML;
var arEntries = response.getElementsByTagName(this.entryTagName); // Use correct node name
var outlineEl = this.outlinePanel.getEl ? this.outlinePanel.getEl() : this.outlinePanel; // Hande if this is a ext.contentpanel or ext.element
var Tree = Ext.tree;
var tree = new Tree.TreePanel(outlineEl, {
animate : true,
enableDD : true,
ddGroup: 'TreeDD',
containerScroll : true,
dropConfig : {appendOnly : true},
rootVisible : false
});

// add a tree sorter in folder mode
//new Tree.TreeSorter(tree, {folderSort : true}); // leave the sort order alone for domino outlines

// set the root node
// var root = new Tree.AsyncTreeNode({
var root = new Tree.TreeNode({
text : 'domino-folders',
draggable : false, // disable root node dragging
id : 'domino-folders'
});
tree.setRootNode(root);
var curNode = null;
var arNodes = [];
for (var i=0; i<arEntries.length; i++) {
var entry = arEntries.item(i);
var extndType = this.isView ? "0" : entry.attributes.getNamedItem('type').value;
var extndTitle = this.isView ? entry.textContent : entry.attributes.getNamedItem('title').value;
// var tmpextndHref = entry.attributes.getNamedItem('url');
// var extndHref = (tmpextndHref) ? tmpextndHref.value : "";
// Build up link dependent on data source (url from outline or build url from unid if from view)
var tmpdwtHref = this.isView ? entry.attributes.getNamedItem('unid') : entry.attributes.getNamedItem('url');
var dwtHref = (tmpdwtHref) ? (this.isView ? dbUrl + '/0/'+ tmpdwtHref.value + '?OpenDocument' : tmpdwtHref.value) : "";



// is expandable?
// if the attribute 'expandable' exists, then it is expandable
// don't be execused by expandable='true' or expandable='false'
// the true and false just tells you their initial state (either already expanded or already collapsed)
var expandable = entry.attributes.getNamedItem(this.isView ? 'children' : 'expandable'); // Categorised views have 'children'
var isExpandable = (expandable) ? true : false;

var tmpextndIcon = entry.attributes.getNamedItem('icon');
var extndIcon = (tmpextndIcon) ? tmpextndIcon.value : "";
var curPosition = entry.attributes.getNamedItem('position').value;

var cls;
switch (extndType) {
// section
case "0" :
cls = (isExpandable) ? "folder" : "file";
break;
// view
case "2" :
cls = "file";
break;
// folder
case "20" :
cls = "folder";
break;
default :
cls = "file";
};

var curNode = new Tree.TreeNode({
text : extndTitle,
cls : cls,
allowDrag : true,
allowDrop : (extndType == "20" || extndType == "0") ? true : false,
isTarget : true,
leaf : false,
extndHref : extndHref,
extndType : extndType,
extndExpandable: isExpandable,
extndPosition : curPosition,
icon : (this.useOutlineIcons) ? extndIcon : null
});

curNode.on('click', this.openEntry.createDelegate(this), this, true);
//curNode.leaf = false;

arNodes[curPosition] = curNode;

if (curPosition.indexOf('.') > 0) {
var parentPosition = curPosition.substring(0,curPosition.lastIndexOf('.'));
arNodes[parentPosition].appendChild(curNode);
} else {
root.appendChild(curNode);
}
}

// handle the drop of the doc on the folder
tree.on('beforenodedrop', this.addToFolder);

// render the tree
tree.render();

//root.expand(false, /*no anim*/ false);
root.expand();
},

// Private
addToFolder: function(e) {
console.log('nodedragover - start');
console.log('addToFolder - start');

var type = e.target.attributes.extndType;
console.log('type='+type);

if (type == "20" || type == "0") {
console.log('expanding');
e.target.expand();
} else {
console.log('no, this is not a folder you can drop docs onto');
}

var unid, sFormula;
sFormula = '@username';
var selections = e.data.selections;
if (selections) {
console.log('we have some docs selected!');
for (var i=0; i<selections.length; i++) {
var oUNID = selections[i].node.attributes.getNamedItem('unid')
var unid = (oUNID) ? oUNID.value : null;
if (unid != null) {
console.log('unid='+unid);
var formula = new Ext.nd.Formula(sFormula,{
"ExecuteInDocumentContext": true,
"unid" : unid
});
// eval/execute formula
console.log('evaling formula');
formula.eval();
}
}
}

console.log('addToFolder - end');
console.log('nodedragover - end');
},

// Private
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") {
// delete the current grid
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];
// now create our new view/folder
//this.UIView(this.viewPanel.getEl(), url);
this.uiView = new Ext.nd.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);
}
}
}
};

// TODO: need to create custom DominoNode class that extends Node so that we don't need to override hadChildNodes method of Node
Ext.data.Node.prototype.hasChildNodes = function() {
// for the domino folders and categories we want to always return true;
var attr = this.attributes;
if (attr.extndType == "20" || ((attr.extndType == "0" || attr.extndType == "2") && (this.attributes.extndExpandable))) {
return true;
} else {
return false;
}
};

jratcliff
13 Jun 2007, 8:16 AM
Perhaps the Ext.nd team could make like changes to their code? :D


I think we just might do that. :) Thanks for sharing!

Zakaroonikov
17 Jun 2007, 3:01 PM
I have noticed that this does not work in IE as node.textContent is a firefox element. Instead we need a browser independent version:

Change:

var extndTitle = this.isView ? entry.textContent : entry.attributes.getNamedItem('title').value

To:


var dwtTitle = this.isView ? this.getInnerText(entry) : entry.attributes.getNamedItem('title').value;

And Add:



DWT.JCWDominoUIOutline.prototype.getInnerText = function (node) {
if (typeof node.textContent != 'undefined') {
return node.textContent;
}
else if (typeof node.innerText != 'undefined') {
return node.innerText;
}
else if (typeof node.text != 'undefined') {
return node.text;
}
else {
switch (node.nodeType) {
case 3:
case 4:
return node.nodeValue;
break;
case 1:
case 11:
var innerText = '';
for (var i = 0; i < node.childNodes.length; i++) {
innerText += getInnerText(node.childNodes[i]);
}
return innerText;
break;
default:
return '';
}
}
};

Zakaroonikov
2 Dec 2009, 2:47 PM
Here is an update to get this to work in the new Ext.nd



Ext.override(Ext.nd.UIOutline,{
isView : false,
initComponent: function() {

// Using applyIf here to allow full developer control
// over passing in new config settings, anything passed
// into UIOutline will override these
Ext.applyIf(this, {
id: 'xnd-outline-' + Ext.id(),
autoScroll: true,
containerScroll: true,
useEntryTitleAsTargetTitle: true,
loader: new Ext.nd.UIOutline.Loader({
url: this.outlineUrl + (this.isView ? '?ReadViewEntries&ExpandView&Count=-1' : '?ReadEntries')
}),
dropConfig: {
appendOnly: true,
notifyDrop: this.addToFolder.createDelegate(this),
onNodeOver: this.addToFolderCheck.createDelegate(this)
},
root: new Ext.nd.TreeNode({
text: 'outline root',
expanded: true,
draggable: false, // disable root node
// dragging
id: 'xnd-outline-root' + Ext.id()
})
});

Ext.nd.UIOutline.superclass.initComponent.call(this);

this.addEvents(

'readentries',

'beforeopenentry',

'openentry',

'beforeaddtofolder',

'addfoldersuccess',

'addfolderfailure');

this.on('click', this.openEntry, this);
}
});


Ext.override(Ext.nd.UIOutline.Loader, {
createNode: function(attr, tree) {


var a = attr.attributes, cls, nodeAttr, title;

var viewOutlineQuery = this.alwaysEdit ? '?EditDocument' : '?OpenDocument'

var rtUrl = (this.rootCategory) ? '&restricttocategory='+ this.rootCategory : '';
// var type = a.getNamedItem('type').value;
var type = this.isView ? "0" : a.getNamedItem('type').value;

var tmpHref = this.isView ? a.getNamedItem('unid') : a.getNamedItem('url');

// var unid = a.getNamedItem('unid') ? a.getNamedItem('unid').value : null;
var unid = (tmpHref) ? tmpHref.value : '';

//var title = a.getNamedItem('title').value;
if (this.isView)
{
var entryData = Ext.DomQuery.selectNode("entrydata", attr);
title = this.getInnerNodeText(entryData);
}
else
{
title = a.getNamedItem('title').value;
}
title = title.replace(/\r/g, "").replace(/\n/g, "");

//var href = a.getNamedItem('url') ? a.getNamedItem('url').value : '';
var href = (tmpHref) ? (this.isView ? this.dbUrl + '/0/'+ tmpHref.value + viewOutlineQuery + rtUrl: tmpHref.value) : "";

// var expandable = a.getNamedItem('expandable');
var expandable = a.getNamedItem(this.isView ? 'children' : 'expandable');
var isExpandable = (expandable) ? true : false;
var isExpanded = (expandable && expandable.value == 'true') ? true : false;

var icon = a.getNamedItem('icon') ? a.getNamedItem('icon').value : '';
var position = a.getNamedItem('position').value;

switch(type) {
case "0": // section
cls = (isExpandable) ? "folder" : "file";
break;
case "2": // view
cls = "file";
break;
case "20": // folder
cls = "folder";
break;
default:
cls = "file";
}

nodeAttr = {
text: title,
cls: (tree.showIcons) ? cls : null,
iconCls: (tree.showIcons) ? ((tree.useOutlineIcons) ? 'xnd-icon' : null) : 'xnd-no-icon',
allowDrag: (type == "20") ? true : false,
allowDrop: (type == "20") ? true : false,
isTarget: true,
leaf: false,
expanded : isExpanded,
extndHref: href,
extndType: type,
extndUNID: unid,
extndExpandable: expandable,
extndPosition: position,
icon: (tree.showIcons && tree.useOutlineIcons) ? icon : null
};

return new Ext.nd.TreeNode(nodeAttr);
},

/**
* Browser independent method to retrieve innertext of a dom node
* @param {Object} node
* @return {String} Inner text of dom node
*/
getInnerNodeText : function (node) {
if (typeof node.textContent != 'undefined') {
return node.textContent;
}
else if (typeof node.innerText != 'undefined') {
return node.innerText;
}
else if (typeof node.text != 'undefined') {
return node.text;
}
else {
switch (node.nodeType) {
case 3:
case 4:
return node.nodeValue;
break;
case 1:
case 11:
var innerText = '';
for (var i = 0; i < node.childNodes.length; i++) {
innerText += getInnerText(node.childNodes[i]);
}
return innerText;
break;
default:
return '';
}
}
return true;
},

/**
* Given a url return the .nsf pathname
* @param {String} url Url to extract .nsf pathname from
* @return {String} path of .nsf file (including filename)
*/
getDbUrl : function(url) {
var iLocNSF = url.toLowerCase().indexOf('.nsf') + 4; // in case ! is used instead of ?
if (iLocNSF != -1)
return url.substring(0,iLocNSF);
else
return '';
},

processResponse: function(response, node, callback) {
// If this is a view treepanel
if (this.url.toLowerCase().indexOf('?readviewentries') !== -1)
{
this.isView = true;
this.dbUrl = this.getDbUrl(this.url);
this.entryTagName = 'viewentry';
}
else
{
this.isView = false;
this.dbUrl = '';
this.entryTagName = 'outlineentry';
}

var o = response.responseXML;
var entries = o.getElementsByTagName(this.entryTagName);
try {
node.beginUpdate();
var nodes = [];
for(var i = 0; i < entries.length; i++) {
var entry = entries.item(i);
var n = this.createNode(entry, node.getOwnerTree());
if (n) {
var curPosition = entry.attributes.getNamedItem('position').value;
nodes[curPosition] = n;
if (curPosition.indexOf('.') > 0) {
var parentPosition = curPosition.substring(0, curPosition.lastIndexOf('.'));
nodes[parentPosition].appendChild(n);
} else {

node.appendChild(n);
}
}
}
node.endUpdate();

if (typeof callback == "function") {
callback(this, node);
}
} catch (e) {
this.handleFailure(response);
}
}
});


To use this code I modified the multiple-outlines.html in the demo database added another column in form and added a div with id 'viewoutline1'



var viewoutline1 = new Ext.nd.UIOutline({
outlineName : 'sc1b',
isView : true,
renderTo : 'viewoutline1',
border : false,
width : 200,
height : 500
});

jratcliff
3 Dec 2009, 9:08 AM
Here is an update to get this to work in the new Ext.nd



Ext.override(Ext.nd.UIOutline,{
isView : false,
initComponent: function() {

// Using applyIf here to allow full developer control
// over passing in new config settings, anything passed
// into UIOutline will override these
Ext.applyIf(this, {
id: 'xnd-outline-' + Ext.id(),
autoScroll: true,
containerScroll: true,
useEntryTitleAsTargetTitle: true,
loader: new Ext.nd.UIOutline.Loader({
url: this.outlineUrl + (this.isView ? '?ReadViewEntries&ExpandView&Count=-1' : '?ReadEntries')
}),
dropConfig: {
appendOnly: true,
notifyDrop: this.addToFolder.createDelegate(this),
onNodeOver: this.addToFolderCheck.createDelegate(this)
},
root: new Ext.nd.TreeNode({
text: 'outline root',
expanded: true,
draggable: false, // disable root node
// dragging
id: 'xnd-outline-root' + Ext.id()
})
});

Ext.nd.UIOutline.superclass.initComponent.call(this);

this.addEvents(

'readentries',

'beforeopenentry',

'openentry',

'beforeaddtofolder',

'addfoldersuccess',

'addfolderfailure');

this.on('click', this.openEntry, this);
}
});


Ext.override(Ext.nd.UIOutline.Loader, {
createNode: function(attr, tree) {


var a = attr.attributes, cls, nodeAttr, title;

var viewOutlineQuery = this.alwaysEdit ? '?EditDocument' : '?OpenDocument'

var rtUrl = (this.rootCategory) ? '&restricttocategory='+ this.rootCategory : '';
// var type = a.getNamedItem('type').value;
var type = this.isView ? "0" : a.getNamedItem('type').value;

var tmpHref = this.isView ? a.getNamedItem('unid') : a.getNamedItem('url');

// var unid = a.getNamedItem('unid') ? a.getNamedItem('unid').value : null;
var unid = (tmpHref) ? tmpHref.value : '';

//var title = a.getNamedItem('title').value;
if (this.isView)
{
var entryData = Ext.DomQuery.selectNode("entrydata", attr);
title = this.getInnerNodeText(entryData);
}
else
{
title = a.getNamedItem('title').value;
}
title = title.replace(/\r/g, "").replace(/\n/g, "");

//var href = a.getNamedItem('url') ? a.getNamedItem('url').value : '';
var href = (tmpHref) ? (this.isView ? this.dbUrl + '/0/'+ tmpHref.value + viewOutlineQuery + rtUrl: tmpHref.value) : "";

// var expandable = a.getNamedItem('expandable');
var expandable = a.getNamedItem(this.isView ? 'children' : 'expandable');
var isExpandable = (expandable) ? true : false;
var isExpanded = (expandable && expandable.value == 'true') ? true : false;

var icon = a.getNamedItem('icon') ? a.getNamedItem('icon').value : '';
var position = a.getNamedItem('position').value;

switch(type) {
case "0": // section
cls = (isExpandable) ? "folder" : "file";
break;
case "2": // view
cls = "file";
break;
case "20": // folder
cls = "folder";
break;
default:
cls = "file";
}

nodeAttr = {
text: title,
cls: (tree.showIcons) ? cls : null,
iconCls: (tree.showIcons) ? ((tree.useOutlineIcons) ? 'xnd-icon' : null) : 'xnd-no-icon',
allowDrag: (type == "20") ? true : false,
allowDrop: (type == "20") ? true : false,
isTarget: true,
leaf: false,
expanded : isExpanded,
extndHref: href,
extndType: type,
extndUNID: unid,
extndExpandable: expandable,
extndPosition: position,
icon: (tree.showIcons && tree.useOutlineIcons) ? icon : null
};

return new Ext.nd.TreeNode(nodeAttr);
},

/**
* Browser independent method to retrieve innertext of a dom node
* @param {Object} node
* @return {String} Inner text of dom node
*/
getInnerNodeText : function (node) {
if (typeof node.textContent != 'undefined') {
return node.textContent;
}
else if (typeof node.innerText != 'undefined') {
return node.innerText;
}
else if (typeof node.text != 'undefined') {
return node.text;
}
else {
switch (node.nodeType) {
case 3:
case 4:
return node.nodeValue;
break;
case 1:
case 11:
var innerText = '';
for (var i = 0; i < node.childNodes.length; i++) {
innerText += getInnerText(node.childNodes[i]);
}
return innerText;
break;
default:
return '';
}
}
return true;
},

/**
* Given a url return the .nsf pathname
* @param {String} url Url to extract .nsf pathname from
* @return {String} path of .nsf file (including filename)
*/
getDbUrl : function(url) {
var iLocNSF = url.toLowerCase().indexOf('.nsf') + 4; // in case ! is used instead of ?
if (iLocNSF != -1)
return url.substring(0,iLocNSF);
else
return '';
},

processResponse: function(response, node, callback) {
// If this is a view treepanel
if (this.url.toLowerCase().indexOf('?readviewentries') !== -1)
{
this.isView = true;
this.dbUrl = this.getDbUrl(this.url);
this.entryTagName = 'viewentry';
}
else
{
this.isView = false;
this.dbUrl = '';
this.entryTagName = 'outlineentry';
}

var o = response.responseXML;
var entries = o.getElementsByTagName(this.entryTagName);
try {
node.beginUpdate();
var nodes = [];
for(var i = 0; i < entries.length; i++) {
var entry = entries.item(i);
var n = this.createNode(entry, node.getOwnerTree());
if (n) {
var curPosition = entry.attributes.getNamedItem('position').value;
nodes[curPosition] = n;
if (curPosition.indexOf('.') > 0) {
var parentPosition = curPosition.substring(0, curPosition.lastIndexOf('.'));
nodes[parentPosition].appendChild(n);
} else {

node.appendChild(n);
}
}
}
node.endUpdate();

if (typeof callback == "function") {
callback(this, node);
}
} catch (e) {
this.handleFailure(response);
}
}
});


To use this code I modified the multiple-outlines.html in the demo database added another column in form and added a div with id 'viewoutline1'



var viewoutline1 = new Ext.nd.UIOutline({
outlineName : 'sc1b',
isView : true,
renderTo : 'viewoutline1',
border : false,
width : 200,
height : 500
});


Very nice! =D> I forgot all about this from when you first did it a while back. I definitely want to look it over to see if we can incorporate this into the base of Ext.nd.

Thanks again!
Jack

Zakaroonikov
3 Dec 2009, 5:17 PM
No problem. Happy to help out.

TY@GP
18 Dec 2009, 5:07 PM
Sorry.

I just wan a dialog box to select value(s) from a tree where data are provided by parent/child documents. Child data beeing retrived in an async process. Async because tree could contain many many data. So I need to retrieve only first level of the tree, then retrieve next level only by clicking on the corresponding node.

I don't look for a complexe dialog layout.

B2T


I developed an extension on the uiview for B2.x that contains this behavour, I am currently porting it back to ExtND R3. I will keep you informed.