Validate Private Page Bookmarklet

ValidatePrivatePage <– validates in current window

ValidatePrivatePage <– validates in new window (your pop-up blocker may complain)

If you need to validate the markup of a page that’s not public (e.g. on localhost), you can now use this bookmarklet to auto-submit the current page source to the validator (instead of viewing source, copying, opening the validator, pasting in, and pressing “check”).

Note: this gets the page source making an XMLHTTPRequest to the current URL, so it does not get interpreted by the browser; i.e. this is NOT based on innerHTML(). If the request made returns a different page (e.g. you were logged out in the meantime), that page’s source will be sent to the validator. Not much can be done about that. I once wrote a crusty PHP4 class/bookmarklet combo that helped do this, but thanks to the standardization of XMLHTTPRequest, this is easy in JS now. You should also thank W3C for allowing cross-domain POSTs to the validator :)

Bookmarklet: Horizontally invert HTML5 videos

My demands for “reverse” glasses have gone unserved, but I made a bookmarklet that provides the same effect: “flopping” a video horizontally.

  1. Install the SwitchStance bookmarklet, for which you’ll need a modern browser that supports CSS transforms on video elements.
  2. Opt-in to YouTube’s HTML5 trial
  3. Load up any video without ads (here’s one of Matt Hensley skating)
  4. While the video plays, click the bookmarklet.

The video will mirror and you’ll see Hensley, a regular-footed skater, now skating goofy foot (in “switch stance“). Or you can get Paul McCartney to play guitar right-handed.

We need a frontend design tool for live web pages

It’s quite frequently that an HTML/CSS designer might want to make changes to a live web page. Maybe she doesn’t have write access, or maybe the fixes needed aren’t worth the start-up cost of copying the page locally and working on it there, or multiple designers want to work up ideas on a given page simultaneously. The “Inspect Element” capabilities of most modern browsers will let you make HTML/CSS changes to a live page, but navigating or refreshing causes those changes to be lost, and they’re hard to keep track of.

Here’s a feature wishlist:

  1. keep track of “Inspect Element” user changes with the ability to save them locally
  2. keep changes in discrete “changesets” that can be re-applied, or saved as a unified patch of the original files, or at least as the modified original files
  3. allow swapping page CSS files with user-controlled CSS files (e.g. file:/// or htttp://localhost/)
  4. allow swapped CSS files to be periodically “refreshed” so the user wouldn’t have to switch between CSS editor and browser.

Firefox’s Stylish extension looks to come close to (3), allowing you to add user styles to a page/site, like Greasemonkey does for Javascript. It doesn’t look like the editing experience is great, though.

You can manually do (3) and use the CSS Reload Every bookmarklet, but it reloads all CSS, which is kinda of jarring.

A bookmarklet could implement (3) and (4) and persist its settings in a cookie.

Other ideas?

Update: Here’s a bookmarklet that let’s you swap CSS files and stores its settings in a cookie for the current page. Next step is for it to allow adding files and controlling the cookie path.

You must enable Javascript! (right-click, add to favorites or bookmarks)

(CSSswap source).

Bookmarklet and PHP to prevent Shibboleth-related Firefox Lockouts

Reason this might be useful.

/*
 * Remove all _shibstate cookies if there are too many of them. This usually
 * occurs due to Firefox session restores. Unfortunately we don't know which is
 * the active state cookie, so we have to delete them all, but this is a lessor
 * crime than locking the user out with server errors.
 *
 * In an app a good time to call this is when a user is not logged in or has an
 * expired app session. This way we can cleanup their cookies before forwarding
 * them to the shib login process. Also after logout you'll want to call this
 * with parameter 0 to always remove them.
 *
 * @param int $allowableStateCookies if the number of _shibstate cookies
 * exceeds this, they will all be removed.
 */
function Shibboleth_preventFirefoxLockout($allowableStateCookies = 10)
{
    $stateKeys = array();
    foreach ($_COOKIE as $key => $val) {
        if (0 === strpos($key, '_shibstate')) {
            $stateKeys[] = $key;
        }
    }
    if (count($stateKeys) > $allowableStateCookies) {
        foreach ($stateKeys as $key) {
            setcookie($key, '', time() - 3600, '/');
        }
    }
}

Here’s a bookmarklet that essentially does the same thing: Fix Shibboleth Lockout

Multibyte Input Bookmarklet

All modern web applications should be using UTF-8 encoding. For developers with English keyboards (where all keys produce 7-bit ASCII), testing web forms with multibyte characters can be a pain. You can, of course, enter Unicode characters via obscure key combinations, but using this bookmarklet may be easier:

Get it

You must enable Javascript! (right-click, add to favorites or bookmarks)

This simply visits all text/password/textarea inputs on a page and replaces Latin vowels with multibyte variants. E.g. John A PublicJōhn Ā Pūblīc.

Test it here

The bookmarklet prompts me for “Match beginning”. What is this?

If you only want to affect certain inputs, enter a phrase at the prompt. The bookmarklet will then only affect inputs whose values start with that phrase. E.g. To affect only a “comment” field, place “||” at the beginning of the field, and enter “||” at the match prompt. The bookmarklet will affect only this field and strip the “||” from the field for you.

Uncompressed source

Hacking a 3rd party script for bookmarklet fun

A few weeks ago I created a simple bookmarklet that loads del.icio.us’s PlayTagger script into the current page. This post covers how some problems with this script were worked through.

Too late

The first challenge was that PlayTagger was designed to initialize itself (let’s call this method “init“) on window.onload: If a user fired the bookmarklet after window.onload (99% of the time), playtagger.js would load but init would’ve missed its chance to be called. This means I had to call init manually, but since script elements load asynchronously, I had to wait until init actually existed in the global scope to call it. This was fairly easily accomplished by attaching my code to the new script element’s “load” event (and using some proprietary “readyState” junk for IE).

Too early

If the page takes a long time to load, it’s possible the user will fire the bookmarklet before window.onload. One of two things will occur:

If it’s fired before the DOM is even “ready”, the bookmarklet throws an error when it tries to append the script element. I could use one of the standard “DOMready” routines to run the bookmarklet code a little later, but this case is rare enough to be not worth the effort to support; by the time the user can see there are mp3s on the page, the DOM is usually ready.

Assuming the DOM is ready, playtagger.js gets loaded via a new script element, the bookmarklet fires init, but then, thanks to playtagger’s built-in event attachment, init is called a second time on window.onload, producing a second “play” button per mp3 link. Harmless, but not good enough.

Preventing the 2nd init call

It would be nice if you could sniff whether or not window.onload has fired, but this doesn’t seem to be possible. Maybe via IE junk. Any ideas for a standards based way to tell?

My only hope seemed to be to somehow disable init after manually calling it. The first try was to just redefine init to a null function after calling it:

init();
init = function () {};

I figured out that redefining init would not help here due to the way it’s attached to window.onload:

// simplified
var addLoadEvent = function(f) {
    var old = window.onload;
    window.onload = function() {
        if (old) { old(); }
        f();
    };
};
addLoadEvent(init);

What’s important to notice here is that init is passed to addLoadEvent as f and window.onload is redefined as a new function, capturing f in the closure. So now f holds init‘s original code (because functions are first-class in Javascript), and f, not the global init, is what is really executed at window.onload. As f is private (hidden by the closure), I can’t overwrite it.

Disabling init from the inside by “breaking” Javascript

The second thing I tried was to break init‘s code from the inside. The first thing init does is loop over the NodeList returned by document.getElementsByTagName('a'), so if I could get that function to return an empty array, that would kill init‘s functionality. Because Javascript is brilliantly flexible I can do just that:

// cache for safe keeping
document.gebtn_ = document.getElementsByTagName;
// "break" the native function
document.getElementsByTagName = function(tag) {
    if (tag != 'a') return document.gebtn_(a);

    // called with 'a' (probably from init)
    // "repair" this function for future use
    document.getElementsByTagName = document.gebtn_;
    // return init-busting empty array
    return [];
};

Simplest solution

While the code above works pretty well, I thought of a simpler, more elegant solution: just rewrite window.onload to what it was before playtagger.js was loaded.

And with that here is the final unpacked bookmarklet code:

javascript:(function () {
    if (window.Delicious && (Delicious.Mp3 || window.Mp3))
        return;
    var d = document
        ,s = d.createElement('script')
        ,wo = window.onload
        ,go = function () {
            Delicious.Mp3.go();
            window.onload = wo || null;
        }
    ;
    s.src = 'http://images.del.icio.us/static/js/playtagger.js';
    if (null === s.onreadystatechange) 
        s.onreadystatechange = function () {
            if (s.readyState == 'complete')
                go();
        };
    else 
        s.onload = go;
    d.body.appendChild(s);
})();

Reload CSS Every… Bookmarklet

One annoying aspect of writing a stylesheet is having to reload the page in your browser to see your incremental changes. There are ways to workaround this, but I find them less than ideal so I created ReloadCSSEvery. It refreshes only the CSS of a loaded page every 2 seconds so you can use your CSS editor of choice and see semi-real-time changes in your browser when you save.
Continue reading  

PHP for Easy Bookmarklet Testing and Distribution

Bookmarklet authors have it tough. On top of the usual challenges of cross-browser Javascript testing, we’ve traditionally also had to workaround IE’s character limit and jump through hoops to embed code inside of javascript: links.

Bookmarklet Server (source) eases testing and deployment by allowing you to keep code where it should be—in .js files. A single SCRIPT element dynamically loads the bookmarklet code and creates the javascript: link for you.

Continue reading  

PlayTagger bookmarklet

PlayTagger loads del.icio.us’s Play Tagger in the page, which allows you to listen to (and bookmark) mp3 links.

Get it

PlayTagger

Shamelessly self-promoting test links

Brittle Stars – So Unfair
The French Horns – Brighter Now

Previously powered by…

This page used to have a bookmarklet that did a similar function using the open source XSPF Flash Music Player, but SourceForge now prevents direct linking to the SWF files. Rewriting the bookmarklet to use PlayTagger is easier than explaining that you have to host your own SWF and adjust the bookmarklet accordingly.