Last active
November 26, 2020 09:50
-
-
Save whal-e3/d305ea6dcb555582ddb75b01fc407463 to your computer and use it in GitHub Desktop.
JS Patterns
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// PATTERN | |
// MODULE PATTERN | |
// BASIC Structure | |
// IIFE (immediate invoked function expression) | |
(function () { | |
// Declare private vars and functions | |
return { | |
// Declare public vars and functions | |
}; | |
})(); | |
// ----------------------------------------------- | |
// STANDARD MODULE pattern | |
const UICtrl = (function () { | |
let text = 'Hello World'; | |
const changeText = function () { | |
const element = document.querySelector('h1'); | |
element.textContent = text; | |
}; | |
return { | |
callChangeText: function () { | |
changeText(); | |
console.log(text); | |
} | |
}; | |
})(); | |
UICtrl.callChangeText(); | |
// REVEALING MODULE pattern | |
const ItemCtrl = (function () { | |
let _data = []; | |
function add(item) { | |
_data.push(item); | |
console.log('Item added...'); | |
} | |
function get(id) { | |
return _data.find(item => { | |
return item.id === id; | |
}); | |
} | |
return { | |
add: add, | |
get: get | |
}; | |
})(); | |
ItemCtrl.add({ id: 1, name: 'John' }); | |
console.log(ItemCtrl.get(1)); | |
// ------------------------------------------------------------------------------------------------------- | |
// Singleton | |
const Singleton = (function () { | |
let instance; | |
function createInstance() { | |
const object = new Object({ name: 'Eric' }); | |
return object; | |
} | |
return { | |
getInstance: function () { | |
if (!instance) { | |
instance = createInstance(); | |
} | |
return instance; | |
} | |
}; | |
})(); | |
const instanceA = Singleton.getInstance(); | |
console.log(instanceA); | |
// -------------------------------------------------------------------------------------- | |
// FACTORY | |
function MemberFactory() { | |
this.createMember = function (name, type) { | |
let member; | |
if (type === 'simple') { | |
member = new SimpleMembership(name); | |
} else if (type === 'standard') { | |
member = new StandardMembership(name); | |
} else if (type === 'super') { | |
member = new SuperMembership(name); | |
} | |
member.type = type; | |
member.define = function () { | |
console.log(`${this.name} (${this.type}): ${this.cost}`); | |
}; | |
return member; | |
}; | |
} | |
const SimpleMembership = function (name) { | |
this.name = name; | |
this.cost = '$5'; | |
}; | |
const StandardMembership = function (name) { | |
this.name = name; | |
this.cost = '$15'; | |
}; | |
const SuperMembership = function (name) { | |
this.name = name; | |
this.cost = '$25'; | |
}; | |
const members = []; | |
const factory = new MemberFactory(); | |
members.push(factory.createMember('John Doe', 'simple')); | |
members.push(factory.createMember('Eric Whale', 'super')); | |
members.push(factory.createMember('Jenny Whale', 'standard')); | |
members.forEach(member => { | |
member.define(); | |
}); | |
// -------------------------------------------------------------------------------------- | |
// OBSERVER | |
// ES5 format | |
// function EventObserver() { | |
// this.observers = []; | |
// } | |
// EventObserver.prototype = { | |
// subscribe: function (fn) { | |
// this.observers.push(fn); | |
// console.log(`You are now subscribed to ${fn.name}`); | |
// }, | |
// unsubscribe: function (fn) { | |
// this.observers = this.observers.filter(item => { | |
// if (item !== fn) { | |
// return item; | |
// } | |
// }); | |
// console.log(`You are now unsubscribed from ${fn.name}`); | |
// }, | |
// fire: function () { | |
// this.observers.forEach(item => { | |
// item.call(); | |
// }); | |
// } | |
// }; | |
class EventObserver { | |
constructor() { | |
this.observers = []; | |
} | |
subscribe(fn) { | |
this.observers.push(fn); | |
console.log(`You are now subscribed to ${fn.name}`); | |
} | |
unsubscribe(fn) { | |
this.observers = this.observers.filter(item => { | |
if (item !== fn) { | |
return item; | |
} | |
}); | |
console.log(`You are now unsubscribed from ${fn.name}`); | |
} | |
fire() { | |
this.observers.forEach(item => { | |
item.call(); | |
}); | |
} | |
} | |
const click = new EventObserver(); | |
// Event listeners | |
document.querySelector('.sub-ms').addEventListener('click', function () { | |
click.subscribe(getCurMilliseconds); | |
}); | |
document.querySelector('.unsub-ms').addEventListener('click', function () { | |
click.unsubscribe(getCurMilliseconds); | |
}); | |
document.querySelector('.sub-s').addEventListener('click', function () { | |
click.subscribe(getCurSeconds); | |
}); | |
document.querySelector('.unsub-s').addEventListener('click', function () { | |
click.unsubscribe(getCurSeconds); | |
}); | |
document.querySelector('.fire').addEventListener('click', function () { | |
click.fire(); | |
}); | |
// Click handler | |
const getCurMilliseconds = function () { | |
console.log(`Current Milliseconds: ${new Date().getMilliseconds()}`); | |
}; | |
const getCurSeconds = function () { | |
console.log(`Current Seconds: ${new Date().getSeconds()}`); | |
}; | |
// ---------------------------------------------------------------------------------------------- | |
// MEDIATOR | |
const User = function (name) { | |
this.name = name; | |
this.chatroom = null; | |
}; | |
User.prototype = { | |
send: function (message, to) { | |
this.chatroom.send(message, this, to); | |
}, | |
receive: function (message, from) { | |
console.log(`${from.name} to ${this.name}: ${message}`); | |
} | |
}; | |
const Chatroom = function () { | |
let users = {}; | |
return { | |
register: function (user) { | |
users[user.name] = user; | |
user.chatroom = this; | |
}, | |
send: function (message, from, to) { | |
if (to) { | |
// single user message | |
to.receive(message, from); | |
} else { | |
// Mass message | |
for (key in users) { | |
if (users[key] != from) { | |
users[key].receive(message, from); | |
} | |
} | |
} | |
} | |
}; | |
}; | |
const brad = new User('Brad'); | |
const jeff = new User('Jeff'); | |
const sara = new User('Sara'); | |
const chatroom1 = new Chatroom(); | |
chatroom1.register(brad); | |
chatroom1.register(jeff); | |
chatroom1.register(sara); | |
brad.send('Hello Jeff', jeff); | |
sara.send('Hello Brad', brad); | |
jeff.send('Hello Everyone'); | |
// ------------------------------------------------------------------------- | |
// STATE | |
function app(initialState = {}) { | |
const state = initialState; | |
return { | |
setState(newState = state) { | |
return e => { | |
console.log('previous state', state); | |
Object.assign(state, newState); | |
console.log('updated state', state); | |
document.getElementById('heading').textContent = state.heading; | |
document.getElementById('content').innerHTML = state.content(); | |
e.preventDefault(); | |
}; | |
} | |
}; | |
} | |
function homeComponent() { | |
return ` | |
<div class="jumbotron"> | |
<h1 class="display-4">Hello, world!</h1> | |
<p class="lead">This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> | |
<hr class="my-4"> | |
<p>It uses utility classes for typography and spacing to space content out within the larger container.</p> | |
<p class="lead"> | |
<a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a> | |
</p> | |
</div> | |
`; | |
} | |
function aboutComponent() { | |
return ` | |
<p>This is the about page</p> | |
`; | |
} | |
function contactComponent() { | |
return `<form> | |
<div class="form-group"> | |
<label>Name</label> | |
<input type="text class="form-control"> | |
</div> | |
<div class="form-group"> | |
<label>Email Address</label> | |
<input type="email" class="form-control"> | |
</div> | |
<button type="submit" class="btn btn-primary">Submit</button> | |
</form> | |
`; | |
} | |
const pageState = app(); | |
document.addEventListener( | |
'DOMContentLoaded', | |
pageState.setState({ heading: null, content: homeComponent }) | |
); | |
document | |
.getElementById('home') | |
.addEventListener( | |
'click', | |
pageState.setState({ heading: null, content: homeComponent }) | |
); | |
document | |
.getElementById('about') | |
.addEventListener( | |
'click', | |
pageState.setState({ heading: 'About Us', content: aboutComponent }) | |
); | |
document | |
.getElementById('contact') | |
.addEventListener( | |
'click', | |
pageState.setState({ heading: 'Contact Us', content: contactComponent }) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment