I'm playing around with node graphs using Sigmajs.
Recently I tried to implement moving nodes in the graph but in the web-debugger I get an error saying "TypeError: Right hand side of instanceof is not an object" referring to the plugin sigma.plugins.dragNodes.js.
I followed the example given by the good folks at Sigmajs.org called "drag-nodes.html" and I believe I've included the packages correctly, yet I get the error.
The web-debugger refers to two places in the sigma.plugins.dragNodes.js file, these being: (At line 64)
if (renderer instanceof sigma.renderers.svg) {
_mouse = renderer.container.firstChild;
}
and (at line 304)
if (!_instance[s.id]) {
_instance[s.id] = new DragNodes(s, renderer);
}
This is my code:
<script src='{{ url_for("static", filename="js/sigma.min.js") }}'></script>
<script src='{{ url_for("static", filename="js/sigma.parsers.json.min.js") }}'></script>
<script src='{{ url_for("static", filename="js/sigma.plugins.dragNodes.js") }}'></script>
<div>
<button onclick="AddNode()"> Click</button>
</div>
<div>
<!-- testing function -->
<button onclick="update()"> update</button>
</div>
<div> <!-- ONSUBMIT send: (fromNode, toNode) Not complete -->
<input type="text" maxlength="2" name="value" id="value" />
<input type="button" value="submit" onclick="AddEdge()" />
</div>
<div id="container">
<style>
#graph-container {
max-width: 800px;
height: 500px;
margin: auto;
}
</style>
<div id="graph-container"></div>
</div>
<script>
var nodeCount = 0,
edgeCount = 0,
s,
maxNodes = 20,
maxEdges = 50,
g = {
nodes: [],
edges: []
}
s = new sigma({
graph: g,
container: 'graph-container',
renderers:[ {
container: document.getElementById('graph-container'),
type: 'canvas'
}],
settings: {
}
});
// Testing function only
function PrintNodes(){
var edgeval = document.getElementById('value').value[0];
alert(edgeval);
}
function AddNode() {
s.graph.addNode({
id: 'n' + nodeCount,
label: 'Node ' + nodeCount,
x: nodeCount,
y: 5,
size: 8,
color: '#000000'
});
nodeCount =nodeCount +1;
s.refresh();
}
function AddEdge() {
var fromNode = document.getElementById('value').value[0];
var toNode = document.getElementById('value').value[1];
s.graph.addEdge({
id: 'e' + edgeCount,
source: 'n' + fromNode,
target: 'n' + toNode,
size: 8,
color: '#FF0000'
});
edgeCount = edgeCount + 1;
s.refresh();
}
// Testing function only
function update(){
s.graph.nodes().forEach(function(n){
n.size = 34,
n.color = '#000'
});
s.refresh();
}
// Initialize the dragNodes plugin:
var dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
dragListener.bind('startdrag', function(event) {
console.log(event);
});
dragListener.bind('drag', function(event) {
console.log(event);
});
dragListener.bind('drop', function(event) {
console.log(event);
});
dragListener.bind('dragend', function(event) {
console.log(event);
});
</script>
Why is this giving me that error? And any help to fix it is appreciated.
Thanks.
You have this code:
if (renderer instanceof sigma.renderers.svg) {
_mouse = renderer.container.firstChild;
}
You should check sigma.renderers.svg ( console.log(sigma.renderers.svg) ) or something else, because as error insists it isn't an object. It could be undefined, null etc...
Check where you are defining sigma.renderers.svg.
As usual, the solution was more simple than I thought but at least I learned a lot whilst trying to solve it. The object was correct all the time but I had forgotten to implement necessary renderers. Even though I don't use the SVG type I had to have ../src/renderers/sigma.renderers.svg.js, included as a script-package.
Thanks for the help!
Related
I want to render a pay widget in the Flutter web app and I need a unique token there, so I calling Iframe from Dart to render it. However I didn't find how to send parameters or call a dart func (only about dart func, but this doesn't work)
<script src="https://yookassa.ru/checkout-widget/v1/checkout-widget.js"></script>
<!--HTML-element to render the form-->
<div id="payment-form"></div>
<script>
const checkout = new window.YooMoneyCheckoutWidget({
confirmation_token: foo(),
return_url: 'https://app.moneyhat.ru/',
customization: {
colors: {
controlPrimary: '#00BF96'
}
},
error_callback: function(error) {
}
});
checkout.render('payment-form');
</script>
this is part from Main.dart
String foo() {
return "ct-2830b393-000f-5000-8000-19466365c438";
}
js.context['foo'] = foo;
here I'm calling HTMLELEMNT from iframe
final html.IFrameElement _iframeElement = html.IFrameElement();
_iframeElement.height = MediaQuery.of(context).size.height.toString();
_iframeElement.width = MediaQuery.of(context).size.width.toString();
_iframeElement.src =
'paywall.html';
_iframeElement.style.border = 'none';
_iframeElement.id = 'iframe';
final wrapper = html.DivElement()
..style.width = '100%'
..style.height = '100%';
wrapper.append(_iframeElement);
// ignore: UNDEFINED_PREFIXED_NAME
ui.platformViewRegistry.registerViewFactory(
viewID,
(int viewId) => wrapper,
);
return Scaffold(
body: SizedBox(
height: 500,
child: HtmlElementView(
viewType: viewID,
),
));
Please help me to find a way to call dart func from JS of pass 2 String parameters in Flutter Web
You can do something like . You need to use html.window.postMessage(json, "*");
In your dart file inside build method
final data = <String, dynamic>{};
final jsonEncoder = JsonEncoder();
final json = jsonEncoder.convert(data);
final iframe = html.IFrameElement()
..src = 'assets/assets/html/show_images.html'
..style.border = 'none'
..onLoad.listen(
(event) async {
html.window.onMessage.listen((event) {
if (event.data == null) {
return;
}
print(event.data);
});
html.window.postMessage(json, "*");
},
);
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(viewId, (int id) {
return iframe;
});
in html file
<html>
<head>
<style>
.card-container {
display: flex;
height: 45px;
max-width: 100%;
overflow-x: hidden;
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>
</head>
<body>
<div class="card-container">
<form>
<input type="text" id="imagename" value="" />
<input type="button" id="btn" value="GO" />
</form>
</div>
<script type="text/javascript">
window.parent.addEventListener('message', handleMessage, false);
function handleMessage(e) {
var data = JSON.parse(e.data);
console.log(data);
}
</script>
</body>
</html>
My intention is to develop a pie chart from a csv file. The perspectives are the headers. My code takes the csv file. The headers are to be stored as options in the drop down menu. When a drop down menu item is selected a visualisation of the selected perspective is to be shown. A sample of the csv file is as follows:
,org_title,role_title,continent,country,updated_at_date
1,Startup,Founder,Oceania,Australia,27/06/2016
2,SME,C-Level / Owner,Oceania,Australia,27/06/2016
3,School / University,Student,Oceania,Australia,27/06/2016
4,School / University,Student,South America,Brazil,27/06/2016
5,Government Department,other,Asia,Philippines,28/06/2016
6,other,other,Asia,Singapore,27/06/2016
7,Non Profit Organisation,other,Asia,Malaysia,27/06/2016
8,Non Profit Organisation,other,Asia,Mongolia,27/06/2016
My code is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<input type="file" id="file" name="file"/>
<div id='container'/>
<select id='options'/>
<script>
$('#options').change(function () {
var v =this.value;
var res=[];
Object.keys(CSVARRAY[v]).forEach(function(k) {
res.push({'name':k,'y':CSVARRAY[v][k]});
});
console.log(JSON.stringify(res));
Highcharts.chart('container', {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
},
series: [{
data: res
}]
});
});
//Selecting file and converting it to tabular form
var file = document.getElementById('file');
var CSVARRAY;
file.addEventListener('change', function() {
var reader = new FileReader();
var f = file.files[0];
reader.onload = function(e) {
CSVARRAY = parseResult(e.target.result); //this is where the csv array will be
};
reader.readAsText(f);
});
function parseResult(result) {
var res = result.split("\n");
var headers = res[0].split(',');
headers.shift();
res.shift();
var d = {};
var prev={};
headers.forEach(function(h) {
d[h] = {};
prev[h] = [];
});
res.forEach(function(row) {
var i=0;
var r = row.split(",");
r.shift();
r.forEach(function(cell) {
if (cell !== prev[headers[i]])
{
d[headers[i]][cell]=[];
d[headers[i]][cell]=[];
d[headers[i]][cell]=1;
}
else
{
d[headers[i]][cell]+=1;
}
prev[headers[i]]=cell;
i += 1;
});
});
//return resultArray;
var options = $("#options");
headers.forEach(function(h) {
options.append($("<option />").val(h).text(h));
});
return d;
}
</script>
</body>
</html>
It is almost correct. However, the drop down menu dissappears after I click on any item.
The reason is actually because your div with the id "container" is not closed correctly. This means that the browser is interpreting that the select tag is actually within the container div. The same container div which is being overwritten with your chart.
If you change the following from:
<div id='container'/>
// javascript references are here
<select id='options'/>
To:
<input type="file" id="file" name="file"/>
<div id='container'>
</div>
// javascript references are here
<select id='options'/>
On an aside, your JavaScript code is very hard to follow, mostly because there is a lot of strange indenting going on. Take a look at airBnB's JavaScript style guide for information on making your code easier for others to read.
I'm trying to create a very simple website consisting of a Google bubble chart overlaid on a background image. The bubble chart is supposed to be generated based on data from a set of Google spreadsheets, and the user can select, through a simple text form, the names of the data points that are to be published. In the code below I have obfuscated the spreadsheet URL, because I don't want to make the data public yet (note however that the viewing privileges of the document are set to public, as required).
The code doesn't work, as no chart is drawn. Obviously there is something fishy going on, because there is never an alert from the collectData method, which handles the query response.
Also, initially I didn't have the draw method and its code was instead in the sendAndDraw method, sans the setTimeout. In that version, I got a Data table not found error on the webpage, but again, the collectData method didn't seem to be called, as it didn't raise an error.
Any suggestions as to what might be the issue? I should add that I am completely new to both javascript and Google developers tools.
EDIT: Following kfa's comment, the form was changed to include a post method. Now I get the Data Table not defined problem once again.
<!DOCTYPE html>
<html>
<head>
<style>
#container{
position: relative;
width: 200px;
height: 200px;
}
#background{
width: 100%;
height: 100%;
}
#bubbleChart{
width: 100%;
height: 100%;
}
</style>
<title>gRNA</title>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages' : ['corechart']});
google.charts.setOnLoadCallback(function() {initialize()});
var dataSourceUrls = [
'https://docs.google.com/spreadsheets/d/foo/edit#gid=0&headers=1'
];
var nSheets = dataSourceUrls.length;
var query;
var bubbleDataArray = [];
var bubbleData;
function initialize() {
//Currently not doing anything here
}
//Takes a list of names as a comma separated list.
function sendQueries(nameString) {
var queryString = generateQuery(nameString);
for(i = 0; i < nSheets; i++) {
query = new google.visualization.Query(dataSourceUrls[i]);
query.setQuery(queryString);
query.send(collectData);
query.abort();
}
}
//Generates the query string for the selected names.
function generateQuery(nameString) {
nameString = nameString.split(",");
var nNames = nameString.length;
var queryString = [];
queryString.push("select F, D, E, B ");
queryString.push("where F matches ");
queryString.push(nameString[0]);
for(i = 1; i < nNames; i++) {
queryString.push("or ");
queryString.push(nameString[i]);
}
return queryString.join("");
}
//Collect and manage the query responses.
function collectData(response) {
alert('Hi!');
if(response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' +
response.getDetailedMessage());
return;
}
var data = response.getDataTable();
if(data.getNumberOfRows() > 0) {
bubbleDataArray.push(data);
}
}
function sendAndDraw(nameString) {
bubbleDataArray = [];
sendQueries(nameString);
setTimeout(draw,2000);
}
function draw() {
bubbleData = bubbleDataArray[0];
var nTables = bubbleDataArray.length;
for(i = 1; i < nTables; i++) {
bubbleData = google.visualization.data.join(bubbleData,
bubbleDataArray[i], 'full', [[0,0]],
[1,2,3], [1,2,3]);
}
var container = document.getElementById('bubbleChart');
var bubbleChart = new google.visualization.BubbleChart(container);
var options = {
'backgroundColor':'transparent'
}
bubbleChart.draw(bubbleData,options);
}
function plot() {
sendAndDraw(document.getElementById('nameSel').value);
}
</script>
</head>
<body>
<form onsubmit="plot(); return false;" method="post">
<input type="text" id="nameSel"/>
<input type="submit" value="Plot"/>
</form>
<br />
<div id="container">
<div id="background"></div>
<div id="bubbleChart"></div>
</div>
</body>
</html>
I need to dynamically change the set of keywords that need to highlight. Here was the answer to a similar theme, but my project already has require.js and when I use the code from the response then I have an error:
Module name "DynHighlightRules" has not been loaded yet for context: _
Then I use files from ace-builds and try get ace using requirejs. This is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>ACE in Action</title>
<style type="text/css" media="screen">
#e1 {
position: absolute;
top: 0;
right: 0;
bottom: 50%;
left: 0;
}
</style>
</head>
<body>
<div id="e1">
function foo(items) {
var x = "All this is syntax highlighted";
return x;
}
first second editor
</div>
<script src="require.js"></script>
<script>
require.config({
baseUrl: window.location.protocol + "//" + window.location.host
+ window.location.pathname.split("/").slice(0, -1).join("/"),
paths: {
ace: "/home/sergey/ace-builds-master/src/",
}
});
define("DynHighlightRules", function() {
this.setKeywords = function(kwMap) {
this.keywordRule.onMatch = this.createKeywordMapper(kwMap, "identifier")
}
this.keywordRule = {
regex : "\\w+",
onMatch : function() {return "text"}
}
this.$rules = {
"start" : [
{
token: "string",
start: '"',
end: '"',
next: [{ token : "constant.language.escape.lsl", regex : /\\[tn"\\]/}]
},
this.keywordRule
]
};
});
require(["ace/ace"], function (ace) {
var editor = ace.edit("e1");
var TextMode = require("ace/mode/text").Mode;
var dynamicMode = new TextMode();
dynamicMode.HighlightRules = require(["DynHighlightRules"]);
editor.session.setMode(dynamicMode);
var tags = ["first", "second"];
dynamicMode.$highlightRules.setKeywords({"keyword": tags.join("|")})
editor.session.bgTokenizer.start(0)
});
</script>
</body>
</html>
This code not working. How can I add new mode to the ace if I already have requirejs in my project?
Thank you!
If you have require.js the best solution is to put DynHighlightRules into it's own file, but if you prefer keeping it inline, you can do the following
define("DynHighlightRules", function(require, exports, module) {
var oop = require("ace/lib/oop");
var TextHighlightRules = require("ace/mode/text_highlight_rules")
.TextHighlightRules;
module.exports = function() {
this.setKeywords = function(kwMap) {
this.keywordRule.onMatch = this.createKeywordMapper(kwMap, "identifier")
}
this.keywordRule = {
regex: "\\w+",
onMatch: function() {
debugger;
return "text"
}
}
this.$rules = {
"start": [{
token: "string",
start: '"',
end: '"',
next: [{
token: "constant.language.escape.lsl",
regex: /\\[tn"\\]/
}]
},
this.keywordRule
]
};
this.normalizeRules()
}
module.exports.prototype = TextHighlightRules.prototype
});
require(["ace/ace", "DynHighlightRules"], function(ace) {
var editor = ace.edit("e1");
var TextMode = require("ace/mode/text").Mode;
var dynamicMode = new TextMode();
dynamicMode.$id = "DynHighlightRules";
dynamicMode.HighlightRules = require("DynHighlightRules");
editor.session.setMode(dynamicMode);
var tags = ["first", "second"];
dynamicMode.$highlightRules.setKeywords({"keyword": tags.join("|")})
editor.session.bgTokenizer.start(0)
});
note that you should call require("DynHighlightRules"); instead of require(["DynHighlightRules"]); since the later form doesn't return a module/
also DynHighlightRules needs to be in dependency list of main require, to trigger require.js to process queue of pending defines, and you need to set proper prototype and call normalizeRules on text mode enable using rules with start/end
I am trying to parse some XML data into JSON using Javascript/Jquery for use in a Highcharts project. Unfortunately, I can't figure out what is wrong with my code as it will not even read the XML. So far I have:
xml:
<Row>
<Category>data</Category>
<actual>data</actual>
</row>
....
HTML:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
</head>
<body>
<h1>Hello</h1>
<div id="container" style="height: 400px; width: 500px"></div>
<script type = "text/javascript" src = "jquery-1.11.1.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script type = "text/javascript" src = "test.js"></script>
</body>
</html>
Javascript:
$(document).ready(function(){
var globalData = new Array();
// $("h1").click(function(){
// Load the data from the XML file
$.get('C:\\Users\\xxxxxx\\Desktop\\xmloutput.xml', function(xml) {
alert("it works");
// Split the lines
var $xml = $(xml);
// push series
$xml.find('Row').each(function(i, row) {
var seriesOptions = {
Category: $(series).find('Category').text(),
Actual: $(series).find('Actual').text(),
};
// add it to the options
globalData.push(seriesOptions);
});
});
// });
$(function() {
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'pie'
},
plotOptions: {
pie: {
borderColor: '#000000',
innerSize: '60%'
}
},
series: [{
data: globalData
}]
},
// using
function(chart) { // on complete
var xpos = '50%';
var ypos = '53%';
var circleradius = 102;
// Render the circle
chart.renderer.circle(xpos, ypos, circleradius).attr({
fill: '#ddd',
}).add();
// Render the text
chart.renderer.text('THIS TEXT <span style="color: red">should be in the center of the donut</span>', 155, 215).css({
width: circleradius*2,
color: '#4572A7',
fontSize: '16px',
textAlign: 'center'
}).attr({
// why doesn't zIndex get the text in front of the chart?
zIndex: 999
}).add();
});
});
});
I believe my actual problem may be that my xml-parsing syntax is incorrect but running this on the development console in Firefox reveals no errors. Hopefully the experts here can spot the issue(s)
Thanks for your time.
One imediate problem that I can see is using local path
$.get('C:\\Users\\xxxxxx\\Desktop\\xmloutput.xml',
$.get first parameter is url that is location on network it could be something like $.get('http://localhost/xmls/xmloutput.xml,...