Education, Training Notes

Sass – Understanding Stylesheet Scripting

Sass has come a long way in a short amount of time to offer web designers and developers a method of using scripting variables in their stylesheets, to change the apearance of their content.  Join with me as I dive into the world of Sass and learn more about CSS Preprocessors!  Lets go!

What Are Preprocessors?

Preprocessors are programs that take one type of data and transform it to another type of data.  In Sass, the preprocessor takes Sass code and transforms it to CSS.  The reason for Sass is it allows us to use variables and nesting and other features within our CSS.

With these features comes the most important reason for using a preprocessor, to save time.  By using Sass, we can accomplish more in less time.

Typical Sass Workflow

Write Sass Code > compile the code into CSS > load the CSS in the page

The compiling is an extra step, but the benefits outweigh the cost of using Sass.

Instaling Sass

Sass is a Ruby Gem, so you must first install Ruby.  If you are a Mac user, you already have Ruby installed.  Windows users should visit http://rubyinstaller.org/downloads/ and download the latest Ruby build.

Once downloaded, run the program and it will install Ruby on your system.  Now we need to install the Gem; open the Command Prompt with Ruby program (run as administrator) and use this line to install Sass:

gem install sass

That will install sass, the other thing to know is when to compile your Sass.  First of all, the sass files must be in a folder.  Then you will cd into the project folder and compile them using this command:

sass --watch fileName.scss:fileName.css

You are telling sass to watch for the .scss file in the folder (specified above) and compile the document into CSS.  You also set up a watch so whenever you change the scss, you also change the css

Of course, there are also third-party extensions to help with compiling, but I know you guys don’t like things the easy way :)

Sass Syntax

The Sass language has two syntaxes:

  1. SCSS (.scss) – New syntax
    1. scss is an extension of the css file.  Any valid .css file is also valid .scss, so you can just write plain css into your .scss file.  Can also incorporate newer variables and nesting behaviors into file
  2. SASS (.sass) – Older Syntax
    1. sass has many differences with css, but can still be compiled into css.  The main differences are semicolons are no longer used, replaced with line breaks to signal the end of a style declaration.  It also doesn’t use brackets, instead indentation is used to demonstrate style nesting, so:
      body{color:blue;} becomes body color:blue

Another difference is how you write comments.  In scss, can use CSS styles (/* */) but cannot use (//)

Decision rule is to use newer SCSS as it is closer to normal CSS, yet still as powerful as SASS

Nesting

Style nesting is a feature ommitted by classical CSS but embraced by Sass.  Nesting is basically writing one objects style inside the declaration for another element.  It can save a bunch of time if used correctly.

Example:

If you wanted to color anchor tags within a paragraph, you would use p a {color:example}; but in Sass, you can nest the a style within the p style, like so…


p {
    margin-bottom: 1.3em;
    color: #666;

    a {
        color: #589ED3;
    }
}

In the above example, the a style is located within the brackets of the p style, but when it compiles, it looks like…


p {
  margin-bottom: 1.3em;
  color: #666; }
  p a {
    color: #589ED3; }

So you can see that while the style is written differently, it compiles in the same way that you would expect.  Sass allows you to write less code, yet still compiles to be exactly the same as if you spelled it out.

Parent Selector (&)

For styling psuedo-elements (:hover, etc), you can use the & character as a placeholder for the root element you are styling.  So, if you wanted to style the hover state of a link…

Example:


a {
    text-decoration: none;

    &:hover {
        text-decoration: underline;
    }
}

Simply substituting the a with &, which fills the place of the parent tag. When compiled, it outputs as:


a {
  text-decoration: none; }
  a:hover {
    text-decoration: underline; }

Can also add classes or ids to the parent selector, so &.red above would select any a tags with a class or “red”.  It compiles to a.red, just as you would expect.

The parent selector can be used in a few different ways…

#demo {
    &-child { margin: .5em; }
    &child { margin: .5em; }
    &.child { margin: .5em; }
    & .child { margin: .5em; }
}

Compiles to become…

#demo-child {
  margin: .5em; }
#demochild {
  margin: .5em; }
#demo.child {
  margin: .5em; }
#demo .child {
  margin: .5em; }

The first example creates a new selector, adding the parent to the hyphen and then the word child (#demo-child).  The second example does the same, but no hyphen.  3rd example creates a class selector for the element, so the element has an id of demo and a class of child.  The final example selects an element with a dependent class of child within an element with an id of demo.

Can also put parent selector at different places in the style declaration to great effect:


.container {
    width: 90%;
    margin: 0 auto;

    .boxed-layout & {
        background-color: #fff;
        padding: 3em;
        border: 1px solid #eaeaea;
        border-width: 0 1px;
    }

    
}

This compiles to:

.container {
  width: 90%;
  margin: 0 auto; }
  .boxed-layout .container {
    background-color: #fff;
    padding: 3em;
    border: 1px solid #eaeaea;
    border-width: 0 1px; }
  

This would be used with javascript libraries such as Modernizr. Modernizr test the browser for its capabilities, then styles the page contents to reflect those abilities. With the above code, you could write the styles for different container elements in multiple different Modernizr versions.

Can also make complex selections:

.container {
    width: 90%;
    margin: 0 auto;

    > header {
        h1 {
            font-size: 4em;
            font-weight: 800;
        }
    }
}

Becomes…

.container {
  width: 90%;
  margin: 0 auto; }
  .container > header h1 {
    font-size: 4em;
    font-weight: 800; }

In the above example, we use the direct dependecy (>) to grab the header, then the h1 inside the header which is directly beneath the container element.

Important Considerations

Nesting is great, but improper nesting can get really complicated and hard to maintain as the pages grow.  Be careful how deep you are nesting.  As a general rule, dont go beyond 3 or maybe 4 DOM levels, and the final level has to be selecting psuedo-elements.

  • Nesting is BEST used for psuedo classes and elements.
  • When using parent selector, be careful to not create style documents that you cannot search through

 

Nested Properties

For style declarations that share the same namespace (font-family, font-size, font-weight), we can combine the declarations into one block:

font: {
        family: Helvetica, Arial, sans-serif;
        size: 1.125em;
        weight: 400;
    }

Compiles to:

 font-family: Helvetica, Arial, sans-serif;
  font-size: 1.125em;
  font-weight: 400;

Or in shorthand:

 font: 400 (font-weight) 1.125em/1.5 (font-size/line-height) Helvetica, Arial, sans-serif(font-family);

This works for anything that shares a property name (background, margin, padding, border, etc.)

Nesting the properties can create more code than necessary, however, it is good practice for beginners and helps make your SCSS file more readable.

Variables

One of the largest developments with the SASS language is the use of variables in your CSS document.  Variables represent reusable style values that can be given a namespace and called on any element, creating large and cascading changes with minimal typing.

Examples of Variables

Variables are a great method of styling repeated values without actually repeating each time.  They always begin with the $ (dollar sign or string) character, just as in JavaScript and are followed by a text string which indicates the purpose of the variable:

$text-color: #333

Then, for any styles which need a text color, you can simply replace the variable for the value, so:

body { color: #333;}

becomes

body { color: $text-color;}

Now the body will get the color value from the text-color variable.  This also means that we can simply change the text-color value and we will change the color values wherever we use the variable.

When compiled, SASS writes the correct CSS code (doesn’t use variables) for you!

Have a section at top of SCSS which sets many global properties for the document, then write my styles using these global properties to make things easier to manage and change going forward.

Most powerfully, variables can also perform operations.  Suppose this test case:
We can set a baseline text size with a variable, then compute different text sizes for the styles based on the baseline variable we have created.


$baseline: 12px;

We can set our text to that baseline by:


body {font-size:$baseline;}

But then we want to have our titles be twice as large as the baseline, we can compute that operation with SASS:


h1 {font-size:$baseline * 2;}

By multiplying the $baseline by 2, we get 24px, which we then style our H1 around. Of course, when the SCSS compiles it displays the 24px value, not the $baseline * 2 value.

Varialbe Scope

Just like JS, there is a scope in which the variables exist.  If you write all your variables at the top of the page, they are global and can be used by the entire stylesheet.  If your variables are placed inside of an elements style declaration, the variable is only available to that element or any children, but nothing above in scope.  However, if we put our varialbes inside style declarations, we can end the value with !global and allow the variable to be read by the entire document.

Variable Interpolation

Substitute a variable in an expression with its value

Lets say you have a variable with a value, for example:

$child: "widget";

then you wanted to add the value of the variable to a selector:

.sidebar-$child {

}

would not work, but you can use:

.sidebar-#{child} {

}

this compiles to:

.sidebar-widget {

}

This feature is also used when writing shorthand css:

font: 400 $font-size/$line-height $font-family

The 400 is font weight, and the rest of the variable could have values attached, however, the middle style of $font-size/$line-height would be calculated because / is an operator (division).  Instead, use interpolation to subsititute values correctly without conducting an operation

font: 400 #{$font-size}/#{$line-height} $font-family

Interpolation can also be used when using content styling:

p:before {content: "$content-before"} would need to be p:before {content: "#{$content-before}"}

Data Types Supported by SASS

SASS supports 7 main data types

  • Numbers
  • Strings (text)
  • Colors
  • Booleans
  • Nulls
  • Lists
  • Maps

Numbers

  • Numbers with units – margin: 100px; (100 is number and px is unit)
  • Decimal numbers without units – line-height: 1.5;
  • Whole Numbers without Units – font-wieght: 800;
  • Percentages – padding: 1%;

Strings

  • Quoted and Unquoted Strings – font-family: “Helvetica”, Arial, sans-serif;

Colors

  • Hex – color: #ccc;
  • RGB – background-color: rgb(255, 255, 255);
  • RGBA – border-color: rgba(0, 0, 0, .5);
  • HSL (Hue Saturation Lightness) – border-color: hsl (155. 33%, 65%);
  • Named Color – border-color: green;
    • Check SASS documentation for full list of named color spaces

Maps

Lists represented by key-value pairs

$colors: (
1: #ccc,
2:#333,
'color-3':red
);

The above example shows a map with key value pairs.  Both the keys and values can be either numbers or strings, and final pair is not followed by comma (think JS).  Note the parenthesis instead of the curly brace to make a map.

$margins: (

tight: 10px 20px,

compact: 30px.

large: 5em

);

A comma separates the key-value pairs, so if your declarations have commas then you need to wrap each value in parenthesis

$fonts: (
option-1: (Arial, sans-serif),
option-2: (Times, serif)
);

To then use the maps, use a function called map.get:

footer {
background-color: map-get($colors, 2);
margin: map-get($margins, large);
};

Operations

SASS supports operations with:

  • Numbers
  • Colors
  • Strings
  • Booleans
  • Lists

Numbers

Can use standard arithmetic operations:

  • Add
  • Subtract
  • Multiple
  • Divide
  • Equalities

{margin: 10px + 20px} becomes {margin: 30px} when output.  This only works if both values are of the same measurement (unit) type, so cant add pixels and em’s or %’s.  Subtraction works in a similar way.  Exception multiplication, can’t have units on both numbers {margin: 5px x 2} outputs to 10px, couldn’t have {margin: 5px X 2px}.

Division is also different.  You cant simply divide two numbers like {margin: 20px / 2;}, you have to wrap the operation in parenthesis, like {margin: (20px / 2);} outputs to {margin: 10px}.  Its also common to use variables with division, so if $baseline: 2em; and {margin: $baseline  / 2;} outputs to {margin: 1em;}.

You can do multiple operations within a single style declaration, such as {padding: 10px + 20px / 2;} outputs to {padding: 10px;}.  It follows the common order of operations (MDAS).  Just like in math, parenthesis can alter the normal order, and you evaluate what is in the parenthesis first.

Can also use inequalities like greater or less than to output to booleans, which can then be used to string together larger operations and style scripts, so {content: 10px > 20px;} outputs to {content: false;}.

Strings

Most common string operation is concatenation.  {font-family: sans + "-serif";} outputs to {font-family: sans-serif;}.  Conversely, if you have the quoted content as the first value, such as {font-family: "sans" + -serif;} the entire value is qutoed, {font-family: "sans-serif";}.  It all depends on which data comes first in the operation.  This is an important distinction.

Can also use interpolation with strings, such as $content: “default”; and {content: "This is a #{$content} button with a width of #{5 * 23} px";} outputs to {content: “This is a default button with a width of 115 px”;}.  Note that interpolating the string content removes the quotes.  Also note that we can run operations with the # sign and {}, but otherwise it would simply display as string data.

@import Directives

@import is used to import sass and scss files.  In basic CSS, @import allows us to import styles from other sheets.  SASS extends to allow us to import both SCSS and SASS files.  Imported files will be merged together in CSS output file.

It is common to separate general layout styles from page specific styles, and we can use @import directives to accomplish this.  If all the SCSS files are in the same folder, just @import "example.scss";  will import the external styles into the current document.  So, @import "generalLayout.scss"; and @import "pageSpecific.scss"; .  Compiler will import the files into the css document and output one CSS file with all styles on the document (not the @import commands, the styles themselves).

If the files are in another directory, must tell SASS how to find the document, such as @import "folderLevel/example.scss"; .  Can also skip the filename extension and SASS assumes you are looking for .sass or .scss files.

You can import multiple files in a single import directive:

@import "folderLevel/example", "otherExample";

When doing this, the order in which you import the styles is the order in which they are brought onto the page, so the output CSS document will have the example.scss before otherExamples.scss styles.  Because best practices are to write more general styles at the top of the document and more specific styles further down, be careful to import your styles in the correct order.

You are able to compile a SASS @import to a CSS @import if the file you are importing is a CSS document, not a SCSS:

@import "exampleStyle.css"; will output to @import url(exampleStyle.css); and not place the actual styles within the referring stylesheet.  It also happens when you import a url, so if you @import url("http://fonts.googleapis.com/css?family=Oswald"); you get @import url("http://fonts.googleapis.com/css?family=Oswald"); .  Finally, if you have the full hypertext link to the file, @import "https://example.com/style.css"; you will initiate a css import of @import url("https://example.com/style.css");

Media Queries

You can also place the media check within the scss import, such as:

@import "layout" print; will call the layout.scss file for import with the print media, or @import "layout" print;

Partial Files

Partial files are SCSS or SASS files that can be imported but are not compiled.  Partial files start with an underscore.

You cannot have a SCSS file partial (with underscore) and a CSS file of the same name in the same folder.

Partials are used to organize your css files without worrying about the SASS compiler transforming your files into CSS.

Be careful of the order your place your partials.  The same specificity and order effects are used for partials as for all other css files.

@media Directives

The big addition to @media drectives in SASS is the ability to write the media directive inside the element you would like to be altered depending on the media state, for example:

If you have a navigation element that you want floated right on tablets, you can write:

nav {
@media screen and (max-width: 768px;) {
float:right;
}

a {
display:block;
}
}

Usually, we write our media queries at the top or bottom of the page, but SASS allows us to write the query within the selector itself.  This will output in proper CSS syntax (at the root level of the document), but we can write it more effectively in SCSS then compile it.

@media queries can also utilize variables (using interpolation):

@media #{$tablet}

with

$tablet: "screen and (max-width: 768px)";

can be compiled properly.

Can also nest @media queries inside other @media queries.  They are combined using the and operator.

@extend Directive

This allows a selector to inherit styles from another selector.  If you have a root class styling (for example, button styling with font-size and padding) but want to have multiple button types, some larger and some smaller, you can now:

.btn {

font-size:12px;

padding: 2em;

}

.btn-large {

@extend .btn;

font-size: 18px;

}

.btn-large will now pull in all styles for the .btn class, but extend the class with an over right of the font-size.

Chain Extends

Can also perform chaining when using your @extend:

.btn-xlarge {

@extend .btn-large;

font-size: 24px;

}

Multiple Extends

Can utilize extends multiple times.  Just place both @extend directives with the class they are inheriting and your css will inherit the styles in that order.

Working with @media Directives

Can also place @extend directives inside @media directives, but the root classes you inherit must exist within the same @media directive.

@if and @for Directives

@if is used to write conditional statements while @for is used to repeatedly outputting certain styles.

The @if directive takes an expression, evaluates the expression, and if any value returns (other than false or null) then the styles inside that expression are used.  For example:

$type: serif;

body {

@if @type == serif {

font-family: serif;

}

}

With a variable set to serif, we can test that variable with the equality operator to check if the values are equal.  If they are, then SASS uses the style inside the expression (font-family, in this instance).

@if also works with @else to provide a default and @else if to test another expression.  You can use as many @else if, for use like switch case statements, for example:

$theme: neutral;

.button {

@if $theme == warm {

background-color:orange;

} @else if $theme == cold {

background-color:blue;

} @else {

background-color:gray;

}

}

If the first two conditions aren’t met, then the scripting engine moves to the @else statement

@for Directives

@for $i from 1 to 3 {

.cell {

background:blue;

}

}

This is a bit more complicated.  You say the directive, then an iterating variable ($i) and give it a margin in which to run.  The above states 1 to 3, so the expression loops 2 times (if you have the keyword to in your looping, the script doesn’t include the larger number).  If you want to include the upper limit number, use the keyword through instead of to.

You can also use variables with your @for loops, which is probably the only meaningful way to deploy these:

$comments: 10;

@for $i from 1 through $comments {

#comment-#{i}:before {

content: "#{$i}";

}

}

We are using the variable to determine how many times we want to loop.  Then we are using interpolation to have the scripting engine output the #comment- with the iteration number appended to the end of it, before the :before psuedo-class (#comment-1, #comment-2).  Inside the style, we are adding content to the style, reading out the current iteration number.

We can also iterate in reverse order.  So, rather than moving from 1 to $comments, you can move from $comments to 1, but the logic will be the same.

@each and @while Directives

Similar to the @for directive in that they repeatedly output certain styles, these directives have very specific uses.

The @each directive will run through a map or a list and can deal with multiple variables:

@each $section in featured, about, contact {

##{$section}-section {

background-image: url('img/bg-#{section}.jpg');

}

}

SASS uses the variable mixed with the list of elements to set the value for “$section” value at each element in the list.  In first iteration, #section will have the value of “featured”, in the 2nd it will have the value of “about”, and in the third, “contact”.  The above code creates three declarations, using interpolation to set the section title differently for each iteration.  SASS can also run through multiple variables with more complex lists:

@each $section, $color, $word in (featured, red, hope), (about, blue, abundance) {

.section-#{section} {

background-color: $color;

content: "$word";

}

}

SASS will iterate twice, creating styles with:

.section-featured {

background-color: red;

content: "hope";

}

and

.section-about{

background-color: blue;

content: "abundance";

}

You can also break variables out into a map as opposed to a list, and everything works the same:

$section-colors: (

featured: red,

about: blue

);

@each $section, $color in $section-colors {

.section-#{$section} {

background-color: $color;

}

}

This outputs the same two lines, but is more readable because the variable and value data are abstracted.  You can also more easily add items to the map.

@while Directive

Repeatedly outputs the nested styles until a certain statement evaluates to false, for example:

$i: 1;

@while $i < 10 {

.item-#{$i} {

top: 5em * $i;

$i: $i + 1;

}

}

First off, $i is set to one.  Then we run a loop until $i reaches 10, thus ending the loop.  Inside this loop, we set a class name with the $i variable, then we set a top offset with the value being a multiple of $i.  We then must increment the variable so the loop may run again with the new data.  Stops once the inequality evaluated to false.  Can increment in larger steps, if desired.

@mixins Directive

@mixins allow us to create reusable styles, for example:

@mixin featured {

font-size: 120%;

font-weight: bold;

border-color: #ff0000;

}

First we use the @mixin namespace and give it a name (featured, in this case).  Then, if we ever want to add these styles to any element, we just have to use an @include directive with the name we have given the mixin (@include featured).

Of course, this ability is the same as the @extends directive, so why are @mixins such a big deal?

@mixins allow us to perform more complex operations, like accepting arguements:

@mixin round($radius) {

border-radius: $radius;

}

.button {

@include round(5px);

}

This outputs to .button {border-radius: 5px;}, allowing us to set variable names above but pause variable values until runtime.

We can set default values for the variables by adding that data to the @mixin:

@mixin round($radius: 10px) {

border-radius: $radius;

}

This is the same code as above, but not the radius has a default value, so if no value is passed into the @mixin, SASS can still set the value.

@mixins can also include selectors, for example:

@mixin border-box {

* {

box-sizing: border-box;

}

}

@include border-box;

Outputs to * {box-sizing: border-box;} which sets all elements to have border-box sizing.

Variable Arguments

@mixin box-shadow($args...) {

-webkit-box-shadow: $args;

box-shadow: $args;

}

.element {

@include box-shadow(1px 1px 5px 0 #000000);

}

Because we have some styles with multiple values in a single declaration (box-shadow has x, y, size, and color), we use the $args… value for our box-shadow namespace, then we pass in the arguments (shadow details) and SASS interprets them correctly.  We can even have multiple sets of arguments:

.element-2 {

@include box-shadow(1px 1px 5px 0 #000, 2px 10px 15px rgba(0, 0, 0, .5));

}

This outputs correctly and places multiple shadows on .element-2.

Nested @Mixins

@mixins can also include other @mixins:

@mixin round($radius) {

border-radius: $radius;

@include featured;

}

Then, when a style is set that invokes the round @mixin, the code from the featured @mixin is added as well.

Education, Training Notes

The Art of Typography

Best Programs for Typography

  • Adobe InDesign – best for laying the type on the page
  • Adobe Photoshop – best for manipulating the type
  • Adobe Illustrator – used for creating own type styles and fonts

Fonts

If using InDesign, you have a preexisting set of fonts that are great.  If we ever want to use additional fonts, here are the best places to retrieve them:

If you need to identify a particular font, use Whats The Font from myfonts.com

  • this is also a great way to find fonts that are similar to custom fonts (primarily used by businesses)

For more information, check Thinking With Type which has great definitions and examples

History of Typography

Typography hasn’t changed much since the Renaissance period.  It all starts in 15th century Germany with Gutenberg who wanted to use movable type.  It wasn’t a new idea, it was used in China and had been imported from Italy.  His difference was the movable type printing press.  His printing press allowed for typography to evolve over time.

The first typographic style was a black letter (insert graphic) style which was popular at the time in Germany.

Black Letter font used by Johan Guttenberg
Black Letter font used by Johan Guttenberg

 

 

 

 

 

This style was used to mimic the common caligraphy used at the time, so it established the first of the typographic rules that we use to this day.

The printing revolution swept across Europe and every country had it’s own font.  Eventually, printers moved from Gothic type to move elegant font faces, which we know as Roman.  Many of these typefaces are still used today, like:

  • Garamond – Designed by Claude Garamond in France in 1530
  • Caslon – Designed by Willian Caslon in England in 1722
  • Baskerville – Designed by Jon Baskerville in England in 1757
  • Fornier – Designed by Pierre Fornier in France in 1740

By 1800’s, typographics started devoloping modern type faces, with vertical shading and non-bracketed serifs. Among these,

  • Didot – Ferman Didot in France in late 1800
  • Bodoni – By Gian Bodoni in Parma, Italy in 1798

Cheap printing continued and apace and led to rapid developments, including many of the fonts we use today, like

  • Times New Roman – by Stanley Morrison in England in 1932

The process of printing type also improved.  Letter Press Printing became overtaken by Offset Lythography Printing in 1960’s.

Typography and fonts represent the times and conditions in which they are used and developed.

What Makes a Type Face Enduring

Many of our modern typefaces are the perfect balance between legibility and elegance, with planned spaces between characters (tracking).  This is what makes typography an art form, it looks simple, but it is an exercise in perfecting your design.

Book Typesetting

Books, originally Gutenberg’s Bible, offer the first examples of typeography and typesetting in Western culture.  Currently, there is a whole field of study around typesetting and professionals are very well paid for laying out content on pages.

How Typography Has Evolved

The 20th century was the age of the poster.  We saw an explosion of commercial advertising.  This led directly to modernism and the swiss style

Modernism is a term used to define a set of styles that dominated design.  It is characterized by:

  • art deco – Geometric and lavish, decorative style
  • cubism – Pablo Piccasso

In the 1920’s, a group of Swiss designers under the axiom “Form Follows Function” applied typographic principles while focusing on:

  • Minimalism
  • Uniformity
  • Geometry
  • and Layout Grids

Additionally, they favored sans-serif fonts, focusing on the use of Helvetica.  By the 60’s, Swiss designers were considered the best-of-class and their designs and principles were considered the pinnacle of modern design.  This is also known as the International Style movement.

Check out “Just My Type” by Simon Garfield for more info.

The international style is still the dominant paradigm in typesetting.  It has a few important components:

  • It’s about the grid – break the layout into precise rows or columns to help channel the type, and get more experimental with the placement of text
  • Sans Serifs – Helvetica, Universe, and Avenir all emerged from international style.  Added benefit is that sans serif font doesn’t compete with graphics and they prioritize the text content.
  • Keep colors to a minimum – Apply fewer, high-contrasting colors to your type which makes designs stand out better.

Components of a Poster

  • A Heading – Large Title
  • B Heading – Smaller, sub headings or strap lines
  • Body Text – Main quantity of text, which will be smaller

The Art of Typography

Typography uses many rules to help lead the development of individual typographic styles in the proper direction.

Grid + Typeface + Formatting + Alignment + a bit more Formatting

Grid

  • before we start putting any content on our page, we need to define the structure of what we are creating
  • always start with the grid when designing – make use of guides and grids to achieve your baseline structure before you even begin

Typeface

  • This is a very personal decision.  That said, there are some classic typefaces (discussed earlier) that will never go out of style.
    • Garamond
    • Baskerville
    • Caslon
    • Fournier
    • Didot
    • Bodoni
  • There are also new typefaces being generated all the time, some can be used to great effect
    • Aller – Clean and simple, get from FontSquirrel
    • Paciencia – Interesting take on Serif style, get from FontSquirrel

Formatting

  • Weight – Can use the regular, bold, or italic weights, but can also use condensed, black, thin, medium, or semibold
  • Size – Determine the size of your type in point metrics
  • Leading – Space between the baseline of each line of font.  Leave atleast to auto, increase if desirable
  • Tracking – Space between characters in a line
  • Kerning – Not to be confused with tracking, kerning is the space between any two characters.  This is used to balance a word on the page.
  • Drop Cap – Pull out the first character, increase the size and place it to the left of the paragraph.  It is an appealing visual effect.

Alignment

  • Left
  • Right
  • Center
  • Justify – stretch text across the given frame
  • Toward or Away from Spine – Can also align it toward or away from the book spine

a bit more Formatting

  • Anything that needs to be modified?
  • Hyphenation?
  • Would larger block of text benefit from indents?
  • Optical Alignment – In the story panel in inDesign, probably available elsewhere, can have computer shift around text and margins for great visual appeal.

These rules are used to guide your design and a whole world of complexity and creativity can be achieved by working within these rules to develop your own style.

Type with Personality

Modern typographic designers wanted typography to be a more significant part of our lives.  They wanted type to shape our emotional response to print communications.  Here is a list of how typefaces make you feel:

  • Futura – Clean and minimal with rounded, bouncy qualities which suggest friendliness
  • Verdana – One of the most popular fonts on the web, verdana has a wide appeal internationally.  It is more edgy and shouts the information rather than simply conveys it.
  • Comic-Sans – Juvenile and slightly irritating, this font is fun yet annoys a large part of many audiences.  People dont take it seriously, or the messages conveyed through the text
  • Didot – Typeface of choice for high-end designs.  Didot and Bodoni have become the fonts for high-fashion.  The font is directed towards ladies, while Bodoni is more for everyone. Didot is aspirational, it can convey a sense of style, sophistication, and wealth beyond simply the content.  Makes you more inclined to spend money.
  • Optima – Used to convey trustworthiness and healthiness.  Also used for reflective displays, it has a light yet dignified quality.

Typefaces can embody human emotions.  It can have a significant impact on how the viewer emotes from our text.  It’s not only the font that can cause an emotional reaction, spacing and capitalization can also have an impact.  Subtle tweeks to the typography can have an outsize impact on the viewers and these messages are often received subconsciously.

When setting your type, don’t just think about the technical aspects of the font, also think about the personality and adjust the type to reflect your brand.

Is Digital Typography Art?

Typography Defined – The art, or skill, of designing communication by means of the printed word – Ruari McLean in The Thames & Hudson Manual of Typography, Page 8

We will no longer see printed works nearly as much, most of our experience with typography will consist of websites and reading text on phones and devices.  Does this make the text design any less typographic?

Digital typography is just as much of an art and a skill as printed typography.  They both share the same roots and apply the same rules.  What digital typography does entail is that we have to evolve and adapt to new ways of rendering type to audiences.

Different Branches of Typography

  • Typsetting
  • Type Design
  • Logo Design
  • Digital Typography – as the quality of web design improves, the need for understanding the use of digital typography grows as well.

Digital Typography is a separate field of typography because the methods and tools we use to achieve our typographic goals will be quite different from those used in print designs.  Conversely, as our type will need to be coded, there are additional restrictions that print designers don’t run into.  However, being able to enhance our type designs with animations and video makes the trade-off worth it.  We can create interactive designs that aren’t possible with print media.

New fonts have also been developed for use on the web.  Check out http://google.com/fonts and http://typekit.com to see the newest typefaces for the web.  New fonts are created all the time!

These new fonts allow web typographers to create print-standard works.  We can also start to create the typographic effects that were only available to print designers.  Additionally, we can prioritize the text on the page to make the content stand out.  The web is moving towards an understated minimalism, the type that good typography naturally leads to.  Web pages are becoming more legible and readable and engaging.

This trend will only accelerate as more traditional medias are overtaken by digital forms.  The future of typography is certainly digital and the new advancements are moving the field forward.

Creating Your Own Fonts

Adding your inspiration to the world of fonts couldn’t be easier than it is right now.  There are great software programs developed within the past few years to give designers the tools they need to create their own font libraries.  Amongst the software options (most are developed for Mac), here are the best:

Conclusion

In conclusion, typography is an art  form that has be continually reinvented for over 100 years, and the speed of reinvention is picking up.  The digital world offers possibilities that couldn’t have even been imagined, but it is important to use the concepts of print to ensure that your designs convey their information correctly.  For more information about these topics, use these resources:

Print Typography

  • Letterpress – Traditional typography used in a modern and hip way.  There are tons of designers whom specialize in producing designs for letterpress.
  • Publishing Design – Print book design, once a dying industry, has experienced a resurgence thanks to users preferring the printed page to eBooks.  They are looking back to traditional techniques to create nostalgic, unique items that readers can treasure.

Digital Typography

  • Websites – When looking around the web, take note of designs your really like and research the design team, odds are there are just a handful of teams whom are creating the designs that really resonate with you.
  • Responsive Typography – Jason Pamental has written a book to help with understand how to use text in a responsive fashion. Or check his website at rwt.io

 

 

Education, Programming, Training Notes

Proxy Pattern

The Proxy pattern uses one object as the interface for another object

  • It sits between users or clients of the object and the object itself
  • client makes request to proxy, proxy makes request to object
  • clients may or may not know if they are using a proxy
  • the proxy controls access to the original object (acts as a guardian)
  • often used for performance reasons
    • if the object needs to make expensive HTTP requests (or others), we make batch requests in the proxy in order to send fewer requests to the object
    • proxy can include cashe to store requests for further use
  • Proxies can also be used to delay the instantiation of a slow or resourse intensive object, when it is better for performance to delay
    • we might need the object at some time
    • this is called a Just-In-Time Proxy, which is what we will be making
    • first time that proxy invokes methods of objects will be slow, but subsequent times will be fast as object has already been initialized
    • great thing about this is even if client initializes proxy, we may not need the slow object unless a method on the slowObject is needed

Step 1 – Page: slowObject.js


// JavaScript Document
define(function () {
		'use strict';
		
		var SlowObject = function () { //set up slowObject
			this.someMethod = function () {
				console.log('some method on the slow object was invoked');	//use method to log a statement
			};
		};
		
		return {
			init: function () { //add artificial initialization delay with for loop
				for (var x = 0, max = 1000; x < max; x++) { //for loop iterates 1000 times
					console.log('slowness...');
				}
				return new SlowObject();//once loop finishes, returns new instance of slowObject
			}
		};
});

Step 2 - Page: slowObjectProxy.js


// JavaScript Document
define(function (require) {//use require function
		'use strict';
		
		var SlowObjectProxy, slowObjectInstance, //initialize variables
			slowObject = require('proxy/slowObject');
			
		SlowObjectProxy = function () { //set up constructor for proxy object
			this.someMethod = function () { //add method that matches the slowObject method
				var interval; //add the new variable
				
				if (!slowObjectInstance) { //check if the slowObject has been initialized previously
					slowObjectInstance = slowObject.init();	//if return is falsy, we haven't initialized yet, so we use init method to initialize
				} else { //if it has been initialized
					slowObjectInstance.someMethod();	//we invoke the same method on the slowObject
				}
				
				interval = window.setInterval(invokeMethodWhenExists, 100); //set this up to poll the object and wait for initizialization.
				
				function invokeMethodWhenExists() { //the above interval will invoke this method every 100 seconds in order to check if slowObject has been created yet
					if (slowObjectInstance) { //we check the slowObjectIstance variable, and if truthy
						console.log('proxying some method'); //use a log to know the proxy is working as expected
						window.clearInterval(interval); //clear the interval to stop the loop
						
						slowObjectInstance.someMethod(); //then invoke the method on the slow object
					}
				}
			};
		};
		
		return {
			init: function () {
				return new SlowObjectProxy();	
			}
		};
});

Step 3 - Page: init.js


define(function(require) {
	'use strict';

	return {
		init: function() {
			
			var myProxy, //set up variables
				slowObjectProxy = require('proxy/slowObjectProxy');
				
				myProxy = slowObjectProxy.init(); //initialize the slowObject, which delayed by the interval
				myProxy.someMethod();
		}
	};
});

Step 4 - Page: main.js


// JavaScript Document
require (
	['proxy/init'],
	function ( proxy) {
			'use strict';
	
			var examples = {
					
					proxy:proxy
				};
			
			window.runExample = function (example) {
				examples[example].init();
			};
	}
);

Conclusion

The proxy pattern can be used to control access another object, either because it takes a long time to initialize or it is an expensive operation to carry out

  • proxy exposes same interface as the original object and sits between client and object, intercepting requests and handling on behalf of the object.
Education, Programming, Training Notes

Composite Pattern

Used to treat single objects or collections of objects in the same way

Compositions are used to create nested structures of nodes

  • a node may be a single node (leaf) or a container of nodes
  • the ability to iterate through the composite beginning from any node and moving up the tree

What we will be doing:
  • children with no children are leafs
  • children with kids are containers
  • Step 1 – Page: node.js

    
    // JavaScript Document
    define(function () {
    		'use strict';
    		
    		var Person = function (name) { //set up Person object constructor
    			this.name = name; //add name to a property of the object
    			this.children = []; //add children as property and set to empty aray
    			this.parent = null;	//add parent as property as set to null
    		};
    		
    		Person.prototype.addChild = function (child) { //set up method to add children to Person object
    			this.children.push(child);	//push the child arguement into the children array for the object
    			child.parent = this; //create a reciprocal link by setting current person as parent of child passed to the method.  We need this reciprocal link so we can traverse up and down the tree
    		};
    		
    		Person.prototype.traverseUp = function () { //set up method to traverse up
    			if (this.parent) { //check whether current object has parent
    				console.log(this.name + ' is the child of ' + this.parent.name); //if it does, log out a message
    				this.parent.traverseUp(); //then invoke traverseUp method of parent
    			} else { // if there are no parents
    				console.log(this.name + ' is the root node'); //we then know this is a root node
    			}
    		};
    		
    		Person.prototype.traverseDown = function () { //set up traverseDown
    			if (this.children.length) { //check for children
    				this.children.forEach(function (child) { //if so, iterate through children collection
    							console.log(this.name + ' is the parent of ' + child.name); //send out log statement
    							child.traverseDown(); //then invoke traverseDown on child
    				}, this);//set the context for the forEach method, so inside the handler, this still refers to current person objects
    			} else { //if no children
    				console.log(this.name + ' is a leaf node');	//then object is a leaf node
    			}
    		};
    		return Person; //return the person constructor
    });
    

    Step 2 – Page: init.js

    
    define(function(require) {
    	'use strict';
    
    	return {
    		init: function() {
    			
    			var Node = require('composite/node'), //require in node.js
    				root = new Node('Fred'), //set up nodes, al nodes are created in same way
    				child1 = new Node('John'),
    				child2 = new Node('Jane'),
    				child3 = new Node('Jack'),
    				child4 = new Node('Jill'),
    				child5 = new Node('James'),
    				child6 = new Node('Jess')
    				
    				root.addChild(child1); //add two children to root node, then leave child1 as leaf
    				root.addChild(child2);
    				
    				child2.addChild(child3); //add child nodes to child2, making it a container
    				child2.addChild(child4);
    				
    				child4.addChild(child5); //leave child3 as leaf, and make child4 a container with one child
    				
    				child5.addChild(child6); //child5 is container, and child6 is lowest leaf on the tree
    				
    				root.traverseDown(); //displays entire tree
    				root.traverseUp(); //root is the top level, so returns that root is a root node
    				
    				child6.traverseUp(); //displays entire tree
    				child6.traverseDown(); //bottom level, so returns that Jess is a leaf node with no children
    		}
    	};
    });
    

    Step 3 – Page: main.js

    
    // JavaScript Document
    require (
    	['composite/init'],
    	function (composite) {
    			'use strict';
    	
    			var examples = {
    					
    					composite: composite
    					
    				};
    			
    			window.runExample = function (example) {
    				examples[example].init();
    			};
    	}
    );
    
    

    Conclusion

    Main purpose of composite pattern is to allow single objects or collections of objects to be used in the same way

    • we don’t need to know if object is container or leaf, we can process it the same way.
    Education, Programming, Training Notes

    Adapter Pattern

    • Used to convert one interface to another
    • an objects interface is the method and properties exposed by the object, what we use to interact with the object
    • useful pattern when something changes and we don’t want to go throughout code and refactor the object
      • It’s not necessary to use this pattern if the object you are changing doesn’t have a lot of dependencies

    Step 1 – Page: oldInterface.js

    
    // This will be a email validation script that will check to see if the string has an at symbol
    define(function () {
    		'use strict';
    		
    		var OldInterface = function () { }; //set up an object constructor
    		
    		OldInterface.prototype.doSomethingOld = function () { //add a method to the constructor prototype
    			console.log('doing the old thing');
    		};
    		
    		return new OldInterface(); //return a new instance of the object
    });
    

    Step 2 – Page: newInterface.js

    
    // This will be a email validation script that will check to see if the string has an at symbol
    define(function () {
    		'use strict';
    		
    		var NewInterface = function () { }; //set up an object constructor
    		
    		NewInterface.prototype.doSomethingNew = function (newArg) { //add a method to the constructor prototype
    			console.log('doing the ', newArg);
    		};
    		
    		return new NewInterface(); //return a new instance of the object
    });
    

    Step 3 – Page: adapter.js

    
    // This will be a email validation script that will check to see if the string has an at symbol
    define(function (require) {
    		'use strict';
    		
    		var newInterface = require('adapter/newInterface'); //require in the new interface
    		
    		return {
    			doSomethingOld: function () { //reset the method from the oldInterface with the method from the new interface
    				return newInterface.doSomethingNew('new thing');	
    			}
    		};
    });
    

    Step 4 – Page: init.js

    
    define(function(require) {
    	'use strict';
    
    	return {
    		init: function() {
    			
    			var OldInterfaceAdapter = require('adapter/adapter'); //set up new variable for OldInterface and rename to OldInterfaceAdapter to make it clear to any subsequent coders that we are using an adapter for the oldInterface
    			
    			OldInterfaceAdapter.doSomethingOld();
    		}
    	};
    });
    

    Step 5 – Page: main.js

    
    // JavaScript Document
    require (
    	['adapter/init'],
    	function (adapter) {
    			'use strict';
    	
    			var examples = {
    					
    					adapter:adapter
    				};
    			
    			window.runExample = function (example) {
    				examples[example].init();
    			};
    	}
    );
    
    

    Conclusion

    The Adapter pattern allows us to change one part of our application without changing the others. It is also a good example of a design pattern you wouldn’t use when developing your application. Adapters are only needed when there is a change between dependencies, so this pattern only arises when issues occur.

    • it is common to use design patterns when refactoring code to make things work better and more efficiently
    Education, Photography, Training Notes

    Decorator Pattern

    Structural pattern used to add new functionality to existing objects

    • using JavaScript we can extend classes whenever we want, but the decorator pattern is still used to minimize the amount of sub-classes we will need

    Use-Case

    User class represents a member of staff at an organization. All members have read access to documents, but administrators have right access and other behaviors and executives need access to private docs. If we used sub-class method, we would already have a huge anough of sub classes with this simple example. So instead, we use decorators

    We have a simple base class which we need to use to build different objects from. Some will need certain behaviors, some will need different ones, and some wont need any

    • we can create different sub class for every combination of behaviors, but this is hard to maintain as project grows
    • we will use decorators for each variation and then apply them to objects as required

    Step 1 – Page: user.js

    
    // JavaScript Document
    define(function () {
    		'use strict';
    		
    		var User = function (id) { //create a simple constructor
    			this.id = id;
    			this.getPermissions = function () { //user objects have a method called getPermissions, which details their level of access to the application
    				return 'public:read';	
    			};
    		};
    		
    		User.prototype.decoratePermissions = function (decorator) { //user objects also have method for user objects to inherit permissions
    			this.getPermissions = decorator.getPermissions; //this method is passed new decorator, and overrights getPermissions property
    		};
    		
    		return User;  //return the constructor
    });
    

    Step 2 – Page: exec.js

    
    // JavaScript Document
    define(function () {
    		'use strict';
    		
    		return {
    			getPermissions: function () { //the exec decorator returns a method fo switch teh getPermissions param to confidential:read
    				return 'public:read, condidential:read';	
    			}
    		};
    });
    

    Step 3 – Page: admin.js

    
    // JavaScript Document
    define(function () {
    		'use strict';
    		
    		return {
    			getPermissions: function () { //the admin decorator returns a method fo switch the getPermissions param to confidential:write
    				return 'public:read, condidential:write';	
    			}
    		};
    });
    

    Step 4 – Page: init.js

    
    define(function(require) {
    	'use strict';
    
    	return {
    		init: function() {
    			var user1, user2, //set up 2 users
    			User = require('decorator/user'), //require in the User constructor and the 2 decorators
    			execDecorator = require('decorator/decorators/exec'),
    			adminDecorator = require('decorator/decorators/admin');
    			
    			user1 = new User('user1'); //new user should have public read permissions
    			user1.decoratePermissions(execDecorator); //this will change the user status to exec, and give the confidential:read priviledges
    			
    			user2 = new User('user2'); //set up new user2
    			user2.decoratePermissions(adminDecorator); //give admin privs
    			console.log(user1.getPermissions());
    			console.log(user2.getPermissions());
    		}
    	};
    });
    

    Step 5 – Page: main.js

    
    // JavaScript Document
    require (
    	['decorator/init'],
    	function (decorator) {
    			'use strict';
    	
    			var examples = {
    					decorator:decorator
    				};
    			
    			window.runExample = function (example) {
    				examples[example].init();
    			};
    	}
    );
    
    

    Conclusion

    We looked at simple decorator pattern

    • used to add new behavior to objects
    • minimizes the number of sub-classes an application must maintain
    Education, Programming, Training Notes

    Facade Pattern

    The facade is a simple interface that is shown to the public to hide the complexity of the underlying system

    • they conceal the implementation
    • It is a structural pattern that simplifies the use of your API
    • It also shields developers from being locked to an architecture (can change the internals while keeping the look the same to the public)
    • It has been used for a long time in JavaScript, ever since frameworks wrapped a simple interface around the disparate browser API’s

    Step 1 – Page: processor.js

    
    // JavaScript Document
    define(function() {
    	'use strict';
    	
    	return { //module returns an API of 5 methods that each deal with a different data type.  This is just for example, the processing isn't complex or necessarily useful.  Module doesn't depend on facade, just exposes the API methods.  It could have dependencies with other modules, but should never depend on facade.  Facade depends on this.
    		processString: function (string) { 
    			return string.substring(0, string.length / 2);
    		},
    		processNumber: function (number) {
    			return number * number;
    		},
    		processBoolean: function (bool) {
    			return !bool;
    		},
    		processArray: function (array) {
    			return array.length;
    		},
    		processObject: function (object) {
    			return Object.keys(object).length;	
    		}
    	};
    });
    

    Step 2 – Page: facade.js

    
    // JavaScript Document
    define(function(require) { //must use require function to load the processor module
    	'use strict';
    	
    	var processor = require('facade/processor'); //load the processor as a dependency
    	
    	return { //return the single method contained by the facade
    		processData: function (data) { //this is the method exposed by the facade
    			switch (Object.prototype.toString.call(data)) { //in this method, we use a switch statement to invoke a processor method depending on the data type passed to the facade.  Value that we switch upon is the data type.  We use object.prototype.toString.call method to convert data type to object String, object Number, object Boolean, etc.  We then switch on this
    				case '[object String]':
    					return processor.processString(data);
    					break;
    				case '[object Number]':
    					return processor.processNumber(data);
    					break;	
    				case '[object Boolean]':
    					return processor.processBoolean(data);
    					break;
    				case '[object Array]':
    					return processor.processArray(data);
    					break;
    				case '[object Object]':
    					return processor.processObject(data);
    					break;
    				default:
    					return 'Unable to process the data';
    			}
    		}
    	};
    });
    

    Step 3 – init.js

    
    define(function(require) {
    	'use strict';
    
    	return {
    		init: function() {
    			var facade = require('facade/facade'); //add the facade as a dependency
    			
    			console.log(facade.processData('test string')); //log out a bunch of statements
    			console.log(facade.processData(5));
    			console.log(facade.processData(false));
    			console.log(facade.processData([1, 2, 3]));
    			console.log(facade.processData({prop: 'something', other: 'else'}));
    		} //this init file is nicely decoupled from processor.  Processor can be refactored as needed, as long as API methods are the same
    	};
    });
    

    Step 4 – main.js

    
    // JavaScript Document
    require (
    	['facade/init'],
    	function ( facade) {
    			'use strict';
    	
    			var examples = {
    					
    					facade: facade
    				};
    			
    			window.runExample = function (example) {
    				examples[example].init();
    			};
    	}
    );
    
    

    Conclusion

    With a facade, we can hide the complexity of the underlying system and just expose a way to interact with the system. It presents a simplified API as the means of working with the application. The subsystems (or modules like the processor) can be changed or refactored as necessary, as long as the API methods remain the same.

    Education, Programming, Training Notes, Web Design

    Speech Synthesis API

    Here is a brand new addition to browser API’s, the Speech Synthesis API.  It is used to make the browser read text out loud to the viewer, and can be implemented for many different effects.  Want a congratulations to be sent to the visitor?  Now you aren’t constrained to simple visual input.  I’ll be extending this with the web audio API in the future, but I wanted to share this new discovery with you today.  Here is how to set things up.

    var utterance  = new SpeechSynthesisUtterance();

    That line will initialize the Speech Synthesis object in the browser, now we need to tell it what to say:

    utterance.text = 'I may be a computer, but I want to be a real boy!';

    That line places a string property for the utterance variable with the supplied text. Now we just need to string the pieces together:

    speechSynthesis.speak(utterance);

    That line will invoke the Speech Synthesis object and pass it the utterance variable, which we set with a text property that will now be read by the browser! Toss those three lines into your browser console right now to see them in action!

    Pretty cool, huh! Now extend your knowledge with the Browser Speech Tutorial from Envato Tuts+, one of my favorite places to go to keep learning about emerging technologies.  Thanks for stopping by!

    Education, Programming, Training Notes

    Iterator Pattern

    Javascript itself has iteration built into the language

    • there are a number of for and forEach methods to iterate through arrays
    • we have the forIn loop to iterate through objects

    Iterator pattern is different as it doesn’t run in a synchronous loop and the iterator keeps track of which items have been processed

    • we manually choose when to extract the data of the next item
    • the purpose is to provide access to the items in a collection contiguously, while keeping track of which items have been accessed
    • common to have a next() method which returns next item in collection
    • some libraries have hasNext, isDone, first, and reset()
    • in JS ES7, iterators will be added as a core part of the language, we have to create our own for the time being, look here for more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators

    Step 1 – Page: iterator.js

    
    // JavaScript Document
    define(function() {
    	'use strict';
    	
    	var Iterator = function(collection) { //define object constructor, which is passed a collection of items
    		this.collection = collection; //store this collection as a property of the object
    		this.index = 0; //set up an index property to keep track of which items have been processed.  Initialized to 0
    	};
    	
    	Iterator.prototype = {
    		constructor: Iterator, //first thing we need to do is set constructor property for the prototype object to the constructor we created.  If we don't do this, the constructor will point to the object constructor instead.
    		next: function () {
    			return this.collection[this.index++]; //this is the next method, which is a critical component of an iterator.  We are simply returning the next item in the collection with the index property, then we are incrementing it by 1
    		},
    		isDone: function () {
    			return this.index === this.collection.length; //set up isDone method that returns true once all the items in the collection have been iterated through.  We are returning whether the index equals the length of the collection (# of items in the array)
    		},
    		reset: function () { //set up reset method to set the index back to 0, in case we want to iterate again
    			this.index = 0;
    			return this; //then return the iterator so that other methods can be chained on after the reset
    		},
    		take: function (numberOfItems) { //the take method will return a specified number of items and update the index accordingly.  It will receive the number of items we want to take as an argument
    			var newIndex = this.index + numberOfItems, //calculates what the new index will be by adding numberOfItems to the current index and stores this in a variable
    				newArr = Array.prototype.slice.call(this.collection, this.index, newIndex); //we then create a new array using the slice method.  Pass the collection to the call method to as the first argument to set the collection as the this object.  We then pass in the current index as the index to start slicing from. The newIndex is the set as the second argument
    				
    			this.index = newIndex; //set iterators index to the new index
    			return newArr;	//return the new array
    		}
    	};
    	
    	return { //return an object from the module that has one build method.  This is an implementation of the factory pattern
    		build: function (collection) { //build method is passed the collection.  We only need this if object is passed to iterator, in which case we have to build an array for us to work with the data.
    			var keys = Object.keys(collection), //keys method of object constructor will create an array of all the keys in the object.
    				tempArray = [],
    				prop;	
    				
    			if (typeof collection === 'number') { //if a number is passed into the iterator
    				collection = collection.toString();	//convert the number to a string and the iterator can work with it
    			}
    			
    			if (keys.length) { //if object is passed, it is a collection of key value pairs that can be parsed
    				for (prop in collection) { //extract the values from the object
    					tempArray.push(collection[prop]);	//construct a new array from these values
    				}
    				collection = tempArray;//send these values to the iterator
    			}
    			
    			if (collection.length) { //if the collection exists
    				return new Iterator(collection); //initialize the iterator
    			} else {
    				throw ('Iterator cannot be built from Boolean, null, or undefined data');	
    			}
    		}
    	};
    });
    

    Step 2 – Page: init.js

    
    define(function(require) {
    	'use strict';
    
    	return {
    		init: function() {
    			var iterator = require('iterator/iterator'), //load the iterator
    				testArray = [{ something: 'yay', other: 123}, {something: 'test', other: 456}], //create a test array
    				myArrayIterator = iterator.build(testArray), //build the array into the iterator, where we can then iterate through data
    				testString = 'teststring', //set up test string
    				myStringIterator = iterator.build(testString); //send testString to iterator
    				
    			console.log(myArrayIterator.next()); //log the data from the first index in the array
    			console.log(myArrayIterator.next()); //log the data from the next index
    			
    			while (!myStringIterator.isDone()) { //loop through test string
    				console.log(myStringIterator.next());	//log the next data in the testString loop
    			}
    			
    			console.log(myStringIterator.reset().take(4).join('')); //we can reset the iterator, then use the take method to choose single values from the array (this will grab the first 4).  We then join the data to create a word.
    		}
    	};
    });
    

    Step 3 – main.js

    
    // JavaScript Document
    require (
    	['iterator/init'],
    	function (iterator) {
    			'use strict';
    	
    			var examples = {
    					iterator: iterator
    				};
    			
    			window.runExample = function (example) {
    				examples[example].init();
    			};
    	}
    );
    
    

    Conclusion

    Iterator pattern isn’t as common is JavaScript, but it will soon become a core component of the specification. It decouples the processing of a collection of items, from the collection itself

    • we don’t need to know what the data is or what type, the iterator is designed to control for all events.
    Education, Programming, Training Notes

    Mediator Pattern

    Situation: If you have multiple independent modules that work in a system (parts of a web page or a user interface system) and they must be kept seperate from eachother and aren’t allowed to communicate directly

    Solution: Install a mediator and modules can communicate through mediator, which handles requests and directs the requests to the appropriate module

    • modules that need to communicate are known as colleagues

    Step 1 – Page: colleague.js

    
    // JavaScript Document
    define(function() {
    	'use strict';
    	
    	var Colleague = function (id, mediator) { // In this step, we will set up colleage constructor.  It accepts arguments of id and an instance of the mediator.  They are set as properties of the colleage instance, below...
    		this.id = id;
    		this.mediator = mediator;
    	};
    	
    	Colleague.prototype.receiveMessage = function (message) { //now we extend the Colleage constructor with a method to receive messages
    		console.log('Module', this.id, 'received message:', message); //receives the message as an argument and logs it to the console
    		return true; //return true once the logging has occurred
    	};
    	
    	Colleague.prototype.sendMessage = function (message, recipientId) { //extend class with method to send mesage, accepts the message and a recipient ID
    		(recipientId) ? this.mediator.send(recipientId, message) : //if you are given a recipientID, then use the mediator send method to send the message to the prescribed colleague.  If recipientID is not supplied...
    			this.mediator.broadcast(message, this); //use the mediator broadcast method to send the message to all colleagues.  We also pass the current id to the broadcast as to prevent the broadcast from sending the message to the colleague that sent it.
    	};
    	
    	return {//rather than return the constructor like we usually do, we will be returning an object with a create method.  
    		create: function (id, mediator) {
    				var that = new Colleague (id, mediator); //Inside this method, we will initialize a new colleage and register it with mediator before passing back the new colleage
    				
    				mediator.register(that);
    				
    				return that;
    		}
    	};
    });
    

    Step 2 – Page: mediator.js

    
    // JavaScript Document
    define(function() {
    	'use strict';
    	
    	var Mediator = function () { //set up mediator constructor
    		this.colleagues = [];	//this will need to store all colleagues that it will be mediating for.  We don't know them all right now, so set this up as empty array
    	};
    	
    	Mediator.prototype.register = function (colleague) { //this method will register a colleague with the mediator
    		this.colleagues.push(colleague); //by pushing the current collegue into the colleagues array
    	};
    	
    	Mediator.prototype.send = function (recipientId, message) { //this sets up the send method, which sends messages to individual colleagues.  Pass in recipiendId and message
    		this.colleagues.some(function(colleague) { //now we iterate through some of the ids in the collegue array.  Some method works similiarly to forEach method in that it invokes a callback on items in an array.  It will keep invoking callback until return is true, then it stops.
    			if (colleague.id === recipientId) { //this works because send method is only trying to send the message to the intended recipient, so once it finds it's destination, we don't have to keep parsing through the array
    				return colleague.receiveMessage(message);	//it then returns the value from the receiveMessage method on the colleague, which will return true once we are one the target recipient
    			}
    		});
    	};
    	
    	Mediator.prototype.broadcast = function (message, sender) { //sets up broadcast method, receive message to send
    		this.colleagues.forEach(function(colleague) { //uses foreach method to iterate through entire array and run callback function
    			if (colleague.id !== sender.id) { //the function sends the message to all colleagues except the colleague with a matching sender.id
    				colleague.receiveMessage(message);	
    			}
    		});
    	};
    	
    	return Mediator; //return constructor
    });
    

    Step 3 – Page: init.js

    
    define(function(require) {
    	'use strict';
    
    	return {
    		init: function() {
    			var mediator, colleague1, colleague2, colleague3, //set up variables
    				Mediator = require('mediator/mediator'), //set up object constructors
    				colleague = require('mediator/colleague');
    				
    			mediator = new Mediator(); //create new instance of object
    			colleague1 = colleague.create('colleague1', mediator); //create colleagues
    			colleague2 = colleague.create('colleague2', mediator);
    			colleague3 = colleague.create('colleague3', mediator);
    			
    			colleague1.sendMessage('Hey there', 'colleague2'); //send message from colleague 1 to 2
    			colleague2.sendMessage('Hi colleague1', 'colleague1');
    			colleague3.sendMessage('Hey guys!'); //broadcast a message with no recipient
    		}
    	};
    });
    

    Step 4 – Page: main.js

    
    // JavaScript Document
    require (
    	['factory/init', 'pubSub/init', 'strategy/init', 'observer/init', 'COR/init', 'mediator/init'],
    	function (factory, pubSub, strategy, observer, COR, mediator) {
    			'use strict';
    	
    			var examples = {
    					factory: factory,
    					pubSub: pubSub,
    					strategy: strategy,
    					observer: observer,
    					COR: COR,
    					mediator: mediator
    				};
    			
    			window.runExample = function (example) {
    				examples[example].init();
    			};
    	}
    );
    
    

    Mediator Pattern is great for decoupling a group of modules that need to work together, but don’t need to know about eachother. Instead of every module depending on every other module, creating a tangled mess of dependencies, we can have them interact through the mediator.

    Education, Programming, Training Notes

    Strategy Pattern

    The strategy pattern is used to allow for a behavior to be selected at code run time.

    • this can be based on input data or other cues
    • The different behaviors are knows as the strategies
    • The strategy pattern is easy to implement in JS, but it’s not as commonly used as some of the other design patterns
    • This pattern is most useful in the situation that you have lots of similiar behaviors or modules doing similiar actions and you can’t code in which behavior will occur when the code runs live

    The strategy module needs to expose a method for the strategy or behavior to be selected. It must also provide a way for the selected strategy (also called concrete strategy) to be invoked or used.

    The beauty of this pattern is that main strategy doesn’t know anything about concrete (sub) strategies, and vice-versa. This makes it easy to add or remove stategies in the future.

    Implementation

    Page: strategy.js


    // JavaScript Document
    define(function () {
    'use strict';

    var Validator = function () {}; //this sets up main validation subroutine. In this example, we are creating a data validation script that will be different depending on what type of data is being validated.

    Validator.prototype.selectValidator = function (validator) { //this allows for the concrete strategies to be selected.

    this.validator = validator; //This will receive the strategies as an argument, and can set the argument as a property of the main validator.

    return this; //return the main validator to enable chaining
    };

    Validator.prototype.validate = function (value) { //simple validate method that invokes the sub-validation strategy of the same name. It receives the value to validate as an argument, so we must make sure a validator has been selected before we attempt to use it. If not, we will throw and error.
    if (this.validator) {
    return this.validator.validate(value);
    }
    throw ('No Validator Selected');

    };

    return Validator; //return the object constructor
    });

    Page: telValidator.js


    // This will be a telephone validation script that will check to see if the numbers entered into a telephone form object are valid
    define(function () {
    'use strict';

    return {
    validate: function (value) { //the validation function receive the data to evaluate as a value
    return (/^[0-9]{10}$/g).test(value);
    }
    };
    });

    Page: emailValidator.js


    // This will be a email validation script that will check to see if the string has an at symbol
    define(function () {
    'use strict';

    return {
    validate: function (value) { //the validation function receive the data to evaluate as a value
    return value.indexOf('@') !== -1; //this line checks if there is an @ symbol in the entered string
    }
    };
    });

    Page: init.js


    define(function(require) {
    'use strict';

    return {
    init: function() {
    var Strategy = require('strategy/strategy'),
    telValidator = require('strategy/telValidator'),
    emailValidator = require('strategy/emailValidator'),
    validator;

    validator = new Strategy(); //create a new validator by invoking strategy constructor

    console.log(validator.selectValidator(telValidator).validate(123456789)); //this is testing the validation strategy for a 9 digit number, which should fail validation

    console.log(validator.selectValidator(emailValidator).validate('jamesAtjamesportis.com'));//testing email varification strategy, no at symbol so this should fail
    }
    };
    });