All Apps and Add-ons

Can I hide a module on page load

guilhem
Contributor

Hello,

I am using this code to show/hide modules, and it works very well, but I would like to hide the module by default (on page load the module should be hidded). Anything I have tried seems not to work.
Here is the code

Sideview.utils.declareCustomBehavior("hideModule", hideFunction);

function hideFunction(module)
{
        module.onContextChange=contextFunctionCallBack;
}

function contextFunctionCallBack()
{
        if(this.getContext().get("MyParam") == -1)
        {
                this.show();
        }
        else
        {
                this.hide();
        }
}

I have tried to put "this.hide();" in the hideFunction(module), but JS says that hide is not a function, so I have tried to put "this.hide = true;" but it doesn't work either.

I have also tried adding module.onRendered=renderFunctionCallback, and then put a this.hide() inside the renderFunctionCallBack, but it doesn't work either.

I don't know what's going on. If someone has an insight.

Guilhem

1 Solution

guilhem
Contributor

In order for the onContextChange function to be applied on page load, you have to set the autoRun property of the customized module to true.

That's all.

View solution in original post

sideview
SplunkTrust
SplunkTrust

A couple things to be very careful of.

First, you have to be careful if you're overriding a module method that actually does something. It depends on the module, but for most modules, the onContextChange method is quite important. If you reassign that method to another custom method, be aware that whatever the module originally did onContextChange, will no longer happen. So if it's a Pulldown then it will no longer reload its options or absorb values from URLLoader, or if it's an HTML module it will no longer re-render its HTML, etc.

Secondly, the module show() and hide() methods take an argument, and although that argument is technically optional, it can be important. It is a string that's intended to be a unique string that represents the reason for which the module should be shown or hidden. Whatever string you use for the show should also be used for the hide. If you omit this argument, it will work in simple cases. However in more complex cases, for instance in cases where there is more than one mechanism on the page showing and hiding modules (and sending reasons), the "reasons" are crucial because the framework can only show the module when all of the various reasons say that they should be shown. Not passing the reason argument opens a small but significant door here to invite future problems. Basically the reason is "", and if anyone ever writes a second piece of show/hide logic where they cut the same corner, these pieces of logic will fight eachother to the death (!).

You should also be careful to wrap this customBehavior definition in an if statement that makes sure that Sideview Utils is loaded in the given page. Application.js will put the code into every view across the whole app, but on any view where the SideviewUtils module is not present, this code will throw a JS error. There are always globally exported views like flashtimeline and _admin that users will land on unexpectedly and you dont want them to smack into javascript errors.

Here's another version that avoids these problems. Also, I addressed the original problem, such that this example doesn't need autoRun to be set to true. The reference to the module that's passed as an argument to the declareCustomBehavior is the initialized module object so you can just hide it right then and there. It wont be right at the moment the page loads, but it will be very shortly thereafter. (You can use custom CSS to hide the module initially if you want it to be truly invisible when the page is loading. )

if (typeof(Sideview)!="undefined") {
    Sideview.utils.declareCustomBehavior("hideModuleOnPageLoad", function(htmlModule) {
        var visibilityReason = "customBehavior hides the module initially";
        htmlModule.hide(visibilityReason);

        // preserve the existing onContextChange method.
        var methodReference = htmlModule.onContextChange.bind(htmlModule);

        // now override the onContextChange method
        htmlModule.onContextChange = function() {
            var context = this.getContext();
            if (context.get("MyParam") == -1) {
                this.show(visibilityReason);
            } else {
                this.hide(visibilityReason);
            }
            // but note that we both call the original method, and we also are
            // careful to return the original method's return value.
            return methodReference();
        }
    });
}

and here's a little piece of XML that uses this customBehavior:

<module name="Checkbox">
  <param name="name">MyParam</param>
  <param name="onValue">-1</param>
  <param name="label">Show text</param>

  <module name="HTML">
    <param name="html"><![CDATA[
     This content will be initially hidden, and it will only be shown when the checkbox is checked.
    ]]></param>
    <param name="customBehavior">hideModuleOnPageLoad</param>
  </module>
</module>

sideview
SplunkTrust
SplunkTrust

My apologies. it's the same problem though - toggle() works by adding/removing display:none into the html, which will be clobbered when HTML.onContextChange runs, The answer is to stay outside of the confines of the HTML contents. It's easier than it sounds. two examples:

1) instead of this.container.find('div#openModal').toggle();",
this.show()/this.hide() can toggle the whole module.

2) do this.container.addClass("showModal") and this.container.removeClass("showModal") as appropriate and then have contextual CSS - .showModal #openModal {display:block}

0 Karma

justgrumpy
Path Finder

I have the "display: none" in a custom CSS included with the customStylesheet param. In the onContextChange code I have added, "this.container.find('div#openModal').toggle();" to show my div. The "this.show(visibiliyReason);" shows the html module, but doesn't show my div. As I said earlier, the div shows, but disappears again on returning.

0 Karma

sideview
SplunkTrust
SplunkTrust

That's inline CSS, and because the HTML module is always regenerating it's HTML so as to pick up $foo$ token changes, it always regenerates the inline CSS. Thus your inline CSS state is always being clobbered back to "display:none" on every onContextChange. What I meant by custom CSS was more precisely external CSS, either in application.css or in a custom CSS file. If you apply your initial display:none CSS in this way it'll work and the state won't be continually clobbered by the HTML module reloading itself. http://docs.splunk.com/Documentation/Splunk/5.0.2/AdvancedDev/UseCSS

0 Karma

justgrumpy
Path Finder

Nick, in your answer you state, "You can use custom CSS to hide the module initially if you want it to be truly invisible when the page is loading." I am having some difficulty with this. If I have a div in my html module and CSS for that div such as, "display: none;". I can't seem to make it visible again. I added a line to show the div in the onContextChange. If I debug my javascript as it is running I see the div appear while in the onContextChange, but once it returns, the div is invisible again. What do you suggest for the custom CSS and how do you make the html visible again?

0 Karma

Drainy
Champion

Just to echo this, Nick is awesome. Basically the Mr Miyagi of Splunk XML/JS

guilhem
Contributor

Thanks! I really appreciate the time you take to explain all the possible pitfalls to avoid when using splunk.

I will try this solution, as I don't really like to have to rely on autoRun = true for the module to be hidden.

Also, it is good to know that overridding the onContextChange will reset the default behavior, I was having some trouble with it without knowing it. Knowing the bind thing to keep default behavior is also very usefull. I hope I am quite ready to tackle js customisation.

0 Karma

guilhem
Contributor

In order for the onContextChange function to be applied on page load, you have to set the autoRun property of the customized module to true.

That's all.

Get Updates on the Splunk Community!

Introducing Splunk Enterprise 9.2

WATCH HERE! Watch this Tech Talk to learn about the latest features and enhancements shipped in the new Splunk ...

Adoption of RUM and APM at Splunk

    Unleash the power of Splunk Observability   Watch Now In this can't miss Tech Talk! The Splunk Growth ...

Routing logs with Splunk OTel Collector for Kubernetes

The Splunk Distribution of the OpenTelemetry (OTel) Collector is a product that provides a way to ingest ...