How to implement drag and connect feature provided by Rappid with pure JointJS? - jointjs

There is a feature in Rappid (the paid version of JointJS) which allows you to drag a button from the toolbox of an element and connect that element to another element where you release your mouse button.
I want to implement this feature with JointJS core library. I've managed to create a tool box with elementTools and added two buttons, one for removing the element and one for this drag and connect feature.
The Picture of element with element toolbox
The problem is the button for drag fires only when I click on the button. It doesn't allow me to drag and have x, y coordinates of the mouse.
There is a similar question which was left unanswered in stackoverflow:
Creating a ToolElement for every object JointJS
Here is my snippet for the button:
const InfoButton = joint.elementTools.Button.extend({
name: 'info-button',
options: {
focusOpacity: 0.5,
distance: 60,
action: function (evt: JQueryEventObject, elementView, buttonView) {
// alert('View id: ' + this.id + '\n' + 'Model id: ' + this.model.id);
const link = new Models.SequenceFlow();
link.set('source', { id: elementView.model.get('id') });
link.set('target', new joint.g.Point(evt.pageX, evt.pageY));
// const alev = jQuery.Event()
// evt.preventDefault();
// paper.trigger('AliEvt', evt);
link.addTo(model);
// link.se(this.model);
// link.target(new joint.g.Point(0, 0));
},
markup: [
{
tagName: 'circle',
selector: 'button',
attributes: {
r: 7,
fill: '#001DFF',
cursor: 'pointer',
},
},
{
tagName: 'path',
selector: 'icon',
attributes: {
d: 'M -2 4 2 4 M 0 3 0 0 M -2 -1 1 -1 M -1 -4 1 -4',
fill: 'none',
stroke: '#FFFFFF',
'stroke-width': 2,
'pointer-events': 'none',
},
},
],
},
});
const infoButton = new InfoButton();
const toolsView = new joint.dia.ToolsView({
name: 'basic-tools',
tools: [removeButton, boundaryTool, infoButton],
});
Any help would be appreciated.

Related

Hyperlink on a Graphic element in ArcGis

i need your help please.
I would like to be able to click on a point added on an ArcGis map so that when I click on it I am redirected to another web page
I have been following the tutorials:
https://developers.arcgis.com/javascript/latest/display-a-map/
Display a map
Add a point
add a feature layer
Display a popup
This is the code so far:
require([
"esri/config",
"esri/Map",
"esri/views/MapView",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/layers/FeatureLayer"
], function(esriConfig,Map, MapView, Graphic, GraphicsLayer, FeatureLayer) {
esriConfig.apiKey = "YOUR_KEY";
const map = new Map({
basemap: "arcgis-topographic"
});
const view = new MapView({
container: "DivCarte",
map: map,
center: [-83.54500,19.02700],
zoom: 6
});
const graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);
const point = { //Create a point
type: "point",
longitude: -86.900000,
latitude: 21.201278
};
const simpleMarkerSymbol = {
type: "simple-marker",
color: [226, 119, 40], // Orange
outline: {
color: [255, 255, 255], // White
width: 1
}
};
const popupTemplate = {
title: "Cancun",
content: "<a href=http://travelwithnico.com>Site</a>"
}
const attributes = {
Name: "AttGraphic",
Description: "Ilalala"
}
const pointGraphic = new Graphic({
geometry: point,
symbol: simpleMarkerSymbol,
attributes: attributes,
popupTemplate: popupTemplate
});
graphicsLayer.add(pointGraphic);
I managed to open a popup showing the link but it opens on a new tab.
How can I force it to move to the link in the same window?
Thank you for your help.
Nico
Have you tried inlining a JavaScript inside an onclick event? Something like this:
...
content: 'Site'
...
I'm not sure if this will work, but it worths trying.

OWL 2.2.0 Is it possible to see only the item active center and hide slides before and after?

2.0 and I would like to see only one slide which is the class: "owl-item active center"
Could you help me?
thank you and have a good day
jQuery script :
var owl = $('.owl-carousel');
$(".owl-carousel").each(function(index, el) {
var containerHeight = $(el).height();
$(el).find("img").each(function (index, img) {
var w = $(img).prop('naturalWidth');
var h = $(img).prop('naturalHeight');
$(img).css({
'width': Math.round(containerHeight * w / h) + 'px',
'height': containerHeight + 'px'
});
})
});
// Carousel initialization
owl.owlCarousel({
center: true,
loop:false,
margin:0,
singleItem:true,
autoWidth: true,
navSpeed:500,
nav:true,
autoplay: false,
rewind: true,
items:1
});**strong text**
enter image description here

Saving layer from OpenLayer 3 Map created by user

I'm trying to correctly save an OpenLayer 3 Map layer created by a user in order to display it another map using geoJSON, but I'm having troubles with this.
On the client side I save the dinamic layer in this function:
function addInteractions() {
draw = new ol.interaction.Draw({
source: source,
type: typeSelect.value
});
draw.on("drawend", function(e) {
var f = e.feature;
features.push(f);
geoJson = format.writeFeatures(features);
console.log(geoJson);
document.getElementById('js-textarea').value = geoJson;
});
map.addInteraction(draw);
snap = new ol.interaction.Snap({source: source});
map.addInteraction(snap);
}
Then the geoJSON object is saved into a .json file, but when I try to display it, it doesn't appear on the map.
Here his my display function:
var geoDataUrl = '/data/' + '{{percorso._id}}' + '.json';
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: geoDataUrl,
format: new ol.format.GeoJSON()
}),
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var map = new ol.Map({
layers: [raster, vectorLayer],
target: 'map',
view: new ol.View({
center: {{#if percorso.mapCenter}}[{{percorso.mapCenter}}] {{else}} ol.proj.transform([9.688053, 45.362760], 'EPSG:4326', 'EPSG:3857'){{/if}},
zoom: {{#if percorso.zoomLevel}}{{percorso.zoomLevel}} {{else}} 13{{/if}}
})
});
I also tested the display function with other layers (for example the provided one on the OpenLayer examples website ) and it works fine
On the server side I save the geoJSONobject with this function, where oggetto_mappa is the dinamic geoJSON object:
var jsonMappa = JSON.stringify(eval("(" + oggetto_mappa + ")"));
require("fs").writeFile("./public/data/" + id_perc + ".json", jsonMappa, 'utf8', function(f_err) {
if(f_err)
console.log(f_err);
});
For refernce this is what my function saves onto the .json file:
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"id" : "aa",
"geometry":
{
"type":"LineString",
"coordinates":[
[1073328.751180445,5680150.227413875],
[1077857.6451063417,5682481.556776573],
[1070385.9255914658,5679156.546046168],
[1076825.7452244917,5680226.66444216],
[1073328.751180445,5680169.336670946]
]
},
"properties":null
},
{
"type":"Feature",
"id" : "ab",
"geometry":
{
"type":"LineString",
"coordinates":[
[1073328.751180445,5680169.336670946],
[1071628.0273010998,5677130.96479661]
]
},
"properties":null}
]
}
To get things working, replace
geoJson = format.writeFeatures(features)
with
geoJson = format.writeFeatures(features, {featureProjection: 'EPSG:3857'})
You may wonder why?
When you draw in OpenLayers, you are drawing in the projection of the map (the default is EPSG:3857) whereas when you consume a GeoJSON the expected projection is EPSG:4326.
See the API documentation from ol.format.GeoJSON writeFeatures to understand better
Some additional informations:
when you consume the GeoJSON from your drawing as the coordinates are not in decimal degrees (EPSG:4326) but in meters (EPSG:3857)
the order of magnitude for coordinates is different (millions for EPSG:3857 and less than some hundred for EPSG:4326) without accounting for the positive/negative coordinates

Graph search for element by element's name in jointJS

I have a problem in Rappid/jointJS
I have in stencil.js 4 shapes(2 basic.Circle and 2 basic.Rect) with names START(basic.Circle), END(basic.Circle), Activity(basic.Rect) and Workitem( basic.Rect) and I want in my main.js from all my graph to get the basic shape with name(I mean with attrs text ) "Activity".
This is the Stencil description for "Activity" :
new joint.shapes.basic.Rect({ size: { width: 5, height: 3 },
attrs: {
rect: {
rx: 2, ry: 2, width: 50, height: 30,
fill: '#0000FF'
},
text: { text: 'Activity', fill: '#ffffff', 'font-size': 10,
stroke: '#000000', 'stroke-width': 0 }
}
}),
How wil I get it? The only way I can search in my graph so far is if a cell has type basic.Circle(use of get('type') === 'basic.Circle')). but with type Circle I have two items:Activity and Workitem.
Is it so difficult to search for the graph element with name : "Activity"?
Thank you in advance
You can obtain all the elements (except for links) from following method
var allElement = graph.getElements()
Next if you want to obtain elements with 'Activity' do as follows
var activityElements = [];
allElement.forEach(elem => {
var textVal = elem.attributes.attrs.text.text;
if(textVal !== undefined && textVal === 'Activity') {
activityElements.push(elem);
}
});
Now the activityElements array will contain all the elements you require.
I solved my problem by taking element data in JSON format:
_.each(this.graph.getElements(), function(element) {
if(element.attributes.attrs["text"]["text"] == "Activity"){
//alert("YEAHHHHHH");
}
});
you could use the api on element as well, element.attr('text') returns the text object from the shape: { text: 'Activity', fill: '#ffffff', 'font-size': 10,
stroke: '#000000', 'stroke-width': 0 }
You could also set an "id" attribute to your shape and use graph.getCell('id_name_goes_here'); which would be much simpler if you didn't mind adding an id field to each shape.

How to differentiate between node click and hyperlink text click on element in jointjs

var el1 = new joint.shapes.custom.ElementLink({
position: { x: 80, y: 80 },
size: { width: 170, height: 100 },
attrs: {
rect: { fill: '#E67E22', stroke: '#D35400', 'stroke-width': 5 },
a: { 'xlink:href': 'http://jointjs.com', 'xlink:show': 'new', cursor: 'pointer' },
text: { text: 'Element as a link:\nhttp://jointjs.com', fill: 'white' }
}
});
I want a handler for anchor tag where I can call any event from my viewmodel
It depends what you want exactly. If you're using the joint.shapes.custom.ElementLink from this tutorial: http://jointjs.com/tutorial/hyperlinks, then this shape is defined so that it is totally wrapped in the <a> anchor tag and so clicking anywhere inside the element will follow the link. However, you can catch the click event and, for example, based on the target of the event or some other condition decide whether you want to follow the link or do other things:
paper.on('cell:pointerclick', function(cellView, evt, x, y) {
// evt.target contains the SVG subelement that was the target of the click
// cellView is the view for the joint.shapes.custom.ElementLink cell model
// cellView.model is the cell model
if (someCondition) {
// This is how you can prevent the default browser action which is
// following the <a> link.
evt.preventDefault();
}
})

Resources