title: Flot charts- producing custom trend with unique x-axis values
body: <p>I have DB relation that holds information that I wish to display.
  each record holds a numerical value, and a 'name' that looks like '20140325_064532'.</p>
  
  <p>The order of creating the records doesn't matter, and so I wish to present the numerical value on the y-axis and the x axis to have:</p>
  
  <ol>
  <li>to have <strong>constant margin</strong> between ticks.</li>
  <li>to present the data based on <strong>'name' order</strong> (lexicographic).</li>
  <li>the x-axis label shouldn't present all the values, but "selected ones", such that no overlapping should be displayed.</li>
  <li>to prevent two point to be placed in the same x-value, even if they hold the same 'name' (the inner order has no meaning).</li>
  </ol>
  
  <p>how should I define my Flot chart so this can be achieved?</p>
  
  <p><strong>EDIT</strong>: My implementation thoughts so far:</p>
  
  <ol>
  <li>I will fetch (distinctly) from the DB the 'name' field along with a row_number value (starting from 1).</li>
  <li>Based on that I'll create a Hash, using the names as the key to the row number. Lets say     <code>:name =&gt; row#</code></li>
  <li><p>I'll generate the series(s) with the following structure:     <code>rawdata = [ [row#1, numericValue1], [row#2, numericValue2], ....];</code> </p>
  
  <p>Note that row# will be a numerical value starting at 1.</p></li>
  <li><p>I'll define the ticks to represent the actual names. (This will be a line graph with dots, and not a bar chart).</p></li>
  </ol>
  
  <p><strong>Now, all of this will work (I think) but looks really messy.
  And, ontop, the ticks will almost surely overlap, and as to the fact that it will be hard coded, any zooming-in and out will not render the ticks with overlapping thoughts.</strong></p>
  
  <p><strong>Update #2:</strong></p>
  
  <p>I passed the data to the js using two data attributes.
  the 'results' has an array that representing the series, and holds 4 fields, such that
       <code>data-results="[[[0,371144,"20140206_000030-std",375],[1,373141,"20140328_230027",343],[2,374196,"20140401_230051",436],[3,374734,"20140401_230051_2",460],[4,374394,"20140401_230051_3",484],[5,376029,"20140401_230051_4",508]],... ,[another_series]]]</code></p>
  
  <p>The 3rd field is 'name' and the last one is 'id'</p>
  
  <p>the 'series' reresents the name I have for each series (and how it is displayed in the legend), and looks like:</p>
  
  <pre><code>data-series="["PLATFORM_A__CONFIG_B","PLATFORM_B__CONFIG_NONE"]"
  </code></pre>
  
  <p>I tried editing the   <code>content</code> of the tooltip trying to integrate information from the last part of each point, so that I'll have something like this displayed:
  Run: 
  ID: 
  value: $y (the 2nd array field, representing the y-axis value)</p>
  
  <p>I searched the web but couldn't find anything that works using tooltip (which looks nicer to handle).
  in the docs it is mentioned:</p>
  
  <blockquote>
    <p>If you require even more control over how the tooltip is generated you
    can pass a callback function(label, xval, yval, flotItem) that must
    return a string with the format described.</p>
  </blockquote>
  
  <p>I tried implementing this by calling Chart.getTooltip but all I get in the console is </p>
  
  <pre><code>Uncaught TypeError: undefined is not a function jquery.flot.tooltip.min.js?body=1:2h jquery.flot.tooltip.min.js?body=1:2(anonymous function) jquery.flot.tooltip.min.js?body=1:2jQuery.event.dispatch jquery.js?body=1:4642elemData.handle jquery.js?body=1:4310jQuery.event.trigger jquery.js?body=1:4551(anonymous function) jquery.js?body=1:5261jQuery.extend.each jquery.js?body=1:384jQuery.fn.jQuery.each jquery.js?body=1:137jQuery.fn.extend.trigger jquery.js?body=1:5260Y jquery.flot.cust.min.js?body=1:2V jquery.flot.cust.min.js?body=1:2jQuery.event.dispatch jquery.js?body=1:4642elemData.handle jquery.js?body=1:4310
  </code></pre>
  
  <p><strong>Update #3</strong>
  Thanks to @Ryley great tips and guidance, I was able to correctly display my chart using the unique values passed into Flot.
  I've updated my code so that in order to avoid overlapping in the ticks values, I used    <code>flot-tickrotor</code> js to rotate the looks. 
  I've came across with a problem, in which my bottom values gets cut-off.
  I've also noticed that this is a <a href="https://github.com/markrcote/flot-tickrotor/issues/3" rel="nofollow">reported issue</a>, but I couldn't find any solution or workaround for this. 
  Is there any solution for this issue?</p>
  
  <p>Next, I want to enable to viewer to show/hide the series with a click.
  I found bunch of solutions, both official and others, but none of those worked for me.
  I'll explain:</p>
  
  <ol>
  <li><a href="http://www.flotcharts.org/flot/examples/series-toggle/index.html" rel="nofollow">Official turning series on/off</a>: this works, but looks very messy as the legend is eventually duplicated twice (disappears from official legend once the series turned off).</li>
  <li><a href="https://github.com/markrcote/flot-hiddengraphs" rel="nofollow">Hiddengraphs.js</a>: this is a plugin which can be found at the plugin repository, but it doesn't work and interact well with Chrome (tried more than one machine, it just don't work). </li>
  <li><a href="http://jsfiddle.net/AcuC7/1/" rel="nofollow">This solution</a> is actually really nice (I don't mind that there are no checkboxes to check), but when I integrated it into my code, all I got was "jumping" to the top of the page, and nothing happens.</li>
  <li><a href="http://jess.murdoch.edu.au/fpebel.shtml" rel="nofollow">Lastly, I found this solution</a>, which also works, altough using another js library, called    <code>flot.togglelegend.js</code>.
  In this implementation I found some major conflicts with    <code>flot.cust.js</code>, and couldn't get them both to work together. </li>
  </ol>
  
  <p>Finally, I tried to implement the select-zooming and double-click zoom-reset, using      <code>flot.selection.js</code>
  I was able indeed to get the functionality to work, but the re-rendering process generates into my second and third chart the data of the first one.</p>
  
  <p>It is also worth saying that I'm rendering 3 charts in this page, all rendered in the same way.</p>
  
  <p>Here's my updated code:</p>
  
  <p>Here's my current js (written in coffeescript)</p>
  
  <pre><code>colorArray = []
  colorArray.push "rgba(180, 0, 75,    0.6)"
  colorArray.push "rgba(0, 150, 100,   0.6)"
  colorArray.push "rgba(0, 0, 255,     0.6)"
  colorArray.push "rgba(140, 0, 255,   0.6)"
  colorArray.push "rgba(90, 180, 20,   0.6)"
  colorArray.push "rgba(255, 236, 0,   0.6)"
  colorArray.push "rgba(234, 170, 21,  0.6)"
  colorArray.push "rgba(95, 180, 190,  0.6)"
  colorArray.push "rgba(214, 92, 63,   0.6)"
  colorArray.push "rgba(218, 106, 234, 0.6)"
  colorArray.push "rgba(213, 128, 155, 0.6)"
  
  # chart colors default 
  $chrt_border_color = "#efefef"
  $chrt_grid_color = "#DDD"
  $chrt_main = "#E24913"
  
  # red       
  $chrt_second = "#6595b4"
  # blue      
  $chrt_third = "#FF9F01"
  # orange    
  $chrt_fourth = "#7e9d3a"
  # green     
  $chrt_fifth = "#BD362F"
  # dark red  
  $chrt_mono = "#000"
  
  Chart = 
  
  generateDataObjects: (all_series, all_series_data) -&gt;
      plotData = []
  
      for series, i in all_series
          obj =
              label: series.replace /__/g, "|"
              data: all_series_data[i]
              color: colorArray[i]
  
          plotData.push obj
  
      return plotData
  
  getTooltip: (label, xval, yval, flotItem) -&gt;
      return 'Build: &lt;span&gt;'+ flotItem.series.data[flotItem.dataIndex][2]+'&lt;/span&gt;' +" | Run ID: &lt;strong&gt; #{flotItem.series.data[flotItem.dataIndex][3].toString()}&lt;/strong&gt;" + '&lt;br&gt; Result: &lt;span&gt;'+Chart.commify(yval)+'&lt;/span&gt;'
  
  commify: (x) -&gt;
      return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  
  generateChartOptions: (legend_container, ticks) -&gt;
      return (
          series:
              lines:
                  show: true
  
              points:
                  show: true
  
          crosshair:
              mode: "x"
  
          legend:
              container: $("##{legend_container}")
              # labelFormatter: (label, series) -&gt;
  #                   "&lt;a href=\"#\" onClick=\"togglePlot(" + series.idx + "); return false;\"&gt;" + label + "&lt;/a&gt;"
              noColumns: 4
              # hideable: true
  
          grid:
            hoverable: true
            clickable: true
            tickColor: $chrt_border_color
            borderWidth: 0
            borderColor: $chrt_border_color
  
          tooltip: true
          tooltipOpts: 
            content : Chart.getTooltip
            #content : "Value &lt;b&gt;$x&lt;/b&gt; Value &lt;span&gt;$y&lt;/span&gt;",
            defaultTheme: false
  
          xaxis:
              ticks: ticks
              rotateTicks: 30
  
          selection:
              mode: "xy"
          )
  </code></pre>
  
  <p>jQuery ->
      if $("#normalized_bw_chart").length         # render only if the chart-id is present</p>
  
  <pre><code>    raw_data = $("#normalized_bw_chart").data('results')
      ticks = $("#normalized_bw_chart").data('ticks')
      all_series = $("#normalized_bw_chart").data('series')
  
      plot = $.plot($("#normalized_bw_chart"), Chart.generateDataObjects(all_series, raw_data), Chart.generateChartOptions('normalized_bw_legend', ticks))    
  
  if $("#concurrent_flows_chart").length      # render only if the chart-id is present
  
      raw_data = $("#concurrent_flows_chart").data('results')
      ticks = $("#concurrent_flows_chart").data('ticks')
      all_series = $("#concurrent_flows_chart").data('series')
  
      plot = $.plot($("#concurrent_flows_chart"), Chart.generateDataObjects(all_series, raw_data), Chart.generateChartOptions('concurrent_flows_legend', ticks))
  
  if $("#bandwidth_chart").length         # render only if the chart-id is present
  
      raw_data = $("#bandwidth_chart").data('results')
      ticks = $("#bandwidth_chart").data('ticks')
      all_series = $("#bandwidth_chart").data('series')
  
      plot = $.plot($("#bandwidth_chart"), Chart.generateDataObjects(all_series, raw_data), Chart.generateChartOptions('bandwidth_legend', ticks))    
  
  $("[data-behavior~=chart-selection]").bind "plotselected", (event, ranges) -&gt;
          selected_chart = $(this).attr('id')[0...-6] # slicing the name of the selected item
          console.log  ("zooming in to " + selected_chart)
          plot = $.plot($("##{selected_chart}_chart"), plot.getData(), $.extend(true, {}, Chart.generateChartOptions(selected_chart+'_legend', ticks),
            xaxis:
              min: ranges.xaxis.from
              max: ranges.xaxis.to
  
            yaxis:
              min: ranges.yaxis.from
              max: ranges.yaxis.to
          ))
       return
  
  $("[data-behavior~=chart-selection]").bind "dblclick", (event, pos, item) -&gt;
          selected_chart = $(this).attr('id')[0...-6] # slicing the name of the selected item
          console.log  ("zooming out to " + selected_chart)
          plot = $.plot($("##{selected_chart}_chart"), plot.getData(), $.extend(true, {}, Chart.generateChartOptions(selected_chart+'_legend', ticks),
            xaxis:
              min: null
              max: null
        yaxis:
          min: null
          max: null
      ))
   return
  </code></pre>
  
  <p>thanks a lot!</p>