Cascading submit buttonsHighlander and Splunk? Really?

Such a mental stretch may come to mind shortly after digging for examples of how to add buttons - Submit buttons specifically - to Splunk dashboards.

Have you built a dashboard with input filters inside of panels? Did you want to localize the filtering you apply to data in your charts? Then you probably wished you had a Submit button in that panel.


Unlike the Immortals (for which there was always more than one), SimpleXML in Splunk 6.x does not allow more than one Submit (or any type of) button per dashboard (double-check here).


Are Submit buttons special? No.


Can you put them in places other than the top of a dashboard? You bet.


Can you do more than "submit" all tokens with a button? Absolutely.


Per usual with my posts, it's time to break out the JavaScript.


Splunk Submit buttons are not that different than buttons you see elsewhere on the web. Like most web-related items in the Splunk Web Framework, they are just a variation of the built-in buttons from Bootstrap.

Adding JavaScript and CSS extensions for this use case is no different than any other. Look here as a reference or check my other posts for more examples of using JavaScript and CSS in SimpleXML dashboards.

Before diving into the JavaScript, let's make note of one thing: where Splunk currently likes to put the Submit button. Per the earlier Splunk reference, we know that the sole Submit button lives in a fieldset element on the top of a dashboard. The fieldset element is also found atop of every Splunk panel that holds input elements / forms.

Now let's start with the JavaScript function to generate a button and put it where we want and how to make it look. Below is the RequireJS function that will put a button in Splunk dashboard based on a number of options.

The parameters to our function generateButton specify the how the button should look and where to put it. The what or action taken when clicking the button will come later.

Parameters to generateButton:

  • id: the HTML identifier to assign to the button
  • label: the text to display on the button (e.g., "Submit", "Toggle", etc.)
  • parent: the HTML id of the HTML panel element that will contain the button
  • append: boolean value indicating if the button should be inserted as the last child (append = true) of the containing fieldset, or if the button should be inserted as the first child or prepended (append = false)
  • submit: boolean value indicating if you want the button to appear like a normal "Submit" button (e.g., green in color) or not
  • vertical: boolean value indicating if the button's CSS attributes should be set for vertical alignment in a panel or horizontal, where the latter (vertical = false) is the common scenario (e.g., Submit button in a horizontal row with other inputs)

Note, the repeated conditional statement of the form !!var is a shorthand expression in JavaScript that evaluates undefined values as false.

      // generate HTML button in a parent element
      function generateButton(id, label, parent, append, submit, vertical) {

        var btn = document.createElement('button');
        var span;

        // apply id field
        if (typeof id !== 'undefined' && id.length > 0) {
          btn.id = id;
          btn.name = id;
        }

        // apply label
        if (typeof label !== 'undefined' && label.length > 0) {
          span = document.createElement('span');
          span.innerHTML = label;
          btn.appendChild(span);
        }

        // assign styling and insert if parent is discovered
        if (typeof parent !== 'undefined' && parent.length > 0) {
          var parentID = (parent[0] === '#' ? parent : '#' + parent);
          var p = $(parentID);

          // set button in its place of the parent
          if (p.length) {
            var t = p.find('.fieldset');
            if (t.length) {
              t = $(t[0]);
              if (!!append) {
                t.append(btn);
              } else {
                t.prepend(btn);
              }
            }
          }
        }

        // set button type classes and CSS
        if (!!submit) {
          btn.className = 'btn btn-primary';
        } else {
          btn.className = 'btn-info';
          btn.style.padding = "3px 12px";
          btn.style.borderRadius = "4px";
        }

        // set button's CSS based on it being in a
        // vertical stack of items or not
        if (!!vertical) {
          btn.style.verticalAlign = 'middle';
          btn.style.margin = "5px 10px 5px 0px";
        } else {
          btn.style.verticalAlign = 'top';
          btn.style.marginTop = "21px";
          btn.style.marginRight = " 10px";
        }

        return $(btn);
      }



Using the generateButton function, we can create a new Submit-style button in a panel with just a few lines of JavaScript. We also add another non-Submit button that allows us to toggle a token to reveal some other hidden HTML element.

    require([
        'underscore',
        'jquery',
        "splunkjs/mvc",
        "splunkjs/ready!",
        "splunkjs/mvc/simplexml/ready!",
    ], function(_, $, mvc) {

      // generate HTML button in a parent element
      function generateButton(id, label, parent, append, submit, vertical) {
         ...
      }

      // Sets token 'name' to 'value' in submittedTokenModel
      function setSubmittedToken(name, value) {
        if (typeof name === 'undefined') {
          return;
        }
        var tokens = mvc.Components.get('submitted');
        if (tokens) {
            tokens.set(name, value);
        }
      }

      // Copy defaultTokenModel values into submittedTokenModels
      function submitTokens() {
        var submittedTokens = mvc.Components.get('submitted');
        var defaultTokens = mvc.Components.get('default');
        if (submittedTokens && defaultTokens) {
          submittedTokens.set(defaultTokens.toJSON());
        }
      } 

      // create Submit button inside of a Splunk panel named "panel_custom_table"
      generateButton('btn_submit', 'Submit', '#panel_custom_table', true, true, false).click(function() {
        submitTokens();
      });

      // create special toggle button inside of a Splunk panel named "panel_custom_chart" 
      // where clicking the toggle button reveals another hidden panel using
      // a token named "show_panel"
      generateButton('btn_toggle', 'Show Panel', '#panel_custom_chart', true, false, false).click(function() {
        if ($(this).hasClass('btn-info')) {
          $(this).removeClass('btn-info');
          $(this).addClass('btn-secondary');
          $(this).html('Close Panel');
          setSubmittedToken('show_panel', "true");
        } else {
          $(this).removeClass('btn-secondary');
          $(this).addClass('btn-info');
          $(this).html('Show Panel');
          setSubmittedToken('show_panel', undefined);
        }
      });
    });



These are simple examples of how to add new buttons to do the same old thing as the generic Submit button or inserting some new capabilities that are more web-like.

There are few inherent limitations to what you can do with JavaScript extensions - it just takes some time and determination to get it to do what you want it to do.

Do you want more examples of what can be done with JavaScript extensions? Check out the screenshot below that includes custom Submit buttons, input tooltips, input element highlighting, table cell highlighting, custom-panel widths, etc.

Need some help figuring these things out? Try downloading open-source apps / repositories where developers have done the groundwork for you. You can also ping me on the Slack team chat for the Splunk User Group community via the handle @artie73.

Note, this screenshot is from our Layer8Insight App for Splunk. Get a trial of Layer8Insight here to obtain the endpoint data needed to interact with our Splunk app.



JavaScript features