Skip to content

Instantly share code, notes, and snippets.

@max-berman
Created August 13, 2014 10:24
Show Gist options
  • Save max-berman/d8a56179b56d91d1d743 to your computer and use it in GitHub Desktop.
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
<!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>
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;
}
/**
* 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