Monday 17 October 2016

Polyfill for CSS backdrop-filter (on whole page)

On my latest project, which was based on Bootstrap, the client (/ designer) wanted to substitute the default gray background of the modal window with a nice gaussian blur.
Default Bootstrap modal
Bootstrap modal with gaussian blur over background
Fortunately, literally a couple of weeks beforehand I'd skimmed a reddit post on a very similar thing (except the modal is blurred instead of the background).  CSS for browsers that support it, some sort of SVG fallback for those which don't.  Easy, I thought naively.  On closer inspection you'll notice that all the other methods actually blur one particular image which is used as the background.  This won't work in our case, we need to blur the entire rest of the page.

Ok first off, let's get to the code for browsers which support the backdrop-filter tag (as of this post, that's only iOS Safari, and Chrome if you have the "experimental web platform features" flag checked).  We can use the CSS @supports at-rule to make sure this is only handled by browsers which support it (and an inverse rule for the remainder).  This is pretty well supported, but you can always polyfill it as well.

@supports (backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px)) {
    .modal-backdrop.in {
        opacity: 1;
        background-color: transparent;
        -webkit-backdrop-filter: blur(4px);
        backdrop-filter: blur(4px);
    }
}

(the screenshot above is using this code in Chrome - with the flag enabled)

In all the digging through other posts on workarounds using SVG, and testing out various solutions I had a sudden moment of clarity (or madness).  What if I somehow got an image of the entire page and set that as the (blurred) background-image? Well, a SO search result shows that it's very much possible, and html2canvas is the framework to use.

Shut up and give me the code!

Ok ok...

The CSS:

@supports not ((backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px))) {
    .modal-backdrop {
        background-color: initial;
        -webkit-transition: all .25s ease-in-out;
        -moz-transition: all .25s ease-in-out;
        transition: all .25s ease-in-out;
        opacity: 0;
    }
}

And the Javascript:

if (!CSS.supports('backdrop-filter', 'blur(4px)') && !CSS.supports('-webkit-backdrop-filter', 'blur(4px)')) {
    $('[data-target="#myModal"]').click(function () {
        html2canvas(document.body).then(function (canvas) {
            $('.modal-backdrop').css({
                "background-image": 'url(' + canvas.toDataURL("image/png") + ')',
                "filter": "blur(4px)",
                "opacity": "1"
            });
        });
    });
}
Where [data-target="#myModal"] is the link/button/whatever that opens your modal.

Boom! We have a nice .25 second transition to a blurred screenshot of the page as our modal background.  By testing for support, theoretically we should have nice degradation back to the default Bootstrap modal (for things like IE10).

Note: I have not tested this in all browsers, or even many browsers, just the latest of Chrome, Firefox, Edge, and IE.  If you have a lot of components on your page then html2canvas can take a while to render the image.  Use (or don't) after testing per the requirements of your solution.

Monday 10 October 2016

"Invalid/missing hash was encountered" for documents

Reviewing our logs recently we discovered that we were getting an unusually large number of messages to the tune of
ERROR MediaRequestProtection: An invalid/missing hash value was encountered.

As we all know, Sitecore 7.5 added the concept of a hash which is required when resizing media items, so naturally we assumed that some images were being included incorrectly on a page somewhere, or the secret was incorrectly configured.  However, on closer inspection we realised that it wasn't actually images at all, but documents (which certainly aren't being resized, and surely don't need a hash).

Documents (mostly PDFs) were being uploaded to the media library, and then in a rich text field somewhere on the site, an author was linking to the document using insert link -> media item.

Upon reaching out to Sitecore, they were quick to reply that this was actually a bug in the current version of Sitecore (8.1 update 2 - 160302).  So if you're having a similar issue and want to clean out your logs a bit, you can contact support for the patch, and/or use the reference number 438674.