Animal
27 Mar 2007, 7:07 AM
Well, so much for off the cuff code! It was rubbish!
I've fixed it up. If you copy the two functions at the top heer into your test page, they should work.
Here it is in my Tree test page which drops into examples/tree. "Update" displays the Tree's XML:
MenuBuilder.js:
/**
* Returns a string of XML that represents the tree
* @param {Function} (optional) A function, which when passed the node, returns true or false to include
* or exclude the node.
* @param {Function} (optional) A function, which when passed an attribute name, and an attribute value,
* returns true or false to include or exclude the attribute.
* @return {String}
*/
Ext.data.Tree.prototype.toXMLString = function(nodeFilter, attributeFilter){
return '\u003C?xml version="1.0"?>\u003Ctree>' +
this.getRootNode().toXMLString(nodeFilter, attributeFilter) +
'\u003C/tree>';
};
/**
* Returns a string of XML that represents the node
* @param {Function} (optional) A function, which when passed the node, returns true or false to include
* or exclude the node.
* @param {Function} (optional) A function, which when passed an attribute name, and an attribute value,
* returns true or false to include or exclude the attribute.
* @return {String}
*/
Ext.data.Node.prototype.toXMLString = function(nodeFilter, attributeFilter){
// Exclude nodes based on caller-supplied filtering function
if (nodeFilter && (nodeFilter(this) == false)) {
return '';
}
var result = '\u003Cnode';
// Add the id attribute unless the attribute filter rejects it.
if (!(attributeFilter && (attributeFilter("id", this.id) == false))) {
result += ' id="' + this.id + '"';
}
// Add all user-added attributes unless rejected by the attributeFilter.
for(var key in this.attributes) {
if (attributeFilter && (attributeFilter(key, this.attributes[key]) == false)) {
continue;
}
if (typeof this.attributes[key] != "object") {
result += ' ' + key + '="' + this.attributes[key] + '"';
}
}
// Add child nodes if any
var children = this.childNodes;
var clen = children.length;
if(clen == 0){
result += '/>';
}else{
result += '>';
for(var i = 0; i < clen; i++){
result += children[i].toXMLString(nodeFilter, attributeFilter);
}
result += '\u003C/node>';
}
return result;
};
/*
*
* Add a couple of overrides only needed during Ext 1.0 Alpha test...
*
*/
Ext.menu.Menubar = function(config){
Ext.applyIf(config, {
plain: true,
cls: ""
});
Ext.menu.Menubar.superclass.constructor.call(this, config);
this.cls += " x-menubar";
if (this.orientation == "vertical") {
this.subMenuAlign = "tl-tr?";
this.cls += " x-vertical-menubar";
} else {
this.subMenuAlign = "tl-bl?";
this.cls += " x-horizontal-menubar";
}
};
Ext.extend(Ext.menu.Menubar, Ext.menu.Menu, {
minWidth : 120,
shadow : false,
orientation: "horizontal",
hide: function(){
if(this.activeItem){
this.activeItem.deactivate();
delete this.activeItem;
}
},
onClick : function(e){
if (this.activeItem) {
this.activeItem.deactivate();
delete this.activeItem;
}
else {
var t;
if(t = this.findTargetItem(e)){
if(t.canActivate && !t.disabled){
this.setActiveItem(t, true);
}
}
this.fireEvent("click", this, e, t);
}
},
onMouseOver : function(e){
if (this.activeItem) {
var t;
if(t = this.findTargetItem(e)){
if(t.canActivate && !t.disabled){
this.setActiveItem(t, true);
}
}
this.fireEvent("mouseover", this, e, t);
}
},
onMouseOut : function(e){}
});
Ext.override(Ext.tree.TreeNode, {
ensureVisible : function(callback){
var c = callback;
var a = Ext.get(this.getUI().anchor);
var treeEl = this.getOwnerTree().getEl()
this.getOwnerTree().expandPath(this.getPath(), false, function() {
a.scrollIntoView(treeEl);
if (c) {
c();
}
});
}
});
/*
*
*
* The functionality of the Menu Builder page
*
*
*/
function initPage() {
Ext.pageLayout = new Ext.BorderLayout(document.body, {
north: {
split:false
},
west: {
initialSize: 200,
titlebar: true,
collapsible: true,
split:true,
animate:true,
minSize: 120,
maxSize: 250
},
center: {
titlebar: false,
autoScroll:true
},
south: {
collapsible: true,
collapsed: true,
split: true,
animate:true,
initialSize: 150,
minSize: 25,
maxSize: 250,
titlebar: true,
autoScroll:false
}
});
Ext.headerRegion = Ext.pageLayout.getRegion("north");
Ext.navRegion = Ext.pageLayout.getRegion("west");
Ext.contentRegion = Ext.pageLayout.getRegion("center");
Ext.messageRegion = Ext.pageLayout.getRegion("south");
Ext.pageTitleBar = Ext.get("page-titlebar");
Ext.pageToolbar = new Ext.Toolbar("page-toolbar");
Ext.pageToolbar.addButton({
id: 'home-btn',
cls:'x-btn-text-icon home-button',
text: 'Home',
handler: function(){}
});
Ext.headerPanel = new Ext.ContentPanel("page-header", {
toolbar: Ext.pageToolbar
});
Ext.navPanel = new Ext.ContentPanel("page-leftnav", {});
Ext.contentElement = Ext.get("page-content");
Ext.contentPanel = new Ext.ContentPanel(Ext.contentElement, {});
Ext.messagePanel = new Ext.ContentPanel("page-message", {});
Ext.messageEl = Ext.messageRegion.collapsedEl.createChild({tag:"div", 'float':"left"});
Ext.pageLayout.beginUpdate();
Ext.headerRegion.add(Ext.headerPanel);
Ext.navRegion.add(Ext.navPanel);
Ext.contentRegion.add(Ext.contentPanel);
Ext.messageRegion.add(Ext.messagePanel);
Ext.pageLayout.endUpdate();
Ext.contentUM = Ext.contentPanel.getUpdateManager();
};
function displayMessage(m) {
Ext.messageEl.update("");
Ext.messageEl.update(m);
Ext.messageEl.addClass("error");
setTimeout(function() {
Ext.messageEl.className = "";
Ext.messageEl.update("");
}, 5000);
};
Ext.onReady(function(){
initPage();
Ext.appMenuBar = new Ext.menu.Menubar({orientation:'horizontal'});
Ext.appMenuBar.add({text: 'Static Data',cls: "aspicio-menu ",menu : {items: [
{text: "Area/Postal/Zip Codes",href: "/aspicio/form/Lister.jsp?listEntityType=Area",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Class Control",href: "/aspicio/form/Lister.jsp?listEntityType=ClassControl",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Companies",href: "/aspicio/form/Lister.jsp?listEntityType=Company",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "House Components",href: "/aspicio/form/Lister.jsp?listEntityType=Component",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Contacts",href: "/aspicio/form/Lister.jsp?listEntityType=Contact",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "ContactTypes",href: "/aspicio/form/Lister.jsp?listEntityType=ContactType",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Countries",href: "/aspicio/form/Lister.jsp?listEntityType=Country",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Country sub-entities",href: "/aspicio/form/Lister.jsp?listEntityType=CountrySubEntity",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Currencies",href: "/aspicio/form/Lister.jsp?listEntityType=Currency",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "DateInfo",icon: "../../resources/images/default/tree/leaf.gif",handler:function(){0}},{text: "Economic Groups",href: "/aspicio/form/Lister.jsp?listEntityType=EconomicGroup",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Languages",href: "/aspicio/form/Lister.jsp?listEntityType=Language",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Markets",href: "/aspicio/form/Lister.jsp?listEntityType=Market",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Main Menu Groupings",href: "/aspicio/form/Lister.jsp?listEntityType=Menu",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Supply-Chain Players",href: "/aspicio/form/Lister.jsp?listEntityType=Player",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Player Types",href: "/aspicio/form/Lister.jsp?listEntityType=PlayerType",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "TimeZones",href: "/aspicio/form/Lister.jsp?listEntityType=TimeZone",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Users",href: "/aspicio/form/Lister.jsp?listEntityType=User",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "User Groups",href: "/aspicio/form/Lister.jsp?listEntityType=UserGroup",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick}
]}},
{text: 'Application Data',cls: "aspicio-menu ",menu : {items: [
{text: "Tax No Validations",href: "/aspicio/form/Lister.jsp?listEntityType=AppTaxNoValidation",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Application Classes",href: "/aspicio/form/Lister.jsp?listEntityType=AppClass",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Application Components",href: "/aspicio/form/Lister.jsp?listEntityType=AppComponent",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick}
]}},
{text: 'Test Menu',cls: "aspicio-menu ",menu : {items: [
{text: "Application Classes",href: "/aspicio/form/Lister.jsp?listEntityType=AppClass",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Economic Groups",href: "/aspicio/form/Lister.jsp?listEntityType=EconomicGroup",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Languages",href: "/aspicio/form/Lister.jsp?listEntityType=Language",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: 'Test YUI Submenus',cls: "aspicio-menu ",menu : {items: [
{text: "Application Classes",href: "/aspicio/form/Lister.jsp?listEntityType=AppClass",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Application Components",href: "/aspicio/form/Lister.jsp?listEntityType=AppComponent",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick}
]}},
{text: "Markets",href: "/aspicio/form/Lister.jsp?listEntityType=Market",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Main Menu Groupings",href: "/aspicio/form/Lister.jsp?listEntityType=Menu",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Supply-Chain Players",href: "/aspicio/form/Lister.jsp?listEntityType=Player",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick},{text: "Player Types",href: "/aspicio/form/Lister.jsp?listEntityType=PlayerType",icon: "../../resources/images/default/tree/leaf.gif",handler:Ext.menuClick}
]}});
Ext.appMenuBar.show(Ext.get('aspicio-menu-bar'),'tl-tl');
});
YAHOO.util.Event.onAvailable('menu-container', function(){
var menuContainer = Ext.get("menu-container");
var menuBox = Ext.get(menuContainer.boxWrap("x-box"));
menuBox.child(".x-box-mc").insertFirst({tag: "h3", html: "Menu"});
var tree = new Ext.tree.TreePanel(menuContainer, {
animate: false,
loader: new Ext.tree.TreeLoader(),
enableDD: true,
ddGroup: "menu-tree"
});
var newNodeCount = 0;
// Build the tree of existing Menu entries.
// In a live environment, ths icon would be a path to a servlet serving an appropriate image for the class
var root = new Ext.tree.AsyncTreeNode({
text:'Nigel\u0027s Menu',id:1,className:'com.aspicio.entity.Menu',allowDrag:false,leaf: false, children: [
{text:'Static Data',id:2,className:'com.aspicio.entity.Menu',allowDrag:true,leaf: false, children: [
{text:'Area/Postal/Zip Codes',id:3,className:'com.aspicio.entity.Menu',componentId:4,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Class Control',id:4,className:'com.aspicio.entity.Menu',componentId:5,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Companies',id:5,className:'com.aspicio.entity.Menu',componentId:6,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'House Components',id:6,className:'com.aspicio.entity.Menu',componentId:7,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Contacts',id:7,className:'com.aspicio.entity.Menu',componentId:8,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'ContactTypes',id:8,className:'com.aspicio.entity.Menu',componentId:9,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Countries',id:9,className:'com.aspicio.entity.Menu',componentId:10,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Country sub-entities',id:10,className:'com.aspicio.entity.Menu',componentId:11,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Currencies',id:11,className:'com.aspicio.entity.Menu',componentId:12,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'DateInfo',id:12,className:'com.aspicio.entity.Menu',componentId:13,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Economic Groups',id:13,className:'com.aspicio.entity.Menu',componentId:14,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Languages',id:14,className:'com.aspicio.entity.Menu',componentId:15,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Markets',id:15,className:'com.aspicio.entity.Menu',componentId:16,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Main Menu Groupings',id:16,className:'com.aspicio.entity.Menu',componentId:17,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Supply-Chain Players',id:17,className:'com.aspicio.entity.Menu',componentId:18,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Player Types',id:18,className:'com.aspicio.entity.Menu',componentId:19,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'TimeZones',id:19,className:'com.aspicio.entity.Menu',componentId:20,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Users',id:20,className:'com.aspicio.entity.Menu',componentId:21,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'User Groups',id:31,className:'com.aspicio.entity.Menu',componentId:22,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true}
]},
{text:'Application Data',id:22,className:'com.aspicio.entity.Menu',allowDrag:true,leaf: false, children: [
{text:'Tax No Validations',id:32,className:'com.aspicio.entity.Menu',componentId:3,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Application Classes',id:23,className:'com.aspicio.entity.Menu',componentId:1,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Application Components',id:24,className:'com.aspicio.entity.Menu',componentId:2,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true}
]},
{text:'Test Menu',id:33,className:'com.aspicio.entity.Menu',allowDrag:true,leaf: false, children: [
{text:'Application Classes',id:43,className:'com.aspicio.entity.Menu',componentId:1,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Economic Groups',id:34,className:'com.aspicio.entity.Menu',componentId:14,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Languages',id:35,className:'com.aspicio.entity.Menu',componentId:15,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Test YUI Submenus',id:44,className:'com.aspicio.entity.Menu',allowDrag:true,leaf: false, children: [
{text:'Application Classes',id:45,className:'com.aspicio.entity.Menu',componentId:1,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Application Components',id:46,className:'com.aspicio.entity.Menu',componentId:2,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true}
]},
{text:'Markets',id:36,className:'com.aspicio.entity.Menu',componentId:16,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Main Menu Groupings',id:37,className:'com.aspicio.entity.Menu',componentId:17,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Supply-Chain Players',id:38,className:'com.aspicio.entity.Menu',componentId:18,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true},
{text:'Player Types',id:39,className:'com.aspicio.entity.Menu',componentId:19,icon:'../../resources/images/default/tree/leaf.gif',allowDrag:true,leaf: true}
]}
]
});
tree.setRootNode(root);
tree.render();
root.expand(true);
root.collapse(true);
root.expand();
tree.animate = true;
// add an inline editor for the nodes
var ge = new Ext.Editor(new Ext.form.TextField({
allowBlank: false,
blankText: 'A name is required',
autoSize: true
}), {
parentEl: tree.getEl(),
alignment: 'tl-tl'
});
ge.on('complete', function(e, value){
ge.node.setText(value);
});
// listen for a click on a node that is already selected
// and start editing. Return false to cancel the default click action.
tree.on('beforeclick', function(node){
if(tree.getSelectionModel().isSelected(node)){
ge.node = node;
ge.startEdit(node.ui.getAnchor(), node.text);
return false;
}
});
// Create the tree's context menu
var treeMenu = new Ext.menu.Menu({id: "menu-tree-menu"});
treeMenu.on("itemclick", function(item) {
switch (item.id) {
case "delete":
this.contextNode.parentNode.removeChild(this.contextNode);
break;
case "new":
var newNode = new Ext.tree.TreeNode({
text: "New Menu " + (++newNodeCount),
className: "com.aspicio.entity.Menu",
leaf:false
});
var n = this.contextNode;
if (n.isLeaf()) {
n.parentNode.insertBefore(newNode, n.nextSibling);
} else {
n.appendChild(newNode);
}
}
}, treeMenu, true);
var deleteNode = treeMenu.add({
icon: "../../resources/images/default/delete.gif",
id: "delete",
text: "Delete Item"
});
var newNode = treeMenu.add({
icon: "../../resources/images/default/new.gif",
id: "new",
text: "New Submenu"
});
tree.on("contextmenu", function(node, e) {
contextNode = node;
if (node.isRoot) {
deleteNode.disable();
} else {
deleteNode.enable();
}
treeMenu.contextNode = node;
node.select();
treeMenu.showAt(e.getXY());
});
var menuForm = Ext.get("menuForm");
menuForm.on("submit", function(e)
{
e.stopEvent();
menuForm.dom.elements["updateXML"].value = tree.toXMLString(function(node){
}, function(key, val) {
if ((key == "id") && (typeof val == "string") && (val.match(/^ynode/))) {
return false;
}
return (["componentId", "allowDrag", "leaf", "icon"].indexOf(key) == -1);
});
alert(menuForm.dom.elements["updateXML"].value);
});
});
// Build the source of application Components which may be dragged into the Menu tree
YAHOO.util.Event.onAvailable('component-container', function(){
var componentContainer = Ext.get("component-container");
var componentBox = Ext.get(componentContainer.boxWrap("x-box"));
componentBox.child(".x-box-mc").insertFirst({tag: "h3", html: "Components"});
var components = [
{id:1, desc: "Application Classes", 'class': "com.aspicio.entity.Component", entity: "AppEntity"},
{id:2, desc: "Application Components", 'class': "com.aspicio.entity.Component", entity: "AppComponent"},
{id:3, desc: "Tax No Validations", 'class': "com.aspicio.entity.Component", entity: "AppTaxNoValidation"},
{id:4, desc: "Area/Postal/Zip Codes", 'class': "com.aspicio.entity.Component", entity: "Area"},
{id:5, desc: "Class Control", 'class': "com.aspicio.entity.Component", entity: "ClassControl"},
{id:6, desc: "Companies", 'class': "com.aspicio.entity.Component", entity: "Company"},
{id:7, desc: "House Components", 'class': "com.aspicio.entity.Component", entity: "Component"},
{id:8, desc: "Contacts", 'class': "com.aspicio.entity.Component", entity: "Contact"},
{id:9, desc: "ContactTypes", 'class': "com.aspicio.entity.Component", entity: "ContactType"},
{id:10, desc: "Countries", 'class': "com.aspicio.entity.Component", entity: "Country"},
{id:11, desc: "Country sub-entities", 'class': "com.aspicio.entity.Component", entity: "CountrySubEntity"},
{id:12, desc: "Currencies", 'class': "com.aspicio.entity.Component", entity: "Currency"},
{id:13, desc: "DateInfo", 'class': "com.aspicio.entity.Component", entity: "Currency"},
{id:14, desc: "Economic Groups", 'class': "com.aspicio.entity.Component", entity: "EconomicGroup"},
{id:15, desc: "Languages", 'class': "com.aspicio.entity.Component", entity: "Language"},
{id:16, desc: "Markets", 'class': "com.aspicio.entity.Component", entity: "Market"},
{id:17, desc: "Main Menu Groupings", 'class': "com.aspicio.entity.Component", entity: "Menu"},
{id:18, desc: "Supply-Chain Players", 'class': "com.aspicio.entity.Component", entity: "Player"},
{id:19, desc: "Player Types", 'class': "com.aspicio.entity.Component", entity: "PlayerType"},
{id:20, desc: "TimeZones", 'class': "com.aspicio.entity.Component", entity: "TimeZone"},
{id:21, desc: "Users", 'class': "com.aspicio.entity.Component", entity: "User"},
{id:22, desc: "User Groups", 'class': "com.aspicio.entity.Component", entity: "UserGroup"},
{id:23, desc: "Menu Builder", 'class': "com.aspicio.entity.Component", entity: "Menu"}
];
var CompRecord = Ext.data.Record.create([
{name: 'id'},
{name: 'class'},
{name: 'entity'},
{name: 'desc'}
]);
var reader = new Ext.data.JsonReader({
root: 'components',
}, CompRecord);
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy({'components': components}),
reader: reader,
remoteSort: true
});
// Create the View of available Components.
// Each draggable element is in a DIV labelled with CSS class "app-component"
// In a live environment, the image src would be a servlet serving up an appropriate image for the class.
var view = new Ext.View(componentContainer,
'<div id="component_{id}" class="{class} app-component">' +
'../../resources/images/default/tree/leaf.gif?entity={entity}{desc}</div>', {
multiSelect: true,
selectedClass: 'component-selected',
jsonRoot: 'components',
store: ds
});
view.getEl().unselectable();
var dragZone = new ComponentDragZone(view, {
containerScroll:true,
ddGroup: 'menu-tree'
});
ds.load();
});
/**
* Create a DragZone instance for our JsonView
*/
ComponentDragZone = function(view, config){
this.view = view;
ComponentDragZone.superclass.constructor.call(this, view.getEl(), config);
};
Ext.extend(ComponentDragZone, Ext.dd.DragZone, {
// We don't want to register our Component elements, so let's
// override the default registry lookup to fetch the Component
// from the event instead by finding the element with the known CSS class "app-component"
getDragData : function(e) {
e = Ext.EventObject.setEvent(e);
var target = e.getTarget('.app-component');
if(target){
var view = this.view;
if(!view.isSelected(target)){
view.select(target, e.ctrlKey);
}
var selNodes = view.getSelectedNodes();
var dragData = {
nodes: selNodes
};
if(selNodes.length == 1){
dragData.ddel = target.cloneNode(true); // the div element
dragData.single = true;
}else{
var div = document.createElement('div'); // create the multi element drag "ghost"
div.className = 'multi-proxy';
for(var i = 0, len = selNodes.length; i < len; i++){
div.appendChild(selNodes[i].cloneNode(true));
}
dragData.ddel = div;
dragData.multi = true;
}
return dragData;
}
return false;
},
/*
* This method is called by the TreeDropZone after a node drop.
* The result of the overriden method above, "getDragData" is in "this.dragData".
* We use this data to create a new node (or nodes) for the tree.
*/
getTreeNode : function(data, targetNode, point, e){
var folderNode = ((point == "above") || (point == "below")) ? targetNode.parentNode : targetNode;
var treeNodes = [];
var nodeData = this.dragData.nodes;
for(var i = 0, len = nodeData.length; i < len; i++){
var data = nodeData[i];
var newId = parseInt(data.id.split("component_")[1]);
var newClassName = data.className.split(" ")[0];
// See if an item for this component exists.
var dup = folderNode.findChildBy(function(node){
var a = node.attributes;
return (((a.className == newClassName) && (a.id == newId)) || (a.componentId == newId));
});
// If we found a duplicate ensure it is visible and highlight it
if (dup) {
dup.ensureVisible(function() {
Ext.get(dup.getUI().anchor).frame('red', 1);
displayMessage("Component already in Menu");
});
} else {
var newText = data.childNodes[1].nodeValue;
treeNodes.push(new Ext.tree.TreeNode({
icon: data.firstChild.src,
text: newText,
id: newId,
className: newClassName,
leaf:true
}));
}
}
return (treeNodes.length > 0) ? treeNodes : false;
},
/**
* The default action is to "highlight" after a bad drop
* but framing in red is better
*/
afterRepair:function(){
for(var i = 0, len = this.dragData.nodes.length; i < len; i++){
Ext.fly(this.dragData.nodes[i]).frame('red', 1);
}
this.dragging = false;
},
/** override the default repairXY with one offset for the margins and padding. */
getRepairXY : function(e){
if(!this.dragData.multi){
var xy = Ext.Element.fly(this.dragData.ddel).getXY();
xy[0]+=3;xy[1]+=3;
return xy;
}
return false;
}
});
MenuBuilder.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Building a custom menu. Submitting tree data in XML form</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../yui-utilities.js"></script>
<script type="text/javascript" src="../../ext-yui-adapter.js"></script>
<script type="text/javascript" src="../../ext-all-debug.js"></script>
<script type="text/javascript" src="MenuBuilder.js"></script>
<style type="text/css">
.x-menubar {
background-color:#deecfd
}
.x-horizontal-menubar {
width:100%!important;
border-left:0px none;
border-right:0px none;
}
.x-horizontal-menubar > .x-menu-list {
float:left;
width:100%;
border-left:0px none;
border-right:0px none;
}
.x-horizontal-menubar > .x-menu-list > .x-menu-list-item {
text-decoration:none;
padding-left:0px;
padding-right:10px;
margin-left:10px;
float:left;
background-image:none
}
.x-horizontal-menubar > .x-menu-list > .x-menu-list-item.x-menu-item-active {
text-decoration:none;
padding-left:0px;
padding-right:10px;
margin-left:10px;
float:left;
background-image:none;
border:0px none;
}
.x-horizontal-menubar > .x-menu-list > .x-menu-list-item > .x-menu-item-arrow {
background: transparent url(../../resources/images/default/menu/menubar-parent.gif) no-repeat scroll right 0.6em;
padding-right:15px;
}
.x-menubar > .x-menu-list > .x-menu-list-item > .x-menu-item > .x-menu-item-icon {
display:none;
}
</style>
<style type="text/css">
* {
font-family: arial, helvetica, sans-serif;
font-size:small;
color:rgb(102, 102, 102);
}
div#page-title-container {
height:40px;
}
div#page-titlebar {
float:left;
color:white;
font-family:arial;
font-size:30px;
font-weight:300;
padding:2px 0px 0px 2px;
text-align:left;
}
div#page-toolbar {
float:right;
margin-right:5px;
margin-top:7px;
}
div#aspicio-menu-bar {
height:25px;
}
#menu-container {
height:500px;
width:400px;
overflow:auto;
}
#component-container {
height:500px;
width:400px;
overflow:auto;
white-space:nowrap;
}
.app-component {
cursor:pointer;
background-color:lightblue;
border-bottom:1px groove;
}
.component-selected {
background-color:#000070!important;
color:white;
}
.error {
color: red;
font-weight:bold
}
</style>
<title>Menu maintenance</title>
</head>
<body class="x-box-blue">
<div id="page-header">
<div id="page-title-container" class="x-layout-panel-hd">
<div id="page-titlebar">Menu maintenance</div>
<div id="page-toolbar"></div>
</div>
<div id="aspicio-menu-bar"></div>
</div>
<div id="page-leftnav"></div>
<div id="page-content">
<div style="padding:10px">
<div style="float:left;margin-right:10px">
<div id="menu-container"></div>
</div>
<div style="float:left">
<div id="component-container"></div>
</div>
<form id="menuForm" name="menuForm" style="padding-top:10px;clear:both" method="POST" >
<input type="hidden" name="menuId" value="1"></input>
<input type="hidden" name="updateXML"></input>
<input type="submit" value="Update"></input>
</form>
</div>
</div>
<div id="page-message"></div>
</body>
</html>
Powered by vBulletin® Version 4.1.5 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.