jsPlumb connecting custom overlays - endpoint not moved - jsplumb

I am creating custom overlays for my connections in jsPlumb.
connectorOverlays: [
["Custom", {
create: function(component) {
return connectionNode();
},
location:0.5,
id:"customOverlay"
}]
]
connectionNode() creates a div with a select list in it. The divs themselves should be connectable, i.e., I want to connect two labels of different connectors.
var overlay_div = $(connection.overlays[0].canvas);
jsPlumb.addEndpoint(overlay_div, { anchor:[ "Perimeter", { shape:"Rectangle"}] }, relationEndpoint);
Enpoint on the connector overlay is defined as such:
var relationEndpoint = {
endpoint:["Dot", {radius:4} ],
anchor: ["BottomRight","TopLeft", "TopRight", "BottomLeft"],
paintStyle:{ fillStyle:"#ff33333", opacity:0.5 },
isSource:true,
connectorStyle:{ strokeStyle:"#ff33333", lineWidth:3 },
connector : "Flowchart",
isTarget:true,
dropOptions : {
tolerance:"touch",
hoverClass:"dropHover",
activeClass:"dragActive"
},
beforeDetach:function(conn) {
return confirm("Detach connection?");
}
};
When I now move any of the original nodes that are connected by the connection with the custom overlay, the endpoint is not moved along with the label but remains static where it was created. Can I somehow trigger its movement programatically or am I missing some configuration option?

I had this problem too. I was able to fix it with
instance.draggable(jsPlumb.getSelector(".flowchart-demo .window"), { grid: [5, 5] });
where ".flowchart-demo .window" is the class of the div.
The example shown is from jplumb page examples... in my project this line stays
instance.draggable(jsPlumb.getSelector(".flowchart-demo .clsExecutando"), { grid: [5, 5] });
I hope this information helps you.

Related

Highstock dataGrouping not working with live data

I am currently working on a project for my company, where I need to plot highstock charts, which show energy-data of our main buildings.
Since it is live data, new datapoints come per Websocket every few-or-so seconds. However, the graph should only show one datapoint every hour. I wanted to clear this with the highstock dataGrouping, but it does not really work. It groups the points yes, but it still shows the „transmission“, the graph-line, between them. Thus making the whole graph completely irreadable.
In an other Version of the project, the graph only shows the latest datapoint of each group (as specified in the „approximate“ object in the chart options), but also does not start a new group after the chosen Interval runs through.
I've been sitting on this problem for about 3 days now and have not found any proper completely working solution yet.
Unfortunately, due company policy and due to hooks and components necessary, which are only used here in the company, I'm not able to give you a jsfilddle or similar, even though I'd really love to. What I can do is give you the config, mabye you find something wrong there?
const options = {
plotOptions: {
series: {
dataGrouping: {
anchor: 'end',
approximation: function (groupData: unknown[]) {
return groupData[groupData.length - 1];
},
enabled: true,
forced: true,
units: [['second', [15]]],
},
marker: {
enabled: false,
radius: 2.5,
},
pointInterval: minutesToMilliseconds(30),
pointStart: currentWeekTraversed?.[0]?.[0],
},
},
}
This would be the plotOptions.
If you need any more information, let me know. I'll see then, what and how I can send it to you.
Thank you for helping. ^^
This is example how dataGrouping works with live data,
try to recreate your case in addition or use another demo from official Highcharts React wrapper page.
rangeSelector: {
allButtonsEnabled: true,
buttons: [{
type: 'minute',
count: 15,
text: '15S',
preserveDataGrouping: true,
dataGrouping: {
forced: true,
units: [
['second', [15]]
]
}
}, {
type: 'hour',
count: 1,
text: '1M',
preserveDataGrouping: true,
dataGrouping: {
forced: true,
units: [
['minute', [1]]
]
}
}
},
Demo: https://jsfiddle.net/BlackLabel/sr3oLkvu/

How to modify just a property from a dexie store without deleting the rest?

I'm having the dexie stores showed in the print screen below:
Dexie stores print screen
My goal is to update a dexie field row from a store without losing the rest of the data.
For example: when I edit and save the field "com_name" from the second row (key={2}) I want to update "com_name" only and not lose the rest of the properties, see first and the third row.
I already tried with collection.modify and table.update but both deleted the rest of the properties when used the code below:
dexieDB.table('company').where('dexieKey').equals('{1}')
//USING table.update
//.update(dexieRecord.dexiekey, {
// company: {
// com_name: "TOP SERVE 2"
// }
//})
.modify(
{
company:
{
com_name: TOP SERVE 2
}
}
)
.then(function (updated) {
if (updated)
console.log("Success.");
else
console.log("Nothing was updated.");
})
.catch(function (err) { console.log(err); });
Any idea how can I accomplish that?
Thanks
Alex
You where right to use Table.update or Collection.modify. They should never delete other properties than the ones specified. Can you paste a jsitor.com or jsfiddle repro of that and someone may help you pinpoint why the code doesn't work as expected.
Now that you are saying I realised that company and contact stores are created dynamically and editedRecords store has the indexes explicitly declared therefore when update company or contact store, since dexie doesn't see the indexes will overwrite. I haven't tested it yet but I suspect this is the behaviour.
See the print screen below:
Dexie stores overview
Basically I have json raw data from db and in the browser I create the stores and stores data based on it, see code below:
function createDexieTables(jsonData) { //jsonData - array, is the json from db
const stores = {};
const editedRecordsTable = 'editedRecords';
jsonData.forEach((jsonPackage) => {
for (table in jsonPackage) {
if (_.find(dexieDB.tables, { 'name': table }) == undefined) {
stores[table] = 'dexieKey';
}
}
});
stores[editedRecordsTable] = 'dexieKey, table';
addDataToDexie(stores, jsonData);
}
function addDataToDexie(stores, jsonData) {
dbv1 = dexieDB.version(1);
if (jsonData.length > 0) {
dbv1.stores(stores);
jsonData.forEach((jsonPackage) => {
for (table in jsonPackage) {
jsonPackage[table].forEach((tableRow) => {
dexieDB.table(table).add(tableRow)
.then(function () {
console.log(tableRow, ' added to dexie db.');
})
.catch(function () {
console.log(tableRow, ' already exists.');
});
});
}
});
}
}
This is the json, which I convert to object and save to dexie in the value column and the key si "dexieKey":
[
{
"company": [
{
"dexieKey": "{1}",
"company": {
"com_pk": 1,
"com_name": "CloudFire",
"com_city": "Round Rock",
"serverLastEdit": [
{
"com_pk": "2021-06-02T11:30:24.774Z"
},
{
"com_name": "2021-06-02T11:30:24.774Z"
},
{
"com_city": "2021-06-02T11:30:24.774Z"
}
],
"userLastEdit": []
}
}
]
}
]
Any idea why indexes were not populated when generating them dynamically?
Given the JSON data, i understand what's going wrong.
Instead of passing the following to update():
{
company:
{
com_name: "TOP SERVE 2"
}
}
You probably meant to pass this:
{
"company.com_name": "TOP SERVE 2"
}
Another hint is to do the add within an rw transaction, or even better if you can use bulkAdd() instead to optimize the performance.

Placing Markers on Harp-GL globe

I try to build a globe with markers (like the markers on google maps) with HERE and harp.gl. These markers are SVG-Images and need to be loaded from their file.
They also need to be clickable with some metadata attached like an ID.
So my questions are:
what is the best way to display these markers?
how can I make them clickable? (raycasting?)
is there a way to attach some metadata?
thanks in advance!
Edit:
To clarify, the Markers are SVG-Images stored in SVG-Files which need to be loaded and displayed as Markers.
The Data is provided by an API and therefore I tried adding it as Point of it's own like the Cube-Example and also tried to translate it to GeoJSON and FeatureSets:
const geojsonPoints: {type: "FeatureCollection", features: Feature[]} = { type: "FeatureCollection",
features: [
]
};
for(let i = 0; i < locationdata.length; i++) {
geojsonPoints.features.push({
type: "Feature",
id: i.toString(),
geometry: {
type: "Point",
coordinates: [locationdata[i]["lonlat"][1], locationdata[i]["lonlat"][0]]
},
properties: locationdata[i]
})
}
const features: MapViewFeature[] = [];
for(let i = 0; i < locationdata.length; i++) {
features.push(new MapViewPointFeature([locationdata[i]["lonlat"][1], locationdata[i]["lonlat"][0]], locationdata[i]))
}
When I try adding a GeoJSON-Layer I get an error that the decoder.min.js couldn't be loaded but I configured it like that:
const mapView = new MapView({
canvas: this.canvas,
projection: sphereProjection,
theme: {
extends: pluginpath + "/js/harp.gl-example/dist/resources/berlin_tilezen_base_globe.json",
styles: {
geojson: this.getStyleSet()
}
},
decoderUrl: pluginpath + "/js/harp.gl-example/dist/decoder.bundle.js"
});
pluginpath is a variable containing prefix since the js-folder isn't directly in the root-directory like in all the examples.
To sum it all up:
I need to display the data provided by the API as markers. The markers should be the SVG-Images mentioned earlier and these markers should be clickable.
Edit 2:
I tried modifying this example to display the SVG-Markers.
The first step worked where I just displayed the cubes from the example at the needed locations, but I couldn't replace the cube with markers. I used these two documentations from three.js website but they didn't work for me:
https://threejs.org/docs/#examples/en/renderers/SVGRenderer
https://threejs.org/docs/#examples/en/loaders/SVGLoader
I didn't get any error the SVGs just didn't show up.
Just a quick note that in general, it's better to ask one question at a time. I'm going to focus on your first one about adding markers. Our tutorial has a section on adding markers, https://developer.here.com/tutorials/harpgl/#add-data. In the example, it assumes GeoJSON data. You didn't mention what kind of file you had so I don't know if it's GeoJSON or not.
I'd say - begin by describing what kind of file you have, how the data looks. Then look at the example I linked to in terms of adding markers. Then - share with us what you tried.
Loading SVGs directly is not supported but you could use base64 encoded svg images, e.g.:
const imageString =
"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIyLjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHdpZHRoPSI0OHB4IiBoZWlnaHQ9IjQ4cHgiIHZlcnNpb249IjEuMSIgaWQ9Imx1aS1pY29uLWRlc3RpbmF0aW9ucGluLW9uZGFyay1zb2xpZC1sYXJnZSIKCSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ4IDQ4IgoJIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDQ4IDQ4IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGc+Cgk8ZyBpZD0ibHVpLWljb24tZGVzdGluYXRpb25waW4tb25kYXJrLXNvbGlkLWxhcmdlLWJvdW5kaW5nLWJveCIgb3BhY2l0eT0iMCI+CgkJPHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTQ3LDF2NDZIMVYxSDQ3IE00OCwwSDB2NDhoNDhWMEw0OCwweiIvPgoJPC9nPgoJPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNmZmZmZmYiIGQ9Ik0yNCwyQzEzLjg3MDgsMiw1LjY2NjcsMTAuMTU4NCw1LjY2NjcsMjAuMjIzMwoJCWMwLDUuMDMyNSwyLjA1MzMsOS41ODg0LDUuMzcxNywxMi44ODgzTDI0LDQ2bDEyLjk2MTctMTIuODg4M2MzLjMxODMtMy4zLDUuMzcxNy03Ljg1NTgsNS4zNzE3LTEyLjg4ODMKCQlDNDIuMzMzMywxMC4xNTg0LDM0LjEyOTIsMiwyNCwyeiBNMjQsMjVjLTIuNzY1LDAtNS0yLjIzNS01LTVzMi4yMzUtNSw1LTVzNSwyLjIzNSw1LDVTMjYuNzY1LDI1LDI0LDI1eiIvPgo8L2c+Cjwvc3ZnPgo=";
This image can then be used in the style definition like this:
styles: {
geojson: [
{
when: ["==", ["geometry-type"], "Point"],
technique: "labeled-icon",
attr: {
text: ["get", "text"],
textMayOverlap: true,
size: 14,
imageTexture: "custom-icon",
screenHeight: 32,
iconScale: 0.5,
distanceScale: 1,
iconYOffset: 20
}
}
]
},
images: {
"custom-icon": {
url: imageString,
preload: true
}
},
imageTextures: [
{
name: "custom-icon",
image: "custom-icon"
}
]

KendoUI - Chart data labels

Is is possible to for the KendoUI Chart (Area) to have multiple data labels or even a concatenation of two? I need to display both a value and a percentage for each data point. Is this something that would need to be handled on the data source side or is it on the view?
Thanks for any help.
You can use templates to format both labels and tooltips; see labels.template and tooltip.template.
The key is to reference the Property you want using dataItem ex:
dataItem.TotalDollars
template: "${ category } - #= kendo.format('{0:C}', dataItem.TotalDollars)#"
The answer above wont really help unless you have a strong understanding of the Kendo UI framework. I was having a similar issue and before I found my answer I found this question. I circled back because the answer is simple and some simple example code is really simple. Lets save everyone some clicks.
DATA RESPONSE FROM REMOTE DATA (copy and past for local binding):
[
{
"ProgramName":"Amarr Garage Doors",
"PercentageShare":50.12,
"TotalDollars":5440.000000
},
{
"ProgramName":"Monarch Egress Thermal Hinge C",
"PercentageShare":4.64,
"TotalDollars":504.000000
},
{
"ProgramName":"Monarch Egress Window Wells",
"PercentageShare":15.73,
"TotalDollars":1707.000000
},
{
"ProgramName":"Monarch Premier V Egress Windo",
"PercentageShare":16.25,
"TotalDollars":1764.000000
},
{
"ProgramName":"Organized Living Shelftech Ven",
"PercentageShare":13.27,
"TotalDollars":1440.000000
}
]
**Chart Generation Code: **
function createChart() {
$("#SubmissionSummaryByProgramChart").kendoChart({
title: {
text: "Breakdown by Program"
},
legend: {
position: "right"
},
dataSource: {
transport: {
read: {
url: "GetFooData",
dataType: "json",
data: {
Year : 2014,
Quarter : 1,
}
}
}
},
series: [{
type: "pie",
field: "PercentageShare",
categoryField: "ProgramName"
}],
tooltip: {
visible: true,
template: "${ category } - #= kendo.format('{0:C}', dataItem.TotalDollars)#"
}
});
};
$(document).ready(createChart);

How to set a "blank" initial sort order for ng-grid

I have an angularjs application that uses an ng-grid. I need to be able to persist the sort order state of the grid even when the grid is repopulated.
The app uses a service that manages state, including the grid configuration, and this provides the persistence that I need:
//variable defined in service, and exposed via controller to grid
var gridConfig = {
data: 'withCandidate',
multiSelect: false,
selectedItems: [],
columnDefs: getAlternateColumnDefinition(),
rowTemplate: 'Templates/grids/WithCandidateCaseRow.html',
headerRowHeight: 20,
rowHeight: 20,
sortInfo: { fields: ["CaseNumber"], directions: [] }
};
<div class="gridStyle" ng-grid="gridConfig"></div>
The sort order is persisted by the sortInfo object supplied. This works fine. However, ideally I would like the grid to have no initial sort order, but still persist any selection made by the user. That means using an empty sortInfo object, but I can't find out how to configure it. I have tried the following, but all produce angular script errors.
sortInfo: null
sortInfo: { }
sortInfo: { fields: [], directions: [] }
sortInfo: { fields: [""], directions: [] }
sortInfo: { fields: [null], directions: [] }
Is this possible? How can I define a null sortInfo object?

Resources