Splunk Search

Fix table header and add vertical scrollbar using CSS and JavaScript

493669
Super Champion

Hi All,

I want to display 100 rows results in table per page with vertical scrollbar and fix the header when we move down.
I am trying to use overflow-y: scroll; on div. so it shows vertical scrollbar but it is showing 10 rows per page with header is not fixed.

can any one please help me...
Thanks.

0 Karma

preacher_15
Explorer

alt text

0 Karma

niketnilay
Legend

@preacher_15 try one of my older answers to decide height of chart based on number of results: https://answers.splunk.com/answers/617135/how-can-i-get-the-bar-chart-with-fixed-bar-height.html

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

preacher_15
Explorer

@niketnilay i wasn't quite able to follow....is it possible to do this in js...or in any other simpler way??? please help.
when i select head 5 bars should appear without scroll...and when is elect head 10....the first 5 bars should remain as it is and a scroll should come so that i can scroll down and see remaining 5....similarly for head 15...first 5 and then scroll down for rest...i got the scrolldown using overflow-y: auto !important;
i just want to fix a limit for scroll so that it appears for head>5...
been stuck at this for a long time...need help.

0 Karma

vnravikumar
Champion

Hi @nagar57

Try this

<dashboard>
  <label>scrollbar_sample</label>
  <row depends="$hide$">
    <panel>
      <html>
      <style>
        #rk div [data-view="views/shared/results_table/ResultsTableMaster"]{
          overflow-y: auto !important;
          height: 300px !important;

        }
        #rk div [data-view="views/shared/results_table/ResultsTableMaster"] table{
        border-collapse: collapse !important;
          width: 10px !important;

        }
        #rk div [data-view="views/shared/results_table/ResultsTableMaster"] th {
          position: sticky !important;
          text-align: left !important;
          top: 0 !important;
        }
      </style>
    </html>
    </panel>
  </row>

  <row>
    <panel>
      <title>Test</title>
      <table id="rk">
        <title>Test</title>
        <search>
          <query>index=_internal |table index, source, sourcetype</query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
        </search>
        <option name="count">100</option>
        <option name="drilldown">none</option>
      </table>
    </panel>
  </row>
</dashboard>

preacher_15
Explorer

Hi @vnravikumar i wanted to do the same thing for a bar chart.... as in.. a bar chart with with bars of same width and a vertical scrolldown to go up and down to view all the bars... is it possible??

0 Karma

james_hopton
New Member

Thank you for a great example of two things. Embedding css and customizing the table.

0 Karma

vnravikumar
Champion

@preacher_15, Can you post some screenshot?

0 Karma

preacher_15
Explorer

@vnravikumar iam trying but not able to send any scrrenshots..
edit: i can post it down below as answer...so please look into it

0 Karma

vnravikumar
Champion

@preacher_15

Try this, and modify height accordingly

<dashboard>
  <label>chart</label>
  <row>
    <panel>
      <html>
      <style>
        #rk div [data-view="views/shared/ReportVisualizer"]{
        overflow-y: auto !important;
          height: 300px !important;
        }

        #rk .facets-container{
        height: 600px !important;
        }
      </style>
    </html>
    </panel>
  </row>
  <row>
    <panel>
      <chart id="rk">
        <search>
          <query>index=_internal |stats count by component</query>
          <earliest>-4h@m</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">bar</option>
        <option name="charting.drilldown">none</option>
        <option name="refresh.display">progressbar</option>
      </chart>
    </panel>
  </row>
</dashboard>

preacher_15
Explorer

@vnravikumar thank you very much it worked

0 Karma

preacher_15
Explorer

@vnravikumar and also is there any way where i can fix the space between the bars??

0 Karma

preacher_15
Explorer

@vnravikumar

edit:was able to fix the space between the bars using charting.chart.barSpacing

is it possible to fix the width of the bar....as in if i am showing 30 bars the width should be same as when iam showing 10 bars...of course i have to scrolldown to see all the bars ...but can it be done???

0 Karma

preacher_15
Explorer

@vnravikumar
is it possible to fix the width of the bar..?? initially just say show 5 bars in a chart no need of scrolling...but if when i select 10 or more scroll should come without changing the size of the bar....first it should show just 5 and when i scroll down the other 5 will be visible?? can it be done ?? please help

0 Karma

nagar57
Communicator

This is great. It worked like magic. Thanks a lot.
Just a small thing I'd like to point out is I can see the rows getting scrolled up in the background of the table header which looks little odd.
Can you suggest something to to make them not visible in the background?

0 Karma

nagar57
Communicator

Does anyone resolved this? I am also having the same requirement.
@niketnilay I tried your solution but that is also not working for me. The table header is hidden and dummy table header is not getting displayed.
Here is my XML:

<row>
 <panel>
    <html>
      <style>
        #tableFixedHeader {
         position: fixed; /* Set the Dummy Table Header to fixed position */
         z-index: 2; /* Overlay Dummy Table Header on Table Body through z-index priority */
       }
       #tableFixedHeader div.lazy-results-table {
         width: 98% !important; /* Due to fixed position of Dummy Table Header Table width 100% does not account for padding*/
       }
       div[id^="tableFixedHeader-footer"]{
         visibility: hidden; /* Table footer should not be displayed for Dummy Table Header*/ 
       }
       #tableFixedHeader tbody{
         visibility: hidden; /* Dummy Table has only one row. Hide the Dummy Table body */
       }
       #tableScrollBody{
         z-index: 1;
       }
       #tableScrollBody thead{
         visibility: hidden; /* Hide the Header from Table Body as the Header is displayed through Dummy Table with Header */
       }
      </style>
    </html>
   <title>Pre-Live Offer Details</title>
   <input type="dropdown" searchWhenChanged="true" token="OfferStatus">
     <label>Offer Status</label>
     <choice value="*">All</choice>
     <choice value="Live">Live</choice>
     <choice value="Live with No Enrollments">Live with No Enrollments</choice>
     <choice value="Live with Missing Elements">Live with Missing Elements</choice>
     <choice value="Ready to Go Live">Ready to Go Live</choice>
     <choice value="Ready to Go Live with Missing Elements">Ready to Go Live with Missing Elements</choice>
     <choice value="In-Process">In-Process</choice>
     <choice value="Failed">Failed</choice>
     <choice value="Stalled">Stalled</choice>
     <default>*</default>
   </input>
  <table id="tableFixedHeader">
      <!-- Query to create Dummy Table with only one row. Used Post Processing to avoid separate search query. 
      Post Processing would not be required if Base Search does not contain transforming command or returns raw events as table. 
      It would be better to re-run the same query with | head 1, instead of post processing.-->
      <search base="baseSearch">
        <query>
          | head 1
        </query>
      </search>
      <option name="count">1</option>

     <option name="rowNumbers">true</option>

    </table>
   <table id="tableScrollBody">
     <search id="baseSearch">
       <query>

|inputlookup oip_status_enhancements.csv
| addinfo
|eval five_days_ago=relative_time(now(),"-5d@d")
|where OFFR_STRT_DT1Epoch>= strptime(strftime(now(),"%m/%d/%y"),"%m/%d/%y") OR ((Status="In-Process" OR Status="Failed" OR Status="Stalled" OR Status="Live with Missing Elements") AND OFFR_STRT_DT1Epoch>=five_days_ago)

|replace "ALL" with * in OFFR_ID
|replace "*ALL" with * in GCOR_ID
|replace "*ALL" with * in MDT_ID
|replace "*ALL" with * in MDT_CAMPAIGN_ID
|rename MDT_ID as "Offer ID", MDT_CAMPAIGN_ID as "MDT Campaign Id", OFFR_ID as "RC ID", GCOR_ID as "DOE ID",OFFR_STRT_DT as "Offer Start Date(MST)",OFFR_END_DT as "Offer End Date(MST)",CountryCode as "Country Code", OFFER_GOAL as "Offer Type/Goal"
| replace "
, Intl" with "*" in "Country Code"
|search Status="$OfferStatus$"
|rename CountryName as "Country Name", Status as "Offer Status" Redemption_Type AS "Redemption Type" CMCount AS "Eligibility Count"
|table OfferName, "Offer Status","Offer Start Date(Local)", "Offer Start Date(MST)", "Offer End Date(MST)", "Offer Type/Goal" "Country Code" "Eligibility Count" "MDT Campaign Id" "Offer ID" "RC ID" "DOE ID" "Redemption Type" couponLess
-90d
now

100
true
none
row
true

0 Karma

niketnilay
Legend

@493669, while I could not figure out Splunk JS changes to format TableView with Fixed Header, following is a CSS based change position: fixed; that will fix table header. Applying it to the main table with data would not let bootstrap apply required table formatting, hence,

1) I created a dummy table with single row.
2) Then I fixed the Dummy Table Header,
3) Hidden one dummy row and
4) Also hidden the Actual Table Header to be replaced by Dummy Table Header whose position was fixed through CSS.
5) Finally through CSS set the z-index for Dummy Table with Header to be higher priority than the Actual Table with Data so that Fixed Dummy table Header Overlays.

PS: I have to set the width the Fixed Table Header to slightly less than 100% to account for padding which does not get applied by Bootstrap due to our fixed position CSS override.

For setting the Table rows to 100 following Simple XML Table Configuration option has been used:

<option name="count">100</option>

alt text

Following is a run anywhere sample dashboard running on Splunk's _internal index.

<dashboard hideChrome="false" hideTitle="false" hideEdit="false">
  <label>Fix Table Header and Vertical Scroll</label>
  <row>
    <panel>
      <html>
        <style>
          #tableFixedHeader {
            position: fixed; /* Set the Dummy Table Header to fixed position */
            z-index: 2; /* Overlay Dummy Table Header on Table Body through z-index priority */
          }
          #tableFixedHeader div.lazy-results-table {
            width: 98% !important; /* Due to fixed position of Dummy Table Header Table width 100% does not account for padding*/
          }
          div[id^="tableFixedHeader-footer"]{
            visibility: hidden; /* Table footer should not be displayed for Dummy Table Header*/ 
          }
          #tableFixedHeader tbody{
            visibility: hidden; /* Dummy Table has only one row. Hide the Dummy Table body */
          }
          #tableScrollBody{
            z-index: 1;
          }
          #tableScrollBody thead{
            visibility: hidden; /* Hide the Header from Table Body as the Header is displayed through Dummy Table with Header */
          }
        </style>
      </html>
      <table id="tableFixedHeader">
        <!-- Query to create Dummy Table with only one row. Used Post Processing to avoid separate search query. 
        Post Processing would not be required if Base Search does not contain transforming command or returns raw events as table. 
        It would be better to re-run the same query with | head 1, instead of post processing.-->
        <search base="baseSearch">
          <query>| head 1
          </query>
        </search>
        <option name="count">1</option>
      </table>
      <table id="tableScrollBody">
        <!-- Table with content. Created as Base Search to pass on the results to -->
        <search id="baseSearch">
          <query>index=_internal sourcetype=splunkd
| timechart span=5m count by log_level
          </query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
        </search>
        <!-- Table option to show 100 results per page. -->
        <option name="count">100</option>
      </table>
    </panel>
  </row>
</dashboard>

Please try out and see if it suffices the needs. If it does not you will have to search online for
1) Detailed CSS override for fixed menu in a page or
2) SplunkJS Stack with Custom Render for TableView
3) Create your own custom visualization to display table as per your need using Splunk Custom Visualization API.

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

493669
Super Champion

@niketnilay,
Currently i am trying below css:-

  table>tbody {
      overflow: scroll !important;
      height: 400px !important;
      overflow-x: hidden !important;
      display: block  !important;
      width: 100% !important;
    }

table>thead {
                display: block  !important;
                position: relative  !important;
                width: 100% !important;
}

thead tr th:nth-child(1) {
width: 2.7% !important;
text-align: left !important;
}


tbody tr td:nth-child(1) {
width: 1.2% !important;
text-align: left !important;
}

tbody tr td:nth-child(2) {
width: 1.2% !important;
text-align: left !important;
}

thead tr th:nth-child(2) {
width: 2.7% !important;
text-align: left !important;
}
0 Karma

niketnilay
Legend

@493669, is your CSS working for you? Have you tried the run any where dashboard example I have provided? Can it suffice the need? Will you be having only Table in your Dashboard or other visualizations as well?

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

493669
Super Champion

the above css is fixing the header . I need to make few alignment changes for th and td for all child.
Thanks @niketnilay
I tried your dashboard example it is fixing header position but when I scroll I am seeing rows above and below that header.
I am populating my dashboard after serch criteria and then clicking on submit button the table is getting displayed .
So I am fixing table (panel) height too.

0 Karma

493669
Super Champion

@niketnilay

Could you please suggest any modification on above css for auto alignment

0 Karma
Did you miss .conf21 Virtual?

Good news! The event's keynotes and many of its breakout sessions are now available online, and still totally FREE!