How to get the text of an editable TextBlock in GoJS?
I'm not sure what you're asking. The literal answer to your question is that you can get the text string from any TextBlock by getting its TextBlock.text property value.
But you mention that the TextBlock is editable, so maybe you are asking about how to get the previous value of the TextBlock.text during editing.
First, the validation predicate is given both the original string as well as the new proposed string: the TextBlock.textValidation and TextEditingTool.textValidation properties and the TextEditingTool.isValidText method.
Second, the "TextEdited" DiagramEvent gets the original string value as the DiagramEvent.parameter: DiagramEvent
Add this to your diagram's nodeTemplate. This helps.
$(go.TextBlock, {
editable: true
})
myDiagram.nodeTemplate =
$(go.Node, "Horizontal", {
isTreeExpanded: false,
click: showDetail
},
$(go.Panel, "Auto",
$(go.Shape, "RoundedRectangle", {
fill: "#cce6ff", // the default fill, if there is no data-binding
stroke: "#6699ff",
height: 40,
strokeWidth: 2,
portId: "",
cursor: "pointer", // the Shape is the port, not the whole Node
}, new go.Binding("fill", "fill")),
$(go.TextBlock, {
editable: true
},
new go.Binding("text", "text"))
),
$("TreeExpanderButton", { alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Top }, { visible: true })
);
If you want to trigger edit textblock use below cade
var textBlock = myDiagram.findNodeForKey(nodekey).findObject('TextBlockName');
if (myDiagram.commandHandler.canEditTextBlock(textBlock))
myDiagram.commandHandler.editTextBlock(textBlock);
Related
Im learning sample code from gojs/logic circuit, in that i want to add more ports to logic gates dynamically through context menu or some button, can i do it, i saw dynamic ports example in gojs, but its not working for logic gates, its only working for rectangular box created in that example(dynamic ports), but i want to add more input and out ports to logic gates which are predefined, is that possible ? Im able to add manually by increasing in and out numbers manually in the code(js), but not dynamically, i also want to know is it possible to add 'n' number of ports to predefined logic gates ?
The node templates in the Logic Circuit sample each have a fixed number of ports. For example:
var andTemplate =
$(go.Node, "Spot", nodeStyle(),
$(go.Shape, "AndGate", shapeStyle()),
$(go.Shape, "Rectangle", portStyle(true),
{ portId: "in1", alignment: new go.Spot(0, 0.3) }),
$(go.Shape, "Rectangle", portStyle(true),
{ portId: "in2", alignment: new go.Spot(0, 0.7) }),
$(go.Shape, "Rectangle", portStyle(false),
{ portId: "out", alignment: new go.Spot(1, 0.5) })
);
It is possible to add or remove ports from a particular instance of a Node, but is that really what you want? Adding or removing an element (that happens to be a port) won't modify the model, so when you save and then re-load the model, those changes will have disappeared.
If you want a variable number of ports on a node, you need to define the node template to support a variable number of ports, where the node data object has one or more properties that are Arrays of port descriptor objects. Each port descriptor would have information about identifier, name, shape, color, position, and perhaps other parameters.
Then there would be one or more Panels whose Panel.itemArray is data bound to the corresponding Array property. The Panel.itemTemplate would declare how each item (i.e. port) is visualized. Please read: https://gojs.net/latest/intro/itemArrays.html
For an example of this with four item Arrays, one for each side of a Node, please examine this sample: https://gojs.net/latest/samples/dynamicPorts.html
That sample also demonstrates various ways in which the user can add or remove or move ports dynamically.
In that sample there is only a single node template, but it's more complex because it supports four separate Arrays of port descriptor objects, one for each side of the Node. That node template looks like:
myDiagram.nodeTemplate =
$(go.Node, "Table",
{
locationObjectName: "BODY",
locationSpot: go.Spot.Center,
selectionObjectName: "BODY",
contextMenu: nodeMenu
},
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
// the body
$(go.Panel, "Auto",
{
row: 1, column: 1, name: "BODY",
stretch: go.GraphObject.Fill
},
$(go.Shape, "Rectangle",
{
fill: "#dbf6cb", stroke: null, strokeWidth: 0,
minSize: new go.Size(60, 60)
}),
$(go.TextBlock,
{ margin: 10, textAlign: "center", font: "bold 14px Segoe UI,sans-serif", stroke: "#484848", editable: true },
new go.Binding("text", "name").makeTwoWay())
), // end Auto Panel body
// the Panel holding the left port elements, which are themselves Panels,
// created for each item in the itemArray, bound to data.leftArray
$(go.Panel, "Vertical",
new go.Binding("itemArray", "leftArray"),
{
row: 1, column: 0,
itemTemplate:
$(go.Panel,
{
_side: "left", // internal property to make it easier to tell which side it's on
fromSpot: go.Spot.Left, toSpot: go.Spot.Left,
fromLinkable: true, toLinkable: true, cursor: "pointer",
contextMenu: portMenu
},
new go.Binding("portId", "portId"),
$(go.Shape, "Rectangle",
{
stroke: null, strokeWidth: 0,
desiredSize: portSize,
margin: new go.Margin(1, 0)
},
new go.Binding("fill", "portColor"))
) // end itemTemplate
}
), // end Vertical Panel
... three more Panels with itemArray Bindings ...
This is the node template I'm working with:
$(go.Node, "Auto",
{
deletable: false,
selectionAdorned: false
},
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
$(go.Shape, "Terminator",
{
fill: "#f8da07", strokeWidth: 2, minSize: new go.Size(90, 40), portId: "", cursor: "pointer", stroke: '#000000', fromLinkable: true,
toLinkable: false, fromLinkableSelfNode: false, toLinkableSelfNode: false, fromLinkableDuplicates: false, toLinkableDuplicates: false, fromMaxLinks: 1
},
new go.Binding("figure"),
new go.Binding("fill", "color"),
new go.Binding("fill", "isSelected", function(sel) {
return sel ? "#e1e1e1" : [selfColor];
}).ofObject()),
{
click: (e, obj) => {
clickNode(e, obj);
}
},
$(go.TextBlock,
{
stroke: "#000000", margin: 4, editable: false, font: "bold 12pt sans-serif", isMultiline: true
},
new go.Binding("text").makeTwoWay())
);
You can see that the default color for the node is #f8da07, but it is actually being written by the node self color property with the line "new go.Binding("fill", "color")".
And as it is, I have no way of knowing which one is the current color code of the node being selected.
I want to be able to change the color of the node to "#e1e1e1" when I select it, but I also want it to change back to the old color when not - (which is NOT "#f8da07").
Is there a proper way to do this?
Any help will be appreciated! Thanks
$(go.Shape,
{ fill: "#f8da07" }, // default color
new go.Binding("fill", "color"),
new go.Binding("fill", "isSelected", function(sel, shape) {
return sel ? "#e1e1e1" : shape.part.data.color || "#f8da07";
}).ofObject()),
Hi I need to add number to each of ports as you see in the picture below.
Ps. How ever I looking for resolve the problem on this site https://gojs.net/latest/intro/ports.html and I check solution with portId and TextBlock but it doesn't work :/
You are using a Shape for a port, but any GoJS object can be a port, and you really want to use a Panel (Auto Panel) with a Shape and a TextBlock as your port.
I suggest you read: https://gojs.net/latest/intro/buildingObjects.html
Hi thank you for your Answer :) hmm I try to use a Panel but I don't see change :/ What I do wrong?
this.$(go.Panel, 'Horizontal',
new go.Binding('itemArray', 'bottomArray'),
{
row: 2, column: 1,
itemTemplate:
this.$(go.Panel, 'Vertical',
{
_side: 'bottom',
fromSpot: go.Spot.Bottom, toSpot: go.Spot.Bottom, fromMaxLinks: 1,
fromLinkable: true, toLinkable: false, cursor: 'pointer'
},
new go.Binding('portId', 'portId'),
this.$(go.Shape, 'RoundedRectangle',
{
stroke: null, strokeWidth: 0,
desiredSize: portSize,
margin: new go.Margin(2, 1, 0, 1)
},
new go.Binding('fill', 'portColor')),
this.$(go.TextBlock,
new go.Binding('text', 'name'))
)
}
),
I've been using jVectorMap quite successfully-- it's a wonderful package for displaying interactive maps!
In this case, I only want some regions to be selectable, and there doesn't seem to be an option to set regions active/inactive. So instead, I set "regionsSelectable=false", and then set "selectedRegions" to the ones I want active.
This works fine (showing the correct hover attributes, etc. for "active" regions only)-- with one exception, in iOS. There, it takes two "clicks" (touches) for the "onRegionClick" handler to get invoked. On the first click, the "selectedHover" attributes are set correctly, but "handleRegion" never gets called. A second click, and "handleRegion" is called.
Initialization code looks like:
map = new jvm.WorldMap({
container: $('#mapdiv'),
map: 'world_mill_en',
regionsSelectable: false,
regionStyle: {
initial: { fill: '#0086d0' },
hover: { "fill-opacity": 1.0 },
selected: { fill: '#003a6a' },
selectedHover: { fill: '#ff7a00' }
},
onRegionClick: handleRegion,
selectedRegions:["CN","RU","US"],
...
});
function handleRegion(e,cc) {
alert("cc="+cc);
...
}
What is needed is either a way to "activate" only a few regions, or a way around this two-click problem.
I know this is a bit outdated question, but here is a hack around iOS issue for others like me who bumped to this question while searching for some hack around this.
As you already noted, iPad/iPhone are emulating hover with first "tap" .. and click with second "tap".
So to fix this ackward behavior we will do following (example on fiddle)
var lastCode = "";
var iOS = /(iPad|iPhone|iPod)/g.test( navigator.userAgent );
$('#world-map').vectorMap({
map: 'world_mill_en',
backgroundColor: 'green',
normalizeFunction: 'polynomial',
regionsSelectable: true,
regionsSelectableOne: true,
zoomOnScroll: true,
zoomButtons: true,
regionStyle: {
initial: {
fill: "white",
"fill-opacity": 1,
stroke: "none",
"stroke-width": 0,
"stroke-opacity": 1
},
hover: {
fill: "white",
"fill-opacity": 1
},
selected: {
fill: "#EC6602",
"fill-opacity": 1
},
selectedHover: {
fill: "#EC6602",
"fill-opacity": 1
}
},
onRegionClick: function(e, country){
if (lastCode && lastCode == country) {
e.preventDefault();
return;
}
var map = $("#world-map").vectorMap("get", "mapObject");
$("#world-map").vectorMap("set", "focus", country);
map.setScale(2);
if(country=="US" || country=="RU") {
map.setScale(1);
}
lastCode = country;
},
onRegionLabelShow: function (e, el, country) {
if (iOS) {
e.preventDefault();
var map = $("#world-map").vectorMap("get", "mapObject");
if (lastCode) {
map.regions[lastCode].element.setSelected(false);
}
map.regions[country].element.setSelected(true);
$("#world-map").vectorMap("set", "focus", country);
map.setScale(2);
if(country=="US" || country=="RU") {
map.setScale(1);
}
lastCode = country;
}
},
markers: [{
latLng: [37.7833, -122.4167],
name: 'San Francisco'
}]
});
In short words, we are overwriting onRegionLabelShow functionality with custom behavior (only for the iOS devices). Basically we are preventing the tooltip from showing and instead of that we are selecting the hovered (tapped) ccountry, focusing it and storing it's code in global variable.
On second tap we are detecting if the country has changed by comparing current code with last value and in that case un-selecting previously selected country and selecting new one.
It should be fairly easy to adapt the resolution to your needs.
actually, you should check onRegionTipShow:
...
handleIOSClick = function (e, el, code) {
if (istouch) {
var mapObject = $(map).vectorMap('get', 'mapObject');
map.regions[code].element.setSelected(true);
e.preventDefault();
}
},
CreateMap = function () {
if (typeof $(map) !== 'undefined'){
$(map).width(700);
$(map).height(400);
mapObject = $(map).vectorMap({
map: 'us_lcc_en',
onRegionClick: regionClicked,
onRegionTipShow: handleIOSClick,
backgroundColor: "inherit",
regionStyle: {
initial: {
fill: '#477294'
}
}
});
}
},
...
I have a QTip assigned to an element as follows:
$('#myDiv').qtip({
show: { when: { event: 'click', } },
hide: { when: { event: 'unfocus' } },
style: {
border: {
width: 5,
radius: 10
},
padding: 10,
textAlign: 'center',
tip: true, // Give it a speech bubble tip with automatic corner detection
name: 'red' // Style it according to the preset 'cream' style
},
position: {
corner: {
tooltip: 'topMiddle', // Use the corner...
target: 'bottomMiddle' // ...and opposite corner
}
},
content: {
text: self.parent('.qtip').html(),
title: { text: 'My Title' }
},
});
Under 'text' in 'content', I am trying to access the innerHTML of the element that triggered this QTip to appear after being clicked on.
However, my current means of self.parent('.qtip').html(), as displayed above, is not working.
What is the standard way to do this? Thanks.
I later found the solution to this question.
To access properties of the element that triggered the QTip, one must structure the code in this way:
$("#container a").each(function() {
$(this).qtip({ // QTip code });
});
That way, one can use $(this) to access data such as innerHTML of the element that triggered the QTip.
Maybe you could set it before:
var text = $('#myDiv').text();
And use it inside the object:
text: text,