Friday, June 24, 2022

Defeating Blogger's Preview Click Trap

One quirk of Google's Blogger platform is that when you preview posts it sets up an invisible HTML element overlaying the page that keeps click events from being delivered. For example, in preview mode, this link can't be clicked on. In the preview page source code, Google names this element appropriately: blogger-clickTrap. Click trap, indeed.

If you right-mouse click on the preview page and select 'Inspect' you can see the details of this overlay:

Removing the click trap using the inspector panel is straightforward. Add display: none to the blogger-clickTrap element's style and clicks work again.

For years I've either ignored the click trap, or when necessary, manually removed it.

Yesterday, however, I wrote a post that made heavy use of click events. While composing the post I found I needed to frequently refresh the page and then take a few moments to manually remove the overlay. After the 100th time of doing this, I stopped what I was doing and took a moment to consider: could I automatically disable the blogger-clickTrap element?

Tampermonkey to the Rescue

With a few minutes of consideration, I realized that Tampermonkey should be able to save the day. Tampermonkey allows custom code to be injected on the page of your choice. All I needed was to write a few lines of code that would set display: none on the right element when the page loaded, and the click trap would be a distant memory.

I created a new Tampermonkey script to get started:

// ==UserScript==
// @name         Bye-bye clicktrap!
// @namespace    http://blogbyben.com/
// @version      0.1
// @description  Remove blogger preview's clicktrap
// @author       Ben Simon
// @match        https://draft.blogger.com/blog/post/edit/preview/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=blogger.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    console.log("Is this thing on?");
})();

I loaded up the preview page and success!

I then updated the code to show that it could find the offending element:

// ==UserScript==
// @name         Bye-bye clicktrap!
// @namespace    http://blogbyben.com/
// @version      0.1
// @description  Remove blogger preview's clicktrap
// @author       Ben Simon
// @match        https://draft.blogger.com/blog/post/edit/preview/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=blogger.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    var found = document.querySelector('.blogger-clickTrap');
    console.log("Found it!", found);
})();

And that's where I hit a problem: no matter how or when I queried the document, my Tampermonkey script couldn't find the click trap element. In the inspector, I could see it was there, and yet, I couldn't programatically access it.

After much debugging I realized that the preview page is a generic shell and imports a specific post by using an iframe pointed to https://<something>.blogspot.com/b/blog-preview?token=.

my attempts to access the iframe's contents via the main page were being denied, apparently because they weren't from the same origin.

My first thought was: I'm already mucking with these requests, perhaps I can turn off this security policy that's blocking me?

However in my search to figure out how to do this, I realized there's a much simpler solution. I needed to be running my Tampermonkey script not on the preview page, but on *.blogspot.com/b/blog-preview*.

When I updated the @match rule on the script above, my code began to work:

Once I was running the Tampermonkey code on the right URL, having it remove the click trap itself was trivial. Here's the final Tampermonkey script:

// ==UserScript==
// @name         Bye-bye clicktrap!
// @namespace    http://blogbyben.com/
// @version      0.1
// @description  Remove blogger preview's clicktrap
// @author       Ben Simonm
// @match        https://*.blogspot.com/b/blog-preview*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=blogger.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    var found = document.querySelector('.blogger-clickTrap');
    found.style.display = 'none';
})();

Happy clicking!

No comments:

Post a Comment