I'm getting my instance like this:
jsp = jsPlumb.getInstance();
jsp.setContainer(_domnodeId);
jsp.ready(function(){
//doing some stuff - connecting boxes with arrows...
var conn2 = jsp.connect({
source: boxSST_IPMRS_COBRAIP.boxId,
target: boxCOBRA_IM.boxId
});
}
result:
in another function I'm doing the same:
jsp = jsPlumb.getInstance();
jsp.setContainer(_domnodeId);
jsp.ready(function(){
//var dynamicAnchor = [ [ 0.2,1,0.5 ], [ 0.2, 1, 0.5 ], "Top", "Bottom" ];
var common = {
anchor:[ "Continuous", { faces:["bottom","right"] }],
endpoint: "Blank",
connector:[ "Bezier", { curviness:50 }, common ],
overlays: [
["Arrow", {location:1, width:10, length:10}],
]
};
jsp.connect({
source: boxes.b1.boxId,
target: boxes.b2.boxId
}, common);
}
The arrows are all moving to the left,top corner...
var jsp is global and I cleared _domnodeId at the beginning of my second function. Any suggestions?
clearing my domnodeID:
function clean(container){
//remove everything
$("#" + container)
.children()
.not('nav')
.remove();
// box id counter
window.EvmClasses.chartBox.boxId = 0;
}
I cleared _domnodeId at the beginning of my second function
How did you done that? It seems to me that you didn't clear it properly.
Did you read "Removing" section of the manual?
If you have configured a DOM element with jsPlumb in any way you
should use jsPlumb to remove the element from the DOM (as opposed to
using something like jQuery's remove function, for example).
Please read it thoroughly. You may need either jsPlumb.empty, deleteEveryEndpoint, or reset.
Related
I have a simple block its element is dynamically added to DOM, I want the user to be able to create a block and it should be draggable using jsplumb library.
Unfortunately, now I can create element but their not draggable but if I add them manually to the dom, it's draggable.
Here is what I have so far
function addMovieButton() {
var newMovieBlockButton = $("<div class='movie-button w'>Button New<div class='ep' action='begin'></div><div>");
}
Here is plumb.js
jsPlumb.ready(function () {
// setup some defaults for jsPlumb.
var instance = jsPlumb.getInstance({
Endpoint: ["Dot", {radius: 5}],
Connector:"StateMachine",
HoverPaintStyle: {stroke: "#1e8151", strokeWidth: 2 },
ConnectionOverlays: [
[ "Arrow", {
location: 1,
id: "arrow",
length: 14,
foldback: 0.8
} ],
[ "Label", { label: "FOO", id: "label", cssClass: "aLabel" }]
],
Container: "canvas"
});
instance.registerConnectionType("basic", { anchor:"Continuous", connector:"StateMachine" });
window.jsp = instance;
var canvas = document.getElementById("canvas");
var windows = jsPlumb.getSelector(".statemachine-demo .w");
var windows_movie = jsPlumb.getSelector(".statemachine-demo .movie-block ");
// bind a click listener to each connection; the connection is deleted. you could of course
// just do this: jsPlumb.bind("click", jsPlumb.detach), but I wanted to make it clear what was
// happening.
instance.bind("click", function (c) {
instance.deleteConnection(c);
});
// bind a connection listener. note that the parameter passed to this function contains more than
// just the new connection - see the documentation for a full list of what is included in 'info'.
// this listener sets the connection's internal
// id as the label overlay's text.
instance.bind("connection", function (info) {
info.connection.getOverlay("label").setLabel(info.connection.id);
});
// bind a double click listener to "canvas"; add new node when this occurs.
jsPlumb.on(canvas, "dblclick", function(e) {
// newNode(e.offsetX, e.offsetY);
});
//
// initialise element as connection targets and source.
//
var initNode = function(el) {
// initialise draggable elements.
instance.draggable(el);
instance.makeSource(el, {
filter: ".ep",
anchor: "Continuous",
connectorStyle: { stroke: "#5c96bc", strokeWidth: 2, outlineStroke: "transparent", outlineWidth: 4 },
connectionType:"basic",
extract:{
"action":"the-action"
},
maxConnections: 6,
onMaxConnections: function (info, e) {
alert("Maximum connections (" + info.maxConnections + ") reached");
}
});
instance.makeTarget(el, {
dropOptions: { hoverClass: "dragHover" },
anchor: "Continuous",
allowLoopback: true
});
// this is not part of the core demo functionality; it is a means for the Toolkit edition's wrapped
// version of this demo to find out about new nodes being added.
//
instance.fire("jsPlumbDemoNodeAdded", el);
};
// suspend drawing and initialise.
instance.batch(function () {
for (var i = 0; i < windows.length; i++) {
initNode(windows[i], true);
console.log(windows[i]);
}
for (var j = 0; j < windows_movie.length; j++) {
initNode(windows_movie[j], true);
console.log(windows_movie[j]);
}
});
jsPlumb.fire("jsPlumbDemoLoaded", instance);
});
Here is live demo live demo
Here is plunker full source code
On the demo above just right click to add movie block for testing
Why does draggable not working for dynamically created elements?
here is a sample page I made a while ago when I first discovered 'jsplumb', it does exactly what you want so you might wanna use it or build on top of it.
Remember, indeed you should call the draggable method after the elements are added to the DOM, my example is so simple:
it doesn't need the jsplumb.fire
it doesn't need the .ready binding
it doesn't need the 'batch' processing offered by jsplumb
so you get to avoid problems like the scope of ready and other I'm still trying to master.
Edit: After trying out different hand-made solutions, I am using JSPlumb and trying to let it visually connect a clicked item from one list with a clicked item from another list (see screenshot).
I built upon this Stackoverflow thread and made it work basically, however the code provided there allows multiple connections, i.e. JSPlumb draws multiple endpoints and lines, and it doesn't react if a 'Target' is clicked first.
However, in my case there should be strictly only one connection, and JSPlumb should re-connect once I click on another list item on either side.
(E.g. I click on 'Source 1' and 'Target 3', JSPlumb draws the connection. I click on 'Target 4', JSPlumb should keep 'Source 1' as source and re-set 'Target 4' as the target, e.g. now draw the connection from 'Source 1' to 'Target 4'. The same with clicking a different 'Source', i.e. the target should stay the same.)
In what way would I need to alter the code in order to achieve the desired re-draw?
CodePen
jQuery(document).ready(function () {
var targetOption = {
anchor: "LeftMiddle",
isSource: false,
isTarget: true,
reattach: true,
endpoint: "Dot",
connector: ["Bezier", {
curviness: 50}],
setDragAllowedWhenFull: true
};
var sourceOption = {
tolerance: "touch",
anchor: "RightMiddle",
maxConnections: 1,
isSource: true,
isTarget: false,
reattach: true,
endpoint: "Dot",
connector: ["Bezier", {
curviness: 50}],
setDragAllowedWhenFull: true
};
jsPlumb.importDefaults({
ConnectionsDetachable: true,
ReattachConnections: true,
Container: 'page_connections'
});
//current question clicked on
var questionSelected = null;
var questionEndpoint = null;
//remember the question you clicked on
jQuery("#select_list_lebensbereiche ul > li").click( function () {
//remove endpoint if there is one
if( questionSelected !== null )
{
jsPlumb.removeAllEndpoints(questionSelected);
}
//add new endpoint
questionSelected = jQuery(this)[0];
questionEndpoint = jsPlumb.addEndpoint(questionSelected, sourceOption);
});
//now click on an answer to link it with previously selected question
jQuery("#select_list_wirkdimensionen ul > li").click( function () {
//we must have previously selected question
//for this to work
if( questionSelected !== null )
{
//create endpoint
var answer = jsPlumb.addEndpoint(jQuery(this)[0], targetOption);
//link it
jsPlumb.connect({ source: questionEndpoint, target: answer });
//cleanup
questionSelected = null;
questionEndpoint = null;
}
});
});
You were already keeping track of the "source" end of the linked items in a global variable; one way of getting to your desired behavior mostly just requires keeping track of the "target" end the same way. (There's room for improving this -- globals are maybe not an ideal strategy, and there's some code duplication between the 'source' and 'target' click handlers, but this should do for demonstration at least.)
// ...other init variables skipped
var questionEndpoints = []; // 'source' and 'target' endpoints
// "source" click handler
jQuery("#select_list_lebensbereiche ul > li").click(function() {
//remove existing start endpoint, if any:
jsPlumb.deleteEndpoint(questionEndpoints[0]);
// add a new one on the clicked element:
questionEndpoints[0] = jsPlumb.addEndpoint(jQuery(this), sourceOption);
connectEndpoints();
});
// "target" endpoint
jQuery("#select_list_wirkdimensionen ul > li").click(function() {
if (!questionEndpoints[0]) return; // don't respond if a source hasn't been selected
// remove existing endpoint if any
jsPlumb.deleteEndpoint(questionEndpoints[1]);
//create a new one:
questionEndpoints[1] = jsPlumb.addEndpoint(jQuery(this), targetOption);
connectEndpoints();
});
var connectEndpoints = function() {
jsPlumb.connect({
source: questionEndpoints[0],
target: questionEndpoints[1]
});
};
});
Working CodePen example
I would like to add category icons to a Wordpress page, each icon animated with snap.svg.
I added the div and inside an svg in the loop that prints the page (index.php). All divs are appearing with the right size of the svg, but blank.
The svg has a class that is targeted by the js file.
The js file is loaded and works fine by itself, but the animation appears only in the first div of that class, printed on each other as many times it is counted by the loop (how many posts there are on the actual page from that category).
I added "each()" and the beginning of the js, but is not allocating the animations on their proper places. I also tried to add double "each()" for the svg location and adding the snap object to svg too, but that was not working either.
I tried to add unique id to each svg with the post-id, but i could not pass the id from inside the loop to the js file. I went through many possible solutions I found here and else, but none were adaptable, because my php and js is too poor.
If you know how should I solve this, please answer me. Thank you!
// This is the js code (a little trimmed, because the path is long with many randoms, but everything else is there):
jQuery(document).ready(function(){
jQuery(".d-icon").each(function() {
var dicon = Snap(".d-icon");
var dfirepath = dicon.path("M250 377 C"+ ......+ z").attr({ id: "dfirepath", class: "dfire", fill: "none", });
function animpath(){ dfirepath.animate({ 'd':"M250 377 C"+(Math.floor(Math.random() * 20 + 271))+ .....+ z" }, 200, mina.linear);};
function setIntervalX(callback, delay, repetitions, complete) { var x = 0; var intervalID = window.setInterval(function () { callback(); if (++x === repetitions) { window.clearInterval(intervalID); complete();} }, delay); }
var dman = dicon.path("m136 ..... 0z").attr({ id: "dman", class:"dman", fill: "#222", transform: "r70", });
var dslip = dicon.path("m307 ..... 0z").attr({ id: "dslip", class:"dslip", fill: "#196ff1", transform:"s0 0"});
var dani1 = function() { dslip.animate({ transform: "s1 1"}, 500, dani2); }
var dani2 = function() { dman.animate({ transform: 'r0 ' + dman.getBBox().cx + ' ' + dman.getBBox(0).cy, opacity:"1" }, 500, dani3 ); }
var dani3 = function() { dslip.animate({ transform: "s0 0"}, 300); dman.animate({ transform: "s0 0"}, 300, dani4); }
var dani4 = function() { dfirepath.animate({fill: "#d62a2a"}, 30, dani5); }
var dani5 = function() { setIntervalX(animpath, 200, 10, dani6); }
var dani6 = function() { dfirepath.animate({fill: "#fff"}, 30); dman.animate({ transform: "s1 1"}, 100); }
dani1(); }); });
I guess your error is here:
var dicon = Snap(".d-icon");
You are passing a query selector to the Snap constructor, this means Snap always tries to get the first DOM element with that class, hence why you're getting the animations at the wrong place.
You can either correct that in two ways:
Declare width and height inside the constructor, for example var dicon = Snap(800, 600);
Since you are using jQuery you can access to the current element inside .each() with the $(this) keyword. Since you are using jQuery instead of the dollar you could use jQuery(this).
Please keep in mind this is a jQuery object and probably Snap will require a DOM object. In jQuery you can access the dom object by appending a [0] after the this keyword. If var dicon = Snap( jQuery(this) ); does not work you can try with var dicon = Snap( jQuery(this)[0] );
Additionally, you have several .attr({id : '...', in your code. I assume you are trying to associate to the paths an ID which are not unique. These should be relatively safe since they sit inside a SVG element and I don't see you are using those ID for future selection.
But if you have to select those at a later time I would suggest to append to these a numerical value so you wont have colliding ID names.
I'm trying to use jsPlumb, version 1.4.1 with the jquery dependency, to bind some divs in my UI together.
My initial code:
jsPlumb.bind("ready", function() {
var eclipse = jsPlumb.addEndpoint("java-eclipse");
var netbeans = jsPlumb.addEndpoint("java-netbeans");
jsPlumb.connect({
source:eclipse,
target:netbeans,
connector:"Straight",
paintStyle:{ lineWidth:5, strokeStyle:'rgba(0, 0, 200, 0.5)' },
endpoint:"Dot",
anchor:[ "Perimeter", { shape:"Circle" }]
});
});
Which works as intended, but as soon as I try to add more end points to make another connection:
//Innitial working endpoints
var eclipse = jsPlumb.addEndpoint("java-eclipse");
var netbeans = jsPlumb.addEndpoint("java-netbeans");
//Just adding these endpoints causes my script to crash
var javaSE = jsPlumb.addEndpoint("java-se");
var javaSW = jsPlumb.addEndpoint("java-sw");
This gets me the following error:
Error: H is undefined
r#https://cdnjs.cloudflare.com/ajax/libs/jsPlumb/1.4.1/jquery.jsPlumb-1.4.1-all-min.js:1:9455
I have no idea why the second set of endpoints I create causes the whole thing to crash, the divs exist and have the right ids and looking at the js plumb demos and docs making two separate connections (se->sw and eclipse->netbeans) should be possible.
Try this;
jsPlumb.connect({
source:eclipse,
target:netbeans,
connector:"Straight",
paintStyle:{ lineWidth:5, strokeStyle:'rgba(0, 0, 200, 0.5)' },
endpoint:"Dot",
anchor:[ "Perimeter", { shape:"Circle" }],
maxConnections: -1
});
Though I have successfully colored the bars of google chart individually but not able to keep them when we hover mouse over it. It is getting reset back to blue(which is default).
Here is the jsfiddle of what I have done jsfiddle.
I tried to control the hover behaviour with multiple ways like below.
This I am keeping outside (document.ready) but inside script tag.
1)
$('#chart_div').hover(
function() {
$('#chart_client').hide(); // chart_client is another google chart div.
}, function() { // just for testing I was doing hide/show of that.
$('#chart_client').show();
}
);
2)
$("#chart_div").on({
mouseenter: function () {
$('#chart_client').hide();
},
mouseleave:function () {
$('#chart_client').show();
}
},'rect');
3)
google.visualization.events.addListener('#chart_div', 'ready', function () {
$('#chart_div rect').mouseover(function (e) {
alert('hello');
});
});
I must be doing something wrong, could you please tell me what and where.
I solved it using below code. Earlier I was trying to create charts using dynamically adding rows into chart(please visit my jsfiddle) but with this below approach I am first preparing data(converting dynamic to static) and adding that static data in to chart's 'arrayToDataTable' method.
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawUserKeywordChart);
function drawUserKeywordChart() {
var val = 'Tax:47;Finance:95;Awards:126;Bank:137;Debt:145;';
var length = val.length;
var array = [];
//preparing data
while(length>0){
var sepAt = val.indexOf(";");
var value = parseInt(val.substring(val.indexOf(":")+1, sepAt));
array.push(val.substring(0, val.indexOf(":")));
array.push(value);
val = val.substring(val.indexOf(";")+1, length);
length = val.length;
}
var data = google.visualization.arrayToDataTable([
['Keyword', 'Occurences', { role: 'style' }],
[array[0], array[1], '#8AA3B3'],
[array[2], array[3], '#A9B089'],
[array[4], array[5], '#848C49'],
[array[6], array[7], '#44464A'],
[array[8], array[9], '#704610'],
]);
var options = {
title: 'Keyword Matches',
width: 660,
height: 450,
titleTextStyle:{bold:true,fontSize:20},
legend:{position:'none'}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_keyword1'));
chart.draw(data, options);
}
Please advice if you find anything wrong here or you have better approach than this.