Article summary
We use a popular brand of network camera as a baby monitor at home. The camera’s been great, but I have one minor quibble with its web interface. It doesn’t work very well in small window sizes.
If I place the window in the corner of my screen while I do something else, for example, the video frame becomes obnoxiously small:
The camera’s image occupies just a small fraction the page area! If only there were a way I could change this.
Helper Monkeys
Enter the userscript. First popularized with the Greasemonkey add-on for Firefox, userscripts alter websites on the fly as you visit them. Today I’m running them with Tampermonkey for Chrome. Public repositories offer customization scripts for all sorts of websites, but it’s also pretty easy to write your own.
To get started, install Tampermonkey. Tap its toolbar icon, and select Add a new script
. An editor opens with a default script. There’s a bunch of metadata at the top; fill out the @match
field to control where the script will run. (The pattern is specified according to Chrome’s Match Patterns.
Here’s a minimum working example:
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://atomicobject.com/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
console.log("hello, world!");
})();
The Script
Now that we can easily execute our own code on this page, what should we do?
Initially, I’m interested in removing the big white box at the bottom of the window. I’d like my script to detect whenever the element appears and remove it. I’d like this to work even as I click around different screens within the app, so it’s not enough to do it just once.
I started with a polling approach, but I later settled on a MutationObserver, which reacts faster and is much more efficient:
var observer = new MutationObserver(function(mutations) {
if($('.player-footer').length > 0){
console.log("removing footer..");
$('.player-footer').detach();
}
});
observer.observe(document.querySelector('#home-container'), {
subtree: true,
childList: true,
attributes: false,
characterData: false,
attributeOldValue: false,
characterDataOldValue: false
});
It works! The big white box is gone, and the page has become much more usable in a small window.
But wait, there’s more! While I was rummaging around under the hood, I noticed that the video is a flash object, of the form:
<object name="flash-player" type="application/x-shockwave-flash" data="/flash/video.swf">
<param name="flashvars" value="uuid=123&sessionToken=456&cameraScale=1&cameraCenterX=0.5&...">
</object>
Hmm. That flashvars
value looks a lot like a query string. I wonder if I could visit the .swf
file directly, supplying the flashvars
via the URL? Yep–it worked! Now I have access to the video frame without a website wrapped around it.
This enables a fun new challenge: creating a “pop-out” link. I added some code in the mutation observer callback to extract the URL and flashvars, and then inserted a link positioned at the top of the page next to the settings gear:
var fp = $('.cards object');
if (fp.length === 1 && $('.my-swf-link').length === 0) {
console.log('adding button..');
var link_to_swf = fp.attr('data') + '?' + fp.children("[name='flashvars']").attr('value');
var myButton = $('⬈');
myButton.css({
"position": "absolute",
"right": "5rem",
"color": "white",
"top": "1.5rem",
"font-size": "1.9rem",
"outline": "0"
});
myButton.insertAfter("h1.card-title");
}
New and Improved
Here’s how it looks with my enhancements:
Use the same camera? Here’s the current version of my script.
Conclusion
One of my favorite things about the web is how open and accessible software can be. See a cool effect, and wonder how they did it? The implementation is right there for your inspection!
Another side to this openness is that it enables users to exert more control over software running on their own computer, even if the software wasn’t created with this freedom in mind. It’d be very difficult to make changes like these as a user of phone or desktop software!
Like Tron, userscripts fight for the users. Do you use any regularly? What for? If not, I’d encourage you install Tampermonkey or Greasemonkey to try writing a few to tackle frustrations with websites you use regularly.