Create an Ext.tree.TreePanel from an XML document


Hi,

Recently I created menu manager with Ext JS components.
First I loaded tree from XML documents, But then I realize JSON will be very much easy. Still if you think that XML document is perfect for you then here is my work.

On fly I’m just providing html page and xml file, so if you have any doubts or questions then you can place comment bellow.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>
			Manage Menu 
		</title>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<link href="http://dev.sencha.com/deploy/ext-3.4.0/resources/css/ext-all.css" rel="stylesheet"/>
		<script src="http://dev.sencha.com/deploy/ext-3.4.0/adapter/ext/ext-base.js"></script>
		<script src="http://dev.sencha.com/deploy/ext-3.4.0/ext-all.js"></script>
		<link href="http://dev.sencha.com/deploy/ext-3.4.0/examples/tree/xml-tree-loader.css"/>
		<script src="http://dev.sencha.com/deploy/ext-3.4.0/examples/ux/XmlTreeLoader.js"></script>
		<script>
			//Excellent function that converts tree data into json
			function getJson(treeNode) {
				treeNode.expandChildNodes();
				var json = {};
				var attributes = treeNode.attributes;
				for(var item in attributes){
					if (item == 'src' || item == 'text' || item == 'allowDrop' || item == 'allowDrag') { //get only required attributes
						json[item] = attributes[item];
					}
				}
				json.children = [];
				if(treeNode.childNodes.length > 0){
					for (var i=0; i < treeNode.childNodes.length; i++) {
						json.children.push(getJson(treeNode.childNodes[i]));
					}
					json.leaf = false;
				} else {
					json.leaf = true;
				}
				return json;
			}
			//
			// Extend the XmlTreeLoader to set some custom TreeNode attributes specific to our application:
			//
			Ext.app.CustomTreeLoader = Ext.extend(Ext.ux.tree.XmlTreeLoader, {
				processAttributes : function(attr){
					// Set the node text that will show in the tree since our raw data does not include a text attribute:
					attr.text = attr.title;
					if(attr.src == 'javascript:void(0);'){ // Does the node has child?
						// Override these values for our folder nodes because we are loading all data at once.  If we were
						// loading each node asynchronously (the default) we would not want to do this:
						attr.loaded = true;
						attr.expanded = true;
					}
					else { // is it a leaf node?
						// Tell the tree this is a leaf node.  This could also be passed as an attribute in the original XML,
						// but this example demonstrates that you can control this even when you cannot dictate the format of
						// the incoming source XML:
						attr.leaf = true;
					}
				},
				requestMethod: 'GET'
			});
			Ext.onReady(function(){
				new Ext.Panel({
					title: 'Menu',
					renderTo: 'menuTree',
					layout: 'border',
					width: 500,
					height: 500,
					items: [{
						xtype: 'treepanel',
						id: 'tree-panel',
						region: 'center',
						margins: '2 2 0 2',
						autoScroll: true,
						rootVisible: false,
						enableDD: true,
						viewConfig: {
				            plugins: [{
				                ptype: 'treeviewdragdrop'
				            }]
				        },
						root: new Ext.tree.AsyncTreeNode(),
							loader: new Ext.app.CustomTreeLoader({
								dataUrl:'menu.xml'  //load your xml file
							}),
							listeners: {
								'render': function(tp){
								tp.getSelectionModel().on('selectionchange', function(tree, node){
									var el = Ext.getCmp('details-panel').body;
									tpl.overwrite(el, node.attributes);
								})
							}
						}
					}]
			    });
			});
			function savechanges(){
				var myTree = Ext.getCmp('tree-panel');
				var json = getJson(myTree.getRootNode());
				console.log(Ext.encode(json.children)); //serialize json data into string so we can send back to server
			}
		</script>
	</head>
	<body>
		<div id="menuTree"></div>
	</body>
</html>

Sample XML file…

<?xml version="1.0" encoding="UTF-8"?>
<menu src="root" title="root" id="0">
	<!-- Home -->
	<menu src="/page.htm2" title="Home"></menu>
	<menu title="Clients" src="javascript:void(0);">
		<menu src="/page1.html" title="Bank Management"></menu>
		<menu src="/page2.html" title="Client Management"></menu>
		<menu src="javascript:void(0);" title="Updates">
			<menu src="/page2.html" title="View Updates"></menu>
			<menu src="/page3.html" title="Report Bug"></menu>
		</menu>
	</menu>
	<!--  Ends -->
</menu>

I used third party control, that extends the XMLLoader for processing XML attributes…

In the Next post, I’ll show you how we can use JSON for easy storage and loading into tree. I’ll also post add/edit/delete/drag & drop/restriction etc.