{"version":"https://jsonfeed.org/version/1","title":"Aaron Gustafson: Content tagged ExpressionEngine","description":"The latest 20 posts and links tagged ExpressionEngine.","home_page_url":"https://www.aaron-gustafson.com","feed_url":"https://www.aaron-gustafson.com/feeds/expressionengine.json","author":{"name":"Aaron Gustafson","url":"https://www.aaron-gustafson.com"},"icon":"https://www.aaron-gustafson.com/i/og-logo.png","favicon":"https://www.aaron-gustafson.com/favicon.png","expired":false,"items":[{"id":"https://www.aaron-gustafson.com/notebook/adaptive-images-in-expressionengine-with-ce-image/","title":"✍🏻 Adaptive Images in ExpressionEngine with CE Image","summary":"With browser implementations now available and a rock-solid set of implementation choices, we’ve begun implementing responsive images in every new project. Here’s how we did it for a recent ExpressionEngine build using the CE Image add-on.","content_html":"<p>One of the biggest headaches of responsive design has been dealing with images. Thankfully our work on the <a href=\"http://ricg.io\">Responsive <del>Images</del> <ins>Issues</ins> Community Group</a> has resulted in a rock-solid set of elements and attributes to address all of your adaptive image needs. My company, <a href=\"http://easy-designs.net\">Easy Designs</a>, recently redesigned <a href=\"http://www.nichols.edu\">Nichols College’s website</a> and that project just happened to coincide adaptive images landing in <a href=\"http://www.chromium.org/blink\">Blink</a> (the rendering engine that powers Chrome and Opera). Naturally, we jumped at the opportunity to use them.</p>\n<p>Most Nichols College sites run on <a href=\"http://ellislabs.com/expressionengine\">EllisLab’s ExpressionEngine</a>, a solid little workhorse of a CMS we’ve been using for years. We love it because it gives us complete control over the markup it generates. Now EE offers some pretty decent file management and image manipulation utilities out of the box, but the options it provides were not enough to handle our adaptive image needs; we needed backup. <a href=\"http://www.causingeffect.com/software/expressionengine/ce-image\">Causing Effect’s CE Image</a> add-on is reasonably priced and offered exactly the functionality we needed to make our adaptive image dreams a reality.</p>\n<p>I won’t bore you with how to set up CE Image as there is <a href=\"http://www.causingeffect.com/software/expressionengine/ce-image/user-guide\">documentation on that</a>, but I will walk you through two different responsive image use-cases we had and how we addressed them using this add-on.</p>\n<h2 id=\"header-images\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#header-images\" aria-hidden=\"true\">#</a> Header images</h2>\n<p>The first use case we had was a series of large, focal images. You can find different examples of them on <a href=\"http://www.nichols.edu\">the homepage</a> and landing pages (like <a href=\"http://www.nichols.edu/admissions/\">this one for Admissions</a>). The first pass on making these images adaptive involved the <code>picture</code> element for which <a href=\"https://html.spec.whatwg.org/multipage/embedded-content.html#adaptive-images\">the spec</a> is known. The markup we were generating was based on the pattern outlined for <a href=\"http://scottjehl.github.io/picturefill/\">Picturefill</a>, a JavaScript polyfill that implements adaptive images in browsers that don’t:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>picture</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>page__image-header__photo<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token comment\">&lt;!--[if IE 9]>&lt;video style=\"display: none;\">&lt;![endif]--></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>source</span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>about_940_343_int_s_c1_full.jpg<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">media</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>(min-width: 40em)<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>source</span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>about_800_350_int_c1_medium.jpg<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">media</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>(min-width: 20em)<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>source</span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>about_480_350_int_c1_small.jpg<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n  <span class=\"token comment\">&lt;!--[if IE 9]>&lt;/video>&lt;![endif]--></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{made}<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>picture</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>To get to that point, however, we needed to use CE Image to generate (and cache) the specific sizes we needed:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>picture</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>page__image-header__photo<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token comment\">&lt;!--[if IE 9]>&lt;video style=\"display: none;\">&lt;![endif]--></span>\n  {exp:ce_img:pair src=\"{content_focal_image}\" filename_suffix=\"_full\"\n  width=\"940\" allow_scale_larger=\"yes\" crop=\"yes\" interlace=\"yes\" cache_dir=\"/\"\n  }\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>source</span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{made}<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">media</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>(min-width: 40em)<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n  {/exp:ce_img:pair} {exp:ce_img:pair src=\"{content_focal_image}\"\n  filename_suffix=\"_medium\" width=\"800\" height=\"600\" crop=\"yes\" interlace=\"yes\"\n  cache_dir=\"/\" }\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>source</span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{made}<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">media</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>(min-width: 20em)<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n  {/exp:ce_img:pair} {exp:ce_img:pair src=\"{content_focal_image}\"\n  filename_suffix=\"_small\" width=\"480\" height=\"360\" crop=\"yes\" interlace=\"yes\"\n  cache_dir=\"/\" }\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>source</span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{made}<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n  <span class=\"token comment\">&lt;!--[if IE 9]>&lt;/video>&lt;![endif]--></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{made}<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n  {/exp:ce_img:pair}\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>picture</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>Not what’s a lot of code, so let’s just look at one segment of that jumble:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\">{exp:ce_img:pair src=\"{content_focal_image}\" filename_suffix=\"_full\" width=\"940\"\nallow_scale_larger=\"yes\" crop=\"yes\" interlace=\"yes\" cache_dir=\"/\" }\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>source</span> <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{made}<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">media</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>(min-width: 40em)<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n{/exp:ce_img:pair}</code></pre>\n<p>This is an example using CE Image’s tag pair option, which lets you control the markup output. In the opening tag, we set several properties:</p>\n<ul>\n<li><code>src</code> is the path to the original image uploaded by content authors;</li>\n<li><code>filename_suffix</code> is the suffix we want added to the cached file to differentiate it from others in the cache (and make the files more easily scannable);</li>\n<li><code>width</code> is our desired output width for the generated image;</li>\n<li><code>allow_scale_larger</code> does exactly what you’d expect: it dictates whether or not CE Image should scale the image to reach the desired width;</li>\n<li><code>crop</code> tells CE Image whether it’s okay to crop the image;</li>\n<li><code>interlace</code> tells CE Image to use image interlacing (which can speed load time); and</li>\n<li><code>cache_dir</code> tells CE Image where to store the cached image (in relation to our global configuration)</li>\n</ul>\n<p>Then, within the tag pair is the <code>source</code> element with the <code>srcset</code> value set to the path to the file CE Image generated (referenced by the <code>made</code> variable) and the associated media query.</p>\n<p>Multiply that a few times for the different sizes and you have the full <code>picture</code> element.</p>\n<p>Now that’s all well and good, but shortly after launch, <a href=\"http://ericportis.com/\">Eric Portis</a> wrote <a href=\"http://ericportis.com/posts/2014/srcset-sizes/\">an amazing post explaining how the <code>srcset</code> and <code>sizes</code> attributes operate</a> and it cleared up a lot of my confusion on the matter. He convinced me that the age-old <code>img</code> element, with these new attributes, would be far more maintainable. With a fire in my belly, I rewrote the markup:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\">&lt;img class=\"page__image-header__photo\" alt=\"\"\n    {exp:ce_img:pair\n        src=\"{embed:image}\"\n        filename_suffix=\"_small\"\n        width=\"480\"\n        height=\"320\"\n        crop=\"yes\"\n        interlace=\"yes\"\n        cache_dir=\"/\"\n        }\n        src=\"{made}\"\n        srcset=\"{made} 480w,\n    {/exp:ce_img:pair}\n    {exp:ce_img:pair\n        src=\"{embed:image}\"\n        filename_suffix=\"_medium\"\n        width=\"800\"\n        height=\"600\"\n        crop=\"yes\"\n        interlace=\"yes\"\n        cache_dir=\"/\"\n        }\n        {made} 800w,\n    {/exp:ce_img:pair}\n    {exp:ce_img:pair\n        src=\"{embed:image}\"\n        filename_suffix=\"_full\"\n        width=\"940\"\n        allow_scale_larger=\"yes\"\n        crop=\"yes\"\n        interlace=\"yes\"\n        cache_dir=\"/\"\n        }\n        {made} 940w\"\n    {/exp:ce_img:pair}\n    ></code></pre>\n<p>The CE Image behavior is exactly the same, but the resulting markup is much clearer:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span>\n  <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>page__image-header__photo<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>about_480_320_int_c1_small.jpg<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>\n    about_480_320_int_c1_small.jpg  480w,\n    about_800_350_int_c1_medium.jpg 800w,\n    about_940_343_int_s_c1_full.jpg 940w\n  <span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">/></span></span></code></pre>\n<p>The added bonus of this approach is that I am not hard-coding any media queries and the browser gets to make the ultimate decision of which image to request. All I am doing is telling the browser the image options and their respective widths within the <code>srcset</code> attribute. As all of the images take up 100% of their containers, I didn’t even need to use the <code>sizes</code> attribute. Easy peasy.</p>\n<h2 id=\"%E2%80%9Cnice-to-have%E2%80%9D-images\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#%E2%80%9Cnice-to-have%E2%80%9D-images\" aria-hidden=\"true\">#</a> “Nice to Have” Images</h2>\n<p>Not every image adds something to the page. Some are purely optional, a visual enhancement. In order to reduce the size of pages on smaller screens, we often choose to “lazy load” certain image assets after page load, when we know there is enough room to display the image or when we feel it would be an enhancement to the design.</p>\n<p>Now some of you might be wondering: <em>Why not just <code>display:none</code> below a certain threshold?</em> Well, I’ll tell you: images that are hidden with CSS are still requested by the browser. That means users who don’t see the images are still paying to download them (whether in terms of time waiting for the page to render or actual money on a metered connection). That kinda sucks for them. We should show our users a bit more respect and only request the images when we need them.</p>\n<p>We wrote <a href=\"https://github.com/easy-designs/easy-lazy-images.js\">a lazy-loading image script</a> a few years back and have battle tested it on numerous sites to great success. It’s all based on a simple markup pattern:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span>\n  <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>module__image image--lazy<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-image-src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Tim-Smith_220x140_220_140_int_c1.jpg<span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>The <code>data-img-src</code> attribute defines the path to the “nice to have” image and then the JavaScript adds the image element into the page when the appropriate conditions are met:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span>\n  <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>module__image image--lazy<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-image-src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Tim-Smith_220x140_220_140_int_c1.jpg<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-image-loaded</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Tim-Smith_220x140_220_140_int_c1.jpg<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>Pretty simple. It even supports <code>srcset</code>:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span>\n  <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>module__image image--lazy<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-image</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>about_480_320_int_c1_small.jpg<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-image-srcset</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>about_480_320_int_c1_small.jpg 480w,\n                      about_800_350_int_c1_medium.jpg 800w,\n                      about_940_343_int_s_c1_full.jpg 940w<span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>The <a href=\"https://github.com/easy-designs/easy-lazy-images.js#usage\">full documentation is up on Github</a>.</p>\n<p>Implementing this in the context of CE Image was a breeze and builds on the <code>source</code> pattern I showed earlier:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\">{if testimonial_photo} {exp:ce_img:pair src=\"{testimonial_photo}\" width=\"223\"\nheight=\"140\" allow_scale_larger=\"yes\" crop=\"yes\" interlace=\"yes\" cache_dir=\"/\" }\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>module__image image--lazy<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">data-image-src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{made}<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n{/exp:ce_img:pair} {/if}</code></pre>\n<p>We are only just beginning to scratch the surface of what’s possible with adaptive images and I am sure we will come up with newer, better ways to do this stuff. Heck, there may even be an adaptive images add-on in the pipeline for ExpressionEngine. But, in the meantime, if you are trying to implement adaptive images with ExpressionEngine, CE Image is a good way to go.</p>\n","url":"https://www.aaron-gustafson.com/notebook/adaptive-images-in-expressionengine-with-ce-image/","tags":["web design","responsive web design","ExpressionEngine","progressive enhancement"],"date_published":"2014-11-21T23:18:23Z"},{"id":"https://www.aaron-gustafson.com/notebook/jail-ing-images-in-expressionengine/","title":"✍🏻 JAIL-ing images in ExpressionEngine","summary":"A while back I came across a link to Sebastiano Armeli-Battana’s jQuery Asynchronous Image Loader ( JAIL ) and filed it away to revisit when I had some time. I finally made some time this weekend.","content_html":"<p>\n\tA while back I came across a link to <a href=\"https://github.com/sebarmeli/JAIL\">Sebastiano Armeli-Battana’s jQuery Asynchronous Image Loader</a> (JAIL) and filed it away to revisit when I had some time. I finally made some time this weekend.</p>\n<p>\nJAIL’s a cool little script that takes care of lazy loading images for you in order to speed up initial page rendering. To use it, you implement the following markup pattern:</p>\n```html\n  <img class=\"jail\" src=\"blank.gif\" data-src=\"foo.png\" alt=\"\"/>\n  <noscript>\n   <img src=\"foo.png\" alt=\"\"/>\n  <noscript>\n```\n<p>\n\tThis is pretty ingenious actually. Without JS, the actual image is served up, but with JavaScript, the blank image is displayed until JAIL lazy loads the real image path stored in the <code>data-src</code> attribute. You initialize JAIL like this:</p>\n```js\n  $(function(){\n   $('img.jail').jail();\n  });\n```\n<p>\n\tSimple, right? Well, yes and no.</p>\n<p>\n\tOn a site that isn’t updated frequently and where a skilled front-end coder is involved, this is cake. That, however, is seldom the reality. Heck, even on this blog, remembering to use that pattern while authoring content in the backend is not terribly likely. I needed a way to make it easier. So I <a href=\"https://github.com/easy-designs/easy_jail.ee_addon\">automated JAIL as an ExpressionEngine plug-in</a>.</p>\n<p>\n\tWith this plug-in I can automatically enable (or remove) JAIL at the template level with a simple tag pair: <code>exp:easy_jail:prep</code></p>\n```html\n  {exp:easy_jail:prep}\n    {body}\n  {/exp:easy_jail:prep}\n```\n<p>\n\tThe plugin will hunt for any image elements inside the tag pair and convert them to use the JAIL markup pattern. By default, it uses a base-64 encoded representation of a blank GIF (a.k.a. a <a href=\"https://en.wikipedia.org/wiki/Data_URI_scheme\">Data URI</a>) to reduce the number of requests, but you can override that with the path to your own image (or a different Data URI) using the <code>blank_img</code> property. You can also customize the <code>class</code> used for the blank image using the <code>class_name</code> property.</p>\n```html\n  {exp:easy_jail:prep blank_img=\"/i/blank.gif\" class_name=\"my_class\"}\n    {body}\n  {/exp:easy_jail:prep}\n```\n<p>\n\tThen it’s just a matter of including the JAIL JavaScript code and executing it. You can, of course, include Sebastiano’s script and your JAIL config in your own JavaScript build, but the plug-in also includes a convenience function to drop it in for you. Simply add the <code>exp:easy_jail:js</code> tag before the close of the <code>body</code> element (after jQuery of course):</p>\n```html\n  <script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js\"></script>\n  <script>window.jQuery || document.write('<script src=\"/j/jquery.js\"><\\/script>')</script>\n  {exp:easy_jail:js}\n```\n<p>\n\tAs with the <code>exp:easy_jail:prep</code> tag, you can customize the JavaScript output using the <code>class_name</code> property to tell JAIL what to lazy load. You can also customize the JAIL configuraiton using the <code>config</code> property. Just pass in a valid JSON object describing the configuration you want. JAIL is pretty darn configurable. There are a ton of options available, but the most intriguing to me currently is <code>offset</code>. We’re using it here on the blog to load images when you scroll to within 300px of the top of the image. Here’s how you’d do that using the plug-in:</p>\n```html\n  <script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js\"></script>\n  <script>window.jQuery || document.write('<script src=\"/j/jquery.js\"><\\/script>')</script>\n  {exp:easy_jail:js config=\"{offset:300}\"}\n```\n<p>\n\tAnd there you have it. Simple, lazy loaded images without having to train content editors to author the relatively complex markup pattern. If you want to have a play, feel free to <a href=\"https://github.com/easy-designs/easy_jail.ee_addon\">grab the code from Github</a> or <a href=\"https://github.com/easy-designs/easy_jail.ee_addon/fork\">you can fork it and help us to make it even more useful</a>.</p>\n","url":"https://www.aaron-gustafson.com/notebook/jail-ing-images-in-expressionengine/","tags":["performance","images","ExpressionEngine"],"date_published":"2013-07-22T18:04:00Z"},{"id":"https://www.aaron-gustafson.com/appearances/podcasts/2012-02-23-progressive-enhancement/","title":"🎧 Progressive Enhancement","content_html":"<p>Lea Alcantara, Emily Lewis, and I talked about progressive enhancement, ExpressionEngine &amp; more.</p>\n","url":"http://ctrlclickcast.com/episodes/progressive-enhancement","tags":["progressive enhancement","ExpressionEngine"],"date_published":"2012-02-23T00:00:00Z"},{"id":"https://www.aaron-gustafson.com/notebook/progressive-enhancement-and-expressionengine/","title":"✍🏻 Progressive Enhancement and ExpressionEngine","summary":"This past week was a bit of a whirlwind as Kelly and I flew to DC for a few meetings and then to NYC for the ExpressionEngine CodeIgniter Conference . We had a blast at the conference, meeting new people, seeing old friends, and eating…","content_html":"<p>\n\tThis past week was a bit of a whirlwind as Kelly and I flew to DC for a few meetings and then to NYC for <a href=\"http://eeciconf.com\">the ExpressionEngine CodeIgniter Conference</a>. We had a blast at the conference, meeting new people, seeing old friends, and eating a ton of great food. While we were there, we got name-dropped by the affable <a href=\"http://ellislab.com/company/team/leslie_camacho/\">EllisLab CEO, Leslie Comacho</a> in his keynote address for our work on the forthcoming native rich text editor for ExpressionEngine and we also met up with the always charming <a href=\"http://adactio.com\">Jeremy Keith</a> (and the lovely <a href=\"http://lostintranslation.com\">Jessica Spengler</a>) to hatch some <a href=\"http://retreats4geeks.com\">R4G</a> plans that will be unveiled in the next week or so.</p>\n<p>\n\tThe best part for me, though, was getting to talk about progressive enhancement. The conference organizer, <a href=\"http://twitter.com/roberteerhart\">Robert Eerhart</a>, gave me an hour to advocate on behalf of users and I made the most of that time by delving into the ways and means of progressive enhancement and how it can be accomplished in ExpessionEngine (and, to a lesser extent, CodeIgniter). I got tons of great questions from the audience and had many lively discussions after stepping off the stage as well. It was really nice to see so many people getting excited about a topic about which I’m incredibly passionate.</p>\n<p>\n\tI’ve <a href=\"http://www.slideshare.net/AaronGustafson/progressive-eenhancement-eeci-2011\">posted my slides to SlideShare</a>. If you were able to make the presentation, these will hopefully help jog your memory when it comes to the techniques I discussed, but if you couldn’t make the show, they’re also up for your enjoyment.</p>\n<figure class=\"video-embed video-embed--16x9\"><iframe class=\"video-embed__video\" src=\"http://www.slideshare.net/slideshow/embed_code/9812085?rel=0\" frameborder=\"0\"></iframe></figure>\n<p>\n\tI’d like to thank everyone who made EECI2011 so amazing and I’d like to give a special thank you to everyone who picked up a copy of my book while we were there. And if you missed out on getting a copy, you can pick one up over on <a href=\"http://easy-readers.net\">the Easy Readers site</a>. I’ll be happy to sign it for you if you reply to the receipt email and let the team know you missed out on picking up a copy at the event.</p>\n<p>\n\tThanks again and I look forward to seeing you all again next year!</p>\n","url":"https://www.aaron-gustafson.com/notebook/progressive-enhancement-and-expressionengine/","tags":["progressive enhancement","ExpressionEngine","presentations"],"date_published":"2011-10-25T13:17:00Z"},{"id":"https://www.aaron-gustafson.com/notebook/template-based-asset-munging-in-expressionengine/","title":"✍🏻 Template-based Asset Munging in ExpressionEngine","summary":"In our years of working with ExpressionEngine, we’ve tweaked our standard setup quite a few times. We generally handle most every asset, including CSS and JavaScript, as a template. Being a bit obsessed with organization and overall…","content_html":"<p>In our years of working with ExpressionEngine, we’ve tweaked our standard setup quite a few times. We generally handle most every asset, including CSS and JavaScript, as a template. Being a bit obsessed with organization and overall maintainability of code, we separate out our styles and scripts into separate templates for each major concern (e.g. typography, color, screen layout, etc.).</p>\n<figure><img alt=\"\" src=\"/i/posts/2010-07-11/2010-07-11-style-templates.png\"/></figure>\n<p>A while back, it was not uncommon for us to include each of these assets into the document separately, but, as website optimization and performance folks will tell you, all of that separation leads to a lot of additional overhead because the browser must request each of those files individually. In the interest of streamlining the download process, we decided to merge all of the stylesheets together at the template level before sending them over the wire. Here’s the simple recipe we devised:</p>\n```css\n  /* ———————————\n   * Core Stylesheet\n   * Created by Easy! Designs, LLC\n   * http://easy-designs.net\n   * ——————————— */\n<p embed=\"styles/reset\"></p>\n<p embed=\"styles/typography\"></p>\n<p>@media screen {\n{embed=“styles/layout-screen”}\n}</p>\n<p>@media print {\n{embed=“styles/layout-print”}\n}</p>\n<p embed=\"styles/color\"></p>\n<p embed=\"styles/effects\"></p>\n<pre><code>&lt;p&gt;This framework allows us to pull in each template in the optimum way for progressive enhancement with only a single download on the user end, which is much faster. And server-side caching only adds to the speed improvements. Beyond that, we can continue to add new &lt;code class=&quot;css&quot;&gt;@media&lt;/code&gt; blocks (including media queries) as necessary either within the embedded files or in this master one.&lt;/p&gt;\n&lt;p&gt;We use a similar setup for our JavaScript:&lt;/p&gt;\n```js\n  {embed=&quot;javascripts/jquery.FunctionHandler&quot;}\n  {embed=&quot;javascripts/jquery.hoverIntent&quot;}\n  {embed=&quot;javascripts/eCSStender&quot;}\n  \n  /* Individual page handlers go here */\n</code></pre>\n<p>In this particular example, we’re including two jQuery plugins: <a href=\"http://github.com/easy-designs/FunctionHandler.js\">FunctionHandler</a> and <a href=\"http://cherne.net/brian/resources/jquery.hoverIntent.html\">hoverIntent</a>, along with <a href=\"http://eCSStender.org\">eCSStender</a> before adding our <a href=\"/notebook/a-new-onload-scheme/\">page-specific code in FunctionHandler registrations</a>. (jQuery itself is loaded in from Google.)</p>\n<p>Using ExpressionEngine’s template system to manage the munging like this is dead simple and (from our experience evaluating other people’s EE setups) often underused. Give it a shot on your next project.</p>\n","url":"https://www.aaron-gustafson.com/notebook/template-based-asset-munging-in-expressionengine/","tags":["performance","ExpressionEngine","CSS","JavaScript"],"date_published":"2010-07-11T12:28:47Z"},{"id":"https://www.aaron-gustafson.com/notebook/counting-the-results-of-a-nested-query-in-expressionengine/","title":"✍🏻 EE Tip: Counting the results of a nested query","summary":"If you’ve built anything remotely challenging in ExpressionEngine, you’ve no doubt discovered things that are easier done in native PHP than in EE tags. A lot of it has to do with how ExpressionEngine parses templates and what gets…","content_html":"<p>If you’ve built anything remotely challenging in ExpressionEngine, you’ve no doubt discovered things that are easier done in native PHP than in EE tags. A lot of it has to do with how ExpressionEngine parses templates and what gets parsed first.</p>\n<p>One recent bugbear I ran into was trying to use the <code class=\"ee\">{count}</code> <span class=\"initial quote\">“</span>magic” variable from a call to <code class=\"ee\">{exp:query}</code> that resided inside a <code class=\"ee\"></code> loop. I needed the <code class=\"ee\">{entry_id}</code> from the entry in the SQL statement, but <code class=\"ee\">{count}</code> (despite being used inside <code class=\"ee\">{exp:query}</code>) was evaluating as the <code class=\"ee\"></code> count and not the <code class=\"ee\">{exp:query}</code> count. To solve the issue, I came up with the following:</p>\n<script src=\"https://gist.github.com/aarongustafson/335632.js\"></script>\n<p>You’ll notice I’m using <code class=\"ee\">{exp:query}</code> twice. The first time is to establish a variable in the SQL connection. Then I am free to use the variable in the second query and the count (returned as <code class=\"ee\">{query_count}</code>) will be a count of the inner loop instead of the outer one.</p>\n<p>It is important to note, however, that MySQL will evaluate the variable’s incrementation before paying attention to any <code class=\"sql\">ORDER BY</code> clauses, so your mileage may vary. Regardless, it’s a handy technique.</p>\n","url":"https://www.aaron-gustafson.com/notebook/counting-the-results-of-a-nested-query-in-expressionengine/","tags":["ExpressionEngine"],"date_published":"2010-03-17T18:16:25Z"}]}