Async troubles with layout and loading elements - javascript

This is my file graph.json
{
"nodes":[
{"data":{"id": "Node 1"}},
{"data":{"id": "Node 2"}}
],
"edges":[
{"data":{"source":"Node 1", "target":"Node 2"}}
]
}
which I am trying to visualize with cytoscape.js in the CoSE layout using the code below. Unfortunately I only get an empty graph without any nodes. It does work however if I use the 'concentric' or 'grid' layout, or if I write the graph data directly into the cytoscape.js initialization part. Why does it not work the way I did it: with the 'CoSE' layout and a graph loaded from a JSON file?
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://cytoscape.github.io/cytoscape.js/api/cytoscape.js-latest/cytoscape.js"></script>
<script>
$(function () {
$('#cy').cytoscape({
layout: {name: 'cose'},
style: cytoscape.stylesheet()
.selector('node')
.css({'content': 'data(id)'}),
ready: function () {window.cy = this;}
});
$.getJSON('graph.json', function(data) {cy.load(data)});
});
</script>
</head>
<body>
<div id="cy" style="height: 100%; width: 100%; position: absolute; left: 0; top: 0;">
</div>
</body>
</html>

(1) Cytoscape is doing exactly what you're telling it to do. You initialise with no elements, running CoSE on them. You load additional elements asynchronously, which will certainly happen after init.
(2) This blog seems to have a decent description of sync/async. You may want read a book on JS if you're new to the language or if you're new to programming in general.
(3) If you want to keep things simple, pass a fetch promise as options.elements. Read the init section for more info: http://js.cytoscape.org/#core/initialisation

Related

Error when importing web components in the "wrong" order

I have built a small library of several HTML web components for internal company use. Some components are mutually dependent on each other, so I also import them mutually. Until recently, I had no serious issues with this approach, but I am now encountering an error message when loading a HTML page that uses such mutually dependent components.
I have isolated the issue in a small example. Please review the following three files.
test-container.js
import { TestItem } from "./test-item";
export class TestContainer extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" }).innerHTML = `
<style>
* {
position: relative;
box-sizing: border-box;
}
:host {
contain: content;
display: block;
}
</style>
<div>
<slot></slot>
</div>
`;
}
connectedCallback() {
if (!this.isConnected) {
return;
}
for (const node of this.childNodes) {
if (node instanceof TestItem) {
//...
}
}
}
}
customElements.define("test-container", TestContainer);
test-item.js
import { TestContainer } from "./test-container";
export class TestItem extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" }).innerHTML = `
<style>
* {
position: relative;
box-sizing: border-box;
}
:host {
contain: content;
display: block;
}
</style>
<div>
<slot></slot>
</div>
`;
}
}
customElements.define("test-item", TestItem);
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
<script type="module" src="/test-container"></script>
<script type="module" src="/test-item"></script>
<style>
test-container {
width: 600px;
height: 400px;
background: lightblue;
border: 1px solid;
}
test-item {
width: 200px;
height: 200px;
background: lightgreen;
border: 1px solid;
}
</style>
</head>
<body>
<test-container>
<test-item></test-item>
</test-container>
</body>
</html>
This code seems to work fine.
However, if I switch the two <script> tags in the index.html file, the developer tools console shows the following error:
Uncaught ReferenceError: Cannot access 'TestItem' before initialization
at HTMLElement.connectedCallback (test-container:30)
at test-container:37
Since I import several modules in many of my components, I want to sort them alphabetically (for clarity). In my test example it's fine, but in my actual code it isn't...
So basically I want my modules to be completely independent of the order in which they will be imported by other modules. Is there any way to achieve that?
All suggestions are very welcome. However, I am not allowed to install and use any external/3rd party packages. Even the use of jQuery is not allowed. So a solution should consist of only plain vanilla JS, plain CSS, and plain HTML5, and it should at least work correctly in the latest Google Chrome and Mozilla Firefox web browsers.
When you can't control the order in which Elements are loaded,
you have to handle the dependency in your Element
Use: https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/whenDefined
whenDefined returns a Promise!
So your <test-container> code needs something like:
customElements.whenDefined('test-item')
.then( () => {
//execute when already exist or became available
});
https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/whenDefined
has a more detailed example waiting for all undefined elements in a page
Dependencies
An Event driven approach might be better to get rid of dependencies.
Make <test-item> dispatch Event X in the connectedCallback
<test-container> listens for Event X and does something with the item
You can then add <another-item> to the mix without having to change <test-container>
Maybe the default slotchange Event can be of help:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/slotchange_event
.
Success met welke aanpak je ook kiest
it may help
<!-- This script will execute after… -->
<script type="module" src="1.mjs"></script>
<!-- …this script… -->
<script src="2.js"></script>
<!-- …but before this script. -->
<script defer src="3.js"></script>
The order should be 2.js, 1.mjs, 3.js.
The way scripts block the HTML parser during fetching is baaaad.
With regular scripts you can use defer to prevent blocking, which also delays script execution until the document has finished parsing, and maintains execution order with other deferred scripts.
Module scripts behave like defer by default – there's no way to make a module script block the HTML parser while it fetches.
Module scripts use the same execution queue as regular scripts using defer.
Source

generating js code from python, not sure if going the right path

I have a web application that is structured as the following:
Server is written in Python. It serves the client an HTML page with
about 100 different tables (grids) and matching JS files. Every grid is a DIV with JS code that initializes it:
page.html:
<script type="text/javascript" src="static/assets/js/grid_type_1.js"></script>
<script type="text/javascript" src="static/assets/js/grid_type_2.js"></script>
<script type="text/javascript" src="static/assets/js/grid_type_3.js"></script>
<div id="grid_type_1" style="width: 100%; height: 200px;"></div>
<div id="grid_type_2" style="width: 100%; height: 200px;"></div>
<div id="grid_type_3" style="width: 100%; height: 200px;"></div>
grid_type_1.js:
$(function () {
w2utils.settings['dataType'] = 'JSON'
$('#grid_type_1').w2grid({
// configuration here
});
All the JS files use the same UI framework (W2UI) but each grid is of different configuration and structure. After the page loads, each grid makes a POST request to the server and it replies with a JSON that is used to populate that grid with entries.
I'm already using Jinja2 to template the HTML files and 80% of the code in the JS files is the same, so I was thinking if it would be better to generate the JS files as well, instead of duplicating 80% of the JS grid code 100 times.
Is it a viable approach to this issue?

Building Angular Modules form jQuery Plugins

Hi All Thank you in advance.
I am faced with a task of converting an HTML and jQuery intensive website and make it work with AngularJs. The issue is that it has a lot of plug-ins like
http://adnantopal.github.io/slimmenu
https://github.com/inuyaksa/jquery.nicescroll
http://tympanus.net/codrops/2012/08/02/animated-responsive-image-grid/
https://dev7studios.com/dropit/
http://fitvidsjs.com/
They are loaded as follows on the HTML page
```
<script src="js/slimmenu.js"></script>
<script src="js/jquery.nicescroll.js"></script>
<script src="js/gridrotator.js"></script>
<script src="js/js/ionrangeslider.js"></script>
other scripts
```
Then there is a main.js file that is used to init the lib's in a section that is needed
E.G
````
// main.js
$(document).ready(function(){
$('html').niceScroll({
cursorcolor: "#000",
cursorborder: "0px solid #fff",
railpadding: {
top: 0,
right: 0,
left: 0,
bottom: 0
},
....etc
});
owlCarouselSlider.owlCarousel({/*--code--*/});
});
$('div.bg-parallax').each(function(){/*//code*/});
$('input.time-pick').timepicker({
minuteStep: 15,
showInpunts: false
})
$('.form-group-cc-number input').payment('formatCardNumber');
$(function() {
$('#ri-grid').gridrotator({})
});
````
The Issue
These plug-ins only work if your page is static and they do not work when I use them with AngularJs. I get errors like gridrotator is undefined
Question
How can I make the jQuery-plugin and other libraries be a module that I can use with Angular
Here is an example plnkr that I try to make.
But now do I put the original lib code on the Factory or Service providers in Angular?

MathJax not rendering latex

I've tryed to embed MathJax into a page to have latex rendered as real formula/expressions however I get no errors nor any rendering. The code is taken directly from the MathJax documentation
I have the following code
var div = MathJax.HTML.Element(
"div",
{id: "MathDiv", style:{border:"1px solid", padding:"5px"}},
["Here is math: \\(x+1\\)",["br"],"and a display $$x+1\\over x-1$$"]
);
document.body.appendChild(div);
that executes with no errors, so MathJax is loaded correctly and there's no errors in the console either. So very little information to go on. Any good suggestion to how I debug this scenario or even better a solution :)
This code works for me.
<!doctype html>
<html>
<head>
<!-- or use the cdn for mathjax source code -->
<script src="../MathJax/MathJax.js">
MathJax.Hub.Config({
jax: ["input/TeX","output/HTML-CSS"],
extensions: ["tex2jax.js"],
tex2jax: {
inlineMath: [ ['\\(','\\)'] ],
displayMath: [ ['$$','$$'] ]
}
});
function doOnLoad() {
var div = MathJax.HTML.Element(
"div",
{id: "MathDiv", style:{border:"1px solid", padding:"5px"}},
["Here is math: \\(x^2+1\\)",["br"],"and a display $$x+1\\over x-1$$"]
);
document.body.appendChild(div);
// This does not seem needed but you can use if to force rendering of a div
// MathJax.Hub.Queue(["Typeset",MathJax.Hub,'MathDiv']);
}
</script>
</head>
<body onload="doOnLoad();">
</body>
</html>
I think you need to add the div in the onload method, so the div is added after the page has been fully parsed.

running Javascript inside Durandal view

I am building a demo to use Durandal to work with D3.js. I modified on the Starter Kit.
It has two views: Welcome and Flickr. I added a new view Chart and copied some d3js visualization javascript code inside my view:
<section>
chart demo
<link type="text/css" rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
//more scripts
<div id="container" style="height: 500px; min-width: 500px"></div>
<script type="text/javascript">
d3 visualization code here.
</script>
chart end
</section>
But I find that in a Durandal view, JavaScript code cannot be included. The above code can only display something like:
chart begin
a empty box of size style="height: 500px; min-width: 500px"
chart end
It seems that all the javascirpt code are removed automatically by Durandal.
My question is how to use JavaScript inside a Durandal view? Thanks!
You could leverage the viewAttached function of your durandal view model to execute d3 code. Like so:
define(function (require) {
var vm = {};
vm.viewAttached = function (view) {
// d3 visualization code here
// use class names to find the container instead of id and you can have multiple instances on the same page
d3.select(view).select(".d3container")
.classed("well", true)
.text('I just styled this div using the magic of D3.');
};
return vm;
});

Categories