I write Greasemonkey scripts to do all sorts of automation and screen scraping for my job. I've got a list of items/accounts to work on and I iterated through them pulling data from various web tools.
I trap the document ready event and start my processing from there, and when I'm done I'll load the next page in sequence either with a window.href or just clicking a link to the next page.
Every now and then when the page loads Greasemonkey doesn't run. There's no errors in the consoles and if I just refresh the page it works. It's like the #include directives are failing. I'd say the URL was changing but it's not, and a page refresh starts the script just fine (albeit with me having to stop what I'm doing and hit F5).
Anyone seen this before? Is there anything I can do about it (short of switching to Selenium)?
// ==UserScript==
// #name testG
// #version 1
// #grant none
// #require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
// ==/UserScript==
var mySearches = localStorage.getItem('mySearches');
var myResults = localStorage.getItem('myResults');
if (mySearches){
mySearches = JSON.parse(mySearches);
}else{
mySearches = ["one", "two", "three","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39"];
localStorage.setItem('mySearches', JSON.stringify(mySearches));
}
if (myResults){
myResults = JSON.parse(myResults);
}else{
myResults = [];
}
$(document).ready( function() {
var search = $("input[title='Search']");
console.log("mySearches is " + JSON.stringify(mySearches));
var mySearch = mySearches.shift();
myResults.push(mySearch);
localStorage.setItem('myResults', JSON.stringify(myResults));
search.val( mySearch );
if ( mySearches.length < 1){
localStorage.removeItem('mySearches');
alert (myResults);
}else{
myResults.push(mySearch);
localStorage.setItem('mySearches', JSON.stringify(mySearches));
window.location.replace("https://www.google.com");
}
} );//END DOCUMENT READY
Related
I'm trying to add a script tag to every dom page through privileged chrome, so far i'm able to get the first pageload of a tab, but after that, the script does nothing, I'm using Firefox Nightly 44.0. What am i doing wrong???
Documents I'm following:
https://developer.mozilla.org/en-US/Add-ons/Code_snippets/On_page_load
https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/Intercepting_Page_Loads
mozilla-central/browser/base/content/browser.xul (line: 74)
<script type="application/x-javascript" src="chrome://browser/content/yyy/x.js" />
chrome://browser/content/yyy/x.js
var myExtension = {
init: function() {
// The event can be DOMContentLoaded, pageshow, pagehide, load or unload.
if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);
},
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered the event
var win = doc.defaultView; // win is the window for the doc
// test desired conditions and do something
// if (doc.nodeName != "#document") return; // only documents
// if (win != win.top) return; //only top window.
// if (win.frameElement) return; // skip iframes/frames
alert("page is loaded \n" +doc.location.href);
}
}
window.addEventListener("load", function load(event){
window.removeEventListener("load", load, false); //remove listener, no longer needed
myExtension.init();
},false);
mozilla-central/browser/base/jar.mn
content/browser/yyy/x.js (content/yyy/x.js)
You'll want to use loadFrameScript with argument of true to listen to future pages. Here are examples: https://github.com/mdn/e10s-example-addons/tree/master/run-script-in-all-pages
globalMM.loadFrameScript("chrome://modify-all-pages/content/frame-script.js", true);
This is documented here: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFrameScriptLoader#loadFrameScript%28%29
To stop it from loading in new tabs, then you have to use removeDelayedFrameScript
That github link also shows an example of how to do it with addon-sdk content-scripts.
I'm a newbie trying to not rely so much or at all on using ptor.sleep() calls, especially after the click below. The line below never gets the value (they all return Nan)unless I include the ptor.sleep(1000); call after the click() below.
I've made various attempts to make the array elem to resolve before the results of the list after clicking, wrapping the click in the function, etc, but nothing I've tried works without the sleep calls. Already read up on protractor control flow.
devCountString = parseInt(arr[i]);
Thanks for any insights, maybe something obvious I've missed so that I can remove the ptor.sleep() calls.
my spec:
describe('\n == patch List suite results == \n', function() {
// login already was done in config files, onPrepare function.
var ptor, noFilterCount;
// needed here if we turn ptor.ignoreSynchronization = false;
beforeEach(function() {
ptor = protractor.getInstance();
ptor.ignoreSynchronization = true;
browser.get('https://my.abc.com:3000/fixes');
ptor.sleep(1200);
}); //end beforeEach()
it('11 - verify filter fewer', function() {
var sevStringElm, sevString;
var applicableCount;
ptor.ignoreSynchronization = false;
ptor.sleep(500);
sevStringElm = element(by.css("input.form-control.bf-spinner"));
sevStringElm.clear();
ptor.sleep(500);
sevStringElm.sendKeys( '8' );
ptor.sleep(500);
// click on the "fewer" spinner, wrap the click to wrap the .
var fewerPromise = element(by.css("span.bf-spinner-toggle:nth-child(2)")).click();
ptor.sleep(1000);
// now get the list of clickable elements in each device card. by title
var applicableDevicesElm = element.all(by.css("[title$='Applicable\ Devices']"));
applicableDevicesElm.getText().then(function(arr) {
console.log("arr.length= "+arr.length);
for (var i = 0; i < arr.length; i++) {
devCountString = parseInt(arr[i]);
expect(devCountString).toBeLessThan( 9 );
};
});
});
Everytime an action goes to the webdriver, Protractor will put that into the flow queue as shown in the documentation. As a result, when you get to inspect your elements after the click, the queue should have resolved the dependencies and have your state ready for the finder. In any case, even if you don't want to have the implicit wrapping that Protractor does on its actions (which are always asyc), you can put a .then(function(){}) after the click and put the post click logic in that anonymous calback function.
On a side note, you should have to use ptor anymore. Use browser instead that mixes in the protractor instance capabilities. Example: browser.sleep(1000)
Is it possible to add event listeners for a document before a page has been navigated to using a Bootstrapped add-on? I would like to see what page the user wants to navigate to as well as later after the page loads to inspect the DOM. I need to run code in the HTML content context.
In the past I used a toolbar XUL and included javascript within it and it would load before the HTML page loaded.
i looked into doing stuff before DOMContentLoaded sometime ago and found out there is a document inserted observer.
order of events after running research code at bottom
readystate changes to interactive (i think multiple times, not sure)
readystate changes to complete
DOMContentLoaded event fires
load event fires (Sometimes load doesnt fire, if you might have to change addEventListener with capture arugment (3rd argument) as false or true)
apparently there should be readystate loading before all of this but i can never catch it i dont know why.
after running the code in scratchpad, browser environemnt of course, then load a new page and watch the error console it will throw these reports in this order:
ready state changed! ("interactive") Scratchpad/4:18
02:28:07.873 ready state changed! ("complete") Scratchpad/4:18
02:28:07.874 DOMContentLoaded event fired! Scratchpad/4:53
02:28:07.938 Load event fired! Scratchpad/4:45
here is the research code. it adds a the listeners and observer to see whats firing.
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
var os = Cc['#mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
var LMObserver;
function myObserver() {
this.register();
}
myObserver.prototype = {
observe: function (subject, topic, data) {
//Cu.reportError(subject);
//Cu.reportError(data);
//i think subject is window element
subject.onreadystatechange = function () {
//loading
//interactive
//complete
Cu.reportError('ready state changed! ("' + subject.readyState + '")');
//var body = subject.documentElement.querySelector('body')
//you want to change title so you would do that here do something like: if (subject.readystate == 'complete') { subject.title = 'blah blah' }
//Cu.reportError('has body element: ' + body)
}
},
register: function () {
os.addObserver(this, 'document-element-inserted', false);
},
unregister: function () {
os.removeObserver(this, 'document-element-inserted', false);
}
};
//below this is the DOMContentLoaded thing i put this here so we can see what fires in what order
var pageLoad = function(event) {
var win = event.originalTarget.defaultView;
if (win && win.frameElement) {
return;
}
Cu.reportError('Load event fired!');
}
var pageDOMContentLoaded = function(event) {
var win = event.originalTarget.defaultView;
if (win && win.frameElement) {
return;
}
Cu.reportError('DOMContentLoaded event fired!');
}
LMObserver = new myObserver;
gBrowser.addEventListener("load", pageLoad, true);
gBrowser.addEventListener("DOMContentLoaded", pageDOMContentLoaded, true);
//gBrowser.removeEventListener("load", pageLoad, true);
//gBrowser.removeEventListener("DOMContentLoaded", pageDOMContentLoaded, true);
//LMObserver.unregister();
Here's some more indepth research on load events added with true or false as capture argument: https://github.com/Noitidart/event-listener-experiment-DOMC-and-load/blob/master/bootstrap.js
I have a list of a tags that are hidden. I tried using the data-prefetch attribute as described in the jquery mobile docs. The only problem is it fires off an ajax request for all of them at once and there is no garentee of the order that they get loaded in.
The ordering is very important in what pages are shown next via swipe.
So I decided to try and cache the links programatically via this bit of code.
var last_cache_page = false;
function cache_next_page(){
if(last_cache_page == false){
var cache_link = $('.cache').first();
last_cache_page = cache_link;
}
else{
var cache_link = last_cache_page.nextAll('.cache');
last_cache_page = cache_link;
}
//Start Caching any other pages that we want to swip to
$.mobile.loadPage(cache_link.attr('href'), {showLoadMsg: false});
}
So on $(document).on('pageshow') I call cache_next_page(). That part works fine the real problem is that when using $.mobile.loadPage no jquery mobile page related events fire once the first cached page is interested into the dom.
I have tried pageshow, pageinit and pageload but they only fire the first time the page is loaded. Now if I load the first page which starts the caching directly. That is to say with out visiting any other pages in the application it DOES trigger all the expected events such as pageload.
It is only when you start on page_1 and then go to page_2 (which has the code to start the cache) that it fails to have a pageload event triggered when the cached page is inserted into the dom.
I found out there there is a .done on the object that is returned from .loadPage so I have modified my code as follows to allow it to cache my links in order.
var last_cache_page = false;
function start_caching(){
if(last_cache_page == false){
var cache_link = $('.cache').first();
last_cache_page = cache_link;
}
else{
var cache_link = last_cache_page.nextAll('.cache').first();
last_cache_page = cache_link;
}
if(cache_link.length == 1){
//Start Caching any other pages that we want to swipe to
new_page = $.mobile.loadPage(cache_link.attr('href'), {showLoadMsg: false});
new_page.done(function(){
start_caching();
});
}
}
I'm writing an extension for firefox. Using dom.location to keep track of visited search results pages, i'm getting this url http://www.google.com/search?hl=en&source=hp&q=hi&aq=f&aqi=&oq=&fp=642c18fb4411ca2e . If you click it, the google search results for "hi" should come up. You'll know that from the title bar - because the rest of the page won't load. This happens with any google search. Oddly enough, if you cut part of it off, so say, http://www.google.com/search?hl=en&source=hp&q=hi - it works! But Googling "hi" myself does give me a longish URL - http://www.google.com/#hl=en&source=hp&q=hi&aq=f&aqi=&oq=&fp=db658cc5049dc510 . I know for a fact that the first time that URL was visited, the page loaded, I did it myself.
Can anyone make reason out of this?
I just tried my experiment again, this time saving the original URL in the location bar. It turns out, dom.location.href is giving a different value. How is this happening?
Original:
http://www.google.com/#hl=en&source=hp&q=hi&aq=f&aqi=&oq=&fp=642c18fb4411ca2e
dom.location.href
http://www.google.com/search?hl=en&source=hp&q=hi&aq=f&aqi=&oq=&fp=642c18fb4411ca2e
window.addEventListener("load", function() { myExtension.init(); }, false);
var myExtension = {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
var messagepane = document.getElementById("messagepane"); // mail
if(messagepane)
messagepane.addEventListener("load", function () { myExtension.onPageLoad(); }, true);
},
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
// do something with the loaded page.
// doc.location is a Location object (see below for a link).
// You can use it to make your code executed on certain pages only.
var url = doc.location.href;
if (url.match(/(?:p|q)(?:=)([^%]*)/)) {alert("MATCH" + url);resultsPages.push(url);} else {alert(url);
}
}
This snippet comes directly from Mozilla with the matching and alerts my own. I apologize for not posting the code earlier.
Well, on the "right" page http://www.google.com/#hl=en&source=hp&q=hi&aq=f&aqi=&oq=&fp=1&cad=b there seems to be a frame with the "wrong" location: frames[0].location == "http://www.google.com/search?hl=en&source=hp&q=hi&aq=f&aqi=&oq=&fp=1&cad=b". You're probably getting the inner frame's location. I have no idea why, since you didn't post any of your code and just mention some "dom.location", which I never heard of.