function drawTimeline()

in src/core/main.ts [2510:2735]


  function drawTimeline(data) {
    selectWithParent("#timeline_metadata").style("display", "none");
    selectWithParent("#timeline_metadata_contents").html("");
    instance.importPanel.hide();

    /**
    ---------------------------------------------------------------------------------------
    CALL STANDALONE TIMELINE VISUALIZATIONS
    ---------------------------------------------------------------------------------------
    **/

    control_panel.selectAll("input").attr("class", "img_btn_enabled");
    selectWithParent("#navigation_div").style("bottom", (instance.options.showAbout === false || instance.playback_mode) ? "20px" : "50px");
    selectWithParent("#filter_type_picker").selectAll("input").property("disabled", false);
    selectWithParent("#filter_type_picker").selectAll("img").attr("class", "img_btn_enabled");

    selectAllWithParent("#record_scene_btn, #play_scene_btn").selectAll("img")
      .attr("class", "img_btn_enabled");

    var hasScenes = globals.scenes && globals.scenes.length;
    if (hasScenes) {
      selectWithParent("#record_scene_btn").attr("class", "img_btn_disabled");
      timeline_vis.tl_scale(globals.scenes[0].s_scale)
        .tl_layout(globals.scenes[0].s_layout)
        .tl_representation(globals.scenes[0].s_representation);
    }

    updateRadioBttns(timeline_vis.tl_scale(), timeline_vis.tl_layout(), timeline_vis.tl_representation());

    determineSize(data, timeline_vis.tl_scale(), timeline_vis.tl_layout(), timeline_vis.tl_representation());

    adjustSvgSize();

    globals.global_min_start_date = data.min_start_date;
    globals.global_max_end_date = data.max_end_date;

    main_svg.datum(data)
      .call(timeline_vis.duration(instance._getAnimationStepDuration()).height(globals.height).width(globals.width));

    // TODO: This should move into each of the chart renderers when we have some time
    instance._hideError();
    instance._main_svg.style("opacity", 1);

    if (hasScenes) {
      instance._currentSceneIndex = 0;
      changeScene(0);
    }

    if (globals.legend_panel) {
      globals.legend_panel.remove();
      globals.legend_panel = undefined;
    }

    if (globals.num_categories <= 12 && globals.num_categories > 1) {
      // setup legend
      globals.legend_panel = main_svg.append("svg")
        .attr("height", 35 + globals.track_height * (globals.num_categories + 1) + 5)
        .attr("width", globals.max_legend_item_width + 10 + globals.unit_width + 10 + 20)
        .attr("y", 100)
        .attr("id", "legend_panel")
        .attr("class", "legend")
        .on("mouseover", function () {
          // if (selectAllWithParent("foreignObject")[0].length === 0) {
          //   addLegendColorPicker();
          // }
          d3.select(this).select(".legend_rect").attr("filter", "url(#drop-shadow)");
          d3.select(this).select("#legend_expand_btn").style("opacity", 1);
        })
        .on("mouseout", function () {
          d3.select(this).select(".legend_rect").attr("filter", "none");
          d3.select(this).select("#legend_expand_btn").style("opacity", 0.1);
        })
        .call(legendDrag);

      globals.legend_panel.append("rect")
        .attr("class", "legend_rect")
        .attr("height", globals.track_height * (globals.num_categories + 1))
        .attr("width", globals.max_legend_item_width + 5 + globals.unit_width + 10)
        .append("title")
        .text("Click on a color swatch to select a custom color for that category.");

      globals.legend_panel.append("svg:image")
        .attr("id", "legend_expand_btn")
        .attr("x", globals.max_legend_item_width + 5 + globals.unit_width - 10)
        .attr("y", 0)
        .attr("width", 20)
        .attr("height", 20)
        .attr("xlink:href", imageUrls("min.png"))
        .style("cursor", "pointer")
        .style("opacity", 0.1)
        .on("click", function () {
          if (globals.legend_expanded) {
            instance.collapseLegend();
          } else {
            instance.expandLegend();
          }
        })
        .append("title")
        .text("Expand / collapse legend.");

      var legendElementContainer = globals.legend_panel.selectAll(".legend_element_g").data(globals.categories.domain().sort());
      globals.legend = legendElementContainer
        .enter()
        .append("g")
        .attr("class", "legend_element_g");

      // Remove the element when not data bound.
      legendElementContainer.exit().remove();

      globals.legend.append("title")
        .text(function (d) {
          return d;
        });

      globals.legend.attr("transform", function (d, i) {
        return ("translate(0," + (35 + (i + 1) * globals.track_height) + ")");
      });

      globals.legend.on("mouseover", function (d) {
        var hovered_legend_element = d;

        //logEvent("legend hover: " + hovered_legend_element, "legend");

        d3.select(this).select("rect").style("stroke", "#f00");
        d3.select(this).select("text").style("font-weight", "bolder")
          .style("fill", "#f00");
        selectAllWithParent(".timeline_event_g").each(function (d) { // eslint-disable-line no-shadow
          if (d.category === hovered_legend_element || d.selected) {
            d3.select(this).selectAll(".event_span")
              .style("stroke", "#f00")
              .style("stroke-width", "1.25px")
              .attr("filter", "url(#drop-shadow)");
            d3.select(this).selectAll(".event_span_component")
              .style("stroke", "#f00")
              .style("stroke-width", "1px");
          } else {
            d3.select(this).selectAll(".event_span")
              .attr("filter", "url(#greyscale)");
            d3.select(this).selectAll(".event_span_component")
              .attr("filter", "url(#greyscale)");
          }
        });
      });

      globals.legend.on("mouseout", function (d) {
        d3.select(this).select("rect").style("stroke", "#fff");
        d3.select(this).select("text").style("font-weight", "normal")
          .style("fill", "#666");
        selectAllWithParent(".timeline_event_g").each(function () {
          d3.select(this).selectAll(".event_span")
            .style("stroke", "#fff")
            .style("stroke-width", "0.25px")
            .attr("filter", "none");
          d3.select(this).selectAll(".event_span_component")
            .style("stroke", "#fff")
            .style("stroke-width", "0.25px")
            .attr("filter", "none");
          if (d.selected) {
            d3.select(this)
              .selectAll(".event_span")
              .attr("filter", "url(#drop-shadow)")
              .style("stroke", "#f00")
              .style("stroke-width", "1.25px");
            d3.select(this)
              .selectAll(".event_span_component")
              .style("stroke", "#f00")
              .style("stroke-width", "1px");
          }
        });
      });

      globals.legend.append("rect")
        .attr("class", "legend_element")
        .attr("x", globals.legend_spacing)
        .attr("y", 2)
        .attr("width", globals.legend_rect_size)
        .attr("height", globals.legend_rect_size)
        .attr("transform", "translate(0,-35)")
        .style("fill", globals.categories)
        .on("click", function (d, i) {
          var colorEle = this;
          instance._colorPicker.show(this, globals.categories(d), function (value) {
            // Update the display
            selectWithParent(".legend").selectAll(".legend_element_g rect").each(function () {
              if (this.__data__ === d) {
                d3.select(colorEle).style("fill", value);
              }
            });

            instance.setCategoryColor(d, i, value);

            if (main_svg && timeline_vis) {
              main_svg.call(timeline_vis.duration(instance._getAnimationStepDuration()));
            }
          });
        })
        .append("title");

      globals.legend.append("text")
        .attr("class", "legend_element")
        .attr("x", globals.legend_rect_size + 2 * globals.legend_spacing)
        .attr("y", globals.legend_rect_size - globals.legend_spacing)
        .attr("dy", 3)
        .style("fill-opacity", "1")
        .style("display", "inline")
        .attr("transform", "translate(0,-35)")
        .text(function (d) {
          return d;
        });

      globals.legend_panel.append("text")
        .text("LEGEND")
        .attr("class", "legend_title")
        .attr("dy", "1.4em")
        .attr("dx", "0em")
        .attr("transform", "translate(5,0)rotate(0)");
    }

    return new Promise(resolve => {
      if (timeline_vis.renderComplete) {
        timeline_vis.renderComplete.then(resolve);
      } else {
        resolve();
      }
    });
  }