// Clear the current SVG data
function clearTimeline() {
  var svg = document.getElementById('svgOutput');
  removeChildren(svg);
}

// Update the SVG diagram with a new timeline based on the passed data
function createTimeline(data) {
  var svg = document.getElementById('svgOutput');
  
  // Basic layout parameters
  var xStart = 100;
  var xEnd = 500;
  var xRange = xEnd - xStart;
  var y = 100;
  
  // Determine time range
  var startTime = Date.parse(data.start);
  var endTime = Date.parse(data.end);
  var timeRange = endTime - startTime;
  
  // Calculate event times
  var numberOfEvents = data.events.length;
  for (var i = 0 ; i < numberOfEvents ; i++) {
    var time = Date.parse(data.events[i].date);
    data.events[i].x = ((time - startTime) / timeRange) * xRange + xStart;
  }
  
  // Draw base timeline
  svg.appendChild(makeLine(xStart, y, xEnd, y, data.lineColor, 4));
  
  // Draw caps
  svg.appendChild(makeLine(xStart, y - 10, xStart, y + 10, data.lineColor, 2));
  svg.appendChild(makeLine(xEnd, y - 10, xEnd, y + 10, data.lineColor, 2));
  
  // Draw event ticks
  for (var i = 0 ; i < numberOfEvents ; i++) {
    svg.appendChild(makeLine(data.events[i].x, y - 10, data.events[i].x, y + 10, data.lineColor, 1));
  }
  
  // Cap text
  svg.appendChild(makeDateText(xStart, y + 20, data.textColor, data.start));
  svg.appendChild(makeDateText(xEnd, y + 20, data.textColor, data.end));
  // Event text
  for (var i = 0 ; i < numberOfEvents ; i++) {
    svg.appendChild(makeNameText(data.events[i].x, y - 10, data.textColor, data.events[i].name));
    svg.appendChild(makeDateText(data.events[i].x, y + 20, data.textColor, data.events[i].date));
  }
}

// Entry point, called by button
function generate() {
  var data = loadTimelineData();
  updateTimeline(data);
}

// Load timeline data as an object
function loadTimelineData() {
  var jsonSource = document.getElementById('jsonSource').value;
  var obj = JSON.parse(jsonSource);
  return obj;
}

// Utility function to generate an SVG <line>
function makeLine(x1, y1, x2, y2, color, lineWidth) {
  var e = document.createElementNS('http://www.w3.org/2000/svg','line');
  e.setAttribute('x1', x1);
  e.setAttribute('y1', y1);
  e.setAttribute('x2', x2);
  e.setAttribute('y2', y2);
  e.setAttribute('stroke', color);
  e.setAttribute('stroke-width', lineWidth);
  return e;
}

function makeDateText(x, y, color, text) {
  var e = makeText(x, y, color, text);
  e.setAttribute('transform', 'rotate(-45, ' + x + ', ' + y + ')');
  e.setAttribute('text-anchor', 'end');
  return e;
}

function makeNameText(x, y, color, text) {
  var e = makeText(x, y, color, text);
  e.setAttribute('transform', 'rotate(-45, ' + x + ', ' + y + ')');
  return e;
}

// Utility function to generate an SVG <text>
function makeText(x, y, color, text) {
  var e = document.createElementNS('http://www.w3.org/2000/svg','text');
  e.setAttribute('x', x);
  e.setAttribute('y', y);
  e.setAttribute('fill', color);
  e.setAttribute('font-size', 14);
  e.setAttribute('font-family', 'arial');
  e.textContent = text;
  return e;
}

// Remove all children of the specified element
function removeChildren(node) {
  while(node.firstChild) {
    node.removeChild(node.firstChild);
  }
}

// Update the timeline wrt the supplied data
function updateTimeline(data) {
  clearTimeline();
  createTimeline(data);
}


@@ -1669,16 +1669,252 @@
 %0A  %7D%0A%7D%0A%0A
+// Make a string HTML-safe%0Afunction escapeHtml(unsafe) %7B%0A  var safe = unsafe%0A    .replace(/&/g, %22&amp;%22)%0A    .replace(/%3C/g, %22&lt;%22)%0A    .replace(/%3E/g, %22&gt;%22)%0A    .replace(/%22/g, %22&quot;%22)%0A    .replace(/'/g, %22&#039;%22);%0A  return safe;%0A%7D%0A%0A
 // Entry
@@ -2017,16 +2017,44 @@
 (data);%0A
+  updateSvgSourceDisplay();%0A
 %7D%0A%0A// Lo
@@ -3488,24 +3488,236 @@
 ld);%0A  %7D%0A%7D%0A%0A
+// Update the SVG source display%0Afunction updateSvgSourceDisplay() %7B%0A  var svgSource = escapeHtml(document.getElementById('svgOutput').outerHTML);%0A  document.getElementById('svgSource').innerHTML = svgSource;%0A%7D%0A%0A
 // Update th

Implement SVG source display.