How to write haml code for corresponding javascript? - sinatra

Here is the haml that i have created out of html. But it doesn't seem to give any output. Please help me to find out the error. May be I am going somewhere wrong with the syntax or not getting what to put in the index section of haml.
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra'
require 'haml'
get '/' do
haml :index
end
__END__
## layout
%html
%head
%meta{:charset => "utf-8"}/
:css
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
%body
%script{:src => "http://d3js.org/d3.v3.js"}
:javascript
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.ID); })
.y(function(d) { return y(d.temperature); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.tsv("pckt_thru.tsv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "ID"; }));
data.forEach(function(d) {
d.ID = +d.ID;
});
var cities = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {ID: d.ID, temperature: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.ID; }));
y.domain([
d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }),
d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("VALUES");
var city = svg.selectAll(".city")
.data(cities)
.enter().append("g")
.attr("class", "city");
city.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
city.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.ID) + "," + y(d.value.temperature) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
});
=yield
## index
#header
%h1 Graph using Sinatra

You're missing all the % signs off the beginning of elements, e.g. html should be %html. See the tutorial. Hope that helps.

If this is the exact source and no typos.
You are missing % on the tags
%html # not html
Your nesting seems to be incorrect
%html
%meta
%body
%html
%head
%meta
%body
Try running your original html/erb through http://html2haml.heroku.com. That might help you get started if you don't know HAML at all.

Related

FileManagerBundle. Implement FileMangerBundle (artgris) using TinyMCE v6.2 with Symfony4

I have tinyMCE 6.2 in my project. How to chose file?
And I can't choose an image by click or by check.
The selected file path (tinymceCallBackURL) is empty. Can you help me?
tinyMCE init:
tinymce.init({ selector: '.tinymce', file_picker_callback: myFileBrowser, .......... }
My code js:
var type = meta.filetype;
var cmsURL = "file_manager/?conf=tiny";
if (cmsURL.indexOf("?") < 0) {
cmsURL = cmsURL + "?type=" + type;
} else {
cmsURL = cmsURL + "&type=" + type;
}
var windowManagerCSS = '<style type="text/css">' + '.tox-dialog {max-width: 100%!important; width:97.5%!important; overflow: hidden; height:95%!important; border-radius:0.25em;}' + '.tox-dialog__body { padding: 0!important; }' + '.tox-dialog__body-content > div { height: 100%; overflow:hidden}' + '</style> ';
window.tinymceCallBackURL = '';
window.tinymceWindowManager = tinymce.activeEditor.windowManager;
tinymceWindowManager.open({
title: 'Menedżer plików',
url: cmsURL,
body: {
type: 'panel',
items: [{
type: 'htmlpanel',
html: windowManagerCSS + <iframe src="/file_manager/?conf=tiny&type=${type}" style="width:100%; height:500px" id="filemanager"></iframe> }]
},
buttons: [],
onClose: function () {
if (tinymceCallBackURL != '') callback(tinymceCallBackURL, {}); //to set selected file path } }); }````
I have a solution. (unswer in github issue https://github.com/artgris/FileManagerBundle/issues/107):
I needed to add module=tiny in cmsURL :
var cmsURL = "file_manager/?module=tiny&conf=tiny";
and replace:
html: windowManagerCSS + '<iframe src="/file_manager/?conf=tiny&type=${type}" ... thinking
with:
html: windowManagerCSS + '<iframe src="' + cmsURL ...
https://github.com/artgris/FileManagerBundle/blob/master/Resources/doc/tutorials/integrate-tinymce.md

Chartjs stacked bar separate tooltip for all stacked

I want to make a separate tooltip for every stacked bar, Ex. My demo "2022-01-17" has TWO stacked bars with FOUR values but I need a total of Stack 1 group and Stack 2 group
I've reviewed most of the options in chartjs https://www.chartjs.org/docs/3.5.1/samples/bar/stacked-groups.html
var barChartData = {
labels: ["2022-01-17","2022-01-18","2022-01-19","2022-01-20","2022-01-21","2022-01-22","2022-01-23","2022-01-24","2022-01-25","2022-01-26","2022-01-27","2022-01-28","2022-01-29","2022-01-30"],
datasets: [{"label":"Product 2","data":["292.53","328.5","273.83","305.44","260.33","251.87","118.15","253.95","86.64","87.78","116.68","295.49","61.32","83.78"],"backgroundColor":"#66bb6a","borderColor":"#66bb6a","pointBackgroundColor":"#66bb6a","stack":"Stack 0"},{"label":"Product ","data":["1522.27","1844.83","1581.01","2767.68","2821.36","2940.31","2876.1","2037.79","1593.01","1900.86","1607.21","2188.92","2428.74","2508.81"],"backgroundColor":"#1b5e20","borderColor":"#1b5e20","pointBackgroundColor":"#1b5e20","stack":"Stack 0"},{"label":"Product 2","data":["200","4.14","28.51","13.68","0","0","19.93","0","0","0","10.47","23.05","9.42","10.58"],"backgroundColor":"#ffcdd2","borderColor":"#ffcdd2","pointBackgroundColor":"#ffcdd2","stack":"Stack 1"},{"label":"Product ","data":["680.2","536.51","524.41","479.69","453.19","521.87","530.57","485.13","440.25","591.29","722.73","711.58","686.63","510.72"],"backgroundColor":"#ef9a9a","borderColor":"#ef9a9a","pointBackgroundColor":"#ef9a9a","stack":"Stack 1"}]
};
const footer = (tooltipItems) => {
let sum = 0;
tooltipItems.forEach(function(tooltipItem) {
sum += tooltipItem.parsed.y;
});
return 'Sum: ' + sum;
};
var ctx = document.getElementById("canvas").getContext("2d");
var myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
interaction: {
intersect: false,
mode: 'index',
},
plugins: {
tooltip: {
callbacks: {
footer: (tooltipItem) => {
let sum = 0;
tooltipItem.forEach(function(tooltipItem) {
sum += tooltipItem.parsed.y;
});
return 'Sum: ' + sum;
}
}
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.7.0/dist/chart.min.js"></script>
<canvas id="canvas" height="100"></canvas>
to get the total of each stack, you can use the dataPoints found in the tooltip context
and use the dataset labels to group by each stack
// group stacks
const groups = {};
tooltip.dataPoints.forEach(function (point) {
if (groups.hasOwnProperty(barChartData.datasets[point.datasetIndex].label)) {
groups[barChartData.datasets[point.datasetIndex].label] += parseFloat(barChartData.datasets[point.datasetIndex].data[point.dataIndex]);
} else {
groups[barChartData.datasets[point.datasetIndex].label] = parseFloat(barChartData.datasets[point.datasetIndex].data[point.dataIndex]);
}
});
e.g. --> {"Product 2":492.53,"Product ":2202.4700000000003}
then use the external option to create a custom tooltip
see following working snippet...
$(document).ready(function() {
var barChartData = {
labels: ["2022-01-17","2022-01-18","2022-01-19","2022-01-20","2022-01-21","2022-01-22","2022-01-23","2022-01-24","2022-01-25","2022-01-26","2022-01-27","2022-01-28","2022-01-29","2022-01-30"],
datasets: [{"label":"Product 2","data":["292.53","328.5","273.83","305.44","260.33","251.87","118.15","253.95","86.64","87.78","116.68","295.49","61.32","83.78"],"backgroundColor":"#66bb6a","borderColor":"#66bb6a","pointBackgroundColor":"#66bb6a","stack":"Stack 0"},{"label":"Product ","data":["1522.27","1844.83","1581.01","2767.68","2821.36","2940.31","2876.1","2037.79","1593.01","1900.86","1607.21","2188.92","2428.74","2508.81"],"backgroundColor":"#1b5e20","borderColor":"#1b5e20","pointBackgroundColor":"#1b5e20","stack":"Stack 0"},{"label":"Product 2","data":["200","4.14","28.51","13.68","0","0","19.93","0","0","0","10.47","23.05","9.42","10.58"],"backgroundColor":"#ffcdd2","borderColor":"#ffcdd2","pointBackgroundColor":"#ffcdd2","stack":"Stack 1"},{"label":"Product ","data":["680.2","536.51","524.41","479.69","453.19","521.87","530.57","485.13","440.25","591.29","722.73","711.58","686.63","510.72"],"backgroundColor":"#ef9a9a","borderColor":"#ef9a9a","pointBackgroundColor":"#ef9a9a","stack":"Stack 1"}]
};
var ctx = document.getElementById("canvas").getContext("2d");
var myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
interaction: {
intersect: false,
mode: 'index',
},
plugins: {
tooltip: {
enabled: false,
position: 'nearest',
external: function (context) {
// init
const {chart, tooltip} = context;
// remove old tooltip
var container = chart.canvas.parentNode.querySelector('.tooltip');
if (container) {
chart.canvas.parentNode.removeChild(container);
}
// determine if tooltip exists
if (tooltip.opacity === 0) {
return;
}
// group stacks
const groups = {};
tooltip.dataPoints.forEach(function (point) {
if (groups.hasOwnProperty(barChartData.datasets[point.datasetIndex].label)) {
groups[barChartData.datasets[point.datasetIndex].label] += parseFloat(barChartData.datasets[point.datasetIndex].data[point.dataIndex]);
} else {
groups[barChartData.datasets[point.datasetIndex].label] = parseFloat(barChartData.datasets[point.datasetIndex].data[point.dataIndex]);
}
});
// build tooltip rows
var rows = '';
Object.keys(groups).forEach(function (groupName) {
rows += renderTemplate('template-tooltip-row', {
group: groupName,
value: groups[groupName].toLocaleString(undefined, {minimumFractionDigits: 2})
});
});
// build tooltip
chart.canvas.parentNode.insertAdjacentHTML('beforeEnd', renderTemplate('template-tooltip', {
rows: rows,
title: tooltip.title[0]
}));
// position tooltip
const {offsetLeft: positionX, offsetTop: positionY} = chart.canvas;
container = chart.canvas.parentNode.querySelector('.tooltip');
container.style.left = positionX + tooltip.caretX + 'px';
container.style.top = positionY + tooltip.caretY + 'px';
container.style.font = tooltip.options.bodyFont.string;
container.style.padding = tooltip.options.padding + 'px ' + tooltip.options.padding + 'px';
}
}
}
}
});
/**
* render html template
* #param {string} templateId - id of html template
* #param {object} templateValues - values for each template placeholder
* #return {string} template content
*/
function renderTemplate(templateId, templateValues) {
var propHandle; // property key
var templateText; // html template content
var templateValue; // value for template placeholder
// get template content, replace each placeholder with value
templateText = document.querySelector('#' + templateId).innerHTML;
if (templateValues) {
for (propHandle in templateValues) {
if (templateValues.hasOwnProperty(propHandle)) {
templateValue = '';
// convert template value to string
if (templateValues[propHandle] !== null) {
if (templateValues[propHandle].hasOwnProperty('results')) {
templateValue = encodeURIComponent(JSON.stringify(templateValues[propHandle].results));
} else {
templateValue = templateValues[propHandle].toString();
}
}
// handle dollar sign in template value
if (templateValue.indexOf('$') > -1) {
templateValue = templateValue.replace(new RegExp('\\$', 'g'), '$$$');
}
// replace template placeholder(s) with template value
if (templateText.indexOf('{{' + propHandle + '}}') > -1) {
templateText = templateText.replace(
new RegExp('{{' + propHandle + '}}', 'g'),
templateValue
);
}
}
}
}
return templateText.trim();
}
});
.align-right {
text-align: right;
}
.table {
border-collapse: separate;
border-spacing: 0vw 0vw;
display: table;
}
.table-body {
display: table-row-group;
}
.table-cell {
display: table-cell;
padding: 4px;
}
.table-foot {
display: table-footer-group;
}
.table-head {
display: table-header-group;
}
.table-row {
display: table-row;
}
.title {
font-weight: bold;
}
.tooltip {
background-color: rgba(0, 0, 0, 0.85);
border-radius: 3px;
color: #ffffff;
pointer-events: none;
position: absolute;
transform: translate(-50%, 0);
transition: all 0.1s ease;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.7.0/dist/chart.min.js"></script>
<canvas id="canvas" height="100"></canvas>
<script id="template-tooltip" type="text/html">
<div class="tooltip">
<div class="title">{{title}}</div>
<div class="table">
<div class="table-body">{{rows}}</div>
</div>
</div>
</script>
<script id="template-tooltip-row" type="text/html">
<div class="table-row">
<div class="table-cell title">{{group}}:</div>
<div class="table-cell align-right">{{value}}</div>
</div>
</script>

How can I see the information from a tooltip of a circle marker which is contained within a polygon which also has a tooltip

I am very new to leaflet.
Below is my code where a polygon layer and a point layer are loaded from Geoserver through wfs service.
Each layer has a tooltip. When the two layers do not overlap the tooltips work as expected. When a point overlaps a polygon, in its position the tooltip of the polygon is shown. Unfortunately, for my purposes, when the two geometries overlap I want only the circle marker tooltip to be shown, that is exactly the opposite behavior than it is currently doing. It seems to be a kind of issue so impossible to solve for me.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1,user-scalable=no,maximum-scale=1,width=device-width">
<title>Example Leaflet</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css">
</head>
<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100%;
}
</style>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet#1.0.3/dist/leaflet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
var map = new L.Map('map');
var OSM = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: '© OpenStreetMap contributors'}).addTo(map);
var myRenderer = L.canvas({padding: 0.5});
var dataset = new L.layerGroup().addTo(map);
$.ajax({
url: 'http://46.101.36.208:8080/geoserver/ows?service=WFS&version=2.0&request=GetFeature&typeName=deep_map:point_tooltip_test&outputFormat=text/javascript&format_options=callback:getJson1&SrsName=EPSG:4326&MaxFeatures=200',
dataType: 'jsonp',
jsonpCallback: 'getJson1',
success: function(response) {
WFSLayer1 = L.geoJson(response, {
style: function(feature) {
return {
color: '#696969'
};
},
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, {
renderer: myRenderer
});
},
onEachFeature: function(feature, layer) {
var popupText = '';
if (feature.properties.NOMECOMUNE) {
popupText += "<b>NOMECOMUNE: </b>" + feature.properties.NOMECOMUNE + "<br />";
}
if (feature.properties.CIVICO) {
popupText += "<b>CIVICO: </b>" + feature.properties.CIVICO + "<br />";
}
layer.bindTooltip(popupText, {'sticky': true});
}
}).addTo(dataset);
// map.fitBounds(WFSLayer1.getBounds());
}
});
$.ajax({
url: 'http://46.101.36.208:8080/geoserver/ows?service=WFS&version=2.0&request=GetFeature&typeName=deep_map:polygon_tooltip_test&outputFormat=text/javascript&format_options=callback:getJson2&SrsName=EPSG:4326&MaxFeatures=200',
dataType: 'jsonp',
jsonpCallback: 'getJson2',
success: function(response) {
WFSLayer2 = L.geoJson(response, {
style: function(feature) {
return {
stroke: true,
fillOpacity: 0
};
},
onEachFeature: function(feature, layer) {
var popupText = '';
if (feature.properties.NOMECOMUNE) {
popupText += "<b>NOMECOMUNE: </b>" + feature.properties.NOMECOMUNE + "<br />";
}
if (feature.properties.ZONA) {
popupText += "<b>TIPO ZONA: </b>" + feature.properties.ZONA + "<br />";
}
if (feature.properties.DEN_FI) {
popupText += "<b>AREA DI RISPETTO: </b>" + feature.properties.DEN_FI + "<br />";
}
if (feature.properties.TR_VINC) {
popupText += "<b>TRATTO VINCOLATO: </b>" + feature.properties.TR_VINC + "<br />";
}
if (feature.properties.DESCRIZION) {
popupText += "<b>CATEGORIA FORESTALE: </b>" + feature.properties.DESCRIZION + "<br />";
}
if (feature.properties.GIARDINI) {
popupText += "<b>PRESENZA GIARDINI: </b>" + feature.properties.GIARDINI + "<br />";
}
if (feature.properties.STAB_INDUS) {
popupText += "<b>STABILIMENTO A RISCHIO INCIDENTE GRAVE: </b>" + feature.properties.STAB_INDUS + "<br />";
}
if (feature.properties.CHANGETYPE) {
popupText += "<b>VARIAZIONI: </b>" + feature.properties.CHANGETYPE + "<br />";
}
layer.bindTooltip(popupText, {'sticky': true});
}
}).addTo(map);
map.fitBounds(WFSLayer2.getBounds());
}
});
map.on('zoomend', function() {
if (map.getZoom() < 16){
map.removeLayer(dataset);
}
else {
map.addLayer(dataset);
}
});
var BaseMap = {
"Base map": map
};
L.control.layers(BaseMap).addTo(map);
</script>
</html>
What I tried
I tried to create two explicit separate panes for each layer as follow:
map.createPane("polygonsPane");
map.createPane("pointsPane");
map.getPane('pointsPane').style.zIndex = 750;
map.getPane('polygonsPane').style.zIndex = 350;
Then I assigned each layer to its pane inside the style section.
For the polygon layer:
style: function(feature) {
return {
stroke: true,
fillOpacity: 1,
pane: "polygonsPane"
};
},
And for the point layer:
style: function(feature) {
return {
stroke: true,
fillOpacity: 1,
pane: "pointsPane"
};
},
With this, I was able to bring the points to the front and to make the tooltip work. Unfortunately, the tooltip for the polygon doesn't show anymore!
I'm very new to Leaflet. I'm sure I'm missing something obvious but I've been racking my brain trying to see what I'm missing. I would really appreciate it if anyone is able to give me a workaround.
Thank you very much.

How to add visualization to the charts created using d3.js?

This is my sample code to generate a bar chart. When I click on a particular column, it should lead to another page. Please help me with it. Another thing is how can I make the charts more interactive and use event handling?
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(formatPercent);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.tsv("data.tsv", function(error, data) {
data.forEach(function(d) {
d.frequency = +d.frequency;
});
function mouseover(d, i) {
d3.select(rect[0][i]).style("fill", "red");
}
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); });
});
</script>
In both cases, use the .on() functions described in the d3 api.
To cause a navigation to a new page, attach an "on()" method to your column (rectangle), using an event handler like
.on( "click", function(d,i) {
window.location.href='mynextPage';
})

How to add events to the individual sections(arcs) of a pie chart created out of d3.js?

This is a basic code to create a pie chart for protocol distribution. In my .csv file, I have two columns viz., protocol name and the percentage.I want to add events on individual arcs. For example, when i click only on the arc containing TCP stats, it should lead to another page. Please help how can i do this. I was able to add click event for the pie chart as whole.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.arc path {
stroke: #fff;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.count; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.csv("flow_count.csv", function(error, data) {
data.forEach(function(d) {
d.count = +d.count;
});
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.proto); });
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function(d) { return d.data.proto; });
g.on( "click", function(d,i) {
window.location.href='index.html';
})
});
</script>
Within the "svg.selectAll(".bar") you could add an on click line:
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); })
.on("click", function(d) {
// code you want executed on the click event
});