<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>John Dugan</title>
	<atom:link href="https://john-dugan.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://john-dugan.com</link>
	<description>Software Engineer</description>
	<lastBuildDate>Thu, 24 May 2018 04:50:20 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.8.6</generator>
	<item>
		<title>Asynchronous JavaScript: The Event Loop</title>
		<link>https://john-dugan.com/javascript-event-loop/</link>
					<comments>https://john-dugan.com/javascript-event-loop/#respond</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Thu, 24 May 2018 04:17:36 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2633</guid>

					<description><![CDATA[Today I attended Will Sentance&#8217;s workshop &#8220;JavaScript Hard Parts&#8221; on Frontend Masters. It was a foundational overview of how asynchronous JavaScript is processed using the JavaScript Event Loop. This is not a perspective that I have studied before. Perhaps I should have. Learning about it helped me to understand how things work at a deeper &#8230; <a href="https://john-dugan.com/javascript-event-loop/" class="more-link">Continue reading <span class="screen-reader-text">Asynchronous JavaScript: The Event Loop</span></a>]]></description>
										<content:encoded><![CDATA[<p>Today I attended Will Sentance&#8217;s workshop &#8220;JavaScript Hard Parts&#8221; on <a href="https://frontendmasters.com">Frontend Masters</a>. It was a foundational overview of how asynchronous JavaScript is processed using the JavaScript Event Loop. This is not a perspective that I have studied before. Perhaps I should have. Learning about it helped me to understand how things work at a deeper level across the entire language.</p>
<p>The first building block to understanding asynchronous JavaScript is to identify the core processing components of JavaScript, and understand how they work together using the Event Loop. Below is a brief walk through it.</p>
<h2 id="engine-components">JavaScript Processing Components</h2>
<ol>
<li>JavaScript Engine</li>
<li>Runtime Environment (usually a web browser or Node.js)</li>
<li>Event Queue</li>
<li>Call Stack</li>
</ol>
<p>The JavaScript Engine is the component that <a href="https://john-dugan.com/hoisting-in-javascript/">compiles and executes JavaScript</a>. This may seem obvious, but consider a call to <code>setTimeout</code>. That is <em>not</em> a JavaScript function. <code>setTimeout</code> is an Environment API method. All methods that interact with the <abbr title="Document Object Model">DOM</abbr> are also Environment APIs.</p>
<p>Pure JavaScript, ie: <code>var num = 10;</code>, is processed in the JavaScript Engine. But Environment API methods are processed outside of the JavaScript Engine in the Runtime Environment. If it weren&#8217;t for these Environment APIs, JavaScript would be far less useful because it would not be able to interact with the outside world. So, it&#8217;s important to understand how the components work together using the JavaScript Event Loop. Let&#8217;s look at a simple example.</p>
<h2 id="event-loop">JavaScript Event Loop</h2>
<pre><code class="prettyprint linenums">function sayHi() {
    console.log('hi');
}

setTimeout(sayHi, 0);

console.log('hi first');</code></pre>
<p>On line 1, <code>sayHi</code> is declared as a function in the global scope. Memory is allocated in the JavaScript Engine, and the body of the function is stored (lines 1&ndash;3). <code>sayHi</code> points to that location in memory. You can verify this in your browser&#8217;s console.</p>
<div class="callout--neutral">
<p><em>Want a better understanding of how declaration, assignment, and execution is processed in JavaScript? Check out my post on <a href="https://john-dugan.com/hoisting-in-javascript/">Hoisting in JavaScript</a>.</em></p>
</div>
<figure id="attachment_2634" aria-describedby="caption-attachment-2634" style="width: 592px" class="wp-caption aligncenter"><a data-caption="Function Reference In Memory" data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-body.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-body.png" alt="Screenshot of a value referencing a function in Chrome Dev Tools" width="592" height="213" itemprop="image" class="size-full wp-image-2634" srcset="https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-body.png 592w, https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-body-150x54.png 150w, https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-body-400x144.png 400w" sizes="(max-width: 592px) 100vw, 592px" /></a><figcaption id="caption-attachment-2634" class="wp-caption-text">Function Reference In Memory</figcaption></figure>
<p>On line 5, <code>setTimeout</code> is called. This is where things get interesting. Because <code>setTimeout</code> is an Environment API, it is processed outside of the JavaScript Engine in the Runtime Environment. As you may know, the second parameter of <code>setTimeout</code> accepts a number argument representing a delay. While you could say this delay defines how long it should be until <code>sayHi</code> is executed, more specifically, it defines how long it <em>will be</em> until <code>sayHi</code> is added to the Event Queue by the Runtime Environment.</p>
<p>In our example, <code>sayHi</code> will be added to the Event Queue after <code>0</code> milliseconds. It will remain in the Event Queue until the Call Stack is completely empty. The Call Stack will be empty when all functions in all scopes have executed. At that point, the Event Queue will push the first item its queue (<code>sayHi</code>) to the top of the Call Stack. The process of monitoring the Call Stack, then transferring items from the Event Queue to the Call Stack is referred to as the &#8220;<strong>Event Loop</strong>&#8220;.</p>
<p>The Event Loop operates on a first-in, first-out order (<abbr title="First-In, First-Out">FIFO</abbr> for you accountants turned programmers). A mental model of this process can be established with the analogy of taking trip to the store. You leave your home (the JavaScript Engine) for the store (the Runtime Environment). There, you put an item in your shopping cart and head to the checkout line (the Event Queue). Once it is your turn, you move the item from your cart to the top of the checkout counter (the Call Stack) and the transaction is processed. You then head back to your home (the JavaScript Engine) with the item.</p>
<p>Meanwhile, just because you left to run an errand doesn&#8217;t mean the activity at your house stops. So, to complete the analogy, while <code>setTimeout</code> is processed in the Runtime Environment, then added to the Event Queue, before being pushed to the Call Stack, <code>console.log('hi first');</code> is executed. That is why you see <code>hi first</code> logged before <code>hi</code>.</p>
<figure id="attachment_2635" aria-describedby="caption-attachment-2635" style="width: 592px" class="wp-caption aligncenter"><a data-caption="Asynchronous Function Execution" data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-execution.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-execution.png" alt="Screenshot containing an asynchronous function execution to illustrate the JavaScript Event Loop" width="592" height="242" itemprop="image" class="size-full wp-image-2635" srcset="https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-execution.png 592w, https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-execution-150x61.png 150w, https://john-dugan.com/wp-content/uploads/2018/05/sayHi-function-execution-400x164.png 400w" sizes="(max-width: 592px) 100vw, 592px" /></a><figcaption id="caption-attachment-2635" class="wp-caption-text">Asynchronous Function Execution</figcaption></figure>
<p>I hope this explanation helps to clarify how the JavaScript Event Loop works. Thanks for taking the walk!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/javascript-event-loop/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Asynchronous JavaScript: Promises</title>
		<link>https://john-dugan.com/javascript-promises-overview/</link>
					<comments>https://john-dugan.com/javascript-promises-overview/#respond</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Sat, 24 Dec 2016 03:43:02 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2592</guid>

					<description><![CDATA[What is a Promise? A promise is a placeholder for the result of an asynchronous operation. That&#8217;s it. JavaScript Promises may seem like a very complicated concept, but they are not. A promise is just placeholder. Why do Promises Exist? Promises make flow-control easy to manage. The more complex an application gets, the more difficult &#8230; <a href="https://john-dugan.com/javascript-promises-overview/" class="more-link">Continue reading <span class="screen-reader-text">Asynchronous JavaScript: Promises</span></a>]]></description>
										<content:encoded><![CDATA[<h2>What is a Promise?</h2>
<p><strong>A promise is a placeholder for the result of an asynchronous operation.</strong> That&#8217;s it. JavaScript Promises may seem like a very complicated concept, but they are not. A promise is just placeholder.</p>
<h2>Why do Promises Exist?</h2>
<p><strong>Promises make flow-control easy to manage.</strong> The more complex an application gets, the more difficult flow control becomes. Before promises, event-driven patterns like pub/sub were popularized. They have their place and will remain popular. But event driven architecture is reliant upon event handlers being bound prior to an event occurring. If for instance a button were clicked before a click handler was bound, nothing would happen. This is a problem that promises solve.</p>
<p>But before you think that you should change everything to a promise, wait. You should not. Event driven architecture is extremely helpful for simple <em>user interaction</em>. Where event driven architecture becomes problematic is complex <em>systems/network interaction</em>.</p>
<p>When Node.js was created, it solved this problem with the callback pattern. In the callback pattern you don&#8217;t have to worry about event handlers being registered before an event is triggered because the handlers are passed as arguments &#8211; <em>callback</em> arguments. The callback pattern makes chaining multiple [callback] functions throughout the flow of a program simple. But that simplicity can quickly become a nightmare &#8211; just Google &#8220;callback hell&#8221; for the pitfalls of the callback pattern.</p>
<p>So back to the question, why do promises exist? JavaScript needed a better way to manage flow control. Ahhhhh, we&#8217;ve come full circle.</p>
<h2>What Happens in a Promise?</h2>
<p>First, let&#8217;s remember what a promise is: a promise is a placeholder. When a promise is explicitly assigned via the <code>Promise()</code> constructor, or implicitly returned from a method like <code>fetch()</code>, what is actually returned from either scenario is just an object. The returned object&#8217;s <code>__proto__</code> property points to <code>Promise</code>. So, we call it a &#8220;Promise Object&#8221;. But do remember that it&#8217;s just an object. If you look through the prototype chain shown in the screenshot below, you&#8217;ll see just one level up that the <code>__proto__</code> property points to <code>Object</code>.</p>
<figure id="attachment_2593" aria-describedby="caption-attachment-2593" style="width: 685px" class="wp-caption aligncenter"><a data-caption="Basic JavaScript Promise" data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2016/12/basic-promise-example.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2016/12/basic-promise-example-685x385.png" alt="Basic JavaScript Promise" width="685" height="385" itemprop="image" class="size-large wp-image-2593" srcset="https://john-dugan.com/wp-content/uploads/2016/12/basic-promise-example-685x385.png 685w, https://john-dugan.com/wp-content/uploads/2016/12/basic-promise-example-150x84.png 150w, https://john-dugan.com/wp-content/uploads/2016/12/basic-promise-example-400x225.png 400w, https://john-dugan.com/wp-content/uploads/2016/12/basic-promise-example-768x431.png 768w, https://john-dugan.com/wp-content/uploads/2016/12/basic-promise-example-794x446.png 794w, https://john-dugan.com/wp-content/uploads/2016/12/basic-promise-example.png 812w" sizes="(max-width: 685px) 100vw, 685px" /></a><figcaption id="caption-attachment-2593" class="wp-caption-text">Basic JavaScript Promise</figcaption></figure>
<p>Okay, moving on. The promise object that is returned contains an internal <code>[[PromiseStatus]]</code> property. There are three status values that this property can have, which together comprise the &#8220;Promise Life Cycle&#8221;. Those statuses are: </p>
<ul>
<li>
<p class="margin-top--none"><code>"pending"</code>: this is the first status. It indicates the underlying operation has not completed. A promise will <em>always</em> have a pending status at some point in its life cycle.</p>
</li>
<li>
<p><code>"fulfilled"</code>: this status indicates that the underlying operation has successfully completed.</p>
</li>
<li>
<p class="margin-bottom--none"><code>"rejected"</code>: this status indicates that the underlying operation did not complete. This may be due to a bug, network issue, etc.</p>
</li>
</ul>
<p>Again, those are the <em>statuses</em> that comprise the <em>life cycle</em> of a promise in JavaScript.</li>
<p>Let&#8217;s talk about the <em>state</em> of a promise. State in promises is very simple, it&#8217;s either settled or unsettled. When a promise&#8217;s status is <code>"pending"</code>, its state is <strong>unsettled</strong>. When a promise&#8217;s status is <code>"fulfilled"</code> or <code>"rejected"</code>, its state is <strong>settled</strong>. Simple when it&#8217;s not over complicated, huh?</p>
<h2>Let&#8217;s Review Promises</h2>
<ul>
<li>A promise is a placeholder for the result of an asynchronous operation.</li>
<li>Promises make flow-control easy to manage.</li>
<li>Promises have three statuses that comprise their life cycle: pending, fulfilled, and rejected.</li>
<li>Promises have two states: settled and unsettled.</li>
</ul>
<h2>Final Word on Promises</h2>
<p>I&#8217;ve seen/read/viewed a lot of people who use the terms &#8220;status&#8221; and &#8220;state&#8221; loosely &#8211; even interchangeably at times. This causes a lot of confusion.</p>
<p>Understanding the difference between &#8220;status&#8221;, &#8220;state&#8221;, and &#8220;life cycle&#8221; is critical to understanding promises. Conflating these terms is one of the main reasons promises seem so confusing. Understand them, and you are well positioned to mastering promises.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/javascript-promises-overview/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Google Analytics Custom Events Emitter</title>
		<link>https://john-dugan.com/google-analytics-custom-events-emitter/</link>
					<comments>https://john-dugan.com/google-analytics-custom-events-emitter/#respond</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Sun, 07 Aug 2016 16:26:07 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2577</guid>

					<description><![CDATA[A while back I looked in to implementing Google Tag manager so that marketing folks at my company could manage custom events in Google Analytics. Beyond custom events, I&#8217;m not sure what Google Tag Manager does (it&#8217;s been a while since I looked at it). Perhaps there are a bunch of great benefits that I &#8230; <a href="https://john-dugan.com/google-analytics-custom-events-emitter/" class="more-link">Continue reading <span class="screen-reader-text">Google Analytics Custom Events Emitter</span></a>]]></description>
										<content:encoded><![CDATA[<p>A while back I looked in to implementing Google Tag manager so that marketing folks at my company could manage custom events in Google Analytics. Beyond custom events, I&#8217;m not sure what Google Tag Manager does (it&#8217;s been a while since I looked at it). Perhaps there are a bunch of great benefits that I am missing.</p>
<p>I ended up not deploying Tag Manager for the same reason that others would choose to deploy it: simplicity. For me, the best way to keep things simple is to avoid another application abstraction and just use code. So, I created a JavaScript module that allows me to easily add custom events. Below is the code for my Google Analytics custom events emitter module.</p>
<pre><code class="prettyprint">// ----------------------------------------------------
// ---------- GOOGLE ANALYTICS CUSTOM EVENTS ----------
// ----------------------------------------------------
/*
    Assign an `analyticsEvents` property to a global `APP` object. This property
    stores our module. The immediately invoked function expression (IIFE)
    assigned to this module ensures that all code within the module is contained
    within its own scope (the module scope). jQuery is passed as an argument
    which is assigned to the `$` character. This way, we protect jQuery from
    conflicting with other libraries that also alias to the $ character.
 */
APP.analyticsEvents = (function($) {

    /*
        Assign Google Analytics "Event Actions" to constants. This prevents us
        from passing the wrong event action to Google. In the case of a typo, we
        get an "undefined" error instead of not seeing an error at all.
     */
    var APPLY = 'Apply',
        BROWSE = 'Browse',
        CLICK = 'Click',
        LOGIN = 'Login',
        REGISTER = 'Register',
        REQUEST = 'Request',
        SEARCH = 'Search',
        SUBMIT = 'Submit',
        SUBSCRIBE = 'Subscribe';

    /*
        All of our custom events are stored in an `events` object. Each key in
        the `events` object corresponds to a Google Analytics "Event Category".
     */
    var events = {
        /*
            An array is assigned to each key in the `events` object. Each index
            of the array contains sub arrays. The sub arrays contain the actual
            events.

            The first index of the sub array is a `data-event` attribute that we
            add element(s) in the DOM. The Second index of the sub array is the
            Google Analytics "Event Action" (where our constants created above
            are used). The third and final index of the sub array is the Google
            Analytics "Event Label".
         */
        'Account Actions': [
            ['[data-event="start-account-create"]', REGISTER, 'Start Account Registration Before Checkout'],
            ['[data-event="start-account-create-quote-checkout"]', REGISTER, 'Start Account Registration During Quote Checkout'],
            ['[data-event="create-account"]', REGISTER, 'Register Account Before Checkout'],
            ['[data-event="create-account-order-checkout"]', REGISTER, 'Register Account After Order Checkout'],
            ['[data-event="login-account"]', LOGIN, 'Login To Account Before Checkout'],
            ['[data-event="login-account-order-checkout"]', LOGIN, 'Login To Account During Order Checkout'],
            ['[data-event="login-account-quote-checkout"]', LOGIN, 'Login To Account During Quote Checkout'],
            ['[data-event="start-credit-application"]', APPLY, 'Start Credit Application']
        ],
        'Content Marketing': [
            ['[data-event="start-catalog-request"]', REQUEST, 'Start Catalog Request'],
            ['[data-event="start-white-paper-request"]', REQUEST, 'Start White Paper Request'],
            ['[data-event="start-utility-request"]', REQUEST, 'Start Worksheet Request'],
            ['[data-event="start-newsletter-subscription"]', SUBSCRIBE, 'Start Newsletter Subscription']
        ],
        'Shopping Actions': [
            ['[data-event="shop-categories"]', BROWSE, 'Shop By Category'],
            ['[data-event="shop-manufacturers"]', BROWSE, 'Shop By Manufacturer'],
            ['[data-event="search-site"]', SEARCH, 'Search Entire Site'],
            ['[data-event="search-category"]', SEARCH, 'Search Within Category'],
            ['[data-event="search-results"]', SEARCH, 'Search Within Results'],
            ['[data-event="add-to-cart"]', CLICK, 'Add Product To Cart'],
            ['[data-event="add-to-quote"]', CLICK, 'Add Product To Quote']
        ],
        'Quote Checkout': [
            ['[data-event="start-quote-checkout"]', CLICK, 'Start Quote Checkout'],
            ['[data-event="opc-quote-shipping-address"]', SUBMIT, 'Enter Shipping Address For Quote'],
            ['[data-event="opc-quote-shipping-method"]', SUBMIT, 'Select Shipping Method For Quote'],
            ['[data-event="opc-quote-complete"]', SUBMIT, 'Complete Quote Checkout']
        ],
        'Order Checkout': [
            ['[data-event="start-order-checkout"]', CLICK, 'Start Order Checkout'],
            ['[data-event="opc-guest-checkout"]', SUBMIT, 'Order Checkout As Guest'],
            ['[data-event="opc-shipping-address"]', SUBMIT, 'Enter Shipping Address For Order'],
            ['[data-event="opc-shipping-method"]', SUBMIT, 'Select Shipping Method For Order'],
            ['[data-event="opc-payment"]', SUBMIT, 'Enter Payment Information For Order'],
            ['[data-event="opc-complete"]', SUBMIT, 'Complete Order Checkout']
        ],
        'Quote Actions': [
            ['[data-event="edit-quote"]', CLICK, 'Edit Quote'],
            ['[data-event="remove-quote"]', CLICK, 'Remove Quote'],
            ['[data-event="convert-quote"]', CLICK, 'Convert Quote To Order']
        ],
        'Order Actions': [
            ['[data-event="start-rma-request"]', CLICK, 'Start RMA Request'],
            ['[data-event="start-reorder"]', CLICK, 'Start Reorder']
        ]
    };

    /*
        The `init` method gets things rolling. This is called when the
        `DOMContentLoaded` event fires (which happens after the HTML document
        has been loaded and parsed by the browser).
     */
    function init() {
        /*
            Below we assign each key ("Event Category") in the `events` object
            to an array using the `Object.keys` method. We then itterate through
            that array using the `forEach` method, executing an anonymous
            function that we pass the "Event Category" to as an argument. Inside
            that anonymous function, our module's `buildEvents` function is
            called with our category passed as the first argument and the array
            assigned to that category as the second argument.
         */
        Object.keys(events).forEach(function(category) {
            buildEvents(category, events[category]);
        });
    }

    /*
        The `bindListeners` method binds our Google Analytics "Custom Event"
        function created in the `buildEvents` method below as a callback to the
        DOM node whose selector is passed as the first argument (explained
        further in the in the comments for the `buildEvents` function below).
     */
    function bindListeners(selector, evt) {
        $(selector).on('click', evt);
    }

    /*
        The `buildEvents` method is called inside the `init` method. Its
        purpose is to construct the "Custom Event" function that gets called
        when an a user interaction takes place.
     */
    function buildEvents(categoryName, categoryEvents) {
        categoryEvents.forEach(function(item) {
            /*
                The `evt` variable holds our "Custom Event" function. This
                function is passed as an argument to the `bindListensers`
                function above. As noted above, this function gets called when
                a user interaction takes place.
             */
            var evt = function() {
                /*
                    We wrap our "Custom Event" funciton in a try/catch block.
                    This way, if the event fails (because Google Analytics
                    fails to load, etc), we can notify ourselves.
                 */
                try {
                    ga('send', 'event', categoryName, item[1], item[2]);
                } catch (err) {
                    /*
                        The `APP.logError` module, which is not covered in this
                        post, will notify us of an error.
                     */
                    APP.logError(err);
                }
            };

            /*
                Finally, we call the `bindListeners` function. This binds the
                function stored in `evt` as a callback to be executed when a
                user interaction takes place. The first argument contains the
                a selector (our `data-events`) attribute. The second argument
                is our `evt` callback function.
             */
            bindListeners(item[0], evt);
        });
    }

    /*
        Once the DOMContentLoaded event has fired, we execute our module's
        `init` function using jQuery's `ready` funciton.
     */
    $(document).ready(init);

}(jQuery));</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/google-analytics-custom-events-emitter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Introducing Contrast Theme for Sublime Text</title>
		<link>https://john-dugan.com/contrast-theme/</link>
					<comments>https://john-dugan.com/contrast-theme/#respond</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Sun, 21 Feb 2016 04:23:31 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2553</guid>

					<description><![CDATA[Contrast is a theme for Sublime Text born out of my frustration with inconsistent cross-language syntax highlighting. The purpose of Contrast is to reduce cognitive load by making color representative of how a program actually works, rather than just highlighting text. Contrast Theme Language Support I took a ground-zero approach when creating Contrast. No theme &#8230; <a href="https://john-dugan.com/contrast-theme/" class="more-link">Continue reading <span class="screen-reader-text">Introducing Contrast Theme for Sublime Text</span></a>]]></description>
										<content:encoded><![CDATA[<p>Contrast is a theme for Sublime Text born out of my frustration with inconsistent cross-language syntax highlighting. The purpose of Contrast is to reduce cognitive load by making color representative of how a program actually works, rather than just highlighting text.</p>
<h2>Contrast Theme Language Support</h2>
<p>I took a ground-zero approach when creating Contrast. No <a href="http://tmtheme-editor.herokuapp.com/" title="Sublime Text theme editor">theme editor/generator</a> was used. I started with, and will continue to build Contrast in raw XML. Currently, Contrast is focused on the languages below.</p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>Sass</li>
<li>JavaScript</li>
<li>PHP</li>
<li>JSON</li>
<li>XML</li>
</ul>
<p>My next step is to improve support for Sass. The current language definitions in Sublime Text for Sass are pretty awful. So, I need to create a better language file or find an open source one. The improved language file will provide the necessary Sass definitions to bind Contrast&#8217;s syntax highlighting rules to.</p>
<h2>Contrast Theme Preview</h2>
<p>Below is a screenshot of Contrast in JavaScript, where Sublime Text 3 <em>does provide</em> good language definitions. You will notice that function declarations and expressions are in blue, and function invocations are in light blue. While a relationship is established by all functions being blue, the different shades of blue imply a different context. Though subtle, this approach achieves the goal of reducing cognitive load by making it easier for developers to build a mental model.</p>
<figure id="attachment_2558" aria-describedby="caption-attachment-2558" style="width: 486px" class="wp-caption aligncenter"><a data-caption="Contrast Theme JavaScript Preview" data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2016/02/contrast-theme-preview.png" rel="attachment wp-att-2558"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2016/02/contrast-theme-preview-486x685.png" alt="Screenshot of a JavaScript module in Contrast Theme for Sublime Text" width="486" height="685" itemprop="image" class="size-large wp-image-2558" srcset="https://john-dugan.com/wp-content/uploads/2016/02/contrast-theme-preview-486x685.png 486w, https://john-dugan.com/wp-content/uploads/2016/02/contrast-theme-preview-107x150.png 107w, https://john-dugan.com/wp-content/uploads/2016/02/contrast-theme-preview-284x400.png 284w, https://john-dugan.com/wp-content/uploads/2016/02/contrast-theme-preview-374x527.png 374w, https://john-dugan.com/wp-content/uploads/2016/02/contrast-theme-preview.png 708w" sizes="(max-width: 486px) 100vw, 486px" /></a><figcaption id="caption-attachment-2558" class="wp-caption-text">Contrast Theme JavaScript Preview</figcaption></figure>
<p>Lastly, my intent is to publish Contrast on <a href="https://packagecontrol.io/" title="Sublime Text package manager">Package Control</a> when Sass support is better. For now, I&#8217;ll continue to use Contrast privately and fix errors and inconsistencies along the way. Feel free to <a href="https://github.com/johndugan/contrast-theme" title="Contrast Theme for Sublime Text">download Contrast from GitHub</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/contrast-theme/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>2016 New Year&#8217;s Resolution</title>
		<link>https://john-dugan.com/2016-new-years-resolution/</link>
					<comments>https://john-dugan.com/2016-new-years-resolution/#respond</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Thu, 31 Dec 2015 03:24:38 +0000</pubDate>
				<category><![CDATA[Productivity]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2527</guid>

					<description><![CDATA[My professional goal in 2015 was to up my JavaScript skills. I focused on developing a much deeper understanding of the language and mastering its concepts. I feel good about the progress I made. While I still use (and love) jQuery, it&#8217;s no longer a crutch to mask my understanding of the language. In 2016 &#8230; <a href="https://john-dugan.com/2016-new-years-resolution/" class="more-link">Continue reading <span class="screen-reader-text">2016 New Year&#8217;s Resolution</span></a>]]></description>
										<content:encoded><![CDATA[<p>My professional goal in 2015 was to up my JavaScript skills. I focused on developing a much deeper understanding of the language and mastering its concepts. I feel good about the progress I made. While I still use (and love) jQuery, it&#8217;s no longer a crutch to mask my understanding of the language. In 2016 my JavaScript goal remains, but I am going to narrow my focus to a specific stack.</p>
<p>Right now there is so much innovation with JavaScript that it can feel overwhelming. It seems like every day there is a new framework, library <span class="disclaimer text--strike">or</span> and build tool that the community clamors about. There is too much noise. The noise breaks focus, which impedes learning and hurts productivity. From an idealistic standpoint the stack should depend on the project. But for me, that&#8217;s just not practical. Time is the ultimate constraint, and I&#8217;d rather not spend it becoming a master of nothing.</p>
<p>Over the last couple months, I&#8217;ve done a fair amount of research and learning about different JavaScript technologies. Understanding their core methodologies has helped me isolate those that I feel have the most potential and will be the most fun to learn. So, in 2016 I&#8217;ve decided to focus on the following:</p>
<ul>
<li><a href="https://nodejs.org/en/">Node <span class="disclaimer">&mdash; ground zero</span></a></li>
<li><a href="http://sailsjs.org/">Sails <span class="disclaimer">&mdash; API + database</span></a></li>
<li><a href="http://rackt.org/redux/docs/introduction/Motivation.html">Redux <span class="disclaimer">&mdash; state management</span></a></li>
<li><a href="https://facebook.github.io/react/">React <span class="disclaimer">&mdash; user interface</span></a></li>
</ul>
<p>Each of these layers in the stack will come with a ton of new things to learn. By no means do I expect to become an expert by year&#8217;s end. I do expect however to be proficient with them, and I&#8217;m pretty excited about that!</p>
<p>Happy New Year <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/2016-new-years-resolution/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Setup ionCube Loaders in WAMP</title>
		<link>https://john-dugan.com/setup-ioncube-loaders-in-wamp/</link>
					<comments>https://john-dugan.com/setup-ioncube-loaders-in-wamp/#respond</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Wed, 16 Dec 2015 04:17:03 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2479</guid>

					<description><![CDATA[In order to develop sites on WAMP that have ionCube encrypted PHP files, you need to setup ionCube loaders in WAMP. Several years ago, I posted a popular screencast to my YouTube channel on the subject. I just upgraded to Windows 10 and took the opportunity to record another screencast on setting up ionCube loaders &#8230; <a href="https://john-dugan.com/setup-ioncube-loaders-in-wamp/" class="more-link">Continue reading <span class="screen-reader-text">Setup ionCube Loaders in WAMP</span></a>]]></description>
										<content:encoded><![CDATA[<p>In order to develop sites on WAMP that have ionCube encrypted PHP files, you need to setup ionCube loaders in WAMP. Several years ago, I posted a popular screencast to <a href="https://www.youtube.com/johnnydugs" title="Visit my YouTube channel">my YouTube channel</a> on the subject. I just upgraded to Windows 10 and took the opportunity to record another screencast on setting up ionCube loaders in WAMP.</p>
<p>The original screencast explains step-by-step how to setup ionCube loaders in WAMP using ionCube&#8217;s installation wizard. The new screencast does <em>not</em> use the wizard &mdash; it takes a more direct approach. While the installation wizard is recommended on ionCube&#8217;s website, the new approach is consistent with how you install any PHP extension in WAMP. Bottom line, both approaches will get the job done.</p>
<figure class="entry__figure margin-bottom--paragraph">
  <iframe loading="lazy" title="Setup ionCube Loaders in WAMP Server on Windows" width="660" height="495" src="https://www.youtube.com/embed/P7ig8XK6ZUA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><figcaption class="entry__figcaption margin--small">Setup ionCube Loaders Using The Wizard (the old)</figcaption></figure>
<figure class="entry__figure">
  <iframe loading="lazy" title="Setup ionCube Loaders in WAMP Server on Windows 10" width="660" height="371" src="https://www.youtube.com/embed/X-7JYyeL3UM?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><figcaption class="entry__figcaption margin--small">Setup ionCube Loaders Without The Wizard (the new)</figcaption></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/setup-ioncube-loaders-in-wamp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Visual Studio Code vs. Sublime Text</title>
		<link>https://john-dugan.com/visual-studio-code-vs-sublime-text/</link>
					<comments>https://john-dugan.com/visual-studio-code-vs-sublime-text/#comments</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Wed, 04 Nov 2015 02:30:09 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2397</guid>

					<description><![CDATA[I want to start by giving high praise to the Visual Studio Code team at Microsoft. It&#8217;s an incredible product that I believe will only get better. The git integration, the task runner integration, JavaScript debugging, IntelliSense, and parameter hinting are all incredible features. Visual Studio Code (VS Code) is well designed and it&#8217;s fast. &#8230; <a href="https://john-dugan.com/visual-studio-code-vs-sublime-text/" class="more-link">Continue reading <span class="screen-reader-text">Visual Studio Code vs. Sublime Text</span></a>]]></description>
										<content:encoded><![CDATA[<p>I want to start by giving high praise to the Visual Studio Code team at Microsoft. It&#8217;s an incredible product that I believe will only get better. The git integration, the task runner integration, JavaScript debugging, IntelliSense, and parameter hinting are all incredible features. Visual Studio Code (VS Code) is well designed and it&#8217;s fast. It strikes a near perfect balance between being feature rich and simple. </p>
<p><strong>BUT&hellip;</strong></p>
<p>Visual Studio Code is lacking in some key areas that matter to me:</p>
<ol>
<li>Color Themes</li>
<li>Packages</li>
<li>Language Support</li>
<li>Key Bindings</li>
</ol>
<h2 id="color-themes">VS Code Color Themes</h2>
<p>At the moment, you are pretty well stuck with a handful of color themes provided by Microsoft. While it <em>is possible</em> to use Yeoman to build/convert a <code>.tmTheme</code> file for Visual Studio Code, in my experience it simply doesn&#8217;t work. I used <a href="https://github.com/Microsoft/generator-code">Microsoft&#8217;s Yeoman generator</a> to convert a couple <a href="http://colorsublime.com/">themes on Color Sublime</a>, and while there were no errors doing so, the syntax coloring was completely wrong compared to the same theme in Sublime Text. This is very frustrating. When you stare at a code editor all day, color really does matter.</p>
<figure id="attachment_2455" aria-describedby="caption-attachment-2455" style="width: 685px" class="wp-caption aligncenter"><a data-caption="1337 Theme in VS Code and Sublime Text (JavaScript)" data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-js.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-js-685x385.png" alt="Screenshot of JavaScript code using the same color theme in Visual Studio Code and Sublime Text" width="685" height="385" itemprop="image" class="size-large wp-image-2455" srcset="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-js-685x385.png 685w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-js-150x84.png 150w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-js-400x225.png 400w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-js-794x447.png 794w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-js-1200x675.png 1200w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-js.png 1920w" sizes="(max-width: 685px) 100vw, 685px" /></a><figcaption id="caption-attachment-2455" class="wp-caption-text">1337 Theme in VS Code and Sublime Text (JavaScript)</figcaption></figure>
<figure id="attachment_2456" aria-describedby="caption-attachment-2456" style="width: 685px" class="wp-caption aligncenter"><a data-caption="1337 Theme in VS Code and Sublime Text (Sass)" data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-scss.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-scss-685x385.png" alt="Screenshot of CSS (Sass) code using the same color theme in Visual Studio Code and Sublime Text" width="685" height="385" itemprop="image" class="size-large wp-image-2456" srcset="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-scss-685x385.png 685w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-scss-150x84.png 150w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-scss-400x225.png 400w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-scss-794x447.png 794w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-scss-1200x675.png 1200w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-scss.png 1920w" sizes="(max-width: 685px) 100vw, 685px" /></a><figcaption id="caption-attachment-2456" class="wp-caption-text">1337 Theme in VS Code and Sublime Text (Sass)</figcaption></figure>
<figure id="attachment_2457" aria-describedby="caption-attachment-2457" style="width: 685px" class="wp-caption aligncenter"><a data-caption="1337 Theme in VS Code and Sublime Text (PHP)" data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-php.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-php-685x385.png" alt="Screenshot of PHP code using the same color theme in Visual Studio Code and Sublime Text" width="685" height="385" itemprop="image" class="size-large wp-image-2457" srcset="https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-php-685x385.png 685w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-php-150x84.png 150w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-php-400x225.png 400w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-php-794x447.png 794w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-php-1200x675.png 1200w, https://john-dugan.com/wp-content/uploads/2015/11/vs-code-vs-sublime-text-color-theme-php.png 1920w" sizes="(max-width: 685px) 100vw, 685px" /></a><figcaption id="caption-attachment-2457" class="wp-caption-text">1337 Theme in VS Code and Sublime Text (PHP)</figcaption></figure>
<h2 id="packages">VS Code Packages</h2>
<p>With most developer tools, the strength of the community makes a huge difference in a product&#8217;s value proposition. This is certainly evident in Sublime Text where there are hundreds of packages available. While Sublime Text has felt old and unrefined for a couple years, the package ecosystem continues to set the editor apart. I don&#8217;t know a single Sublime Text user that runs the editor without multiple packages in use. The result of such a robust package ecosystem is that each Sublime Test user runs a tailored variant of base product. This is a huge plus for Sublime. It&#8217;s not all things to all developers, but it can [almost] be.</p>
<aside class="callout--neutral">
<h3 class="callout__heading">Sublime Text Packages</h3>
<p class="callout__subheading">Packages that I rely on</p>
<ul>
<li><a href="https://packagecontrol.io/packages/Alignment" title="View Alignment on Package Control">Alignment</a> <span class="disclaimer">Easy alignment of multiple selections and multi-line selections</span></li>
<li><a href="https://packagecontrol.io/packages/ApplySyntax" title="View Apply​Syntax on Package Control">Apply​Syntax</a> <span class="disclaimer">Syntax detector for Sublime Text</span></li>
<li><a href="https://packagecontrol.io/packages/DocBlockr" title="View Doc​Blockr on Package Control">Doc​Blockr</a> <span class="disclaimer">Simplifies writing DocBlock comments in Javascript, PHP, CoffeeScript, Actionscript, C &#038; C++</span></li>
<li><a href="https://packagecontrol.io/packages/EJS" title="View EJS on Package Control">EJS</a> <span class="disclaimer">An EJS syntax definition specifically for sublime text</span></li>
<li><a href="https://packagecontrol.io/packages/Emmet" title="View Emmet on Package Control">Emmet</a> <span class="disclaimer">Emmet (ex-Zen Coding) for Sublime Text</span></li>
<li><a href="https://packagecontrol.io/packages/Emmet%20Css%20Snippets" title="View Emmet Css Snippets on Package Control">Emmet Css Snippets</a> <span class="disclaimer">Emmet CSS completions for Sublime Text</span></li>
<li><a href="https://packagecontrol.io/packages/ExpandRegion" title="View Expand​Region on Package Control">Expand​Region</a> <span class="disclaimer">Like &#8220;Expand Selection to Scope&#8221; but better</span></li>
<li><a href="https://packagecontrol.io/packages/LineEndings" title="View Line​Endings on Package Control">Line​Endings</a> <span class="disclaimer">On statusbar and on command palete</span></li>
<li><a href="https://packagecontrol.io/packages/Package%20Control" title="View Package Control on Package Control">Package Control</a> <span class="disclaimer">A full-featured package manager</span></li>
<li><a href="https://packagecontrol.io/packages/Sass" title="View Sass on Package Control">Sass</a> <span class="disclaimer">Sass support for TextMate &#038; Sublime Text (2 &#038; 3)</span></li>
<li><a href="https://packagecontrol.io/packages/SublimeCodeIntel" title="View Sublime​Code​Intel on Package Control">Sublime​Code​Intel</a> <span class="disclaimer">Full-featured code intelligence and smart autocomplete engine</span></li>
<li><a href="https://packagecontrol.io/packages/SublimeLinter" title="View Sublime​Linter on Package Control">Sublime​Linter</a> <span class="disclaimer">Interactive code linting framework for Sublime Text 3</span></li>
<li><a href="https://packagecontrol.io/packages/SublimeLinter-contrib-htmlhint" title="View Sublime​Linter-contrib-htmlhint on Package Control">Sublime​Linter-contrib-htmlhint</a> <span class="disclaimer">SublimeLinter plugin for HTML using htmlhint</span></li>
<li><a href="https://packagecontrol.io/packages/SublimeLinter-jshint" title="View Sublime​Linter-jshint on Package Control">Sublime​Linter-jshint</a> <span class="disclaimer">SublimeLinter plugin for JavaScript using jshint</span></li>
<li><a href="https://packagecontrol.io/packages/SublimeLinter-php" title="View Sublime​Linter-php on Package Control">Sublime​Linter-php</a> <span class="disclaimer">SublimeLinter 3 plugin for PHP using php -l</span></li>
<li><a href="https://packagecontrol.io/packages/TrailingSpaces" title="View Sublime​Linter-php on Package Control">Trailing​Spaces</a> <span class="disclaimer">Highlight trailing spaces and delete them in a flash</span></li>
<li><a href="https://packagecontrol.io/packages/WordPress" title="View Word​Press on Package Control">Word​Press</a> <span class="disclaimer">Sublime Text WordPress package</span></li>
</ul>
</aside>
<h2 id="language-support">VS Code Language Support</h2>
<p>I initially installed Visual Studio Code because I am about to start a Node.js project. The editor shines with Node &#8211; like it was made specifically for Node development. It&#8217;s 100% awesome. But I also develop for Magento and WordPress, both of which are built on PHP. To the same degree that Visual Studio Code is awesome with Node, it lacks with PHP. Though, this isn&#8217;t too big of a concern for me. Microsoft has made their <a href="https://code.visualstudio.com/docs/languages/overview">current language focus</a> clear, and as the product progresses, I&#8217;d imagine that language support will improve.</p>
<h2 id="key-bindings">VS Code Key Bindings</h2>
<p>Last and least, the available key bindings (keyboard shortcuts) just aren&#8217;t there. This is a problem that I am less confident will be resolved. While the critical key bindings are available, and customizing them is near identical to Sublime Text, the <em>breadth of bindings</em> that you can customize in Visual Studio Code is trumped by Sublime Text. I&#8217;m sure some developers don&#8217;t take advantage of keyboard shortcuts to the extent that I do. Again, this is an area where Sublime Text is not all things to all developers, but it can be. With Visual Studio Code, it&#8217;s flat out not.</p>
<aside class="callout--neutral">
<h3 class="callout__heading">Sublime Text Key Bindings</h3>
<p class="callout__subheading">Key bindings that I wrote</p>
<pre class="margin-top--section"><code class="prettyprint">[

  // -------- Editor --------

  // Visibility
  { "keys": ["ctrl+b"], "command": "toggle_side_bar" },
  { "keys": ["f11"], "command": "toggle_full_screen" },
  { "keys": ["shift+f11"], "command": "toggle_distraction_free" },

  // Multiple Panes
  { "keys": ["alt+shift+1"], "command": "set_layout", "args": {"cols": [0.0, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1]]} },
  { "keys": ["alt+shift+2"], "command": "set_layout", "args": {"cols": [0.0, 0.5, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]} },
  { "keys": ["alt+shift+3"], "command": "set_layout", "args": {"cols": [0.0, 0.33, 0.66, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1], [1, 0, 2, 1], [2, 0, 3, 1]]} },
  {"keys": ["alt+shift+4"], "command": "set_layout", "args": {"cols": [0.0, 0.25, 0.5, 0.75, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1], [1, 0, 2, 1], [2, 0, 3, 1], [3, 0, 4, 1]]} },
  { "keys": ["ctrl+1"], "command": "focus_group", "args": { "group": 0 } },
  { "keys": ["ctrl+2"], "command": "focus_group", "args": { "group": 1 } },
  { "keys": ["ctrl+3"], "command": "focus_group", "args": { "group": 2 } },
  { "keys": ["ctrl+4"], "command": "focus_group", "args": { "group": 3 } },


  // -------- Traversal --------

  // Left/Right
  { "keys": ["ctrl+left"], "command": "move", "args": {"by": "words", "forward": false} },
  { "keys": ["ctrl+right"], "command": "move", "args": {"by": "word_ends", "forward": true} },
  { "keys": ["ctrl+alt+left"], "command": "move_to", "args": {"to": "bol", "extend": false} },
  { "keys": ["ctrl+alt+right"], "command": "move_to", "args": {"to": "eol", "extend": false} },
  { "keys": ["ctrl+space"], "command": "move", "args": {"by": "subword_ends", "forward": true} },
  { "keys": ["alt+space"], "command": "move", "args": {"by": "subwords", "forward": false} },

  // Up/Down
  { "keys": ["alt+]"], "command": "move_to", "args": {"to": "brackets"} },
  { "keys": ["alt+>"], "args": {"action": "matching_pair"}, "command": "run_emmet_action", "context": [{"key": "emmet_action_enabled.matching_pair"}] }, // ! requires Emmet !
  { "keys": ["ctrl+home"], "command": "move_to", "args": {"to": "bof", "extend": false} },
  { "keys": ["ctrl+end"], "command": "move_to", "args": {"to": "eof", "extend": false} },


  // -------- Selection --------

  // Left/Right
  { "keys": ["ctrl+shift+left"], "command": "move", "args": {"by": "words", "forward": false, "extend": true} },
  { "keys": ["ctrl+shift+right"], "command": "move", "args": {"by": "word_ends", "forward": true, "extend": true} },
  { "keys": ["ctrl+alt+shift+left"], "command": "move_to", "args": {"to": "bol", "extend": true} },
  { "keys": ["ctrl+alt+shift+right"], "command": "move_to", "args": {"to": "eol", "extend": true} },

  // Up/Down
  { "keys": ["ctrl+shift+down"], "command": "expand_selection", "args": {"to": "line"} },
  { "keys": ["ctrl+shift+up"], "command": "expand_selection", "args": {"to": "line"} }, // PROBLEM: not possible to select lines above
  { "keys": ["ctrl+alt+shift+up"], "command": "move_to", "args": {"to": "bof", "extend": true} },
  { "keys": ["ctrl+alt+shift+down"], "command": "move_to", "args": {"to": "eof", "extend": true} },


  // -------- Deletion --------

  { "keys": ["ctrl+backspace"], "command": "delete_word", "args": { "forward": false } },
  { "keys": ["alt+backspace"], "command": "delete_word", "args": { "forward": true } },
  { "keys": ["ctrl+alt+backspace"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete to Hard BOL.sublime-macro"} },
  { "keys": ["ctrl+shift+backspace"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete Line.sublime-macro"} },
  { "keys": ["ctrl+shift+alt+d"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete Line.sublime-macro"} },
  { "keys": ["alt+shift+backspace"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete to Hard EOL.sublime-macro"} },
  { "keys": ["ctrl+alt+enter"], "command": "expand_as_you_type", "context": [{"operand": false, "operator": "equal", "match_all": true, "key": "setting.is_widget"}, {"match_all": true, "key": "emmet_action_enabled.expand_as_you_type"}] }, // ! requires Emmet !


  // -------- Search --------

  { "keys": ["ctrl+f"], "command": "show_panel", "args": {"panel": "find", "reverse": false} },
  { "keys": ["ctrl+shift+f"], "command": "show_panel", "args": {"panel": "replace", "reverse": false} },
  { "keys": ["ctrl+shift+alt+f"], "command": "show_panel", "args": {"panel": "find_in_files"} },


  // -------- Find & Replace --------

  { "keys": ["ctrl+d"], "command": "find_under_expand" },
  { "keys": ["ctrl+alt+a"], "command": "find_all_under" },
  { "keys": ["ctrl+alt+z"], "command": "soft_undo" },
  { "keys": ["ctrl+alt+up"], "command": "find_prev" },
  { "keys": ["ctrl+alt+down"], "command": "find_under" },
  { "keys": ["alt+shift+up"], "command": "expand_region" }, // ! requires ExpandRegion !
  { "keys": ["alt+shift+down"], "command": "expand_region", "args": {"undo": true}, "context": [{ "key": "expand_region_soft_undo" }]}, // ! requires ExpandRegion !


  // -------- Code --------

  // Lines
  { "keys": ["alt+up"], "command": "swap_line_up" },
  { "keys": ["alt+down"], "command": "swap_line_down" },
  { "keys": ["ctrl+shift+d"], "command": "duplicate_line" },
  { "keys": ["ctrl+j"], "command": "join_lines" },
  { "keys": ["ctrl+shift+v"], "command": "paste_and_indent" },
  { "keys": ["ctrl+enter"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Add Line.sublime-macro"} },
  { "keys": ["ctrl+shift+enter"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Add Line Before.sublime-macro"} },

  // Integers ! requires Emmet !
  { "keys": ["alt+="], "args": {"action": "increment_number_by_1"}, "command": "run_emmet_action", "context": [{"key": "emmet_action_enabled.increment_number_by_1"}] },
  { "keys": ["alt+-"], "args": {"action": "decrement_number_by_1"}, "command": "run_emmet_action", "context": [{"key": "emmet_action_enabled.decrement_number_by_1"}] },
  { "keys": ["alt+shift+="], "args": {"action": "increment_number_by_10"}, "command": "run_emmet_action", "context": [{"key": "emmet_action_enabled.increment_number_by_10"}] },
  { "keys": ["alt+shift+-"], "args": {"action": "decrement_number_by_10"}, "command": "run_emmet_action", "context": [{"key": "emmet_action_enabled.decrement_number_by_10"}] },

  // Comments
  { "keys": ["ctrl+/"], "command": "toggle_comment", "args": { "block": false } },
  { "keys": ["ctrl+shift+/"], "command": "toggle_comment", "args": { "block": true } },

  // Hints
  { "keys": ["alt+d"], "command": "goto_definition" },
  { "keys": ["ctrl+shift+space"], "command": "code_intel_auto_complete" }, // ! requires SublimeCodeIntel !

  // Multiple Cursors
  { "keys": ["ctrl+up"], "command": "select_lines", "args": {"forward": false} },
  { "keys": ["ctrl+down"], "command": "select_lines", "args": {"forward": true} },

]</code></pre>
</aside>
<h2>VS Code vs. Sublime Text Conclusion</h2>
<p>It&#8217;s good to periodically assess the features of an editor that you <em>really</em> depend on. That was the inspiration for this comparison. I <em>am frustrated</em> with Sublime Text&#8217;s lack of innovation. Working with Visual Studio Code for a few days made me realize how awesome an editor can be. I want to move to it. Unfortunately, Microsoft is just not there yet. Visual Studio Code will likely be my editor of choice in the future. For now, Sublime Text lives on as my canvas for another day.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/visual-studio-code-vs-sublime-text/feed/</wfw:commentRss>
			<slash:comments>32</slash:comments>
		
		
			</item>
		<item>
		<title>Don&#8217;t Use Large Words When Small Words Will Do</title>
		<link>https://john-dugan.com/dont-use-large-words-when-small-words-will-do/</link>
					<comments>https://john-dugan.com/dont-use-large-words-when-small-words-will-do/#respond</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Fri, 04 Sep 2015 05:45:23 +0000</pubDate>
				<category><![CDATA[Marketing & Strategy]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2288</guid>

					<description><![CDATA[This post isn&#8217;t directed toward any specific experience I&#8217;ve recently had. It&#8217;s inspired by the communications I encounter as a human being every day. Typically, I write about web development. I document things that I encounter and [try to] explain them in a way that other developers can easily understand. After all, understanding is a &#8230; <a href="https://john-dugan.com/dont-use-large-words-when-small-words-will-do/" class="more-link">Continue reading <span class="screen-reader-text">Don&#8217;t Use Large Words When Small Words Will Do</span></a>]]></description>
										<content:encoded><![CDATA[<p>This post isn&#8217;t directed toward any specific experience I&#8217;ve recently had. It&#8217;s inspired by the communications I encounter as a human being every day.</p>
<p>Typically, I write about web development. I document things that I encounter and [try to] explain them in a way that other developers can easily understand. After all, understanding is a goal of any communication.</p>
<p>The funny thing is that people often seem to forget this. Ironically, marketers are the largest offenders, but other professionals are right up there too. I constantly see people use large words and long sentences to communicate simple messages.</p>
<p>To these offenders (including myself at times): be simple in your communications. Don&#8217;t increase cognitive load on recipients by using long sentences and large words when they aren&#8217;t necessary. Make the bridge between your message and the recipients&#8217; understanding as short as possible. Choose words wisely. Don&#8217;t use large words when small words will do.</p>
<p><code>// end rant</code></p>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/dont-use-large-words-when-small-words-will-do/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Fixed Headers With hash Links</title>
		<link>https://john-dugan.com/fixed-headers-with-hash-links/</link>
					<comments>https://john-dugan.com/fixed-headers-with-hash-links/#comments</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Wed, 26 Aug 2015 03:09:28 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2314</guid>

					<description><![CDATA[I was working on a site today that had several links in which the href attribute references an id or hash value on another page. The site has a fixed header, so I needed to way to offset the element referenced in the URL&#8217;s hash from the top of the page. Otherwise, some content would &#8230; <a href="https://john-dugan.com/fixed-headers-with-hash-links/" class="more-link">Continue reading <span class="screen-reader-text">Fixed Headers With <code>hash</code> Links</span></a>]]></description>
										<content:encoded><![CDATA[<p>I was working on a site today that had several links in which the <code>href</code> attribute references an <code>id</code> or <code>hash</code> value on another page. The site has a fixed header, so I needed to way to offset the element referenced in the URL&#8217;s <code>hash</code> from the top of the page. Otherwise, some content would be hidden behind the fixed header.</p>
<p>Solutions for this problem with in-page links have been thoroughly documented across the Web (mine is included at the <a href="#page-scroll-animation" data-animate="scroll">bottom of this post</a>). However, in the case of links that are <em>not</em> in-page, I found Uncle Google (ahem, StackOverlflow) to be lacking. My problem is with links that take the user to a new page. Specifically, I have a call to action whose <code>href</code> links to a contact page and includes the <code>hash</code> value of a form <code>id</code> on that page. The URL looks something like this: </p>
<pre><code class="prettyprint">&lt;a href="https://domain.com/contact#form"&gt;Contact Us&lt;/a&gt;</code></pre>
<p>When a user clicks the &#8220;Contact Us&#8221; link and the contact page loads, I need a way to grab the <code>hash</code> value from the URL that corresponds with the <code>form</code> element&#8217;s <code>id</code> and adjust the top offset accordingly. Otherwise, some form fields will be hidden behind the fixed header. This seems like something that would have been done 1,000 times over&hellip; Apparently not, at least judging by Google&#8217;s search results.</p>
<p>I spun my wheels for a bit trying to figure out an elegant way to solve the problem. Typically, I prefer to rely more on CSS than JavaScript for <abbr title="User Interface">UI</abbr> issues like this. What I came up with accomplishes that goal. My solution uses minimal JavaScript for <abbr title="Document Object Model">DOM</abbr> manipulation and relies on CSS to do the visual lifting. </p>
<p>Below, the solution to my fixed header dilemma is provided in in two flavors: jQuery and vanilla JavaScript. <abbr title="For what it's worth">FWIW</abbr>, even though the site I am working on uses jQuery, I opted for the vanilla JavaScript solution.</p>
<h2>Fixed Header jQuery Solution</h2>
<p class="subheading"><small class="disclaimer">Link to an element on another page and account for a fixed header offset using jQuery.</small></p>
<pre class="margin-bottom--hero"><code class="prettyprint linenums">if ( window.location.hash ) {
    var hash = window.location.hash,
        $hash = $(hash);

    $hash.removeAttr('id');
    $hash.before('&lt;div id="'+hash.slice(1)+'" class="hashlink"&gt;&lt;/div&gt;');
    window.location.hash = hash;
}</code></pre>
<h2>Fixed Header <span class="disclaimer">[vanilla]</span> JavaScript Solution</h2>
<p class="subheading"><small class="disclaimer">Link to an element on another page and account for a fixed header offset using vanilla JavaScript.</small></p>
<pre class="margin-bottom--hero"><code class="prettyprint linenums">if ( window.location.hash ) {
    var hash = window.location.hash,
        id   = hash.slice(1),
        elem = document.getElementById(id),
        hashlink = '&lt;div id='+id+' class="hashlink"&gt;&lt;/div&gt;';

    elem.removeAttribute('id');
    elem.insertAdjacentHTML('beforebegin', hashlink);
    window.location.hash = hash;
}</code></pre>
<p>In both examples you can see that I first check if the URL contains a <code>hash</code> value on line 1. Following that, variables are created to store the <code>hash</code> value, as well as the html that needs to be added. The critical thing to understand is on line 6 of the jQuery example and line 8 of the vanilla JavaScript example, where a new element is added to the DOM.</p>
<p>The line that immediately follows the DOM insertion in both examples updates the <code>window.location.hash</code> value with the new element&#8217;s <code>id</code> (which retains the same value of the <code>hash</code> that was originally linked to). This forces the browser to jump to the new element, on which we have a <code>hashlink</code> class that can be styled with CSS. My styles for that class look like this:</p>
<pre><code class="prettyprint">.hashlink {
    height: $header-height;
    margin-top: -$header-height;
    visibility: hidden;
}</code></pre>
<p>Because I am handling UI updates with CSS (Sass in this case), I can reference the variable that holds the height value of my fixed header. Should I need to, I can also account for style changes in media queries. Huge win.</p>
<h2>In-Page Link Scrolling Animation</h2>
<p>Below is how I handle in-page links with JavaScript scrolling animations. The commented out lines are for sites that use Velocity.js, a <a href="http://julian.com/research/velocity/">high-performance JavaScript animation library</a>.</p>
<pre id="page-scroll-animation"><code class="prettyprint">// In-Page Scroll Animation
// ------------------------
$('a[href^="#"]').on('click', function(e) {
    var hash  = this.hash,
    	$hash = $(hash),
        addHash = function() {
            window.location.hash = hash;
        };

    if ( hash !== '#header' ) {
        // $hash.velocity('scroll', { duration: 500, offset: -50, complete: addHash }); // Velocity.js
        $('html,body').animate({ 'scrollTop': $hash.offset().top -50 }, 500, addHash);
    } else {
        // $hash.velocity('scroll', { duration: 500, offset: 0, complete: addHash }); // Velocity.js
        $('html,body').animate({ 'scrollTop': $hash.offset().top }, 500, addHash);
    }
    e.preventDefault();
});</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/fixed-headers-with-hash-links/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Four Rules to Define this in JavaScript</title>
		<link>https://john-dugan.com/this-in-javascript/</link>
					<comments>https://john-dugan.com/this-in-javascript/#comments</comments>
		
		<dc:creator><![CDATA[John Dugan]]></dc:creator>
		<pubDate>Fri, 10 Jul 2015 15:29:54 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://john-dugan.com/?p=2254</guid>

					<description><![CDATA[Understanding how this works in JavaScript is fairly simple. Knowing what this points to however&#8230; that is much more difficult. Scope and context become important concepts to understand. Knowing exactly what this points to and why within each function/method in your JavaScript code can be utterly confusing. Hopefully the rules and corresponding examples below provide &#8230; <a href="https://john-dugan.com/this-in-javascript/" class="more-link">Continue reading <span class="screen-reader-text">Four Rules to Define <code>this</code> in JavaScript</span></a>]]></description>
										<content:encoded><![CDATA[<p>Understanding how <code>this</code> works in JavaScript is fairly simple. Knowing what <code>this</code> points to however&hellip; that is <em>much</em> more difficult. Scope and context become important concepts to understand. Knowing exactly what <code>this</code> points to and <em>why</em> within each function/method in your JavaScript code can be utterly confusing. Hopefully the rules and corresponding examples below provide clarity on <code>this</code>.</p>
<div class="callout--primary">
<p><abbr title="Too long; didn't read.">TL;DR</abbr> &mdash; The four rules presented for determining what <code>this</code> in JavaScript points to boil down to one simple question: <strong>What is the calling object?</strong></p>
<p><strong>Precedence of the four rules:</strong><br /><small class="disclaimer">(The JavaScript interpreter will ask in this order)</small></p>
<ol>
<li>Is the function called by <code>new</code>?</li>
<li>Is the function called by <code>call()</code>, <code>apply()</code>, or <code>bind()</code>? </li>
<li>Is the function called as a method, ie: <code>obj.func()</code>?</li>
<li>
<p class="margin--none">Is the function called in the global scope?</p>
<ul class="margin-top--none">
<li>If strict mode is enabled, return <code>undefined</code>.</li>
<li>Otherwise, return the global object, ie: <code>window</code>.</li>
</ul>
</li>
</ol>
</div>
<blockquote>
<p>In JavaScript functions don&#8217;t know where they live. They only know how they are called.</p>
<p><cite>Alexis Abril, <a href="https://frontendmasters.com/courses/javascript-jquery-dom/">Advanced JS Fundamentals to jQuery &#038; Pure DOM Scripting</a> (What is &#8220;this&#8221;: 9:09&ndash;9:13)</cite></p>
</blockquote>
<ol class="list-style--numbers">
<li id="rule1" class="margin-bottom--hero">
<h2 class="heading--h3">Whenever a function is contained in the global scope, the value of <code>this</code> inside of that function will be the <code>window</code> object.</h2>
<pre><code class="prettyprint">// Basic Function
// --------------
function greetMe(name) {
    console.log('Hello ' + name);
    console.log(this);
}

greetMe('John');</code></pre>
<figure class="entry__figure aligncenter lightbox--img"><a data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule1.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule1.png" alt="Screenshot of console output from this in JavaScript rule 1 example" width="949" height="198" class="aligncenter size-full wp-image-2276" srcset="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule1.png 949w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule1-150x31.png 150w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule1-400x83.png 400w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule1-685x143.png 685w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule1-794x166.png 794w" sizes="(max-width: 949px) 100vw, 949px" /></a></figure>
<p>Functions within the global scope are in fact methods on the <code>window</code> object. So, calling <code>greetMe('john');</code> is no different than calling <code>window.greetMe('john');</code> Therefore, <code>this</code> inside of the <code>greetMe</code> function points to <code>window</code>.</p>
</li>
<li id="rule2" class="margin-bottom--hero">
<h2 class="heading--h3">Whenever a function is called by a preceding dot, the object before that dot is <code>this</code>.</h2>
<pre><code class="prettyprint">// Object Method
// -------------
var greetMe = {
    greeting: 'Hello ',
    speak: function(name) {
        console.log(this.greeting + name);
        console.log(this);
    }
}

greetMe.speak('John');</code></pre>
<figure class="entry__figure aligncenter lightbox--img"><a data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2a.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2a.png" alt="Screenshot of console output from this in JavaScript rule 2 example" width="946" height="252" class="aligncenter size-full wp-image-2278" srcset="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2a.png 946w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2a-150x40.png 150w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2a-400x107.png 400w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2a-685x182.png 685w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2a-794x212.png 794w" sizes="(max-width: 946px) 100vw, 946px" /></a></figure>
<p>This example is similar to what we saw above with <code>window.greetMe</code>. Here, instead of <code>window</code> we have the <code>greetMe</code> object on the left of the dot. Therefore, <code>this</code> inside of the <code>speak</code> method points to <code>greetMe</code>.</p>
<pre><code class="prettyprint">// Method Assignment
// -----------------
var greeting = 'Salutations ',
    greet = greetMe.speak;

greet('John');</code></pre>
<figure class="entry__figure aligncenter lightbox--img"><a data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2b.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2b.png" alt="Screenshot of console output from this in JavaScript rule 2 example" width="949" height="161" class="aligncenter size-full wp-image-2279" srcset="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2b.png 949w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2b-150x25.png 150w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2b-400x68.png 400w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2b-685x116.png 685w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule2b-794x135.png 794w" sizes="(max-width: 949px) 100vw, 949px" /></a></figure>
<p>While this example appears to break <a href="#rule2" data-animate="scroll">rule 2</a>, it doesn&#8217;t because it actually applies to <a href="#rule1" data-animate="scroll">rule 1</a>. In this example, we establish two global variables: <code>greeting</code> and <code>greet</code>. Remember, since these variables are declared in the global scope, they are actually just properties on the <code>window</code> object. Therefore, when <code>greet</code> is called, while it points to the <code>greetMe.speak</code> method, it is executed in the context of the <code>window</code> object. It would be as if you executed <code>window.greet('John');</code>. Therefore, <code>this</code> inside of the <code>greet</code> function points to <code>window</code>.</p>
</li>
<li id="rule3" class="margin-bottom--hero">
<h2 class="heading--h3">Whenever a constructor function is used, <code>this</code> refers to the specific instance of the object that is created and returned by the constructor function.</h2>
<pre><code class="prettyprint">// Constructor Function
// --------------------
function GreetMe(name) {
    this.greeting = 'Hello ';
    this.name = name;
    this.speak = function() {
        console.log(this.greeting + this.name);
        console.log(this);
    }
};

var greetJohn = new GreetMe('John');
var greetJane = new GreetMe('Jane');

greetJohn.speak();
greetJane.speak();</code></pre>
<figure class="entry__figure aligncenter lightbox--img"><a data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3a.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3a.png" alt="Screenshot of console output from this in JavaScript rule 3 example" width="949" height="390" class="aligncenter size-full wp-image-2281" srcset="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3a.png 949w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3a-150x62.png 150w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3a-400x164.png 400w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3a-685x282.png 685w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3a-794x326.png 794w" sizes="(max-width: 949px) 100vw, 949px" /></a></figure>
<p>In the example above, both the <code>greetJohn</code> and <code>greetJane</code> variables are assigned a unique object returned by the <code>GreetMe</code> constructor function. Therefore, <code>this</code> inside of the <code>speak</code> method points to the unique <code>GreetMe</code> object instance stored in the variable on which the <code>speak</code> method is being called. This is evident by looking at the <code>name</code> property on the <code>GreetMe</code> object.</p>
<aside class="callout--neutral">
<p><em>The <code>new</code> keyword in JavaScript makes a standard function in to a <em>constructor function</em>. It does several other things as well, detailed at the top of my post on <a href="https://john-dugan.com/object-oriented-javascript-pattern-comparison/">object oriented JavaScript patterns</a>.</em></p>
</aside>
<pre><code class="prettyprint">// Constructor Function Prototype Method
// -------------------------------------
GreetMe.prototype.sayGoodbye = function() {
    console.log('Goodbye ' + this.name);
    console.log(this);
};

greetJohn.sayGoodbye();
greetJane.sayGoodbye();</code></pre>
<figure class="entry__figure aligncenter lightbox--img"><a data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3b.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3b.png" alt="Screenshot of console output from this in JavaScript rule 3 example" width="947" height="264" class="aligncenter size-full wp-image-2283" srcset="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3b.png 947w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3b-150x42.png 150w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3b-400x112.png 400w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3b-685x191.png 685w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule3b-794x221.png 794w" sizes="(max-width: 947px) 100vw, 947px" /></a></figure>
<p>This example is similar to the previous. The difference is that instead of a method being called that exists directly on the object instance, the method is called from the constructor function&#8217;s prototype. However, the context of <code>this</code> does not change &dash; it still points to the unique <code>GreetMe</code> object stored in the variable on which the <code>sayGoodbye</code> method is being called.</p>
</li>
<li id="rule4">
<h2 class="heading--h3">Whenever JavaScript&#8217;s <code>call</code> or <code>apply</code> method is used, <code>this</code> is explicitly defined.</h2>
<pre><code class="prettyprint">// Using call/apply
// ----------------
greetJohn.sayGoodbye.call(greetJane);
greetJane.sayGoodbye.apply(greetJohn);</code></pre>
<figure class="entry__figure aligncenter lightbox--img"><a data-effect="mfp-zoom-in" title="Enlarge image" class="mfp-zoom" href="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule4.png"><img loading="lazy" src="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule4.png" alt="Screenshot of console output from this in JavaScript rule 4 example" width="949" height="173" class="aligncenter size-full wp-image-2284" srcset="https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule4.png 949w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule4-150x27.png 150w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule4-400x73.png 400w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule4-685x125.png 685w, https://john-dugan.com/wp-content/uploads/2015/07/this-in-javascript-rule4-794x145.png 794w" sizes="(max-width: 949px) 100vw, 949px" /></a></figure>
<p>JavaScript&#8217;s <code>call</code> and <code>apply</code> methods allow you to execute a function in a different context. The first argument passed to either of these methods explicitly sets what <code>this</code> points to. Because <code>call</code> and <code>apply</code> are explicit, they present the clearest case of what <code>this</code> points to. This is evident by looking at the <code>name</code> property logged to the console by each invocation of the <code>sayGoodbye</code> method.</p>
</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://john-dugan.com/this-in-javascript/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
