scattering clouds

Coding practice 5: Regain control of your web browsing experience.

I’ve been wanting to write this blog post for a long time, but life got busy!

Websites these days are filled to the brim with flashing ads, autoplaying videos, popups, and cookie consents. Some sites would even lock down your ability to scroll, right-click, and select text, making for an awful browsing experience.

On the rare occasion, I may be happy to click on an ad that piques my interest to show support for whomever is providing the content. Most of the times though, I simply get annoyed by the sheer amount of crap we are forced to sift through.

Ways to deal with unwanted ads.

The most common approach is to install an ad blocker, be it an extension added to your browser, or some software installed on your computer or mobile phone.

Problem is, more and more advertising-reliant websites started implementing measures to discourage the use of ad blocking on their site. Even Google started to test out ways to prevent the use of adblockers on YouTube mid-2023.

To access such sites, you have to adjust your adblock filters or create exceptions, which rather defeats the purpose of having an adblocker in the first place.

Another solution is to block websites from running JavaScript code. Most modern browsers come with settings to block JavaScript, and this approach works wonders to stop websites from loading third party advertisements.

Unfortunately, blocking JavaScript may also disable certain core functionalities of a website, such as the ability to

  • bring up a mobile navigation menu,
  • show hidden content by clicking on the “show more” option, or
  • scroll to the top of the webpage using a JavaScript-based “back to top” button.

As we can see, most adblocking methods come with their own pros and cons, and there is no guarantee that things will always work in your favor.

The bookmarklet approach.

I’ve been messing around with bookmarklets in the last few blog posts, and have successfully used them to manipulate certain website elements to improve ease of use, for example:

With all of the above in mind, I decided to explore alternate methods to target, remove, and/or circumvent unwanted website elements using bookmarklets.

Side note: You can visit this blog post to learn how to create and use bookmarklets. You can even make use of bookmarklets on mobile browsers!

The biggest downside to this approach is that changes made using bookmarklets are NOT persistent. Anything that has been adjusted or removed will return once the page refreshes, so it is only good for making temporary changes to a site.

Reenable scrolling.

Some websites will disable your ability to scroll up and down while a popup is active. You can open developer tools and delete the popup, but you remain unable to browse the site contents because scrolling is still disabled on the page.

Fortunately, a few simple lines of code will fix that up right quick.

javascript:(() => {
	let style = document.createElement('style'); 
	style.innerHTML = 'html, body { overflow: auto !important; }';
	document.body.appendChild(style); 
})()

Reenable text selection and editing.

One of my biggest pet peeves are websites that removes your ability to highlight and copy text. Fortunately, there are two ways to reenable this functionality:

javascript: (() => {
	document.body.contentEditable = document.body.contentEditable === 'true' ? 'false' : 'true';
})()

javascript: (() => {
	document.designMode = document.designMode === 'on' ? 'off' : 'on';
})()

Both of the above bookmarklets will achieve the same result, and you only need to use one or the other. This code creates a toggle-able bookmarklet – activate it once to enable text editing, and activate it once again to disable text editing.

Hide / remove a chosen element.

I created this bookmarklet mainly as a quick way to deal with all those pesky popups and cookie consent boxes. Although this bookmarklet can also be used to remove unwanted advertisements, it does so to a much lesser extent.

This is because that most third-party advertisements are enclosed within iframes, and bookmarklets are generally unable to affect anything inside an iframe.

javascript: (() => {
	const flipToggle = () => {
		if(document.body.dataset.scHideElemToggle === undefined) document.body.dataset.scHideElemToggle = "true";
		else document.body.dataset.scHideElemToggle = document.body.dataset.scHideElemToggle === "true" ? "false" : "true";
	};
	const toggleIsActive = () => {
		return document.body.dataset.scHideElemToggle === "true";
	};
	const pushToStack = (e, original) => {
		if(window.scStack) window.scStack = {data:e, display:original, prev:window.scStack};
		else window.scStack = {data:e, display:original, prev:null};
	};
	const popFromStack = () => {
		if(!window.scStack) return;
		window.scStack.data.style.display = window.scStack.display;
		window.scStack = window.scStack.prev;
	};
	const disableDefaultBehaviour = (e) => {
		if(toggleIsActive()) e.preventDefault();
	};
	const hideElement = (e) => {
		if(!toggleIsActive()) return;
		disableDefaultBehaviour(e);
		pushToStack(e.target, e.target.style.display);
		e.target.style.setProperty("display", "none", "important");
	};
	const undoHide = (e) => {
		if(e.ctrlKey && e.key === "z") popFromStack();
	};
	const highlightElement = (e) => {
		if(!toggleIsActive()) return;
		e.target.onclick = null;
		e.target.style.outline = "6px solid red";
		e.target.style.outlineOffset = "-3px";
	};
	const removeHighlight = (e) => {
		e.target.style.outline = "";
		e.target.style.outlineOffset = "";
	};
	const setListeners = () => {
		if (document.body.dataset.scHideListenerAdded !== undefined) return;
		window.addEventListener("mousedown", hideElement);
		window.addEventListener("mouseup", disableDefaultBehaviour);
		window.addEventListener("click", disableDefaultBehaviour);
		window.addEventListener("keydown", undoHide);
		window.addEventListener("mouseover", highlightElement);
		window.addEventListener("mouseout", removeHighlight);
		document.body.dataset.scHideListenerAdded = "true";
	};
	setListeners();
	flipToggle();
})()

There is a lot of things going on in this bookmarklet. It is also toggle-able – activate it once, and any element your cursor moves over will be highlighted in a red outline.

Click on the highlighted element, and it will be hidden from sight.

I have also added some mouse event listeners in an attempt to disable link clicks whilst the bookmarklet is active, although it does not work as well as I had hoped. Mainly because of advertisement links that are embedded within iframes.

The bookmarklet also keeps track of hidden elements using a stack.

If you removed something wrong by mistake, you can use the keyboard shortcut “CTRL” + “z” to undo the removal. If on mobile, you can activate the following bookmarklet instead to perform a single undo:

javascript: (() => {
	const popFromStack = () => {
		if(!window.scStack) return;
		window.scStack.data.style.display = window.scStack.display;
		window.scStack = window.scStack.prev;
	};
	popFromStack();
})()

Remove all elements with the same HTML tag.

Since the previous bookmarklet is unable to deal with advertisements that are enclosed within iframes, I have also created the following bookmarklet to simply remove all elements that belong to the same HTML tag, such as the <iframe> tag.

javascript: (() => {
	const tagNames = [
		'iframe',
		'video'
	];
	if(!window.scLiveList) window.scLiveList = {};
	for(const tagName of tagNames) {
		if(tagName in window.scLiveList) continue;
		window.scLiveList[tagName] = document.getElementsByTagName(tagName);
		window.addEventListener('scroll', () => {
			if(window.scLiveList[tagName] && window.scLiveList[tagName].length > 0) {
				Array.from(window.scLiveList[tagName]).forEach((e) => {
					if('src' in e) e.src = '';
					e.remove();
				});
			}
		});
		window.dispatchEvent(new Event("scroll"));
	}
})()

In this case we are targeting both <iframe> and <video> tags, because they are usually the two most common source of auto-loading advertisements on a website.

The bookmarklet is implemented in such a way that you can add, remove, and target multiple HTML tags if need be. You can create different bookmarklets that deals with different HTML tags, or a subset of HTML tags.

back to top