Dashboards & Visualizations

ChartElement selection event fires after render

Contributor

Is there any way to tell that the selection event on ChartElement fired right after render wasn't initiated by the user? I'd like to do a bunch of stuff if the user has dragged a new selection, but not when Splunk is figuring out how it's going to draw the graph.

Here's a code snippet:

var ce = new ChartElement({ ... }, {}).render();
ce.on('selection', function(e) {
  e.preventDefault();

  // determine if this event actually happened because a user did something.
});

My end goal is to modify the values of a timepicker based on what the user chose. Unfortunately, this event fires A LOT, and I can't figure out if the user initiated the change.

0 Karma

Champion

Oh, I hate this issue. You will see the same thing in SimpleXML or JavaScript.

You can get around it by still using SimpleXML and a JavaScript extension.

The way to get around it is to use JavaScript extension to spy on the Reset button on the chart. That will tell you if the user as triggered the pan and zoom feature. You can download my app (Layer8Insight App for Splunk, https://splunkbase.splunk.com/app/3171/), and look at the JS file /appserver/static/dd-app-ux-session.js to see the whole code segment in context.

Here is one of the XML segments for one of my charts.

<selection>
  <set token="time_dd_select_metrics.earliest">$start$</set>
  <set token="time_dd_select_metrics.latest">$end$</set>
</selection>

Here is my code as it appears in that file. The gist is that you listen for changes to either one of those tokens, set a timer for a very short amount of time so that both values have time to update, and then check if the Reset button is present on the chart before changing the drilldown time token form.dd_time. Note, I have two charts that use the selection feature to change the drilldown time values, hence why you see another set of tokens time_dd_select_alerts..... You can ignore that part and the passing of the chart id.

var pan_zoom_timer_is_on = 0;

// set timeout to evaluate pan-zoom time changes
function setPanZoomTimer(chart) {
  if (!pan_zoom_timer_is_on) {
    myVar = setTimeout(checkPanZoomBoundaries, 100, chart);
    pan_zoom_timer_is_on = 1;
  }
}

// see if pan-zoom feature is active in order to set the drilldown time
// based on the selected time range
function checkPanZoomBoundaries(chart) {
  if (pan_zoom_timer_is_on) {
    pan_zoom_timer_is_on = 0;
  }

  var ts_earliest, ts_latest;

  if (chart === "chart_ux_plot") {
    ts_earliest = appUtils.getToken("time_dd_select_metrics.earliest");
    ts_latest = appUtils.getToken("time_dd_select_metrics.latest");
  } else {
    ts_earliest = appUtils.getToken("time_dd_select_alerts.earliest");
    ts_latest = appUtils.getToken("time_dd_select_alerts.latest");
  }

  chart = "#" + chart;

  // spy on the reset button on the charts to determine if the pan-zoom feature is active,
  // which means the drilldown time should be adjusted
  if ($(chart).find('[class*="btn-reset"]').length && ts_earliest > 0 && ts_latest > 0) {
    appUtils.setToken("form.dd_time.earliest", ts_earliest);
    appUtils.setToken("form.dd_time.latest", ts_latest);
    setDrilldownButton("#btn_dd_enable", true);
    appUtils.submitTokens();
  }
}

// listen to changes in the pan-zoom values
defaultTokenModel.on("change:time_dd_select_metrics.earliest", function(model, value, options) {
  setPanZoomTimer("chart_ux_plot");
});
defaultTokenModel.on("change:time_dd_select_metrics.latest", function(model, value, options) {
  setPanZoomTimer("chart_ux_plot");
});

defaultTokenModel.on("change:time_dd_select_alerts.earliest", function(model, value, options) {
  setPanZoomTimer("chart_ux_alerts_plot");
});
defaultTokenModel.on("change:time_dd_select_alerts.latest", function(model, value, options) {
  setPanZoomTimer("chart_ux_alerts_plot");
});

I will be at .conf2017 presenting on this kind of thing. You can find my session here (http://conf.splunk.com/sessions/2017-sessions.html#tracks=Foundations&search=Ryan%20Thibodeaux&). I actually call out this example in my appendix. Would be happy to talk if you are going and can attend.

0 Karma

Champion

@vbumgarner, did you have any luck trying my solution? Please let me know if you have any questions.

0 Karma

Legend

By Selection do you mean 'mouseover' or 'Click'? Can you elaborate the scenario? The question is not specific at the moment.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

Legend

This can be done directly via Simple XML (no need to SplunkJS extension or HTML conversion). Since, this is selection event, I am not sure how this is triggering for you while rendering the chart itself. Ideally it can trigger only on selection of specific area of the chart.

element4.on('selection', function(e) {
    e.preventDefault();
    setToken("selection.earliest", TokenUtils.replaceTokenNames("$start$", _.extend(submittedTokenModel.toJSON(), e.data)));
    setToken("selection.latest", TokenUtils.replaceTokenNames("$end$", _.extend(submittedTokenModel.toJSON(), e.data)));
    setToken("start.count", TokenUtils.replaceTokenNames("$start.count$", _.extend(submittedTokenModel.toJSON(), e.data)));
    setToken("end.count", TokenUtils.replaceTokenNames("$end.count$", _.extend(submittedTokenModel.toJSON(), e.data)));
});

Refer to Splunk Documentation on <selection> Event Handler in simple XML and available tokens: http://docs.splunk.com/Documentation/Splunk/latest/Viz/EventHandlerReference#selection

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

Contributor

Right. I've tried this before with the simple xml. You get the same behavior.

What I actually want to do is change the TimePicker used for the overall query, based on what the user selects, but since it changes on its own to some timescale that lines up with buckets, and then fires that event again, it does the search at least twice. Now, throw more than one graph on the page with this selection event, and it gets really funky. You can end up with a page that never stops redrawing.

I'm using the javascript because I'm drawing multiple graphs and tables dynamically based on user input.

0 Karma

Legend

@vbumgarner, so what I understand is that you are collecting the token on Selection change and then want to redraw the same chart with selection.

Ideally you should try either one of the following options:
(1) Have a separate Button to submit the earliest and latest time of selection to the form, so that entire chart redraws (but events are separate i.e. User select a Time Range and then user accepts the time range by clicking on a button. This is the behavior in the Timeline bar of the _raw Events tab when you perform a Search without transforming command. You can make a Selection which filters the Events based on Selection. When you click on Zoom to Selection, it re-runs the search to get only the events for the selected time range on Timeline.

(2) Have a second panel similar to the one where user is making Selection. When the Selection is made i.e. selection tokens are set, hide the main chart and display the second chart using rejects and depends based on selection tokens respectively. You can code vice-versa from the second chart to toggle back to first.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma
State of Splunk Careers

Access the Splunk Careers Report to see real data that shows how Splunk mastery increases your value and job satisfaction.

Find out what your skills are worth!