Having problems with Storage Review/Session Storage

Hi there,

I’m following some tutorials from PluralSight from Jesse Liberty and I’m having some problems getting my JavaScript to work properly.

What is supposed to happen is that the values saved within Session Storage are all displayed within the box below the inputs and provide data such as the URL etc. However, not even the labels are being displayed, nevermind the data related to them.

My thought is that it is because they are not being defined anywhere. However, I have downloaded and reviewed the source code related to the exercise and it too does not work and has the exact same code layout as me (minus a few line spaces etc. to display the code more clearly)

Please could someone review the attached code and let me know what’s wrong? I’ve looked over it many times and I can only draw the same conclusion - that “oldValue”, “newValue” etc. need to be defined somewhere.

Thoughts please?

Cheers,

Shoxt3r

HTML Code

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="stylesheet" href="datastorage-mystyles.css" />
		<title>Data Storage</title>
		<script src="datastorage-localstorage-storagereview.js"></script>
	</head>
	<body>
		<section id="form-section">
			<form name="dataForm">
				<label for="key">Key: </label><br />
				<input type="text" id="key" name="key" /><br />
				<label for="value">Value:</label><br />
				<input type="text" id="value" name="value" /><br />
				<input type="button" id="save" value="Save" />
				<input type="button" id="retrieve" value="Retrieve" />
				<input type="button" id="delete" value="Delete" />
				<input type="button" id="review" value="Review" />
				<input type="button" id="clear" value="Clear" />
			</form>
		</section>
		<section id="data">
			No data
		</section>
	</body>
</html>

CSS Code

body{


}

#dataform{
	float:left;
	padding:15px;
	border:1px solid #cccccc;
}

#data{
	float:left;
	width:400px;
	margin-left:10px;
	padding:15px;
	border:1px solid #cccccc;

}

#data > div{
	padding:5px;
	border-bottom:1px solid #cccccc;
}

#key #text{
	width:200px;
}

JS Code

function initiate()
{
	var saveButton = document.getElementById('save');
	var retrieveButton = document.getElementById('retrieve');
	var deleteButton = document.getElementById('delete');
	var reviewButton = document.getElementById('review');
	var clearButton = document.getElementById('clear');
	
	saveButton.addEventListener('click', saveItem);
	retrieveButton.addEventListener('click', retrieveItem);
	deleteButton.addEventListener('click', deleteItem);
	reviewButton.addEventListener('click', reviewAll);
	clearButton.addEventListener('click', clearAll);
	addEventListener('storage', storageReview);
	
}

function saveItem(){
	
		var key = document.getElementById('key').value;
		var value = document.getElementById('value').value;
		localStorage[key] = value;
		
}

function retrieveItem(){
	
		var data = document.getElementById('data');
		var key = document.getElementById('key').value;
		var value = localStorage[key];
		data.innerHTML = '<div>' + key + ': ' + value + "</div>";
		
}

function deleteItem(){
	if (confirm('Delete?')){
		var key = document.getElementById('key').value;
		var value = document.getElementById('value').value;
		localStorage.removeItem(key);
		data.innerHTML = '<div>Deleted ' + key + ' ' + value + ' </div>';	
		
	}
	
}

function reviewAll(){
	for (var i = 0; i < localStorage.length; i++){
		var key = localStorage.key(i);
		var value = localStorage[key];
		data.innerHTML += '<div>' + key + ': ' + value + '<br></div>';
		
	}
	
}

function clearAll(){
	if (confirm('Clear?')){
		localStorage.clear();
		data.innerHTML = '<div>Cleared.</div>';
		
	}

}

function storageReview(e){
		data.innerHTML += '<div>' +
		'key: ' + e.key + '<br>' +
		'old value: ' + e.oldValue + '<br>' +
		'new value: ' + e.newValue + '<br>' +
		'url: ' + e.url + '<br>' +
		'storage area: ' + e.storageArea + '<br></div>';
		

}

addEventListener("load", initiate);
1 Like

the storage event is never being fired, I was unfamilar with that event but it seems to only be fired when the storage is changed in a separate window.

You’ll also want to fetch the data div when that’s firing otherwise you’ll get an error, if you add this and open up the page in multiple windows of the same browser. Not sure it works in all browsers but seems to work in Firefox and Chrome at least.

var data = document.getElementById('data');

One other thing is to always define which object you’re calling addEventListener on, you should explicitly call window.addEventListener as there’s also document.addEventListener for different events.

1 Like

Thanks for the guidance Mark - I’ve had another look over the code and you’re right, data isn’t even defined in the functions it needs to be.

I’ve corrected this and also assigned the function to the “review” button so that on-click it will output the data needed. I’m still clueless as to how this could have worked in the trainer’s example though? A screenshot of his code is below:


Uploading…

One final problem is that the storageReview function is meant to output various details about the key saved in the session storage, as follows using the parameter “e”? However, I don’t understand where this data is meant to come from as nowhere has it been defined…and sure enough everything comes back as “undefined”.

  • old value
  • new value
  • url
  • storage area

Updated JS code below:

function initiate()
{
	var saveButton = document.getElementById('save');
	var retrieveButton = document.getElementById('retrieve');
	var deleteButton = document.getElementById('delete');
	var reviewButton = document.getElementById('review');
	var clearButton = document.getElementById('clear');
	
	
	saveButton.addEventListener('click', saveItem);
	retrieveButton.addEventListener('click', retrieveItem);
	deleteButton.addEventListener('click', deleteItem);
	//reviewButton.addEventListener('click', reviewAll);
	clearButton.addEventListener('click', clearAll);
	reviewButton.addEventListener('click', storageReview);
	
}

function saveItem(){
	
		var key = document.getElementById('key').value;
		var value = document.getElementById('value').value;
		localStorage[key] = value;
		
}

function retrieveItem(){
	
		var data = document.getElementById('data');
		var key = document.getElementById('key').value;
		var value = localStorage[key];
		data.innerHTML = '<div>' + key + ': ' + value + "</div>";
		
}

function deleteItem(){
	if (confirm('Delete?')){
		
		var data = document.getElementById('data');
		var key = document.getElementById('key').value;
		var value = document.getElementById('value').value;
		localStorage.removeItem(key);
		data.innerHTML = '<div>Deleted ' + key + ' ' + value + ' </div>';	
		
	}
	
}

function reviewAll(){
	var data = document.getElementById('data');
	
	for (var i = 0; i < localStorage.length; i++){
		var key = localStorage.key(i);
		var value = localStorage[key];
		data.innerHTML += '<div>' + key + ': ' + value + '<br></div>';
		
	}
	
}

function clearAll(){
	var data = document.getElementById('data');
	
	if (confirm('Clear?')){
		localStorage.clear();
		data.innerHTML = '<div>Cleared.</div>';
		
	}

}

function storageReview(e){
		var data = document.getElementById('data');
	
		data.innerHTML += '<div>' +
		'key: ' + e.key + '<br>' +
		'old value: ' + e.oldValue + '<br>' +
		'new value: ' + e.newValue + '<br>' +
		'url: ' + e.url + '<br>' +
		'storage area: ' + e.storageArea + '<br></div>';
		

}

window.addEventListener("load", initiate);

Thanks in advance!

EDIT: Just listened back to the tutorial and apparently when an item is added, edited or removed this raises a “storage event” which causes the information I mentioned above (i.e. old value, new value etc.) to be accessed and amended automatically?

That’s correct.

To see this working you’ll need to open two windows in the same browser. When the storage is changed in one window, the event will fire in the other so that you have a way to keep the windows in sync. Make sense?

Event handlers are always passed an event object with information about what happened. e.g. saveItem also recieves an event object with information about the click event.

function saveItem(e){
  console.log(e)
}

Hi there,

Thanks for the explanation - however I still can’t get my code to work properly. I’ve set the code up exactly how the demonstration shows it.
In the first window I’m setting two sets of data as follows:

  • Key set to “key1”, value set to “value1”
  • Key set to “key2”, value set to “value2”

Each time pressing “Save” to save the values in Local Storage. I’m then pressing “Review” in the first window and then going to the second window, and pressing “Review” and the data comes back in both cases.

I then go back to the first window, enter “key1” in the key field and enter “valuetwo” in the value field then press “Save”. However, when I press “Review” in the second window, only the “key1” and “valuetwo” data appears, none of the additional details such as oldvalue, newvalue and url are displayed.

What am I missing?

function initiate()
{
	
	var saveButton = document.getElementById('save');
	var retrieveButton = document.getElementById('retrieve');
	var deleteButton = document.getElementById('delete');
	var reviewButton = document.getElementById('review');
	var clearButton = document.getElementById('clear');
	
	
	saveButton.addEventListener('click', saveItem);
	retrieveButton.addEventListener('click', retrieveItem);
	deleteButton.addEventListener('click', deleteItem);
	reviewButton.addEventListener('click', reviewAll);
	clearButton.addEventListener('click', clearAll);
	addEventListener('storage', storageReview);
	
}

function saveItem(){
	
		var key = document.getElementById('key').value;
		var value = document.getElementById('value').value;
		localStorage[key] = value;
		
}

function retrieveItem(){
	
		var data = document.getElementById('data');
		var key = document.getElementById('key').value;
		var value = localStorage[key];
		data.innerHTML = '<div>' + key + ': ' + value + "</div>";
		
}

function deleteItem(){
	if (confirm('Delete?')){
		
		var data = document.getElementById('data');
		var key = document.getElementById('key').value;
		var value = document.getElementById('value').value;
		localStorage.removeItem(key);
		data.innerHTML = '<div>Deleted ' + key + ' ' + value + ' </div>';	
		
	}
	
}

function reviewAll(){
	var data = document.getElementById('data');
	
	for (var i = 0; i < localStorage.length; i++){
		var key = localStorage.key(i);
		var value = localStorage[key];
		data.innerHTML += '<div>' + key + ': ' + value + '<br></div>';
		
	}
	
}

function clearAll(){
	var data = document.getElementById('data');
	
	if (confirm('Clear?')){
		localStorage.clear();
		data.innerHTML = '<div>Cleared.</div>';
		
	}

}

function storageReview(e){
		var data = document.getElementById('data');
	
		data.innerHTML += '<div>' +
		'key: ' + e.key + '<br>' +
		'old value: ' + e.oldValue + '<br>' +
		'new value: ' + e.newValue + '<br>' +
		'url: ' + e.url + '<br>' +
		'storage area: ' + e.storageArea + '<br></div>';
		

}

window.addEventListener("load", initiate);

Cheers,

Shoxt3r

Don’t worry about cross window syncing of storage, it’s a very limited use-case and you probably don’t need it.

Hi Mark,

Thanks for your reply. Is this the only reason for the Storage Review function or is it useful for pulling out the old and the new values in other cases, other than access via multiple windows?

Cheers,

Shoxt3r

The only time the storageReview function is called in your code is when that event is triggered from a second window.

addEventListener('storage', storageReview);

The other functions for save, review, delete, clear should work reliably in a single window.

Hi Mark,

Excellent, thanks for your help with this. As you say not something that I am likely to use regularly but it’s still good to have a working demo should I need to do it or something like it.

I’ve now moved onto an alternative version from Craig Shoemaker and am having problems getting the values entered into the textarea to be stored when you close and then reopen the browser. I’ve checked it in both Chrome and Firefox but no deal. Note you’ll need to change the script reference for the jQuery version to point to live to get it working.

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>Title Here</title>
		<style type="text/css">
			textarea{
				font-family:Arial;
				width:500px;
				height:200px;
				display:block;
				margin-bottom:25px;
			
			}
		
			#messageContainer{
				height:20px;
			
			}
		
		</style>
		
	</head>
	<body>
		<div id="container">
			<h1>Using Local Storage</h1>
			<h2>Task List</h2>
			<div id="messageContainer"><span id="msg"></span></div>
			<textarea id="tasksBox" autofocus></textarea>
			<button id="saveButton">Save</button>
			<a href="javascript:void(0);" id="deleteAllLink">Delete</a>
		</div>		
	</body>
	<script src="jquery-1.12.3.js"></script>
	<script>
		var tasksBox, msg;
		
		$(function(){
			tasksBox = $("tasksBox");
			msg = $("#msg");
			
			if (window.localStorage){
			
				if (window.localStorage.taskList != null){
					var tasks = window.localStorage.taskList;
					var taskList = tasks.split(",").join("\n");
					tasksBox.val(taskList);
				}
			}
		}
		
		$("#saveButton").click(function(){
			save();
			showMessage("Saved");
		});
		
		$("#deleteAllLink").click(function(){
			window.localStorage.removeItem("taskList");
			tasksBox.val("");
			showMessage("Deleted");
		});
		
		
		function save(){
			var tasks = tasksBox.val();
			var taskList = tasks.split("\n").join(",");
			window.localStorage.taskList = taskList;
		}
		
		function showMessage(message){
			msg.html(message);
			msg.fadeOut(1000);
		
		}
		
	
</html> 

Any thoughts?

Cheers,

Shoxt3r

localStorage saves data for the current domain, if you’re just running this as a local file on your computer it won’t work as expected.

If you have a Mac or python installed you’ll be able to run this to start up a little server in the current directory to test.

python -m SimpleHTTPServer

Scratch that, you just had errors in the code. The main one being you never closed the <script> tag

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Title Here</title>
        <style type="text/css">
            textarea{
                font-family:Arial;
                width:500px;
                height:200px;
                display:block;
                margin-bottom:25px;
            }
            #messageContainer{
                height:20px;
            }
        </style>
    </head>
    <body>
        <div id="container">
            <h1>Using Local Storage</h1>
            <h2>Task List</h2>
            <div id="messageContainer"><span id="msg"></span></div>
            <textarea id="tasksBox" autofocus></textarea>
            <button id="saveButton">Save</button>
            <a href="javascript:void(0);" id="deleteAllLink">Delete</a>
        </div>
    </body>
    <script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
    <script>
        var tasksBox, msg;
        $(function(){
            tasksBox = $("#tasksBox");
            msg = $("#msg");
            if (window.localStorage){
                if (window.localStorage.taskList != null){
                    var tasks = window.localStorage.taskList;
                    var taskList = tasks.split(",").join("\n");
                    tasksBox.val(taskList);
                }
            }
        });

        $("#saveButton").click(function(){
            save();
            showMessage("Saved");
        });
        $("#deleteAllLink").click(function(){
            window.localStorage.removeItem("taskList");
            tasksBox.val("");
            showMessage("Deleted");
        });
        function save(){
            var tasks = tasksBox.val();
            var taskList = tasks.split("\n").join(",");
            window.localStorage.taskList = taskList;
        }
        function showMessage(message){
            msg.html(message);
            msg.fadeOut(1000);
        }
        </script>
        </body>
</html>

The best way to debug is to put console.log('adsf'); in the code. When doing that with your original code it didn’t show up in the log so I knew something was up :wink:

Great thanks Mark!

I have another problem with a function but only when testing within Internet Explorer and Microsoft Edge. The code doesn’t show any console errors within Chrome and Firefox.

The error centres around the save() function which I have created, while the specific error is SCRIPT5007: Unable to set property ‘taskList’ of undefined or null reference.

According to Internet Explorer there is also an “unexpected token” on line 29, though this doesn’t cause a problem in Chrome/Firefox either. Any thoughts?

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>Title Here</title>
		<style type="text/css">
			textarea{
				font-family:Arial;
				width:500px;
				height:200px;
				display:block;
				margin-bottom:25px;
			}
		
			#messageContainer{
				height:20px;
			}
		</style>		
	</head>
	<body>
		<div id="container">
			<h1>Using Local Storage</h1>
			<h2>Task List</h2>
			<div id="messageContainer"><span id="msg"></span></div>
			<textarea id="tasksBox" autofocus></textarea>
			<button id="saveButton">Save</button>
			<a href="javascript:void(0);" id="deleteAllLink">Delete</a>
		</div>		
	</body>
	<script src="jquery-1.12.3.js"></script>
	<script>
		var tasksBox, msg		
		$(function(){
			tasksBox = $("#tasksBox");
			msg = $("#msg");		
			if (window.localStorage){	
				if (window.localStorage.taskList != null){
					var tasks = window.localStorage.taskList;
					var taskList = tasks.split(",").join("\n");
					tasksBox.val(taskList);
				}
			}
		});
		
		$("#saveButton").click(function(){
			save();
			showMessage("Saved");
		});
		$("#deleteAllLink").click(function(){
			window.localStorage.removeItem("taskList");
			tasksBox.val("");
			showMessage("Deleted");
		});		
		function save() {
			var tasks = tasksBox.val();
			var taskList = tasks.split("\n").join(",");
			window.localStorage.taskList = taskList;
		}	
		function showMessage(message){
			msg.html(message);
			msg.fadeOut(1000);
		}
	</script>		
</html>

At a guess I’d put a semicolon here:

var tasksBox, msg;

Thanks for the heads-up about the semicolon Mark - I’ve corrected this in the following code. However, I’m still getting the “Unable to set property ‘taskList’ of undefined or null reference” error. Is this because Web Storage isn’t supported within Microsoft Edge?

When I enter information into the textbox and then press Save the error appears within the console and the action isn’t carried out which points me to another typo though I cannot be sure. I’ll hopefully get hold of the source code from the tutorial itself so that I can do a comparison. The problem is probably related to me trying to copy the code down from the video and it missing a vital function or line.

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>Handling the Web Storage Event</title>
	</head>
	<body>
		<div id="container">
			<h1>Handling the Web Storage Event</h1>
			<h2>Task List</h2>
			<div id="messageContainer"><span id="msg"></span></div>
			<textarea id="tasksBox" autofocus></textarea>
			<button id="saveButton">Save</button>
			<a href="javascript:void(0);" id="deleteAllLink">Delete</a>
			<div id="log"></div>
			<fieldset>
				<label>Key</label>
				<span id="key"></span><br /><br />
				
				<label>New Value</label>
				<span id="newValue"></span><br /><br />
				
				<label>Old Value</label>
				<span id="oldValue"></span><br /><br />
				
				<label>Url</label>
				<span id="url"></span><br /><br />
			</fieldset>
		</div>
	</body>
	<script src="jquery-1.12.3.js"></script>
	<script>
		var tasksBox, msg;
		
		$(function(){
			tasksBox = $("#tasksBox");
			msg = $("#msg");
			
			if (window.localStorage){
				if (window.localStorage.taskList != null){
					var tasks = window.localStorage.taskList;
					var taskList = tasks.split(",").join("\n");
					tasksBox.val(taskList);				
				}
			}
			
			$("#saveButton").click(function(){
				save();
				showMessage("Saved");
			});
			
			$("#deleteAllLink").click(function(){
				window.localStorage.removeItem("taskList");
				tasksBox.val("");
				showMessage("Deleted");
			});
			
			
			//* check if the character "e" can be replaced with "b" etc.
			//* check if it makes any difference what the order of the displayStorageEvent elements is
			
			
			function displayStorageEvent(e){
				$("#key").html(e.key);
				$("#newValue").html(e.newValue);
				$("#oldValue").html(e.oldValue);
				$("#url").html(e.url);
				//e.storageArea <- reference to either Local or Session instance
			}
			
			window.addEventListener("storage", displayStorageEvent, false);
			
			if (typeof (window.onstorage) == "undefined"){
				$("body").append("<div class='msg'>This demo only works with a browser that supports Web Storage</div>");
			
			}
		
			function save(){
				var tasks = tasksBox.val();
				var taskList = tasks.split("\n").join(",");
				window.localStorage.taskList = taskList;
			}	
			
			function showMessage(message){
				msg.html(message);
				msg.fadeOut(1000);
			}
		
		
		});
	</script>
	
</html> 

Any thoughts?

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.