ExpressionEngine Snippets with Emmet

A few weeks ago I was watching some YouTube video tutorials in which one of them (cannot remember which video now) used Emmet to quickly expand large chunks of text. I've previously used a couple of different text expanders but for some reason was never really happy with them and shortly afterwards stopped using them. Emmet however is brilliant, easy to use, and is available as a plugin to several text editors which makes it very appealing. If you change your editor in the future or switch from Mac to Windows or Linux you'll still be able to use all the shortcuts that you know and love.

This example from the Emmet Documentation shows the power of what you can do. Typing ul.generic-list>lorem10.item*4 followed by a tab key results in this code

1
2
3
4
5
6
<ul class="generic-list">
    <li class="item">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nam vero.</li>
    <li class="item">Laboriosam quaerat sapiente minima nam minus similique illum architecto et!</li>
    <li class="item">Incidunt vitae quae facere ducimus nostrum aliquid dolorum veritatis dicta!</li>
    <li class="item">Tenetur laborum quod cum excepturi recusandae porro sint quas soluta!</li>
</ul>

I typically use this when building out sections of the HTML of a site using bootstrap so I would often type out: div.container>div.row>div.col-sm-6*2>h2{Lorem Title}+p>lorem15 which results in this code

1
2
3
4
5
6
7
8
9
10
11
12
<div class="container">
	<div class="row">
		<div class="col-sm-6">
			<h2>Lorem Title</h2>
			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur sequi repellat enim cumque et. Voluptas.</p>
		</div>
		<div class="col-sm-6">
			<h2>Lorem Title</h2>
			<p>Aut, beatae, molestias dolore voluptates nemo saepe commodi illum quas soluta deleniti asperiores aliquid! Modi.</p>
		</div>
	</div>
</div>

Clearly this is very powerful and will save you lots of keystrokes and time when coding. Last week I saw this post on The Meta Q which inspired me to create a set of EE snippets and share them with the ExpressionEngine community. You can download the snippets at https://bitbucket.org/CreateSean/ee-emmet-snippets I've added snippets for both native ExpressionEngine Code and Third Party addons. Some of the snippets that I've added are ones that I have to check the EE docs everytime to get correct such as ee:search:simple

1
2
3
4
5
6
7
8
9
10
11
12
13
{exp:search:simple_form 
        channel="not foo" 
        result_page="search/results" 
        no_result_page="search/noresults" 
        search_in="everywhere" 
        status="not closed" 
        where="all" 
        form_class="navbar-form navbar-right"} 
        <div class="form-group"> 
                <input type="text" placeholder="" name="keywords" class="form-control search"> 
        </div> 
        <button type="submit" class="btn btn-success">Search</button>
{/exp:search:simple_form}

or ee:paginate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{paginate}
<div class="row">
    <div class="col-sm-12">
    {pagination_links}
        <ul class="pagination">
            
 
            {previous_page}
                <li><a href="{pagination_url}" class="page-previous"><span class="glyphicon glyphicon-chevron-left"></span></a></li>
            {/previous_page}
 
            {page}
                <li><a href="{pagination_url}" class="page-{pagination_page_number} {if current_page}active{/if}">{pagination_page_number}</a></li>
            {/page}
 
            {next_page}
                <li><a href="{pagination_url}" class="page-next"><span class="glyphicon glyphicon-chevron-right"></span></a></li>
            {/next_page}
 
            
        </ul>
    {/pagination_links}
    </div>
</div>
{/paginate}

Feel free to download or contribute additional snippets. I do have plans to add more snippets, both native and third party, as I have time. If there is a chunk of code that you would like added you can contact me via twitter @caffeinecre8ion or contribute directly to the repo.

Native ExpressionEngine Snippets

  • ee:entries
  • ee:entry:date
  • ee:entry:path
  • ee:comment:date
  • ee:comment:entries
  • ee:comment:form
  • ee:layout
  • ee:layout:set
  • ee:paginate
  • ee:simple:search

Third Party Addon Snippets

  • freeform:form
  • ceimg:single
  • ceimg:pair
  • switch:ee
  • crox:ifelse
  • hacksaw
  • low:reorder
  • low:variables:single
  • low:variables:pair
  • seolite

Why You Should Use Low Variables on Your ExpressionEngine Builds

I've been using Low Variables on all of my ExpressionEngine builds for the last couple of years and I think you should be too. Low Variables (LV) is basically the swiss army knife of ExpressionEngine addons, a multipurpose tool that will allow you to do more with less. It is a commercial addon but for what you get the $49 price tag is well worth it.

The one part of LV that I use on every site is the ability to edit variables (textarea type) as flat files. Now your important variables with template code are able to be version controlled and editable in your favorite text editor. I set the file path to be the same as my tempalte folders. You can set this in the settings for LV in the CP or if you are using the FocusLab multi environment set up then you can add the following lines to your config.master.php which will set both your regular template path and LV flat files.

1
2
3
4
5
6
7
8
9
// add-on themes path
	$env_config['path_third_themes'] = $base_path . '/addons/themes/';
	$env_config['url_third_themes'] = $env_config['base_url'] . '/addons/themes/';
	// add-on system path
	$env_config['third_party_path']    = $base_path . '/addons/system/';
 
	// low variables
	$env_config['low_variables_save_as_files'] = 'y';
	$env_config['low_variables_file_path'] = $base_path . '/templates/';

Low Variables also allows you to hide variables from non managers. I set the managers group to super admin and hide all template code variables from other users. Other settings in the CP that I use are:

Clear Cache "Yes"
Enable Early Parsing "Yes before snippets"
Add member data to early parsed variables "no" 
 

Enabling Early parsing is useful because we can now on a per variable basis set the variable to be early parsed. This allows you to use EE code and pass variables through to your files as you would with an embed. The bonus here is that there is less overhead than with embeds which speeds up your site. Many sites split up repeatable content into embeds using {embed="includes/_nav"} or {embed="includes/_doctype_header" meta_title="foo bar"} Where the variable meta_title is passed to the embedded content. The same approach can be used with LV but with less overhead. 

In your template you would have the following code:

1
2
3
4
5
6
{exp:low_variables:single var="lv_doctype_header"
	preparse:pre_meta_title="Some Page Title Here"
	}
<body>
	code here
</body >

Then in your low variable lv_doctype_header you would have the following code where you can see that the page title is now using {pre_meta_title}:

1
2
3
4
5
6

<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>{pre_meta_title}</title>
</head>

I put all of the above style template code into a group called Developer Variables and all variables inside this group are hidden from non super admins. Remaining variables are then put into groups depending on the section they belong to. I will typically have a Homepage, SEO, and Miscellaneous group. If another section of the site has several variables then that section will also get it's own group of variables.

On the homepage many sites have a home slider and I make this a low variable using the matrix field type. This matrix has four cells:

  1. image-upload "File"
  2. slide-title "text"
  3. slide-text "text"
  4. slide-link "text"

The template code looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{exp:low_variables:pair var="lv-home-slider"}
	<li &#123;if row_count=="1"}class="active"&#123;/if}>
	{if slide-text}	
		{exp:ce_img:pair src="{image-upload}" width="650" height="392" alt="image"}
			<img src="{made}" alt="" width="{width}" height="{height}" />
		{/exp:ce_img:pair}
		<div class="text-holder">
			<strong class="title">{slide-title}</strong>
			<p>{slide-text}</p>
			<a href="{slide-link}" class="more">read more</a>
		</div>
	{/if}
	{if slide-text ==""}
		{exp:ce_img:pair src="{image-upload}" width="950" height="392" alt="image"}
			<img src="{made}" alt="" width="{width}" height="{height}" />
		{/exp:ce_img:pair}
	{/if}
	</li>
{/exp:low_variables:pair}

On another site I just finished a landing page for one section needed to have a grid of four items with custom copy for the title, short blurb and thumbnail, but link to an interior page on the site. I set this up again with Low Variables and a matrix. This time the matrix had a minium of 4 rows and a maximum of 4 rows set. There were four cells, the playa cell could easily be a "select entries" field which comes with Low Variables. The code for this is below.

  1. sector_title "text"
  2. sectory_copy "text"
  3. sector_link "playa"
  4. sector_image "file"

1
2
3
4
5
6
7
8
{exp:low_variables:pair var="lv-investment-sectors"}
<div class="col-md-3 col-sm-6 invest-grid" data-match-height="invest-grid">
	<a href="/about/detail/{sector_link}{url_title}{/sector_link}"><img src="{sector_image}" alt="..." class="img-circle"></a>
	<h3><a href="/about/detail/{sector_link}{url_title}{/sector_link}">{sector_title}</a></h3>
	<p>{sector_copy}</p>
	<a href="/about/detail/{sector_link}{url_title}{/sector_link}" class="more-icon"></a>
</div>
{/exp:low_variables:pair}

The SEO group is set up to handle landing pages where SEO description and meta title is not available in a channel entry. I've previously written about this on my post SEO and ExpressionEngine.

In conclusion Low Variables allows you to effiently code your site using DRY code and provides a clean easy to use interface for your clients to edit various bits of copy around the site that don't necessarily belong in a channel. My clients have all been very happy with the intuitive and easy to use interface that Low Variables provides them. For the developer, you are able to use snippets and global variables by setting the parse early option on a per variable basis and edit those variables as files, thus allowing you to have your code version controlled and easy to edit.

FITC Spotlight: Advanced JS Roundup

Yesterday I had the pleasure of attending FITC Spotlight: Advanced JS at the University of Toronto. The talks at this event were a little above my skill level, but still interesting and informative.

The sessions included:

Client Side MVC and The Gosh Darn Back Button

In this presentation  Harry Brundage discussed clients side MVCs and memory leakage. It is easy to leak memory in JavaScript Apps. With jQuery memory use goes up then down and repeats like this chart:

However in JS MVC there is no reset and memory continually goes up as in the chart below:

For this reason it's important to use .remove() but also easy to forget. But if you don't then your memory will continue to leak and the app will become less and less responsive. Harry then discussed how to fight memory leaks and stressed that .remove() should be used in an MVC environment. He also said that frameworks should handle lifecycle focus as .remove() puts on the onus on the developer to remember.

Using frameworks means having to surrender control, however we get less wrong. 

Turbocharging Client-Side Processing: Leveraging asm.js

Vladimir Vukicevic introduced asm.js (prounounced ahzem) as an optimizable subset of JavaScript that is intended as a compilation target. Asm.js uses rigid rules that are not intended to be written by hand, though it is possible (but painful to do so).The compilation target is not just C++ but also IIjs, typescript, emscriptem for C/C++. 

Other items of note:

  • deal with manual memory management & allcoation by making a wrapper and avoid thinking aout it again.
  • user worker threads - asyncronous execution
  • Workers are awesome - APIS coming soon
    • WebRTC
    • WebGL & Canvas2d
    • Web Sockets
    • Web Audio
  • near future compilation will be cached resulting in a near instant load
  • process/resize photos client side
  • text to speech
  • use asm.js to load specialized codecs when device can use them

Virtual Machines 101

This talk, by Tasveer Singh, was well presented, but I was unable to follow much of what was said due to the speed of his presentation and my notes no longer make any sense to me. Sorry Tasveer, you were a good speaker, I just couldn't follow your topic.

Rich Interactivity with CreateJS

This presentation was just after lunch and I was in a post lunch coma just before Grant Skinner started his talk, however I was soon wide awake. Grant was an enthusiatic speaker and gave an introduction to CreateJS that demonstrated how easy it is to create rich media with javascript. CreateJS is actually a suite of JavaScript libraries that include EaselJs, TweenJs, SoundJs & PreloadJs

Essentially much of what was previously done using Flash can now be done with CreateJS. In fact, Flash CC works with create.js natively and can render as HTML5 using CreateJS. Other things that CreateJS has is that there are no dependencies and it plays well with other libraries. This is definitely something I want to spend some time learning.

Continuous Deployment Workflows for Non-Trivial Full-Stack JavaScript Applications

Nick Van Weerdenburg discussed continuous deployment and numerous best practices with GIT. One thing that stood out for me was that with teams of people he suggested that the DevOp Manager change each week. By doing so there would be no single point of failure. Other points include:

  • if you aren't improving, you're getting worse
  • automate everything you can
  • you cannot under invest in GIT (I think he meant it's not possible to over invest)
  • pair programming
  • SOLID GIT training is essential.

Nick also recommended three books Functional Javascript, Testable JavaScript & Maintainable Javascript.

Awesome Ember Tricks

Next Robin Ward introduced four awesome tricks to use with Ember.js. Ember.js is a browser application framework that uses handlebars templating and values convention over configuration. Below are the tricks:

  • Trick #1: computed property macros are smart. Content changes as updated, if not, then no change
  • Trick #2: Async everything. Updates are coalesced so that an event queue combines multiple inputs into one output
  • Trick #3: Custom resolver - extensible
  • Trick #4: View Cloaking. This was explained with regards to infinite scrolling and how you could unload off screen view (cloaking) and reduce ram usage.

Realtime “Eye Candy” with AngularJS

The final presentation of the day, by Matias Niemelä, was also very interesting. Matias introduced Angular.js by informing the audience that it extends browser capabilities to make it feel like dynamic data and that it is very quick to make web apps. In fact he built a simple app during his talk. 

Using pusher.js in combination with angular it's possible to make a "hybrid" web app that combines the best of traditional website and ajax powered web sites. During Matias' presentation I forgot to take a lot of notes as I was too focused on what he was doing and saying. You can, however, view the slides for Matias's presentation here.

Final Thoughts

The after party at Pour Girl was quite good and had good beer. I talked with a few people and even found a couple of people interested in trying out ExpressionEngine, my CMS of choice. This was my second FITC event and I would highly recommend attending if the topic is something you are interested in. Both times the venue was good and easily accessibile, the speakers of high caliber with excellent presentations.

Hope to see you at the next FITC event.

Multilingual Dates in ExpressionEngine

I've built about 15 multilanguage sites and have a good process for building them out using Transcribe, which I really enjoy using. Today I ran into something new for the first time. The site I'm working on needs to display entry dates, however there is no built in way with Transcribe or ExpressionEngine to translate the dates.

A quick search on Devot:ee later and I found Date/Time Language Converter by Carl Crawley. This little plugin is super easy to use. Below is my code to get a French/English site to display the dates in both languages. The key to notice is that the entry date tag that is wrapped by the datetime_convert tags has no formatting parameter.

1
2
3
4
5
{if "{transcribe:language_abbreviation}" == "en"}
	{entry_date format="%F %d%S %Y"}
{if:else}
	{exp:datetime_convert language="fr_FR" format="%B %e %Y"}{entry_date}{/exp:datetime_convert}
{/if}

Be sure to read Jelle Dijkstra's comment below for a better way to do this with sites that have more than two languages.

Your Voice Here
Leave a Comment