Javascript MINI framework
<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="jquery-1.11.2.js"></script>
<script src="Greetr.js"></script>
<script src="app.js"></script>
</body>
</html>
;(function(global, $) {
// 'new' an object
var Greetr = function(firstName, lastName, language) {
return new Greetr.init(firstName, lastName, language);
}
// hidden within the scope of the IIFE and never directly accessible
var supportedLangs = ['en', 'es'];
// informal greetings
var greetings = {
en: 'Hello',
es: 'Hola'
};
// formal greetings
var formalGreetings = {
en: 'Greetings',
es: 'Saludos'
};
// logger messages
var logMessages = {
en: 'Logged in',
es: 'Inició sesión'
};
// prototype holds methods (to save memory space)
Greetr.prototype = {
// 'this' refers to the calling object at execution time
fullName: function() {
return this.firstName + ' ' + this.lastName;
},
validate: function() {
// check that is a valid language
// references the externally inaccessible 'supportedLangs' within the closure
if (supportedLangs.indexOf(this.language) === -1) {
throw "Invalid language";
}
},
// retrieve messages from object by referring to properties using [] syntax
greeting: function() {
return greetings[this.language] + ' ' + this.firstName + '!';
},
formalGreeting: function() {
return formalGreetings[this.language] + ', ' + this.fullName();
},
// chainable methods return their own containing object
greet: function(formal) {
var msg;
// if undefined or null it will be coerced to 'false'
if (formal) {
msg = this.formalGreeting();
}
else {
msg = this.greeting();
}
if (console) {
console.log(msg);
}
// 'this' refers to the calling object at execution time
// makes the method chainable
return this;
},
log: function() {
if (console) {
console.log(logMessages[this.language] + ': ' + this.fullName());
}
// make chainable
return this;
},
setLang: function(lang) {
// set the language
this.language = lang;
// validate
this.validate();
// make chainable
return this;
},
HTMLGreeting: function(selector, formal) {
if (!$) {
throw 'jQuery not loaded';
}
if (!selector) {
throw 'Missing jQuery selector';
}
// determine the message
var msg;
if (formal) {
msg = this.formalGreeting();
}
else {
msg = this.greeting();
}
// inject the message in the chosen place in the DOM
$(selector).html(msg);
// make chainable
return this;
}
};
// the actual object is created here, allowing us to 'new' an object without calling 'new'
Greetr.init = function(firstName, lastName, language) {
var self = this;
self.firstName = firstName || '';
self.lastName = lastName || '';
self.language = language || 'en';
self.validate();
}
// trick borrowed from jQuery so we don't have to use the 'new' keyword
Greetr.init.prototype = Greetr.prototype;
// attach our Greetr to the global object, and provide a shorthand '$G' for ease our poor fingers
global.Greetr = global.G$ = Greetr;
}(window, jQuery));
// gets a new object (the architecture allows us to not have to use the 'new' keyword here)
var g = G$('John', 'Doe');
// use our chainable methods
g.greet().setLang('es').greet(true).log();
// let's use our object on the click of the login button
$('#login').click(function() {
// create a new 'Greetr' object (let's pretend we know the name from the login)
var loginGrtr = G$('John', 'Doe');
// hide the login on the screen
$('#logindiv').hide();
// fire off an HTML greeting, passing the '#greeting' as the selector and the chosen language, and log the welcome as well
loginGrtr.setLang($('#lang').val()).HTMLGreeting('#greeting', true).log();
});