<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pascal Louwes</title>
    <description>The latest articles on DEV Community by Pascal Louwes (@ipasqualito).</description>
    <link>https://dev.to/ipasqualito</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F642678%2Fd9c1fece-974c-404f-8564-539b1162aac0.jpeg</url>
      <title>DEV Community: Pascal Louwes</title>
      <link>https://dev.to/ipasqualito</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ipasqualito"/>
    <language>en</language>
    <item>
      <title>Adding DOM Elements LIKE A BOSS</title>
      <dc:creator>Pascal Louwes</dc:creator>
      <pubDate>Thu, 03 Jun 2021 12:00:11 +0000</pubDate>
      <link>https://dev.to/ipasqualito/adding-dom-elements-like-a-boss-5cb7</link>
      <guid>https://dev.to/ipasqualito/adding-dom-elements-like-a-boss-5cb7</guid>
      <description>&lt;p&gt;In my AB testing Framework I have a method that creates DOM nodes, sets their properties and attributes, and adds them to the DOM for me. Since in 90% of all the tests we run, we need one or more custom elements, I decided to create a function that does all that for me. The requirements were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create (one or more) DOM Element(s) by config&lt;/li&gt;
&lt;li&gt;add attributes to element (class, style, innerText/ -HTML, and even events like onclick)&lt;/li&gt;
&lt;li&gt;insert element in DOM relative to a target, or replace that target&lt;/li&gt;
&lt;li&gt;return a reference to the element for later use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OK, let’s write a function that can do all of that – it’s possible to do it in only a few lines of code!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const buildNodesFromConfigArray = nodes =&amp;gt; nodes.map(({tag, attributes, position, target}) =&amp;gt; {
    // create the element
    const node = document.createElement(tag);
    // iterate through property list,
    // match innerText, innerHTML or event attributes (event attributes should be wrapped functions!),
    // else just set the attribute
    Object.entries(attributes).map(([key, value]) =&amp;gt; (/^(inner|on)\w+$/i.test(key)) ? node[key] = attributes[key] : node.setAttribute(key, value));
    // [optional] place it in the DOM
    if (position &amp;amp;&amp;amp; target) (position === "replace") ? target.replaceWith(node) : target.insertAdjacentElement(position, node);
    // return it for use in the caller function
    return node;
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, first we create a DOM element. Then comes a pretty magical line of code if I may say so, we map over the attributes object so we can check these as key-value pair, one by one. If the regex matches on the key, we have to set either innerText or innerHTML, or an event like ‘onclick’ or ‘onmousesomething’ or whatever event you fancy. If it does not, we set an attribute with name ‘key’ and value ‘value’. Finally, if a position and target are set in our config, we add the element to the DOM relative to a target, or replace that target. Now, let’s see this awesome code in action!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// let's create a new stylesheet
const [style] = buildNodesFromConfigArray([{
    tag: 'style',
    attributes: {
        id: "ra-stylesheet",
        rel: "stylesheet",
        type: "text/css"
    },
    position: "beforeend",
    target: document.head
}]);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We declare an array and use the destructure technique to have the variable(s) immediately available to us. That way we can use it later on in our code. Like so, for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
style.append(document.createTextNode(`
    body {
        background-color: #00ff88;
    }
`))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you can see the stylesheet added to the DOM. All the properties are set like we specified.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.recoveryarea.nl%2Fuploads%2F2021%2F06%2FScreenshot-2021-06-03-at-13.39.08-1024x578.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.recoveryarea.nl%2Fuploads%2F2021%2F06%2FScreenshot-2021-06-03-at-13.39.08-1024x578.png"&gt;&lt;/a&gt;inspect element shows the sheet where we expect it.&lt;/p&gt;

&lt;p&gt;What if we want to add some meta tags to the head of our site? That would look like this. (You could actually skip the variable declaration if all you want is to add these to the head).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const [meta1, meta2] = buildNodesFromConfigArray([{
    tagName: "meta",
    attributes: {
        class: "ra-133-meta",
        property: "og:type",
        content: "website"
    },
    position: "beforeend",
    target: document.head
}, {
    tagName: "meta",
    attributes: {
        class: "ra-133-meta",
        property: "og:site_name",
        content: document.location.origin
    },
    position: "beforeend",
    target: document.head
}])

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s a final example, where we won’t be needing the elements later in our code, we just want them added in the DOM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
buildNodesFromConfigArray([{
    tagName: "div", //
    attributes: {
        class: "first",
        innerText: "My Paragraph",
        onclick: (event) =&amp;gt; {
            // make sure the value here is an actual function!
            alert(event)
        }
    },
    position: "beforebegin", // use insertAdjacentElement position parameter, or replace
    target: document.querySelector("#someElement")
}, {
    tagName: "div",
    attributes: {
        class: "second",
    },
    position: "replace",
    target: document.querySelector("#someOtherElement")
}]);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, now you know how to create one or more DOM elements LIKE A BOSS. &lt;a href="https://www.recoveryarea.nl/contact/" rel="noopener noreferrer"&gt;Contact me&lt;/a&gt; if you want to know more!&lt;/p&gt;

&lt;p&gt;Next time, I’ll share a trick I posted on Twitter a while ago, how I exclude IE from my tests, the recoveryArea way!&lt;/p&gt;

&lt;p&gt;Happy coding &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs.w.org%2Fimages%2Fcore%2Femoji%2F13.0.1%2F72x72%2F1f642.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs.w.org%2Fimages%2Fcore%2Femoji%2F13.0.1%2F72x72%2F1f642.png" alt="🙂"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.recoveryarea.nl/javascript/adding-dom-elements-like-a-boss/" rel="noopener noreferrer"&gt;Adding DOM Elements LIKE A BOSS&lt;/a&gt; appeared first on &lt;a href="https://www.recoveryarea.nl" rel="noopener noreferrer"&gt;recoveryArea&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>abtesting</category>
      <category>javascript</category>
    </item>
    <item>
      <title>My Secret to Super Fast AB Test Loading</title>
      <dc:creator>Pascal Louwes</dc:creator>
      <pubDate>Wed, 02 Jun 2021 10:09:00 +0000</pubDate>
      <link>https://dev.to/ipasqualito/my-secret-to-super-fast-ab-test-loading-4060</link>
      <guid>https://dev.to/ipasqualito/my-secret-to-super-fast-ab-test-loading-4060</guid>
      <description>&lt;p&gt;When I am testing elements that take some time to load, the last thing I want is a flash of un-styled content, or see the unchanged element jump into its changed state. Since a few years, browsers have a great API built in that I use to achieve super fast loading of my test code: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"&gt;Mutation&lt;/a&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"&gt;Observer&lt;/a&gt;. (link opens new tab)&lt;/p&gt;

&lt;p&gt;In this post I’ll explain how I use this API to my advantage.&lt;/p&gt;

&lt;p&gt;Make sure your script is loaded as soon as possible. It’s OK if you load it asynchronously, but you want it to be available as the first piece of JS the page is loading.&lt;/p&gt;

&lt;p&gt;Here’s the function I use to observe when an element gets added to the DOM. I basically wrap a querySelector in a MutationObserver. The latter will fire upon every DOM mutation. The querySelector will then test for the existence of my element. If that returns true, I disconnect the observer if I don’t need it anymore. Finally, I run the callback function that was passed as the second parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const observeDOM = (config, callback) =&amp;gt; {
    // use a regular function so `this` refers to the Mutation Observer
    new MutationObserver(function() {
        const element = document.querySelector(config.selector);
        if (element) {
            // disconnect if you don't need it again
            if(config.disconnect) this.disconnect();
            // test and run the callback function
            if(typeof callback === "function") callback(element);
        }
    }).observe(config.parent || document, {
        subtree: config.recursive,
        childList: true
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use a ‘normal’ function keyword on the Mutation Observer function because if I don’t, I won’t be able to disconnect it if that is what I want. This will then refer to the Window object and not the MutationObserver instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const config = {
    selector: 'li.timeline-item', // what element are we looking for?
    parent: document.querySelector("ul.timeline"), // narrow down search scope if possible...
    recursive: true, // look at descendant elements too
    disconnect: false // disconnect when one hit is enough
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the config file above you can see that I am observing an unordered list for additions of list items. Since disconnect is set to false, the observer will fire on every mutation and do the element test again. Note: You can prevent triggering on the same element over and over again by adding a class (.found) to the element as soon as it’s found, and change your selector accordingly: a li.timeline-item:not(.found) selector does that trick just fine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// run this function when the element is found
const callback = console.log;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a simple example of a callback function you can run when you have a hit. In your case you probably want to kick off your AB test code. See what I did there?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// kickoff mutation observer
observeDOM(config, callback);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last but not least, you want to start observing by calling your function with config and callback parameters.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.recoveryarea.nl/javascript/my-secret-to-super-fast-ab-test-loading/"&gt;My Secret to Super Fast AB Test Loading&lt;/a&gt; appeared first on &lt;a href="https://www.recoveryarea.nl"&gt;recoveryArea&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>abtesting</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Notify Enter Viewport the proper way: Intersection Observer.</title>
      <dc:creator>Pascal Louwes</dc:creator>
      <pubDate>Tue, 04 Feb 2020 12:52:35 +0000</pubDate>
      <link>https://dev.to/ipasqualito/notify-enter-viewport-the-proper-way-intersection-observer-32p7</link>
      <guid>https://dev.to/ipasqualito/notify-enter-viewport-the-proper-way-intersection-observer-32p7</guid>
      <description>&lt;p&gt;In previous articles I have written about how to track elements when they enter or leave the browsers viewport. The reason why you might want to track this is when you are doing a test on an element that is outside the viewport on page initialisation, you don’t want to count this as a visitor immediately but only when the element is scrolled into view.&lt;/p&gt;

&lt;p&gt;If the (changed) element is seen by the visitor, you fire an event, not before. In the past I accomplished this by using something called notify enter viewport. This worked just fine but it came with a lot of caveats.&lt;/p&gt;

&lt;p&gt;For instance, notify enter viewport only accepts elements that are already loaded in the DOM. Second, a lot of calculations have to be done inside the function before we know an elements position. It’s complicated.&lt;/p&gt;

&lt;p&gt;Modern browsers come with an API that can help us accomplish basically the same in a much simpler way, the Intersection Observer.&lt;/p&gt;

&lt;p&gt;Here’s a code example of how I use it in my own AB testing framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const observeIntersections = function (config) {
    // loop through all entries in config array
    config.forEach(function (options) {

        document.querySelectorAll(options.element).forEach(function (element) {

            const observer = new IntersectionObserver(function (entries) {
                entries.forEach(function (entry) {

                    if (entry.isIntersecting) {

                        sendDimension({
                            event: 'trackEventNI',
                            eventCategory: abtest.testid + ": " + abtest.testName,
                            eventAction: 'Viewport hit for element [' + element + ']',
                            eventLabel: abtest.variation,
                            eventNonInteraction: true
                        });

                    }
                });
            }, {
                root: null, // use document viewport as container
                rootMargin: "0px",
                threshold: 1 // fire callback as each of these thresholds is reached
            });

            observer.observe(element);

        });

    })
};

observeIntersections([{
        element: 'h4', // the element or elements we want to observe
        tag: 'H4 Element',
        threshold: 1,
        root: null,
        rootMargin: "0px"
    }, {
        element: 'h2#Intersection_observer_concepts_and_usage',
        tag: 'H2 title element',
        threshold: 1,
        root: null,
        rootMargin: "0px"
    }, {
        element: 'iframe.live-sample-frame.sample-code-frame',
        tag: 'IFRAME ELEMENT',
        threshold: [0, 0.5, 1],
        root: null,
        rootMargin: "0px"
    }
]);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://www.recoveryarea.nl/ab-testing/notify-enter-viewport-the-proper-way-intersection-observer/"&gt;Notify Enter Viewport the proper way: Intersection Observer.&lt;/a&gt; appeared first on &lt;a href="https://www.recoveryarea.nl"&gt;recoveryArea&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>abtesting</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Notify Enter Viewport</title>
      <dc:creator>Pascal Louwes</dc:creator>
      <pubDate>Thu, 21 Jun 2018 12:16:31 +0000</pubDate>
      <link>https://dev.to/ipasqualito/notify-enter-viewport-2jie</link>
      <guid>https://dev.to/ipasqualito/notify-enter-viewport-2jie</guid>
      <description>&lt;p&gt;Sometimes we are testing a page element or component that, when the page has loaded, lies outside of the viewport. This has the simple consequence that you should not count this page load as a visitor to your test. Only when the element you are testing scrolls into view, the visitor can be added to your test. To accomplish this, we needed some code that keeps track of the elements position on the page with regard to the page’s dimensions.&lt;/p&gt;

&lt;p&gt;This one still relies on jQuery, I’ll upload a JS only version soon.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var notifyEnterViewport = function(o) {
        var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame,
            l = $(window).height(),
            r = $(window),
            t = r.scrollTop(),
            enter = function(e) {
                e.addClass("MM_inside_viewport"), e.hasClass("MM_outside_viewport") &amp;amp;&amp;amp; e.removeClass("MM_outside_viewport")

            },
            exit = function(e) {
                e.addClass("MM_outside_viewport"), e.hasClass("MM_inside_viewport") &amp;amp;&amp;amp; e.removeClass("MM_inside_viewport")
            },
            loop = function() {
                var e = r.scrollTop();
                t !== e &amp;amp;&amp;amp; (t = e, o.length &amp;amp;&amp;amp; $.each(o, function(e) {
                    var o = $(this),
                        raf = o.height(),
                        t = o.offset().top,
                        loop = t - r.scrollTop(),
                        n = t - r.scrollTop() + raf;
                    0 &amp;lt;= loop &amp;amp;&amp;amp; n &amp;lt;= l &amp;amp;&amp;amp; !o.hasClass("MM_inside_viewport") &amp;amp;&amp;amp; (console.log("test: element " + (e + 1) + " scrolled into view"), enter(o)), (n &amp;lt; 0 || l &amp;lt; loop) &amp;amp;&amp;amp; !o.hasClass("MM_outside_viewport") &amp;amp;&amp;amp; (console.log("test: element " + (e + 1) + " scrolled out of view"), exit(o))
                })), raf(loop)
            };
        raf &amp;amp;&amp;amp; loop();
    }
    elementsToCheck = $("div#checkThisElement");
notifyEnterViewport(elementsToCheck);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;UPDATE!
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var notifyEnterViewport = function(el) {
    var w = window,
        raf = w.requestAnimationFrame,
        vpHeight = w.innerHeight,
        lastPgYO = w.pageYOffset,
        scroll = function() {
            var height = el.offsetHeight,
                elOffset = offSet(el),
                top = elOffset.top,
                pTop = top - w.pageYOffset,
                pBottom = pTop + height;
            if (pTop &amp;gt;= 0 &amp;amp;&amp;amp; pBottom &amp;lt;= vpHeight &amp;amp;&amp;amp; !el.classList.contains('mm_enter')) {
                enter(el);
            }
            if ((pBottom &amp;lt; 0 || pTop &amp;gt; vpHeight) &amp;amp;&amp;amp; !el.classList.contains('mm_exit')) {
                exit(el);
            }
        },
        offSet = function(el) {
            var rect = el.getBoundingClientRect(),
                pgxo = w.pageXOffset,
                pgyo = w.pageYOffset;
            return {
                top: rect.top + pgyo,
                left: rect.left + pgxo
            };
        },
        enter = function(el) {
            //console.log("enter: ", el);
            el.classList.add('mm_enter');
            el.classList.remove('mm_exit');
        },
        exit = function(el) {
            //console.log("exit: ", el);
            el.classList.add('mm_exit');
            el.classList.remove('mm_enter');
        },
        loop = function() {
            var PgYO = w.pageYOffset;
            if (lastPgYO === PgYO) {
                raf(loop);
                return;
            } else {
                lastPgYO = PgYO;
                scroll();
                raf(loop);
            }
        };
    if (raf) loop();
};

// call:
notifyEnterViewport(document.querySelector('ul#sub_nav &amp;gt; li.active:not(.first)'));

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://www.recoveryarea.nl/ab-testing/notify-enter-viewport/"&gt;Notify Enter Viewport&lt;/a&gt; appeared first on &lt;a href="https://www.recoveryarea.nl"&gt;recoveryArea&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>abtesting</category>
      <category>javascript</category>
    </item>
    <item>
      <title>AB Test jQuery Performance Cheat Sheet</title>
      <dc:creator>Pascal Louwes</dc:creator>
      <pubDate>Fri, 14 Oct 2016 16:02:50 +0000</pubDate>
      <link>https://dev.to/ipasqualito/ab-test-jquery-performance-cheat-sheet-41i0</link>
      <guid>https://dev.to/ipasqualito/ab-test-jquery-performance-cheat-sheet-41i0</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fstatic.recoveryarea.nl%2Fuploads%2F2016%2F10%2FCheating-In-Exams-16.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fstatic.recoveryarea.nl%2Fuploads%2F2016%2F10%2FCheating-In-Exams-16.jpg" alt="cheating"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you write AB tests with jQuery you have to make sure you write your code as optimised as possible. Every millisecond you shave off results in less chance of unwanted repaint or reflow flickers.&lt;/p&gt;

&lt;p&gt;Update: Tip number 1: Do NOT use jQuery! Why wait for a library to load, when vanilla JS nowadays does everything jQuery does – but faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Faster Selectors.
&lt;/h3&gt;

&lt;p&gt;Know which selectors perform the fastest to optimise your code!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// ID selector - very fast (document.getElementById)
$("#id");
// TAG selector - fast (document.getElementsByTagName)
$("p");, $("input");, $("form");
// CLASS selector - performs well in modern browsers (document.getElementsByClassName)
$(".class");
// ATTRIBUTE SELECTOR - slow - needs document.querySelectorAll to perform OK-ish
$("[attribute=value]");
// PSEUDO selector - slowest - needs document.querySelectorAll to perform OK-ish
$(":hidden");

// also, instead of this:
$("#id p");
// do this:
$("#id").find("p"); // --&amp;gt; limit the scope that has to be searched: more than twice as fast!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Caching.
&lt;/h3&gt;

&lt;p&gt;Basically every time you use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$('someselector')

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you iterate through the dom. If you need an element more than twice, you should store the element reference!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// instead of this:
$('a.contactus').css('padding', '10px');
$('a.contactus').css('margin', '4px');
$('a.contactus').css('display', 'block');
// do this:
var myvar = $('a.contactus');
myvar.css({
padding: '10px',
margin: '4px',
display: 'block'
}); // element stored, CSS passed as object

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Chaining.
&lt;/h3&gt;

&lt;p&gt;Chained methods will be slightly faster than multiple methods made on a cached selector, and both ways will be much faster than multiple methods made on non-cached selectors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// instead of this
$("#object").addClass("active");
$("#object").css("color","#f0f");
$("#object").height(300);
// do this
var myvar = $('a.contactus');
myvar.addClass("active").css("color", "#f0f").height(300);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Event Delegation.
&lt;/h3&gt;

&lt;p&gt;Event listeners cost memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// instead of this: (an event listener for EVERY table cell)
$('table').find('td').on('click',function() {
$(this).toggleClass('active');
});
// do this: (an event listener for only the table that gets fired by its 'td' children)
$('table').on('click','td',function() {
$(this).toggleClass('active');
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Smarter DOM Manipulation.
&lt;/h3&gt;

&lt;p&gt;Every time the DOM is manipulated, the browser has to repaint and reflow content which can be extremely costly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// instead of this:
const arr = [reallyLongArrayOfImageURLs];
$.each(arr, function(count, item) {
let newImg = '&amp;lt;li&amp;gt;&amp;lt;img src="'+item+'"&amp;gt;&amp;lt;/li&amp;gt;';;
$('#imgList').append(newImg); // aargh a selector in a loop! and we're adding an element here, too!
});



// do this
var arr = [reallyLongArrayOfImageURLs],
tmp = '';
$.each(arr, function(count, item) {
tmp += '&amp;lt;li&amp;gt;&amp;lt;img src="'+item+'"&amp;gt;&amp;lt;/li&amp;gt;'; // no selector and the HTML to add is stored in a variable...
});
$('#imgList').append(tmp); // ..that will be added once when the loop has finished

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://www.recoveryarea.nl/ab-testing/ab-test-jquery-performance-cheat-sheet/" rel="noopener noreferrer"&gt;AB Test jQuery Performance Cheat Sheet&lt;/a&gt; appeared first on &lt;a href="https://www.recoveryarea.nl" rel="noopener noreferrer"&gt;recoveryArea&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>abtesting</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Track That!</title>
      <dc:creator>Pascal Louwes</dc:creator>
      <pubDate>Sun, 07 Feb 2016 18:11:44 +0000</pubDate>
      <link>https://dev.to/ipasqualito/track-that-5f0</link>
      <guid>https://dev.to/ipasqualito/track-that-5f0</guid>
      <description>&lt;p&gt;This function tracks every event with all its attributes in the div that’s set in the caller function. Handy if you need custom tracking for your AB test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var trackThat = function() {

    var t = {},
        r = {},
        a = window.event ? window.event.srcElement : i.target,
        c = document.getElementsByTagName(a.tagName),
        k = "";
    try {
        for (var d = 0; d &amp;lt; c.length; ++d) c[d] == a &amp;amp;&amp;amp; (r.tag = a.tagName, r.index = d, r.text = a.hasChildNodes() ? a.childNodes[0].data : "null"); for (var l, d = 0, o = a.attributes, g = o.length; g &amp;gt; d; d++) l = o[d], t[l.nodeName] = l.nodeValue;
        r.attrs = t, k = JSON.stringify(r);
    } catch (i) {
        k = "error: " + i.message;
    } finally {
        return k;
    }
};

$( 'div.main-holder' ).on('click', function(e){
    console.log(trackThat(e));
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://www.recoveryarea.nl/javascript/track-that/"&gt;Track That!&lt;/a&gt; appeared first on &lt;a href="https://www.recoveryarea.nl"&gt;recoveryArea&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>A smarter console.info</title>
      <dc:creator>Pascal Louwes</dc:creator>
      <pubDate>Wed, 09 Feb 2011 09:05:17 +0000</pubDate>
      <link>https://dev.to/ipasqualito/a-smarter-console-info-m63</link>
      <guid>https://dev.to/ipasqualito/a-smarter-console-info-m63</guid>
      <description>&lt;p&gt;Here is a little piece of code you can use in your project for slightly smarter console messages. Objects and arrays are handled differently when logged to the console than strings. Firebug gives you a stringified version of the object while console.dir gives you an expandable object. Both give you the expandable object in Chrome. To work around this you can use this little snippet, it will always give you the correct version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var debug = function(message) {
    "object" === typeof console &amp;amp;&amp;amp; ("object" === typeof message || "array" === typeof message ? console.dir(message) : console.info(message));
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post &lt;a href="https://www.recoveryarea.nl/javascript/a-smarter-console-info/"&gt;A smarter console.info&lt;/a&gt; appeared first on &lt;a href="https://www.recoveryarea.nl"&gt;recoveryArea&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
  </channel>
</rss>
