5

So I know it's something to do with AJAX, but I've read a few topics and don't quite understand what I have to do. Currently everything works fine, but I have to refresh the page for my script to run. What needs to be done with my code to get it working without refresh?

// ==UserScript==
// @name    Job Aids
// @description Aid in closing tickets
// @include https://techaccess.ad.qintra.com/WorkJobs/WorkJobs.aspx*
// @namespace   camzilla.net
// @version     1.1.20121128
// ==/UserScript==

var url  = window.location.href.split(".aspx");
var page = url[1].toLowerCase();

if (page == "#finaltest") {
    window.addEventListener ("load", finalResults, false);
} else if (page == "#threetoneslope") {
    window.addEventListener ("load", toneSlopeResults, false);
} else if (page == "#codes") {
    window.addEventListener ("load", closingComments, false);
} else if (page == "#cras") {
    window.addEventListener ("load", crasResults, false);
} else if (page == "#jobinfo") {
    window.addEventListener ("load", addLinks, false);
} else if (page == "") {
    if (getCookie("updater") == null) {
        var d = new Date();

        setCookie("updater", d.getTime(), 1);
        try {
            updateCheck();
        } catch(err) {
            // alert('Update checking failed');
        }
    }

    // setTimeout(promptDispatch, 1000);
}

function addLinks() {
    var mydiv   = document.querySelector('div[data-bind="CurrentJob.addr"]');
    var address = 'https://maps.google.com/maps?q=' + mydiv.textContent + ", UT";
    address.replace(/ /g, '+');  
    var a       = document.createElement("a");
    var txt     = document.createTextNode(mydiv.textContent);
    mydiv.textContent = "";
    a.appendChild(txt);
    a.href   = address;
    a.target = '_blank';
    mydiv.appendChild(a);

    mydiv   = document.querySelector('div[data-bind="CurrentJob.cktid"]');
    address = 'http://acmspjv1.interprise.com/cgi-bin/QC/DSL/dslam6100Int.pl?telephoneNum=';
    address+= mydiv.textContent;
    a       = document.createElement("a");
    txt     = document.createTextNode(mydiv.textContent);
    mydiv.textContent = "";
    a.appendChild(txt);
    a.href   = address;
    a.target = '_blank';
    mydiv.appendChild(a);
}

function updateCheck() {
    try {
        GM_xmlhttpRequest(
        {
            method: 'GET',
            url: 'http://camzilla.net/downloads/jobAids.user.js?v' + getCookie("updater"),
            headers: {'Cache-Control': 'no-cache'},
            onload: function(resp) {
                var local_version, remote_version, rt, script_name;

                rt = resp.responseText;
                remote_version = (/@version\s*(.*?)\s*$/m.exec(rt)[1]);
                local_version  = GM_info.script.version;

                if (remote_version != local_version) {

                    if(confirm(GM_info.script.name+' update v'+remote_version+ ' is available.\nWould you like to install it now?')) {
                        GM_openInTab('http://camzilla.net/downloads/jobAids.user.js');
                    } else {
                        alert('You will be reminded again tomorrow');
                    }
                }
            }
        });
    } catch(err) {
        // do something here
    }
}

function setCookie(c_name, value, exdays) {
    var exdate=new Date();
    exdate.setDate(exdate.getDate() + exdays);
    var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
    document.cookie=c_name + "=" + c_value;
}

function getCookie(c_name) {
    var i,x,y,ARRcookies=document.cookie.split(";");

    for (i=0;i<ARRcookies.length;i++) {

        x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
        y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
        x=x.replace(/^\s+|\s+$/g,"");

        if (x==c_name) {
            return unescape(y);
        }
    }

    return null;
}

function finalResults() {
    var dc, current, loss, noise, pi, lb;

    dc      = getRandom(51, 49, 2);   
    current = getRandom(37, 29, 2);
    loss    = getRandom(7, 2, 2);
    noise   = getRandom(7, 1, 2);
    pi      = getRandom(67, 60, 2);
    lb      = getRandom(79, 70, 2);

    document.getElementById('finalTestInsightNo').click();

    document.getElementById("finalTestBeforeAcTg").value        = "0.00";
    document.getElementById("finalTestBeforeAcRg").value        = "0.00";
    document.getElementById("finalTestBeforeAcTr").value        = "0.00";
    document.getElementById("finalTestBeforeDcTr").value        = dc;
    document.getElementById("finalTestBeforeDcTg").value        = "0.00";
    document.getElementById("finalTestBeforeDcRg").value        = dc;
    document.getElementById("finalTestBeforeLoopCurrent").value = current;
    document.getElementById("finalTestAfterLoss").value         = loss;
    document.getElementById("finalTestAfterNoise").value        = noise;
    document.getElementById("finalTestAfterPi").value           = pi;
    document.getElementById("finalTestAfterLb").value           = lb;

    document.getElementById("finalTestAfterLb").focus();
    window.scrollTo(0, document.body.scrollHeight-250);

    // Store cookies to be used on cras page if needed
    setCookie("loss", loss, 1);
    setCookie("pi", pi, 1);
    setCookie("current", current, 1);
    setCookie("noise", noise, 1);
    setCookie("lb", lb, 1);
}

function crasResults() {
    document.getElementById("crasCircuitLoss").value    = getCookie("loss");
    document.getElementById("crasPowerInfluence").value = getCookie("pi");
    document.getElementById("crasLineCurrent").value    = getCookie("current");
    document.getElementById("crasCircuitNoise").value   = getCookie("noise");
    document.getElementById("crasBalance").value        = getCookie("lb");

    document.getElementById('crasFoundInF2').click();
}

function toneSlopeResults() {
    var dc = getRandom(51, 49, 2);   

    document.getElementById("ToneSlopeInsightNo").click();
    document.getElementById("ToneSlopeDmarcTaggedYes").click();
    document.getElementById("ToneSlopeClecDtPresentYes").click();

    document.getElementById("ToneSlopeBeforeDcTr").value    = dc;
    document.getElementById("ToneSlopeBeforeDcTg").value    = "0.00";
    document.getElementById("ToneSlopeBeforeDcRg").value    = dc;   
    document.getElementById("ToneSlopeRingbackTr").value    = getRandom(90,85,2);
    document.getElementById("ToneSlopeAfterResistTg").value = getRandom(998,20,0);
    document.getElementById("ToneSlopeAfterResistRg").value = getRandom(998,20,0);
    document.getElementById("ToneSlopeAfterResistTr").value = getRandom(998,20,0);

    document.getElementById("ToneSlopeAfter404").value      = "0.00";
    document.getElementById("ToneSlopeAfter1004").value     = getRandom(7, 3, 2);
    document.getElementById("ToneSlopeAfter2804").value     = "0.00";
    document.getElementById("ToneSlopeAfterNoise").value    = getRandom(7, 1, 2);
    document.getElementById("ToneSlopeAfterLb").value       = getRandom(79, 70, 2);
    document.getElementById("ToneSlopeCotName").value       = "NA";

    document.getElementById("ToneSlopeTn").focus();
}

function closingComments() {
    document.getElementById("flatRateJacks").value = "0";
    document.getElementById("rewiredJacks").value  = "0";

    document.getElementById("tripNo").click();
    document.getElementById("marketMass").click();
    document.getElementById("custTypeRes").click();
    document.getElementById("pairChangeNo").click();
    document.getElementById("tempDropNo").click();
    document.getElementById("goodCbrYes").click();

    document.getElementById("jobCloseComments").focus();
    window.scrollTo(0, 5000);
}

function getRandom(max, min, tenths) {
    var result = min + (Math.random() * (max - min + 1));
    return result.toFixed(tenths);
}
Cameron Darlington
  • 355
  • 2
  • 7
  • 14

2 Answers2

7

See "addEventListener only working at page refresh?" for more information and a similar scenario.

Page elements, that your script expects, are no doubt appearing after the load event has fired. Additionally, from your comments, it sounds like whole sections of the page are swapped out by AJAX, but the AJAX is polite enough to change the URL hash. This means you'll want to fire off the hashchange event.

Don't use addEventListener ("load"... in this case. Use the waitForKeyElements() utility in conjunction with hashchange.

Without refactoring the whole script to use jQuery (which would give clearer and more robust code), replace everything before function addLinks() {..., with:

// ==UserScript==
// @name        Job Aids
// @description Aid in closing tickets
// @include     https://techaccess.ad.qintra.com/WorkJobs/WorkJobs.aspx*
// @namespace   camzilla.net
// @version     1.1.20121128
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require     https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant       GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/

//-- Pages are "loaded" via AJAX...
window.addEventListener ("hashchange", fireOnNewPage,  false);

waitForKeyElements ("#crasCircuitLoss",                 crasResults);
waitForKeyElements ("#finalTestInsightNo",              finalResults);
waitForKeyElements ("#flatRateJacks",                   closingComments);
waitForKeyElements ("#ToneSlopeInsightNo",              toneSlopeResults);
waitForKeyElements ("div[data-bind="CurrentJob.addr"]", addLinks);

function fireOnNewPage () {
    switch (location.hash.toLowerCase() ) {
        case "#finaltest":
        case "#threetoneslope":
        case "#codes":
        case "#cras":
        case "#jobinfo":
            //-- No action needed, waitForKeyElements() handles this.
        break;
        default:
            if (getCookie("updater") == null) {
                var d = new Date();

                setCookie("updater", d.getTime(), 1);
                try {
                    updateCheck();
                } catch(err) {
                    // alert('Update checking failed');
                }
            }
        break;
    }
}
fireOnNewPage ();   //-- Initial run on initial, full page load.
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • I posted the entire script. I didn't realize you would need all of it. Just to avoid confusion since I'm an amateur, could you update your code to show exactly how I would use it? – Cameron Darlington Dec 24 '12 at 18:39
  • Okay, updated the answer. The key was to choose appropriate selectors. Didn't port the rest of the script to jQuery as that's too much work, and out of scope, for this question. But it should work much better with the new front section. (Can't vouch for the whole script; it uses a ton of elements without safeguards for when they are not there.) – Brock Adams Dec 24 '12 at 19:10
  • Still have to refresh each page. Posted the html here http://pastebin.com/6KkKqC0C All those additional pages are loaded when you click on a button that links to it somehow. – Cameron Darlington Dec 24 '12 at 19:46
  • I ended up putting an inteval in there to check my page every 1/3 of a second and run the code accordingly. It works, but assuming there is a better way still. – Cameron Darlington Dec 24 '12 at 20:07
  • See the updated answer. From your comments, it seems the page is doing major swaps via AJAX, but is polite about updating the hash. – Brock Adams Dec 24 '12 at 20:15
  • Thanks for all your help Brock. I had to make some minor changes, but the idea is good. – Cameron Darlington Dec 24 '12 at 21:57
  • You're welcome. Glad you got it sorted. For my edification, please pastebin the script showing the changes you needed to make. – Brock Adams Dec 24 '12 at 22:37
  • window.addEventListener ("hashchange", fireOnNewPage, false); This was the line I needed. waitforkeyelements was not working for some reason, so I had to continue using eventlistener "load", but everything is working perfectly now. – Cameron Darlington Dec 26 '12 at 17:34
  • Hi @BrockAdams, I'm having a similar issue. I posted a [question](http://stackoverflow.com/q/27693612/1077789). Can you please take a look at it? – Isuru Dec 30 '14 at 08:54
-1

check out some ajax examples across the net by searching. for example: http://www.w3schools.com/ajax/ajax_examples.asp

AJAX, or (A)synchronous (J)avascript (A)nd (X)ML (which interestingly enough tends to use JSON more these days), is a system in which Javascript uses a browser object to communicate with a remote server. The general use case of this is to be able to update a client's interface without needing to go to another page. Before we begin though, a few words of caution.

Ajax is not recommended for login authentication and posting forms Users can turn off Javascript, or may be restricted from running Javascript due to IT policies

With this in mind it is advised that you do not use AJAX as the sole solution for critical user functionality! Always have a fallback! Note: This community wiki post uses JQuery to show the example AJAX calls. It's recommended for newcomers as it hides the browser compatibility issues of making AJAX calls. Please check the JQuery website for more information on JQuery.

Note: The examples use communication with a PHP server, but any server side language will work.

AJAX Callbacks

function makeAjaxCall() {
  $.ajax({
    url: 'ajax/test.html',
    success: function(data) {
      alert('Horray the AJAX call succeeded!');
    },
    error: function(xhr, error) {
      alert('Holy errors batman!');
    }
  });
}

The Nature of AJAX Calls

AJAX calls can be either Asynchronous or Synchronous. Asynchronous means that the browser will make the AJAX request and continue doing other things. Synchronous means the browser will stop what it's doing until the AJAX call completes. Here is an example of the differences in the two code wise:

// An asynchronous call
// This is the default
$.ajax({
  url: '/server.php',
  success: function(data) {
    alert('Horray the AJAX call succeeded!');
  },
  error: function(xhr, error) {
    alert('Holy errors batman!');
  }
});
// This will get called right away
myFunction();
Now for a synchronous call:

// A synchronous call
$.ajax({
  url: '/server.php',
  async: false, // set the property here
  success: function(data) {
    alert('Horray the AJAX call succeeded!');
  },
  error: function(xhr, error) {
    alert('Holy errors batman!');
  }
});
jsteinmann
  • 4,502
  • 3
  • 17
  • 21
  • This does not seem to apply to this question. Remember it's a Greasemonkey context, so the user does not control the target page. And, his script does not appear to be doing AJAX itself. – Brock Adams Dec 24 '12 at 18:25