Jean-Francois Paradis

Web Developer + Architect

Mastering the Lightning Framework

| Comments

Salesforce is built on the Lightning Platform. This session will provide you with the same training that Salesforce engineers receive during on-boarding. We are bringing this training to you in a two part series.

Part 1 will provide detailed information about Component Definition including component-based architecture, component structure, component implementation and key components.

Part 2 explains how MVC is used in Lightning, and covers the connection to data sources from the server.

CSS Specificity Using the Olympic Medals Table

| Comments

CSS Specificity is one of the most difficult concepts to grasp when working with stylesheets. In a nutshell, specificity determines which CSS rule is selected by the browser when multiple rules match a given HTML element. It’s important to understand it in order to know:

  • why some rules are rejected when debugging a page
  • how to overwrite a given rule with the minimal syntax

You can calculate specificity, or you can use a simpler and more intuitive analogy. Let’s review the former.

Using Calculation

The W3C proposes the following method for calculating a selector’s specificity:

  • a = the number of #id
  • b = the number of .class + [attribute] + :pseudo-class
  • c = the number of TYPE + :pseudo-element()
  • ignore the universal selector
  • concatenate the three numbers a-b-c to obtain the specificity (assume a large base)

Examples (simplified from W3C):

1
2
3
4
5
6
7
8
9
*                  /* a=0 b=0 c=0 -> specificity =   0 */
H1                 /* a=0 b=0 c=1 -> specificity =   1 */
H1 A               /* a=0 b=0 c=2 -> specificity =   2 */
H1+P A             /* a=0 b=0 c=3 -> specificity =   3 */
FORM *[type=text]  /* a=0 b=1 c=1 -> specificity =  11 */
P A:hover          /* a=0 b=1 c=2 -> specificity =  12 */
P.center A.red     /* a=0 b=2 c=2 -> specificity =  22 */
#main              /* a=1 b=0 c=0 -> specificity = 100 */
#main:not(DIV)     /* a=1 b=0 c=1 -> specificity = 101 */

You can test your understanding of this method with a Specificity Calculator.

Because these calculation are tedious to employ on a daily basis, various analogies have been proposed to illustrate how specificity works:

However, I still find these systems either complex or hard to remember, so I came up with yet another analogy, based on the Olympic medal table.

The CSS Olympic Medal Table

The ICO uses the gold first system, a ranking order based first on the number of gold medals won, then silver and bronze. The 2010 Winter Olympics medal table illustrates how this works:

Rank Country Gold Silver Bronze Total
1 Canada 14 7 5 26
2 Germany 10 13 7 30
3 United States 9 15 13 37
4 Norway 9 8 6 23
5 South Korea 6 6 2 14

CSS Specificity works the same way: it’s not the number of selector that counts, it’s how many of the right ones you have.

Here is how the CSS Olympic Medal Table works:

  • use the gold first raking system
  • gold = the number of #id
  • silver = the number of .class + [attribute] + :pseudo-classe
  • bronze = the number of TYPE + :pseudo-element()

Our previous example can be converted as follows:

Rank Selector Gold Silver Bronze
1 #main:not(DIV) 1 0 1
2 #main 1 0 0
3 P.center A.red 0 2 2
4 P A:hover 0 1 2
5 FORM *[type=text] 0 1 1
6 H1+P A 0 0 3
7 H1 A 0 0 2
8 H1 0 0 1

This technique is faster because you don’t have to count at all of the selectors to find out which rule wins!

Monads in 10 Minutes

| Comments

In computer science, a Monad is a design pattern, and like all design patterns, its goal is to solve a problem with simplicity.

Use Case

Let’s define an object containing one value, and see how we can manipulate that value:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Definition
function Simple (value) {

    this.getValue = function () {
        return value;
    }

    this.setValue = function (newValue) {
        value = newValue;
    }
}

// Initialization
var simple = new Simple(10);

// Manipulation
var value = simple.getValue();
value = Math.log(value);
simple.setValue(value);

That’s a lot of code to write every time we need to manipulate the object. To solve that problem we could add a method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Definition
function Simple (value) {

    this.getValue = function () {
        return value;
    }

    this.setValue = function (newValue) {
        value = newValue;
    }

    this.calculateLog = function() {
        value = Math.log(value);
    }
}

// Initialization
var simple = new Simple(10);

// Manipulation
simple.calculateLog();

This is better, but it means that we have to keep adding methods every time we need a new calculation.

Using Simple Monads

Think of a Monad as the opposite of a function: a function contains code and takes a value for argument; a Monad contains a value and take code for argument. Both of the following are equivalent:

1
2
Math.log(10); // 2.3026
new Monad(10).bind(Math.log).return(); // 2.3026

The constructor wraps an initial value:

1
2
3
var Monad = function(value) {
    this.value = value;
}

The bind() method applies a function to the value and returns the Monad for chaining:

1
2
3
4
Monad.prototype.bind = function(fn) {
    this.value = typeof fn === 'function' ? fn.call(this, this.value) : NaN;
    return this;
}

The return() method unwraps the value:

1
2
3
Monad.prototype.return = function() {
    return this.value;
}

Monads allow you to execute multiple arbitrary functions in a sequence:

1
2
3
4
5
6
new Monad(10)
    .bind(Math.log)
    .bind(function(value) {
        return value > 2 ? Math.floor(value) : value;
    })
    .return(); // 2

The 3 Monadic Laws

There are various types of Monads, but their definition is beyond the scope of this article. What is important to know is that all Monads obey a few axioms.

For our proofs below, let’s define a few constants:

1
2
3
4
var a = Math.PI, // a constant
    f = Math.floor, // a function
    g = Math.log, // a function
    h = Math.sqrt; // a function

Left Identity

return() is a neutral function. Applying return() to a Monad returns its value:

1
new Monad(a).bind(f).return() === f(a); // true

Right Identity

Binding return() to a Monad doesn’t alter the Monad:

1
new Monad(a).bind(f).bind(Monad.prototype.return).return() === f(a);  // true

Associativity

Binding is independent of the grouping of elements. Binding two functions in succession is equivalent to binding one function determined from them:

1
2
3
4
5
new Monad(a).bind(f).bind(g).bind(h).return() === new Monad(a).bind(f).bind(
    function(x) {
        return new Monad(x).bind(g).bind(h).return();
    }
).return(); // true

Backbone.accessors

| Comments

Backbone.accessors generates accessors from the fields of a Backbone.js model. For each field XXX, the setXXX(), getXXX(), hasXXX(), and unsetXXX() methods are added. For clarity and readability, the first letter of each XXX filed is converted to uppercase.

Examples:

Without accessor: With accessor:
model.get(‘name’) model.getName()
model.set(‘name’) model.setName()
model.has(‘name’) model.hasName()
model.unset(‘name’) model.unsetName()

This plugin is compatible with AMD provided the proper shim is added.

This approach is inspired by Propel, an Object-Relational Mapping (ORM) for PHP.

Getting started

  1. Include Backbone in your project before including the Backbone.accessors plugin.

  2. In your models, add all fields requiring accessors to the defaults object. Set the value to undefined where no default value is desired:

1
2
3
4
5
6
7
8
var Model = Backbone.Model.extend({

    defaults: {
        id          : undefined,
        firstName   : 'Mary',
        lastName    : 'Poppins'
    },
});
  1. Apply the accessor mixin to each model.
1
Backbone.accessors.apply(Model);
  1. Use your model normally, replacing the calls to get(), set(), has(), unset() with the custom ones:
1
2
3
4
var model = new Model();

// model.set('id', 10);
model.setId(10);

Note: you can mix both types of accesors.

Justification

On larger projects, there is always a concern with maintaining the magic strings and numbers which are often found in JavaScript code:

1
model.set('firstName', name); // 'firstName' is a magic string

One solution is to populate and use a constant object, an approach commonly used in strongly-typed languages such as Java and C#:

1
2
3
4
5
6
7
8
9
var Constants = {
    NameModel: {
        id          :'id',
        firstName   : 'firstName',
        lastName    : 'lastName'
    }
};

model.set(Constants.NameModel.firstName, name); // 'firstName' is gone

While intended to generate an error if there is a typo in Constants.NameModel.firstName, this approach will fail silently if the last identifier of the notation (in practice the most complex) has a mistake in it:

1
2
model.get(Constants.NameModel.firstNaame); // return 'undefined', no error
model.set(Constants.NameModel.firstNaame, name); // no error

On the other hand, with accessors, there is less code to type, no constant file to carry around, and the code will immediately fail (fail hard) if there is a typo in the variable name:

1
2
model.getFirstNaame(); // runtime error
model.setFirstNaame(name); // runtime error

See the included README file for more information.

You can get the code on GitHub.

EE Reword Plugin

| Comments

Reword is a simple plugin for ExpressionEngine inspired from the WordPress functions translate(), __() and _e() which translate a website into another language, depending on the language of the user’s browser, and using a dictionary.

Its basic usage is quite similar to __() so if you are familiar with WordPress, you can use Reword right-away:

  1. Install the plug-in
  2. Provide a dictionary file
  3. Add tags to your templates

Here is a simple dictionary:

1
2
3
4
5
6
7
8
9
<?php
$lang = array(
    'Hello' => 'Bonjour',
    'Hello %s' => 'Bonjour %s',
    '%s search results for "%s"' => '%s résultats pour "%s"',
    '%M %d, %Y' => '%d %M %Y',
    'Posted %d' => "Publié le %d"
);
?>

Here is a sample usage in a template:

1
2
3
4
5
6
7
8
9
10
11
{exp:sk_reword text='Hello'}
// Output: Bonjour

{exp:sk_reword text='Hello %s' string='Mary'}
// Output: Bonjour Mary

{exp:sk_reword text='%s search results for "%s"' string='25|Test'}
// Output: 25 résultats pour "Test"

{exp:sk_reword text='Posted %d' format='%M %d, %Y' date='2012-09-07'}
// Output: Publié le 07 Sep 2012

See the included README file for more information.

You can get the code on GitHub or through Devot-ee.

EE Excerpt Plugin

| Comments

WordPress has several easy-to-use features that are hard to leave behind when you move to other platforms. One of them is the function the_excerpt().

The Codex defines the_excerpt() as follows: “displays an excerpt of the current post with an ellipsis […] at the end; all HTML tags are stripped from the text; and only the first 55 words are kept.”

In the actual WordPress source code, we see that the words are defined as the characters separated by a specific non-word characters (\n, \r, \t, and space).

However, for some East Asian languages, the words are defined as the individual characters. Therefore, our sk_excerpt plugin gives the flexibility to chose either word or character count. When you use the character count, it will try not to cut inside a word. Here are some use cases:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Use the default 200 characters, cutting only between words.
{exp:sk_excerpt chars='true'}{content}{/exp:sk_excerpt}

// Use 500 characters.
{exp:sk_excerpt chars='500'}{content}{/exp:sk_excerpt}

// Use the default 50 words.
{exp:sk_excerpt words='true'}{content}{/exp:sk_excerpt}

// Use 55 words.
{exp:sk_excerpt words='55'}{content}{/exp:sk_excerpt}

// Also change the ellipsis from ' [...]' to '...'
{exp:sk_excerpt words='55' more='...'}{content}{/exp:sk_excerpt}

Examples:

1
2
3
4
5
{exp:sk_excerpt words='3'}After you login to the store, you can enter your bank detail under Accounts->Bank information.{/exp:sk_excerpt}
{exp:sk_excerpt words='3'}在您登录到商店里,您可以在银行信息栏中输入相应的内容。{/exp:sk_excerpt}

{exp:sk_excerpt chars='7'}After you login to the store, you can enter your bank detail under Accounts->Bank information.{/exp:sk_excerpt}
{exp:sk_excerpt chars='7'}在您登录到商店里,您可以在银行信息栏中输入相应的内容。{/exp:sk_excerpt}

Output:

1
2
3
4
After you login []
在您登录到商店里,您可以在银行信息栏中输入相应的内容。
After you []
在您登录到商店 []

However, for most layouts, I find that we get a more consistent look between languages when we think in terms of space used on the screen, so the algorithm switches to characters mode when the words have more than 10 characters on average.

Examples:

1
2
3
4
5
6
7
{exp:sk_excerpt words='3' chars='7'}
After you login to the store, you can enter your bank detail under Accounts->Bank information.
{/exp:sk_excerpt}

{exp:sk_excerpt words='3' chars='7'}
在您登录到商店里,您可以在银行信息栏中输入相应的内容。
{/exp:sk_excerpt}

Output:

1
2
Ater you login []
在您登录到商店 []

By providing two measures (words and chars) which can be adjusted individually, we can accommodate the fact that the Chinese words are slightly wider.

You can get the code on GitHub or through Devot-ee.