# javascript:

### create.your.own('library');

Created by Paul Balchin

`←` `→` `↑` `↓` navigate
`Esc` bird's eye view

## barbie.com's JavaScript library

Functions attached to object trees.

    //SIMPLIFIED EXAMPLE
    mattel = {};
    mattel.loginreg = {};
    mattel.loginreg.variables = {};
    mattel.loginreg.login = function(){};
    mattel.loginreg.logout = function(){};
    mattel.loginreg.isUnder13 = function(){};
    mattel.loginreg.isOver13 = function(){};

↓

1. There are no advantages to this structure
2. All the functions are public
3. None of the functions can share scope

What we really want are functions that look like objects

## The humble function

    var functionName = function(){
        console.log('called functionName()');
    };

↓

Call the function; get a result

    //CONSOLE
    functionName() → 'called functionName()'

## The immediately-invoked function

Just add parens at the end

    var functionName = function(){
        console.log('called functionName()');
    }();

    //CONSOLE
    'called functionName()'

Look ma, no hands!

↓

You can wrap the entire function in another set of parens

    var functionName = (function(){
        console.log('called functionName.init()');
    }());

This is a matter of convention only

Think of it as a declaration

## Popular ways to initialize a function

The set up

    var functionName = (function(){
        console.log('called functionName()');

        var init = function(){
            console.log('called functionName.init()');
        };

        return {
            init: init
        };
    }());

Call immediately

    functionName.init();

Race conditions? External dependencies?

↓

    var functionName = (function(){
        console.log('called functionName()');

        var init = function(){
            console.log('called functionName.init()');
        };

        return {
            init: init
        };
    }());

Call on document ready

    $(document).ready(function(){
        functionName.init();
    });

Where do you put it?

↓

    var functionName = (function(){
        console.log('called functionName()');

        var init = function(){
            console.log('called functionName.init()');
        };

        return {
            init: init
        };
    }());

Call from somewhere in the HTML

    <script>
        functionName.init();
    </script>

↓

Called from partials? Views? Layouts?

# ?

## Initialize from within

    var functionName = (function(){
        console.log('called functionName()');

        // this is an init()
        $(document).ready(function(){
            console.log('called functionName.document.ready()');
        });
    }());

    //CONSOLE
    'called functionName()'
    'called functionName.document.ready() '

↓

1. No need to create separate, public methods
2. Has access to private (and scoped!) methods and properties

## Various ways to initialize

    var functionName = (function(){
        var a, b, c;
        var functionOne = function(){};
        var functionTwo = function(){};
        var functionThree = function(){};

        // types of inits(): event-driven
        $(document).ready(functionName);
        $(document).on('click',functionName);
        $(window).load(functionName);
        $(window).resize(functionName);

        // types of inits(): just call it
        // (where race conditions don't apply)
        functionOne();
    }());

## Initialize with conditions

    var functionName = (function(){
        var doSomethingWithHtml = function(){
            console.log('called functionName.doSomethingWithHtml()');
        };
        var doSomethingWithClick = function(){
            console.log('called functionName.doSomethingWithClick()');
        };

        $(document).ready(function(){
            // limit usage to specific HTML
            if( $('#htmlSelector').length > 0 ){
                doSomethingWithHtml();
            }
        });
    }());

↓

1. Conditional initialization is best practice
2. Proper use of CSS classes and IDs is very useful
3. Functionality is tied to specific HTML, not specific pages

## Initialize events

    var functionName = (function(){
        var a, b, c;
        var onClickButtonOne = function(){};
        var onClickButtonTwo = function(){};
        var functionThree = function(){};
        var functionFour = function(){};

        $(document).ready(function(){
            // list of actions only, do the work above
            $(document).on('click', '#actionButtonOne', onClickButtonOne);
            $(document).on('click', '#actionButtonTwo', onClickButtonTwo);
        });
        $(window).load(function(){
            // list of actions only, do the work above
            functionThree();
        });
    }());

↓

    //CONSOLE
    functionName → 'undefined' // Wait. What?

## You can't build a library on "undefined"

    var functionName = (function(){
        console.log('called functionName()');
    }());

    //CONSOLE
    'called functionName()'
    functionName → 'undefined' // WHAT!?

Immediately-invoked functions that return nothing
are fire and forget

If you return nothing, then there's nothing to pass back to the variable name

## A function can return one thing

    var functionName = (function(){
        console.log('called functionName()');

        // return what?
    }());

That's a pretty limited option.

↓

1. We need the option to return more than one thing
2. We're still looking to build an object-based library

## We return an object

    var functionName = (function(){
        // everything is private by default
        var a, b, c;
        var functionOne = function(){};
        var functionTwo = function(){};
        var functionThree = function(){};

        // except what is returned as public here
        return {
            FunctionOne: functionOne,
            FunctionTwo: functionTwo
        };
    }());

    //STRUCTURE
    functionName → {
        FunctionOne: function (){},
        FunctionTwo: function (){}
    }

## Congratulations!

You've created a JavaScript namespace!

    var namespace = (function(){
        var a, b, c;
        var functionOne = function(){};
        var functionTwo = function(){};
        var functionThree = function(){};

        return {
            FunctionOne: functionOne,
            FunctionTwo: functionTwo
        };
    }());

    //STRUCTURE
    namespace: {
        FunctionOne: function (){},
        FunctionTwo: function (){}
    }

1. A group of related variables and functions
2. wrapped in another function (scope!)
3. that looks like an object

## Build your library of namespaces

    var namespace = (function(){...}());
    var namespace.nestedNamespace1 = (function(){...}());
    var namespace.nestedNamespace2 = (function(){...}());
    var namespace.nestedNamespace2.nestedNamespace2A = (function(){...}());
    var namespace.nestedNamespace2.nestedNamespace2B = (function(){...}());
    var namespace.nestedNamespace3 = (function(){...}());

    //STRUCTURE
    namespace: {
        FunctionOne: function (){},
        FunctionTwo: function (){},
        nestedNamespace1: {
            FunctionOne: function (){},
        },
        nestedNamespace2: {
            FunctionOne: function (){},
            FunctionTwo: function (){},
            FunctionThree: function (){},
            NestedNamespace2A: function (){
                FunctionOne: function (){},
                FunctionTwo: function (){},
            },
            NestedNamespace2B: function (){},
        }
    }

## Build each namespace

    var namespace = (function(){
        //scoped properties and variables,
        //scoped get/set functions for all public properties,
        //scoped core functions,
        //    for each core function
        //        scoped variables,
        //        exception handling
        //        code
        //initialization(s),
        //public declarations.
    }());

## A namespace function that returns nothing?

    var namespace = (function(){
        //scoped properties and variables,
        // --scoped get/set functions for all public properties,--
        //scoped core functions,
        //    for each core function
        //        scoped variables,
        //        exception handling
        //        code
        //initialization(s),
        // --public declarations.--
    }());

1. Public declarations are created to respond to the needs of outside code.
2. It's perfectly valid to build a function that can autonomously react to the outside world, à la fire and forget.
3. But then, what's the point of adding it to the library? Maybe just organization.

### "Micro management" vs. "Fire and forget"*

Micro management

1. Create your library
2. Decide which files will load on which layouts
3. Decide which files will load on which pages
4. Decide which files will load on which partials
5. Decide how they will be bundled
6. Decide how they will be loaded
7. For each new page on the site, return to step 2
8. For each addition to your library, return to step 2

* There are exceptions to every rule.

↓

Fire and forget

1. Create your library
2. Bundle all your files together
3. Load your entire library on each layout page

Keep it simple

1. We load all of jQuery and plugins on every page
2. We load all of our layout engine on every page
3. Why not load all of our library on every page?

# Thank You

(And there's more slides further on)

## JavaScript tips

↓

### Comment your code

Liberally.

It won't add to the file size in production because minification will strip it out.

↓

### All JavaScript should be in *.js files

JavaScript files are cached by the browser

↓

### Strive for unobstrusive JavaScript

Noob

    <span onclick="updateUserProfile();">Save your changes</span>

Pro

    //HTML
    <span class="updateUserProfile">Save your changes</span>

    //JAVASCRIPT
    $(document).on('click', '.updateUserProfile', onUpdateUserProfile});

Event handlers are your friends
(on click, on document ready, on window load, etc.)

↓

### Hoist your variables

1. Functions are the only JavaScript objects that provide scope
2. Always instantiate your variables at the top of each function
3. Using "var" in an if statement or in the middle of a loop is asking for trouble
4. Google "javascript hoisting" or go to http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

↓

### JavaScript is not C#

In JavaScript, you usually create a variable for two reasons:

1. You need to reference a value more than once,
2. You need to maintain the readability of your code, and.Inserting().your('convoluted')[valueName] inside even more code makes it hard to make sense of.

You don't have to create a variable
for the sake of accessing a value.

## jQuery tips

↓

### Don't use the $() shortcut

So similar,

    $(object); // <-- example 1
    $('selector', object); // <-- example 2

yet so far apart.

    $(document).ready(callThisFunction); // <-- example 1 explained
    $(jQueryObject).find('string'); // <-- example 2 explained

Don't be afraid to be verbose:

1. Be kind to the next developer that will have to look at your code
2. There's no performance difference, but it's much easier to read

## CSS tips

↓

### Comment your code

Liberally.

It won't add to the file size in production because minification will strip it out.

↓

### No inline CSS

Noob

    <div style="padding:10px;">

↓

### All CSS should be in *.css files

CSS files are cached by the browser

↓

### Use CSS classes and IDs to identify functionality

dashed-css-classes for styling

    <div class="button-green">
    <div class="list-of-products">

camelCaseClasses for JavaScript hooks

    <div class="updateUserProfile">
    <div class="expandCollapseProductDetails">

Mix and match

    <div class="button-green updateUserProfile">
    <div class="list-of-products expandCollapseProductDetails">

## HTML tips

↓

### Layouts

Use <div> and <span> liberally for your layouts; search engines treat them as "scaffolding" tags and are not considered semantic markup.

↓

### The right tag for the job: Buttons

Buttons (<button> or <input type="button">) are form elements and are for submitting forms

(You can blame ASP.NET for their abuse. Read on.)

↓

### The right tag for the job: Anchors 1/3

    //STANDARD USE
    <a href="/product-details.html?id=345">Details for 345</a>

Anchors are for linking one page to another, and the href is required. It is the only HTML tag search engines use to crawl your site if you don't provide them with a site map.

↓

### The right tag for the job: Anchors 2/3

    //JAVASCRIPT INTERCEPTION
    <a href="/product-details.html?id=345"
       onclick="showModal(); return false;">Details for 345</a>

    // 1. Provides a URL for search engines to follow.
    // 2. When clicked, the user sees a modal instead.

Event handlers, like onclick, are called first and the href last.

Be careful: If you don't return false (here or in the function), the browser will immediately follow the link.

↓

### The right tag for the job: Anchors 3/3

The right way

    <a href="/product-details.html?id=345"
       onclick="showModal(); return false;">Details for 345</a>

The wrong way

    <a href="#" onclick="showModalDetails('345');">Details for 345</a>

    // 1. Improper use of a named anchor,
            e.g. href="#" means "scroll to top of page, then scroll to # on page".
    // 2. No URL for search engines to follow.
    // 3. If you don't "return false" you will:
    //    a. add a "#" to the end of your URL (e.g. "yoursite.com/#")
    //    b. add an entry to your browser's history
    //       (ever click once but have to "go back" twice?)

An alternative way

    <span onclick="showDetails('345');">Details for 345</span>

    // Any element can have event handlers.

End

`