Tampermonkey script - Refresh needed - ajax

I'm trying to create a simple script to autoclick a buy button as soon as the browser goes from the cart page to the checkout page. The script doesn't work unless I manually refresh the checkout page. It appears the site uses AJAX.
I started with this simple script
// ==UserScript==
// #name Auto place order
// #version 0.1
// #description Autoclicks on buy button
// #author You
// #match https://www.mywebsite.com/buy/placeOrder
// #grant none
// ==/UserScript==
(function() {
'use strict';
alert("Matched"); //debug
const buybutton = document.querySelector('#submitOrderButtonId-announce');
if(buybutton) {
buybutton.click()
}
})();
Upon reading other suggestions I tried the below
// ==UserScript==
// #name Auto place order
// #version 0.2
// #description Autoclicks on buy button
// #author You
// #match https://www.mywebsite.com/buy/placeOrder
// #grant none
// #require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// #require https://gist.github.com/raw/2625891/waitForKeyElements.js
// ==/UserScript==
waitForKeyElements ("#submitOrderButtonId", () => {
alert("Matched");
document.querySelector('#submitOrderButtonId-announce').click(); });
but it didn't help. Still needs refresh.
If I use the main domain in #match it works but I can't set it like that.
Could anyone please suggest the exact code I should write to avoid refreshing?

Related

Can I remove extra text in the tab name?

There's a change to the tab name when I receive a notification on social networking sites.
It'll change from Website to 3 Notifications | Website
I'm curious about ways on Firefox I can prevent that sort of change.
Is it possible to filter out certain words from tab names?
You unfortunately cannot prevent tabs from updating the title in any modern browser. The only solution that I've seen, although not ideal, is to use a script to record the initial title of the page and keep the tab updated with that saved value. You can use a greasemonkey script for such a task:
var script = document.createElement("script");
script.textContent = "(" + t.toString() + ")()";
document.body.appendChild(script);
var title = document.title;
var updateTitle = function ()
{
document.title = title;
};
window.setInterval(updateTitle, 0);
The title is usually changed by assigning a new value to the document.title. You can freeze its value after the page is loaded with this user script:
// ==UserScript==
// #name Freeze title page
// #match *://*/*
// #run-at document-idle
// ==/UserScript==
const unsafeDocument = document.wrappedJSObject || document;
let title;
try {
title = unsafeDocument.head.getElementsByTagName('title')[0].innerText;
} catch { }
if (!title) {
title = unsafeDocument.title;
}
Object.defineProperty(unsafeDocument, 'title', {
get() {
return title;
},
set() { },
});
To avoid race condition with other scripts which might change document.title the title is read from <title> tag.
Note that this solution won't work if the title of the page is set to something like 3 Notifications | Website with the <title> element and not via scripts. In such case I have no idea how to do what you want in a generic way. You can hovewer force a manually-defined title on a per URL basis.

Anyone having problems with Greasemonkey #includes not firing?

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

outlook 365 add-in: Office.context is always empty

I work on a simple add-in for outlook 365, but it looks like I'm missing some simple point since office.context variable is always empty for me, for example even base code sample:
// The initialize function is required for all apps.
Office.initialize = function () {
// Checks for the DOM to load using the jQuery ready function.
$(document).ready(function () {
// After the DOM is loaded, app-specific code can run.
var item = Office.context.mailbox.item;
var subject = item.subject;
// Continue with processing the subject of the current item,
// which can be a message or appointment.
});
}
What can I miss? Adds-in permission is highest -- ReadWriteMailbox
Try to take some work example , for example: https://github.com/OfficeDev/Outlook-Add-in-Commands-Translator
You need parts of home.html and home.js.
I think this part of code need to work in your case:
(function () {
'use strict';
// The initialize function must be run each time a new page is loaded
Office.initialize = function (reason) {
$(document).ready(function () {
** now try to get the item **
});
}; })();
I try it and it's work for me..
Good luck.

Firefox Compile Simple Load Script - browser.xul

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.

How do I intercept pjax page changes from a chrome userscript?

Can I detect history.pushState url changes from a chrome user script (not extension), without polling (or breaking out of the script's isolated world to intercept the call in the web page's javascript context)?
My problem, in more detail:
As Github uses history.pushState [WHAT-WG specs] by way of pjax [minimized example] for in-site page-to-page site navigation, instead of reloading the whole page as you browse the site, user scripts targeting a specific url on the site will only fire when you enter the site at that url or manually forcefully reload the page.
I am writing a little user script library on.js for DRY:ing up user scripts, handling that kind of thing for them by intercepting pushState calls to see when we're on a new page the host script wants to run on and only invoking it where relevant.
This would be relatively easy if history.pushState fired events when called, but as best I can tell, no popstate event gets fired except when the first page loads or the user triggers back / forward movement through history, which is fairly useless for my purposes.
I explored limiting it to a pjax/github-only solution too – when a new page loads, github fires a $(document).trigger('pageUpdate') event, but as jQuery implements these internally rather than via DOM events, I can't hear those from the isolated world my user script runs in, unless I inject a little listener in the page itself to have its jQuery instance report this event back to me, and then I might as well hijack the page's history.pushState itself.
Does anyone see other tidy ways of achieving this?
For now, I am taking the not excellent but working latter approach, of injecting a script that intercepts history.pushState calls and fires an event of the same name on the document, once the call has finished (and, optionally, after the pjax pageUpdate event has fired too):
function inject(fn, args) {
var script = document.createElement('script')
, parent = document.documentElement;
args = JSON.stringify(args || []).slice(1, -1);
script.textContent = '('+ fn +')('+ args +');';
parent.appendChild(script);
parent.removeChild(script);
}
inject(function(pjax_event) {
function reportBack() {
var e = document.createEvent('Events');
e.initEvent('history.pushState', !'bubbles', !'cancelable');
document.dispatchEvent(e);
}
var pushState = history.pushState;
history.pushState = function on_pushState() {
if (pjax_event && window.$ && $.pjax)
$(document).one(pjax_event, reportBack);
else
setTimeout(reportBack, 0);
return pushState.apply(this, arguments);
};
}, ['pageUpdated']);
document.addEventListener('history.pushState', function() {
console.log('history.pushState', location.pathname);
// user script code here
}, false);
Before GreaseMonkey changed it's sandbox policy (read: Firefox did, and GM didn't make it backwards compatible) one could use unsafeWindow to fetch an element/window event. Now that that's changed, unsafeWindow isn't working anymore when used with GreaseMonkey API's.
Your proposed answer of injecting a script into the page doesn't work on Github, because of it's very strict content security policy (CSP) not allowing inline scripts;
Content-Security-Policy:default-src *; script-src assets-cdn.github.com collector-cdn.github.com; [...]
My solution is two-fold for two different situations: one with #grant none and one with an GreaseMonkey API #grant.
test-grant-none.user.js
// ==UserScript==
// #name test #grant none
// #namespace https://github.com/jerone/UserScripts
// #include https://github.com/*
// #version 1
// #grant none
// ==/UserScript==
unsafeWindow.$(document).on("pjax:end", function() {
console.log('test #grant none 1');
});
unsafeWindow.$(window).on('popstate', function() {
console.log('test #grant none 2');
});
test-grant-GM.user.js
// ==UserScript==
// #name test #grant GM_*
// #namespace https://github.com/jerone/UserScripts
// #include https://github.com/*
// #version 1
// #grant GM_setValue
// ==/UserScript==
unsafeWindow.$(document).on("pjax:end", exportFunction(function() {
console.log('test #grant GM_* 1');
}, unsafeWindow));
unsafeWindow.$(window).on('popstate', exportFunction(function() {
console.log('test #grant GM_* 2');
}, unsafeWindow));
You can find above scripts here: https://gist.github.com/jerone/e38e8637887559870d84
You can read here more: https://greasyfork.org/en/forum/discussion/3648/hook-into-jquery-existing-events
Thank to Athorcis for pointing me in the right direction.

Resources