Skip to content

Instantly share code, notes, and snippets.

@uchcode
Last active July 14, 2016 02:24
Show Gist options
  • Save uchcode/4e65574693e40966d2f4d82356777904 to your computer and use it in GitHub Desktop.
Save uchcode/4e65574693e40966d2f4d82356777904 to your computer and use it in GitHub Desktop.
State Action Model Patterm(SAM) example
<!DOCTYPE html>
<html>
<body>
<h1>Hello world</h1>
<div id="present"></div>
<script>
////////////////////////////////////////////////////////////////////////////////
// MODEL
class Model {
constructor(view) {
this.view = view;
this.ready = false;
this.complete = false;
}
//
isReady() {
return (
!this.ready
&& !this.complete
);
}
isComplete() {
return (
this.ready
&& this.complete
);
}
// SAM pattern
reactive(data) {
this.present(data);
this.render();
this.nap();
}
present(data) {
if (data.ready !== undefined) {
this.ready = data.ready;
}
if (data.complete !== undefined) {
this.complete = data.complete;
}
}
render() {
const {view} = this;
view.render( view.present(this), this );
}
nap() {
if (!this.isReady() && !this.isComplete()) {
this.stop({});
}
}
//
init(data) {
this.reactive(data);
}
reset(data) {
data.ready = false;
data.complete = false;
this.reactive(data);
}
start(data) {
data.ready = true;
this.reactive(data);
}
stop(data) {
data.complete = true;
this.reactive(data);
}
}
////////////////////////////////////////////////////////////////////////////////
// VIEW
class View {
present(model) {
var contents = {template:'<div>oops... something went wrong, the system is in an invalid state</div>'};
if (model.isReady()) {
contents = this.ready({});
}
if (model.isComplete()) {
contents = this.complete({});
}
if (!model.isReady() && !model.isComplete()) {
contents = {template:'<div></div>'};
}
return contents;
}
//
render(contents, intents) {
const callback = (action, parameter) => {
return evt => {
intents[action](parameter);
evt.preventDefault();
evt.stopPropagation();
return false;
}
}
const {template, action, parameter} = contents;
const newElement = document.createElement('div');
newElement.innerHTML = template.trim();
const form = newElement.getElementsByTagName('form')[0];
if (form && action && parameter) {
form.addEventListener('submit', callback(action, parameter));
}
const element = document.getElementById('present');
if (element.childNodes.length) {
element.replaceChild(newElement.childNodes[0], element.childNodes[0]);
} else {
element.appendChild(newElement.childNodes[0]);
}
}
//
ready(data) {
return {
template: `
<div>
<p>Ready?</p>
<form>
<div class="form-group">
<input type="submit" value="Start">
</div>
</form>
</div>`,
action: 'start',
parameter: {}
};
}
complete(data) {
return {
template: `
<div>
<p>Hello! Welcome to the reactive world.</p>
<form>
<div class="form-group">
<input type="submit" value="Reset">
</div>
</form>
</div>`,
action: 'reset',
parameter: {}
};
}
}
////////////////////////////////////////////////////////////////////////////////
// APPLICATION
(() => {
const view = new View();
const model = new Model(view);
model.init({});
})();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment