Neovis.js not rendering completely in Salesforce Lightning Web Component - neo4j

I've spent about a week or so on this, and there's very little documentation online so I figured I'd come on here to see if anyone could potentially help out. So the top level summary is that I'm trying to use an external library (neovis.js) to visualize a neo4j graph database in a Salesforce Lightning web component. I've already explored d3.js (which is compatible with Salesforces locker service) and a few other visualization libraries, but neovis.js would be the most viable option for my use case. I've made some slight modifications shown in the code below to avoid using Document.getElementById in the neovis.js library to select the element and append the canvas to the page.
However, once the canvas is drawn to the page, none of the canvas elements (nodes and edges) are shown on the screen. Here's the weird part though, I can still hover over where the nodes should be on the canvas, and the popup which displays specific information for each node appears on screen with the correct information for each node. I am not super familiar with how the canvas element works, but it seems to me as if some css property is not being applied because of Salesforce's locker service, which causes to elements to be rendered invisibly.
I've gone through a good chunk of the neovis.js library (which is just a library built on top of vis.js), and I've looked for places where perhaps styles aren't being applied to the canvas element; however up to now I've had no luck.
Here's the code I've used so far:
index.html
<template>
<lightning-card title="Neovis" icon-name="custom:custom19">
<div class="slds-m-around_medium">
<div id="neovisContainerViz" class="neoVizClass" lwc:dom="manual" style="height: 700px; width: 400px;">
</div>
</div>
</lightning-card>
</template>
index.js
drawNeovis() {
const config = {
container_id: "",
server_url: "bolt://neo4j.het.io:7687", //This is a publicly available neo4j database that I'm using for testing purposes.
server_user: "",
server_password: "",
labels: {
},
relationships: {
},
initial_cypher: "MATCH (node:Disease {name: 'lung cancer'}) RETURN node"
}
const parent = this.template.querySelector('div.neoVizClass');
const container = document.createElement('DIV');
container.className = 'neoViz';
parent.appendChild(container);
const viz = new NeoVis.default(config);
viz._container = container; //This is a property inside of the NeoVis library. This property is normally set by using the document.getElementById method, however I've replaced it with my predefined container to get around the Salesforce Locker Service.
viz.render();
}
Here is exactly what is rendered onto the Salesforce App page:
<div class="slds-card__body">
<slot>
<div class="slds-m-around_medium">
<div id="neovisContainerViz-67" class="neoVizClass" style="height: 700px; width: 400px;">
<div class="neovis">
<div class="vis-network" tabindex="900" style="position: relative; overflow: hidden; touch-action: pan-y; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); width: 100%; height: 100%;">
<canvas width="200" height="200" style="position: relative; touch-action: none; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); width: 100%; height: 100%;">
</canvas>
<div class="vis-tooltip" style="left: 5px; top: 5px; visibility: hidden;">
<strong>
license:
</strong>
CC BY 3.0
<br>
<strong>identifier:</strong>
DOID:1324
<br>
<strong>name:</strong>
lung cancer
<br>
<strong>source:</strong>
Disease Ontology
<br>
<strong>url:</strong>
http://purl.obolibrary.org/obo/DOID_1324
<br>
</div>
</div>
</div>
</div>
</div>
</slot>
</div>
The canvas and the tooltip are appended to the DOM, AND the tooltip dynamically updates when I hover over where the canvas elements should be displayed. However none of the nodes or edges are visible on the screen.
All in all, I am not very familiar with how the canvas element actually functions, and am hoping that someone can give me some tips on how to trouble shoot this issue and get the elements on the canvas to display.
Thank you all!

I was able to finally figure this out incase anyone else is running into similar issues. I wouldn't say this is the preferred answer, but it works (for now). Basically I injected an iframe into Salesforce, and inside of the iframe I injected the neovis.js library and generated the graph, works perfectly now.

Related

Difficulty creating very small select statements for Angular Material web app for phone

I have been having trouble creating a web app for a phone using Angular and Material Design components. In order for my web app to work well on a phone, it needs to have small buttons and small select statements. Unfortunately, it looks like the framework is adding a style statement for the select element. That style statement is specifying the width of the element and the width it is specifying is way too big. How can I specify small select statements?
Below are the key parts of the two input files: app.component.html and app.component.css. There is a third section that shows the code that is generated by Angular2 as I see it in Chrome's developer tools. The key part of that code is the style statement (style="width: 139.325px;"). If I change the width using the develop tools then I can get the button size I want. I just don't know how to get the size i want using the CSS file.
---- Resulting Ang2 Code -----
<md-select _ngcontent-c0="" placeholder="Number of players" role="listbox" ng-reflect-model="4" ng-reflect-placeholder="Number of players" class="ng-untouched ng-pristine ng-valid mat-select" tabindex="0" aria-label="Number of players" aria-required="false" aria-disabled="false" aria-invalid="false" aria-owns="md-option-0 md-option-1 md-option-2 md-option-3 md-option-4 md-option-5 md-option-6 md-option-7 md-option-8"><div cdk-overlay-origin="" class="mat-select-trigger"><span class="mat-select-placeholder mat-floating-placeholder" style="width: 139.325px;">Number of players </span><!--bindings={
"ng-reflect-ng-if": "[object Object]"
}--><span class="mat-select-value"><span class="mat-select-value-text">4</span> </span><span class="mat-select-arrow"></span> <span class="mat-select-underline"></span></div><!--bindings={
"ng-reflect-origin": "[object Object]",
"ng-reflect-positions": "[object Object],[object Object",
"ng-reflect-offset-x": 0,
"ng-reflect-offset-y": 0,
"ng-reflect-min-width": "152.3249969482422",
"ng-reflect-backdrop-class": "cdk-overlay-transparent-backdr",
"ng-reflect-has-backdrop": "",
"ng-reflect-open": false
}--></md-select>
---- My attempt to override the css for the select statement in app.component.css -----
md-select{
font-size: 10px;
padding: 1px;
min-width: 12px;
}
md-option{
font-size: 10px;
padding: 1px;
min-width: 12px;
}
---- My app.component.html ---------
<md-select placeholder="Number of players" [(ngModel)]="numPlayers" (ngModelChange)="onChangeNumPlayers()" >
<md-option *ngFor="let mynum of numberOfPlayersList" [value]="mynum.value">{{ mynum.name }}</md-option>
</md-select>
My friend Sergiu from Romania helped me out with this. The framework creates elements that encapsulate the md-select and md-option elements. You cannot set the styles for elements outside of md-select and md-option using app.component.css. In order to control those elements you need to add them to the base styles.css file. These classes were sufficient to shrink the select statement for me.
.mat-select,
.mat-select-trigger,
.mat-select-placeholder,
.cdk-overlay-pane,
.mat-select-panel,
.mat-select-content
{
min-width: 40px !important;
width: 40px !important;
}
.mat-option {
padding: 0 2px!important;
}

Kendo Autocomplete Displays Two Suggestion Lists

My Kendo autocomplete control retrieves a Json list successfully. Unfortunately, it calls the MVC controller method twice and creates two suggestion lists. The duplicate list is displayed directly behind the first. When a value is selected from the first suggestion list, the list disappears, but the duplicate list remains visible. I am using a wrapper for the autocomplete control as shown below. I've confirmed that the control is not being referenced in any of the page scripts. The control is located in a partial view that is added to a cshtml view one time (#{ Html.RenderPartial("_AddLineItem"); }).
#(Html.Kendo().AutoComplete()
.Name("CategorySearch")
.DataTextField("CategoryName")
.Filter("contains")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("PopulateCategories", "Default");
})
.ServerFiltering(false);
})
)
Generated HTML shows the suggestion list twice, but the associated input control only exists once. The following tags are in the generated HTML twice (these are tags for the suggestion list and they also contain li tags and closing div tags, removed from the pasted HTML below):
<div class="k-animation-container" style="left: 431.13px; top: 405.69px; width: 511px; height: 206px; overflow: hidden; padding-right: 2px; padding-bottom: 4px; padding-left: 2px; margin-left: -2px; display: none; position: absolute; z-index: 10002;">
Does anyone have an idea of what is happening here?
Per the comment that I added, the answer is to avoid putting a Kendo autocomplete control inside a JQuery UI dialog control. The dialog forces the autocomplete control to be rendered twice in the browser. I've confirmed this in both Internet Explorer and Firefox. It is reasonable to assume that the same behavior will occur in other browsers as well.

Firebug shows incorrect (possibly hijacked) link CouponDropDown

This is the first time I saw this... I have text in my code and it says Passport and Visa Requirements. This is my markup
<div class="rectangle"><span>Passport and Visa Requirements</span></div>
Crazy thing happens on the live server, somehow a link is injected on the word "visa". This is the markup I see in firebug.
<div class="rectangle">
<span>
Passport and
<a id="_GPLITA_0" title="Click to Continue > by CouponDropDown" style="text-decoration:underline" href="http://i.txtsrving.info/click?v=" in_rurl="http://i.txtsrving.info/click?v=" in_hdr="">
Visa
<img src="http://cdncache1-a.akamaihd.net/items/it/img/arrow-10x10.png" style="display: inline; vertical-align: super; margin: 0px 0px 0px 3px; padding: 0px; border: 0px none; height: 10px;">
</a>
Requirements
</span>
</div>
Is my htaccess file not configured properly? How do I deal with this? Is this a security issue?
http://www.bleepingcomputer.com/virus-removal/remove-coupondropdown
This is probably adware on your computer, affecting your browser. Your website is probably fine.

Google Fusion Tables Card Layout: How to format fields

I have the following template:
{template .contents}
<div class='googft-card-view' style='font-family: sans-serif; height: 17em; width: 450px; padding: 4px; border: 1px solid #ccc; overflow: hidden'>
<table border="0">
<tr>
<td>
<b>Village:</b> {$data.formatted.Village}<br>
<b>Location:</b> {$data.value.Location}<br>
<b>Location Accuracy:</b> {$data.value['Location:Accuracy']} meters<br>
</td>
</table>
</div>
{/template}
Which gives me:
Village: TestVillage
Location: <Point><coordinates>69.1782913000,34.5338741600,1787.5000000000</coordinates></Point>
Location Accuracy: 5.0 meters
I'd like to be able to get rid of the <point>, <coordinate> tags, and format the values. Javascript is disabled/stripped out in the card layout.
How can I manage this, if possible?
Try this:
{$data.value.Location |noAutoescape}
See Closure template docs for details.
You can't easily get to the individual lat/lng inside a KML snippet, but this should have the effect of clipping out the point and coordinate tags (I think).
If this not sufficient you can take over full formatting of the info windows in your own JavaScript code, though that's a bit more work.

Struts errors/messages with div, not span

We add Struts errors and messages using ActionSupport.addActionError(...) and addActionMessage(...) and then output the results using <actionerror class="x"/> and <actionmessage class="x"/>.
When these tags output the messages they output in the form: <ul><li><span class="x">msg</span></li></ul>
As you can see you can specify the css class (in this example 'x') to apply formatting. Problem is that we want to apply the margin-top and margin-bottom css properties and you can't use these properties (I gather) with <span> elements - only with <div> elements.
So is there anyway you can get these Struts tags to output error/message using a <div> instead of a <span>?
Thanks.
Update:
As per the answer/workaround below, I just enclosed the struts tag within a div:
<div class="error-status">
<s:actionerror cssClass="error"/>
<s:actionmessage cssClass="status" />
</div>
The error-status CSS class set the properties on the LI:
.error-status LI { MARGIN-TOP: 5px; MARGIN-BOTTOM: 5px; display: block; }
.error { COLOR: red }
.status { color: #0066CC }
You can apply margin to spans if you also apply display:block.
But the optimal solution is to apply margin to the li elements.

Resources