I want to access the internal widgets but it gives me an error, that I can't index a nil value.
My widget:
local previewWidget = wibox()
previewWidget:setup {
widget = wibox.widget {
{
widget = wibox.widget {
{
widget = awful.widget.clienticon,
client = "",
id = "clientIcon"
},
{
widget = wibox.widget.textbox,
id = "titleText"
},
nil
},
layout = wibox.layout.align.horizontal,
id = "titleBox"
},
{
widget = wibox.widget.imagebox,
id = "clientImage"
},
nil
},
id = "previewBox",
layout = wibox.layout.align.vertical,
border_width = 10,
border_color = "FF0000",
}
This command doesn't give error:
local previewBox = previewWidget:get_children_by_id("previewBox")[1]
But this does:
local titleBox = previewWidget:get_children_by_id("titleBox")[1]
local clientIcon = previewWidget:get_children_by_id("clientIcon")[1]
What am I doing wrong here?
local previewWidget = wibox.widget {
{
{
widget = awful.widget.clienticon,
client = "",
id = "clientIcon"
},
{
widget = wibox.widget.textbox,
id = "titleText"
},
nil,
layout = wibox.layout.align.horizontal,
id = "titleBox"
},
{
widget = wibox.widget.imagebox,
id = "clientImage"
},
nil,
layout = wibox.layout.align.vertical,
id = "previewBox",
}
I incorrectly used the layout:
All 3 widgets needs to be where the layout is called
local some_widget = wibox.widget {
{ widget nr.1 },
{ widget nr.2 },
{ widget nr.3 },
layout = wibox.layout.align.vertical
}
P.S. it's enough to declare a layout without a widget
simple multi barchart only shows the main category ['one', 'two', 'three', 'four', 'five', 'six'] as the x axis labels. Is there a way to show subcategory ['A', 'B', 'C', 'D'] as secondary x axis labels in chartjs?
the graph with sub category labels
You can use grouped bar chart, like here:
const datasets = [{
label: "red",
backgroundColor: "red",
data: [33, 91, null, 48]
}, {
label: "blue",
backgroundColor: "blue",
data: [38, 57, 75, 84]
},
{
label: "yellow",
backgroundColor: "yellow",
data: [97, null, 67, 41]
}
];
new Chart(document.getElementById("myChart"), {
type: 'bar',
data: {
labels: ["one", "two", "three", "four"],
datasets
},
options: {
title: {
display: true,
text: 'Grouped bar chart'
},
scales: {
xAxes: [{
ticks: {
callback: function(label, index, labels, chart) {
let result = "" // initialize
datasets.forEach((dataset) => {
if (dataset.data[index] !== null) {
result += (result.length > 0 ? ', ' : '') + dataset.label;
}
})
return result
}
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="200"></canvas>
Here you can find more options and explanation: https://tobiasahlin.com/blog/chartjs-charts-to-get-you-started/
I am following: http://radacad.com/create-custom-visual-with-r-and-json-part3
Here it is mentioned that with below R code, we can plot the chart:
Values<-data.frame(X,Y,Legend,Row,Column)
g=ggplot(Values, aes(x=X, y=Y,colour = Legend))
I am using similar implementations.
Below code renders blank chart with only axis:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = ~mpg_test,
y = ~cyl_test,
name = "SF Zoo",
type = "bar"
)
Empty chart
Below code also renders empty chart:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = mpg_test,
y = cyl_test,
name = "SF Zoo",
type = "bar"
)
Below code renders correct chart:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = ~mpg_test[1:nrow(Values), ],
y = ~cyl_test[1:nrow(Values), ],
name = "SF Zoo",
type = "bar"
)
Correct chart:
My doubt is, as per the tutorial I must get columns in mpg_test and cyl_test, then why I am getting something like dataframe in here.
Does, plotly handles things differently with the usage of ~ ?
Please help. Also, is there any way I can use the mpg_test and cyl_test without nrow(Values) inside plot_ly
script.r
source('./r_files/flatten_HTML.r')
############### Library Declarations ###############
libraryRequireInstall("ggplot2");
libraryRequireInstall("plotly")
####################################################
################### Actual code ####################
Values <- data.frame(mpt_test, cyl_test)
p <- plot_ly(Values,
x = ~mpt_test[1:nrow(Values), ],
y = ~cyl_test[1:nrow(Values), ],
name = "SF Zoo",
type = "bar"
)
####################################################
############# Create and save widget ###############
#p = ggplotly(p);
internalSaveWidget(p, 'out.html');
####################################################
capabilities.json
{
"dataRoles": [
{
"displayName": "Mileage Per Gallon",
"kind": "GroupingOrMeasure",
"name": "mpg_test"
},
{
"displayName": "Cylinder Size",
"kind": "GroupingOrMeasure",
"name": "cyl_test"
}
],
"dataViewMappings": [
{ "conditions": [
{
"mpg_test": {
"max": 1
},
"cyl_test": {
"max": 1
}
}
],
"scriptResult": {
"dataInput": {
"table": {
"rows": {
"select": [
{
"for": {
"in": "mpg_test"
}
},
{
"for": {
"in": "cyl_test"
}
}
],
"dataReductionAlgorithm": {
"top": {}
}
}
}
},
"script": {
"scriptProviderDefault": "R",
"scriptOutputType": "html",
"source": {
"objectName": "rcv_script",
"propertyName": "source"
},
"provider": {
"objectName": "rcv_script",
"propertyName": "provider"
}
}
}
}
],
"objects": {
"rcv_script": {
"properties": {
"provider": {
"type": {
"text": true
}
},
"source": {
"type": {
"scripting": {
"source": true
}
}
}
}
}
},
"suppressDefaultTitle": true
}
I'm trying to make nodes collapsed on click of node itself. The graph at present is force directed graph with draggable nodes.
Problem I'm facing is, after attaching the node click event I cannot get the click to fire instead node is displaced from it's position (like dragged on mouse click).
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
var graph = { "links" : [ { "relation" : "Relation 0",
"source" : 0,
"target" : 1
},
{ "relation" : "Relation 1",
"source" : 1,
"target" : 3
},
{ "relation" : "Relation 3",
"source" : 1,
"target" : 4
},
{ "relation" : "Relation 4",
"source" : 1,
"target" : 5
},
{ "relation" : "Relation 5",
"source" : 0,
"target" : 2
},
{ "relation" : "Relation 6",
"source" : 2,
"target" : 6
}
],
"nodes" : [ { "collapsed" : false,
"collapsing" : 0,
"id" : 0,
"name" : "Node 0"
},
{ "collapsed" : false,
"collapsing" : 0,
"id" : 1,
"name" : "Node 1"
},
{ "collapsed" : false,
"collapsing" : 0,
"id" : 2,
"name" : "Node 2"
},
{ "collapsed" : false,
"collapsing" : 0,
"id" : 3,
"name" : "Node 3"
},
{ "collapsed" : false,
"collapsing" : 0,
"id" : 4,
"name" : "Node 4"
},
{ "collapsed" : false,
"collapsing" : 0,
"id" : 5,
"name" : "Node 5"
},
{ "collapsed" : false,
"collapsing" : 0,
"id" : 6,
"name" : "Node 6"
}
]
};
var edges = [];
graph.links.forEach(function(e) {
var sourceNode = graph.nodes.filter(function(n) {
return n.id === e.source;
})[0],
targetNode = graph.nodes.filter(function(n) {
return n.id === e.target;
})[0];
edges.push({
source: sourceNode,
target: targetNode,
relation: e.relation
});
});
update();
function update() {
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 8)
.attr("fill", function(d) { return color(d.group); })
.on("click", togglenode)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
node.append("title")
.text(function(d) { return d.id; });
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
}
function dragstarted(d) {
console.log('drag started');
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
console.log('dragged');
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
console.log('drag ended');
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
function togglenode(d) {
console.log('clicked node : '+d.id);
if (!d3.event.defaultPrevented) {
var inc = d.collapsed ? -1 : 1;
recurse(d);
function recurse(sourceNode){
//check if link is from this node, and if so, collapse
edges.forEach(function(l) {
if (l.source.id === sourceNode.id){
l.target.collapsing += inc;
recurse(l.target);
}
});
}
d.collapsed = !d.collapsed;
update();
}
}
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
stroke-width: 4.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.js"></script>
<svg width="800" height="500"></svg>
i have geojson like this :
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "Name": "Saluran I", "descriptio": null, "timestamp": null, "begin": null, "end": null, "altitudeMo": null, "tessellate": 1, "extrude": -1, "visibility": -1, "drawOrder": null, "icon": null }, "geometry": { "type": "LineString", "coordinates": [ [ 115.16149264388849, -8.692345779607091 ], [ 115.1619799975747, -8.693099022961922 ], [ 115.1621209969948, -8.693450580043523 ], [ 115.1621893956145, -8.69367970180001 ], [ 115.1622369286341, -8.693885376054253 ], [ 115.16248624315379, -8.694125330077087 ], [ 115.1625293838875, -8.694297689361708 ], [ 115.1625662929434, -8.694480291402353 ], [ 115.1638244075253, -8.694489484612449 ] ] } },
{ "type": "Feature", "properties": { "Name": "Saluran II", "descriptio": null, "timestamp": null, "begin": null, "end": null, "altitudeMo": null, "tessellate": 1, "extrude": -1, "visibility": -1, "drawOrder": null, "icon": null }, "geometry": { "type": "LineString", "coordinates": [ [ 115.1647420393289, -8.691263798416188 ], [ 115.16480885306601, -8.691910749059817 ], [ 115.1648021389716, -8.692020041570267 ], [ 115.16476460026691, -8.692197857370241 ], [ 115.16467300953239, -8.692311184386924 ], [ 115.1645832229062, -8.692570845169653 ], [ 115.164590403574, -8.69280000074686 ], [ 115.1642184661912, -8.692878192437396 ], [ 115.16418831658579, -8.693471791565786 ], [ 115.16411080877791, -8.69417746825723 ], [ 115.1639500244154, -8.694469415766308 ], [ 115.1638498474275, -8.69450385891758 ], [ 115.1637726241196, -8.6949183073729 ], [ 115.1637482310352, -8.695106949243888 ], [ 115.16369576938609, -8.695516868583109 ], [ 115.1633930487843, -8.695552277605064 ], [ 115.1628619559151, -8.695616245099258 ], [ 115.1628453449146, -8.695861398016726 ], [ 115.1625531407406, -8.695981675836846 ], [ 115.1619167160671, -8.696110249672243 ], [ 115.1621001879372, -8.697348692504496 ], [ 115.1619454016469, -8.697429501488445 ] ] } },
{ "type": "Feature", "properties": { "Name": "Saluran III", "descriptio": null, "timestamp": null, "begin": null, "end": null, "altitudeMo": null, "tessellate": 1, "extrude": -1, "visibility": -1, "drawOrder": null, "icon": null }, "geometry": { "type": "LineString", "coordinates": [ [ 115.1649918428157, -8.698726927918452 ], [ 115.1647717936939, -8.698771893626452 ], [ 115.16464767674699, -8.698766178177538 ], [ 115.164531974608, -8.698766747854149 ], [ 115.1643076171094, -8.698759607942607 ], [ 115.1639182931609, -8.698808262913275 ], [ 115.1637251462856, -8.69887278452787 ], [ 115.1633890383243, -8.698973728970067 ], [ 115.1626822904817, -8.699201749498535 ], [ 115.1626359629325, -8.699082282748639 ], [ 115.1621957225977, -8.698410881596306 ], [ 115.16193358395429, -8.69743434218265 ] ] } }
]
}
i can showing that geojson on my map,
line.loadGeoJson(urlBase + 'peta/aliran.geojson');
// styling features aliran
line.setStyle(function(feature){
return {
strokeColor : '#0000FF',
strokeWeight : 5,
zIndex : 1
}
});
// set map;
line.setMap(map);
but i have problem when i want to animating symbols on the line like this : https://developers.google.com/maps/documentation/javascript/examples/overlay-symbol-animate. could anybody help me ?
Leveraging the code in this related example (which animates a marker along a polyline from the directions service) to animate a symbol along one of the polylines in your data:
proof of concept fiddle
code snippet:
var map;
var position;
var marker = null;
var polyline = null;
var poly2 = null;
var speed = 0.000005,
wait = 1;
var infowindow = null;
var myPano;
var panoClient;
var nextPanoId;
var timerHandle = null;
var polyline;
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var bounds = new google.maps.LatLngBounds();
map.data.addListener('addfeature', function(e) {
processPoints(e.feature.getGeometry(), bounds.extend, bounds);
if (e.feature.getGeometry().getType() == "LineString") {
polyline = new google.maps.Polyline({
map: map,
path: e.feature.getGeometry().getArray(),
strokeWeight: 5,
strokeOpacity: 0.4,
strokeColor: 'red'
});
marker = createMarker(polyline.getPath().getAt(0), "here", "marker text");
setTimeout(startAnimation, 2000);
}
map.fitBounds(bounds);
});
// var line = google.maps.Data;
map.data.addGeoJson(geoJson);
// styling features aliran
map.data.setStyle(function(feature) {
return {
strokeColor: '#0000FF',
strokeWeight: 1,
zIndex: 1
}
});
// set map;
map.data.setMap(map);
}
var step = 5; // metres
var tick = 100; // milliseconds
var eol;
var k = 0;
var stepnum = 0;
var speed = "";
var lastVertex = 1;
//=============== animation functions ======================
function updatePoly(d) {
// Spawn a new polyline every 20 vertices, because updating a 100-vertex poly is too slow
if (poly2.getPath().getLength() > 20) {
poly2 = new google.maps.Polyline([polyline.getPath().getAt(lastVertex - 1)]);
}
if (polyline.GetIndexAtDistance(d) < lastVertex + 2) {
if (poly2.getPath().getLength() > 1) {
poly2.getPath().removeAt(poly2.getPath().getLength() - 1)
}
poly2.getPath().insertAt(poly2.getPath().getLength(), polyline.GetPointAtDistance(d));
} else {
poly2.getPath().insertAt(poly2.getPath().getLength(), polyline.getPath().getAt(polyline.getPath().getLength() - 1));
}
}
function animate(d) {
if (d > eol) {
map.panTo(endLocation.latlng);
marker.setPosition(endLocation.latlng);
return;
}
var p = polyline.GetPointAtDistance(d);
map.panTo(p);
marker.setPosition(p);
updatePoly(d);
timerHandle = setTimeout("animate(" + (d + step) + ")", tick);
}
function startAnimation() {
if (timerHandle) clearTimeout(timerHandle);
eol = google.maps.geometry.spherical.computeLength(polyline.getPath());
map.setCenter(polyline.getPath().getAt(0));
poly2 = new google.maps.Polyline({
path: [polyline.getPath().getAt(0)],
strokeColor: "#0000FF",
strokeWeight: 10
});
setTimeout("animate(0)", tick); // Allow time for the initial map display
}
function processPoints(geometry, callback, thisArg) {
if (geometry instanceof google.maps.LatLng) {
callback.call(thisArg, geometry);
} else if (geometry instanceof google.maps.Data.Point) {
callback.call(thisArg, geometry.get());
} else {
geometry.getArray().forEach(function(g) {
processPoints(g, callback, thisArg);
});
}
}
// ==================================================
function createMarker(latlng, label, html) {
var contentString = '<b>' + label + '</b><br>' + html;
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: label,
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 8,
strokeColor: '#393'
},
zIndex: Math.round(latlng.lat() * -100000) << 5
});
marker.myname = label;
// gmarkers.push(marker);
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map, marker);
});
return marker;
}
google.maps.event.addDomListener(window, "load", initialize);
var geoJson = {
"type": "FeatureCollection",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [{
"type": "Feature",
"properties": {
"Name": "Saluran II",
"descriptio": null,
"timestamp": null,
"begin": null,
"end": null,
"altitudeMo": null,
"tessellate": 1,
"extrude": -1,
"visibility": -1,
"drawOrder": null,
"icon": null
},
"geometry": {
"type": "LineString",
"coordinates": [
[115.1647420393289, -8.691263798416188],
[115.16480885306601, -8.691910749059817],
[115.1648021389716, -8.692020041570267],
[115.16476460026691, -8.692197857370241],
[115.16467300953239, -8.692311184386924],
[115.1645832229062, -8.692570845169653],
[115.164590403574, -8.69280000074686],
[115.1642184661912, -8.692878192437396],
[115.16418831658579, -8.693471791565786],
[115.16411080877791, -8.69417746825723],
[115.1639500244154, -8.694469415766308],
[115.1638498474275, -8.69450385891758],
[115.1637726241196, -8.6949183073729],
[115.1637482310352, -8.695106949243888],
[115.16369576938609, -8.695516868583109],
[115.1633930487843, -8.695552277605064],
[115.1628619559151, -8.695616245099258],
[115.1628453449146, -8.695861398016726],
[115.1625531407406, -8.695981675836846],
[115.1619167160671, -8.696110249672243],
[115.1621001879372, -8.697348692504496],
[115.1619454016469, -8.697429501488445]
]
}
}]
};
/*********************************************************************\
* *
* epolys.js by Mike Williams *
* updated to API v3 by Larry Ross *
* *
* A Google Maps API Extension *
* *
* Adds various Methods to google.maps.Polygon and google.maps.Polyline *
* *
* .Contains(latlng) returns true is the poly contains the specified *
* GLatLng *
* *
* .Area() returns the approximate area of a poly that is *
* not self-intersecting *
* *
* .Distance() returns the length of the poly path *
* *
* .Bounds() returns a GLatLngBounds that bounds the poly *
* *
* .GetPointAtDistance() returns a GLatLng at the specified distance *
* along the path. *
* The distance is specified in metres *
* Reurns null if the path is shorter than that *
* *
* .GetPointsAtDistance() returns an array of GLatLngs at the *
* specified interval along the path. *
* The distance is specified in metres *
* *
* .GetIndexAtDistance() returns the vertex number at the specified *
* distance along the path. *
* The distance is specified in metres *
* Returns null if the path is shorter than that *
* *
* .Bearing(v1?,v2?) returns the bearing between two vertices *
* if v1 is null, returns bearing from first to last *
* if v2 is null, returns bearing from v1 to next *
* *
* *
***********************************************************************
* *
* This Javascript is provided by Mike Williams *
* Blackpool Community Church Javascript Team *
* http://www.blackpoolchurch.org/ *
* http://econym.org.uk/gmap/ *
* *
* This work is licenced under a Creative Commons Licence *
* http://creativecommons.org/licenses/by/2.0/uk/ *
* *
***********************************************************************
* *
* Version 1.1 6-Jun-2007 *
* Version 1.2 1-Jul-2007 - fix: Bounds was omitting vertex zero *
* add: Bearing *
* Version 1.3 28-Nov-2008 add: GetPointsAtDistance() *
* Version 1.4 12-Jan-2009 fix: GetPointsAtDistance() *
* Version 3.0 11-Aug-2010 update to v3 *
* *
\*********************************************************************/
// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetPointAtDistance = function(metres) {
// some awkward special cases
if (metres == 0) return this.getPath().getAt(0);
if (metres < 0) return null;
if (this.getPath().getLength() < 2) return null;
var dist = 0;
var olddist = 0;
for (var i = 1;
(i < this.getPath().getLength() && dist < metres); i++) {
olddist = dist;
dist += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));
}
if (dist < metres) {
return null;
}
var p1 = this.getPath().getAt(i - 2);
var p2 = this.getPath().getAt(i - 1);
var m = (metres - olddist) / (dist - olddist);
return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
}
// === A method which returns the Vertex number at a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetIndexAtDistance = function(metres) {
// some awkward special cases
if (metres == 0) return this.getPath().getAt(0);
if (metres < 0) return null;
var dist = 0;
var olddist = 0;
for (var i = 1;
(i < this.getPath().getLength() && dist < metres); i++) {
olddist = dist;
dist += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));
}
if (dist < metres) {
return null;
}
return i;
}
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<input type="button" value="restart animation" onclick="startAnimation()" />
<div id="map_canvas"></div>