Menus
NodeTreeMenu
You can add nodeTreeMenu using this option:nodeTreeMenu: true,Example:
FamilyTree JS has these menus
- menu - top right corner
- nodeMenu - a button in the node
- nodeContextMenu - context menu for none
Here is how to add a menu in the FamilyTree configuration:
nodeMenu: { details: { text: "Details" }, edit: { text: "Edit" }, add: { text: "Add" }, remove: { text: "Remove" } },The demo bellow demonstrates how to define, menu, nodeMenu and nodeContextMenu in the FamilyTree configuration:
Predefined menus items
- edit - calls editUI.show method
- details - calls editUI.show method
- svg - calls exportSVG method
- pdf - calls exportPDF method
- png - calls exportPNG method
- csv - calls exportCSV method
nodeContextMenu: { edit: { text: "Edit", icon: FamilyTree.icon.edit(18, 18, '#039BE5') }, },
Add your own menu item to the node menu with Icon, Click event and Text
The icon can be image html element (img) or svg element:
let webcallMeIcon = <svg width="24" height="24" viewBox="0 0 300 400"><g transform="matrix... // the svg code is in the example below
nodeMenu: { call: { icon: webcallMeIcon, text: "Call now", onClick: callHandler } },
callHandler function has one parameter nodeId.
function callHandler(nodeId) { let nodeData = family.get(nodeId); let employeeName = nodeData["name"]; window.open('https://webcall.me/' + employeeName, employeeName, 'width=340px, height=670px, top=50px, left=50px'); }
Here is an example:
Override node menu items for specific node using tags
You can override node menu items by tagging a node
If you have this in nodeMenu option:pdf: { text: "Export To Pdf", }To ovverride the menu for some nodes, add a tag in tags option:
overrideMenu:{ nodeMenu:{ edit: {text: "Edit" } } }Then add the same tag in that nodes:
{ id: 2, pid: 1, tags: ["overrideMenu"] }
In the example below the node menu items for father and mother nodes will be different form node menus on children nodes:
Override node menu items for specific node using on show event
The methods should be added before family.load()family.nodeMenuUI.on('show', function(sender, args){ args.menu = { myMenuItem: { text: "My Text", icon: FamilyTree.icon.add(16,16,"#ccc"), onClick: function(id) {alert(id)} } } }); family.menuUI.on('show', function(sender, args){ args.menu = { myMenuItem: { text: "My Text", icon: FamilyTree.icon.add(16,16,"#ccc"), onClick: function(id) {alert(id)} } } }); family.nodeContextMenuUI.on('show', function(sender, args){ args.menu = { myMenuItem: { text: "My Text", icon: FamilyTree.icon.add(16,16,"#ccc"), onClick: function(id) {alert(id)} } } });Example:
Node Circle Menu
To add a Node Circle Menu:
-
First you need to define nodeCircleMenu for your template:
FamilyTree.templates.tommy.nodeCircleMenuButton = FamilyTree.templates.tommy_female.nodeCircleMenuButton = FamilyTree.templates.tommy_male.nodeCircleMenuButton = { radius: 25, x: 230, y: 60, color: '#fff', stroke: '#aeaeae' };
-
Then you need to add nodeCircleMenu in the family configuration:
nodeCircleMenu: { PDFProfile: { icon: FamilyTree.icon.pdf(30, 30, '#aeaeae'), text: "PDF Profile", color: "white" }, editNode: { icon: FamilyTree.icon.edit(30, 30, '#aeaeae'), text: "Edit node", color: "white" }, addClink: { icon: FamilyTree.icon.link(30, 30, '#aeaeae'), text: "Add C link", color: '#fff', draggable: true }, pet: { icon: FamilyTree.icon.teddy(30, 30, '#aeaeae'), text: "Add pet", color: "white" } }
-
You can use the show event to add menu item conditionaly:
family.nodeCircleMenuUI.on('show', function (sender, args) { var node = family.getNode(args.nodeId); delete args.menu.father; delete args.menu.mother; delete args.menu.wife; delete args.menu.husband; if (FamilyTree.isNEU(node.mid)) { args.menu.mother = { icon: FamilyTree.icon.mother(30, 30, '#F57C00'), text: "Add mother", color: "white" }; } if (FamilyTree.isNEU(node.fid)) { args.menu.father = { icon: FamilyTree.icon.father(30, 30, '#039BE5'), text: "Add father", color: "white" }; } if (node.gender == 'male') { args.menu.wife = { icon: FamilyTree.icon.wife(30, 30, '#F57C00'), text: "Add wife", color: "white" }; } else if (node.gender == 'female') { args.menu.husband = { icon: FamilyTree.icon.husband(30, 30, '#F57C00'), text: "Add husband", color: "white" }; } else { args.menu.wife = { icon: FamilyTree.icon.wife(30, 30, '#F57C00'), text: "Add wife", color: "white" }; args.menu.husband = { icon: FamilyTree.icon.husband(30, 30, '#039BE5'), text: "Add husband", color: "white" }; } });
-
Use the click, drop, mouseenter or mouseout nodeCircleMenuUI events to create the node menu items functionality. Example:
family.nodeCircleMenuUI.on('click', function (sender, args) { let node = family.getNode(args.nodeId); switch (args.menuItemName) { case "husband": family.addPartnerNode({ gender: 'male', pids: [args.nodeId] }); break; case "wife": family.addPartnerNode({ gender: 'female', pids: [args.nodeId] }); break; case "pet": family.addPartnerNode({ gender: 'pet', pids: [args.nodeId] }); break; case "mother": let data = { gender: 'female' }; if (!FamilyTree.isNEU(node.fid)) { data.pids = [node.fid]; } family.addParentNode(args.nodeId, 'mid', data); break; case "father": let data = { gender: 'male' }; if (!FamilyTree.isNEU(node.mid)) { data.pids = [node.mid]; } family.addParentNode(args.nodeId, 'fid', data); break; case "PDFProfile": family.exportPDFProfile({ id: args.nodeId }); break; case "editNode": family.editUI.show(args.nodeId); break; default: }; });
family.nodeCircleMenuUI.on('drop', function (sender, args) { family.addClink(args.from, args.to).draw(FamilyTree.action.update); });
family.nodeCircleMenuUI.on('mouseenter', function (sender, args) { if (args.menuItem.text == "Remove node") { var node = document.querySelector('[data-n-id="' + args.from + '"]'); node.style.opacity = 0.5; } });
family.nodeCircleMenuUI.on('mouseout', function (sender, args) { var node = document.querySelector('[data-n-id="' + args.from + '"]'); node.style.opacity = 1; });