Last active
July 13, 2017 05:17
-
-
Save sinhavartika/bce7802a2e311ea3d67a3375124e7e17 to your computer and use it in GitHub Desktop.
MVC in vanilla javascript
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
<html> | |
<head> | |
<style> | |
/* global css */ | |
.mt-sm { | |
margin-top: 5px; | |
} | |
.text-justify { | |
text-align: justify; | |
} | |
.text-center { | |
text-align: center; | |
} | |
.show { | |
display: block; | |
} | |
.clearfix:after { | |
content: " "; /* Older browser do not support empty content */ | |
visibility: hidden; | |
display: block; | |
height: 0; | |
clear: both; | |
} | |
/* custom css */ | |
body { | |
background-color: #333; | |
} | |
.container { | |
width : 600px; | |
margin: 10px auto; | |
padding: 10px; | |
background-color: #fff; | |
} | |
.ui { | |
margin: 10px 0; | |
border: 1px solid #333; | |
padding: 10px; | |
} | |
.ui > ul, .ui > div { | |
float: left; | |
width: 45%; | |
padding: 5px; | |
} | |
.number-list { | |
list-style-type: none; | |
margin: 0; | |
border-right: 1px solid #333; | |
} | |
.number-list > li { | |
height: 30px; | |
margin : 3px 0; | |
padding: 5px 5px 5px 15px; | |
background-color: #f1f1f1; | |
cursor: pointer; | |
word-wrap: break-word; | |
} | |
.number-list > li:hover { | |
background-color: #e1e1e1; | |
} | |
.number { | |
margin: 8px 10px 0 5px; | |
background-color: #f1f1f1; | |
} | |
.number > button{ | |
float: right; | |
} | |
/* tab component */ | |
.tabs > .tab-pane { | |
display: none; | |
} | |
.tabs > .tab-pane.show { | |
display: block; | |
} | |
.tabs > .tab-pane h4 { | |
margin: 5px 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h3 class="text-center">Exploring <strong>Model-View-Controller</strong> in Javascript</h3> | |
<p class="text-justify"> | |
Readme | |
<button id="add-number-to-list">Add</button> | |
</p> | |
<div class="ui clearfix"> | |
<ul id="number-list" class="number-list"></ul> | |
<div class="number"> | |
<button data-target="number_view" data-feature="tab">Edit</button> | |
<div data-tab="number_view" class="tabs"> | |
<div class="tab-pane show"> | |
<h4>View</h4> | |
<div id="selected-number-view"></div> | |
</div> | |
<div class="tab-pane"> | |
<h4>Editor<h4> | |
<input type="text" id="selected-number-edit"/> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- script defining the controller --> | |
<script> | |
(function(){ | |
// function toogles the tab on button click | |
function toggleTab(event){ | |
// get the target tab component | |
var toggleTabTarget = event.target.dataset.target; | |
var targetElm = document.querySelectorAll('[data-tab="' + toggleTabTarget + '"]')[0]; | |
// toggle the show of all the divs with .tab-pane class | |
var elms = targetElm.querySelectorAll(".tab-pane"); | |
elms.forEach(function(elm){ | |
elm.classList.toggle("show"); | |
}); | |
} | |
/***************************** private functions ***************************/ | |
// funciton that should be called when class divs with certain toggles attribs should be toggled | |
function toggleClass(target, classNames){ | |
var elms = document.querySelectorAll('[data-toggle="' + target + '"]'); | |
elms.forEach(function(elm){ | |
elm.classList.toggle(classNames); | |
}); | |
} | |
/***************************** event functions ***************************/ | |
var tabBtns = document.querySelectorAll("[data-feature='tab']"); | |
tabBtns.forEach(function(elm){ | |
elm.addEventListener("click", toggleTab, false); | |
}); | |
})(); | |
</script> | |
<script> | |
var numberController = function(model, view){ | |
/***************** private variables ********************/ | |
var model = model; | |
var view = view; | |
/***************** initializing controller **************/ | |
activate(); | |
/***************** public functions *********************/ | |
// function to render the numbers in the list | |
var renderNumberList = function(){ | |
model.numberList.forEach(function(number){ | |
var li = document.createElement("li"); | |
var text = document.createTextNode(number.value); | |
li.dataset.id = number.id; | |
li.appendChild(text); | |
view.ul.appendChild(li); | |
}); | |
}; | |
// function to select a number from the list | |
var selectNumber = function(event){ | |
// get the number model from list | |
var id = event.target.dataset.id; | |
var number = model.numberList.find(function(number){ | |
return number.id === id; | |
}); | |
// set the number in model | |
model.number = number; | |
// set the number in view | |
view.selected_number_edit.value = number.value; | |
view.selected_number_view.innerHTML = number.value; | |
}; | |
// function to edit a number from the list | |
var editNumber = function(event){ | |
// change in model | |
var listNumberModel = model.numberList.find(function(number){ | |
return number.id === model.number.id; | |
}); | |
listNumberModel.value = view.selected_number_edit.value; | |
model.number.value = view.selected_number_edit.value; | |
// change in view | |
var listNumberView; | |
view.ul.childNodes.forEach(function(numberView){ | |
if(numberView.dataset.id === model.number.id){ | |
listNumberView = numberView; | |
} | |
}); | |
listNumberView.innerHTML = model.number.value; | |
view.selected_number_view.innerHTML = model.number.value; | |
} | |
var addNumberToTheList = function(){ | |
var number = { | |
"id" : model.numberList.length + 1, | |
"value" : model.numberList.length + 1 | |
} | |
model.numberList.push(number); | |
var li = document.createElement("li"); | |
var text = document.createTextNode(number.value); | |
li.dataset.id = number.id; | |
li.appendChild(text); | |
view.ul.appendChild(li); | |
} | |
var toggleEditing = function(event){ | |
model.editing = !model.editing; | |
var editBtn = event.target; | |
if(model.editing){ | |
editBtn.innerHTML = "Preview"; | |
}else{ | |
editBtn.innerHTML = "Edit"; | |
} | |
} | |
/***************** private functions *********************/ | |
function activate(){ | |
var number = model.numberList[0]; | |
// set the number in model | |
model.number = number; | |
// set the number in view | |
view.selected_number_edit.value = number.value; | |
view.selected_number_view.innerHTML = number.value; | |
} | |
return { | |
"renderNumberList" : renderNumberList, | |
"selectNumber" : selectNumber, | |
"editNumber" : editNumber, | |
"toggleEditing" : toggleEditing, | |
"addNumberToTheList" : addNumberToTheList | |
} | |
} | |
</script> | |
<!-- init --> | |
<script> | |
/** | |
Model | |
*/ | |
var numbersModel = { | |
numberList : [ | |
{id:"1", value: 1},{id:"2", value: 2},{id:"3", value: 3} | |
], | |
number : {}, | |
editing : false | |
} | |
/** | |
View | |
*/ | |
var numbersView = { | |
ul : document.getElementById("number-list"), | |
selected_number_view : document.getElementById("selected-number-view"), | |
selected_number_edit : document.getElementById("selected-number-edit") | |
} | |
/** | |
Numbers Controller | |
*/ | |
var numbersController = numberController(numbersModel, numbersView); | |
numbersController.renderNumberList(); | |
/** | |
binding events | |
*/ | |
numbersView.ul.childNodes.forEach(function(elm){ | |
elm.addEventListener("click", numbersController.selectNumber, false); | |
}); | |
numbersView.selected_number_edit.addEventListener("keyup", numbersController.editNumber, false); | |
var tabBtns = document.querySelectorAll("[data-feature='tab']")[0]; | |
tabBtns.addEventListener("click", numbersController.toggleEditing, false); | |
document.getElementById("add-number-to-list").addEventListener("click", numbersController.addNumberToTheList, false); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment