Built with blockbuilder.org
forked from apolan's block: fresh block
forked from apolan's block: World's Biggest Data Breaches
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
#method-hack{background-color:#d6f0b1; position: relative; border: 3px solid #73AD21; margin: 150 20 0 20}
#rowPie{
height:auto;
}
#root_div{
}
#div_parent{
overflow:scroll;
height:748px;
}
#div_story{
margin: auto;
position : relative;
width:560px;
height:auto;
font-size: 120%;
border-style: solid;
border-width: 2px;
border-color: #ff0000 #0000ff;
}
#div_parent{
left : 0;
top : 0;
right : 0;
bottom : 0;
margin: auto;
position : relative;
width:600px;
height:500px;
}
path { stroke: #fff; }
path:hover { opacity:0.9; }
rect:hover { fill:blue; }
.axis { font: 10px sans-serif; }
.legend tr{ border-bottom:1px solid grey; }
.legend tr:first-child{ border-top:1px solid grey; }
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path { display: none; }
.legend{
margin-bottom:76px;
display:inline-block;
border-collapse: collapse;
border-spacing: 0px;
}
.legend td{
padding:4px 5px;
vertical-align:bottom;
}
.legendFreq, .legendPerc{
align:right;
width:50px;
}
</style>
</head>
<body>
<div id="root_div"></div>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
function dashboard(id, fData){
var barColor = 'steelblue';
function segColor(c){ return {Hacked:"#e54e25", inside:"#018040",accidentally:"#9a3a96",lost:"#2c3e50",poor:"#593718"}[c]; }
// compute total for each year.
fData.forEach(function(d){d.total=d.freq.Hacked+d.freq.inside+d.freq.accidentally+d.freq.lost+d.freq.poor;
});
// function to handle histogram.
function histoGram(fD){
var hG={}, hGDim = {t: 60, r: 0, b: 30, l: 0};
hGDim.w = 500 - hGDim.l - hGDim.r,
hGDim.h = 300 - hGDim.t - hGDim.b;
//create svg for histogram.
var hGsvg = d3.select(id).append("svg")
.attr("width", hGDim.w + hGDim.l + hGDim.r)
.attr("height", hGDim.h + hGDim.t + hGDim.b).append("g")
.attr("transform", "translate(" + hGDim.l + "," + hGDim.t + ")");
// create function for x-axis mapping.
var x = d3.scale.ordinal().rangeRoundBands([0, hGDim.w], 0.1)
.domain(fD.map(function(d) { return d[0]; }));
// Add x-axis to the histogram svg.
hGsvg.append("g").attr("class", "x axis")
.attr("transform", "translate(0," + hGDim.h + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
// Create function for y-axis map.
var y = d3.scale.linear().range([hGDim.h, 0])
.domain([0, d3.max(fD, function(d) { return d[1]; })]);
// Create bars for histogram to contain rectangles and freq labels.
var bars = hGsvg.selectAll(".bar").data(fD).enter()
.append("g").attr("class", "bar");
//create the rectangles.
bars.append("rect")
.attr("x", function(d) { return x(d[0]); })
.attr("y", function(d) { return y(d[1]); })
.attr("width", x.rangeBand())
.attr("height", function(d) { return hGDim.h - y(d[1]); })
.attr('fill',barColor)
.on("mouseover",mouseover)// mouseover is defined below.
.on("mouseout",mouseout);// mouseout is defined below.
//Create the frequency labels above the rectangles.
bars.append("text").text(function(d){
if (d[1] >= 1000000000) {
return (d[1] / 1000000000).toFixed(1).replace(/\.0$/, '') + 'G';
}
if (d[1] >= 1000000) {
return (d[1] / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
}
if (d[1] >= 1000) {
return (d[1] / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
}
return d[1];
})
.attr("x", function(d) { return x(d[0])+x.rangeBand()/2; })
.attr("y", function(d) { return y(d[1])-5; })
.attr("text-anchor", "middle");
function mouseover(d){ // utility function to be called on mouseover.
// filter for selected state.
var st = fData.filter(function(s){ return s.year == d[0];})[0],
nD = d3.keys(st.freq).map(function(s){ return {type:s, freq:st.freq[s]};});
// call update functions of pie-chart and legend.
pC.update(nD);
leg.update(nD);
}
function mouseout(d){ // utility function to be called on mouseout.
// reset the pie-chart and legend.
pC.update(tF);
leg.update(tF);
}
// create function to update the bars. This will be used by pie-chart.
hG.update = function(nD, color){
// update the domain of the y-axis map to reflect change in frequencies.
y.domain([0, d3.max(nD, function(d) { return d[1]; })]);
// Attach the new data to the bars.
var bars = hGsvg.selectAll(".bar").data(nD);
// transition the height and color of rectangles.
bars.select("rect").transition().duration(500)
.attr("y", function(d) {return y(d[1]); })
.attr("height", function(d) { return hGDim.h - y(d[1]); })
.attr("fill", color);
// transition the frequency labels location and change value.
bars.select("text").transition().duration(500)
.text(function(d){
if (d[1] >= 1000000000) {
return (d[1] / 1000000000).toFixed(1).replace(/\.0$/, '') + 'G';
}
if (d[1] >= 1000000) {
return (d[1] / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
}
if (d[1] >= 1000) {
return (d[1] / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
}
return d[1];
})
.attr("y", function(d) {return y(d[1])-5; });
}
return hG;
}
// function to handle pieChart.
function pieChart(pD){
var pC ={}, pieDim ={w:250, h: 250};
pieDim.r = Math.min(pieDim.w, pieDim.h) / 2;
// create svg for pie chart.
var piesvg = d3.select(id).append("svg")
.attr("width", pieDim.w).attr("height", pieDim.h).append("g")
.attr("transform", "translate("+pieDim.w/2+","+pieDim.h/2+")");
// create function to draw the arcs of the pie slices.
var arc = d3.svg.arc().outerRadius(pieDim.r - 10).innerRadius(0);
// create a function to compute the pie slice angles.
var pie = d3.layout.pie().sort(null).value(function(d) { return d.freq; });
// Draw the pie slices.
piesvg.selectAll("path").data(pie(pD)).enter().append("path").attr("d", arc)
.each(function(d) { this._current = d; })
.style("fill", function(d) { return segColor(d.data.type); })
.on("mouseover",mouseover).on("mouseout",mouseout);
// create function to update pie-chart. This will be used by histogram.
pC.update = function(nD){
piesvg.selectAll("path").data(pie(nD)).transition().duration(500)
.attrTween("d", arcTween);
}
// Utility function to be called on mouseover a pie slice.
function mouseover(d){
// call the update function of histogram with new data.
hG.update(fData.map(function(v){
return [v.year,v.freq[d.data.type]];}),segColor(d.data.type));
}
//Utility function to be called on mouseout a pie slice.
function mouseout(d){
// call the update function of histogram with all data.
hG.update(fData.map(function(v){
return [v.year,v.total];}), barColor);
}
// Animating the pie-slice requiring a custom function which specifies
// how the intermediate paths should be drawn.
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) { return arc(i(t)); };
}
return pC;
}
// function to handle legend.
function legend(lD){
var leg = {};
// create table for legend.
var legend = d3.select(id).append("table").attr('class','legend');
// create one row per segment.
var tr = legend.append("tbody").selectAll("tr").data(lD).enter().append("tr");
// create the first column for each segment.
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect")
.attr("width", '16').attr("height", '16')
.attr("fill",function(d){ return segColor(d.type); });
// create the second column for each segment.
tr.append("td").text(function(d){ return d.type;});
// create the third column for each segment.
tr.append("td").attr("class",'legendFreq')
.text(function(d){ return d3.format(",")(d.freq);});
// create the fourth column for each segment.
tr.append("td").attr("class",'legendPerc')
.text(function(d){ return getLegend(d,lD);});
// Utility function to be used to update the legend.
leg.update = function(nD){
// update the data attached to the row elements.
var l = legend.select("tbody").selectAll("tr").data(nD);
// update the frequencies.
l.select(".legendFreq").text(function(d){ return d3.format(",")(d.freq);});
// update the percentage column.
l.select(".legendPerc").text(function(d){ return getLegend(d,nD);});
}
function getLegend(d,aD){ // Utility function to compute percentage.
return d3.format("%")(d.freq/d3.sum(aD.map(function(v){ return v.freq; })));
}
return leg;
}
// calculate total frequency by segment for all state.
var tF = ['Hacked','inside','lost','accidentally','poor'].map(function(d){
return {type:d, freq: d3.sum(fData.map(function(t){ return t.freq[d];}))};
});
// calculate total frequency by state for all segment.
var sF = fData.map(function(d){return [d.year,d.total];});
// Se modifica
var pC = pieChart(tF); // create the pie-chart.
var leg= legend(tF); // create the legend.
var hG = histoGram(sF); // create the histogram.
}
function enable(){
dashboard('#dashboard',freqData);
}
function deleteAll(){
document.write(" ");
}
var status = 'none';
var pieCreated = 'no';
/*
Metodo que inicia la visualizacion
*/
function startVis(){
var items=[{method:'hacked',label:'Hacked',description:'Story: Investigators believe the data was obtained via software installed on machines that customers use to swipe magnetic strips on their cards when paying for merchandise at Target stores. Originally 40m customers. Now 70m! of records', color:'#e54e25'},
{method:'inside',label:'Inside Job',description:'Story: Two multimedia discs containing the names, social security numbers, addresses, cell phone numbers, email addresses and workplaces of Korean customers sorted by age were stolen. They were found by an office worker in a backstreet’s trash pile in Seoul. Experts say a GS Caltex employee likely stole the information for personal purposes given there were no signs of hacking.', color:'#018040'},
{method:'lost',label:'Lost data',description:'Story: Names, Social Security numbers, health insurance identification numbers, health insurance information, dates of birth, diagnoses, other medical information, disability codes, addresses, and phone numbers may have been exposed via a laptop theft.', color:'#2c3e50'},
{method:'accidentally',label:'Accidentally published',description:'Story: An employee of the agency inadvertently sent the passport numbers, visa details and other personal identifiers of all world leaders attending the G20 Brisbane summit to the organisers of the Asian Cup football tournament. Barack Obama, Vladimir Putin, Angela Merkel, Xi Jinping, Narendra Modi, David Cameron and many others.', color:'#9a3a96'},
{method:'poor',label:'Poor Security',description:'Story: A freedom of information request resulted in the release of data on all 173 million journeys undertaken by New York taxis in one year. Unfortunately, the data was incorrectly anonymised and relatively easy to decode, revealing the driver IDs, pickup & dropoff times, and GPS routes taken for every single cab journey.', color:'#593718'}
]
var div_parent = document.createElement("div");
div_parent.setAttribute("id","div_parent");
div_parent.overflow = "hidden";
// Creacion de la tabla de los elementos
var table = document.createElement("TABLE");
table.setAttribute("id", "myTable");
var rowPic = document.createElement("TR");
rowPic.setAttribute("id", "rowPic");
var rowNode = document.createElement("TR");
rowNode.setAttribute("id", "rowNode");
var rowStory = document.createElement("TR");
rowStory.setAttribute("id", "rowStory");
var td_story = document.createElement('TD');
td_story.setAttribute("id","td_story");
td_story.style.textAlign = 'center';
document.getElementById("root_div").appendChild(div_parent);
// loop de los elementos legenda
items.forEach(function(name){
var node = document.createElement("p");
node.style.display="inline";
node.id=name.method+"_style";
node.style.margin ="0px 0px 0px 0px";
node.style.fontSize ="x-large";
node.onmouseover = function(){
var p = document.getElementsByTagName("p");
for(i = 0;i < p.length; i++){
if(p[i].id != name.method+"_style"){
p[i].style.color = "#A4A4A4";
}else if(status != name.method){
// Crea la descripcion del legend
p[i].style.fontWeight="bold";
var p1 = document.createElement("p");
p1.setAttribute("id","p_"+name.method);
p1.innerHTML="<br><br>"+name.description;
p1.style.margin = "5px 10px 5px 10px";
p1.style.fontSize ="large";
p1.style.color ="black";
td_story.appendChild(p1);
}
}
p = document.getElementsByTagName("img");
for(i = 0;i < p.length; i++){
if(p[i].id != name.method+"_pic"){
p[i].src = 'https://cocreacionseguros.files.wordpress.com/2016/05/'+(p[i].id).replace("_pic","")+'_gray2.png';
}else{
}
}
};
node.onmouseout = function(){
var p = document.getElementsByTagName("p");
for(i = 0;i < p.length; i++){
if(p[i].id != name.method+"_style"){
p[i].style.color = "black";
p[i].style.fontWeight="normal";
}else{
if(status != name.method ){
}
try {
document.getElementById("p_"+name.method).remove();
}
catch(err) {}
}
}
var p = document.getElementsByTagName("img");
for(i = 0;i < p.length; i++){
if(p[i].id != name.method+"_pic"){
p[i].src = p[i].src = 'https://cocreacionseguros.files.wordpress.com/2016/05/'+(p[i].id).replace("_pic","")+'_color2.png';
}else{
//node.style.fontSize ="medium";
//p[i].style.fontWeight="normal";
}
}
};
node.innerHTML = name.label;
var img = document.createElement('img');
img.src = 'https://cocreacionseguros.files.wordpress.com/2016/05/'+name.method+'_color2.png';
img.setAttribute("id", name.method+"_pic");
img.heigth=60;
img.width=60;
if(name.method=="hacked"){
node.onclick=action_hacked;
img.onclick=action_hacked;
}else if(name.method=="inside"){
node.onclick=action_inside;
img.onclick=action_inside;
}else if(name.method=="lost"){
node.onclick=action_lost;
img.onclick=action_lost;
}else if(name.method=="accidentally"){
node.onclick=action_accidentally;
img.onclick=action_accidentally;
}else if(name.method=="poor"){
node.onclick=action_poor;
img.onclick=action_poor;
}
var col = document.createElement('TD');
col.setAttribute("width","150px");
col.style.width = '2px';
col.style.textAlign = 'center';
col.appendChild(node);
rowPic.appendChild(col);
col = document.createElement('TD');
col.setAttribute("width","150px");
col.appendChild(img);
col.style.textAlign = 'center';
rowNode.appendChild(col);
});
td_story.colSpan = "5";
rowStory.appendChild(td_story);
table.appendChild(rowNode);
table.appendChild(rowPic);
table.appendChild(rowStory);
div_parent.appendChild(table);
}
function action_hacked() {
if(status == 'hacked'){
return;
}
window.alert("entra hacked: " + status);
if(status != 'none'){
document.getElementById("p_2"+status).remove();
status = 'hacked';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}else{
status = 'hacked';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}
startPie();
}
function action_inside() {
if(status == 'inside'){
return;
}
window.alert("entra inside: " + status);
if(status != 'none'){
document.getElementById("p_2"+status).remove();
status = 'inside';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}else{
status = 'inside';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}
startPie();
}
function action_lost() {
if(status == 'lost'){
return;
}
window.alert("entra lost");
if(status != 'none'){
document.getElementById("p_2"+status).remove();
status = 'lost';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}else{
status = 'lost';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}
startPie();
}
function action_accidentally() {
if(status == 'accidentally'){
return;
}
window.alert("entra accidentally");
if(status != 'none'){
document.getElementById("p_2"+status).remove();
status = 'accidentally';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}else{
status = 'accidentally';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}
startPie();
}
function action_poor() {
if(status == 'poor'){
return;
}
window.alert("entra poor");
if(status != 'none'){
document.getElementById("p_2"+status).remove();
status = 'poor';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}else{
status = 'poor';
var p1 = document.getElementById("p_"+status);
p1.setAttribute("id","p_2"+status);
}
startPie();
}
function startPie(){
if(pieCreated != 'yes'){
// Creacion de la tabla de los elementos
var table = document.getElementById("myTable");
var rowPie = document.createElement("TR");
rowPie.setAttribute("id", "rowPie");
var td_pie = document.createElement('TD');
td_pie.colSpan = "5";
td_pie.setAttribute("id","td_pie");
td_pie.style.textAlign = 'center';
rowPie.appendChild(td_pie);
table.appendChild(rowPie);
pieCreated='yes';
dashboard('#td_pie',freqData);
}
}
startVis();
</script>
<script>
// Es el overview de la situacion
var freqData=[
{year:'2004',freq:{Hacked:0, inside:92000000, lost:0, accidentally:0, poor:0}}
,{year:'2005',freq:{Hacked:40000000, inside:0, lost:4100000, accidentally:0, poor:130000}}
,{year:'2006',freq:{Hacked:4000000, inside:2600000, lost:43700000, accidentally:20000000, poor:0}}
,{year:'2007',freq:{Hacked:106100000, inside:18190000, lost:31960000, accidentally:0, poor:0}}
,{year:'2008',freq:{Hacked:24500000, inside:11100000, lost:18906000, accidentally:11600000, poor:0}}
,{year:'2009',freq:{Hacked:176560000, inside:0, lost:80202000, accidentally:0, poor:0}}
,{year:'2010',freq:{Hacked:5960000, inside:1000000, lost:9210000, accidentally:0, poor:0}}
,{year:'2011',freq:{Hacked:198815000, inside:2500000, lost:21435000, accidentally:4580000, poor:1680000}}
,{year:'2012',freq:{Hacked:462330000, inside:202000000, lost:800000, accidentally:27480000, poor:300000}}
,{year:'2013',freq:{Hacked:294906000, inside:3700000, lost:4300000, accidentally:7680000, poor:300000}}
,{year:'2014',freq:{Hacked:393000000, inside:20000000, lost:0, accidentally:0, poor:132000}}
,{year:'2015',freq:{Hacked:187200000, inside:0, lost:0, accidentally:500000, poor:3950000}}
,{year:'2016',freq:{Hacked:457670436, inside:68614105, lost:0, accidentally:0, poor:191000010}}
];
</script>
</body>
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js
https://d3js.org/d3.v3.min.js