Created
August 13, 2014 10:24
-
-
Save max-berman/d8a56179b56d91d1d743 to your computer and use it in GitHub Desktop.
Guest Book Guest book leveraging local storage // source http://jsbin.com/winici/1
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="description" content="Guest book leveraging local storage" /> | |
<link rel="stylesheet" type="text/css" href="styles/style.css" > | |
<link rel="shortcut icon" href="favicon.ico" /> | |
<title>Guest Book</title> | |
<style id="jsbin-css"> | |
body { | |
font-family: 'Lucida Grande', 'Helvetica Neue', sans-serif; | |
font-size: 13px; | |
} | |
section { | |
max-width: 500px; | |
} | |
.form { | |
position: absolute; | |
top:0; | |
left:10px; | |
transition: left 1s ease 0s; | |
-webkit-transition: left 1s ease 0s; | |
-moz-transition: left 1s ease 0s; | |
} | |
.form input, .form textarea { | |
border: 4px solid rgba(0,0,0,0.1); | |
padding: 8px 10px; | |
-webkit-border-radius: 5px; | |
-moz-border-radius: 5px; | |
border-radius: 5px; | |
outline: 0; | |
} | |
.form textarea { | |
width: 470px; | |
} | |
.form input[type="submit"] { | |
cursor: pointer; | |
background: -webkit-linear-gradient(top, #efefef, #ddd); | |
background: -moz-linear-gradient(top, #efefef, #ddd); | |
background: -ms-linear-gradient(top, #efefef, #ddd); | |
background: -o-linear-gradient(top, #efefef, #ddd); | |
background: linear-gradient(top, #efefef, #ddd); | |
color: #333; | |
text-shadow: 0px 1px 1px rgba(255,255,255,1); | |
border: 1px solid #ccc; | |
} | |
.form input[type="submit"]:hover { | |
background: -webkit-linear-gradient(top, #eee, #ccc); | |
background: -moz-linear-gradient(top, #eee, #ccc); | |
background: -ms-linear-gradient(top, #eee, #ccc); | |
background: -o-linear-gradient(top, #eee, #ccc); | |
background: linear-gradient(top, #eee, #ccc); | |
border: 1px solid #bbb; | |
} | |
.form input[type="submit"]:active { | |
background: -webkit-linear-gradient(top, #ddd, #aaa); | |
background: -moz-linear-gradient(top, #ddd, #aaa); | |
background: -ms-linear-gradient(top, #ddd, #aaa); | |
background: -o-linear-gradient(top, #ddd, #aaa); | |
background: linear-gradient(top, #ddd, #aaa); | |
border: 1px solid #999; | |
} | |
.form div { | |
margin-bottom: 8px; | |
} | |
input[name=clearStorage]{display: none;} | |
.form.admin input[name=clearStorage]{ | |
display: inline; | |
} | |
#loginForm span { | |
float: right; | |
clear: both; | |
margin: 0px 0px 0 5px; | |
color: #585858; | |
font-size:12px; | |
line-height: 1.5; | |
} | |
.hide { | |
/*display:none; | |
visibility:hidden;*/ | |
left:-600px; | |
} | |
.floatRight{ | |
float:right; | |
margin-top:20px; | |
line-height: 1.5; | |
} | |
ul { | |
margin: 10px 0; | |
padding:0; | |
} | |
li { | |
padding: 4px 2px; | |
margin: 2px 0; | |
list-style-type: none; | |
line-height: 1.5; | |
animation: fadein 1s; | |
-moz-animation: fadein 1s; /* Firefox */ | |
-webkit-animation: fadein 1s; /* Safari and Chrome */ | |
-o-animation: fadein 1s; /* Opera */ | |
position: relative; | |
-webkit-transition: background-color 1s ease-in-out; | |
-moz-transition: background-color 1s ease-in-out; | |
-ms-transition: background-color 1s ease-in-out; | |
-o-transition: background-color 1s ease-in-out; | |
} | |
li input[type='checkbox']{ | |
position: absolute; | |
right: 5px; | |
top:5px; | |
} | |
li.post-comment { | |
opacity: 1; | |
} | |
.needsAproval { | |
background-color: rgba(255, 250, 245, 0.47)!important; | |
border: 1px dashed #F00; | |
font-style: italic; | |
color: #DDD; | |
position: relative; | |
} | |
.toValidate var { | |
background: none repeat scroll 0 0 #F5F5F5; | |
border: 1px solid #8D7F7F; | |
border-radius: 50% 50% 50% 50%; | |
bottom: 6px; | |
color: #000000; | |
cursor: pointer; | |
display: block; | |
float: right; | |
height: 10px; | |
margin: 0 50px 0 0; | |
position: absolute; | |
right: 0; | |
width: 10px; | |
} | |
.toValidate var:hover { | |
border: 1px solid #fff; | |
} | |
.toValidate var:before { | |
position: relative; | |
content: 'Validate'; | |
color: #fff; | |
float:right; | |
margin-right: 10px; | |
margin-top:-4px; | |
font-size:11px; | |
padding:0 2px; | |
z-index: 1; | |
} | |
.toValidate var:active { | |
background: #000; | |
} | |
.post-comment button { | |
text-transform: capitalize; | |
padding: 0 2px; | |
position: absolute; | |
right: 5px; | |
border: 1px solid #8D7F7F; | |
bottom: 5px; | |
cursor: pointer; | |
background: #F5F5F5; | |
color: #9B6C6C; | |
font-size:10px; | |
} | |
.post-comment button:hover { | |
color: #000; | |
border: 1px solid #000; | |
} | |
.needsAproval:after { | |
content:'Requires Admin\'s approval'; | |
background: #fff; | |
color: #000; | |
position: absolute; | |
right: 10px; | |
padding: 0 2px; | |
} | |
.toValidate{ | |
background-color: rgba(119, 86, 53, 0.47)!important; | |
color: #530028; | |
} | |
@keyframes fadein { | |
from { | |
opacity:0; | |
} | |
to { | |
opacity:1; | |
} | |
} | |
@-moz-keyframes fadein { /* Firefox */ | |
from { | |
opacity:0; | |
} | |
to { | |
opacity:1; | |
} | |
} | |
@-webkit-keyframes fadein { /* Safari and Chrome */ | |
from { | |
opacity:0; | |
} | |
to { | |
opacity:1; | |
} | |
} | |
li:nth-child(odd) { | |
background-color: #f4f4f4; | |
} | |
li span:first-child { | |
font-weight: 600; | |
} | |
li span:first-child:after { | |
content: ':'; | |
} | |
li p { | |
padding-left:10px; | |
display: inline; | |
} | |
iframe { | |
display: none; | |
visibility: hidden; | |
} | |
</style> | |
</head> | |
<body> | |
<section id="loginForm" class="form"> | |
<form target="hiddenFrame"> | |
<p> | |
<input type="text" name="name" id="name" value="" placeholder="Name"> | |
</p> | |
<!--<p>--> | |
<!--<input type="password" name="password" value="" placeholder="Password">--> | |
<!--</p>--> | |
<p><span>Enter login name. <br>(<strong>admin</strong> - to log in as administrator)</span> | |
<input type="submit" name="submit" id="submit" value="Login"> | |
</p> | |
</form> | |
</section> | |
<section id="commentForm" class="form hide" > | |
<ul> | |
</ul> | |
<form target="hiddenFrame" > | |
<p> | |
<textarea rows="10" name="comment" id="comment" placeholder="Comment"></textarea> | |
</p> | |
<p> | |
<input type="submit" name="submitComment" value="Add Comment"> | |
<input type="submit" name="clearStorage" value="Clear Storage"> | |
<a href="/" class="floatRight">Log Out</a> | |
</p> | |
</form> | |
</section> | |
<iframe name="hiddenFrame" class="hide"></iframe> | |
<script src="app.js"></script> | |
<script id="jsbin-javascript"> | |
/** | |
* Created by Max Berman on 10/29/13. | |
*/ | |
if(!window.localStorage){ | |
alert('your browser does not support web storage'); | |
} | |
//document.readyState | |
document.onreadystatechange = function () { | |
if (document.readyState == "complete") { | |
commentForm = document.querySelector('#commentForm'); | |
commentBox = document.querySelector('textarea[name$=comment]'); | |
loginForm = document.querySelector('#loginForm'); | |
list = document.querySelector('#commentForm ul'); | |
} | |
}; | |
//arsenal of usefull functions used in the current project | |
function addClass(el, cl){ | |
el.className += ' '+cl; | |
} | |
function removeClass(el, cl){ | |
var elClass = ' '+el.className+' '; | |
while(elClass.indexOf(' '+cl+' ') != -1) | |
elClass = elClass.replace(' '+cl+' ', ''); | |
el.className = elClass; | |
} | |
//User Object | |
function User (userName) { | |
this.name = userName; | |
this.displayName = function(){ | |
var title = document.createElement("h1"); | |
title.innerHTML = this.name; | |
commentForm.appendChild(title); | |
commentForm.insertBefore(title, commentForm.firstChild); | |
}; | |
this.postComment = function(){ | |
if(window.localStorage){ | |
var localData = { | |
'userName': this.name, | |
'text': commentBox.value, | |
'aproved': (this.name == 'admin') ? true : false | |
}; | |
var listElem = document.createElement('li'); | |
listElem.className = (localData.aproved) ? 'post-comment': 'post-comment needsAproval'; | |
listElem.innerHTML = '<span>'+this.name+'</span><p>'+localData.text+'</p>'; | |
list.appendChild(listElem); | |
list.insertBefore(listElem, list.firstChild); | |
//save as json in session storage | |
var localStorageLength = window.localStorage.length; | |
window.localStorage.setItem('localData-'+localStorageLength, JSON.stringify(localData)); | |
} | |
}; | |
this.displayComments = function(){ | |
for (var i = 0; i < window.localStorage.length; i++){ | |
var output = JSON.parse(window.localStorage.getItem(localStorage.key(i))); | |
var listElem = document.createElement('li'); | |
if (this.name == 'admin') { | |
addClass(commentForm, 'admin'); | |
listElem.setAttribute('data-storage', localStorage.key(i)); | |
listElem.className = (output.aproved) ? 'post-comment': 'post-comment toValidate'; | |
listElem.innerHTML = '<span>'+output.userName+'</span><p>'+output.text+'</p>'; | |
list.appendChild(listElem); | |
list.insertBefore(listElem, list.firstChild); | |
//add Validation element and its functionality | |
var validateBtn = document.createElement('var'); | |
listElem.appendChild(validateBtn); | |
validateBtn.addEventListener('click', function(){ | |
var getCurrentStorageKey = this.parentNode.getAttribute('data-storage'); | |
var tempData = JSON.parse(window.localStorage.getItem(getCurrentStorageKey)); | |
tempData.aproved = true; | |
window.localStorage.setItem(getCurrentStorageKey, JSON.stringify(tempData)); | |
removeClass(this.parentNode, 'toValidate'); | |
}, false); | |
//add delete post button and its functionality | |
var delBtn = document.createElement('button'); | |
delBtn.textContent = 'delete'; | |
listElem.appendChild(delBtn); | |
delBtn.addEventListener('click', function(){ | |
var getCurrentStorageKey = this.parentNode.getAttribute('data-storage'); | |
window.localStorage.removeItem(getCurrentStorageKey); | |
list.removeChild(this.parentNode); | |
}, false); | |
} | |
else if (output.aproved && this.name != 'admin'){ | |
listElem.className = 'post-comment'; | |
listElem.innerHTML = '<span>'+output.userName+'</span><p>'+output.text+'</p>'; | |
list.appendChild(listElem); | |
list.insertBefore(listElem, list.firstChild); | |
} } | |
}; | |
}// /User Object | |
document.querySelector('input[name$=submit]').onclick = function(){ | |
var nameSelector = document.querySelector('input[name$=name]'); | |
var person = new User(nameSelector.value); | |
if (!person.name){ | |
alert('login name is missing'); | |
return false; | |
} | |
removeClass (commentForm, 'hide'); | |
addClass(loginForm, 'hide'); | |
person.displayName(); | |
person.displayComments(); | |
document.querySelector('input[name$=submitComment]').onclick = function(){ | |
if (commentBox.value !== ''){ | |
person.postComment(); | |
} | |
commentBox.value = ''; | |
}; | |
}; | |
document.querySelector('input[name$=clearStorage]').onclick = function(){ | |
window.localStorage.clear(); | |
list.innerHTML = ''; | |
commentBox.value = ''; | |
}; | |
</script> | |
</body> | |
</html> |
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
body { | |
font-family: 'Lucida Grande', 'Helvetica Neue', sans-serif; | |
font-size: 13px; | |
} | |
section { | |
max-width: 500px; | |
} | |
.form { | |
position: absolute; | |
top:0; | |
left:10px; | |
transition: left 1s ease 0s; | |
-webkit-transition: left 1s ease 0s; | |
-moz-transition: left 1s ease 0s; | |
} | |
.form input, .form textarea { | |
border: 4px solid rgba(0,0,0,0.1); | |
padding: 8px 10px; | |
-webkit-border-radius: 5px; | |
-moz-border-radius: 5px; | |
border-radius: 5px; | |
outline: 0; | |
} | |
.form textarea { | |
width: 470px; | |
} | |
.form input[type="submit"] { | |
cursor: pointer; | |
background: -webkit-linear-gradient(top, #efefef, #ddd); | |
background: -moz-linear-gradient(top, #efefef, #ddd); | |
background: -ms-linear-gradient(top, #efefef, #ddd); | |
background: -o-linear-gradient(top, #efefef, #ddd); | |
background: linear-gradient(top, #efefef, #ddd); | |
color: #333; | |
text-shadow: 0px 1px 1px rgba(255,255,255,1); | |
border: 1px solid #ccc; | |
} | |
.form input[type="submit"]:hover { | |
background: -webkit-linear-gradient(top, #eee, #ccc); | |
background: -moz-linear-gradient(top, #eee, #ccc); | |
background: -ms-linear-gradient(top, #eee, #ccc); | |
background: -o-linear-gradient(top, #eee, #ccc); | |
background: linear-gradient(top, #eee, #ccc); | |
border: 1px solid #bbb; | |
} | |
.form input[type="submit"]:active { | |
background: -webkit-linear-gradient(top, #ddd, #aaa); | |
background: -moz-linear-gradient(top, #ddd, #aaa); | |
background: -ms-linear-gradient(top, #ddd, #aaa); | |
background: -o-linear-gradient(top, #ddd, #aaa); | |
background: linear-gradient(top, #ddd, #aaa); | |
border: 1px solid #999; | |
} | |
.form div { | |
margin-bottom: 8px; | |
} | |
input[name=clearStorage]{display: none;} | |
.form.admin input[name=clearStorage]{ | |
display: inline; | |
} | |
#loginForm span { | |
float: right; | |
clear: both; | |
margin: 0px 0px 0 5px; | |
color: #585858; | |
font-size:12px; | |
line-height: 1.5; | |
} | |
.hide { | |
/*display:none; | |
visibility:hidden;*/ | |
left:-600px; | |
} | |
.floatRight{ | |
float:right; | |
margin-top:20px; | |
line-height: 1.5; | |
} | |
ul { | |
margin: 10px 0; | |
padding:0; | |
} | |
li { | |
padding: 4px 2px; | |
margin: 2px 0; | |
list-style-type: none; | |
line-height: 1.5; | |
animation: fadein 1s; | |
-moz-animation: fadein 1s; /* Firefox */ | |
-webkit-animation: fadein 1s; /* Safari and Chrome */ | |
-o-animation: fadein 1s; /* Opera */ | |
position: relative; | |
-webkit-transition: background-color 1s ease-in-out; | |
-moz-transition: background-color 1s ease-in-out; | |
-ms-transition: background-color 1s ease-in-out; | |
-o-transition: background-color 1s ease-in-out; | |
} | |
li input[type='checkbox']{ | |
position: absolute; | |
right: 5px; | |
top:5px; | |
} | |
li.post-comment { | |
opacity: 1; | |
} | |
.needsAproval { | |
background-color: rgba(255, 250, 245, 0.47)!important; | |
border: 1px dashed #F00; | |
font-style: italic; | |
color: #DDD; | |
position: relative; | |
} | |
.toValidate var { | |
background: none repeat scroll 0 0 #F5F5F5; | |
border: 1px solid #8D7F7F; | |
border-radius: 50% 50% 50% 50%; | |
bottom: 6px; | |
color: #000000; | |
cursor: pointer; | |
display: block; | |
float: right; | |
height: 10px; | |
margin: 0 50px 0 0; | |
position: absolute; | |
right: 0; | |
width: 10px; | |
} | |
.toValidate var:hover { | |
border: 1px solid #fff; | |
} | |
.toValidate var:before { | |
position: relative; | |
content: 'Validate'; | |
color: #fff; | |
float:right; | |
margin-right: 10px; | |
margin-top:-4px; | |
font-size:11px; | |
padding:0 2px; | |
z-index: 1; | |
} | |
.toValidate var:active { | |
background: #000; | |
} | |
.post-comment button { | |
text-transform: capitalize; | |
padding: 0 2px; | |
position: absolute; | |
right: 5px; | |
border: 1px solid #8D7F7F; | |
bottom: 5px; | |
cursor: pointer; | |
background: #F5F5F5; | |
color: #9B6C6C; | |
font-size:10px; | |
} | |
.post-comment button:hover { | |
color: #000; | |
border: 1px solid #000; | |
} | |
.needsAproval:after { | |
content:'Requires Admin\'s approval'; | |
background: #fff; | |
color: #000; | |
position: absolute; | |
right: 10px; | |
padding: 0 2px; | |
} | |
.toValidate{ | |
background-color: rgba(119, 86, 53, 0.47)!important; | |
color: #530028; | |
} | |
@keyframes fadein { | |
from { | |
opacity:0; | |
} | |
to { | |
opacity:1; | |
} | |
} | |
@-moz-keyframes fadein { /* Firefox */ | |
from { | |
opacity:0; | |
} | |
to { | |
opacity:1; | |
} | |
} | |
@-webkit-keyframes fadein { /* Safari and Chrome */ | |
from { | |
opacity:0; | |
} | |
to { | |
opacity:1; | |
} | |
} | |
li:nth-child(odd) { | |
background-color: #f4f4f4; | |
} | |
li span:first-child { | |
font-weight: 600; | |
} | |
li span:first-child:after { | |
content: ':'; | |
} | |
li p { | |
padding-left:10px; | |
display: inline; | |
} | |
iframe { | |
display: none; | |
visibility: hidden; | |
} |
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
/** | |
* Created by Max Berman on 10/29/13. | |
*/ | |
if(!window.localStorage){ | |
alert('your browser does not support web storage'); | |
} | |
//document.readyState | |
document.onreadystatechange = function () { | |
if (document.readyState == "complete") { | |
commentForm = document.querySelector('#commentForm'); | |
commentBox = document.querySelector('textarea[name$=comment]'); | |
loginForm = document.querySelector('#loginForm'); | |
list = document.querySelector('#commentForm ul'); | |
} | |
}; | |
//arsenal of usefull functions used in the current project | |
function addClass(el, cl){ | |
el.className += ' '+cl; | |
} | |
function removeClass(el, cl){ | |
var elClass = ' '+el.className+' '; | |
while(elClass.indexOf(' '+cl+' ') != -1) | |
elClass = elClass.replace(' '+cl+' ', ''); | |
el.className = elClass; | |
} | |
//User Object | |
function User (userName) { | |
this.name = userName; | |
this.displayName = function(){ | |
var title = document.createElement("h1"); | |
title.innerHTML = this.name; | |
commentForm.appendChild(title); | |
commentForm.insertBefore(title, commentForm.firstChild); | |
}; | |
this.postComment = function(){ | |
if(window.localStorage){ | |
var localData = { | |
'userName': this.name, | |
'text': commentBox.value, | |
'aproved': (this.name == 'admin') ? true : false | |
}; | |
var listElem = document.createElement('li'); | |
listElem.className = (localData.aproved) ? 'post-comment': 'post-comment needsAproval'; | |
listElem.innerHTML = '<span>'+this.name+'</span><p>'+localData.text+'</p>'; | |
list.appendChild(listElem); | |
list.insertBefore(listElem, list.firstChild); | |
//save as json in session storage | |
var localStorageLength = window.localStorage.length; | |
window.localStorage.setItem('localData-'+localStorageLength, JSON.stringify(localData)); | |
} | |
}; | |
this.displayComments = function(){ | |
for (var i = 0; i < window.localStorage.length; i++){ | |
var output = JSON.parse(window.localStorage.getItem(localStorage.key(i))); | |
var listElem = document.createElement('li'); | |
if (this.name == 'admin') { | |
addClass(commentForm, 'admin'); | |
listElem.setAttribute('data-storage', localStorage.key(i)); | |
listElem.className = (output.aproved) ? 'post-comment': 'post-comment toValidate'; | |
listElem.innerHTML = '<span>'+output.userName+'</span><p>'+output.text+'</p>'; | |
list.appendChild(listElem); | |
list.insertBefore(listElem, list.firstChild); | |
//add Validation element and its functionality | |
var validateBtn = document.createElement('var'); | |
listElem.appendChild(validateBtn); | |
validateBtn.addEventListener('click', function(){ | |
var getCurrentStorageKey = this.parentNode.getAttribute('data-storage'); | |
var tempData = JSON.parse(window.localStorage.getItem(getCurrentStorageKey)); | |
tempData.aproved = true; | |
window.localStorage.setItem(getCurrentStorageKey, JSON.stringify(tempData)); | |
removeClass(this.parentNode, 'toValidate'); | |
}, false); | |
//add delete post button and its functionality | |
var delBtn = document.createElement('button'); | |
delBtn.textContent = 'delete'; | |
listElem.appendChild(delBtn); | |
delBtn.addEventListener('click', function(){ | |
var getCurrentStorageKey = this.parentNode.getAttribute('data-storage'); | |
window.localStorage.removeItem(getCurrentStorageKey); | |
list.removeChild(this.parentNode); | |
}, false); | |
} | |
else if (output.aproved && this.name != 'admin'){ | |
listElem.className = 'post-comment'; | |
listElem.innerHTML = '<span>'+output.userName+'</span><p>'+output.text+'</p>'; | |
list.appendChild(listElem); | |
list.insertBefore(listElem, list.firstChild); | |
} } | |
}; | |
}// /User Object | |
document.querySelector('input[name$=submit]').onclick = function(){ | |
var nameSelector = document.querySelector('input[name$=name]'); | |
var person = new User(nameSelector.value); | |
if (!person.name){ | |
alert('login name is missing'); | |
return false; | |
} | |
removeClass (commentForm, 'hide'); | |
addClass(loginForm, 'hide'); | |
person.displayName(); | |
person.displayComments(); | |
document.querySelector('input[name$=submitComment]').onclick = function(){ | |
if (commentBox.value !== ''){ | |
person.postComment(); | |
} | |
commentBox.value = ''; | |
}; | |
}; | |
document.querySelector('input[name$=clearStorage]').onclick = function(){ | |
window.localStorage.clear(); | |
list.innerHTML = ''; | |
commentBox.value = ''; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment