& patterns
<input type="text" name="date" onchange="validateDate(this);" />
if you have 20+ forms you need to add 20+ onchange functions
JavaScript behavior created and referenced in the HTML can be harder to use and maintain
if you have several handlers
<input type="text" name="date"
onchange="validateDate(this); dance(something); playMusic();" />
<a href="#faq1"
onclick="$('#faq1').css('display') == 'none' ? $('#faq1').show() : $('#faq1').hide();">
FAQ Question 1</a>
<div id="faq1" class="faqAnswer">FAQ Answer 1</div>
<a href="#faq2"
onclick="$('#faq2').css('display') == 'none' ? $('#faq2').show() : $('#faq2').hide();">
FAQ Question 2</a>
<div id="faq2">FAQ Answer 2</div>
<a href="#faq3"
onclick="$('#faq3').css('display') == 'none' ? $('#faq3').show() : $('#faq3').hide();">
FAQ Question 3</a>
<div id="faq3">FAQ Answer 3</div>
<a class=”hide”>Click to hide me</a>
$('.hide').click(function() { $(this).hide(); }
jQuery way:
Profit !
Right? Not exactly
So...
Clean, semantic HTML!
Total separation!
Strictly separating HTML and JS actually led to applications that were harder to maintain and debug
is a software architectural pattern
Trygve Reenskaug introduced MVC into Smalltalk-76 while visiting the Xerox Palo Alto Research Center (PARC) in the 1970s
A bit of history
Apple's WebObjects ("borrowed" from Smalltalk) in Objective-C
WebObjects was ported to Java
Ruby on Rails, Django, ASP.NET MVC
(Client) AngularJS, EmberJS, JavaScriptMVC, Backbone
MVC offers architectural benefits over standard JavaScript — it helps you write better organized, and therefore more maintainable code.
var M = {},
V = {},
C = {};
M.data = "hello world";
V.render = function (M) {
alert(M.data);
}
C.handleOnload = function () {
V.render(M);
}
window.onload = C.handleOnLoad;
traditional MVC pattern vs the modern interpretation in various programming languages:
some MVC–based frameworks will have the view observe the changes in the models while others will let the controller handle the view update
This pattern implements a single object that maintains a reference to a collection of objects (known as "observers") and broadcasts notifications when a change to state occurs.
Observers register with the Subject and wait for notification
Subject notify Observers about a change in state.
Observers take action
from http://www.slideshare.net/saifuddinmerchant/observer-pattern-15133603
var Subject = function() {
this.observers = [];
return {
subscribeObserver: function(observer) {
this.observers.push(observer);
},
unsubscribeObserver: function(observer) {
var index = this.observers.indexOf(observer);
if(index > -1) {
this.observers.splice(index, 1);
}
},
notifyObserver: function(observer) {
var index = this.observers.indexOf(observer);
if(index > -1) {
this.observers[index].notify(index);
}
},
notifyAllObservers: function() {
for(var i = 0; i < this.observers.length; i++){
this.observers[i].notify(i);
};
}
};
};
var Observer = function() {
return {
notify: function(index) {
console.log("Observer " + index + " is notified!");
}
}
}
var subject = new Subject();
var observer1 = new Observer();
var observer2 = new Observer();
var observer3 = new Observer();
var observer4 = new Observer();
subject.subscribeObserver(observer1);
subject.subscribeObserver(observer2);
subject.subscribeObserver(observer3);
subject.subscribeObserver(observer4);
subject.notifyObserver(observer2); // Observer 2 is notified!
subject.notifyAllObservers();
is a variation of Observer pattern.
However PubSub uses a topic/event channel that sits between the objects wishing to receive notifications (subscribers) and the object firing the event (the publisher)
• there is no direct communication between objects
• objects exchange Events rather than share states of object
// create a function to subscribe to topics
var mySubscriber = function( msg, data ){
console.log( msg, data );
};
// add the function to the list of subscribers for a particular topic
// we're keeping the returned token, in order to be able to unsubscribe
// from the topic later on
var token = PubSub.subscribe( 'MY TOPIC', mySubscriber );
// publish a topic asyncronously
PubSub.publish( 'MY TOPIC', 'hello world!' );
// publish a topic syncronously, which is faster in some environments,
// but will get confusing when one topic triggers new topics in the
// same execution chain
// USE WITH CAUTION, HERE BE DRAGONS!!!
PubSub.publishSync( 'MY TOPIC', 'hello world!' );
// create a function to receive the topic
var mySubscriber = function( msg, data ){
console.log( msg, data );
};
// add the function to the list of subscribers to a particular topic
// we're keeping the returned token, in order to be able to unsubscribe
// from the topic later on
var token = PubSub.subscribe( 'MY TOPIC', mySubscriber );
// unsubscribe this subscriber from this topic
PubSub.unsubscribe( token );
// create a function to receive the topic
var mySubscriber = function( msg, data ){
console.log( msg, data );
};
// unsubscribe mySubscriber from ALL topics
PubSub.unsubscribe( mySubscriber );
PubSub.clearAllSubscriptions();
// all subscriptions are removed