PageSourceSearch

https://johnguerra.co/js/experienceTimeline.js

js johnguerra.co collected 2026-10-02 15:10:35 UTC 3,361 bytes, 148 lines download raw bytes

1(function Timeline() {
2  /* global d3 */
3  var svg = d3.select("#timeline"),
4    margin = { top: 20, right: 0, bottom: 40, left: 0 },
5    // width = (svg.node().width.baseVal.value||900) - margin.left - margin.right,
6    width = 900 - margin.left - margin.right,
7    height = +svg.attr("height") - margin.top - margin.bottom,
8    g = svg
9      .append("g")
10      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
11  var gData = g.append("g").attr("class", "data");
12  var y = d3
13    .scaleBand()
14    .rangeRound([0, height])
15    .paddingInner(0.05)
16    .align(0.1);
17
18  var x = d3.scaleTime();
19
20  var color = d3.scaleOrdinal().range(["#507B94", "#86C6D7"]);
21  var parseDate = d3.timeParse("%m/%Y");
22
23  var xAxis = g
24    .append("g")
25    .attr("class", "axis")
26    .attr("transform", "translate(0," + (height) + ")");
27  xAxis.append("path").attr("class", "base");
28
29  function fnWidth(d) {
30    return x(d.End) - x(d.Start) - 2;
31  }
32
33  function fnHeight(d) {
34    return (y.bandwidth() - 1) * d.Height;
35  }
36  function fnX() {
37    return 1;
38  }
39  function fnY(d) {
40    return d.yOffset * fnHeight(d) + 1;
41  }
42  function fnColor(d) {
43    return color(d.Type);
44  }
45
46  function update(data) {
47    try {
48      width =
49        (d3
50          .select("#timeline")
51          .node()
52          .getBoundingClientRect().width || 900) -
53        margin.left -
54        margin.right;
55    } catch (e) {
56      width = 900 - margin.left - margin.right;
57    }
58
59    x.domain([
60      d3.min(data, function(d) {
61        return d.Start;
62      }),
63      d3.max(data, function(d) {
64        return d.End;
65      }),
66    ]).rangeRound([0, width]);
67    y.domain(
68      data.map(function(d) {
69        return d.Type;
70      })
71    );
72    // z.domain(keys);
73
74    var entries = gData.selectAll(".entry").data(data);
75
76    var entriesEnter = entries
77      .enter()
78      .append("g")
79      .attr("class", "entry");
80
81    entriesEnter.merge(entries).attr("transform", function(d) {
82      return "translate(" + x(d.Start) + "," + y(d.Type) + ")";
83    });
84
85    entriesEnter
86      .append("rect")
87      .attr("rx", 2)
88      .attr("ry", 2)
89      .attr("width", 0)
90      .merge(entries.select("rect"))
91      .attr("x", fnX)
92      .attr("y", fnY)
93
94      .style("fill", fnColor)
95      .attr("height", fnHeight)
96
97      .transition()
98      .duration(1000)
99      .attr("width", fnWidth);
100
101    entriesEnter
102      .append("text")
103      .text(function(d) {
104        return d.Description;
105      })
106      .merge(entries.select("text"))
107      .attr("x", function(d) {
108        return fnX(d) + fnWidth(d) / 2;
109      })
110      .attr("y", function(d) {
111        return fnY(d) + fnHeight(d) / 2 + 5;
112      });
113
114    xAxis
115      .transition()
116      .duration(2000)
117      .call(function(sel) {
118        sel.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%Y")));
119        sel
120          .selectAll("line")
121          .attr("stroke", null)
122          .attr("y1", -6);
123      })
124      .select(".base")
125      .attr(
126        "d",
127        d3.line()([
128          [0, 0],
129          [width, 0],
130        ])
131      );
132  }
133
134  d3.csv(
135    "experience.csv",
136    function(d) {
137      d.Start = parseDate(d.Start);
138      d.End = d.End !== "-" ? parseDate(d.End) : new Date();
139      return d;
140    }
141  ).then(function(data) {
142    update(data);
143
144    window.addEventListener("resize", function() {
145      update(data);
146    });
147  });
148})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.