Skip to content

Instantly share code, notes, and snippets.

@radbrt
Last active March 2, 2019 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save radbrt/84908f03b57cd5c9ba01 to your computer and use it in GitHub Desktop.
Save radbrt/84908f03b57cd5c9ba01 to your computer and use it in GitHub Desktop.
Lønnsindeks

Interaktiv lønnsindeks for månedslønn

Ved å klikke på figuren og dra vil lønnendringen mellom tidspunktene regnes ut.

Månedslønnen inkluderer bonus og uregelmessige tillegg, som regnes som hittil-i-år verdi. Derfor kan grafen vise sesongsvingninger avhengig av når på året bonus er utbetalt.

<!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'>&nbsp;</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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment