Dante
Dante

Reputation: 23

Userscript to Click a "Refresh" button every minute except when there is input?

I'm trying to create a Tampermonkey script that would click the page's "Refresh" button every so often, preferably every minute.

It would be even better if it could pause while you are performing other actions on the site like typing but that's more optional.

Reason for this is that we are using a website at work that needs us to keep track of incoming customer requests in a timely manner but the site only has an integrated refresh button that needs to be clicked manually and doesn't refresh automatically.

There are browser plugins which kinda do what I need but they refresh the whole webpage which causes it to loose important information or settings that have been done before. (this does not happen with the refresh button on the site).

So what i have found was the setInterval and the .click function. What i setup was the following which sometimes worked and sometimes didn't. But every time it did work it wouldn't stop even when disabling Tampermonkey.

// ==UserScript==
// @name         Ticket System - Auto Refresh
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://my*******.***.****mand.com/*
// @grant        none
// ==/UserScript==

setInterval(function () {document.getElementById("buttonOcLMZKwM8KoKda967hf2B0_11").click();}, 10000);

//end

I probably have some significant flaws in what i did above but as i said i have no experience with javascript. Also the time used was to test in order to quickly see if it works or not.

As you probably can see i already got stuck at the refresh part, so the stopping part when typing isn't even remotely done.

I also used

document.getElementById("buttonOcLMZKwM8KoKda967hf2B0_11")

and it is very likely target to fail as the website tends to change this ID when you login again. So i tried to do it by using instead:

document.querySelector('[title="Refresh"]');

but that didn't seem to work at all even though the title of the button is Refresh.

This is the full button HTML on the site:

<button type="button" id="buttonOcLMZKwM8KoKda967hf2B0_11" data-sap-ui="buttonOcLMZKwM8KoKda967hf2B0_11" 
data-sap-automation-id="OcLMZKwM8KoKda967hf2B0" title="Refresh" role="button"
aria-disabled="false" tabindex="0" class="sapUiBtn sapUiBtnIconOnly sapUiBtnLite sapUiBtnS width-button-form sapUiBtnStd">
<img id="buttonOcLMZKwM8KoKda967hf2B0_11-img" src="https://.........TbRefresh.png" 
alt="Refresh" class="sapUiBtnIco"></button>

I would really appreciate any help i can get.

Upvotes: 2

Views: 3551

Answers (1)

Brock Adams
Brock Adams

Reputation: 93443

To start and stop polling, or interval clicking, etc.; merely:

  1. Store the value of the setInterval() call.
    EG: var myTimer = setInterval (someFunction, 1000);
  2. Pass that value to clearInterval() to stop the loop.
    EG: clearInterval (myTimer);

Of course, the user interface is the hardest part. I like to:

  1. Put a status and control button in the upper-right of the screen.
  2. Bind a keyboard shortcut to be able to toggle the loop without needing the mouse.

The following userscript does all of the above, plus:

  1. Clicks the "Refresh" button on every iteration of the loop.
  2. Stops/Restarts the loop when the control button is clicked.
  3. Stops/Restarts when F9 is pressed (depending on where the focus is).
  4. Stops the loop when one of the form controls is selected or typed into.
  5. Restarts the loop when the "Refresh" button is clicked.

Here is a complete working userscript (It's just the part above the ****** block.).
To see it in action, Run the code snippet.

// ==UserScript==
// @name     _Click button regularly, with start/stop controls
// @match    *://YOUR_SERVER.COM/YOUR_PATH/*
// @require  https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant    GM_addStyle
// ==/UserScript==

//--- Initialize the refresh button loop and controls.
var rfrshBtnSel = 'button[title="Refresh"]';  //  jQuery selector for the refresh
var rfrshTmr    = LoopManager (clickRefreshButton, 1000);  //  1000 ms == 1 second.
var loopStBtn   = LoopButtonManager (rfrshTmr.toggle);

rfrshTmr.setCallbacks (loopStBtn.start, loopStBtn.stop, loopStBtn.error);
rfrshTmr.start ();  //  Start looping the refresh btn click.

$(window).keydown (keyboardShortcutHandler);

//--- On use of certain form controls, stop the refresh timer:
$("body").on (
    "click keydown focus paste scroll", "input, textarea, select", rfrshTmr.stop
);
//--- On click of the refresh button, (re)start the refresh timer:
$("body").on ("click", rfrshBtnSel, rfrshTmr.start);

function clickRefreshButton () {
    var refreshBtn = $(rfrshBtnSel);
    if (refreshBtn.length === 1)  clickNode (refreshBtn);
    else loopStBtn.error ("Refresh button not found!");
}
function keyboardShortcutHandler (zEvent) {
    if (zEvent.which == 120) {  //  On F9, Toggle the Loop state.
        rfrshTmr.toggle ();
        return false;
    }
    return true;
}
function clickNode (jNode) {
    var clickEvent  = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    jNode[0].dispatchEvent (clickEvent);
}

function LoopManager (callbackFnc, intrvlMillisec, bAutoStart, ...optParams) {
    var _thisInterval = null;
    var _startCB = null, _stopCB = null, _errorCB = null;
    if (bAutoStart)  _start ();

    function _start () {
        if ( ! _thisInterval) {
            _thisInterval = setInterval (callbackFnc, intrvlMillisec, ...optParams);
        }
        if (_startCB)  _startCB ();
    }
    function _stop () {
        clearInterval (_thisInterval);
        _thisInterval = null;
        if (_stopCB)  _stopCB ();
    }
    function _toggle () {
        if (_thisInterval)  _stop ();
        else                _start ();
    }
    function _setCallbacks (startCB, stopCB, errorCB) {
        _startCB = startCB; _stopCB = stopCB; _errorCB = errorCB;
    }
    return {
        start: _start,  stop: _stop,  setCallbacks: _setCallbacks,  toggle: _toggle
    };
}
function LoopButtonManager (clickCB) {
    var _btnNode = $('#tmStartStopBtn');
    if (_btnNode.length === 0) {
        _btnNode = $( `
            <button id="tmStartStopBtn" type="button" class="tmRefreshRunning">
                <span>TBD</span> (F9)
            </button>
        ` ).appendTo ("body");
    }
    var _spanNode = _btnNode.find ("span");

    _btnNode.click (clickCB);

    function _start () {
        setButtonDisplay ("Running", "tmRefreshRunning");
    }
    function _stop () {
        setButtonDisplay ("Stopped", "tmRefreshStopped");
    }
    function _error (errMess) {
        console.error ("TM: " + errMess);
        setButtonDisplay ("See console!", "tmError");
    }
    function setButtonDisplay (btnText, btnClass) {
        _spanNode.text (btnText);
        _btnNode.removeClass ();
        if (btnClass)  _btnNode.addClass (btnClass);
    }
    return { start: _start,  stop: _stop,  error: _error };
}
GM_addStyle ( `
    #tmStartStopBtn {
        position:           absolute;
        top:                0;
        right:              0;
        font-size:          18px;
        margin:             5px;
        opacity:            0.9;
        z-index:            1100;
        padding:            5px 20px;
        color:              black;
        cursor:             pointer;
    }
    .tmRefreshRunning { background: orange; }
    .tmRefreshStopped { background: lime; }
    .tmError { background: red; }
` );

/********************************************************************
******* Everything below this block is simulated target page. *******
******* It's NOT part of the userscript.                      *******
********************************************************************/
$('button[title="Refresh"]').click ( function () {
    $(this).attr ("id", 'spelunk' + Math.random () );
    $("#StatusNd").text ("Refreshed: " + (new Date() + '').replace (/\s*\(.+\)/, "") );
} );
div {
    margin: 0 0 1ex 1em;
    width: 20em;
    padding: 0.5ex 1em 0 1em;
    border: 1px solid darkgreen;
    border-radius: 1ex;
}
label { margin: 0 0 0 2em; }
label[for="Bar"] { display: inline-block;  vertical-align: top; }
button, #StatusNd { margin: 0 0 1ex 2em; }
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://greasyfork.org/scripts/44560-gm-addstyle-shim/code/GM_addStyle_shim.js"></script>
<p>This userscript will click the "Refresh" button every second,<br> unless typing in an input.</p>
<div>Some inputs:<br>
    <label>Foo: <input type="text" id="Foo"></label><br><br>
    <!-- <label for="Bar">Bar: </label>
    <textarea id="Bar"></textarea> -->
</div>
<button type="button" id="some_random_ID" title="Refresh">Refresh</button>
<p id="StatusNd"></p>

Upvotes: 1

Related Questions