Dashboards & Visualizations

How to Run a search using searchmanager (from javascript) when browser/tab closes?

Contributor

I need to run a script only when the browser tab is closed or even the window is closed. That script should in turn update a lookup.

Following is what I am trying. Can someone point out where I am going wrong?

require([ 
        'underscore',
        'jquery',
        'splunkjs/mvc',
        'splunkjs/mvc/utils',
        'splunkjs/mvc/tokenutils',
        'splunkjs/mvc/simplexml/ready!',
        'splunkjs/mvc/searchmanager'
    ], function(_, $, mvc, utils, TokenUtils, SearchManager) {  
    var tokens = mvc.Components.get('default');
    $(window).on("beforeunload", function() { 
        var can_open_field = splunkjs.mvc.Components.getInstance("can_open");
        console.log(can_open_field);
        if(can_open_field != undefined){
            var can_open=tokens.get("can_open_field");
            if(can_open != undefined){                  
                // Handle refresh/tab closure/window closure activities. 
                            // Closing the page should decrement the counter.
                // Instantiate the search manager
                var mysearch = new SearchManager({
                        id: "search1",                      
                        cache: false,
                        search: "|inputlookup instance_validator
                            |eval instance_count=(instance_count-1)
                            | outputlookup instance_validator"
                }); 
                var confirmationMessage = mysearch.on('search:done', function(properties) {
                        console.log("DONE!\nSearch job properties:", properties.content.eventCount);
                        return "Job Completed";
                }); 
                (e || window.event).returnValue = confirmationMessage;
                console.log(confirmationMessage);
                return confirmationMessage;
            }
        }   
    });     
});

Champion

First of all, don't do things in beforeunload events. Custom browser messages, like the one you're using, have long been deprecated in chrome and firefox, and for good reasons. You shouldn't put custom text in browser messages, and you shouldn't interfere when the user tells the browser to close the window. Use the default browser message if you want to alert users who are leaving the site that unsaved changes might get lost, and use "Save & Exit", "Sign out" or "Log off" buttons if you want to handle unsaved content or do other things before a user leaves.
As for why your code doesn't work, I think you need to take a look at the concept of callbacks in js. In your code, line 27 runs immeadiately after the search manager has been created, and assigns the return value of the on function of the mysearch object to confirmationMessage, which I think in this case should be the search manager you just created. Anyway, immediately after that, line 31 is run where you attempt to assign that object to either e.returnValue or window.event.returnvalue if e is something that evaluates to false, though I'm pretty sure this is incorrect syntax and will fail if e is undefined. Anyway, you would then log the object to console in line 32 and return it to the browser in line 33. The browser would then continue its process of unloading the data and closing the window.
What you inteded to do can be done like this:

... continuing from line 19
var mysearch = new SearchManager({
    id: "search1",                        
    cache: false,
    search: "| inputlookup instance_validator | eval instance_count=(instance_count-1) | outputlookup instance_validator"
});    
mysearch.on('search:done', function(properties) {
    // this block is run after the search has sent its 'done' event
    console.log("DONE!\nSearch job properties:", properties.content.eventCount);
    var confirmationMessage = "Job Completed";
    console.log(confirmationMessage);
    // Do more stuff with confirmation message here and close window
});
// Code here is executed immediately after the search as been created, before the block above
// this might be the place for $('exitbutton').disable(); or something

In the callback function you declare there, you could display the confirmation message to the user and close the window for him or navigate to some other place. It might be a good idea to disable the button the user just clicked to prevent them from clicking it again.

What exactly do you track of in that lookup? If you want to keep a record of connected users, you should rely on server side information such as web server logs or application logs, and not on some client side code that might or might not run or changed by the user (possibly by accident).

0 Karma

Contributor

Thanks for the explanation @jeffland. Really appreciate it. But like you said, the search manager should run immediately and put the output into confirmationmessage variable, right? I understand that due to some syntax/conceptual issues the alert or console message is not appearing. But my major concern is the search. I don't see my lookup is getting updated. All those alerts/console logs are just some hit and trials.

All I want is to run the search and update the lookup.

0 Karma

Champion

You should really do it on a button click. Have you created a button and tried running your code on click of that button? This answers post should help you get started with that: https://answers.splunk.com/answers/496890/how-to-use-an-input-typebutton-to-reset-a-token-in.html

0 Karma

Contributor

How do I ensure that a user will click on the button??? ?Here we are trying to run the search on quit (tab/window closure)... Why will someone click on a button while quitting?
Besides, even if I track the 'X' button click on the browser or tab, still that may not help as the user can always use CTRL+W or ALT+F4. I may not be able to track it then.

0 Karma

Champion

Exactly - you don't ensure a user clicks a button. Users either have an incentive to do so (saving their work, complying with workplace regulations to log out before leaving their desk) or they don't. If they don't, then they probably won't. So you have to give them a reason to do it if you want them to click a button. Which re-raises my question from above: what do you want to track in the lookup that makes you want to run code on the client?

0 Karma

Champion

Hi Pramit

I tried small js to write into lookup on window/tab close. Have a look

require([
    "splunkjs/mvc",
    "splunkjs/mvc/searchmanager",
    "splunkjs/mvc/simplexml/ready!",
], function(mvc, SearchManager) {
$(document).ready(function()
{
    $(window).unload(function() {
        query="|makeresults | eval datetime=_time|table datetime | outputlookup ravi.csv append=t";
        mysearch = new SearchManager({
            search: query 
        }).startSearch;
     });


});

});
0 Karma

Contributor

Hi Ravi,

I tried to implement this one. But did not help. I don't think it is even getting executed properly.

0 Karma

Champion

Ok, Pramit. I checked with Splunk 7.2.5.1, Chrome Version 73.0.3683.103 and Opera Version:58.0.3135.127. The script got executed and lookup also updated.

0 Karma

Contributor

Okay let me try in another setup. Will let you know if that works.

0 Karma

Contributor

Hi @vnravikumar,
There were some problems in the code, I tried to fix it.
@pramit46 can you try with following modified code:

require([
    "splunkjs/mvc",
    "splunkjs/mvc/searchmanager",
    "splunkjs/mvc/simplexml/ready!",
], function (mvc, SearchManager) {

    var query = "|makeresults | eval datetime=_time|table datetime | outputlookup ravi.csv append=t";
    var mysearch = new SearchManager({
        search: query,
        autostart: false
    });

    $(window).unload(function () {
        mysearch.startSearch();
    });
});

Also to inform you that this search will also run when the page is reloaded.

0 Karma

Contributor

Hey @vnravikumar, @harshpatel,

I tried something very similar to what both of you had suggested and that worked just fine. The only major difference is, I used beforeunload.

window.addEventListener("beforeunload",function(event) {}

Thanks to both of you for the quick help 🙂 Really appreciate it.

0 Karma

Champion

welcome Pramit 🙂

0 Karma