DEV Community

Can you explain to me what's going on in this code?

Ben Halpern on April 26, 2018

In trying to understand a Google snippet I had the thought that it might be an interesting type of discussion—explaining a code snippet. This code...
Collapse
 
nektro profile image
Meghan (she/her) • Edited

TLDR: What this snippet does is assign a class, namely 'async-hide' to the <html> element of our document, waits 4 seconds, and then removes it.

We have a self running function with a bunch of parameters but let's "prettify" it first.

(function (a, s, y, n, c, h, i, d, e) {
    s.className += ' ' + y;
    h.start = 1 * new Date();
    h.end = i = function () {
        s.className = s.className.replace(RegExp(' ?' + y), '')
    };
    (a[n] = a[n] || []).hide = h;
    setTimeout(function () {
        i();
        h.end = null
    }, c);
    h.timeout = c;
})(window, document.documentElement, 'async-hide', 'dataLayer', 4000, { 'GTM-PNDQRRW': true });

Hmmm. That didn't help much. Okay. Let's replace all the parameters with their actual variables.

(function (h, i, d, e) {
    document.documentElement.className += ' ' + 'async-hide';
    h.start = 1 * new Date();
    h.end = i = function () {
        document.documentElement.className = document.documentElement.className.replace(RegExp(' ?' + 'async-hide'), '')
    };
    (window['dataLayer'] = window['dataLayer'] || []).hide = h;
    setTimeout(function () {
        i();
        h.end = null
    }, 4000);
    h.timeout = 4000;
})({ 'GTM-PNDQRRW': true });

Much better. Now we have left the options object being passed as h, i only being used as variable declaration, and d and e are unused other than making the original parameter list async hide.

  • document.documentElement represents the <html> element
  • .className += ' ' normalizes our variable to a String and is setting the class attribute on `
  • + 'async-hide'; sets the class to async-hide which will be used later.
  • h.start = 1 * new Date(); sets on our options Object a time 1 second from now
  • h.end = i = function () sets the end property and assigns our i parameter a value
  • document.documentElement.className = document.documentElement.className.replace(RegExp(' ?' + 'async-hide'), '') really convoluted way to remove only the async-hide class from <html>
  • (window['dataLayer'] = window['dataLayer'] || []) grabs the dataLayer list from Google Tag Manager or returns an empty Array
  • .hide = h; sets the hide property to out options object
  • i(); calls our function to remove the class
  • h.end = null removes the reference to our function from the options object
  • h.timeout = 4000; the snippet waits 4 seconds before doing anything

So.

What this snippet does is assign a class, namely 'async-hide' to the <html> element of our document, waits 4 seconds, and then removes it.

Addendum, and I almost forgot! The CSS makes the entire document invisible. Presumably to wait for the page to load and hoping everything is done by then so as to not get a FOUC or similar.

Collapse
 
mellen profile image
Matt Ellen

1*new Date() turns the date object into an integer.

Collapse
 
rpalo profile image
Ryan Palo

I tried to un-minimize it. Not all the way there, but at least now it's easier to see what the code is doing. 😁

const docElem = document.documentElement;
docElem.className += ' ' + 'async-hide';

const removeHideClass = function() {
  docElem.className = docElem.className.replace(/ ?async-hide/, '');
}

const hide = {
  'GTM-PNDQRRW': true,
  start: 1*new Date,  // new date (in seconds)
  end: removeHide
};

// window.dataLayer seems to be where Google Tag manager stores data to track

// Load or initialize it to an empty array
window['dataLayer']=window['dataLayer'] || [];
window['dataLayer'].hide = hide;

setTimeout(function() {
  removeHideClass();
  hide.end = null;
}, 4000);

hide.timeout = 4000;
Collapse
 
aspittel profile image
Ali Spittel

Totally cheated, but this explainer for it is pretty good. It hides the page content until the Optimize container is loaded in. Hilarious that they added those extra parameters in to write out asynchide though!

Collapse
 
nickytonline profile image
Nick Taylor • Edited

Here's my stab at it without running the code.

So the style is to set an element to opacity: 0 no matter what because of the !important. It does this on the root element of the document document.documentElement by appending the CSS class async-hide via s.className+=' '+y, where s is `document.documentElement.

Then it adds a property start who's value is 1*newDate to the object being passed in {'GTM-PNDQRRW':true} which is represented by the parameter h in the anonymous immediately invoked function. It also sets an end property on the same object whose value is a function function(){s.className=s.className.replace(RegExp(' ?'+y),'')};

After that it sets a global var on the window, parameter a, via a[n], where n is 'dataLayer'. It sets itself to itself if it exists, otherwise it's initialized to an empty array, (a[n]=a[n]||[]). On window.dataLayer (from a[n]), it sets a hide property which is equal to the object h, the enhanced {'GTM-PNDQRRW':true}, object.

From there a setTimeout is invoked which fires after 4000 milliseconds (taken from the parameter c. Inside the timeout, it runs the function i which is the same reference as the function h.end. Once i() has run, it's set to null via h.end = null. While the timeout is set to run in 4 seconds, the enhanced object represented by h gets a timeout property whose value is c (4000ms).

I'm assuming because of GTM in the object key that this is some Google Tag Manager voodoo?

So all in all what does this do? It looks like it hides document.documentElement and then removes the CSS class that had it's opacity set to 0 for 4 seconds and this action seems to be related to this 'GTM-PNDQRRW'.

Collapse
 
andrewlucker profile image
Andrew Lucker

a,s,y,n,c,h,i,d,e

The function doesn't use d or e variables. Somebody is just being cute.

Collapse
 
dougblackjr profile image
Doug Black

Looks like it assigns a class name to an element for 4 seconds!