function refresh() {
      // process data to remove too late data items
      data = data.filter(function(d) {
        if (d.time.getTime() > startTime.getTime()) return true;
      });

      // determine number of categories
      var categoryCount = yDomain.length;
      if (debug) console.log("yDomain", yDomain);

      // here we bind the new data to the main chart
      // note: no key function is used here; therefore the data binding is
      // by index, which effectivly means that available DOM elements
      // are associated with each item in the available data array, from
      // first to last index; if the new data array contains fewer elements
      // than the existing DOM elements, the LAST DOM elements are removed;
      // basically, for each step, the data items "walks" leftward (each data
      // item occupying the next DOM element to the left);
      // This data binding is very different from one that is done with a key
      // function; in such a case, a data item stays "resident" in the DOM
      // element, and such DOM element (with data) would be moved left, until
      // the x position is to the left of the chart, where the item would be
      // exited
      var updateSel = barG.selectAll(".bar").data(data);

      // remove items
      updateSel.exit().remove();

      // add items
      updateSel
        .enter()
        .append(function(d) {
          if (debug) {
            console.log("d", JSON.stringify(d));
          }
          if (d.type == undefined) console.error(JSON.stringify(d));
          var type = d.type || "circle";
          var node = document.createElementNS(
            "http://www.w3.org/2000/svg",
            type
          );
          return node;
        })
        .attr("class", "bar")
        .attr("id", function() {
          return "bar-" + barId++;
        });

      // update items; added items are now part of the update selection
      updateSel
        .attr("x", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "rect":
              var size = d.size || 6;
              retVal = Math.round(x(d.time) - size / 2);
              break;
            default:
          }
          return retVal;
        })
        .attr("y", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "rect":
              var size = d.size || 6;
              retVal = y(d.category) - size / 2;
              break;
            default:
          }
          return retVal;
        })
        .attr("cx", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "circle":
              retVal = Math.round(x(d.time));
              break;
            default:
          }
          return retVal;
        })
        .attr("cy", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "circle":
              retVal = y(d.category);
              break;
            default:
          }
          return retVal;
        })
        .attr("r", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "circle":
              retVal = d.size / 2;
              break;
            default:
          }
          return retVal;
        })
        .attr("width", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "rect":
              retVal = d.size;
              break;
            default:
          }
          return retVal;
        })
        .attr("height", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "rect":
              retVal = d.size;
              break;
            default:
          }
          return retVal;
        })
        .style("fill", function(d) {
          return d.color || "black";
        })
        //.style("stroke", "orange")
        //.style("stroke-width", "1px")
        //.style("stroke-opacity", 0.8)
        .style("fill-opacity", function(d) {
          return d.opacity || 1;
        });

      // create update selection for the nav chart, by applying data
      var updateSelNav = navG.selectAll("circle").data(data);

      // remove items
      updateSelNav.exit().remove();

      // add items
      updateSelNav
        .enter()
        .append("circle")
        .attr("r", 1)
        .attr("fill", "black");

      // added items now part of update selection; set coordinates of points
      updateSelNav
        .attr("cx", function(d) {
          return Math.round(xNav(d.time));
        })
        .attr("cy", function(d) {
          return yNav(d.category);
        });
    } // end refreshChart function
// (which happens constantly), or after arrival of new data, or at init
(which happens constantly), or after arrival of new data, or at init
( which happens constantly ) or after arrival of new data or at init
function refresh() {
      data = data.filter(function(d) {
        if (d.time.getTime() > startTime.getTime()) return true;
      });
      var categoryCount = yDomain.length;
      if (debug) console.log("yDomain", yDomain);
      var updateSel = barG.selectAll(".bar").data(data);
      updateSel.exit().remove();
      updateSel
        .enter()
        .append(function(d) {
          if (debug) {
            console.log("d", JSON.stringify(d));
          }
          if (d.type == undefined) console.error(JSON.stringify(d));
          var type = d.type || "circle";
          var node = document.createElementNS(
            "http://www.w3.org/2000/svg",
            type
          );
          return node;
        })
        .attr("class", "bar")
        .attr("id", function() {
          return "bar-" + barId++;
        });
      updateSel
        .attr("x", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "rect":
              var size = d.size || 6;
              retVal = Math.round(x(d.time) - size / 2);
              break;
            default:
          }
          return retVal;
        })
        .attr("y", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "rect":
              var size = d.size || 6;
              retVal = y(d.category) - size / 2;
              break;
            default:
          }
          return retVal;
        })
        .attr("cx", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "circle":
              retVal = Math.round(x(d.time));
              break;
            default:
          }
          return retVal;
        })
        .attr("cy", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "circle":
              retVal = y(d.category);
              break;
            default:
          }
          return retVal;
        })
        .attr("r", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "circle":
              retVal = d.size / 2;
              break;
            default:
          }
          return retVal;
        })
        .attr("width", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "rect":
              retVal = d.size;
              break;
            default:
          }
          return retVal;
        })
        .attr("height", function(d) {
          var retVal = null;
          switch (getTagName(this)) {
            case "rect":
              retVal = d.size;
              break;
            default:
          }
          return retVal;
        })
        .style("fill", function(d) {
          return d.color || "black";
        })
        .style("fill-opacity", function(d) {
          return d.opacity || 1;
        });
      var updateSelNav = navG.selectAll("circle").data(data);
      updateSelNav.exit().remove();
      updateSelNav
        .enter()
        .append("circle")
        .attr("r", 1)
        .attr("fill", "black");
      updateSelNav
        .attr("cx", function(d) {
          return Math.round(xNav(d.time));
        })
        .attr("cy", function(d) {
          return yNav(d.category);
        });
    } 
function refresh ( ) { data = data . filter ( function ( d ) { if ( d . time . getTime ( ) > startTime . getTime ( ) ) return true ; } ) ; var categoryCount = yDomain . length ; if ( debug ) console . log ( "yDomain" , yDomain ) ; var updateSel = barG . selectAll ( ".bar" ) . data ( data ) ; updateSel . exit ( ) . remove ( ) ; updateSel . enter ( ) . append ( function ( d ) { if ( debug ) { console . log ( "d" , JSON . stringify ( d ) ) ; } if ( d . type == undefined ) console . error ( JSON . stringify ( d ) ) ; var type = d . type || "circle" ; var node = document . createElementNS ( "http://www.w3.org/2000/svg" , type ) ; return node ; } ) . attr ( "class" , "bar" ) . attr ( "id" , function ( ) { return "bar-" + barId ++ ; } ) ; updateSel . attr ( "x" , function ( d ) { var retVal = null ; switch ( getTagName ( this ) ) { case "rect" : var size = d . size || 6 ; retVal = Math . round ( x ( d . time ) - size / 2 ) ; break ; default : } return retVal ; } ) . attr ( "y" , function ( d ) { var retVal = null ; switch ( getTagName ( this ) ) { case "rect" : var size = d . size || 6 ; retVal = y ( d . category ) - size / 2 ; break ; default : } return retVal ; } ) . attr ( "cx" , function ( d ) { var retVal = null ; switch ( getTagName ( this ) ) { case "circle" : retVal = Math . round ( x ( d . time ) ) ; break ; default : } return retVal ; } ) . attr ( "cy" , function ( d ) { var retVal = null ; switch ( getTagName ( this ) ) { case "circle" : retVal = y ( d . category ) ; break ; default : } return retVal ; } ) . attr ( "r" , function ( d ) { var retVal = null ; switch ( getTagName ( this ) ) { case "circle" : retVal = d . size / 2 ; break ; default : } return retVal ; } ) . attr ( "width" , function ( d ) { var retVal = null ; switch ( getTagName ( this ) ) { case "rect" : retVal = d . size ; break ; default : } return retVal ; } ) . attr ( "height" , function ( d ) { var retVal = null ; switch ( getTagName ( this ) ) { case "rect" : retVal = d . size ; break ; default : } return retVal ; } ) . style ( "fill" , function ( d ) { return d . color || "black" ; } ) . style ( "fill-opacity" , function ( d ) { return d . opacity || 1 ; } ) ; var updateSelNav = navG . selectAll ( "circle" ) . data ( data ) ; updateSelNav . exit ( ) . remove ( ) ; updateSelNav . enter ( ) . append ( "circle" ) . attr ( "r" , 1 ) . attr ( "fill" , "black" ) ; updateSelNav . attr ( "cx" , function ( d ) { return Math . round ( xNav ( d . time ) ) ; } ) . attr ( "cy" , function ( d ) { return yNav ( d . category ) ; } ) ; }
(which happens constantly), or after arrival of new data, or at init
( which happens constantly ) or after arrival of new data or at init
// process data to remove too late data items // determine number of categories // here we bind the new data to the main chart // note: no key function is used here; therefore the data binding is // by index, which effectivly means that available DOM elements // are associated with each item in the available data array, from // first to last index; if the new data array contains fewer elements // than the existing DOM elements, the LAST DOM elements are removed; // basically, for each step, the data items "walks" leftward (each data // item occupying the next DOM element to the left); // This data binding is very different from one that is done with a key // function; in such a case, a data item stays "resident" in the DOM // element, and such DOM element (with data) would be moved left, until // the x position is to the left of the chart, where the item would be // exited // remove items // add items // update items; added items are now part of the update selection //.style("stroke", "orange") //.style("stroke-width", "1px") //.style("stroke-opacity", 0.8) // create update selection for the nav chart, by applying data // remove items // add items // added items now part of update selection; set coordinates of points // end refreshChart function