|
<!DOCTYPE html> |
|
<html> |
|
<meta charset="UTF-8"> |
|
<head> |
|
<title>Lønnsindeks</title> |
|
<script src="https://cdn.jsdelivr.net/npm/jsonstat/json-stat.js"></script> |
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> |
|
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/themes/smoothness/jquery-ui.css" /> |
|
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script> |
|
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> |
|
<style type="text/css"> |
|
|
|
body { |
|
background-color: #fff; |
|
width: 1250px; |
|
display: block; |
|
margin: 0px auto 0px auto; |
|
padding: 5px; |
|
font-family: "Helvetica Neue", "Helvetica", "sans-serif"; |
|
} |
|
|
|
.axis path, |
|
.axis line { |
|
fill: none; |
|
stroke: black; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.axis text { |
|
font-family: "Helvetica Neue", "sans-serif"; |
|
font-size: 11px; |
|
} |
|
|
|
.trigger { |
|
display: block; |
|
} |
|
|
|
#wrap { |
|
float: left; |
|
} |
|
.box, .controlbox { |
|
float: left; |
|
padding-top: 30px; |
|
} |
|
|
|
.grid .tick { |
|
/*stroke: #bbb;*/ |
|
opacity: 0.5; |
|
} |
|
|
|
.main { |
|
display: block; |
|
width: 1100px; |
|
text-align: right; |
|
font-family: "Helvetica Neue", "sans-serif"; |
|
font-size: 9px; |
|
} |
|
|
|
.ui-autocomplete { |
|
max-height: 100px; |
|
overflow-y: auto; |
|
/* prevent horizontal scrollbar */ |
|
overflow-x: hidden; |
|
/* add padding to account for vertical scrollbar */ |
|
padding-right: 20px; |
|
} |
|
|
|
#tags { |
|
width: 500px; |
|
height: 28px; |
|
font-size: 20px; |
|
padding: 0; |
|
padding-left: 5px; |
|
font-family: "Helvetica Neue", "sans-serif"; |
|
margin: 0; |
|
vertical-align: middle; |
|
} |
|
|
|
h2 { |
|
vertical-align: middle; |
|
padding-left: 30px; |
|
display: block; |
|
text-align: left; |
|
font-weight: normal; |
|
} |
|
|
|
.ui-button { |
|
width: 32px; |
|
height: 32px; |
|
margin: 0; |
|
padding: 0; |
|
} |
|
|
|
</style> |
|
</head> |
|
<body> |
|
<h2 id="headline"> Næring: <input id="tags" class="ctrl" value=""></h2> |
|
<div id="wrap"> |
|
<div class="box"></div> |
|
<div class="controlbox"></div> |
|
</div> |
|
|
|
<script> |
|
|
|
function getJSON(url, callback){ |
|
if(window.XDomainRequest){ |
|
// Use Microsoft XDR |
|
var xdr=new XDomainRequest(); |
|
xdr.open("get", url); |
|
xdr.onload=function (){ |
|
var JSON=$.parseJSON(xdr.responseText); |
|
if(JSON==null || typeof (JSON)=='undefined'){ |
|
JSON=$.parseJSON(data.firstChild.textContent); |
|
} |
|
callback(JSON); |
|
}; |
|
xdr.send(); |
|
}else{ |
|
$.ajax({ |
|
type: 'GET', |
|
url: url, |
|
processData: true, |
|
data:{}, |
|
dataType: 'json', |
|
success: function (data){ callback(data); } |
|
}); |
|
} |
|
} |
|
|
|
var height = 400; |
|
var padding = 30; |
|
var width = 750; |
|
var cwidth=200; |
|
|
|
var color_start_stop = "#7B9BBA", |
|
color_text = "#364354", |
|
color_shade = "#9BAAB2", |
|
color_grid = "#CED5E3", |
|
color_line = "#3E51A3"; |
|
|
|
var fra_y = 0; |
|
var til_y = fra_y + 60; |
|
var delta_y = til_y + 60; |
|
|
|
function main(o) { |
|
var b = d3.select(".box") |
|
.append("svg") |
|
.attr("width",width) |
|
.attr("height",height); |
|
|
|
var cb=d3.select(".controlbox") |
|
.append("svg") |
|
.attr("width",cwidth) |
|
.attr("height",height); |
|
|
|
var j = JSONstat(o); |
|
var nl = j.Dataset(0).toTable( { type : "arrobj", content : "id" } ).filter(function(d) { return d["ContentsCode"]=="GjMdTotalIndeks" && d["Region"]=="Ialt"; });; |
|
|
|
var labelBase=j.Dataset(0).Dimension(1); |
|
var narID=labelBase.id; |
|
|
|
var narLookup = new Object(); |
|
var narList = []; |
|
for(var i=0; i<narID.length; i++) { |
|
narLookup[ labelBase.Category(i).label ] = narID[i]; |
|
narList.push(labelBase.Category(i).label); |
|
} |
|
|
|
var input = $('#tags'); |
|
var isOpen = false; |
|
|
|
function _init() { |
|
input.autocomplete({ |
|
source: narList, |
|
minLength: 0, |
|
open: function(event, ui) { |
|
isOpen = true; |
|
}, |
|
select: function(event, ui) { |
|
isOpen = false; |
|
} |
|
}); |
|
} |
|
|
|
function afterInit() { |
|
var button = $("<button type='button'> </button>").attr("tabIndex", -1).attr("title", "Show all items").insertAfter(input).button({ |
|
icons: { |
|
primary: "ui-icon-triangle-1-s" |
|
}, |
|
text: false |
|
}).removeClass("ui-corner-all").addClass("ui-corner-right ui-button-icon").click(function(event) { |
|
input.focus(); |
|
if (isOpen) { |
|
|
|
input.autocomplete("close"); |
|
isOpen = false; |
|
} else { |
|
input.autocomplete("search", ""); |
|
event.stopImmediatePropagation(); |
|
} |
|
}); |
|
} |
|
|
|
$(window).click(function() { |
|
input.autocomplete("close"); |
|
isOpen = false; |
|
}); |
|
$(function() { |
|
_init(); |
|
afterInit(); |
|
}); |
|
|
|
// Do the scales |
|
function getDate(d) { |
|
var year = d.substring(0,4); |
|
var month=d.substring(5,6)*3; |
|
var thing = month + '\/01\/' + year; |
|
return new Date(thing); |
|
} |
|
|
|
function getQ(dtVal) { |
|
var mnd=dtVal.getMonth() + 1; |
|
var yr=dtVal.getYear() + 1900; |
|
if (mnd<4) { |
|
q=1; |
|
} else if (mnd<7) { |
|
q=2; |
|
} else if (mnd<10) { |
|
q=3; |
|
} else { q=4 } |
|
// return q + ". Kvartal " + yr; |
|
return yr + "K" + q; |
|
} |
|
|
|
function getQTxt(QCode) { |
|
var kv=QCode.substring(5,6); |
|
var yr=QCode.substring(0,4); |
|
return kv + ". Kvartal " + yr; |
|
} |
|
|
|
|
|
var x = d3.time.scale() |
|
.domain([getDate(d3.min(j.Dataset(0).Dimension("Tid").id)), getDate(d3.max(j.Dataset(0).Dimension("Tid").id))]) |
|
.range([padding, (width - padding)]) |
|
; |
|
|
|
var y = d3.scale.linear() |
|
.range([(height - padding),0]) |
|
.domain([0,d3.max(j.Dataset(0).value)+5]) |
|
; |
|
|
|
// ****** Do the axes ****** |
|
var xAxis = d3.svg.axis() |
|
.scale(x) |
|
.ticks(d3.time.year, 1) |
|
.orient("bottom") |
|
; |
|
|
|
var yAxis = d3.svg.axis() |
|
.scale(y) |
|
.orient("left"); |
|
|
|
function makeYAxis() { |
|
return d3.svg.axis() |
|
.scale(y) |
|
.orient("left") |
|
.ticks(16); |
|
} |
|
|
|
function makeXAxis() { |
|
return d3.svg.axis() |
|
.scale(x) |
|
.ticks(d3.time.year, 1) |
|
.orient("bottom") |
|
; |
|
} |
|
|
|
b.append("g") |
|
.call(makeYAxis() |
|
.tickSize(- (width - 2*padding) , 0, 0) |
|
.tickFormat("")) |
|
.attr("class", "grid") |
|
.attr("transform", "translate(" + padding + ",0)") |
|
.attr("stroke", color_grid); |
|
|
|
b.append("g") |
|
.call(makeXAxis() |
|
.tickSize(- (height - padding) , 0, 0) |
|
.tickFormat("")) |
|
.attr("class", "grid") |
|
.attr("transform", "translate(" + 0 + " , " + (height - padding) + ")") |
|
.attr("stroke", color_grid); |
|
|
|
b.append("g") |
|
.call(xAxis) |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(" + 0 + " , " + (height - padding) + ")"); |
|
|
|
b.append("g") |
|
.call(yAxis) |
|
.attr("class", "axis") |
|
.attr("transform", "translate(" + padding + ",0)"); |
|
|
|
// TOOLTIP TXT - DOESNT LOOK GOOD; |
|
var fra_g = cb.append("g").attr("width", 200).attr("height", 60).attr("fill", color_text).attr("transform","translate(" + 0 + ","+ 0 + ")"); |
|
fra_g.append("text").attr("x", 0).attr("y", 20).attr("text-align","right").attr("font-family","Helvetica Neue").attr("font-size", 12).text("FRA"); |
|
|
|
var til_g = cb.append("g").attr("width", 200).attr("height", 60).attr("fill", color_text).attr("transform","translate(" + 0 + ","+ 60 + ")"); |
|
til_g.append("text").attr("x", 0).attr("y", 20).attr("text-align","right").attr("font-family","Helvetica Neue").attr("font-size", 12).text("TIL"); |
|
|
|
var delta_g = cb.append("g").attr("width", 200).attr("height", 120).attr("fill", color_text).attr("transform","translate(" + 0 + ","+ 120 + ")"); |
|
delta_g.append("text").attr("x", 0).attr("y", 20).attr("text-align","right").attr("font-family","Helvetica Neue").attr("font-size", 12).text("ENDRING"); |
|
|
|
var fromTxt = fra_g.append("text").attr("x", 0).attr("y", 42).attr("text-anchor","bottom").attr("text-align","right").attr("font-size", 24).attr("font-family","Helvetica Neue"); |
|
var toTxt = til_g.append("text").attr("x", 0).attr("y",42).attr("text-anchor","bottom").attr("text-align","right").attr("font-size", 24).attr("font-family","Helvetica Neue"); |
|
var deltaTxt = delta_g.append("text").attr("x", 0).attr("y",72).attr("text-anchor","bottom").attr("text-align","center").attr("font-size", 62).attr("font-family","Helvetica Neue"); |
|
|
|
var drag = d3.behavior.drag() |
|
.on("dragstart", function(d) { |
|
|
|
d3.selectAll("rect.shade").remove(); |
|
pos1=d3.mouse(this); |
|
v1=lineData.filter(function(d) { return d.Tid==getQ(x.invert(pos1[0])) })[0]; |
|
shade = b.append("rect") |
|
.attr("height", height-padding) |
|
.attr("width", 2) |
|
.attr("fill", color_shade) |
|
.attr("fill-opacity", 0.20) |
|
.attr("class", "shade") |
|
.attr("transform","translate(" + pos1[0] + ","+ 0 + ")"); |
|
fromTxt.text(getQTxt(v1.Tid)); |
|
toTxt.text(""); |
|
deltaTxt.text(""); |
|
|
|
}) |
|
.on("drag", function() { |
|
posNow = d3.mouse(this); |
|
vn=lineData.filter(function(d) { return d.Tid==getQ(x.invert(posNow[0])) })[0]; |
|
shade.attr("width", Math.abs(pos1[0]-posNow[0])); |
|
|
|
if (pos1[0]>posNow[0]) { |
|
fromTxt.text(getQTxt(vn.Tid)); |
|
toTxt.text(getQTxt(v1.Tid)); |
|
deltaTxt.text( ((Math.round(((v1.value/vn.value)-1)*1000))/10).toFixed(1) + "%" ); |
|
shade.attr("transform",function() { |
|
return "translate(" + posNow[0] + ","+ 0 + ")"; |
|
}) |
|
} else { |
|
toTxt.text(getQTxt(vn.Tid)); |
|
deltaTxt.text( ((Math.round(((vn.value/v1.value)-1)*1000))/10).toFixed(1) + "%"); |
|
shade.attr("transform",function() { |
|
return "translate(" + pos1[0] + ","+ 0 + ")"; |
|
}); |
|
} |
|
}); |
|
|
|
// Do the graph |
|
var lfunc = d3.svg.line() |
|
.x(function(d,i) { return x(getDate(d["Tid"])) }) |
|
.y(function(d) { return y(d["value"])}) |
|
.interpolate("linear"); |
|
|
|
document.getElementById("tags").value = narList[0]; |
|
var nid= narLookup[ document.getElementById("tags").value ] ; |
|
var lineData = nl.filter(function(d) { return d.NACE2007==narLookup[document.getElementById("tags").value] }); |
|
|
|
b.selectAll(".line") |
|
.data([lineData]) |
|
.enter() |
|
.append("svg:path") |
|
.attr("d",lfunc) |
|
.attr("stroke", color_line) |
|
.attr("stroke-width", 3) |
|
.attr("fill","none") |
|
.attr("class", "line") |
|
; |
|
|
|
var rn1=(Math.random()*((width*0.4)-padding))+padding; |
|
var rn2=rn1+200; |
|
v1=lineData.filter(function(d) { return d.Tid==getQ(x.invert(rn1)) })[0]; |
|
v2=lineData.filter(function(d) { return d.Tid==getQ(x.invert(rn2)) })[0]; |
|
|
|
var shade = b.append("rect") |
|
.attr("height", height-padding) |
|
.attr("width", 2) |
|
.attr("fill", color_shade) |
|
.attr("fill-opacity", 0.20) |
|
.attr("class", "shade") |
|
.attr("transform","translate(" + padding + ","+ 0 + ")"); |
|
|
|
shade.transition().duration(2000).attr("width", rn2-rn1).attr("transform","translate(" + rn1 + ","+ 0 + ")"); |
|
|
|
if (v1.Tid>v2.Tid) { |
|
fromTxt.text(getQTxt(v2.Tid)); |
|
toTxt.text(getQTxt(v1.Tid)); |
|
deltaTxt.text( ((Math.round(((v1.value/v2.value)-1)*1000))/10).toFixed(1) + "%" ); |
|
} else { |
|
fromTxt.text(getQTxt(v1.Tid)); |
|
toTxt.text(getQTxt(v2.Tid)); |
|
deltaTxt.text( ((Math.round(((v2.value/v1.value)-1)*1000))/10).toFixed(1) + "%"); |
|
} |
|
|
|
d3.selectAll("#ui-id-1").on("click", function() { |
|
d3.selectAll("rect.shade").remove(); |
|
fromTxt.text(""); |
|
toTxt.text(""); |
|
deltaTxt.text(""); |
|
lineData = nl.filter(function(d) { return d.NACE2007==narLookup[document.getElementById("tags").value] }); |
|
b.selectAll(".line") |
|
.data([lineData]) |
|
.transition() |
|
.duration(500) |
|
.attr("d",lfunc) |
|
.attr("stroke",color_line) |
|
.attr("stroke-width", 3) |
|
.attr("fill","none"); |
|
}); |
|
|
|
b.call(drag); |
|
|
|
$("#tags").keyup(function(event){ |
|
if(event.keyCode == 13){ |
|
$("#ui-id-1").click(); |
|
} |
|
}); |
|
|
|
// KILDE OG FORKLARING |
|
cb.append("text").attr("x", 50).attr("y", height-30).attr("font-family", "Helvetica Neue").attr("font-size", 10).text("Marker område for å vise vekst"); |
|
cb.append("text").attr("x", 70).attr("y", height-20).attr("font-family", "Helvetica Neue").attr("font-size", 10).text("Data: " + j.Dataset(0).source); |
|
|
|
} |
|
getJSON('https://data.ssb.no/api/v0/dataset/1124.json?lang=no', main); |
|
|
|
</script> |
|
|
|
</body> |
|
</html> |