contour
clone your own copy | download snapshot

Snapshots | iceberg

Inside this repository

index.html
text/html

Download raw (6.9 KB)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Timeline</title>
</head>
<body>
  <object id="timeline" data="timeline.svg" type="image/svg+xml" style="max-height:90vh"></object>
  <script src="raphael.min.js"></script>
  <script>
    // lastDirection = 1;
    var loopSwitch = true,
        daySwitch = true,
        event = 0,
        day = 0,
        loop = 0,
        timelineSVG,
        highlightpath,
        timelineSegments;

    const timeline = [
      [
        [0],
        [0, 1, 2, 3],
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 
        [0]
      ],
      [
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4, 5, 6, 7],
        [0]
      ],
      [
        [0, 1, 2, 3, 4, 5],
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
        [0]
      ]
    ];

    function timelineSubset(loop, day, event) {
      if (typeof(day) !== "undefined") {
        if(typeof(event) !== "undefined") {
          return timeline[loop][day][event];
        }    
        return timeline[loop][day];
      }
      return timeline[loop];
    }

    function getLength(input) {
      if (Array.isArray(input)) {
        // If the subpath has an uneven amount of children
        // on of them is positioned in the middle of the loop
        // therefor we loose a point on the loop
        var length = (input.length % 2 == 0) ? 3 : 2;

        for (var i=0;i<input.length;i++) {
          length += getLength(input[i]);
        }

        return length;
      } else {
        return 3;
      }
    }

    // If the parent(path) has an even amount of children, and the child
    // is located over the half of the path we have to insert and extra
    // point (top of the loop)
    function middlepointCompensation (parent, key) {
      if (key > 0 && (key + 1) * 2 > parent.length && parent.length % 2 == 0) {
        return 1;
      } else {
        return 0;
      }
    }

    function getStart(loop, day, event) {
      var coord = 1, l = 0, d = 0, e = 0;

      while (l < loop) {
        coord += getLength(timelineSubset(l));
        l++;
      };

      if (typeof(day) !== "undefined") {
        coord++; 
        
        while (d < day) {
          coord += getLength(timelineSubset(l, d));
          d++;
        }

        coord += middlepointCompensation(timelineSubset(l), d);
      
        if (typeof(event) !== "undefined") {
          coord++;

          while (e < event) {
            coord += getLength(timelineSubset(l,d,e));
            e++;
          }

          coord += middlepointCompensation(timelineSubset(l,d), e);
        }
      }

      return coord;
    }

    function getEnd(loop, day, event) {
      var start = getStart(loop, day, event);

      if (typeof(event) !== 'undefined') {
        return start + getLength(timelineSubset(loop, day, event));
      } else if (typeof(day) !== 'undefined') {
        return start + getLength(timelineSubset(loop, day));
      } 

      return start + getLength(timelineSubset(loop));
    }


    function getSegmentCoords(segment) {
      if (segment[0] == 'C') {
        return [segment[5], segment[6]];
      } else {
        return [segment[1], segment[2]];
      }
    }

    function getSubpathFromSegments(segments, start, end) {
      subset = [];
      
      if (start > 0 || segments[start][0] !== 'M') {
        subset.push(['M'].concat(getSegmentCoords(segments[start-1])));
      }

      return subset.concat(segments.slice(start, end+1));
    }

    function makeCoordinateString(x, y)  {
      return x + ' ' + y;
    }

    function makePathString(segments) {
      var pathstring = '';

      for (var s = 0; s < segments.length;s++) {
        var command = segments[s][0];
            coordinates = [];
        for (var c=1; c < segments[s].length; c+=2) {
          coordinates.push(makeCoordinateString(segments[s][c], segments[s][c+1]));
        }
        pathstring += command + coordinates.join(',');
      }

      return pathstring
    }

    function highlight(start, end) {
      highlightpath.setAttribute('d', makePathString(getSubpathFromSegments(timelineSegments, start, end)));

    }

    function highlightSection(loop, day, event) {
      highlight(getStart(loop, day, event)+1, getEnd(loop, day, event)-1);
    }

    function next () {
      // highlight next event
      // on loop switch higlight whole loop
      // on day switch highlight whole day
      // highlight previous event
      if (loopSwitch) {
        loopSwitch = false;
        // highlight loop
        highlightSection(loop, day)
      } else if (daySwitch) {
        daySwitch = false;
        highlightSection(loop, day, event);
      } else {
        event++;
        if (event >= timeline[loop][day].length) {
          // switch day, highlight day
          daySwitch = true;
          day++;      
          if (day >= timeline[loop].length) {
            // switch loop highlight whole loop
            loopSwitch = true
            loop++;
            if (loop >= timeline.length) {
              loop = 0;
            }
            day = 0;
            highlightSection(loop);
          } else {
            highlightSection(loop, day);
          }
          event = 0;
        } else {
          highlightSection(loop, day, event);
        }
      }
    }

    function previous () {
      // highlight previous event
      if (loopSwitch) {
        loopSwitch = false;
        // highlight loop
        highlightSection(loop, day)
      } else if (daySwitch) {
        daySwitch = false;
        // on day switch higlight whole day
        // switch day, highlight day
        highlightSection(loop, day, event);
      } else {
        event--;
        if (event < 0) {
          daySwitch = true;
          day--;

          if (day < 0) {
            // switch loop highlight whole loop
            loopSwitch = true
            loop--;
            if (loop < 0) {
              loop = timeline.length-1;
            }

            highlightSection(loop);
            day = timeline[loop].length - 1;
          } else {
            highlightSection(loop, day);
          }
          event = timeline[loop][day].length - 1;
        } else {
          highlightSection(loop, day, event);
        }
      }
    }

    window.addEventListener('load', function () {
      timelineSVG = document.querySelector('#timeline').contentDocument.rootElement;
      const paths = timelineSVG.querySelectorAll('path');
      highlightpath = paths[5]; //document.querySelector('#timeline').contentDocument.createElement('path');
      timelineSegments = Raphael.parsePathString(paths[4].getAttribute('d'));

      highlightpath.setAttribute("style", "stroke:rgb(100%,0%,0%); stroke-width:5.0;fill:none;");
      
      window.addEventListener('wheel', function (e) {
        (e.deltaY > 0) ? next() : previous();
      });
      
      highlightSection(loop);
    });

  </script>
</body>
</html>