How to dynamically draw edges between nodes using jsplumbtoolkit-react - reactjs

I'm using jsplumbtoolkit-react 2.x version. Using toolkit.addNode to add new nodes dynamically to the graph. But I'm struggling to draw the connection between the newly added nodes. Can someone please point me to the right documentation or if there is any example that I can follow for this specific version?
I added the following properties on the node component
jtk-port={ctx.data.id}
jtk-scope="varchar"
jtk-source="true"
jtk-target="true"
I do have elementsDraggable: true, so all I'm able to do is drag the node but not form a connection. I tried using addPort but with no luck and the jsPlumbtoolkit documentation has not helped so far.

It's possible you are looking at the 5.x documentation, given that you're using attributes in the above example, although I should note that for users of 5.x the attributes are prefixed with data-, eg data-jtk-source="true" etc. In 2.x this connectivity is not configured with attributes, though, but with elements. For instance, for this demonstration:
https://demo.jsplumbtoolkit.com/react-flowchart-builder/
This is the render method for the action component:
render() {
const obj = this.node.data;
return <div style={{width:obj.w + 'px', height:obj.h + 'px'}} className="flowchart-object flowchart-action">
<div style={{position:'relative'}}>
<svg width={obj.w} height={obj.h}>
<rect x={10} y={10} width={obj.w-20} height={obj.h-20} className="inner"/>
<text textAnchor="middle" x={obj.w/2} y={obj.h/2} dominantBaseline="central">{obj.text}</text>
</svg>
</div>
<div className="node-edit node-action" onClick={this.edit.bind(this)}></div>
<div className="node-delete node-action delete" onClick={this.remove.bind(this)}></div>
<div className="drag-start connect"></div>
<jtk-target port-type="target"/>
<jtk-source port-type="source" filter=".connect"/>
</div>
}
The complete source for the version 2.x code for that demonstration is here:
https://github.com/jsplumb-toolkit-demonstrations/react-flowchart-builder/blob/2.x/src/action-component.jsx

Related

Twilio Flex AgentDesktopView Panel Sizing

For the 2 panels in the AgentDesktopView, I'm trying to adjust the size of Panel 1.
I've tried:
flex.AgentDesktopView
.defaultProps
.splitterOptions
.initialFirstPanelSize = '250px'
and
flex.AgentDesktopView
.defaultProps
.splitterOptions
.minimumFirstPanelSize = '250px'
I've tried searching through docs and can't find much information around it.
Twilio developer evangelist here.
If you have a plugin you can put the code in, you can try this
flex.AgentDesktopView.defaultProps.splitterOptions = {
initialFirstPanelSize: "250px",
minimumFirstPanelSize: "250px",
//minimumSecondPanelSize: "xx%"
};
Either the theme or these component options can be used ie. if you're updating the config in the manager when you changed the options:
manager.updateConfig(appConfig);
Let me know if this helps at all!

How to add attributes to elements with HtmlPurifier?

I'm looking to purify HTML with the HtmlPurifier package and add attributes to certain elements. Specifically, I'd like to add classes to <div> and <p> elements so that this:
<div>
<p>
Hello
</p>
</div>
Gets purified/transformed into this:
<div class="div-class">
<p class="p-class">
Hello
</p>
</div>
How would one go about doing this with HtmlPurifier? Is it possible?
I believe you could do this by doing something along these lines (though please treat this as pseudocode, the last time this scenario worked for me was years ago):
class HTMLPurifier_AttrTransform_DivClass extends HTMLPurifier_AttrTransform
{
public function transform($attr, $config, $context) {
$attr['class'] = 'div-class';
return $attr;
}
}
class HTMLPurifier_AttrTransform_ParaClass extends HTMLPurifier_AttrTransform
{
public function transform($attr, $config, $context) {
$attr['class'] = 'p-class';
return $attr;
}
}
$htmlDef = $this->configuration->getHTMLDefinition(true);
$div = $htmlDef->addBlankElement('div');
$div->attr_transform_post[] = new HTMLPurifier_AttrTransform_DivClass();
$para = $htmlDef->addBlankElement('p');
$para->attr_transform_post[] = new HTMLPurifier_AttrTransform_ParaClass();
Remember to allowlist the class attribute for div and p as well, if you haven't already.
That said, at first glance, HTML Purifier doesn't seem to be the right place for this kind of logic, since adding class names isn't relevant for the security of your site (or is it?). If you're already using HTML Purifier to allowlist your HTML tags, attributes and values, and just want to leverage its HTML-parsing capabilities for some light-weight additional DOM manipulation, I see no particular reason not to. :) But it might be worth reflecting on whether you want to add the classes using some other process (e.g. in the frontend, if that's relevant for your use case).

Adding variable to prop

I'm new to React, and I'm sorry beforehand if I use the wrong terms for certain pieces!
I have imported some images in the top if my file with import face_1 from "./assets/face-1.png"; (where the numbers increase up to 6, since I'm making dice)
Later on, I want to show those images based on the value of the die, so I want to grab the images as follows: <img className="dice-image" src={face_#} alt={roll} />;. I want # to be the same value as {roll}, but I can't figure out how I can add the value of {roll} to src?
So basically, I want the <img>-tag to look like this:
<img className="dice-image" src={face_{roll}} alt={roll} />
Is this at all possible? Or do I have to create the face_3 just before I call it as a prop?
Putting all the values into an array, as suggested by Guy Incognito, is a straightforward way to handle this:
const faces = [face_1, face_2, face_3, face_4, face_5, face_6];
return (
<>
{faces.map((face, i) => (
<img className="dice-iamge" key={i} src={face} alt={roll} />
))}
</>
);

Customization of the Height of a Pivot Item Link Line in Fluent UI

I'm trying to increase the height of the line on the selected Pivot item link in Microsoft's Fluent UI using React.
Here's a screenshot for the purposes of clarification:
The orange arrow is pointing to the blue line of which I would like to increase the height.
I have tried setting the styles attribute of the Pivot component but thus far have been unsuccessful. Here's some code
const pivotStyles: Partial<IStyleSet<IPivotStyles>> = {
link: { ? },
linkContent: { ? }
};
<Pivot styles={pivotStyles} linkSize={PivotLinkSize.large}>
<PivotItem headerText="Zane"></PivotItem>
<PivotItem headerText="Kai"></PivotItem>
<PivotItem headerText="Jay"></PivotItem>
</Pivot>
I have experimented with different attributes of both link and linkContent but haven't found a way yet. I believe what I'm trying to do is manipulate the IStyle interface but I can't find details of the attributes of it. The link there is very vague. For example, what are all the available attributes of link, linkContent, etc.?
Any thoughts on this would be most appreciated!
Thank you.
Turns out I was on the right track and just needed the exact fields. Here's what ended up working:
const pivotStyles = {
linkIsSelected: {
selectors: {
':before': {
height: '6px', // was previously defaulted at 2px
}
}
}
};
I scoured about 4.24 million sites to find this answer but here are some of the most helpful in case they are of interest:
the actual source code of Pivot.styles.ts
the Microsoft Fluent UI Pivot Documentation
A deep examination of the classes using Chrome Dev Tools also helped. ;)
Here's a picture of the end result:

Filtering spcific with checkboxes

My question is that I want a filtering system that will filter by checked checkboxes.
The tool is to my comparison website where I compare TV packages.
my visitors should filter the packages by the tv-channels they want to se.
example;
Checkbox 1: Discovery
Checkbox 2: Animal PLanet
Checkbox 3: Disney Channel
Output should be the matching TV-package
Package 1: (contains Discovery and Disney channel)
Package 2: (contains Animal Planet, Disney channel)
Package 3: (contains Animal Planet)
So if checkbox 1 is checked it should only show package 1.
if checkbox 1 + checkbox 2 is checked it should say "No match found, but this package was was closest to your choice"
if checkbox 2 + checkbox 3 is checked it should only show package 2 which match the visitors choice exactly.
I hope your can help me out. I have been searching a lot after this specific solution without any success.
I think it should be in Jquery. i have seen some simular filtering examples, but no one there are like my wish above.
This is an old question, but... I'll take a shot. Working jsfiddle: http://jsfiddle.net/a0nnrfua/
I think a lot really depends on how you intend to define "closest", but presuming a jQuery solution and hopefully your browser requirements aren't TOO far in the past, you could use the data- attributes and jQuery to come up with some relatively simple functions. Or even use the value portions of the checkboxes really.
Psuedocode, it would look like:
Define a click or change handler to detect whenever a checkbox has been touched/changed.
Define a function that will scan all checked items and pass the values into your "closest package" function.
Based on the results of that function, filter your package selection so that your choices are highlighted or marked in some way.
So let's presume the following HTML markup:
<h3>TV Channels</h3>
<div id="TVChannelSelections">
<input type="checkbox" class="tvchannel" name="tvchannel" id="tvchannel_Discovery" value="Discovery" />
<label for="tvchannel_Discovery">Discovery Channel</label>
<br/>
<input type="checkbox" class="tvchannel" name="tvchannel" id="tvchannel_AnimalPlanet" value="Animal Planet" />
<label for="tvchannel_AnimalPlanet">Animal Planet</label>
<br/>
<input type="checkbox" class="tvchannel" name="tvchannel" id="tvchannel_DisneyChannel" value="Disney Channel" />
<label for="tvchannel_Disney">Disney Channel</label>
<br/>
</div>
<div id="message"></div>
<h3>Packages</h3>
<div id="FilteredPackages">
<div class="package deselected" id="Package1" data-channels="Discovery,Disney Channel">Package #1</div>
<div class="package deselected" id="Package2" data-channels="Animal Planet,Disney Channel">Package #2</div>
<div class="package deselected" id="Package3" data-channels="Animal Planet">Package #3</div>
</div>
So in jQuery, your generic change or click handler would be defined in code: Note that I'm saying, any element on your page that has the class "tvchannel" defined, if there's ever a change that occurs, run my filter function.
<script type="text/javascript" src="../path/to/jQuery/library"></script>
<script type="text/javascript">
$(document).ready(function() {
$(".tvchannel").on("change", function() {
FilterMySelectedChannels();
});
});
</script>
Now we can define your Filter function. We're going to assume two things. #1, that we want to find all the selected checkboxes and their values. Then we're going to iterate through the data-channels property of all of our packages (defined as elements with class = "package"). We'll use some form of string comparison and boolean logic to define what a complete match is vs. a close but no cigar match vs. a complete fail.
In order to keep track of things I'm using 3 classes, selected, deselected, and close.
In css, you can decide whether you want notselected to mean "hide the package completely" (i.e. display: none;) or maybe you want it to be visible but greyed out and "struck out" (i.e. text-decoration: strikethrough; color: grey;}
I'm going to use kind of a brute force way of doing the comparison. There are better array functions and comparison functions in javascript, but this should be relatively clear for most people and I trust the good folks at stackoverflow to chime in with better solutions. But this should get you started. :)
<script type="text/javascript">
function FilterMySelectedChannels() {
$checkedboxes = $(".tvchannel:checked");
$packages = $(".package");
var bAnyFound = false;
$packages.each(function () {
var bCloseButNoCigar = false;
var bCompleteMatch = true;
var packagearray = $(this).data("channels").split(",");
var $currentPackage = $(this);
$checkedboxes.each(function () {
if ($.inArray($(this).val(), packagearray) != -1) {
bCloseButNoCigar = true;
} else {
bCompleteMatch = false;
}
});
if (bCompleteMatch) {
$currentPackage.removeClass("selected").removeClass("deselected").removeClass("close").addClass("selected");
bAnyFound = true;
} else if (bCloseButNoCigar) {
$currentPackage.removeClass("selected").removeClass("deselected").removeClass("close").addClass("close");
} else {
$currentPackage.removeClass("selected").removeClass("deselected").removeClass("close").addClass("deselected");
}
});
if (bAnyFound) {
$("#message").html("The following matches were found");
} else {
$("#message").html("No actual matches were found, but here are some close matches based on your selections");
$(".package.close").removeClass("deselected").removeClass("close").removeClass("selected").addClass("selected");
}
}
</script>
<style type="text/css">
.selected {
color: red;
background-color: yellow !important;
}
.deselected {
color: grey;
text-decoration: strike-through !important;
background-color: white !important;
}
</style>
There are obvious optimizations that could probably work here, but it's a start for those trying to do something similar. Note that it assumes that your markup is dynamically generated or properly coded. If you need to guard against human typos, converting your text using .toLowerCase/UpperCase and using the .Trim functions to eliminate extra space will assist. But you still have to choose your data values wisely so there's no overlap. And if you choose them well enough you can use better techniques such as regular expressions and wildcard searches to make the code a bit shorter.
Hope this helps someone!

Resources