Skip to content

Instantly share code, notes, and snippets.

@whal-e3
Last active November 26, 2020 09:50
Show Gist options
  • Save whal-e3/d305ea6dcb555582ddb75b01fc407463 to your computer and use it in GitHub Desktop.
Save whal-e3/d305ea6dcb555582ddb75b01fc407463 to your computer and use it in GitHub Desktop.
JS Patterns
// 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