The below UserScript is meant to work on my own twitter profile page (not the timeline).
// ==UserScript==
// @name CoolScript
// @include https://twitter.com/IJNanayakkara
// @include https://twitter.com/IJNanayakkara/status/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @version 1.0
// @license GPL v3 or any later version (http://www.gnu.org/copyleft/gpl.html)
// @grant GM_addStyle
// ==/UserScript==
function prependToTweet(jNode) {
jNode.prepend("Hello World ");
}
waitForKeyElements("p.js-tweet-text", prependToTweet);
What it does is it appends a given text string to the beginning of every tweet in the page.
Although the script does what I want to, I'm facing two issues.
1. Script affects pages other than the ones defined in @include
.
I install the script and go to my twitter profile. And all the tweets have the Hello World string added to the beginning. This is expected.
But then I go to my timeline page and all the tweets over there also have the Hello World string appended to them which is not an intended behavior.
I need to know why this is happening.
2. Hello World string string duplicates itself.
Say I click on a tweet to view it in a single page. Works fine.
Then I go back to my profile page.
If I go some other page and return again, the string has repeated once more.
These are the two issues I'm facing. I assume these occur due to AJAX but I can't figure out a way to tackle it.
A few things seem to be going on:
When twitter changes to a "new" page, it sometimes keeps the modified text but trashes the jQuery data that waitForKeyElements
uses to track nodes.
When navigating to "new", "unwanted" pages, since there is no page load, the script does not refire and the old waitForKeyElements
is still active.
If you start out on a page were you don't want the adjustments and then navigate to a page were you do, then the script doesn't fire because twitter just displayed a new URL, it didn't actually load much of anything.
Twitter is loading iframes and the script is firing on those too.
To work around the problems we:
- Also track changed nodes by a hard attribute -- which twitter does not trash.
- Change the
@include
to fire on https://twitter.com/*
and then use location.pathname
to refine that further.
- Deactivate
waitForKeyElements
when AJAXing to unwanted pages.
- Monitor
<title>
changes as a reliable way to detect "new" pages.
- Use
@noframes
.
So, this script ought to work better for you (only tested on Greasemonkey, but should work on Tampermonkey):
// ==UserScript==
// @name Twitter: Modify tweets on select pages.
// @include https://twitter.com/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// @noframes
// ==/UserScript==
var tweetSelector = "p.js-tweet-text";
function fireMainCode () {
/*--- Only fire on desired pages. This fires on:
twitter.com/IJNanayakkara*
twitter.com/IJNanayakkara/status/*
*/
if (/^\/IJNanayakkara(\/status\/)?/.test (location.pathname) ) {
if ( ! this.WFKE_fired) {
waitForKeyElements (tweetSelector, prependToTweet);
this.WFKE_fired = true;
}
}
else {
//--- Undesired page, shut off waitForKeyElements
if (this.WFKE_fired) {
this.WFKE_fired = null;
var controlObj = waitForKeyElements.controlObj || {};
var controlKey = tweetSelector.replace (/[^\w]/g, "_");
var timeControl = controlObj [controlKey];
if (timeControl) {
clearInterval (timeControl);
delete controlObj [controlKey]
}
}
}
}
fireMainCode ();
function prependToTweet (jNode) {
var altDoneFlag = jNode.attr ("data-altdoneflag");
if ( ! altDoneFlag) {
jNode.prepend ("XXXXX => ")
.attr ("data-altdoneflag", "yes");
}
}
/*--- Twitter uses some pretty screwy AJAX to "change" pages, but it at least
changes the title. So listen for that to (re) trigger waitForKeyElements.
*/
var myObserver = new MutationObserver (titleChangeDetector);
var obsConfig = {
//-- Subtree needed.
childList: true, characterData: true, subtree: true
};
myObserver.observe (document, obsConfig);
function titleChangeDetector (mutationRecords) {
mutationRecords.forEach ( function (mutation) {
//-- Sensible, Firefox
if ( mutation.type == "childList"
&& mutation.target.nodeName == "TITLE"
) {
fireMainCode ();
}
//-- WTF, Chrome
else if (mutation.type == "characterData"
&& mutation.target.parentNode.nodeName == "TITLE"
) {
fireMainCode ();
}
} );
}