html Javascript Programing

Creating an extension that automatically clicks on the "Following" tab when you open Twitter.

Twitter's Specification Change Makes “For you" the Default

In 2023, Twitter's specifications changed a bit and the "For you" view became the default.

To see only the tweets of people you follow in chronological order, you need to click on “Following” tab.

It is a hassle to click it every time, so we would like to automate it if possible.

There are already extensions with this kind of functionality, but I decided to create my own.

Click on the element found with the attribute role="tab".

The code itself looks like the following.

When I looked at the HTML source in Chrome's “Inspect", I found that the “For you" and “Following" tabs had the attribute role="tab", so I just searched for them and clicked on the second one in the found array.

const tabs= document.querySelectorAll('[role="tab"]');
tabs[1].click();

If you paste this code as is into the Chrome console, it will switch.

Make it a Chrome extension

To make it a Chrome extension, create an appropriate folder and create two files in it: content_script.js and manifest.json.

If you write the URL of the twitter home screen ("https://twitter.com/home") in the matches of manifest.json, the script will run automatically every time the home screen is accessed.

manifest.json

{
  "name": "Twitter Autoselect Following Tab",
  "description": "when open https://twitter.com/home ,select following tab automatically ",
  "version": "0.2",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": [
        "https://twitter.com/home"
      ],
      "js": [
        "content_script.js"
      ],
      "run_at": "document_end",
      "all_frames": true
    }
  ]
}

content_script.js

window.addEventListener("load", main, false);

function main() {
  const jsInitCheckTimer = setInterval(jsLoaded, 1000);
  function jsLoaded() {
    if (document.querySelector('[role="tab"]') != null) {
      clearInterval(jsInitCheckTimer);
      autoSelectFollowing();
    };
  }
}

function autoSelectFollowing() {
  const tabs = document.querySelectorAll('[role="tab"]');
  tabs[1].click();
};

Since Twitter content is dynamically generated, simply writing the process alone will result in an error because it will be executed before the element is loaded.

The part of the process to run the Chrome extension after the page loads was borrowed from the following article. Thanks.

Qiita:動的なページの読み込みが完了してからChrome拡張機能を実行する方法

Register the extension with Chrome

Once the code is ready, go to the Chrome extensions screen chrome://extensions/, turn on developer mode, and drag and drop the folder or use "Load Unpackaged Extensions" to load it.

Then, when you access the Twitter home screen, the "Following" tab will be automatically selected.

It's a little more comfortable for now.

Sometimes it doesn't work.

However, this code sometimes does not work.

It seems like it doesn't work when I go to twitter/home from other pages in Twitter. Even then, when I reload the page, it switches to the following tab. Why is this?

At any rate, if I set my browser bookmark to twitter/home instead of twitter.com, it no longer fails on the first access. (I have already fixed the above code)

Apparently, it still needs to be improved.

PS: To make it Ajax compliant, catch DOM changes with MutationObserver.

After that, I did some research.

It seems that the above script sometimes does not work well because Twitter seems to change the URL without generating a load event.

When you click on an icon in a page, the new content is loaded by Ajax and the URL is changed by the pushState method or something like that.

I had never heard of pushState, replaceState, or any other method that changes only the address.

After some more research, I found out that monitoring changes in the DOM is a good way to capture transition events caused by Ajax.

The method I used was MutationObserver.observe().

https://developer.mozilla.org/ja/docs/Web/API/MutationObserver

https://developer.mozilla.org/ja/docs/Web/API/MutationObserver/observe

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe

// 監視対象の要素を取得。特定の要素に絞らずに"document"とかでもいい。
const elementToObserve = document.querySelector("#targetElementId");

// 新規MutationObserverオブジェクトを作成して、コールバック関数を設定する
const observer = new MutationObserver(function() {
    console.log('callback that runs when observer is triggered');
});

// 監視対象の要素とオプションで監視対象にするものを設定する
observer.observe(elementToObserve, { attributes: true,subtree: true, childList: true });
//アトリビュートフィルターの使い方
// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe

function callback(mutationList) {
  mutationList.forEach((mutation) => {
    switch(mutation.type) {
      case "attributes":
        switch(mutation.attributeName) {
          case "status":
            userStatusChanged(mutation.target.username, mutation.target.status);
            break;
          case "username":
            usernameChanged(mutation.oldValue, mutation.target.username);
            break;
        }
        break;
    }
  });
}

const userListElement = document.querySelector("#userlist");

const observer = new MutationObserver(callback);
observer.observe(userListElement, {
  attributeFilter: [ "status", "username" ],
  attributeOldValue: true,
  subtree: true
});

Improved support for page transitions within Twitter

So here is an improved version.

The observe() method catches changes in the DOM, and when the URL changes to /home, it looks for a tab element to switch to, and clicks on it when found.

I tried to set attributeFilter as an option of observe() to catch only the URL change, but it did not fire the event properly.

So, for now, we are capturing all DOM changes and checking for URL changes on our own.

As with the first version, I use setInterval to search and click on tabs.

On Twitter, DOM change events occur frequently.

If we leave it as it is, a large number of timers will run at the same time, so we only run setInterval the first time there is a URL change.

The code is as follows

console.log("Twitter auto select following tab script launched");

let oldLocationPath = "";

function main() {
  if (oldLocationPath === "/home") return;
  oldLocationPath = "/home";
  const jsInitCheckTimer = setInterval(jsLoaded, 1000);
  function jsLoaded() {
    if (document.querySelector('[role="tab"]') != null) {
      clearInterval(jsInitCheckTimer);
      autoSelectFollowing();
    };
  }
}

function autoSelectFollowing() {
  const tabs = document.querySelectorAll('[role="tab"]');
  if (tabs[1].getAttribute("aria-selected")) {
    tabs[1].click();
    console.log("following selected.");
  }

};


const config = {
  attributes: true,
  childList: true,
  subtree: true,
  // attributeFilter:[location]   did not work
};

const callback = function (mutationsList, observer) {
  console.log("DOM Changed. check if url is twitter.com/home: " + location.pathname);
  if (location.pathname === "/home") {
    main();
  } else {
    oldLocationPath = location.pathname;
  };
};

const observer = new MutationObserver(callback);
observer.observe(document, config);

{
  "name": "Twitter Autoselect Following tab",
  "description": "when open https://twitter.com/home ,select following tab automatically ",
  "version": "0.4",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": [
        "https://twitter.com/*"
      ],
      "js": [
        "content_script.js"
      ],
      "run_at": "document_end",
      "all_frames": true
    }
  ]
}

At least it seems to be working.

It's fun to solve these problems on my own.

Also, it's good for my mental stability to know 100% of what's in the extension.

-html, Javascript, Programing