# Section 8 - Examining Famous Frameworks and Libraries

### Building Our own Framework

#### Requirements

* Name: Greetr
* Generates form and informal greetings
* Reusable, and non interfearing
* English and Spanish
* Easy to Type structure
  * $G&#x20;
* Support Jquery

#### Structuring safe code

```
    ...


    (function (global, $){

    })(window, $)
```

* What happened:
  * Immediately invoked function that creates a new execution context, keeping our variables safe.
  * 2 global objects where passed that we're going to work with.

#### Part 2

```
    (function (global, $){

        var Greetr = function(first, last, lang) {
            return new Greetr.init(first, last, lang);
        }
    }
```

* Greetr is a function, that when invoked, returns a new object, so that we do have to use the keyword ourselves.
* Init is not yet defined, but is a common keyword used to handle initialization.&#x20;

```
    (function (global, $){

        var Greetr = function(first, last, lang) {
            return new Greetr.init(first, last, lang);
        }

        Greetr.prototype = {};

        Greetr.init = function(first, last, lang) {
            this.firstname = first || '[users first name]';
            this.lastname = last || '[users last name]';
            this.language = lang || 'en';

            // defined later -> checks if language is supported
            this.validate();
        }

        Greetr.init.prototype = Greetr.prototype;

    })(window, $)
```

* Next we implement our object constructor.
  * Unique variable primitive to our library are defined as a properties to each respected object.
    * Default variables are invocated by coersion.&#x20;
* We defined a new object as a prototype (inheritance) to each object.
  * Save memory space by not passing it into the constructor.
  * Empty for now
* Because objects where constructed with .init (seperate execution context), we want all Greetr/prototype objects to point to Greetr.init.prototype.
  * Allows us to define methods in Greetr.prototype more cleanly.&#x20;

```
        global.Greetr = global.$G = Greetr;
```

* One last thing before we finish. To establish a neat alias, all we have to set our object function constructor as part of the global window.
* Now, we can treat Greetr, and $G equivalently as constructors.

```
    var g = $G('dan','mak');
    console.log(g); // G…r.init {firstname: "dan", lastname: "mak", language: "en"}
```

### Part 3

```
    var supportedLang = ['en', 'es'];

        Greetr.prototype = {

    };
```

* The next part is really cool. Its just like constructing classes in C++.
* Each unique object will have access to methods defined without our prototype, thanks to our pointer fix.
* Variables constructed WITHIN the immediately invoked function will remain 'private' to the methods within the prototype.
  * That way, our framework is defined where it needs to be, and does not mess around with any global context.
  * Our prototype, however - maintains access to these variables because of closure.

```
    var greetings = {
        en: 'Hello',
        es: 'Hola'
    };

    var formalGreetings = {
        en: 'Greetings',
        es: 'Saludos'
    };

    var logMessages = {
        en: 'Logged In',
        es: 'Inicio sesion'
    };
```

* Next, we define a few reference variables for our prototype methods.

```
    fullname: function() {
        return this.firstname + ' ' + this.lastname;
    },

    validate: function() {
        if (supportedLang.indexOf(this.language) === -1) {
            throw "Invalid language";
        }
        else {
            console.log("Valid language");
        }
    },

    greeting: function() {
        return greetings[this.language] + ' ' + this.firstname + '!';
    },

    formalGreeting: function() {
        return formalGreetings[this.language] + ' ' + this.fullname();
    },

    greet: function(formal) {
        var msg;

        if (formal) {
            msg = this.formalGreeting();
        }

        else {
            msg = this.greeting();
        }

        //show whats happening
        if (console) {
            console.log(msg);
        }

        return this;
    },

    log: function() {
        //Internet explore check if console is open
        if (console) {
            console.log(logMessages[this.language] + ' ' + this.fullname());
        }

        //chainable
        return this;
    },

    setLang: function(lang) {
        this.language = lang;
        this.validate();
        return this;
    } 
```

* Each of these functions will reference with a uniquely constructed new object.
* This is why the keyword this becomes so important.
* validate searches through our index of supported languages with this.language, - the current language supplied to an object.
  * throws and error if the language is invalid.
* function greet is not required, but it grants chainable methods to our library. It also simplifies two methods with a single invocation
  * Optional boolean variable passed in to invoke a formal greeting.&#x20;
* At first I thought it was strange that setLand first let the language, and then validated it, but then I realized something.
  * Even if we change the language of an object to something that is not supported, it does not matter because it of this.validate().
  * If an error is thrown, then the setLand does not return, so it wouldn't allow it to pass through.
* Testing so far

```
    var a = g.fullname();
    console.log(a); // dan mak

    g.validate(); // Valid language

    var b = g.greeting(); 
    console.log(b); // Hello dan!

    var c = g.formalGreeting();
    console.log(c); // Greetings dan!

    g.greet(); // Hello dan!

    g.log(); // Logged In dan mak

    g.setLang('germen');
    g.validate(); //Uncaught Invalid language
```

### Part 3

* Adding jQuery support

&#x20;EnglishSpanish&#x20;

```
    HTMLGreeting: function(selector, formal) {
        if (!$) {
            throw 'Jquery not loaded';
        }

        if (!selector) {
            throw 'Missing Jquery selector';
        }

        var msg;
        if (formal) {
            msg = this.formalGreeting();
        }
        else {
            msg = this.greeting();
        }

        $(selector).html(msg);
        return this;
    }
```

* This function will be used to modify our html page once all of our variables are taken into account. The selector is a jQuery element.
  * Everything else references variables that are already known in the constructed object.
  * We also have a bit of jQuery code on the bottom, that is used to modify any html attribute.
* It is always best to commenet up your code once you finish. It may be understood now, but in time - the memory of your intents may be lost.&#x20;
* It also helps other coders.
* Since I've documented my thoughts here, I wont bother.

```
    $('#login').click(function() {
        var g = $G('dan','mak');
        var loginGreeter = g;

        $('#logindiv').hide();
        loginGreeter.setLang($('#lang').val()).HTMLGreeting('#greeting', true).log();
    });
```

* Finally, its time to finish up our project by adding jQuery functionality to our html.
* That long chained method looks complecated, but lets break it down:
  * Using our constructed object, we set our variable property using a jQuery selector on the html element.
  * The next function call can be thought of as being executed on a new line.

## The Final Library/Framework

```
    //HTML
    <html>
    <head>

    </head>
    <body>
        <div id="logindiv">
            <select id="lang">
                <option value="en">English</option> 
                <option value="es">Spanish</option> 
            </select>
            <input type="button" value="Login" id="login">
        </div>

        <h1 id="greeting"></h1>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script src="Greetr.js"></script>
        <script src="app.js"></script>
    </body>                                            
    </html>


    //Greetr.js
    (function (global, $){

        var Greetr = function(first, last, lang) {
            return new Greetr.init(first, last, lang);
        }

        var supportedLang = ['en', 'es'];

        var greetings = {
            en: 'Hello',
            es: 'Hola'
        };

        var formalGreetings = {
            en: 'Greetings',
            es: 'Saludos'
        };

        var logMessages = {
            en: 'Logged In',
            es: 'Inicio sesion'
        };

        Greetr.prototype = {
            fullname: function() {
                return this.firstname + ' ' + this.lastname;
            },

            validate: function() {
                if (supportedLang.indexOf(this.language) === -1) {
                    throw "Invalid language";
                }
                else {
                    console.log("Valid language");
                }
            },

            greeting: function() {
                return greetings[this.language] + ' ' + this.firstname + '!';
            },

            formalGreeting: function() {
                return formalGreetings[this.language] + ' ' + this.fullname();
            },

            greet: function(formal) {
                var msg;

                if (formal) {
                    msg = this.formalGreeting();
                }

                else {
                    msg = this.greeting();
                }

                //show whats happening
                if (console) {
                    console.log(msg);
                }

                return this;
            },

            log: function() {
                //Internet explore check if console is open
                if (console) {
                    console.log(logMessages[this.language] + ' ' + this.fullname());
                }

                //chainable
                return this;
            },

            setLang: function(lang) {
                this.language = lang;
                this.validate();
                return this;
            },

            HTMLGreeting: function(selector, formal) {
                if (!$) {
                    throw 'Jquery not loaded';
                }

                if (!selector) {
                    throw 'Missing Jquery selector';
                }

                var msg;
                if (formal) {
                    msg = this.formalGreeting();
                }
                else {
                    msg = this.greeting();
                }

                $(selector).html(msg);
                return this;
            }

        };

        Greetr.init = function(first, last, lang) {
            this.firstname = first || '[users first name]';
            this.lastname = last || '[users last name]';
            this.language = lang || 'en';

            // check language
            this.validate();
        }

        Greetr.init.prototype = Greetr.prototype;

        global.Greetr = global.$G = Greetr;

    })(window, $)



    //app.js


    $('#login').click(function() {
        var g = $G('dan','mak');
        var loginGreeter = g;

        $('#logindiv').hide();
        loginGreeter.setLang($('#lang').val()).HTMLGreeting('#greeting', true).log();
    });
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://maksimdan.gitbook.io/javascript/intro_to_javascript/section_8.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
