Is there any way to associate a custom contextMenu to a contentList widget(the widget used to display search results)?
IBM Content Navigator uses RowContextMenu as the JavaScript that is used on a Contentlist.
ecm.widget.listView.gridModules.RowContextMenu
#class This module displays the context menu when the user right clicks or hits Shift F10. It also provides default action capability.
You can extend this class, creating a custom menu.
Then define it within your custom class :
define(["dojo/_base/declare", ..., "myPlugin/myCustomRowContextMenu",...],
function(declare...,RowContextMenu,...) {
return declare("myPlugin.myCustomPane", [
ContentPane]...
Then use it :
_getContentListGridExtensionModules: function() {
var modules = [];
modules.push(RowContextMenu);
return modules;
},
Related
I'm working in Kotlin with the TornadoFX library. Imagine you have a toolbar which shows the tool that are useful for the current view you have. So we have a MainController which has a subController property which is the controller of some view next to the tool bar. So if our subController changes, the view should update. Also, if any property (e.g. selectedTool, tools) of the subController changes, the toolbar should update accordingly. Momentarily, the toolbar is not updated.
class ToolBar : View("Tool bar") {
private val controller: MainController by inject()
override val root = vbox {
tilepane {
for (tool in controller.subController.tools) {
button(tool.name, group).action {
controller.subController.changeTool(tool) // changes selected tool
}
}
}
this += controller.subController.selectedTool.options
}
}
Extra info: subController.tools is an ArrayList and subController.selectedTool is a Tool.
Now my question is, what's the recommended way to do this in TornadoFX?
You have several options. A Parent supports a function called bindChildren which accepts an observable list of items and a function to turn each of these items into a Node. You can use this to create your buttons in the toolbar:
tilepane {
bindChildren(controller.subController.tools) { tool ->
Button(tool.name) ...
}
}
You can also do this manually if you need more control:
tilepane {
controller.subController.tools.onChange {
children.clear()
// create new buttons here, like in your example
}
}
However, instead of injecting controller to access subController to get to the tools, you should have a ToolsModel which is injected into the current scope. The tools model could have a list of tools and the selected tools and can be injected into all views and controllers which needs it. You say that selectedTool is a Tool, but you're not showing what a Tool is, but judging from your code it looks like Tool.options is a Node subclass (?).
You can add/remove the tool.options element using the same technique, or even wrap it in a stackpane or other layoutcontainer to be able to identify the tool to remove (or simply remove all children of the stackpane) on change using the same technique.
I've got two editable feature layers in my application, and I'm trying to attach the appropriate attribute inspector depending on which feature layer my user is trying to edit.
I create the Attribute Inspectors for both feature layers when my application loads and then attach the appropriate attribute inspector to the map's InfoWindow when the user is trying to edit a feature layer.
All works well, until the user tries to edit another feature layer. When I try and attach a different attribute inspector to the infowindow, it just comes up blank.
Here's roughly what I'm doing:
// AttributeEditor1 for FeatureLayer1 in Class1
constructor: function(options) {
this.options = lang.mixin(this.options, options);
this.map = options.map;
this.configureAttributeEditor1();
},
configureAttributeEditor1: function() {
this.attributeEditor1 = new AttributeInspector({
layerInfos: layerInfos
}, domConstruct.create("div"));
// here I add a Save and Delete button and various event handlers
this.attributeEditor1.startup();
},
// I call this when I know that the user wants to edit FeatureLayer 1
attachEditor1: function() {
this.map.infoWindow.setContent(this.attributeEditor1.domNode);
this.map.infoWindow.resize(350, 240);
},
// AttributeEditor2 for FeatureLayer2 in Class2
constructor: function(options) {
this.options = lang.mixin(this.options, options);
this.map = options.map;
this.configureAttributeEditor2();
},
configureAttributeEditor2: function() {
this.attributeEditor2 = new AttributeInspector({
layerInfos: layerInfos
}, domConstruct.create("div"));
// here I add a Save and Delete button and various event handlers
this.attributeEditor2.startup();
},
// I call this when I know that the user wants to edit FeatureLayer 2
attachEditor2: function() {
this.map.infoWindow.setContent(this.attributeEditor2.domNode);
this.map.infoWindow.resize(350, 240);
},
Thanks in advance.
When you update the content of infoWindow using map.infoWindow.setContent, it destroys the previous content and then updated the new content. So basically your AttributeInspector1 will be destroyed when you updated the info window with AttributeInspector2.
You need not create multiple AttributeInspector, while working on multiple FeatureLayer. The layerInfos property is an array type, you could set upd multiple layers.
But, I guess you have different needs/actions to be taken when you switch between layers. The best thing you could do is to either create new AttributeInspector every time you switch, or just update the layerInfos and save and delete events. Make sure you remove the previous save and delete event handles.
I want to add Amchart charts in ExtJS Panel How can I do this?
see below Amchart code
How to add this designed chart on ExtJS Panel
var columnChartData = [
{
"name": "John",
"points": 35654,
"color": "#7F8DA9",
"bullet": "images/0.gif"
}
];
var chart = new AmCharts.AmSerialChart();
chart.dataProvider = columnChartData;
chart.categoryField = "name";
chart.startDuration = 1;
// WRITE
chart.write("example-grid");
//Write this chart on Extjs Panel
add( component ) :
Adds Component(s) to this Container.
Description:
•Fires the beforeadd event before adding.
•The Container's default config values will be applied accordingly (see defaults for details).
•Fires the add event after the component has been added.
Notes:
If the Container is already rendered when add is called, it will render the newly added Component into its content area.
If the Container was configured with a size-managing layout manager, the Container will recalculate its internal layout at this time too.
Note that the default layout manager simply renders child Components sequentially into the content area and thereafter performs no sizing.
If adding multiple new child Components, pass them as an array to the add method, so that only one layout recalculation is performed.
tb = new Ext.toolbar.Toolbar({
renderTo: document.body
}); // toolbar is rendered
// add multiple items.
// (defaultType for Toolbar is 'button')
tb.add([{text:'Button 1'}, {text:'Button 2'}]);
To inject components between existing ones, use the insert method.
to do a dinamic load of new views use .add(component) on your panel.
maybe you should do a panel.refresh() if the new component is added but not shown
I'm using Dojo and would like to create a tree like structure. However, I'd like to be able to display content within the tree once the end node in a particular branch has been expanded. e.g.
top
- a branch
-- last item in this branch
[some content such as a div, span, image etc]
-- another item in this branch
[some more content]
etc
Does anyone know if this can be achieved using dijit Tree and if so, any pointers?
After digging around in the docs I've found a way to do this. It's not simple so thought I'd share. This page has an example of how to display a tree node with a rich text label rather than just text. This involves declaring your own class that inherits from Tree._TreeNode, allowing you to control it's creation. This same technique can be used.
When creating a Tree, I override the _createTreeNode function as follows:
_createTreeNode: function (args) {
if (args.item.type === "content") {
return new LayerManagerContentNode(args);
} else {
return new Tree._TreeNode(args);
}
}
In my store I add an object to represent the content that I want to display inline and give it a type of 'content'.
I create a class that inherits from Tree._TreeNode as follows:
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/dom",
"dojo/dom-construct",
"dojo/on",
"dijit/form/Button",
"dijit/Tree"
], function (declare, lang, dom, domConstruct, on, Button, Tree) {
return declare("my/ui/platforms/desktop/parts/LayerManagerContentNode", [Tree._TreeNode], {
// summary:
// ...
constructor: function () {
},
postCreate: function () {
var button = new Button({
label: "Test"
});
this.domNode.innerHTML = "<div></div>";
this.domNode.innterText = "";
button.placeAt(this.domNode, "first");
}
});
});
in the postCreate, I create a button (this was just for testing, I'll probable create a content pane or something to further populate) to be displayed in place of the usual tree node. I then replace the tree nodes innerHTML and innerText to hide what would normally be displayed, en voila, it works!
I dare say there are better ways to do this so if anyone comes along and has one, please add it.
This is how I create the dropdown menu with checkboxes using dijit.
layerList.reverse();
var menu = new dijit.Menu({
id : 'layerMenu'
});
dojo.forEach(layerList, function(layer) {
menu.addChild(new dijit.CheckedMenuItem({
label : layer.title,
id : layer.title.replace(" ",""),
checked : layer.visible,
onChange : function(evt) {
if (layer.layer.featureCollection) {
//turn off all the layers in the feature collection even
//though only the main layer is listed in the layer list
dojo.forEach(layer.layer.featureCollection.layers, function(layer) {
layer.layerObject.setVisibility(!layer.layerObject.visible);
});
} else {
layer.layer.setVisibility(!layer.layer.visible);
}
}
}));
});
var button = new dijit.form.DropDownButton({
label : i18n.tools.layers.label,
id : "layerBtn",
iconClass : "esriLayerIcon",
title : i18n.tools.layers.title,
dropDown : menu
});
dojo.byId('webmap-toolbar-center').appendChild(button.domNode);
I can access the individual dijit.CheckedMenuItem at runtime when the onChange event fired because I know their id. Since dijit does not has a RadioButton for MenuItem, is there a way I can change the checked status in runtime. Using "this.Id" and "evt", I can know which one is being check/uncheck by the user. Technically I can try to uncheck the other checked items if necessary to simulate the radio button behavior.
Can someone tell me how I can check/uncheck dijit.CheckedMenuItem in runtime? What properties and functions I need to call?
You should be able to just set checked to false on the other CheckedMenuItem widgets
checkedMenuItemWidget.set('checked',false)
To uncheck any given checkedMenuItem.